DOCS/journey/research/260315_companyx_rag_답변합성_시나리오동시종결_리서치.md

19 KiB

tags
tags
research
companyx
rag
answer-composition
scenario
troubleshooting

Company X RAG 답변합성 시나리오·트러블 동시종결 리서치

상위 원칙

목적

  • Company X 근거응답 이슈를 트러블슈팅 + 시나리오 한 문제로 보고, 둘을 함께 닫기 위한 원인 기준을 고정합니다.
  • 현재 실패가 검색 인프라 문제인지, 답변 합성 문제인지, 질문별 하드코딩 구조 문제인지 단일 경로로 좁힙니다.
  • 이 문서는 해결안 확장보다 다음 plan 1건을 만들 수 있을 정도로 직접 원인을 확정하는 데만 집중합니다.

조사 질문

  1. 현재 실패의 직접 레이어는 검색인가, 답변 합성인가
  2. 컴퍼니엑스의 투자사는 몇개야?, 내부 규정 상 휴가는 얼마나 쓸 수 있어?가 왜 깨지는가
  3. 현재 Company X 경로는 일반 규칙 기반인가, 질문별 하드코딩 기반인가
  4. 트러블 문서와 시나리오 문서를 함께 닫으려면 무엇을 plan에서 고정해야 하는가

범위 / 비범위

  • 범위:
    • rb8001의 Company X grounding 진입/검색/응답 합성 경로
    • 재오픈 기준 질문 3개에 대한 처리 구조
    • 프롬프트/if 분기/질문 적합도 선별 구조
  • 비범위:
    • Company X 전체 문서셋 확대 작업
    • skill-rag-file 인덱싱 성능 일반론
    • 다른 프로젝트나 다른 RAG 경로 전면 리팩토링
    • 최종 수정안 구현 자체

사실(Facts)

1. Company X 질문은 의도 분류 전에 전용 grounding 경로로 우선 진입한다

  • route_message()는 사용자 컨텍스트 생성 직후 try_companyx_grounding()을 먼저 호출합니다.
  • 위치:
    • rb8001/app/services/message_service.py:81-93
  • 의미:
    • Company X 질문은 일반 intent/skill 경로 전에 별도 처리됩니다.
    • 따라서 이번 실패는 일반 의도 분류가 Company X 질문을 놓쳤다만으로 설명되지 않습니다.

2. Company X 경로 진입 조건은 팀 ID + 문자열 marker 기반 휴리스틱이다

  • should_handle_companyx_grounding()team_id == COMPANYX_TEAM_ID_looks_like_companyx_grounding_question(message)로만 판단합니다.
  • _looks_like_companyx_grounding_question()근거, 내부 문서, 공동 운영, 컴퍼니엑스, companyx 같은 marker 포함 여부를 봅니다.
  • 위치:
    • rb8001/app/services/companyx_grounding_service.py:28-60
  • 의미:
    • 질문 유형이나 필요한 답변 방식보다 문자열 포함 여부가 우선입니다.
    • 컴퍼니엑스만 들어가도 grounding 경로로 진입할 수 있습니다.

3. 검색 질의 확장은 사실상 질문 2종만 별도 하드코딩돼 있다

  • _build_query_candidates()는 기본적으로 원문 질문 1개를 그대로 사용합니다.
  • 추가 질의 확장은 아래 경우에만 있습니다.
    • 오늘전통 + 옐로펀치
    • X-COURSE
  • 위치:
    • rb8001/app/services/companyx_grounding_service.py:63-91
  • 의미:
    • 투자사 몇 개, 휴가 규정 같은 재오픈 질문은 전용 query expansion이 없습니다.
    • 대표 질문만 상대적으로 유리한 구조입니다.

