diff --git a/ReportEngine/agent.py b/ReportEngine/agent.py index 997600c..f093135 100644 --- a/ReportEngine/agent.py +++ b/ReportEngine/agent.py @@ -433,6 +433,14 @@ class ReportAgent: }) # 章节流式回调:把LLM返回的delta透传给SSE,便于前端实时渲染 def chunk_callback(delta: str, meta: Dict[str, Any], section_ref: TemplateSection = section): + """ + 章节内容流式回调。 + + Args: + delta: LLM最新输出的增量文本。 + meta: 节点回传的章节元数据,兜底时使用。 + section_ref: 默认指向当前章节,保证在缺失元信息时也能定位。 + """ emit('chapter_chunk', { 'chapterId': meta.get('chapterId') or section_ref.chapter_id, 'title': meta.get('title') or section_ref.title, diff --git a/ReportEngine/flask_interface.py b/ReportEngine/flask_interface.py index 08233f6..9261691 100644 --- a/ReportEngine/flask_interface.py +++ b/ReportEngine/flask_interface.py @@ -634,6 +634,13 @@ def stream_task(task_id: str): last_event_id = None def event_generator(): + """ + SSE事件生成器。 + + - 负责注册并消费对应任务的事件队列; + - 先回放历史事件再持续监听实时事件; + - 周期性发送心跳并在任务结束后自动注销监听。 + """ queue = _register_stream(task_id) try: # 断线重连场景下,先补发历史事件,保证界面状态一致 diff --git a/ReportEngine/nodes/chapter_generation_node.py b/ReportEngine/nodes/chapter_generation_node.py index 753dc62..eda6900 100644 --- a/ReportEngine/nodes/chapter_generation_node.py +++ b/ReportEngine/nodes/chapter_generation_node.py @@ -34,6 +34,13 @@ class ChapterJsonParseError(ValueError): """章节LLM输出无法解析为合法JSON时抛出的异常,附带原始文本方便排查。""" def __init__(self, message: str, raw_text: Optional[str] = None): + """ + 构造异常并附加原始输出,便于日志中定位。 + + Args: + message: 人类可读的错误描述。 + raw_text: 触发异常的完整LLM输出。 + """ super().__init__(message) self.raw_text = raw_text @@ -674,6 +681,7 @@ class ChapterGenerationNode(BaseNode): """ def walk(node: Any) -> int: + """递归下钻block树并返回字符估算,跳过非正文类型""" if node is None: return 0 if isinstance(node, list): @@ -891,6 +899,7 @@ class ChapterGenerationNode(BaseNode): fragment_buffer: List[Dict[str, Any]] = [] def flush_buffer(): + """将当前片段缓冲写入merged列表,必要时合并为单段paragraph""" nonlocal fragment_buffer if not fragment_buffer: return diff --git a/ReportEngine/renderers/html_renderer.py b/ReportEngine/renderers/html_renderer.py index 2b8b47e..ac629ae 100644 --- a/ReportEngine/renderers/html_renderer.py +++ b/ReportEngine/renderers/html_renderer.py @@ -427,6 +427,7 @@ class HTMLRenderer: extracted: List[Dict[str, Any]] = [] def traverse(node: Any) -> None: + """递归遍历block树,识别text字段内潜在的嵌套block JSON""" if isinstance(node, dict): for key, value in list(node.items()): if key == "text" and isinstance(value, str): @@ -1087,10 +1088,20 @@ class HTMLRenderer: return tuple(normalized) if normalized else None def _normalize_kpi_item(self, item: Any) -> tuple[str, str, str, str, str] | None: + """ + 将单条KPI记录规整为可对比的签名。 + + 参数: + item: KPI数组中的原始字典,可能缺失字段或类型混杂。 + + 返回: + tuple | None: (label, value, unit, delta, tone) 的五元组;若输入非法则为None。 + """ if not isinstance(item, dict): return None def normalize(value: Any) -> str: + """统一各类值的表现形式,便于生成稳定签名""" if value is None: return "" if isinstance(value, (int, float)):