
문서용 평가 도구를 만들었고, 이를 PostHog의 자체 문서에 실행해 보았습니다
요약
RAG 시스템의 품질을 높이기 위해 문서 자체를 평가하는 도구인 docfit을 소개합니다. 기존의 출력 중심 평가에서 벗어나, 문서의 청크화 가능성, 검색 가능성, 답변 가능성 등 6가지 차원에서 문서의 품질을 측정합니다.
핵심 포인트
- 기존 LLM 평가는 출력에 집중하지만, docfit은 입력 데이터인 문서 품질을 측정함
- 인간과 AI 에이전트라는 두 가지 독자를 모두 고려한 문서 구조 평가
- 청크화, 검색, 답변 가능성, 코드 품질, 모호성, 작업 지향성 6가지 지표 제공
- RAG 파이프라인의 상류(upstream) 문제를 해결하기 위한 접근 방식
제가 찾을 수 있었던 모든 LLM 평가 (eval) 도구들은 출력을 측정합니다. 모델의 답변이 정확했나요? 환각 (hallucination)이 있었나요? 올바른 도구 (tool)를 호출했나요? 모두 중요한 질문들이지만, 모두 파이프라인의 잘못된 끝단을 측정하고 있습니다.
다른 한쪽 끝은 입력 (input)입니다. 만약 당신의 RAG 시스템이 잘못된 문서에서 청크 (chunk)를 가져온다면, 잘못된 답변을 생성하게 되며, 파이프라인에서 당신이 하는 그 어떤 것도 이를 해결할 수 없습니다. 해결책은 상류 (upstream), 즉 문서 자체에서 일어나야 합니다. 그리고 그 계층에서 문서를 수정하려면, 먼저 문서를 측정해야 합니다.
그것이 제가 만든 것입니다. 이름은 docfit이며, 6가지 차원에 걸쳐 문서를 점수화합니다.
두 가지 대상 문제 (The two-audience problem)
과거에 문서는 위에서 아래로 읽는 인간이라는 하나의 대상만을 가졌습니다. 이제는 두 가지 대상을 가집니다. 인간 (여전히 위에서 아래로 읽음)과 AI 에이전트 (특정 질문에 답하기 위해 개별 청크를 가져옴)입니다. 이 두 대상은 미묘하게 다른 것을 원합니다.
인간이 읽기에 좋은 문서는 이전 단락의 명확한 선행사를 바탕으로 "이것"이나 "저것"을 자유롭게 사용할 수 있습니다. 하지만 고립된 하나의 청크를 검색하는 LLM은 그러한 선행사를 가지고 있지 않습니다. 문서는 조용히 망가집니다.
문서는 어떤 기능이 무엇인지(IS)를 높은 수준에서 설명할 수 있습니다. 위에서 아래로 읽는 인간은 주변 문맥으로부터 이를 조립할 수 있습니다. "X를 어떻게 설치하나요?"라는 질문에 답하기 위해 해당 청크를 검색하는 에이전트는 참고할 구체적인 내용이 없습니다. 에이전트는 세부 사항을 지어내거나 답변을 거부하게 됩니다.
저는 모든 페이지를 직접 읽지 않고도 이러한 격차를 드러내는 도구를 원했습니다. 제가 원하는 것을 수행하는 것이 아무것도 없었기에, 직접 만들었습니다.
docfit이 하는 일
6가지 평가기 (evaluators). 각 평가기는 문서에 대해 특정 질문을 던지고, 0-100 사이의 점수를 생성하며, (선택적으로) 구체적인 재작성 (rewrites) 내용을 생성합니다.
**청크화 가능성 (Chunkability)**은 헤더 구조, 단락 형태, 문장 경계를 살펴봅니다. 문서를 합리적인 조각으로 나눌 수 있는가? 완전히 결정론적 (deterministic)이며, LLM이 필요하지 않습니다.
**검색 가능성 (Retrievability)**은 각 청크에 대해 현실적인 질문을 생성하고, 이를 로컬에서 임베딩 (embed)한 뒤, 시맨틱 검색 (semantic search)에서 소스 청크가 어디에 순위가 매겨지는지 측정합니다. RAG 품질에 대한 직접적인 측정입니다.
**답변 가능성 (Answerability)**는 LLM에게 다음과 같이 질문합니다: "오직 이 청크(chunk)만 주어졌을 때, 누락된 문맥을 지어내지 않고 이에 대한 질문에 답할 수 있습니까?" 이는 환각 (hallucination) 위험을 예측합니다.
**코드 품질 (Code quality)**은 코드 블록을 파싱합니다. 언어가 태그되어 있는가? 구문적으로 유효한가? 단독으로 실행될 만큼 충분히 완전한가? 설치 명령어를 자동으로 인식하며, 이를 오탐 (false-positive)하지 않습니다.
**모호성 (Ambiguity)**은 지칭 대상이 불분명한 대명사, 정의되지 않은 전문 용어, 명시되지 않은 문맥을 표시합니다. 이 부분에서 재작성 (rewrite) 제안 기능이 빛을 발합니다.
**작업 지향성 (Task orientation)**은 문서가 사물이 '무엇인지 (ARE)'가 아니라 사용자가 '무엇을 하고 싶은지 (DO)'를 중심으로 구조화되어 있는지를 판단합니다. 작업 지향적인 문서는 사용자의 의도와 더 잘 일치합니다.
PostHog 실행 결과
PostHog의 제품 분석 (product-analytics) 페이지에서 실행한 결과는 다음과 같습니다:
전체 점수인 84.3은 괜찮은 수준입니다. 흥미로운 점은 그 형태입니다. 62.5점인 답변 가능성 (Answerability)은 "이 페이지는 높은 수준으로 읽히지만, 단일 청크만으로는 특정 질문에 완전히 답하지 못한다"는 것을 의미합니다. 80점을 기록한 모호성 (Ambiguity)은 11개의 문제를 포착했는데, 대부분은 funnels, stickiness, Self-driving과 같이 인라인 정의 없이 사용된 전문 용어였습니다.
제가 가장 자랑스럽게 생각하는 부분은 --suggest 옵션으로 실행했을 때 단순히 불평만 하는 것이 아니라, 해결책을 직접 제시한다는 점입니다:
수정 전: 이미 PostHog로 전송 중인 이벤트를 기반으로 트렌드, 퍼널 (funnels), 리텐션 (retention), 경로 (paths), 스티키니스 (stickiness) 및 라이프사이클 인사이트를 구축하세요.
수정 후: 이미 PostHog로 전송 중인 이벤트를 기반으로 트렌드, 퍼널 (funnels, 사용자가 작업을 완료하기 위해 거치는 일련의 단계), 리텐션 (retention, 시간이 지남에 따라 사용자를 계속 참여하게 유지하는 능력), 경로 (paths), 스티키니스 (stickiness, 사용자가 얼마나 자주 돌아오는지) 및 라이프사이클 인사이트를 구축하세요.
이 재작성된 문구는 도구에 의해 생성되었습니다. 이를 문서에 직접 붙여넣고 병합할 수 있습니다. 이것이 무엇이 잘못되었는지 알려주기만 하는 평가 (eval) 도구와, 그것을 고칠 수 있도록 도와주는 도구의 차이입니다.
9개의 PostHog 페이지를 통해 발견한 점
도구를 만드는 동안 9개의 페이지를 감사(audit)했습니다. 몇 가지 패턴이 나타났습니다:
- 답변 가능성 (Answerability)이 거의 모든 곳에서 가장 취약한 차원이었습니다 (중앙값 50). 페이지들이 기능을 높은 수준에서 설명하고는 있지만, 단일 청크 (chunk)가 특정 질문에 답할 수 있게 해주는 구체적인 단계별 설명이 부족한 경우가 많았습니다.
- 설치 가이드 (install guide)가 전체적으로 가장 높은 점수(83.4)를 받았습니다. 작업 지향적이고, 구조가 잘 잡혀 있으며, 구체적입니다. 설치 콘텐츠는 본질적으로 '존재(being)' 중심이 아닌 '수행(doing)' 중심의 형태를 띠기 때문에 승리합니다.
- 랜딩 페이지 (landing page)는 62점을 받았습니다. 이는 올바른 동작이며 버그가 아닙니다. 랜딩 페이지는 서사적 콘텐츠가 아니라 탐색 그리드(navigation grids)이며, 도구는 이를 정확하게 반영하고 있습니다.
- 데이터 웨어하우스 (data-warehouse) 페이지는 청크화 가능성 (chunkability)에서 15점을 받았습니다. 헤더 구조가 거의 없어서, 인간의 훑어보기와 에이전트 검색 (agent retrieval) 모두에 해를 끼칩니다.
이러한 발견 중 어느 것도 문서 팀을 놀라게 하지는 않을 것입니다. 중요한 것은 사람이 모든 페이지를 읽지 않고도, 도구가 이를 체계적이고 대규모로 드러낼 수 있다는 점입니다.
SDET 사고방식의 불공평한 우위
저는 6년 동안 SDET (Software Development Engineer in Test) 엔지니어로 근무했습니다. 그 배경은 제가 LLM 시스템에 접근하는 방식을 변화시킵니다.
대부분의 ML 툴링은 평가 (evaluation)를 사후 고려 사항으로 취급합니다. QA 전문가들은 측정하지 않으면 개선할 수 없다는 것을 알고 있습니다. SDET의 관점에서 LLM 평가 도구를 작성한다는 것은 실패 모드 (failure modes)에 집착한다는 것을 의미합니다. LLM이 잘못된 형식의 JSON을 반환하면 어떻게 될까요? (실제로 일어납니다. 이를 처리해야 합니다.) 실행 도중 일일 토큰 예산이 소진되면 어떻게 될까요? (테스트 중에 실제로 목격했습니다. 이제 도구는 API를 계속 두드리는 대신 깔끔하게 중단됩니다.) trafilatura가 가끔 생성하는 빈 청크 (empty chunk)에서는 어떻게 될까요? (모든 점수를 깎아먹기 전에 필터링해야 합니다.)
이 모든 것들은 실제 문서로 독식 (dogfooding)을 하는 동안 제가 맞닥뜨린 버그들이었습니다. 106개의 테스트는 유기적으로 성장했습니다.
다른 제품 지표처럼 추적하기
어차피 PostHog의 문서에 대해 docfit을 실행하고 있었기 때문에, PostHog 연동 기능을 연결했습니다:
docfit report ./docs.md --posthog-key phc_your_key
각 실행은 모든 점수를 속성(properties)으로 포함하는 docfit_run 이벤트를 전송합니다. PostHog 프로젝트를 지정하면 대시보드를 얻을 수 있습니다.
아이디어는 이렇습니다: docfit을 CI(지속적 통합)에 연결하는 것입니다. 문서 저장소(docs repo)에 커밋할 때마다 실행이 트리거됩니다. PostHog는 그 추세(trend)를 보여줍니다. 만약 PR(Pull Request)로 인해 평균 점수가 떨어진다면 바로 알 수 있습니다. 특정 페이지가 지속적으로 최악의 점수를 기록한다면, 해당 페이지의 수정을 우선순위에 둘 수 있습니다.
docfit이 아직 지원하지 않는 기능
한계점을 미리 솔직하게 말씀드립니다:
- 영어만 지원합니다. 모든 평가자 프롬프트(evaluator prompts)는 영어입니다.
- 배치(Batch) 실행은 순차적으로 진행됩니다. 20페이지 분량의 감사는 시간이 다소 소요됩니다.
- 디렉토리 입력으로 마크다운(markdown) 파일만 지원합니다. HTML, reStructuredText, 그리고 Jupyter notebooks는 로드맵에 포함되어 있습니다.
--suggest모드는 토큰(token) 사용량을 대략 두 배로 늘립니다. 이는 실행 가능한 결과물을 얻기 위한 트레이드오프(tradeoff)입니다.- 작은 로컬 모델(local models)은 판사 프롬프트(judge prompts)에서 때때로 잘못된 형식의 JSON을 반환합니다. 도구가 이를 유연하게 처리하지만, 더 큰 모델을 사용할 때보다 커버리지(coverage)가 낮게 나타날 수 있습니다.
이 중 어느 것도 치명적인 결함은 아닙니다. v0.1 버전의 솔직한 한계점들입니다.
사용해 보기
pip install "git+https://github.com/bewanderer/docfit.git#egg=docfit[embeddings]"
console.groq.com에서 무료 Groq API 키를 받아 내보내기(export)한 후, 다음을 실행하세요:
docfit report https://your-docs.example.com
전체 문서, 설치 가이드 및 CLI 레퍼런스는 github.com/bewanderer/docfit에서 확인하실 수 있습니다.
만약 문서 팀에 계시고 에이전트 가독성(agent-readability) 문제에 대해 고민해 보셨다면, 어떻게 대응하고 계시는지 꼭 듣고 싶습니다. 혹은 여러분의 문서에 docfit을 실행해 보고 어떤 점이 놀라웠는지 알려주세요. 저장소(repo)를 통한 이슈(Issues)와 PR은 언제나 환영합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기
