deepresearch/app/utils/debug_logger.py
2025-07-02 15:35:36 +08:00

159 lines
5.6 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.

# 文件位置: 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()