4. 검색 결과는 질문 적합도 재평가 없이 relevance score 순으로만 합쳐진다

  • _search_companyx_documents()는 후보 질의별 검색 결과를 병합한 뒤 relevance_score 내림차순으로만 정렬합니다.
  • 질문 유형, 문서 종류, 문서-질문 정합성 재평가 단계는 없습니다.
  • 위치:
    • rb8001/app/services/companyx_grounding_service.py:113-127
  • 의미:
    • 검색 hit가 있어도 그 hit가 질문에 맞는 근거인지 다시 검증하지 않습니다.

5. 직접 답 생성은 질문별 if 분기 하드코딩이고, 기본값은 generic 문장이다

  • _build_direct_answer()는 아래 경우만 별도 문장을 가집니다.
    • 오늘전통 + 옐로펀치
    • X-COURSE
  • 그 외 모든 질문은 기본값 Company X 내부 문서에서 관련 근거를 찾았습니다.를 반환합니다.
  • 위치:
    • rb8001/app/services/companyx_grounding_service.py:136-153
  • 의미:
    • 투자사는 몇개야? 같은 수치형 질문은 답을 계산하거나 단정 불가를 판단하지 않고 generic 문장으로 끝납니다.
    • 현재 구조는 질문 유형별 답변 계약이 아니라 일부 질문별 문장 하드코딩입니다.

6. 실패 처리는 검색 결과가 0개일 때만 작동하고, 검색은 됐지만 무관한 경우를 다루지 않는다

  • _build_grounded_response()의 실패 문장은 if not results일 때만 반환됩니다.
  • 결과가 1개라도 있으면 질문 적합성 검증 없이 근거 문서: 목록을 붙입니다.
  • 위치:
    • rb8001/app/services/companyx_grounding_service.py:155-171
  • 의미:
    • 휴가 질문에 무관한 companyx_todaytradition.pdf 청크가 잡히면, 시스템은 이를 실패가 아니라 성공처럼 출력합니다.
    • 즉 현재 실패 경계는 no result만 있고 irrelevant result는 없습니다.

7. 현재 Company X 응답은 LLM 기반 합성이 아니라 규칙 기반 문자열 조합이다

  • Company X 전용 경로는 검색 결과를 가져온 뒤 _build_direct_answer()와 청크 요약 문자열을 이어붙여 응답을 만듭니다.
  • 위치:
    • rb8001/app/services/companyx_grounding_service.py:130-171
  • 의미:
    • 현재 이 문제의 본질은 프롬프트가 약해서라기보다, 규칙 설계가 질문 유형을 감당하지 못하는 상태입니다.
    • 다만 구현 형태는 질문별 문장/분기 하드코딩에 의존하고 있어 유지보수성이 낮습니다.

8. 스킬 문서가 요구하는 계약과 현재 구현 계약은 일치하지 않는다

  • SKILL.md는 답변 순서를 direct answer -> evidence documents -> short evidence summary로 고정합니다.
  • 또한 documents are missing, say the evidence is insufficient를 요구합니다.
  • 위치:
    • DOCS/skills/companyx-rag/SKILL.md
  • 현재 구현은 아래 차이가 있습니다.
    • 직접 답이 generic 문장으로 대체될 수 있음
    • 문서 부족무관한 문서 반환을 구분하지 않음
    • 증거 문서 적합성 검증 없이 score 상위 청크를 그대로 노출함
  • 의미:
    • 문제의 직접 원인은 스킬 문서 부재가 아니라, 구현이 스킬 계약을 끝까지 지키지 못하는 데 있습니다.

9. 대표 성공 질문은 구조적으로 우대돼 있고, 재오픈 질문은 일반화 경로에 놓여 있다

  • 오늘전통 + 옐로펀치 질문은
    • 별도 query expansion이 있고
    • 별도 direct answer 하드코딩이 있으며
    • 대표 근거 문서셋도 이미 worklog에 남아 있습니다.
  • 관련 문서:
  • 반면 재오픈 질문 2개는
    • 전용 query expansion이 없고
    • 질문 유형 분기 규칙도 없고
    • generic fallback 문장으로 마감됩니다.
  • 의미:
    • 현재 성공은 일반화된 성공이 아니라 대표 질문 최적화 성공에 가깝습니다.

