From 2b7b916f7e73db6742e8992bcc53fa717631f069 Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Wed, 22 Oct 2025 01:06:36 +0900 Subject: [PATCH] troubleshooting: IR Deck answers wrong due to RAG mixing and poor extraction; fixes: doc pinning, OCR reindex, full-text-first --- ...dmin_ir_deck_rag_mixing_and_ocr_quality.md | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 troubleshooting/251022_admin_ir_deck_rag_mixing_and_ocr_quality.md diff --git a/troubleshooting/251022_admin_ir_deck_rag_mixing_and_ocr_quality.md b/troubleshooting/251022_admin_ir_deck_rag_mixing_and_ocr_quality.md new file mode 100644 index 0000000..53bb39b --- /dev/null +++ b/troubleshooting/251022_admin_ir_deck_rag_mixing_and_ocr_quality.md @@ -0,0 +1,44 @@ +# rb8001: IR Deck 응답 오류 — RAG 혼입 + 저품질 추출 이슈 + +## 개요 (KST 00:39–00:48, 2025-10-22) +- 증상: Slack에서 IR Deck PDF 페이지별 분석 요청 시, 서로 다른 문서 스니펫이 섞여 응답되거나(혼입), 깨진 텍스트 기반의 추정 서술이 포함됨. +- 영향: 답변 정확성 저하, 페이지 경계 불일치, 근거 인용 부재. + +## 증상 +- RAG 스니펫 혼입: 업로드 파일(서비스 프로세스_리버스마운틴.pdf) 직후에도 `[파일: AIdol_251010.pdf] … TEAM MEMBERS …`가 주입되어 문서 내용이 혼재. +- 저품질 근거 사용: 스니펫이 가비지/깨진 텍스트라 “(추정)” 서술과 일반화가 섞여 사실성 저하. +- 페이지 경계 상실: 청크 수가 1 수준인 케이스에서 페이지별 분석을 강행, 실제 페이지 구조와 불일치. + +## 근거 로그 (요약) +- rb8001: `[Graph] uploading to RAG: …리버스마운틴.pdf` → 직후 `Injected 2 snippet(s)`와 함께 AIdol 스니펫 포함된 Router result 발생. +- skill-rag-file: `File already exists … returning existing document_id`로 중복 판단, 재추출/재인덱싱 없이 과거 인덱스 텍스트 사용. + +## 원인 +1) 문서 식별/고정 미흡 → 동일 스레드에서 과거 인덱스(AIdol) 스니펫이 검색 결과로 혼입. +2) 추출 품질 저하 → PyPDF2가 일부 텍스트를 반환해 OCR 강제 전환이 트리거되지 않음(가비지 포함), 초기 인덱스 품질 불량. +3) 스니펫 의존 → 본문 직접 확인 없이 짧은 조각으로 페이지별 분석을 일반화. + +## 조치 (코드 반영) +- LangGraph 강화(업로드 흐름) + - 업로드 직후 `/api/reindex`(force_ocr) 호출 → OCR 강제/재청킹/재인덱싱 → `/api/text/{doc}`로 full-text 우선 분석 → 스니펫은 보조. + - 파일: `rb8001/app/pipelines/langgraph_document.py`, `rb8001/app/router/slack_handler.py` +- 추출 품질 개선(skill-rag-file) + - PDF 추출 순서: `pdftotext → PyPDF2 → OCR(pytesseract)` + - 품질 휴리스틱(len/garbage_ratio/unique_chars) 도입 → 저품질이면 강제 OCR → 텍스트/품질 메타 저장(`ocr_used`, `quality`). + - 파일: `skill-rag-file/app/services/text_extractor.py`, `skill-rag-file/app/api/upload.py` +- 텍스트 직접 조회 API + - `/api/text/{document_id}`에서 full-text+메타 제공(분석·검증용). + - 파일: `skill-rag-file/app/api/text.py`, `skill-rag-file/app/main.py` +- 문서 고정 + - thread_ts → `{team_id, document_ids}` 캐시로 동일 스레드의 RAG 대상 문서를 고정. + - 파일: `rb8001/app/router/thread_doc_cache.py`, `rb8001/app/router/slack_handler.py` + +## 검증 +- 업로드/분석 시 로그: `[Graph] downloading → uploading → reindex(force_ocr) → searching → Injected …` 순서 확인. +- 텍스트 품질: `/api/text/{doc}`에서 `ocr_used: true`, `quality.garbage_ratio` 개선 확인. +- 응답 근거: 페이지별 분석에 실제 본문 인용(섹션명/쪽 정보) 포함, 혼입/추정 서술 제거. + +## 교훈 ✍️ +- RAG는 “문서 고정(doc_id)”과 “본문 직접 확인(full-text-first)”이 정확성을 좌우한다. +- PDF는 pdftotext 선호, 실패/저품질 시 즉시 OCR 강제 전환 및 재인덱싱으로 품질 가드 필요. +- 재시작/컨테이너 교체 시 로그 공백이 생기므로 외부 스토리지 감사로그를 병행해 트레이싱 신뢰도를 높인다.