1. 统一为使用基于pydantic的.env环境变量管理配置

2. 全项目基于loguru进行日志管理
This commit is contained in:
Doiiars
2025-11-05 14:56:49 +08:00
parent 1d2e23d8c1
commit 537d682861
50 changed files with 1404 additions and 1731 deletions
+39 -63
View File
@@ -5,7 +5,7 @@ Report Agent主类
import json
import os
import logging
from loguru import logger
from datetime import datetime
from typing import Optional, Dict, Any, List
@@ -15,7 +15,7 @@ from .nodes import (
HTMLGenerationNode
)
from .state import ReportState
from .utils import Config, load_config
from .utils.config import settings, Settings
class FileCountBaseline:
@@ -32,7 +32,7 @@ class FileCountBaseline:
with open(self.baseline_file, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
print(f"加载基准数据失败: {e}")
logger.exception(f"加载基准数据失败: {e}")
return {}
def _save_baseline(self):
@@ -42,7 +42,7 @@ class FileCountBaseline:
with open(self.baseline_file, 'w', encoding='utf-8') as f:
json.dump(self.baseline_data, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"保存基准数据失败: {e}")
logger.exception(f"保存基准数据失败: {e}")
def initialize_baseline(self, directories: Dict[str, str]) -> Dict[str, int]:
"""初始化文件数量基准"""
@@ -59,7 +59,7 @@ class FileCountBaseline:
self.baseline_data = current_counts.copy()
self._save_baseline()
print(f"文件数量基准已初始化: {current_counts}")
logger.info(f"文件数量基准已初始化: {current_counts}")
return current_counts
def check_new_files(self, directories: Dict[str, str]) -> Dict[str, Any]:
@@ -109,7 +109,7 @@ class FileCountBaseline:
class ReportAgent:
"""Report Agent主类"""
def __init__(self, config: Optional[Config] = None):
def __init__(self, config: Optional[Settings] = None):
"""
初始化Report Agent
@@ -117,7 +117,7 @@ class ReportAgent:
config: 配置对象,如果不提供则自动加载
"""
# 加载配置
self.config = config or load_config()
self.config = config or settings
# 初始化文件基准管理器
self.file_baseline = FileCountBaseline()
@@ -138,45 +138,20 @@ class ReportAgent:
self.state = ReportState()
# 确保输出目录存在
os.makedirs(self.config.output_dir, exist_ok=True)
os.makedirs(settings.OUTPUT_DIR, exist_ok=True)
self.logger.info("Report Agent已初始化")
self.logger.info(f"使用LLM: {self.llm_client.get_model_info()}")
logger.info("Report Agent已初始化")
logger.info(f"使用LLM: {self.llm_client.get_model_info()}")
def _setup_logging(self):
"""设置日志"""
# 确保日志目录存在
log_dir = os.path.dirname(self.config.log_file)
log_dir = os.path.dirname(settings.LOG_FILE)
os.makedirs(log_dir, exist_ok=True)
# 创建专用的logger,避免与其他模块冲突
self.logger = logging.getLogger('ReportEngine')
self.logger.setLevel(logging.INFO)
logger.add(settings.LOG_FILE, level="INFO")
# 清除已有的handlers
if self.logger.handlers:
self.logger.handlers.clear()
# 创建文件handler
file_handler = logging.FileHandler(self.config.log_file, encoding='utf-8')
file_handler.setLevel(logging.INFO)
# 创建控制台handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 设置格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
# 添加handlers
self.logger.addHandler(file_handler)
self.logger.addHandler(console_handler)
# 防止日志向上传播
self.logger.propagate = False
def _initialize_file_baseline(self):
"""初始化文件数量基准"""
directories = {
@@ -189,16 +164,16 @@ class ReportAgent:
def _initialize_llm(self) -> LLMClient:
"""初始化LLM客户端"""
return LLMClient(
api_key=self.config.llm_api_key,
model_name=self.config.llm_model_name,
base_url=self.config.llm_base_url,
api_key=settings.REPORT_ENGINE_API_KEY,
model_name=settings.REPORT_ENGINE_MODEL_NAME,
base_url=settings.REPORT_ENGINE_BASE_URL,
)
def _initialize_nodes(self):
"""初始化处理节点"""
self.template_selection_node = TemplateSelectionNode(
self.llm_client,
self.config.template_dir
self.llm_client,
self.config.TEMPLATE_DIR
)
self.html_generation_node = HTMLGenerationNode(self.llm_client)
@@ -219,7 +194,7 @@ class ReportAgent:
"""
start_time = datetime.now()
self.logger.info(f"开始生成报告: {query}")
logger.info(f"开始生成报告: {query}")
self.logger.info(f"输入数据 - 报告数量: {len(reports)}, 论坛日志长度: {len(forum_logs)}")
try:
@@ -238,21 +213,21 @@ class ReportAgent:
generation_time = (end_time - start_time).total_seconds()
self.state.metadata.generation_time = generation_time
self.logger.info(f"报告生成完成,耗时: {generation_time:.2f}")
logger.info(f"报告生成完成,耗时: {generation_time:.2f}")
return html_report
except Exception as e:
self.logger.error(f"报告生成过程中发生错误: {str(e)}")
logger.exception(f"报告生成过程中发生错误: {str(e)}")
raise e
def _select_template(self, query: str, reports: List[Any], forum_logs: str, custom_template: str):
"""选择报告模板"""
self.logger.info("选择报告模板...")
logger.info("选择报告模板...")
# 如果用户提供了自定义模板,直接使用
if custom_template:
self.logger.info("使用用户自定义模板")
logger.info("使用用户自定义模板")
return {
'template_name': 'custom',
'template_content': custom_template,
@@ -271,12 +246,12 @@ class ReportAgent:
# 更新状态
self.state.metadata.template_used = template_result['template_name']
self.logger.info(f"选择模板: {template_result['template_name']}")
self.logger.info(f"选择理由: {template_result['selection_reason']}")
logger.info(f"选择模板: {template_result['template_name']}")
logger.info(f"选择理由: {template_result['selection_reason']}")
return template_result
except Exception as e:
self.logger.error(f"模板选择失败,使用默认模板: {str(e)}")
logger.error(f"模板选择失败,使用默认模板: {str(e)}")
# 直接使用备用模板
fallback_template = {
'template_name': '社会公共热点事件分析报告模板',
@@ -288,7 +263,7 @@ class ReportAgent:
def _generate_html_report(self, query: str, reports: List[Any], forum_logs: str, template_result: Dict[str, Any]) -> str:
"""生成HTML报告"""
self.logger.info("多轮生成HTML报告...")
logger.info("多轮生成HTML报告...")
# 准备报告内容,确保有3个报告
query_report = reports[0] if len(reports) > 0 else ""
@@ -316,7 +291,7 @@ class ReportAgent:
self.state.html_content = html_content
self.state.mark_completed()
self.logger.info("HTML报告生成完成")
logger.info("HTML报告生成完成")
return html_content
def _get_fallback_template_content(self) -> str:
@@ -376,19 +351,19 @@ class ReportAgent:
query_safe = query_safe.replace(' ', '_')[:30]
filename = f"final_report_{query_safe}_{timestamp}.html"
filepath = os.path.join(self.config.output_dir, filename)
filepath = os.path.join(settings.OUTPUT_DIR, filename)
# 保存HTML报告
with open(filepath, 'w', encoding='utf-8') as f:
f.write(html_content)
self.logger.info(f"报告已保存到: {filepath}")
logger.info(f"报告已保存到: {filepath}")
# 保存状态
state_filename = f"report_state_{query_safe}_{timestamp}.json"
state_filepath = os.path.join(self.config.output_dir, state_filename)
state_filepath = os.path.join(settings.OUTPUT_DIR, state_filename)
self.state.save_to_file(state_filepath)
self.logger.info(f"状态已保存到: {state_filepath}")
logger.info(f"状态已保存到: {state_filepath}")
def get_progress_summary(self) -> Dict[str, Any]:
"""获取进度摘要"""
@@ -397,12 +372,12 @@ class ReportAgent:
def load_state(self, filepath: str):
"""从文件加载状态"""
self.state = ReportState.load_from_file(filepath)
self.logger.info(f"状态已从 {filepath} 加载")
logger.info(f"状态已从 {filepath} 加载")
def save_state(self, filepath: str):
"""保存状态到文件"""
self.state.save_to_file(filepath)
self.logger.info(f"状态已保存到 {filepath}")
logger.info(f"状态已保存到 {filepath}")
def check_input_files(self, insight_dir: str, media_dir: str, query_dir: str, forum_log_path: str) -> Dict[str, Any]:
"""
@@ -488,9 +463,9 @@ class ReportAgent:
with open(file_paths[engine], 'r', encoding='utf-8') as f:
report_content = f.read()
content['reports'].append(report_content)
self.logger.info(f"已加载 {engine} 报告: {len(report_content)} 字符")
logger.info(f"已加载 {engine} 报告: {len(report_content)} 字符")
except Exception as e:
self.logger.error(f"加载 {engine} 报告失败: {str(e)}")
logger.exception(f"加载 {engine} 报告失败: {str(e)}")
content['reports'].append("")
# 加载论坛日志
@@ -498,9 +473,9 @@ class ReportAgent:
try:
with open(file_paths['forum'], 'r', encoding='utf-8') as f:
content['forum_logs'] = f.read()
self.logger.info(f"已加载论坛日志: {len(content['forum_logs'])} 字符")
logger.info(f"已加载论坛日志: {len(content['forum_logs'])} 字符")
except Exception as e:
self.logger.error(f"加载论坛日志失败: {str(e)}")
logger.exception(f"加载论坛日志失败: {str(e)}")
return content
@@ -515,5 +490,6 @@ def create_agent(config_file: Optional[str] = None) -> ReportAgent:
Returns:
ReportAgent实例
"""
config = load_config(config_file)
config = Settings() # 以空配置初始化,而从从环境变量初始化
return ReportAgent(config)