diff --git a/api/app/core/workflow/nodes/llm/node.py b/api/app/core/workflow/nodes/llm/node.py index 3d9d2fa5..bb87c845 100644 --- a/api/app/core/workflow/nodes/llm/node.py +++ b/api/app/core/workflow/nodes/llm/node.py @@ -246,7 +246,10 @@ class LLMNode(BaseNode): logger.info(f"节点 {self.node_id} LLM 调用完成,输出长度: {len(content)}") # 返回 AIMessage(包含响应元数据) - return AIMessage(content=content, response_metadata=response.response_metadata) + return AIMessage(content=content, response_metadata={ + **response.response_metadata, + "token_usage": getattr(response, 'usage_metadata', None) or response.response_metadata.get('token_usage') + }) def _extract_input(self, state: WorkflowState, variable_pool: VariablePool) -> dict[str, Any]: """提取输入数据(用于记录)""" @@ -305,15 +308,16 @@ class LLMNode(BaseNode): # 调用 LLM(流式,支持字符串或消息列表) last_meta_data = {} + last_usage_metadata = {} async for chunk in llm.astream(self.messages): - # 提取内容 if hasattr(chunk, 'content'): content = self.process_model_output(chunk.content) else: content = str(chunk) - if hasattr(chunk, 'response_metadata'): - if chunk.response_metadata: - last_meta_data = chunk.response_metadata + if hasattr(chunk, 'response_metadata') and chunk.response_metadata: + last_meta_data = chunk.response_metadata + if hasattr(chunk, 'usage_metadata') and chunk.usage_metadata: + last_usage_metadata = chunk.usage_metadata # 只有当内容不为空时才处理 if content: @@ -336,7 +340,10 @@ class LLMNode(BaseNode): # 构建完整的 AIMessage(包含元数据) final_message = AIMessage( content=full_response, - response_metadata=last_meta_data + response_metadata={ + **last_meta_data, + "token_usage": last_usage_metadata or last_meta_data.get('token_usage') + } ) # yield 完成标记 diff --git a/api/app/core/workflow/nodes/parameter_extractor/node.py b/api/app/core/workflow/nodes/parameter_extractor/node.py index 97b1f199..901eddcf 100644 --- a/api/app/core/workflow/nodes/parameter_extractor/node.py +++ b/api/app/core/workflow/nodes/parameter_extractor/node.py @@ -208,7 +208,10 @@ class ParameterExtractorNode(BaseNode): ]) model_resp = await llm.ainvoke(messages) - self.response_metadata = model_resp.response_metadata + self.response_metadata = { + **model_resp.response_metadata, + "token_usage": getattr(model_resp, 'usage_metadata', None) or model_resp.response_metadata.get('token_usage') + } model_message = self.process_model_output(model_resp.content) result = json_repair.repair_json(model_message, return_objects=True) logger.info(f"node: {self.node_id} get params:{result}") diff --git a/api/app/core/workflow/nodes/question_classifier/node.py b/api/app/core/workflow/nodes/question_classifier/node.py index 520eb5b0..74ff1cf9 100644 --- a/api/app/core/workflow/nodes/question_classifier/node.py +++ b/api/app/core/workflow/nodes/question_classifier/node.py @@ -136,7 +136,10 @@ class QuestionClassifierNode(BaseNode): response = await llm.ainvoke(messages) result = self.process_model_output(response.content) - self.response_metadata = response.response_metadata + self.response_metadata = { + **response.response_metadata, + "token_usage": getattr(response, 'usage_metadata', None) or response.response_metadata.get('token_usage') + } if result in category_names: category = result