feat(rag): v1 rerank 精排 + bge-m3 多语言切换(T6/T11 架构审查整改)
- T6 (Issue6): RerankConfig(enabled/model=BAAI/bge-reranker-v2-m3/device)
- rag-layer-design §6.3 Rerank 精排:窗口=RRF top-10、候选≤top_k 跳过、
故障降级 RRF 原序;原 §6.3-6.6 顺延 6.4-6.7
- config-design §5 新增 rerank 段;design §5.5 检索策略加 rerank
- T11 (OV2): EmbeddingConfig.model 默认 bge-small-zh-v1.5 → BAAI/bge-m3(日文语料)
- rag-layer-design 选型表/依赖表/manifest/流程图同步 + 新增 §2.3 日文样本验证
- design.md / implementation-plan 4.3 / config-design embedding 同步
- 新增 test_rag_design_consistency.py 一致性门禁(6 用例防文档漂移)
- TDD: RED(默认模型仍旧 + rerank 字段不存在)→ GREEN → 全量 198 passed / 100.00%(996 stmts/252 br)
This commit is contained in:
Vendored
+5
-2
@@ -1,8 +1,11 @@
|
||||
embedding:
|
||||
model: BAAI/bge-small-zh-v1.5
|
||||
model: BAAI/bge-m3
|
||||
vector_store:
|
||||
adapter: chroma
|
||||
chroma:
|
||||
persist_dir: /data/shared/rules-handbook/chroma
|
||||
retrieval:
|
||||
rrf_k: 42
|
||||
rrf_k: 42
|
||||
rerank:
|
||||
enabled: true
|
||||
model: BAAI/bge-reranker-v2-m3
|
||||
+26
-3
@@ -35,7 +35,7 @@ def test_from_dir_maps_yaml_fields():
|
||||
assert s.inference.models.primary.name == "deepseek-chat"
|
||||
assert s.inference.llm_calls.max_context_tokens == 16000
|
||||
assert s.inference.structured_output.max_parse_retry == 3
|
||||
assert s.rag.embedding.model == "BAAI/bge-small-zh-v1.5"
|
||||
assert s.rag.embedding.model == "BAAI/bge-m3"
|
||||
assert s.rag.retrieval.rrf_k == 42
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ def test_defaults_when_dir_empty(tmp_path):
|
||||
assert s.app.server.max_upload_mb == 100
|
||||
assert s.app.task_queue["backend"] == "memory"
|
||||
assert s.inference.models.primary.name == "deepseek-chat"
|
||||
assert s.rag.embedding.model == "BAAI/bge-small-zh-v1.5"
|
||||
assert s.rag.embedding.model == "BAAI/bge-m3"
|
||||
assert s.rag.retrieval.rrf_k == 60
|
||||
|
||||
|
||||
@@ -82,4 +82,27 @@ def test_expand_env_list_branch(monkeypatch):
|
||||
data = {"models": [{"name": "a", "key": "${SOME_API_KEY}"}, "plain"]}
|
||||
out = _expand_env(data)
|
||||
assert out["models"][0]["key"] == "sk-list-xyz"
|
||||
assert out["models"][1] == "plain"
|
||||
assert out["models"][1] == "plain"
|
||||
|
||||
|
||||
# ---------- T6/T11: rerank 精排 + bge-m3 多语言(I6/OV2) ----------
|
||||
|
||||
def test_embedding_default_model_is_bge_m3():
|
||||
"""OV2:bge-small-zh 面向中文、实际语料为日文 → 默认切换多语言 bge-m3。"""
|
||||
s = Settings()
|
||||
assert s.rag.embedding.model == "BAAI/bge-m3"
|
||||
|
||||
|
||||
def test_rerank_config_defaults():
|
||||
"""I6:v1 引入 rerank 精排(bge-reranker-v2-m3),默认启用、device=cpu。"""
|
||||
s = Settings()
|
||||
assert s.rag.rerank.enabled is True
|
||||
assert s.rag.rerank.model == "BAAI/bge-reranker-v2-m3"
|
||||
assert s.rag.rerank.device == "cpu"
|
||||
|
||||
|
||||
def test_rerank_env_override(monkeypatch):
|
||||
monkeypatch.setenv("GENESIS_RAG__RERANK__ENABLED", "false")
|
||||
s = Settings.from_dir(FIXTURES)
|
||||
assert s.rag.rerank.enabled is False
|
||||
assert s.rag.rerank.model == "BAAI/bge-reranker-v2-m3"
|
||||
@@ -0,0 +1,84 @@
|
||||
"""RAG 模型选型一致性门禁:T6/T11 整改(I6/OV2)的机器契约。
|
||||
|
||||
- T6(I6):v1 引入 rerank 精排 bge-reranker-v2-m3
|
||||
- T11(OV2):embedding 默认切换多语言 bge-m3(实际语料为日文)
|
||||
|
||||
防文档漂移:代码默认值、fixture、当前设计文档四处必须一致;
|
||||
当前设计文档不得残留 bge-small-zh-v1.5(历史评审记录/计划快照不改写,故不扫描)。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
from genesis.config import Settings
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FIXTURES = Path(__file__).parent / "fixtures"
|
||||
|
||||
# 当前设计文档(排除历史评审记录 docs/design-review.md、docs/*-review*.md、
|
||||
# docs/superpowers/plans/* 等历史快照)
|
||||
_CURRENT_DOCS = [
|
||||
"docs/rag-layer-design.md",
|
||||
"docs/config-design.md",
|
||||
"docs/design.md",
|
||||
"docs/implementation-plan.md",
|
||||
]
|
||||
|
||||
EMBEDDING_MODEL = "BAAI/bge-m3"
|
||||
RERANK_MODEL = "BAAI/bge-reranker-v2-m3"
|
||||
# 设计文档用短名(bge-m3);全名含短名子串,故 token 宽松匹配
|
||||
_EMBEDDING_TOKEN = "bge-m3"
|
||||
_RERANK_TOKEN = "bge-reranker-v2-m3"
|
||||
|
||||
|
||||
def _doc_text(name: str) -> str:
|
||||
return (ROOT / name).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def _fixture_rag() -> dict:
|
||||
with (FIXTURES / "rag.yaml").open("r", encoding="utf-8") as f:
|
||||
return yaml.safe_load(f) or {}
|
||||
|
||||
|
||||
# ---------- 代码默认值(T11) ----------
|
||||
|
||||
def test_code_default_embedding_is_bge_m3():
|
||||
s = Settings()
|
||||
assert s.rag.embedding.model == EMBEDDING_MODEL
|
||||
|
||||
|
||||
# ---------- 代码默认值(T6) ----------
|
||||
|
||||
def test_code_rerank_config_defaults():
|
||||
s = Settings()
|
||||
assert s.rag.rerank.enabled is True
|
||||
assert s.rag.rerank.model == RERANK_MODEL
|
||||
|
||||
|
||||
# ---------- fixture 与代码一致 ----------
|
||||
|
||||
def test_fixture_synced_with_code_defaults():
|
||||
rag = _fixture_rag()
|
||||
assert rag["embedding"]["model"] == EMBEDDING_MODEL
|
||||
assert rag["rerank"]["enabled"] is True
|
||||
assert rag["rerank"]["model"] == RERANK_MODEL
|
||||
|
||||
|
||||
# ---------- 文档与选型一致(T6/T11) ----------
|
||||
|
||||
def test_docs_use_bge_m3():
|
||||
missing = [name for name in _CURRENT_DOCS if _EMBEDDING_TOKEN not in _doc_text(name)]
|
||||
assert not missing, f"以下当前设计文档缺失 {_EMBEDDING_TOKEN}:{missing}"
|
||||
|
||||
|
||||
def test_docs_use_rerank_model():
|
||||
missing = [name for name in _CURRENT_DOCS if _RERANK_TOKEN not in _doc_text(name)]
|
||||
assert not missing, f"以下当前设计文档缺失 {_RERANK_TOKEN}:{missing}"
|
||||
|
||||
|
||||
def test_docs_no_legacy_bge_small_zh():
|
||||
legacy = [name for name in _CURRENT_DOCS if "bge-small-zh-v1.5" in _doc_text(name)]
|
||||
assert not legacy, f"当前设计文档残留旧模型 bge-small-zh-v1.5(请同步为 bge-m3):{legacy}"
|
||||
Reference in New Issue
Block a user