Files
2026Technology-Competition/docs/superpowers/plans/rag-task-5-report.md
T

53 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RAG 影响调查接入(Task 5)实现报告
日期:2026-08-29
范式步骤:Agent 实现(RAG 迭代 Task 5,含评审修订 D1/D3
## 真实代码要点(先读后改)
- `src/genesis/server/service.py`
- `GenesisService.__init__`:新增 `rag: ImpactRAG | None = None``use_rag: bool = False``rag_db_path: str | None = None``embedder=None`(默认 `get_embedder("fake")`)。保存 `self.rag`/`self.use_rag``rag=None` 为不启用(向后兼容默认关闭)。
- `upload_file`:当 `file_type == "existing_system"``self.rag is not None`,解压后 `self.rag.index_dir(session_id, path)`;异常 `try/except` + `_LOGGER.warning` 不阻断上传(D1 上传即索引,scope=session_id)。
- `run_impact` 改为 `async def run_impact(self, session_id, use_rag=None)``eff = self.use_rag if use_rag is None else use_rag``eff 且 self.rag is not None` 时走 RAG 路径——`engine` 为空则 `build_inference_engine()`;取 `requirements_text = rec.files["requirements"]["name"] or "要件定義"``await ImpactAgent(engine=..., rag=..., use_rag=True).run_impact(...)`;写 `status=awaiting_impact_confirm` + `impact_summary={"rag_enabled": True, "impact_llm": ...}`,并尽量保留 `impact_report_path`。否则走原确定性 `ImpactAgent().run(...)` 路径(行为不变)。
- `src/genesis/server/app.py`
- `create_app` 新增 `rag=None`;为 None 时内部构造 `RagStore(data_root/rag.db) + ImpactRAG(..., get_embedder("fake"))`(先 `mkdir(parents=True)` 防止 `unable to open database file`),以 `rag=rag, use_rag=False` 注入 `GenesisService`
- **Critical 修复**`_FakeEngine.chat_structured` 改为 `async def`(与真实 `InferenceEngine` 一致)。
- `start_impact` 改为 `async def start_impact(sid, use_rag=False)``await service.run_impact(sid, use_rag=use_rag)`
- `src/genesis/chat/agent.py``_parse_and_confirm``_run_impact` 中两处 `self.service.run_impact(...)``asyncio.run(...)` 包裹(兼容同步消息处理,避免协程未执行)。
- `tests/test_server_service.py`:两处 `svc.run_impact(...)` 改为 `asyncio.run(svc.run_impact(...))`,保持全绿。
- `tests/test_impact_rag_e2e.py`(新增,D3 强验证):真实 `GenesisService` + 临时 `SessionStore` + 临时 `data_root` + 异步 `FakeEngine`(捕获 prompt+ `ImpactRAG(RagStore(tmp/rag.db), FakeEmbedder())``use_rag=True`
- 辅助:`zipfile` 构造含 `src/KnownOrder.java`(内容含「订单创建调用 MyBatis」)的 existing_system ziprequirements/template 用 `glob` 定位 `sample/` 下真实文件。
- 流程:create_session → upload requirements → upload template → upload existing_system → run_parse → confirm_parse(→ impact_running)→ `asyncio.run(svc.run_impact(sid, use_rag=True))`
- 核心断言:`FakeEngine.captured` 含「KnownOrder」(上传源码被 RAG 检索并注入 LLM prompt);上传后 `rag.retrieve(sid, "订单创建", k=1)` 命中非空(D1 验证);另起会话 `rag=None` 且默认 `use_rag` 时走确定性路径、`captured is None` 且不含 RAG 小节标题(向后兼容)。
## 验证状态
- `python -m pytest tests/test_impact_rag_e2e.py -q`**2 passed**
- `python -m pytest tests/test_server_service.py -q`**20 passed**
- `python -m pytest tests/ -k "server or impact or chat" -q`**228 passed**(无回归;最初 `test_server_api``rag.db` 目录不存在报 `OperationalError`,已通过 `Path(rag_db).parent.mkdir(...)` 修复)
## 自我审查(顾虑)
- `create_app` 现在总会创建 `data_root/rag.db`(即使 `use_rag=False`);默认 `app = create_app()` 会在工作区生成 `data/server/rag.db` 文件,属轻微副作用,可接受(向后兼容且关闭时不参与影响调查)。
- `chat/agent.py``asyncio.run` 包裹 `run_impact` 是最小侵入方案;若未来聊天层整体异步化,可改为直接 `await`
- 覆盖配置 `fail_under=99%`,单文件运行 e2e 会因采样不足触发覆盖率告警(非测试失败);以 `-o addopts=""` 运行可获干净结果。
- RAG 路径不依赖 `_rebuild_source`(仅用 requirements 文件名 + RAG 检索),与 Brief 一致;确定性路径仍保留 `_rebuild_source`
## 修复后验证(复审 Minor 3 项最小化修复)
日期:2026-08-30
范式步骤:反馈迭代(RAG 迭代 Task 5 复审 Minor 修复)
### 修复项
1. **死存储(service.py**:移除 `GenesisService.__init__``rag_db_path``embedder` 两个未使用参数及其赋值(`rag`/`use_rag` 保留)。已确认全仓无调用方传入这两个参数(仅 `app.create_app``rag=`)。
2. **引擎构建竞态(service.py**`run_impact` 中引擎懒构建改为双重检查锁:`__init__` 新增 `self._engine_lock = threading.Lock()`,构建处 `with self._engine_lock: if self.engine is None: self.engine = build_inference_engine()`(新增 `import threading`)。
3. **文档措辞(docs/design.md**:将"端点同步改为 `async def`"改为"端点改为 `async def`"(原端点本就是同步 def,去掉"同步"歧义)。
### 验证命令
`python -m pytest tests/test_impact_rag_e2e.py tests/test_server_service.py -q`
### 结果摘要
- **22 passed**test_impact_rag_e2e 2 + test_server_service 20),无回归。
- 注:覆盖率门禁 `fail_under=99%` 在仅运行这两个文件时会触发(项目级全量门禁,与本次修复无关,非测试失败)。按报告既有建议以 `-o addopts=""` 运行可获干净结果。
- 默认路径语义与 `use_rag=False` 行为保持不变。