10. 따라서 지금 실패는 검색 부재보다 답변 합성 + 실패 판정 부재 + 질문별 하드코딩 편향의 결합이다

  • 앞선 사실을 합치면 현재 경로는 아래 구조입니다.
    1. marker 기반으로 Company X 경로 진입
    2. 일부 질문만 유리한 query expansion
    3. relevance score만으로 검색 결과 채택
    4. 일부 질문만 direct answer 하드코딩
    5. 결과가 하나라도 있으면 성공처럼 문서 목록 노출
  • 의미:
    • 이번 이슈의 직접 레이어는 answer composition입니다.
    • 그러나 더 깊게 보면 질문 유형 계약이 없는 규칙 하드코딩 구조가 상위 원인입니다.

11. 현재 Company X RAG는 NAS 대량 문서셋 + 임베딩 전환 이슈 위에 놓여 있다

  • 51123 기준 점검에서 /mnt/nas/workspace/6.Company X 아래 실파일은 53,249개였고, fullscan 최신 summary는 2026-03-17 01:23:10+09:00, hierarchical 최신 summary는 2026-03-17 11:00:06+09:00까지 누적돼 있습니다.
  • 의미:
    • 지금 Company X RAG는 적은 대표 문서 몇 개만의 문제가 아니라, NAS에서 계속 동기화되는 대량 문서셋 위에서 동작해야 합니다.
    • 따라서 대표 질문 2~3개만 통과하는 특례 구조로는 운영 상태를 닫을 수 없습니다.

12. Company X RAG의 임베딩 전제가 문서끼리 일치하지 않는다

  • DOCS/skills/companyx-rag/SKILL.mdDefault embedding path: local 384d로 적고 있습니다.
  • 반면 260316_임베딩_전체프로젝트_현황_및_SSOT_리서치.md260316_임베딩_Gemini_Embedding_2_전환_문제오픈.md는 로빙 전체 기준을 Gemini Embedding 2, 768d, 전수 교체 대상으로 둡니다.
  • 의미:
    • 지금 Company X 답변합성 문제는 순수한 응답 문구 문제만이 아닙니다.
    • 어떤 임베딩 모델/차원/컬렉션 상태를 SSOT로 볼지부터 다시 닫아야 합니다.

13. 그래서 2026-03-15 기준 리서치만으로 바로 구현에 들어가면 전제 충돌을 안고 시작한다

  • 2026-03-15 리서치는 답변합성 구조 문제를 정확히 짚었지만, 그 이후 열린 Gemini Embedding 2 전환 문제와 NAS 대량 문서 운영 상태까지는 반영하지 못했습니다.
  • 의미:
    • 지금 필요한 다음 단계는 새 리서치 전체 재작성이 아니라,
    • 현재 NAS 문서량, 현재 컬렉션 차원, 현재 재임베딩 여부, 현재 대표 질문 재현 상태를 다시 확인하는 짧은 갱신 리서치입니다.

해석(Interpretation)

1. 이 문제는 검색 인프라 장애가 아니라 응답 정책 부재 문제다

  • Company X 전용 경로는 실제로 존재하고, 검색 호출도 수행합니다.
  • 실패가 나는 지점은 질문에 대한 직접 답을 어떻게 만들고, 어떤 검색 결과를 근거로 채택하며, 언제 모른다고 말할지가 비어 있다는 점입니다.

2. 지금 구조는 시나리오를 닫기 어려운 형태다

  • 시나리오는 설명형, 사실 확인형, 수치 확인형, 재정리형을 모두 요구합니다.
  • 하지만 현재 구현은 실질적으로 대표 사실 확인형 2종만 특례 처리합니다.
  • 따라서 새 질문이 들어올수록 if와 문장 하드코딩이 늘어날 가능성이 높고, 시나리오를 일반 규칙으로 닫을 수 없습니다.

