NEW코딩일지 · 11.05코퍼스 메인에 주장 연구실을 세웠다: 사유고2 주장 29만 개를 자동 등록하고 스파크 두 대가 반증 조건까지 검토한다
← 개발로그
·4분

사유고 개발로그 · 7화

600권 완독 코스·마인드맵을 배치로 미리 만들기 시작했다

책을 열 때마다 강의를 만들던 방식을 버리고, 등록된 모든 책의 강의 본문과 주장·근거·사례 표를 배치로 미리 만들기 시작했다.

▸ 사유고#llm#batch#launchd

지금까지 사유고의 완독 코스는 책을 열고 강의를 누를 때 만들어졌다. 한 강을 쓰는 데 1분 가까이 걸리니, 처음 여는 강의는 늘 기다려야 했다. 책이 600권을 넘기자 이 기다림이 곳곳에서 났다. 9월 29일, 등록된 모든 책의 강의를 미리 만들어 두기로 했다. 강의 본문과, 강마다 붙는 주장·근거·사례 표(앱에서는 마인드맵으로 보인다) 두 가지다.

규칙부터 적었다

600권을 한 번에 다시 쓰는 작업이라, 돌리기 전에 지킬 것부터 정했다.

  • 강의 본문은 Sonnet 5.5 하나로만 쓴다. 이 배치 안에서는 다른 모델로 가는 길을 코드에서 막는다.
  • 이미 사람이 손본 강의와 사용자가 고정한 강의는 건드리지 않는다. 그날 직접 다듬은 책 여섯 권도 뺀다.
  • 기존 코스가 있으면 책별로 백업한 뒤 교체하고, 사용자 진도는 그대로 둔다.
  • 강 하나를 저장할 때마다 원장에 한 줄을 남긴다. 중간에 멈췄다가 다시 돌리면 이미 만든 강은 건너뛴다.

’다른 모델로 가는 길을 막는다’는 말로만 두지 않았다. 사유고에는 기능마다 모델을 부르는 입구가 여러 개 있다. 배치가 시작하면 이 입구를 모두 ’걸리면 멈추는 함정’으로 바꿔 끼우고, 실제로 하나씩 불러서 전부 막혔는지 확인한다. 하나라도 통과하면 배치는 시작하지 않는다. 600권을 돌리는 도중 어느 한 경로가 조용히 다른 모델을 부르면, 나중에 어느 강이 무엇으로 쓰였는지 가려낼 방법이 없기 때문이다.

파일럿 세 번

전권을 돌리기 전에 짧은 파일럿을 세 번 돌렸다. 강 몇 개를 만들고 원장과 저장 결과를 보고, 고친 뒤 다시 돌렸다. 도중에 Claude CLI를 2.1.220에서 2.1.284로 올렸는데, 같은 기준으로 재 보니 한 강 중앙값이 61.5초에서 47.0초로 줄었고 품질 게이트 실패는 없었다. 배치는 다시 띄우지 않았다. 다음 호출부터 새 CLI를 쓰기 때문이다.

배치는 macOS의 launchd 작업으로 띄웠다. 비정상 종료면 다시 살아나고, 30분 안에 너무 여러 번 다시 시작되면 스스로 멈추고 알림을 보낸다. 다른 프로젝트에서 한 번 재시작하라고 걸어 둔 작업이 수백 번 되살아난 적이 있어서, 이번에는 되살아나는 횟수에 처음부터 상한을 뒀다.

마인드맵은 따로, 먼저

강의 본문은 등록 순서대로 한 권씩 간다. 끝까지 가는 데 일주일쯤 걸린다. 그 사이 마인드맵은 따로 먼저 만들고 싶었다. 문제는 표가 강의에 묶여 있다는 점이었다. 원래 표는 저장할 때의 강의와 같아야만 유효했다. 표를 먼저 만들어 두면, 본문 배치가 나중에 그 강의를 새로 쓰는 순간 표가 무효가 된다.

코드를 확인해 보니 표를 만들 때 모델에게 들어가는 것은 강의 본문이 아니라 원문 쪽이었다. 그렇다면 표가 기대야 할 것은 강의가 아니라 원문이다. 기준을 바꿨다. 표를 저장할 때 그 강 원문의 지문을 함께 남기고, 강의가 달라졌더라도 원문 지문이 같으면 표를 그대로 쓴다. 강 범위나 원문이 바뀌면 그때는 무효다. 실제로 한 권의 1강 표를 먼저 만들고, 몇 분 뒤 본문 배치가 그 강의를 새로 썼는데 앱에는 14줄짜리 표가 그대로 나왔다.

