from bidmaster.nodes.base import NodeContext from bidmaster.nodes.toc import generate_sub_chapters as gen_module from bidmaster.nodes.toc.generate_sub_chapters import GenerateSubChaptersNode from bidmaster.nodes.toc.user_feedback import UserFeedbackNode from bidmaster.tools.parser import DocumentChapter, ScoringCriteria, TechnicalCategory from bidmaster.utils.document_context import DocumentContext, DocumentContextMatch def test_generate_sub_chapters_uses_context(monkeypatch): captured = {} def fake_generate(criteria_list, parent_chapter, context_snippets=None): captured["context"] = context_snippets return [{"title": "示例小节", "level": 2, "score": 5, "children": []}] class DummySearcher: def __init__(self, *args, **kwargs): pass def search(self, query, top_k=None): return [ DocumentContextMatch( text="系统采用云边协同架构,强调稳定性。", section="项目概述", score=0.95, source_type="paragraph", metadata={}, ) ] monkeypatch.setattr(gen_module, "DocumentContextSearcher", DummySearcher) monkeypatch.setattr(gen_module.LLMHelper, "generate_sub_chapters_ai", staticmethod(fake_generate)) chapter = DocumentChapter( id="chapter_01_technical_solution", title="技术方案", level=1, score=30, ) criteria = [ ScoringCriteria( item_name="系统架构先进性", max_score=10, description="阐述云边端协同", category=TechnicalCategory.TECHNICAL_SOLUTION, chapter_id="chapter_01_technical_solution", original_index=0, ) ] state = { "preliminary_chapters": [chapter], "technical_criteria": criteria, "document_context": DocumentContext("demo.docx", "test-model", []), } node = GenerateSubChaptersNode() result = node.execute(state, NodeContext()) assert result["preliminary_chapters"][0].children assert captured["context"] and "项目概述" in captured["context"][0] def test_user_feedback_auto_triggers_optimization(): chapters = [ DocumentChapter( id="chapter_01", title="技术方案", level=1, score=30, ) ] state = { "final_chapters": chapters, "structure_review": { "suggestions": [ {"description": "补充智慧运维章节", "priority": "high", "type": "add"}, {"description": "可选优化", "priority": "low", "type": "modify"}, ] }, "auto_mode": True, "auto_toc_max_rounds": 2, "auto_optimization_rounds": 0, } node = UserFeedbackNode() result = node.execute(state, NodeContext()) assert result["needs_optimization"] is True assert "补充" in result["user_feedback"] assert result["auto_optimization_rounds"] == 1 assert result["pending_suggestions"] == [] def test_user_feedback_auto_skips_when_no_priority(): chapters = [ DocumentChapter( id="chapter_02", title="实施计划", level=1, score=20, ) ] state = { "final_chapters": chapters, "structure_review": {"suggestions": [{"description": "微调描述", "priority": "low", "type": "modify"}]}, "auto_mode": True, "auto_toc_max_rounds": 1, } node = UserFeedbackNode() result = node.execute(state, NodeContext()) assert result["needs_optimization"] is False assert result["user_feedback"] == "" def test_user_feedback_auto_respects_round_limit(): chapters = [ DocumentChapter(id="chapter_03", title="服务方案", level=1, score=10) ] state = { "final_chapters": chapters, "structure_review": { "suggestions": [{"description": "增加服务考核", "priority": "high", "type": "add"}] }, "auto_mode": True, "auto_toc_max_rounds": 1, "auto_optimization_rounds": 1, "pending_suggestions": [{"description": "增加服务考核", "priority": "high", "type": "add"}], } node = UserFeedbackNode() result = node.execute(state, NodeContext()) assert result["needs_optimization"] is False assert result["pending_suggestions"] == []