3. 트러블 문서가 지적한 회귀의 직접 원인은 질문 적합도 검증 부재다

  • 재오픈 질문들은 검색 결과가 0개라서 실패한 것이 아닙니다.
  • 결과가 있어도 질문과 무관한 청크를 success처럼 출력했습니다.
  • 즉 이번 회귀를 닫는 핵심은 retrieval result exists가 아니라 retrieval result is fit for this question를 판정하는 단계입니다.

4. 스킬 문서는 방향이 맞지만, 구현 계약으로 내려오지 않았다

  • SKILL.md는 이미 직접 답, 근거 문서, 부족 시 명시를 요구합니다.
  • 문제는 그 계약이 코드에서 재현 가능한 판정 규칙으로 변환되지 않은 것입니다.
  • 따라서 다음 plan은 새 문구를 더 쓰는 게 아니라, 스킬 계약을 코드가 판정 가능한 구조로 바꾸는 데 집중해야 합니다.

5. 다만 지금은 응답 계약 구현 전에 운영 전제를 다시 닫아야 한다

  • Company X RAG는 이미 NAS 실문서 대량 적재 상태 위에서 동작하고 있습니다.
  • 동시에 임베딩 SSOT는 384d localGemini 2 / 768d 문서가 공존합니다.
  • 따라서 다음 plan의 첫 단계는 답변합성 코드 수정이 아니라 운영 전제 재검증이어야 합니다.

6. 하드코딩 프롬프트/문장 증식은 이 문제의 해법이 아니다

  • 현재도 대표 질문 성공은 이미 하드코딩 특례에 기대고 있습니다.
  • 이 상태에서 투자사, 휴가, 투자 건수, 규정, 복지 식으로 질문별 문장을 더 추가하면,
    • 시나리오는 겉보기로만 닫히고
    • 트러블은 다른 질문에서 다시 열리며
    • 프롬프트와 if 분기 중복만 쌓이게 됩니다.

미확정 항목(Unresolved)

  1. skill-rag-file의 반환 score만으로 질문 적합도를 판정할 수 있는지, 별도 rerank가 필요한지는 아직 미확정입니다.
  2. 수치형 질문의 단정 가능 / 단정 불가를 문서 메타데이터만으로 먼저 판정할지, 후속 요약 계층을 둘지는 아직 미확정입니다.
  3. 재정리형 질문을 이전 응답 재사용으로 처리할지, 다시 검색해도 되는지는 아직 미확정입니다.
  4. Company X 전용 규칙을 독립 계약 모듈로 둘지, 범용 grounding 정책으로 올릴지는 아직 미확정입니다.
  5. 현재 Company X 컬렉션이 실제로 384d인지, Gemini 2 / 768d 재임베딩이 일부라도 반영됐는지는 아직 미확정입니다.
  6. NAS 최신 문서 동기화본이 Company X RAG 검색 컬렉션에 언제, 어떤 방식으로 반영되는지도 아직 미확정입니다.

결론

  • 이 이슈의 직접 원인은 Company X 검색 실패가 아니라 질문 적합 근거 선별 없는 답변 합성입니다.
  • 더 근본 원인은 질문 유형 계약 없이 일부 질문만 하드코딩 특례 처리하는 구조입니다.
  • 다만 현재는 NAS 대량 문서 운영 상태Gemini Embedding 2 전환 상태가 겹쳐 있으므로, 다음 plan은 구현 전에 운영 전제 재검증부터 고정해야 합니다.
  • 그 전제가 닫힌 뒤 구현 단계에서 아래 3가지를 고정해야 합니다.
    1. 질문 유형별 판정 계약
    2. 검색 결과의 질문 적합도 판정 계약
    3. 근거 부족 시 명시적 실패 계약

