# 文件位置: app/utils/debug_logger.py # 文件名: debug_logger.py """ AI调试日志记录器 记录所有AI模型的输入输出,用于调试和优化 """ import os import json import logging from datetime import datetime from typing import Dict, Any, Optional, List from config import Config logger = logging.getLogger(__name__) class AIDebugLogger: """AI调试日志记录器""" def __init__(self): self.debug_dir = os.path.join(Config.DATA_DIR, 'debug') os.makedirs(self.debug_dir, exist_ok=True) self.current_session_id = None self.socketio = None def set_socketio(self, socketio): """设置socketio实例用于实时推送""" self.socketio = socketio def set_session(self, session_id: str): """设置当前会话ID""" self.current_session_id = session_id # 创建会话专属的调试目录 session_debug_dir = os.path.join(self.debug_dir, session_id) os.makedirs(session_debug_dir, exist_ok=True) def log_api_call(self, model: str, agent_type: str, method: str, prompt: str, response: str, temperature: float = None, max_tokens: int = None, metadata: Dict[str, Any] = None): """记录API调用""" timestamp = datetime.now() # 构建日志条目 - 保存完整内容 log_entry = { "timestamp": timestamp.isoformat(), "session_id": self.current_session_id, "model": model, "agent_type": agent_type, # "R1" or "V3" "method": method, "temperature": temperature, "max_tokens": max_tokens, "prompt_length": len(prompt), "response_length": len(response), "prompt": prompt, # 完整保存 "response": response, # 完整保存 "metadata": metadata or {} } # 保存到文件 if self.current_session_id: self._save_to_file(log_entry) # 通过WebSocket推送(如果可用) if self.socketio and self.current_session_id: self._emit_debug_log(log_entry) # 记录到标准日志(摘要) logger.debug(f"AI Call - {agent_type}/{method}: " f"prompt={len(prompt)}chars, response={len(response)}chars") def log_json_parse_error(self, raw_text: str, error: str, fixed_text: Optional[str] = None): """记录JSON解析错误""" log_entry = { "timestamp": datetime.now().isoformat(), "session_id": self.current_session_id, "type": "json_parse_error", "raw_text": raw_text, "error": error, "fixed_text": fixed_text, "fixed": fixed_text is not None } if self.current_session_id: self._save_error_log(log_entry) if self.socketio and self.current_session_id: self.socketio.emit('parse_error', { 'session_id': self.current_session_id, **log_entry }, room=self.current_session_id) def _save_to_file(self, log_entry: Dict[str, Any]): """保存到文件""" if not self.current_session_id: return # 保存到会话专属文件 session_log_file = os.path.join( self.debug_dir, self.current_session_id, f"api_calls_{datetime.now().strftime('%Y%m%d')}.jsonl" ) with open(session_log_file, 'a', encoding='utf-8') as f: f.write(json.dumps(log_entry, ensure_ascii=False) + '\n') def _save_error_log(self, log_entry: Dict[str, Any]): """保存错误日志""" if not self.current_session_id: return error_log_file = os.path.join( self.debug_dir, self.current_session_id, "errors.jsonl" ) with open(error_log_file, 'a', encoding='utf-8') as f: f.write(json.dumps(log_entry, ensure_ascii=False) + '\n') def _emit_debug_log(self, log_entry: Dict[str, Any]): """通过WebSocket发送调试日志""" # 发送完整内容,不截断 self.socketio.emit('ai_debug_log', { 'session_id': self.current_session_id, 'log_entry': log_entry # 完整发送 }, room=self.current_session_id) def get_session_logs(self, session_id: str, log_type: str = 'all') -> List[Dict[str, Any]]: """获取会话的日志""" logs = [] session_debug_dir = os.path.join(self.debug_dir, session_id) if not os.path.exists(session_debug_dir): return logs # 根据类型读取不同的日志文件 if log_type in ['all', 'api_calls']: api_files = [f for f in os.listdir(session_debug_dir) if f.startswith('api_calls_')] for file_name in api_files: file_path = os.path.join(session_debug_dir, file_name) with open(file_path, 'r', encoding='utf-8') as f: for line in f: logs.append(json.loads(line)) if log_type in ['all', 'errors']: error_file = os.path.join(session_debug_dir, 'errors.jsonl') if os.path.exists(error_file): with open(error_file, 'r', encoding='utf-8') as f: for line in f: logs.append(json.loads(line)) # 按时间戳排序 logs.sort(key=lambda x: x.get('timestamp', '')) return logs # 全局调试日志实例 ai_debug_logger = AIDebugLogger()