riddle: reMarkable Paper Pro에서 펜으로 쓰면 손글씨로 답하는 비전 LLM 일기장

riddle 소개

riddle은 reMarkable Paper Pro 전자잉크 태블릿을 위한 일기장 애플리케이션입니다. 펜으로 페이지에 글을 쓰고 잠시 펜을 놓으면, 일기장이 방금 쓴 잉크를 종이 속으로 빨아들이듯 사라지게 한 뒤, 잠깐 생각하고, 흐르는 손글씨로 답을 한 획씩 써 내려갑니다. 화면 불빛도, 키보드도, 채팅 UI도 없이 종이 위에 잉크가 나타났다 사라지는 경험만 남깁니다.

이 답을 만들어 내는 것은 손글씨를 읽는 비전 LLM입니다. 펜을 놓으면 riddle은 지금까지 쓴 페이지를 작은 이미지로 만들어 언어 모델에 넘기고, 모델이 돌려준 답을 다시 사람이 쓴 것 같은 펜 획으로 합성해 화면에 그립니다. 즉 riddle은 손글씨 입력을 이미지로 캡처하는 부분, 그 이미지를 읽는 모델을 부르는 부분, 그리고 모델의 답을 손글씨 애니메이션으로 되돌려 주는 부분을 하나로 묶은 온디바이스 앱입니다.

riddle은 Rust로 작성되었고, 답을 만드는 모델(개발자는 이를 일기장 속 "오라클(oracle)"이라고 부릅니다)은 두 가지 백엔드 중에서 고를 수 있습니다. 프라이버시 측면에서는 커밋된 페이지 이미지 한 장만 사용자가 직접 설정한 오라클로 전송되고 그 밖의 것은 태블릿을 떠나지 않으며, 별도의 텔레메트리도 없습니다.

 펜 입력 (raw evdev, 4096단계 필압, 하드웨어 이벤트 속도)
   │ 스트로크
   ▼
 riddle ── 2.8초 멈춤 → 페이지 커밋 → PNG ──▶ 오라클 (상주 LLM 프로세스,
   │                                          문장 단위로 답을 스트리밍)
   ▼ 스트로크 (Dancing Script → 1픽셀 펜 경로로 스켈레톤화)
 디스플레이 백엔드
   ├── qtfb   — xochitl 안에서 창 모드로 실행
   └── quill  — 완전 테이크오버: xochitl 정지, 벤더 e-ink 엔진을 직접 구동해
                가장 낮은 지연으로 잉크를 그림 (프리빌트 번들이 쓰는 방식)

riddle의 동작 원리

riddle은 펜의 원시 입력(raw evdev)을 4096단계 필압과 하드웨어 이벤트 속도 그대로 받아 스트로크로 다룹니다. 펜이 약 2.8초간 멈추면 현재 페이지를 커밋해 PNG로 만들고, 이를 상주하는 오라클 프로세스에 넘깁니다. 오라클은 답을 문장 단위로 스트리밍하기 때문에, 모델이 답을 다 끝내기 전부터 화면에는 손글씨가 써지기 시작합니다.

답을 손글씨로 되돌리는 과정은 이 저장소가 직접 담당합니다. 답 텍스트를 Dancing Script 서체로 렌더링한 뒤, Zhang-Suen 세선화(thinning)로 획을 1픽셀 두께의 펜 경로로 줄이고, 그 경로를 추적해 한 획씩 그려지는 애니메이션으로 재생합니다. 저장소에는 펜 입력과 잉크 표면, 이 손글씨 합성, 오라클 프로세스 관리, 그리고 두 개의 디스플레이 백엔드가 모두 들어 있습니다.

디스플레이 백엔드는 두 가지입니다. qtfb 는 xochitl(리마커블 기본 UI) 안에서 창 모드로 도는 방식이고, quill 은 xochitl을 멈추고 화면 전체를 가져가 벤더 e-ink 엔진을 직접 구동하는 완전 테이크오버 방식입니다. 후자가 지연이 가장 낮으며 프리빌트 번들이 쓰는 방식입니다. quill 자체는 별도의 형제 저장소로, 벤더의 libqsgepaper.so 파형 엔진을 감싼 클린룸 MIT 어댑터를 작은 C ABI로 노출하고 riddle이 --features takeover 로 링크합니다.

riddle의 오라클: 두 가지 백엔드

오라클의 답은 커밋된 페이지 이미지를 읽는 비전 LLM에서 나옵니다. 시작 시점에 다음 두 백엔드 중 하나를 고릅니다.

첫 번째는 OpenAI 호환 API입니다. API 키를 설정하면 riddle이 OpenAI 호환 /chat/completions 엔드포인트로 곧장 통신합니다. OpenAI, OpenRouter, Groq, 로컬 서버 등 같은 형식을 지원하는 곳이면 모두 쓸 수 있고, 이미지를 볼 수 있는(비전) 모델이어야 합니다. 태블릿에 추가 소프트웨어가 필요 없고, HTTPS 통신은 순수 Rust로 riddle에 내장되어 있습니다. 관련 설정은 oracle.envRIDDLE_OPENAI_KEY, RIDDLE_OPENAI_BASE, RIDDLE_OPENAI_MODEL 등으로 지정합니다.

