Files
aio-01d4-stu/Last3Mon/71/VIBE-A-TDOC.md
T

7.0 KiB

7교시 바이브 코딩 · tdoc 만들기

정답본 · 수업이 끝난 뒤(8교시 뒤) 학생 저장소에 올립니다. 그 전에는 올리지 않습니다. 요청서는 VIBE-REQ-TDOC.md, 문제는 VIBE-Q-TDOC.md. 68일차부터 바이브 코딩 프로그램은 수업 준비 때 미리 만들어 보지 않습니다. 아래 요청문과 확인 기준은 예시이고, 걸린 시간은 8교시 강사 바이브 코딩에서 재어 기록합니다.

요청서 → 요구 도출 예 (SPEC.md 예)

요청서의 말을 확인할 수 있는 요구로 바꾼 예입니다. 정답이 하나는 아닙니다. "됐다 / 안 됐다"를 말할 수 있는지가 기준입니다.

1. 요구

번호 요구 요청서의 말 확인 방법
R1 tdoc index <폴더>: *.md를 ## 섹션(기본) 또는 글자 수로 청크, SQLite 파일 하나에 저장. 파일 해시 · 청크 설정이 같으면 건너뜀 ① 가짜 임베딩: 파일 2개 → 청크 수 = ## 섹션 수. 바로 다시 → 임베딩 호출 0번. 한 파일만 고침 → 그 파일 청크 수만큼만 호출. 프로그램을 다시 켜도 tdoc search가 됨
R2 tdoc search "..." --top-k N: 점수(소수 셋째 자리) · 파일 · 섹션 · 글 앞부분을 N줄 ② --top-k 5 → 5줄, 가짜 임베딩에서 질문 낱말이 가장 많이 겹치는 청크가 1등
R3 tdoc ask "...": 1등 점수가 --min-score(기본 0.33) 아래면 LLM 없이 "문서에서 찾지 못했습니다". 아니면 번호 붙인 발췌만 주고 사실마다 [번호], 번호 → 파일 · 섹션 ③ 가짜 LLM: 점수 낮은 질문 → LLM 호출 0번. [7](범위 밖)을 돌려주는 가짜 LLM → 근거 목록에서 빠짐
R4 tdoc <폴더>: 질문 · top_k 입력, 답, 근거 목록. 근거를 고르면 그 청크 원문 전체 ④ 질문 하나 → 근거 top_k줄, 하나 고르면 아래 패널에 섹션 전체
R5 tdoc eval questions.yaml --chunking <설정>: 질문마다 1등 파일 · 3등 안 파일이 기대와 맞은 수 ⑤ 같은 questions.yaml(5개 이상)로 section, 200 → "1등 a/5 · 3등 안 b/5" 두 줄

2. 숨은 요구

  • 저장할 것: files(path, sha256, chunking), chunks(path, section, text, vector). 청크 글 앞에 파일 제목 (오늘 Lab 01과 같음).
  • 가짜 임베딩(낱말 해시 벡터) · 가짜 LLM. Embedder · LLM을 바꿔 끼울 수 있게. 테스트는 진짜를 부르지 않음.
  • 근거 번호는 코드가 확인 (범위 밖은 버림). 오늘 Lab 02의 cited.
  • questions.yaml(질문 · 기대 파일)을 프로그램보다 먼저 직접 씀. 답 없는 질문 하나는 R3 확인용으로.
  • 설정마다 DB 파일 따로 (tdoc-section.sqlite, tdoc-200.sqlite).
  • 키: OPENAI_API_KEY 환경 변수만 (grep -c sk- *.sqlite → 0).
  • 화면: 색인 · 검색 · 답은 worker에서, 색인 진행 표시.

3. 범위 밖

PDF · 워드, 공유 서버, 벡터 DB 설치, n8n 연결. (강사 바이브 코딩에서 tdoc serve를 보여 줌)

4. 순서와 이유

  1. 색인 + 검색 (R1 · R2), 가짜 임베딩 테스트. 답 · 화면 · 비교가 모두 이 검색 결과를 씀.
  2. 답과 근거 (R3). 가장 위험한 규칙(점수 낮으면 LLM 안 부름, 없는 번호 버림)을 화면 없이 테스트로 먼저.
  3. TUI와 비교 (R4 · R5). 검색 결과를 보여 주고 세기만 하면 됨.

