1. 统一为使用基于pydantic的.env环境变量管理配置
2. 全项目基于loguru进行日志管理
This commit is contained in:
@@ -3,12 +3,11 @@ Report Engine节点基类
|
||||
定义所有处理节点的基础接口
|
||||
"""
|
||||
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Dict, Optional
|
||||
from ..llms.base import LLMClient
|
||||
from ..state.state import ReportState
|
||||
|
||||
from loguru import logger
|
||||
|
||||
class BaseNode(ABC):
|
||||
"""节点基类"""
|
||||
@@ -23,7 +22,6 @@ class BaseNode(ABC):
|
||||
"""
|
||||
self.llm_client = llm_client
|
||||
self.node_name = node_name or self.__class__.__name__
|
||||
self.logger = logging.getLogger('ReportEngine')
|
||||
|
||||
@abstractmethod
|
||||
def run(self, input_data: Any, **kwargs) -> Any:
|
||||
@@ -66,12 +64,12 @@ class BaseNode(ABC):
|
||||
def log_info(self, message: str):
|
||||
"""记录信息日志"""
|
||||
formatted_message = f"[{self.node_name}] {message}"
|
||||
self.logger.info(formatted_message)
|
||||
logger.info(formatted_message)
|
||||
|
||||
def log_error(self, message: str):
|
||||
"""记录错误日志"""
|
||||
formatted_message = f"[{self.node_name}] {message}"
|
||||
self.logger.error(formatted_message)
|
||||
logger.error(formatted_message)
|
||||
|
||||
|
||||
class StateMutationNode(BaseNode):
|
||||
|
||||
@@ -6,6 +6,7 @@ HTML生成节点
|
||||
import json
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any
|
||||
from loguru import logger
|
||||
|
||||
from .base_node import StateMutationNode
|
||||
from ..llms.base import LLMClient
|
||||
@@ -42,7 +43,7 @@ class HTMLGenerationNode(StateMutationNode):
|
||||
Returns:
|
||||
生成的HTML内容
|
||||
"""
|
||||
self.log_info("开始生成HTML报告...")
|
||||
logger.info("开始生成HTML报告...")
|
||||
|
||||
try:
|
||||
# 准备LLM输入数据
|
||||
@@ -64,11 +65,11 @@ class HTMLGenerationNode(StateMutationNode):
|
||||
# 处理响应(简化版)
|
||||
processed_response = self.process_output(response)
|
||||
|
||||
self.log_info("HTML报告生成完成")
|
||||
logger.info("HTML报告生成完成")
|
||||
return processed_response
|
||||
|
||||
except Exception as e:
|
||||
self.log_error(f"HTML生成失败: {str(e)}")
|
||||
logger.exception(f"HTML生成失败: {str(e)}")
|
||||
# 返回备用HTML
|
||||
return self._generate_fallback_html(input_data)
|
||||
|
||||
@@ -104,7 +105,7 @@ class HTMLGenerationNode(StateMutationNode):
|
||||
HTML内容
|
||||
"""
|
||||
try:
|
||||
self.log_info(f"处理LLM原始输出,长度: {len(output)} 字符")
|
||||
logger.info(f"处理LLM原始输出,长度: {len(output)} 字符")
|
||||
|
||||
html_content = output.strip()
|
||||
|
||||
@@ -120,14 +121,14 @@ class HTMLGenerationNode(StateMutationNode):
|
||||
|
||||
# 如果内容为空,返回原始输出
|
||||
if not html_content:
|
||||
self.log_info("处理后内容为空,返回原始输出")
|
||||
logger.info("处理后内容为空,返回原始输出")
|
||||
html_content = output
|
||||
|
||||
self.log_info(f"HTML处理完成,最终长度: {len(html_content)} 字符")
|
||||
logger.info(f"HTML处理完成,最终长度: {len(html_content)} 字符")
|
||||
return html_content
|
||||
|
||||
except Exception as e:
|
||||
self.log_error(f"处理HTML输出失败: {str(e)},返回原始输出")
|
||||
logger.exception(f"处理HTML输出失败: {str(e)},返回原始输出")
|
||||
return output
|
||||
|
||||
def _generate_fallback_html(self, input_data: Dict[str, Any]) -> str:
|
||||
@@ -140,7 +141,7 @@ class HTMLGenerationNode(StateMutationNode):
|
||||
Returns:
|
||||
备用HTML内容
|
||||
"""
|
||||
self.log_info("使用备用HTML生成方法")
|
||||
logger.info("使用备用HTML生成方法")
|
||||
|
||||
query = input_data.get('query', '智能舆情分析报告')
|
||||
query_report = input_data.get('query_engine_report', '')
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import os
|
||||
import json
|
||||
from typing import Dict, Any, List, Optional
|
||||
from loguru import logger
|
||||
|
||||
from .base_node import BaseNode
|
||||
from ..prompts import SYSTEM_PROMPT_TEMPLATE_SELECTION
|
||||
@@ -38,7 +39,7 @@ class TemplateSelectionNode(BaseNode):
|
||||
Returns:
|
||||
选择的模板信息
|
||||
"""
|
||||
self.log_info("开始模板选择...")
|
||||
logger.info("开始模板选择...")
|
||||
|
||||
query = input_data.get('query', '')
|
||||
reports = input_data.get('reports', [])
|
||||
@@ -48,7 +49,7 @@ class TemplateSelectionNode(BaseNode):
|
||||
available_templates = self._get_available_templates()
|
||||
|
||||
if not available_templates:
|
||||
self.log_info("未找到预设模板,使用内置默认模板")
|
||||
logger.info("未找到预设模板,使用内置默认模板")
|
||||
return self._get_fallback_template()
|
||||
|
||||
# 使用LLM进行模板选择
|
||||
@@ -57,7 +58,7 @@ class TemplateSelectionNode(BaseNode):
|
||||
if llm_result:
|
||||
return llm_result
|
||||
except Exception as e:
|
||||
self.log_error(f"LLM模板选择失败: {str(e)}")
|
||||
logger.exception(f"LLM模板选择失败: {str(e)}")
|
||||
|
||||
# 如果LLM选择失败,使用备选方案
|
||||
return self._get_fallback_template()
|
||||
@@ -67,7 +68,7 @@ class TemplateSelectionNode(BaseNode):
|
||||
def _llm_template_selection(self, query: str, reports: List[Any], forum_logs: str,
|
||||
available_templates: List[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
|
||||
"""使用LLM进行模板选择"""
|
||||
self.log_info("尝试使用LLM进行模板选择...")
|
||||
logger.info("尝试使用LLM进行模板选择...")
|
||||
|
||||
# 构建模板列表
|
||||
template_list = "\n".join([f"- {t['name']}: {t['description']}" for t in available_templates])
|
||||
@@ -118,10 +119,10 @@ class TemplateSelectionNode(BaseNode):
|
||||
|
||||
# 检查响应是否为空
|
||||
if not response or not response.strip():
|
||||
self.log_error("LLM返回空响应")
|
||||
logger.error("LLM返回空响应")
|
||||
return None
|
||||
|
||||
self.log_info(f"LLM原始响应: {response}")
|
||||
logger.info(f"LLM原始响应: {response}")
|
||||
|
||||
# 尝试解析JSON响应
|
||||
try:
|
||||
@@ -133,18 +134,18 @@ class TemplateSelectionNode(BaseNode):
|
||||
selected_template_name = result.get('template_name', '')
|
||||
for template in available_templates:
|
||||
if template['name'] == selected_template_name or selected_template_name in template['name']:
|
||||
self.log_info(f"LLM选择模板: {selected_template_name}")
|
||||
logger.info(f"LLM选择模板: {selected_template_name}")
|
||||
return {
|
||||
'template_name': template['name'],
|
||||
'template_content': template['content'],
|
||||
'selection_reason': result.get('selection_reason', 'LLM智能选择')
|
||||
}
|
||||
|
||||
self.log_error(f"LLM选择的模板不存在: {selected_template_name}")
|
||||
logger.error(f"LLM选择的模板不存在: {selected_template_name}")
|
||||
return None
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
self.log_error(f"JSON解析失败: {str(e)}")
|
||||
logger.exception(f"JSON解析失败: {str(e)}")
|
||||
# 尝试从文本响应中提取模板信息
|
||||
return self._extract_template_from_text(response, available_templates)
|
||||
|
||||
@@ -163,7 +164,7 @@ class TemplateSelectionNode(BaseNode):
|
||||
|
||||
def _extract_template_from_text(self, response: str, available_templates: List[Dict[str, Any]]) -> Optional[Dict[str, Any]]:
|
||||
"""从文本响应中提取模板信息"""
|
||||
self.log_info("尝试从文本响应中提取模板信息")
|
||||
logger.info("尝试从文本响应中提取模板信息")
|
||||
|
||||
# 查找响应中是否包含模板名称
|
||||
for template in available_templates:
|
||||
@@ -175,7 +176,7 @@ class TemplateSelectionNode(BaseNode):
|
||||
|
||||
for variant in template_name_variants:
|
||||
if variant in response:
|
||||
self.log_info(f"在响应中找到模板: {template['name']}")
|
||||
logger.info(f"在响应中找到模板: {template['name']}")
|
||||
return {
|
||||
'template_name': template['name'],
|
||||
'template_content': template['content'],
|
||||
@@ -189,7 +190,7 @@ class TemplateSelectionNode(BaseNode):
|
||||
templates = []
|
||||
|
||||
if not os.path.exists(self.template_dir):
|
||||
self.log_error(f"模板目录不存在: {self.template_dir}")
|
||||
logger.error(f"模板目录不存在: {self.template_dir}")
|
||||
return templates
|
||||
|
||||
# 查找所有markdown模板文件
|
||||
@@ -210,7 +211,7 @@ class TemplateSelectionNode(BaseNode):
|
||||
'description': description
|
||||
})
|
||||
except Exception as e:
|
||||
self.log_error(f"读取模板文件失败 {filename}: {str(e)}")
|
||||
logger.exception(f"读取模板文件失败 {filename}: {str(e)}")
|
||||
|
||||
return templates
|
||||
|
||||
@@ -235,7 +236,7 @@ class TemplateSelectionNode(BaseNode):
|
||||
|
||||
def _get_fallback_template(self) -> Dict[str, Any]:
|
||||
"""获取备用默认模板(空模板,让LLM自行发挥)"""
|
||||
self.log_info("未找到合适模板,使用空模板让LLM自行发挥")
|
||||
logger.info("未找到合适模板,使用空模板让LLM自行发挥")
|
||||
|
||||
return {
|
||||
'template_name': '自由发挥模板',
|
||||
|
||||
Reference in New Issue
Block a user