Files
kebab/crates/kebab-search/tests/fixtures/search/lexical/run-1.json
altair823 24ec86c515 feat(rag): rag-v4 — RAG provenance 라벨 (source/trust + 신뢰도 우선 지시)
RAG 프롬프트의 각 [근거] 청크 머리에 출처/trust 라벨을 붙이고
(`[#n] source=jira trust=secondary doc=…`), system prompt 에 "저신뢰 출처를 권위
출처와 충돌 시 discount 하고 [#번호]로 귀속" 2규칙을 더한다. 출처 필터
(`--source`/`--trust-min`)가 못 잡는 생성 측 실패 — 저신뢰(jira) 청크가 권위(wiki)
청크를 답변에서 덮어쓰는 것 — 를 다룬다.

- SearchHit 에 source_id/trust_level(additive optional). lexical/vector build_hit
  가 documents 조인에서 채움(both 동일: trust_level lowercase TEXT →
  serde lowercase round-trip, doc_summary read-back 과 동형). hybrid fusion 전파.
- pack_context 라벨 렌더(버전 무관 항상). SYSTEM_PROMPT_RAG_V4 = rag-v3 8규칙
  verbatim + 2규칙. config 기본 rag-v3→rag-v4. multi-hop synth 도 2규칙 →
  rag-multi-hop-v1→v2(prompt 변경 = 버전 bump, design §9).
- wire: search_hit.v1 에 두 필드 optional additive(required 아님,
  skip_serializing_if=None → 구 소비자 무영향, v2 bump 아님).
- source_id 는 RAG 헤더에 렌더되므로 validate_sources 에 [A-Za-z0-9._-] char 검증.
- opt-out: rag-v3 핀 = v3 system prompt 선택(discount 지시 빠짐, 라벨은 무해히 잔존).

검증: kebab-core/search/rag/config/eval 전 테스트 green(25 바이너리), clippy 0.
독립 코드 리뷰 APPROVE(7위험 PASS — trust round-trip 실 DB 확인; MEDIUM rag-v3
opt-out doc + multi-hop 버전 / LOW source_id 검증 반영). 도그푸딩: 라벨 메커니즘
end-to-end 검증(search --json 이 competing 쿼리에 wiki/primary + jira/secondary 둘
다 정확 라벨로 노출). LLM-judge(답변 비교)는 instruction LLM 부재로 보류(.2/.47
다운 + lemonade /api/generate it-model template 미적용) — 인프라, .2 복구 시 측정.
버전 bump 은 follow-up 들과 배치 릴리스에서 일괄.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Mc6W1fgsrbFKTsqA6P8La
2026-06-24 05:48:34 +00:00

70 lines
1.7 KiB
JSON

[
{
"chunk_id": "c3000000000000000000000000000000",
"chunker_version": "v1",
"citation": {
"end": 8,
"kind": "line",
"path": "notes/snap.md",
"section": "Snap",
"start": 7
},
"doc_id": "d0000000000000000000000000000000",
"doc_path": "notes/snap.md",
"embedding_model": null,
"heading_path": [
"Snap"
],
"index_version": "v1.0",
"indexed_at": "2024-01-01T00:00:00Z",
"rank": 1,
"retrieval": {
"fusion_score": 1.4490997273242101e-6,
"lexical_rank": 1,
"lexical_score": 1.4490997273242101e-6,
"method": "lexical",
"vector_rank": null,
"vector_score": null
},
"score_kind": "bm25",
"section_label": "Snap",
"snippet": "alpha alpha",
"source_id": "default",
"stale": false,
"trust_level": "primary"
},
{
"chunk_id": "c1000000000000000000000000000000",
"chunker_version": "v1",
"citation": {
"end": 2,
"kind": "line",
"path": "notes/snap.md",
"section": "Snap",
"start": 1
},
"doc_id": "d0000000000000000000000000000000",
"doc_path": "notes/snap.md",
"embedding_model": null,
"heading_path": [
"Snap"
],
"index_version": "v1.0",
"indexed_at": "2024-01-01T00:00:00Z",
"rank": 2,
"retrieval": {
"fusion_score": 9.641424867368187e-7,
"lexical_rank": 2,
"lexical_score": 9.641424867368187e-7,
"method": "lexical",
"vector_rank": null,
"vector_score": null
},
"score_kind": "bm25",
"section_label": "Snap",
"snippet": "alpha bravo charlie",
"source_id": "default",
"stale": false,
"trust_level": "primary"
}
]