test(rag): 补充引擎懒构建与 HTTP 级 RAG e2e 覆盖,恢复 99% 门禁
This commit is contained in:
@@ -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_structured(RAG 路径,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
|
||||||
|
|||||||
Reference in New Issue
Block a user