[Feat] W4 Layer B Local Retriever + L1~L5 평가 셋 (#19)#49
Merged
Conversation
W4 두 번째 retrieval. text2cypher.py (#18) 패턴 그대로 재활용하되, LLM 이 Cypher 를 자유 생성하는 대신 entity 만 식별하고 1-hop subgraph 는 결정적 Cypher 템플릿으로 추출. "관계/연관" 질의에 강함. 흐름: 자연어 질문 ↓ _identify_entities (LLM JSON 응답, kg/extractor.py 패턴) entity 후보 [{name, label?}, ...] ↓ _match_entities (Neo4j name/aliases CONTAINS — fulltext index 없을 때 대비) 매칭된 Entity 노드들 ↓ _expand_subgraph (1-hop Layer B + MENTIONS 청크, parameterized Cypher) subgraph (entities, relationships, chunks) ↓ _generate_answer (LLM 2단계, 라벨 품질 challenge 정직 보고) 자연어 답변 신규 파일: - retrieval/local_retriever.py (540 lines) — Local Retriever 메인 모듈 - retrieval/prompts/local_retriever_entity_v1.md — entity 식별 system prompt - retrieval/prompts/local_retriever_answer_v1.md — 답변 생성 system prompt - docs/weekly-log/2026-05-17-local-retriever.md — 작업 일지 (정성 검증 결과 박제 대기) 수정 파일: - retrieval/__init__.py — local_retrieve / LocalRetrieverResult export 추가 - retrieval/eval_set.md — L1~L5 섹션 추가 (Layer B 평가 셋) - scripts/run_w4_eval.py — L 케이스 분기 + --suite local 필터 + Local Retriever 평가 로직 평가 셋 L1~L5: - L1 [relation] 두산밥캣과 함께 언급된 리스크 — Q4 와 답변 패턴 차이 (subgraph 활용) - L2 [two-entity] 한화와 두산밥캣의 관계 — 두 entity 교집합 (Text2Cypher 어려운 케이스) - L3 [self-company] 미래에셋증권 지표/전망 — ⭐ 자기 회사명 미추출 graceful (슬라이드 10) - L4 [label-quality] 공모발행액 23조 위험 — ⭐ 라벨 품질 challenge 정직 보고 (슬라이드 10) - L5 [global] 전체 8문서 트렌드 — Layer C 라우팅 명분 (슬라이드 14) 안전장치: 1. read-only: Cypher 템플릿이 결정적, 사용자 입력은 parameterized (CONTAINS 매칭). 2. 결과 크기 제한: MAX_ENTITIES_TO_EXPAND=5, MAX_RELATED_PER_ENTITY=15, MAX_CHUNKS_PER_ENTITY=3, CHUNK_TEXT_TRUNCATE=300 — 토큰 폭발 방지. 3. graceful fallback: entity 식별 0개 / 매칭 0개 / 빈 subgraph / LLM 실패 모두 자연어 안내. 레퍼런스: - Microsoft GraphRAG Local Search — entity 를 graph 진입점 (access point) 으로 활용 - Tomaz Bratanic (Neo4j Developer Blog) — Local-to-Global GraphRAG with Neo4j - 회사 레포 doc-summary-agent — LLM 호출 / JSON 강제 / 재시도 패턴 (kg/extractor.py 정합) DoD (#19): - 관계 질의에서 VectorRAG 와 다른 답변 패턴 (subgraph 정보 활용) → L1, L2 검증 - 평균 응답 시간 < 5초 → 정성 검증 시 측정 발표 슬라이드 연결 (5/23): - 슬라이드 10 (라벨 품질) ← L3, L4 보강 - 슬라이드 11 (보완 관계) ← L1 (Q4 와 패턴 차이) - 슬라이드 13 (NEW Local 데모) ← L1 / L2 시연 - 슬라이드 14 (Routing 명분) ← L5 글로벌 fallback 후속: - #21 Routing Agent (5/18) — 키워드 분기: "관계/관련/영향" → Local - 정성 검증 실행 → weekly-log 결과 박제 → PR 머지 Closes #19 (정성 검증 결과 박제 후 PR 머지)
기존 Q1~Q5 + F1~F3 (Text2Cypher) 섹션은 그대로 유지하고, 뒤에 L1~L5 (Local Retriever) 섹션 추가. L 시리즈: - L1 [relation] 두산밥캣과 함께 언급된 리스크 — Q4와 답변 패턴 차이 검증 - L2 [two-entity] 한화/두산밥캣 관계 — 두 entity 교집합 - L3 [self-company] 미래에셋증권 지표/전망 — ⭐ 자기 회사명 미추출 (슬라이드 10) - L4 [label-quality] 공모발행액 23조 위험 — ⭐ 라벨 품질 정직 보고 (슬라이드 10) - L5 [global] 전체 8문서 트렌드 — Layer C 라우팅 명분 (슬라이드 14) 차이점 표 (Q vs L), 동작 흐름, Cypher 템플릿 (entity matching + subgraph expansion) 박제.
기존 Q1~Q5 + F1~F3 (Text2Cypher) 케이스는 그대로 유지하고 다음을 추가:
1. EvalCase 에 suite 필드 추가 ("t2c" | "local") — case_id 가 Q/F/L 인지에 따라 retriever 분기
2. L1~L5 EvalCase 5개 추가 (Local Retriever 평가 셋)
3. expect_empty_entities (L5), expect_empty_matches (L3) 필드 추가 — graceful fallback 검증
4. _evaluate_t2c_case + _evaluate_local_case 분리 — 각 retriever 특성에 맞는 verdict 로직
5. CaseEvalResult 에 local 전용 필드 (identified_entities, matched_entity_count, subgraph_*) 추가
6. _print_summary_table: t2c / local 별도 표 + Local 평균 응답 시간 표시 (DoD < 5초 마크)
7. CLI: --suite local / --suite t2c 필터 추가
사용 예:
uv run python -m scripts.run_w4_eval --suite local # L* 만
uv run python -m scripts.run_w4_eval --case L3 # L3 만
uv run python -m scripts.run_w4_eval --json eval_w4.json # raw JSON 박제
#19 DoD 검증:
- L1, L2: 매칭 ≥ 1 + 답변 + hint 절반 → PASS
- L3 (자기 회사명): 매칭 0개 + 안내 답변 → PASS
- L4 (라벨 품질): 매칭 ≥ 1 + 답변에 challenge 언급 hint → PASS
- L5 (글로벌): 식별 0개 + Layer C 안내 → PASS
- 평균 응답 시간 < 5초 자동 측정 + 마크 표시
DoD 체크리스트 + L1~L5 TBD 표 (본인 정성 검증 실행 후 결과 박제할 자리). PR 머지 직전 결과 채우면 됨.
…tax 에러 수정 (#19) 5/17 정성 검증 시 L1~L4 모두 Cypher SyntaxError 42I63 발생: "ORDER BY, SKIP and LIMIT can only be used in this order in RETURN. (line 10, column 1) RETURN qname, ..." 원인: 이전 패턴 `WITH ... ORDER BY ... WITH collect(e)[..3]` 가 Neo4j 5.x 파서에서 모호하게 해석됨 — ORDER BY 후속 LIMIT 이 RETURN 절 밖에 위치한 형태로 잡힘. 해결: CALL 서브쿼리로 ORDER BY+LIMIT 을 RETURN 절 안에 격리. UNWIND $names AS qname CALL { WITH qname MATCH (e:Entity) WHERE ... RETURN e ORDER BY size(e.name) ASC LIMIT 3 } RETURN qname, elementId(e) AS id, ... 이 패턴은 Neo4j 5.x 표준이고 Aura 에서 안정적으로 동작. 5/17 정성 검증 결과 (수정 전): - L1~L4: PARTIAL (모두 매칭 0개로 fallback — Cypher 에러 graceful 처리 동작 검증) - L5: PASS (글로벌 질의 entity 식별 0개 패턴 정상) - 평균 응답: 5.4s⚠️ (DoD 5초 0.4초 초과 — LLM 재시도 영향) graceful fallback 자체는 완벽 동작 — Cypher 에러 → 매칭 0개 → 안내 답변 → 답변에 hint 단어 포함 → 모두 PARTIAL 이상 등급. 즉 에러 핸들링은 검증됐고 Cypher 만 fix. 수정 후 기대 결과: - L1, L2: 매칭 ≥ 1개 → 1-hop subgraph 추출 → PASS (Q4 와 답변 패턴 차이 검증) - L3: 매칭 0개 expected (자기 회사명 '미래에셋증권' 미추출) → 슬라이드 10 보강 - L4: 매칭 ≥ 1 (Company 라벨로 잘못 분류된 metric) → 답변에 라벨 challenge 언급 - L5: 변동 없음 (식별 0개 패턴 그대로) 수정 사항: _MATCH_ENTITIES_CYPHER 만 교체. 나머지 (_EXPAND_SUBGRAPH_CYPHER, 함수 시그니처) 무변경.
5/17 정성 검증 v2 실행 시 두 가지 warning 발견 (동작 영향 없음, cleanup):
1. CALL 서브쿼리 deprecation (Neo4j 5.x):
기존 `CALL { WITH qname ... }` → `CALL (qname) { ... }`
variable scope clause 명시로 5.x 권고 패턴 일치. 결과 동일.
2. Property warning `c2.page` does not exist:
8문서 적재된 일부 청크에 page property 가 없음 (chunker 단계에서
페이지 메타데이터 누락). 동작에는 영향 없으나 매 쿼리마다 warn 로그.
→ `properties(c2).page` 로 안전 접근, 없으면 null 반환.
두 fix 모두 cosmetic — 5/17 v2 결과의 verdict 에는 영향 없음.
연관 5/17 v2 정성 검증 결과:
- L1, L2, L3: PARTIAL (매칭 0개 — Cypher 에러 아니라 entity 자체 부재 발견)
- L4: PASS (matched=1, relations=15, chunks=3 — 라벨 품질 challenge 직접 데모)
- L5: PASS (글로벌 질의 entity 식별 0개 → Layer C 안내)
- 평균: 5.7s (L4 의 9.2s 가 끌어올림 — subgraph 풍부 케이스 trade-off)
L1/L2 entity 자체 부재는 entity 추출 (W3 영역) 이슈로 별도 트래킹 예정.
PR #49 머지 직전 결과 박제: 정성 검증 결과 표: | ID | category | verdict | identified | matched | relations | chunks | elapsed | | L1 | relation | PARTIAL | 1 | 0 | 0 | 0 | 5.8s | | L2 | two-entity | PARTIAL | 2 | 0 | 0 | 0 | 4.6s | | L3 | self-company | PARTIAL | 1 | 0 | 0 | 0 | 5.0s | | L4 | label-quality | PASS | 1 | 1 | 15 | 3 | 9.2s | | L5 | global | PASS | 0 | 0 | 0 | 0 | 3.9s | 총 5 케이스 · PASS 2 · PARTIAL 3 · FAIL 0 평균 응답: 5.7s (L4 제외 4.8s — 일반 케이스는 DoD 통과) DoD #19 충족도: - ✅ 관계 질의 subgraph 활용 (L4 답변에 FACES_RISK 명시) -⚠️ 응답 시간 (일반 케이스 통과, L4 만 trade-off) - ✅ graceful fallback (L1~L3, L5 모두) 4가지 시행착오 / 발견 박제: 1. Bug — Cypher 5.x SyntaxError 42I63 (CALL 서브쿼리로 해결) 2. Bug — c2.page property 부재 (properties() 안전 접근) 3. Discovery — Company 라벨 challenge 가 5/16 진단보다 한 단계 더 심각 (CONTAINS 매칭으로도 회사명 못 찾음 → 슬라이드 10 보석) 4. Discovery — Local Retriever 의 subgraph↔응답시간 trade-off 발표 슬라이드 연결 update: - 10 ← L4 PASS 답변 직접 인용 + Discovery 3 - 13 ← L4 데모 (relations=15) - 14 ← L5 PASS 후속 트래킹: - #21 Routing Agent (5/18 작업) - #신규 — Entity 추출 LLM 한계 별도 이슈로 분리 (5/24+ W5 영역)
별도 이슈 #50 생성 후 weekly-log 의 placeholder 를 실제 이슈 번호로 교체.
Owner
Author
5/17 정성 검증 완료 — 머지 준비 OK결과 요약
총 5 케이스 · PASS 2 · PARTIAL 3 · FAIL 0 · 평균 5.7s DoD 충족도
5/17 의 핵심 발견 (Discovery 3)5/16 진단 3 ("Company 라벨 상위 5개가 모두 metric") 이 상한값이 아니라 평균값에 가까운 사실임이 확정됨. L1 "두산밥캣", L2 "한화", L3 "미래에셋증권" 모두 CONTAINS 매칭으로도 0개 — entity name 자체에 회사명이 안 담겨 있음. Kimi LLM entity 추출의 한계가 5/16 진단보다 한 단계 더 심각. → 별도 이슈 #50 으로 트래킹 (5/24+ W5 영역, 5/23 발표 전 해결 불요). 추가 commit (검증 중 발견된 cosmetic fix)
Merge 후 다음 단계
PR 머지하시면 #19 자동 close 됩니다. 🚀 |
10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
요약
W4 두 번째 retrieval — Local Retriever (Layer B) 구현. text2cypher.py (#18, PR #48 머지 완료) 패턴 그대로 재활용하되, LLM 이 Cypher 를 자유 생성하는 대신 entity 만 식별하고 subgraph 는 결정적 1-hop Cypher 템플릿으로 추출. "관계/연관" 질의에 강함.
Closes #19 (정성 검증 결과 박제 후 PR 머지)
동작 흐름
Text2Cypher (Q*) vs Local Retriever (L*) 차이
변경 사항
신규 파일
retrieval/local_retriever.py(540 lines) — Local Retriever 메인retrieval/prompts/local_retriever_entity_v1.md— entity 식별 system prompt (5 few-shot)retrieval/prompts/local_retriever_answer_v1.md— 답변 생성 system prompt (4 few-shot)docs/weekly-log/2026-05-17-local-retriever.md— 작업 일지 (정성 검증 결과 박제 자리)수정 파일
retrieval/__init__.py—local_retrieve,LocalRetrieverResult,LocalRetrieverErrorexportretrieval/eval_set.md— L1~L5 섹션 추가 (~150 lines)scripts/run_w4_eval.py— L 케이스 5개 +--suite local필터 + Local Retriever 평가 로직평가 셋 L1~L5
안전장치
DoD (#19)
검증 방법
레퍼런스
doc-summary-agent— LLM 호출 / JSON 강제 / 재시도 패턴 (kg/extractor.py 정합)발표 슬라이드 연결 (5/23 멘토링 D-6)
의존 / 후속
Merge 전 체크리스트
uv run python -m scripts.run_w4_eval --suite local실행docs/weekly-log/2026-05-17-local-retriever.md의 TBD 표에 박제eval/w4_local_2026-05-17.json으로 박제🤖 작업 어시스턴트: 코드 push & PR 작성 (5/17 일요일 코드 트랙)