두 번째는 pi 를 쓰는 경로입니다. RIDDLE_OPENAI_KEY 를 설정하지 않으면 자동으로 선택되며, 상주하는 pi --mode rpc 프로세스를 따뜻하게 유지해 매 턴마다 모델 지연만 지불하도록 합니다. 두 백엔드 모두 답을 문장 단위로 스트리밍합니다. 기억 동작에는 차이가 있는데, HTTP 백엔드에서는 매 페이지가 새로운 대화라 이전 페이지를 기억하지 않는 반면, pi 백엔드에서는 일기장을 연 뒤의 세션 내용을 이어서 기억합니다. 오라클이 답할 수 없을 때(키 누락, 거부, 네트워크 없음)는 일기장이 그 이유를 페이지에 적고 전체 오류는 저널에 남깁니다.

riddle의 기억

끝난 페이지는 실제 펜 스트로크와 전사(transcription), 그리고 오라클의 답까지 함께 보관됩니다. 이 덕분에 일기장은 세 가지를 할 수 있습니다. 최근 페이지를 요청에 함께 실어 보내 대화를 이어 가고, 손으로 "정원에 대해 쓴 페이지를 보여줘" 처럼 물으면 그 페이지를 눈앞에서 사용자의 필체로 날짜와 함께 흐릿한 잉크로 다시 써 주며, "무엇을 기억해?" 라고 물으면 기억하는 순간들의 손글씨 목록으로 답합니다.

기억은 태블릿 안 /home/root/riddle-data/memories 아래 평범한 파일로만 저장되고(폴더를 지우면 일기장은 잊으며, 최근 약 400페이지가 유지됩니다) 외부로 나가지 않습니다. oracle.env 에서 RIDDLE_MEMORY=off 로 두면 저장과 추가 전송이 모두 꺼집니다.

riddle 설치와 사용

가장 쉬운 방법은 형제 프로젝트인 remagic 을 이용하는 것입니다. remagic은 개발자 모드를 켜고 필요한 환경을 한 번에 준비해 주며, 그다음 riddle을 설치합니다.

remagic install riddle     # 체크섬 검증 다운로드 → AppLoad
remagic config riddle      # 브라우저에서 설정 폼 (+ 휴대폰용 QR)

이후 AppLoad 에서 Reload 를 누르고 The Diary 를 실행한 뒤, 글을 쓰고 펜을 놓으면 됩니다. 사용에는 개발자 모드로 전환하고 런처를 설치한 reMarkable Paper Pro가 필요합니다. 프리빌트 번들과 카탈로그 빌드는 테이크오버 모드로 동작하는데, 이 모드는 The Diary를 실행하면 리마커블 UI 전체를 멈추고 화면을 가져가며 root 권한으로 e-ink 엔진을 직접 구동합니다. 빠져나올 때는 다섯 손가락 탭을 사용하면 xochitl이 자동으로 다시 시작됩니다. 개발팀은 이 방식이 기기를 변경하며 reMarkable Paper Pro(ferrari, aarch64, OS 3.26~3.27)에서만 테스트되었고 전적으로 사용자 책임임을 명시하고 있습니다.

주요 제스처는 다음과 같습니다.

이렇게 하면 이렇게 됩니다
글을 쓰고 펜을 놓기 일기장이 잉크를 빨아들이고 오라클이 답함
"…에 대해 쓴 것을 보여줘" 라고 쓰기 그 페이지가 종이 위로 떠오르며 필체 그대로 다시 써짐
"무엇을 기억해?" 라고 쓰기 기억하는 순간들의 손글씨 목록으로 답함
마커 뒤집기 지우기
큰 물음표 그리기 내장 가이드 호출
다섯 손가락 탭 일기장 나가기 (테이크오버 모드)

riddle의 라이선스

riddle은 저장소의 모든 것이 MIT 라이선스로 공개되어 있어 개인 및 상업적 목적으로 자유롭게 사용할 수 있습니다. 다만 riddle이 링크해 쓰는 벤더 라이브러리(libqsgepaper.so, Qt)는 저장소에 포함되지 않으며 사용자 본인의 기기나 SDK에서 가져와야 합니다. 답에 쓰이는 손글씨 서체는 Dancing Script(SIL OFL 1.1)입니다.

:github: riddle 프로젝트 GitHub 저장소

:file_folder: quill 형제 저장소 (테이크오버 디스플레이 호스트)

더 읽어보기




이 글은 GPT 모델로 정리한 글을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 덧글로 알려주시기를 부탁드립니다. :hugs:

:pytorch:파이토치 한국 사용자 모임:south_korea:이 정리한 이 글이 유용하셨나요? 회원으로 가입하시면 주요 글들을 이메일:love_letter:로 보내드립니다! 텔레그램(Telegram)이나 Slack/Discord/Teams/Dooray/GoogleChat 등으로도 새 글 알림을 받으실 수 있습니다. :smiley:

:wrapped_gift: 아래:down_right_arrow:쪽에 좋아요:+1:를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ :star_struck: