test(rag): 补充引擎懒构建与 HTTP 级 RAG e2e 覆盖,恢复 99% 门禁

This commit is contained in:
lhl
2026-08-30 00:44:49 +08:00
parent 9a02fcd00f
commit ee224e7c56
+78
View File
@@ -8,10 +8,14 @@ from __future__ import annotations
import asyncio import asyncio
import glob import glob
import io import io
import json
import zipfile import zipfile
from pathlib import Path from pathlib import Path
import pytest import pytest
from fastapi.testclient import TestClient
from genesis.server.app import create_app
from genesis.impact.impact_agent import _RAG_CONTEXT_TITLE from genesis.impact.impact_agent import _RAG_CONTEXT_TITLE
from genesis.rag.embeddings import FakeEmbedder from genesis.rag.embeddings import FakeEmbedder
@@ -144,3 +148,77 @@ def test_rag_e2e_use_rag_false_backward_compat(tmp_path):
assert _RAG_CONTEXT_TITLE not in (engine.captured or "") assert _RAG_CONTEXT_TITLE not in (engine.captured or "")
# 确定性报告存在 # 确定性报告存在
assert rec.impact_report_path and Path(rec.impact_report_path).exists() assert rec.impact_report_path and Path(rec.impact_report_path).exists()
def test_service_rag_lazy_engine_build(tmp_path, monkeypatch):
"""覆盖 service.py:233-236:构造未传 engine 且 run_impact(use_rag=True) 时懒构建引擎。"""
store = SessionStore(db_path=str(tmp_path / "s.db"))
rag = ImpactRAG(RagStore(str(tmp_path / "rag.db")), FakeEmbedder())
# 注入的懒构建产物:一个会捕获 prompt 的 FakeEngine
injected_engine = FakeEngine()
monkeypatch.setattr(
"genesis.inference.factory.build_inference_engine", lambda: injected_engine
)
svc = GenesisService(
store=store,
data_root=str(tmp_path / "data"),
rag=rag,
use_rag=False, # 构造时不传 engine、RAG 默认关闭
)
assert svc.engine is None # 尚未构建
sid = svc.create_session("u1").session_id
svc.upload_file(sid, "requirements", "requirements_newdev.xlsx", _sample_req())
svc.upload_file(sid, "template", "template_design_ja.docx", _sample_tpl())
# 上传即索引(D1),existing_system 含 KnownOrder 源码
svc.upload_file(sid, "existing_system", "existing.zip", _make_existing_zip())
svc.run_parse(sid)
svc.confirm_parse(sid)
assert svc.get_session(sid).status == "impact_running"
# 显参开启 RAG → 触发 engine 为 None 的懒构建分支
rec = asyncio.run(svc.run_impact(sid, use_rag=True))
assert rec.status == "awaiting_impact_confirm"
# 懒构建的引擎被注入并实际使用
assert svc.engine is injected_engine
summary = json.loads(rec.impact_summary)
assert summary.get("rag_enabled") is True
# 引擎捕获的 prompt 含 RAG 检索注入的 KnownOrder 片段
assert injected_engine.captured is not None
assert "KnownOrder" in injected_engine.captured
def test_http_start_impact_use_rag_e2e(tmp_path):
"""覆盖 app.py start_impact 异步端点 + _FakeEngine.chat_structuredRAG 路径,HTTP 级)。"""
store = SessionStore(db_path=str(tmp_path / "s.db"))
rag = ImpactRAG(RagStore(str(tmp_path / "rag.db")), FakeEmbedder())
app = create_app(
store=store,
data_root=str(tmp_path / "data"),
engine="fake", # 触发内部 _FakeEngine(异步 chat_structured
rag=rag,
)
client = TestClient(app)
sid = client.post("/api/sessions", json={"user_id": "u1"}).json()["session_id"]
# multipart 上传:要件/模板/既有系统
client.post(f"/api/sessions/{sid}/files",
data={"file_type": "requirements"},
files={"file": ("requirements_newdev.xlsx", _sample_req())})
client.post(f"/api/sessions/{sid}/files",
data={"file_type": "template"},
files={"file": ("template_design_ja.docx", _sample_tpl())})
client.post(f"/api/sessions/{sid}/files",
data={"file_type": "existing_system"},
files={"file": ("existing.zip", _make_existing_zip())})
assert client.post(f"/api/sessions/{sid}/start-parse").status_code == 200
# 有既有系统 → impact_running
assert client.post(f"/api/sessions/{sid}/confirm-parse").json()["status"] == "impact_running"
# 异步端点:start-impact?use_rag=True(显参开启 RAG
r = client.post(f"/api/sessions/{sid}/start-impact?use_rag=True")
assert r.status_code == 200
ir = client.get(f"/api/sessions/{sid}/impact-result").json()
# 经 HTTP 真实走到 RAG 路径,摘要标记 rag_enabled
assert ir.get("rag_enabled") is True