만드는 쪽과 보는 쪽을 나눴다

표는 Sonnet 5.5가 만들고 Opus 5.5가 원문과 대조해 검수한다. 검수자는 사실 오류, 대상 혼동, 말한 사람을 잘못 붙인 것, 근거가 주장과 맞지 않는 것, 사례 유형, 핵심 누락만 본다. 지적이 있으면 Sonnet이 한 번 고치고 Opus가 다시 본다. 재검수 결과는 기록으로만 남기고 수정본을 저장한다. Opus는 이 검수 경로에서만 부를 수 있게 막아 뒀다.

검수가 값을 하는지는 첫 실측에서 보였다. 『가난한 찰리의 연감』 2강에서 Sonnet이 서로 다른 두 글의 이야기를 섞었는데, Opus가 그것을 잡아 고치게 했다. 같은 조건에서 Opus는 Sonnet보다 두 배쯤 느리고 비용은 세 배쯤 들었다. 그래서 쓰는 일은 Sonnet에게, 보는 일만 Opus에게 맡겼다.

표 배치는 책 순서를 셋으로 나눠 세 개를 나란히 돌린다. 세 몫이 모든 책을 정확히 한 번씩 맡는지는 테스트로 확인했다. 상태 파일과 원장, 정지 파일은 본문 배치와 따로 둬서 서로 덮어쓰거나 멈추게 하지 않는다. 정지 파일 하나로 세 개를 한꺼번에 멈출 수 있다.

같은 날 두 번 부딪혔다

첫 번째는 동시 편집이었다. 저녁에 다른 세션이 같은 파일 세 개를 예전 사본 기준으로 다시 쓰면서 Opus 검수와 샤드 나누기가 통째로 빠졌다. 그쪽 변경(한도 문구 처리)은 살리고 이쪽 변경을 다시 얹어 합친 뒤 테스트 40개를 통과시켰다. 이미 떠 있던 샤드들은 옛 코드를 메모리에 들고 있어서, 현재 강을 마치게 한 뒤 새 코드로 다시 띄웠다.

두 번째는 사용 한도였다. 저녁 무렵 5시간 한도와 추가 사용 월 한도가 한꺼번에 걸렸고, 당시 코드는 그 문구를 한도로 알아보지 못해 강 몇 개를 실패로 넘겼다. 실패한 강은 다음 바퀴에 다시 채워지니 손실은 크지 않았다. 다만 이 일로 더 큰 문제가 보였다. 이 배치는 내가 다른 일에 쓰는 구독과 같은 한도를 쓴다. 이 이야기는 다음 화에 쓴다.

배운 것

오래 도는 배치는 돌리기 전에 지킬 것을 코드로 만들어 둬야 한다. ’이 모델만 쓴다’는 규칙은 입구를 막고 막혔는지 확인해야 규칙이 된다. 그리고 무엇에 기댈지는 실제로 무엇을 읽는지를 보고 정해야 한다. 마인드맵은 강의가 아니라 원문을 읽으므로, 원문에 묶어 두니 강의와 따로 먼저 만들 수 있었다.

사유고 개발로그 · 전 11화

  1. 1화종이책 사진에 물어보는 서재: 글자·그림 검색 두 갈래로 세웠다
  2. 2화저자 토론 기능을 붙였다: GPT가 저자 연기를 거부했다
  3. 3화학습 루프를 만들었다: 증거 없이 완료되는 구멍이 나왔다
  4. 4화저자 인터뷰와 대목 연결 기능을 붙였다: 결함 5개를 먼저 고쳤다
  5. 5화책 587권 자동 등록: 파일은 왔는데 페이지가 빠져 있었다
  6. 6화AI 강의 품질을 쟀다: 모델이 쓴 인용은 문구가 바뀌고 쪽수가 틀렸다
  7. 7화600권 완독 코스·마인드맵을 배치로 미리 만들기 시작했다
  8. 8화배치 사용량 문지기: 5시간 한도 80%에서 쉬고 주간 90%에서 멈춘다
  9. 9화사유고2는 책 795권을 원문 10분의 1 크기 지도로 바꿨다: 답하는 서재에서 늘어놓는 서재로
  10. 10화투자 책 50권만으로 노트 2,094개짜리 지식 연결망이 나왔다: 795권으로 키우기 전에 고민할 것
  11. 11화사유고 촬영 자동화를 맥북 프로에서 맥북 에어로 옮겨 같은 작업을 이어 갔다: 바꾼 코드는 두 줄이었다