"""用户交互节点 与用户交互获取章节填写要求和RAG配置。 """ import logging from typing import Any, Dict from ..base import BaseNode, NodeContext logger = logging.getLogger(__name__) class InteractWithUserNode(BaseNode): """用户交互节点 职责: 1. 询问用户该章节需要强调的内容 2. 询问是否使用RAG知识库 3. 如果使用RAG,选择具体的知识库 4. 保存配置供后续子章节继承 """ @property def name(self) -> str: return "interact_user" @property def description(self) -> str: return "与用户交互获取章节配置" def execute(self, state: Dict[str, Any], context: NodeContext) -> Dict[str, Any]: """执行用户交互 Args: state: 当前状态 context: 执行上下文 Returns: 更新后的状态 """ chapter = state.get("current_chapter", {}) chapter_id = chapter.get("id") chapter_title = chapter.get("title") if not chapter_id: raise ValueError("当前章节信息缺失") # 检查是否需要交互 needs_interaction = state.get("needs_interaction", False) if not needs_interaction: # 不需要交互,直接返回 return state # 获取交互处理器 interaction_handler = state.get("interaction_handler") if not interaction_handler: # 无交互处理器时立即失败,暴露配置问题 raise ValueError("交互处理器未配置,无法获取章节配置") logger.info(f"开始与用户交互,获取章节配置: {chapter_id} - {chapter_title}") # 1. 询问需要强调的内容 emphasis = interaction_handler( interaction_type="text", prompt=f"📝 正在处理章节:{chapter_id}. {chapter_title}\n" f" 是否有需要特别强调的内容?(直接回车跳过)", default="", key=f"emphasis_{chapter_id}", ) # 2. 询问是否使用RAG use_rag_response = interaction_handler( interaction_type="choice", prompt="是否使用RAG知识库辅助生成内容", options=["是", "否"], default="否", key=f"use_rag_{chapter_id}", ) use_rag = use_rag_response == "是" rag_store = None # 3. 如果使用RAG,选择知识库 if use_rag: rag_store = self._select_rag_store(interaction_handler, chapter_id, state) # 保存章节配置 config = { "emphasis": emphasis.strip() if emphasis else "", "rag_enabled": use_rag, "rag_store": rag_store, } state.setdefault("chapter_configs", {})[chapter_id] = config logger.info( f"章节配置已保存: 强调内容={'有' if config['emphasis'] else '无'}, " f"RAG={'启用' if use_rag else '禁用'}" ) return state def _select_rag_store(self, interaction_handler, chapter_id: str, state: Dict[str, Any]) -> str: """选择RAG知识库 Args: interaction_handler: 交互处理器 chapter_id: 章节ID state: 当前状态 Returns: 知识库标识 """ # 从state获取RAGTool实例(由InitConfigNode统一初始化) rag_tool = state.get("rag_tool") if not rag_tool: raise ValueError("RAGTool未初始化,请检查InitConfigNode配置") try: stats = rag_tool.get_stats() total_chunks = stats.get("total_chunks", 0) total_files = stats.get("total_files", 0) # 显示知识库统计信息 store_info = f"默认知识库 ({total_files}个文档, {total_chunks}个文档块)" choice = interaction_handler( interaction_type="choice", prompt=f"选择知识库", options=[ ("default", store_info), ("none", "不使用RAG") ], default="default", key=f"rag_store_{chapter_id}", ) if choice == "default": return "default" return None except Exception as e: logger.error(f"获取知识库信息失败: {e}", exc_info=True) raise ValueError("获取知识库信息失败,无法选择RAG存储") from e