다음 plan이 반드시 고정해야 할 항목

  1. 현재 Company X RAG의 실제 임베딩 경로와 컬렉션 차원(384d/768d)을 먼저 재검증할 것
  2. NAS 최신 문서 동기화본이 현재 검색 컬렉션에 언제 반영되는지 확인할 것
  3. 재오픈 기준 질문 3개를 현재 운영 상태에서 다시 재현해 검색 실패 / 무관한 hit / 답변 합성 실패를 분리할 것
  4. success의 정의를 검색 hit 존재가 아니라 직접 답 + 질문 적합 근거 또는 명시적 부족 안내로 바꿀 것
  5. 질문별 direct answer 하드코딩 추가를 금지하고, 질문 유형별 공통 계약으로 대체할 것
  6. 무관한 청크 반환실패로 판정하는 경계를 추가할 것
  7. 스킬 문서 계약과 코드 계약을 1:1로 맞출 것

관련 문서


2026-03-17 코드 검토: 사실 섹션 현행화

이 리서치는 2026-03-15 코드 기준으로 작성됐습니다. 2026-03-17 실제 코드(rb8001/app/services/companyx_grounding_service.py)를 직접 검토한 결과, 아래 사실들이 이미 코드에서 변경되거나 구현된 것으로 확인됐습니다.

이미 구현되어 outdated된 사실

리서치 사실 현재 코드 상태
Fact 3: query expansion이 2종 하드코딩 _build_query_candidates()_extract_keywords() + _DOCUMENT_HINTS_BY_TYPE 기반 동적 확장으로 변경됨
Fact 4: relevance score만으로 결과 채택 _score_result_relevance(), _select_relevant_results()로 질문 적합도 재평가 구현됨
Fact 5: 직접 답이 2종 하드코딩 + generic 기본값 _classify_question_type() + type-based _build_direct_answer()로 4개 유형 처리 구현됨
Fact 6: 실패 처리가 results=0일 때만 작동 _select_relevant_results() 필터링 후 relevant=0이면 _build_failure_answer() 호출됨. QUESTION_QUANTITATIVE_can_answer_quantitative()로 수치 존재 여부도 판정함
Fact 9: 대표 질문만 특례 처리 이제 _classify_question_type()_build_query_candidates()_score_result_relevance() 공통 경로. 하드코딩 특례 제거됨

여전히 사실인 항목

  • Fact 1: Company X 경로는 의도 분류 전에 우선 진입 (message_service.py:81)
  • Fact 2: 진입 조건은 여전히 marker 기반 (_looks_like_companyx_grounding_question)
  • Fact 7: 응답 합성은 여전히 규칙 기반 문자열 조합 (LLM 합성 아님)

현재 미해결 항목 (Unresolved 그대로)

  • relevance score만으로 질문 적합도 판정 가능한지, 별도 rerank 필요한지 미확정
  • 수치형 질문의 단정 가능/불가_COUNT_MARKER_PATTERN 패턴만으로 충분한지 미검증
  • 재정리형 질문은 이전 응답 재사용 없이 재검색함 (세션 연결 없음)

현재 코드에서 추가 확인된 구조

  • _DOCUMENT_HINTS_BY_TYPE: 유형별 문서 힌트 (quantitative는 투자/포트폴리오/실적 계열)
  • _supports_quantitative_focus(): 수치형 질문에서 count marker 패턴(\d+개사, 총\d+ 등) 존재 여부 판정
  • _select_evidence_results(): 관련 결과 중 상위 2개만 근거로 선별 (중복 문서 제거)
  • _build_failure_answer(): 유형별 다른 실패 메시지 반환

미완료 항목 (코드 기준)

  • Phase 5 테스트 고정 미완료: 재오픈 기준 질문 3개에 대한 자동화 테스트 없음
  • Slack 실응답 검증 미완료: 코드는 구현됐으나 실제 Slack에서 재오픈 질문 3개 통과 여부 미확인
  • 종결 worklog 미존재: 트러블슈팅 문서가 참조하는 260315_companyx_정확표기_slack_근거응답_경로종결.md 파일 없음

상세: 260317_companyx_grounding_코드검토_및_문서현행화