from bidmaster.nodes.base import NodeContext from bidmaster.nodes.toc.prepare_tech_consistency_prompt import ( PrepareTechConsistencyPromptNode, ) from bidmaster.tools.parser import ScoringCriteria, TechnicalCategory class DummyRagTool: def __init__(self, results): self._results = results self.last_query = None def search(self, query: str, k: int = 5): self.last_query = query return list(self._results) def _criteria(description: str): return [ ScoringCriteria( item_name="技术方案-基本要求", max_score=3.0, description=description, category=TechnicalCategory.TECHNICAL_SOLUTION, chapter_id="chapter_01_technical_solution", original_index=0, ) ] def test_prepare_prompt_uses_tender_and_rag_when_available(): rag = DummyRagTool( results=[ {"content": "系统采用云边端协同架构,边缘侧负责就近处理与缓存。", "score": 0.9}, {"content": "技术选型:容器化部署+统一监控告警+权限审计。", "score": 0.8}, ] ) state = { "technical_criteria": _criteria("供应商须提供总体架构设计方案,包含技术选型与安全策略。"), "rag_tool": rag, } node = PrepareTechConsistencyPromptNode() result = node.execute(state, NodeContext()) assert result["tech_consistency_source"] == "tender+rag" prompt = result["tech_consistency_prompt"] assert "招标技术要求摘录" in prompt assert "知识库技术解决方案摘录" in prompt assert "云边端协同" in prompt def test_prepare_prompt_falls_back_when_rag_missing(): rag = DummyRagTool(results=[]) state = { "technical_criteria": _criteria("供应商须提供总体架构设计方案,包含技术选型与安全策略。"), "rag_tool": rag, } node = PrepareTechConsistencyPromptNode() result = node.execute(state, NodeContext()) assert result["tech_consistency_source"] == "fallback" prompt = result["tech_consistency_prompt"] assert "系统架构" in prompt assert "技术选型" in prompt