Files
autogen/utils/logger.py
2026-03-12 13:27:03 +08:00

193 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
日志工具模块 - 记录多智能体对话历史和系统事件
"""
import os
import json
import logging
from datetime import datetime
from typing import Dict, List, Any, Optional
from pathlib import Path
class ConversationLogger:
"""对话历史日志记录器"""
def __init__(self, log_dir: str = "logs"):
"""
初始化日志记录器
Args:
log_dir: 日志目录
"""
self.log_dir = Path(log_dir)
self.log_dir.mkdir(parents=True, exist_ok=True)
# 创建会话 ID
self.session_id = datetime.now().strftime("%Y%m%d_%H%M%S")
self.log_file = self.log_dir / f"session_{self.session_id}.jsonl"
# 配置日志
self.logger = logging.getLogger(f"autogen_sdls_{self.session_id}")
self.logger.setLevel(logging.INFO)
# 文件处理器
file_handler = logging.FileHandler(self.log_file, encoding='utf-8')
file_handler.setLevel(logging.INFO)
# 控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 格式化器
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
self.logger.addHandler(file_handler)
self.logger.addHandler(console_handler)
# 对话历史
self.conversation_history: List[Dict[str, Any]] = []
def log_message(
self,
agent_name: str,
message: str,
role: str = "assistant",
metadata: Optional[Dict] = None
):
"""
记录单条消息
Args:
agent_name: Agent 名称
message: 消息内容
role: 角色user/assistant/system
metadata: 额外元数据
"""
entry = {
"timestamp": datetime.now().isoformat(),
"session_id": self.session_id,
"agent_name": agent_name,
"role": role,
"message": message,
"metadata": metadata or {}
}
self.conversation_history.append(entry)
# 写入 JSONL 文件
with open(self.log_file, 'a', encoding='utf-8') as f:
f.write(json.dumps(entry, ensure_ascii=False) + '\n')
self.logger.info(f"[{agent_name}] {message[:100]}...")
def log_event(self, event_type: str, description: str, data: Optional[Dict] = None):
"""
记录系统事件
Args:
event_type: 事件类型
description: 事件描述
data: 相关数据
"""
entry = {
"timestamp": datetime.now().isoformat(),
"session_id": self.session_id,
"event_type": event_type,
"description": description,
"data": data or {}
}
with open(self.log_file, 'a', encoding='utf-8') as f:
f.write(json.dumps(entry, ensure_ascii=False) + '\n')
self.logger.info(f"[EVENT] {event_type}: {description}")
def get_conversation_history(self) -> List[Dict[str, Any]]:
"""获取完整的对话历史"""
return self.conversation_history
def export_to_json(self, output_path: Optional[str] = None) -> str:
"""
导出对话历史为 JSON 格式
Args:
output_path: 输出路径,默认在 logs 目录下
Returns:
导出文件的路径
"""
if output_path is None:
output_path = self.log_dir / f"conversation_{self.session_id}.json"
else:
output_path = Path(output_path)
export_data = {
"session_id": self.session_id,
"created_at": datetime.now().isoformat(),
"total_messages": len(self.conversation_history),
"conversation": self.conversation_history
}
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(export_data, f, ensure_ascii=False, indent=2)
self.logger.info(f"对话历史已导出到:{output_path}")
return str(output_path)
def export_to_markdown(self, output_path: Optional[str] = None) -> str:
"""
导出对话历史为 Markdown 格式
Args:
output_path: 输出路径
Returns:
导出文件的路径
"""
if output_path is None:
output_path = self.log_dir / f"conversation_{self.session_id}.md"
else:
output_path = Path(output_path)
with open(output_path, 'w', encoding='utf-8') as f:
f.write(f"# AutoGen SDLC 对话历史\n\n")
f.write(f"**会话 ID**: {self.session_id}\n")
f.write(f"**创建时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"**总消息数**: {len(self.conversation_history)}\n\n")
f.write("---\n\n")
for entry in self.conversation_history:
timestamp = entry["timestamp"][:19].replace('T', ' ')
agent = entry["agent_name"]
message = entry["message"]
f.write(f"### [{timestamp}] {agent}\n\n")
f.write(f"{message}\n\n")
f.write("---\n\n")
self.logger.info(f"对话历史已导出为 Markdown: {output_path}")
return str(output_path)
# 全局日志实例
_global_logger: Optional[ConversationLogger] = None
def get_logger(log_dir: str = "logs") -> ConversationLogger:
"""获取或创建全局日志记录器"""
global _global_logger
if _global_logger is None:
_global_logger = ConversationLogger(log_dir)
return _global_logger
def reset_logger():
"""重置全局日志记录器"""
global _global_logger
_global_logger = None