자주 빠뜨리는 것 (수업 준비 때 예상)

빠뜨린 것 생기는 일
"모른다고"의 조건 (점수 기준) 문서에 없는 질문에도 LLM이 그럴듯한 답을 씀 (가장 위험)
정답표(questions.yaml) "좋아진 것 같다"만 남고 ⑤를 확인할 방법이 없음
파일 해시 한 줄 고칠 때마다 전부 다시 임베딩 (시간 · 비용)
설정마다 DB 따로 200자 청크와 섹션 청크가 섞여 비교가 안 됨
가짜 임베딩 테스트할 때마다 진짜 임베딩 호출

확인 기준

요구 기준
R1 가짜 임베딩 테스트: 파일 2개 색인 → 청크 수 = ## 섹션 수. 한 파일만 고치고 다시 색인 → 그 파일 청크만 다시 임베딩(호출 수로 확인)
R2 가짜 임베딩에서 질문 낱말이 가장 많이 겹치는 청크가 1등, top_k만큼
R3 가짜 LLM으로: 근거 번호가 범위 밖이면 버림, 점수가 기준 아래면 LLM을 부르지 않음
R5 questions.yaml 5개, 두 설정의 맞은 수 표
비밀 OPENAI_API_KEY 환경 변수만, SQLite·코드에 키 없음

단계별 요청문 예

1. 색인과 검색

~/vibe/tdoc 에 Python 프로젝트를 만들어 줘. uv 사용, 명령 이름 tdoc, 코드와 화면 글자는 영어(답만 한국어).
이번 단계는 TUI 없이 두 명령만.
- tdoc index <folder> [--chunking section|<chars>] [--db tdoc.sqlite]: *.md 를 "## " 섹션(기본) 또는 글자 수로 청크.
  청크 글 앞에 파일의 첫 줄 제목을 붙인다. SQLite 테이블 files(path, sha256, chunking), chunks(id, path, section, text, vector BLOB).
  파일의 sha256 과 chunking 이 같으면 건너뛴다 (바뀐 파일만 다시).
- tdoc search "<question>" [--top-k 3]: 질문 임베딩과 코사인 유사도, 점수·파일·섹션·글 앞 80자.
- tdoc/embed.py: Embedder 인터페이스. OpenAI 구현(text-embedding-3-large, OPENAI_API_KEY, 한 번에 여러 개)과 테스트용 FakeEmbedder(낱말 해시 벡터).
- pytest: FakeEmbedder 로 청크 수, 바뀐 파일만 다시, 검색 순서.

2. 답과 근거

- tdoc ask "<question>" [--top-k 3] [--min-score 0.33]: 1등 점수가 min-score 아래면 LLM을 부르지 않고 "문서에서 찾지 못했습니다".
  아니면 gpt-4.1-mini 에 번호 붙인 발췌만 주고, 한국어 3문장 이내, 사실마다 [번호], 없으면 "문서에서 찾지 못했습니다".
  번호를 파일·섹션으로 바꿔 근거 목록과 함께 출력. 범위 밖 번호는 버린다.
- tdoc/llm.py: LLM 인터페이스와 FakeLLM. pytest 로 min-score 경로, 번호 변환.

3. TUI와 비교

- tdoc <folder>: Textual TUI. 위 질문 입력 + top_k 입력, 가운데 답, 아래 근거 목록(ListView). 근거를 고르면 원문 청크 전체를 아래 패널에.
  검색·답은 worker 로. 색인이 없으면 먼저 색인 진행 표시.
- tdoc eval <questions.yaml> [--chunking ...]: questions: [{question, expect_path}] 로 1등 파일이 맞은 수, 3등 안에 맞은 수를 표로.
  설정마다 DB 파일을 따로 (tdoc-section.sqlite, tdoc-200.sqlite).

7교시에 볼 것

볼 것 막혔을 때 한마디
색인할 때마다 전부 다시 임베딩 "파일 해시로 바뀐 파일만"
테스트가 진짜 임베딩을 부름 "가짜 임베딩으로"
근거 번호가 범위를 벗어남 "번호를 코드에서 확인하고 버리게"
비교할 때 두 설정이 한 DB에 섞임 "설정마다 DB 파일 따로"
키가 DB나 로그에 "환경 변수만"