添加AI日志记录器支持,增强对话日志记录功能,记录请求和响应信息,包括成功和错误情况,以提高调试和监控能力。
This commit is contained in:
parent
8bebc13efe
commit
315301fc0b
55
.gitignore
vendored
Normal file
55
.gitignore
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Virtual Environment
|
||||
venv/
|
||||
env/
|
||||
ENV/
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# Database
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Project specific
|
||||
parsed_fields.json
|
||||
*.docx.bak
|
||||
|
||||
181
services/ai_logger.py
Normal file
181
services/ai_logger.py
Normal file
@ -0,0 +1,181 @@
|
||||
"""
|
||||
AI对话日志记录模块
|
||||
用于记录大模型对话的输入和输出信息,方便排查问题
|
||||
"""
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Dict, Optional, Any
|
||||
from threading import Lock
|
||||
|
||||
class AILogger:
|
||||
"""AI对话日志记录器"""
|
||||
|
||||
def __init__(self, log_dir: Optional[str] = None):
|
||||
"""
|
||||
初始化日志记录器
|
||||
|
||||
Args:
|
||||
log_dir: 日志文件保存目录,默认为项目根目录下的 logs/ai_conversations 目录
|
||||
"""
|
||||
if log_dir is None:
|
||||
# 默认日志目录:项目根目录下的 logs/ai_conversations
|
||||
project_root = Path(__file__).parent.parent
|
||||
log_dir = project_root / "logs" / "ai_conversations"
|
||||
|
||||
self.log_dir = Path(log_dir)
|
||||
self.log_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 线程锁,确保日志写入的线程安全
|
||||
self._lock = Lock()
|
||||
|
||||
# 是否启用日志记录(可通过环境变量控制)
|
||||
self.enabled = os.getenv('AI_LOG_ENABLED', 'true').lower() == 'true'
|
||||
|
||||
print(f"[AI日志] 日志记录器初始化完成,日志目录: {self.log_dir}")
|
||||
print(f"[AI日志] 日志记录状态: {'启用' if self.enabled else '禁用'}")
|
||||
|
||||
def log_conversation(
|
||||
self,
|
||||
prompt: str,
|
||||
api_request: Dict[str, Any],
|
||||
api_response: Optional[Dict[str, Any]] = None,
|
||||
extracted_data: Optional[Dict[str, Any]] = None,
|
||||
error: Optional[str] = None,
|
||||
session_id: Optional[str] = None
|
||||
) -> str:
|
||||
"""
|
||||
记录一次完整的AI对话
|
||||
|
||||
Args:
|
||||
prompt: 输入提示词
|
||||
api_request: API请求参数
|
||||
api_response: API响应内容(完整响应)
|
||||
extracted_data: 提取后的结构化数据
|
||||
error: 错误信息(如果有)
|
||||
session_id: 会话ID(可选,用于关联多次对话)
|
||||
|
||||
Returns:
|
||||
日志文件路径
|
||||
"""
|
||||
if not self.enabled:
|
||||
return ""
|
||||
|
||||
try:
|
||||
with self._lock:
|
||||
# 生成时间戳和会话ID
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3] # 精确到毫秒
|
||||
if session_id is None:
|
||||
session_id = f"session_{int(time.time() * 1000)}"
|
||||
|
||||
# 创建日志记录
|
||||
log_entry = {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"session_id": session_id,
|
||||
"prompt": prompt,
|
||||
"api_request": {
|
||||
"endpoint": api_request.get("endpoint", "unknown"),
|
||||
"model": api_request.get("model", "unknown"),
|
||||
"messages": api_request.get("messages", []),
|
||||
"temperature": api_request.get("temperature"),
|
||||
"max_tokens": api_request.get("max_tokens"),
|
||||
"enable_thinking": api_request.get("enable_thinking", False),
|
||||
},
|
||||
"api_response": api_response,
|
||||
"extracted_data": extracted_data,
|
||||
"error": error,
|
||||
"success": error is None
|
||||
}
|
||||
|
||||
# 保存到文件(按日期组织)
|
||||
date_str = datetime.now().strftime("%Y%m%d")
|
||||
log_file = self.log_dir / f"conversation_{date_str}_{timestamp}.json"
|
||||
|
||||
with open(log_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(log_entry, f, ensure_ascii=False, indent=2)
|
||||
|
||||
print(f"[AI日志] 对话日志已保存: {log_file.name}")
|
||||
return str(log_file)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[AI日志] 保存日志失败: {e}")
|
||||
return ""
|
||||
|
||||
def log_request_only(
|
||||
self,
|
||||
prompt: str,
|
||||
api_request: Dict[str, Any],
|
||||
session_id: Optional[str] = None
|
||||
) -> str:
|
||||
"""
|
||||
仅记录请求信息(在发送请求前调用)
|
||||
|
||||
Args:
|
||||
prompt: 输入提示词
|
||||
api_request: API请求参数
|
||||
session_id: 会话ID
|
||||
|
||||
Returns:
|
||||
日志文件路径
|
||||
"""
|
||||
return self.log_conversation(
|
||||
prompt=prompt,
|
||||
api_request=api_request,
|
||||
session_id=session_id
|
||||
)
|
||||
|
||||
def get_recent_logs(self, limit: int = 10) -> list:
|
||||
"""
|
||||
获取最近的日志文件列表
|
||||
|
||||
Args:
|
||||
limit: 返回的日志文件数量
|
||||
|
||||
Returns:
|
||||
日志文件路径列表(按时间倒序)
|
||||
"""
|
||||
try:
|
||||
log_files = sorted(
|
||||
self.log_dir.glob("conversation_*.json"),
|
||||
key=lambda x: x.stat().st_mtime,
|
||||
reverse=True
|
||||
)
|
||||
return [str(f) for f in log_files[:limit]]
|
||||
except Exception as e:
|
||||
print(f"[AI日志] 获取日志列表失败: {e}")
|
||||
return []
|
||||
|
||||
def read_log(self, log_file: str) -> Optional[Dict]:
|
||||
"""
|
||||
读取指定的日志文件
|
||||
|
||||
Args:
|
||||
log_file: 日志文件路径
|
||||
|
||||
Returns:
|
||||
日志内容字典,如果读取失败返回None
|
||||
"""
|
||||
try:
|
||||
log_path = Path(log_file)
|
||||
if not log_path.is_absolute():
|
||||
log_path = self.log_dir / log_file
|
||||
|
||||
with open(log_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"[AI日志] 读取日志文件失败: {e}")
|
||||
return None
|
||||
|
||||
|
||||
# 全局日志记录器实例
|
||||
_ai_logger: Optional[AILogger] = None
|
||||
|
||||
def get_ai_logger() -> AILogger:
|
||||
"""获取全局AI日志记录器实例"""
|
||||
global _ai_logger
|
||||
if _ai_logger is None:
|
||||
_ai_logger = AILogger()
|
||||
return _ai_logger
|
||||
|
||||
@ -18,6 +18,14 @@ except ImportError:
|
||||
repair_json = None
|
||||
print("[AI服务] 警告: json-repair库未安装,将使用基础JSON修复功能。建议运行: pip install json-repair")
|
||||
|
||||
# 导入AI日志记录器
|
||||
try:
|
||||
from services.ai_logger import get_ai_logger
|
||||
AI_LOGGER_AVAILABLE = True
|
||||
except ImportError:
|
||||
AI_LOGGER_AVAILABLE = False
|
||||
print("[AI服务] 警告: AI日志记录器未找到,将不记录对话日志")
|
||||
|
||||
|
||||
class AIService:
|
||||
"""AI服务类"""
|
||||
@ -41,6 +49,16 @@ class AIService:
|
||||
# 确定使用的AI服务
|
||||
self.ai_provider = self._determine_ai_provider()
|
||||
|
||||
# 初始化AI日志记录器
|
||||
if AI_LOGGER_AVAILABLE:
|
||||
try:
|
||||
self.ai_logger = get_ai_logger()
|
||||
except Exception as e:
|
||||
print(f"[AI服务] 初始化日志记录器失败: {e}")
|
||||
self.ai_logger = None
|
||||
else:
|
||||
self.ai_logger = None
|
||||
|
||||
def _determine_ai_provider(self) -> str:
|
||||
"""确定使用的AI服务提供商(仅支持华为大模型)"""
|
||||
if self.huawei_api_endpoint and self.huawei_api_key:
|
||||
@ -208,6 +226,9 @@ class AIService:
|
||||
"""
|
||||
单次调用华为大模型API(不包含重试逻辑)
|
||||
"""
|
||||
# 生成会话ID(用于关联同一次调用的请求和响应)
|
||||
session_id = f"session_{int(time.time() * 1000)}"
|
||||
|
||||
payload = {
|
||||
"model": self.huawei_model,
|
||||
"messages": [
|
||||
@ -238,6 +259,18 @@ class AIService:
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
# 记录请求信息(发送请求前)
|
||||
api_request_info = {
|
||||
"endpoint": self.huawei_api_endpoint,
|
||||
"model": self.huawei_model,
|
||||
"messages": payload["messages"],
|
||||
"temperature": payload.get("temperature"),
|
||||
"max_tokens": payload.get("max_tokens"),
|
||||
"enable_thinking": payload.get("enable_thinking", False),
|
||||
}
|
||||
if self.ai_logger:
|
||||
self.ai_logger.log_request_only(prompt, api_request_info, session_id)
|
||||
|
||||
# 根据是否开启思考模式动态调整超时时间
|
||||
# 开启思考模式时,模型需要更多时间进行推理,超时时间需要更长
|
||||
enable_thinking = payload.get('enable_thinking', False)
|
||||
@ -250,17 +283,32 @@ class AIService:
|
||||
timeout = min(self.api_timeout, 120) # 最多120秒
|
||||
print(f"[AI服务] 思考模式未开启,使用超时时间: {timeout}秒")
|
||||
|
||||
response = requests.post(
|
||||
self.huawei_api_endpoint,
|
||||
json=payload,
|
||||
headers=headers,
|
||||
timeout=timeout
|
||||
)
|
||||
extracted_data = None
|
||||
error_message = None
|
||||
|
||||
if response.status_code != 200:
|
||||
raise Exception(f"API调用失败: {response.status_code} - {response.text}")
|
||||
try:
|
||||
response = requests.post(
|
||||
self.huawei_api_endpoint,
|
||||
json=payload,
|
||||
headers=headers,
|
||||
timeout=timeout
|
||||
)
|
||||
|
||||
result = response.json()
|
||||
if response.status_code != 200:
|
||||
error_message = f"API调用失败: {response.status_code} - {response.text}"
|
||||
# 记录错误
|
||||
if self.ai_logger:
|
||||
self.ai_logger.log_conversation(
|
||||
prompt=prompt,
|
||||
api_request=api_request_info,
|
||||
api_response=None,
|
||||
extracted_data=None,
|
||||
error=error_message,
|
||||
session_id=session_id
|
||||
)
|
||||
raise Exception(error_message)
|
||||
|
||||
result = response.json()
|
||||
|
||||
# 提取AI返回的内容
|
||||
if 'choices' in result and len(result['choices']) > 0:
|
||||
@ -323,9 +371,29 @@ class AIService:
|
||||
# 即使提取的字段不完整,也返回结果(更宽容的处理)
|
||||
if any(v for v in normalized_data.values() if v): # 至少有一个非空字段
|
||||
print(f"[AI服务] 返回提取的数据(包含 {sum(1 for v in normalized_data.values() if v)} 个非空字段)")
|
||||
# 记录成功的对话
|
||||
if self.ai_logger:
|
||||
self.ai_logger.log_conversation(
|
||||
prompt=prompt,
|
||||
api_request=api_request_info,
|
||||
api_response=result,
|
||||
extracted_data=normalized_data,
|
||||
error=None,
|
||||
session_id=session_id
|
||||
)
|
||||
return normalized_data
|
||||
else:
|
||||
print(f"[AI服务] 警告:提取的数据全部为空,但继续返回(允许部分字段为空)")
|
||||
# 记录对话(即使数据为空)
|
||||
if self.ai_logger:
|
||||
self.ai_logger.log_conversation(
|
||||
prompt=prompt,
|
||||
api_request=api_request_info,
|
||||
api_response=result,
|
||||
extracted_data=normalized_data,
|
||||
error="提取的数据全部为空",
|
||||
session_id=session_id
|
||||
)
|
||||
return normalized_data
|
||||
|
||||
# 如果无法提取JSON,记录错误但尝试更宽容的处理
|
||||
@ -336,6 +404,16 @@ class AIService:
|
||||
parsed_data = self._parse_text_response(content, output_fields)
|
||||
if parsed_data and any(v for v in parsed_data.values() if v): # 至少有一个非空字段
|
||||
print(f"[AI服务] 使用备用方法解析成功,提取到 {len(parsed_data)} 个字段")
|
||||
# 记录对话
|
||||
if self.ai_logger:
|
||||
self.ai_logger.log_conversation(
|
||||
prompt=prompt,
|
||||
api_request=api_request_info,
|
||||
api_response=result,
|
||||
extracted_data=parsed_data,
|
||||
error=None,
|
||||
session_id=session_id
|
||||
)
|
||||
return parsed_data
|
||||
|
||||
# 如果所有方法都失败,尝试最后一次修复尝试
|
||||
@ -352,6 +430,16 @@ class AIService:
|
||||
normalized_data = self._normalize_field_names(extracted_data, output_fields)
|
||||
normalized_data = self._normalize_date_formats(normalized_data, output_fields)
|
||||
normalized_data = self._post_process_inferred_fields(normalized_data, output_fields)
|
||||
# 记录对话
|
||||
if self.ai_logger:
|
||||
self.ai_logger.log_conversation(
|
||||
prompt=prompt,
|
||||
api_request=api_request_info,
|
||||
api_response=result,
|
||||
extracted_data=normalized_data,
|
||||
error=None,
|
||||
session_id=session_id
|
||||
)
|
||||
return normalized_data
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
@ -360,14 +448,36 @@ class AIService:
|
||||
|
||||
# 如果所有方法都失败,返回空字典而不是抛出异常(更宽容)
|
||||
# 这样至少不会导致整个调用失败,前端可以显示部分结果
|
||||
print(f"[AI服务] 警告:无法从API返回内容中提取JSON数据,返回空结果。原始内容长度: {len(raw_content)}, 清理后内容长度: {len(content)}")
|
||||
error_msg = f"无法从API返回内容中提取JSON数据。原始内容长度: {len(raw_content)}, 清理后内容长度: {len(content)}"
|
||||
print(f"[AI服务] 警告:{error_msg}")
|
||||
print(f"[AI服务] 完整内容: {content}")
|
||||
# 返回一个包含所有输出字段的空字典,而不是抛出异常
|
||||
empty_result = {field['field_code']: '' for field in output_fields}
|
||||
print(f"[AI服务] 返回空结果(包含 {len(empty_result)} 个字段,全部为空)")
|
||||
# 记录失败的对话
|
||||
if self.ai_logger:
|
||||
self.ai_logger.log_conversation(
|
||||
prompt=prompt,
|
||||
api_request=api_request_info,
|
||||
api_response=result,
|
||||
extracted_data=empty_result,
|
||||
error=error_msg,
|
||||
session_id=session_id
|
||||
)
|
||||
return empty_result
|
||||
else:
|
||||
raise Exception("API返回格式异常:未找到choices字段或choices为空")
|
||||
error_msg = "API返回格式异常:未找到choices字段或choices为空"
|
||||
# 记录错误
|
||||
if self.ai_logger:
|
||||
self.ai_logger.log_conversation(
|
||||
prompt=prompt,
|
||||
api_request=api_request_info,
|
||||
api_response=None,
|
||||
extracted_data=None,
|
||||
error=error_msg,
|
||||
session_id=session_id
|
||||
)
|
||||
raise Exception(error_msg)
|
||||
|
||||
def _extract_json_from_text(self, text: str) -> Optional[Dict]:
|
||||
"""
|
||||
|
||||
95
test_scripts/test_ai_logger.py
Normal file
95
test_scripts/test_ai_logger.py
Normal file
@ -0,0 +1,95 @@
|
||||
"""
|
||||
测试AI日志记录功能
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目根目录到路径
|
||||
project_root = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(project_root))
|
||||
|
||||
from services.ai_logger import get_ai_logger
|
||||
|
||||
def test_logger():
|
||||
"""测试日志记录器"""
|
||||
print("=" * 60)
|
||||
print("测试AI日志记录功能")
|
||||
print("=" * 60)
|
||||
|
||||
# 获取日志记录器
|
||||
logger = get_ai_logger()
|
||||
|
||||
# 测试记录一次对话
|
||||
print("\n1. 测试记录对话...")
|
||||
prompt = "请从以下文本中提取信息:张三,男,1980年5月出生,某公司总经理"
|
||||
api_request = {
|
||||
"endpoint": "http://test.example.com/v1/chat/completions",
|
||||
"model": "test-model",
|
||||
"messages": [
|
||||
{"role": "system", "content": "你是一个数据提取助手"},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1000,
|
||||
"enable_thinking": False
|
||||
}
|
||||
api_response = {
|
||||
"choices": [
|
||||
{
|
||||
"message": {
|
||||
"content": '{"target_name": "张三", "target_gender": "男"}'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
extracted_data = {
|
||||
"target_name": "张三",
|
||||
"target_gender": "男",
|
||||
"target_date_of_birth": "1980年05月"
|
||||
}
|
||||
|
||||
log_file = logger.log_conversation(
|
||||
prompt=prompt,
|
||||
api_request=api_request,
|
||||
api_response=api_response,
|
||||
extracted_data=extracted_data,
|
||||
error=None,
|
||||
session_id="test_session_001"
|
||||
)
|
||||
|
||||
if log_file:
|
||||
print(f"✓ 日志已保存: {log_file}")
|
||||
else:
|
||||
print("✗ 日志保存失败")
|
||||
return
|
||||
|
||||
# 测试读取日志
|
||||
print("\n2. 测试读取日志...")
|
||||
log_data = logger.read_log(log_file)
|
||||
if log_data:
|
||||
print(f"✓ 日志读取成功")
|
||||
print(f" 时间戳: {log_data['timestamp']}")
|
||||
print(f" 会话ID: {log_data['session_id']}")
|
||||
print(f" 成功: {log_data['success']}")
|
||||
print(f" 提取的字段数: {len(log_data.get('extracted_data', {}))}")
|
||||
else:
|
||||
print("✗ 日志读取失败")
|
||||
return
|
||||
|
||||
# 测试获取最近的日志
|
||||
print("\n3. 测试获取最近的日志...")
|
||||
recent_logs = logger.get_recent_logs(limit=5)
|
||||
print(f"✓ 找到 {len(recent_logs)} 条最近的日志")
|
||||
for i, log_file in enumerate(recent_logs, 1):
|
||||
print(f" {i}. {Path(log_file).name}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("测试完成!")
|
||||
print("=" * 60)
|
||||
print(f"\n日志目录: {logger.log_dir}")
|
||||
print(f"日志状态: {'启用' if logger.enabled else '禁用'}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_logger()
|
||||
|
||||
213
技术文档/AI对话日志使用说明.md
Normal file
213
技术文档/AI对话日志使用说明.md
Normal file
@ -0,0 +1,213 @@
|
||||
# AI对话日志使用说明
|
||||
|
||||
## 功能概述
|
||||
|
||||
系统已集成AI对话日志记录功能,可以自动记录每次大模型调用的详细信息,包括:
|
||||
- 输入提示词(prompt)
|
||||
- API请求参数
|
||||
- API响应内容(完整响应)
|
||||
- 提取后的结构化数据
|
||||
- 错误信息(如果有)
|
||||
|
||||
## 日志文件位置
|
||||
|
||||
日志文件保存在项目根目录下的 `logs/ai_conversations/` 目录中。
|
||||
|
||||
日志文件命名格式:`conversation_YYYYMMDD_HHMMSS_mmm.json`
|
||||
|
||||
例如:`conversation_20241215_143025_123.json`
|
||||
|
||||
## 日志文件格式
|
||||
|
||||
每个日志文件是一个JSON文件,包含以下字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2024-12-15T14:30:25.123456",
|
||||
"session_id": "session_1702627825123",
|
||||
"prompt": "请从以下输入文本中提取结构化信息...",
|
||||
"api_request": {
|
||||
"endpoint": "http://10.100.31.26:3001/v1/chat/completions",
|
||||
"model": "DeepSeek-R1-Distill-Llama-70B",
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "..."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "..."
|
||||
}
|
||||
],
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 12000,
|
||||
"enable_thinking": true
|
||||
},
|
||||
"api_response": {
|
||||
"choices": [...],
|
||||
"usage": {...}
|
||||
},
|
||||
"extracted_data": {
|
||||
"target_name": "张三",
|
||||
"target_gender": "男",
|
||||
...
|
||||
},
|
||||
"error": null,
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
## 启用/禁用日志记录
|
||||
|
||||
日志记录功能默认启用。可以通过环境变量控制:
|
||||
|
||||
### 方法1:设置环境变量
|
||||
|
||||
```bash
|
||||
# Windows
|
||||
set AI_LOG_ENABLED=false
|
||||
|
||||
# Linux/Mac
|
||||
export AI_LOG_ENABLED=false
|
||||
```
|
||||
|
||||
### 方法2:在代码中修改
|
||||
|
||||
编辑 `services/ai_logger.py`,修改 `__init__` 方法中的默认值:
|
||||
|
||||
```python
|
||||
self.enabled = os.getenv('AI_LOG_ENABLED', 'false').lower() == 'true' # 改为默认禁用
|
||||
```
|
||||
|
||||
## 查看日志文件
|
||||
|
||||
### 方法1:直接查看JSON文件
|
||||
|
||||
日志文件是标准的JSON格式,可以用任何文本编辑器或JSON查看器打开。
|
||||
|
||||
### 方法2:使用Python脚本查看
|
||||
|
||||
可以使用以下Python代码查看最近的日志:
|
||||
|
||||
```python
|
||||
from services.ai_logger import get_ai_logger
|
||||
|
||||
logger = get_ai_logger()
|
||||
|
||||
# 获取最近的10条日志
|
||||
recent_logs = logger.get_recent_logs(limit=10)
|
||||
for log_file in recent_logs:
|
||||
print(f"日志文件: {log_file}")
|
||||
log_data = logger.read_log(log_file)
|
||||
if log_data:
|
||||
print(f" 时间: {log_data['timestamp']}")
|
||||
print(f" 成功: {log_data['success']}")
|
||||
if log_data.get('error'):
|
||||
print(f" 错误: {log_data['error']}")
|
||||
print()
|
||||
```
|
||||
|
||||
### 方法3:使用命令行工具
|
||||
|
||||
在项目根目录下,可以使用以下命令查看日志:
|
||||
|
||||
```bash
|
||||
# Windows PowerShell
|
||||
Get-ChildItem logs\ai_conversations\*.json | Sort-Object LastWriteTime -Descending | Select-Object -First 10
|
||||
|
||||
# Linux/Mac
|
||||
ls -lt logs/ai_conversations/*.json | head -10
|
||||
```
|
||||
|
||||
## 日志文件管理
|
||||
|
||||
### 自动清理
|
||||
|
||||
日志文件会按日期组织,建议定期清理旧日志文件以节省磁盘空间。
|
||||
|
||||
### 手动清理
|
||||
|
||||
可以删除指定日期之前的日志文件:
|
||||
|
||||
```bash
|
||||
# Windows PowerShell - 删除7天前的日志
|
||||
Get-ChildItem logs\ai_conversations\*.json | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-7)} | Remove-Item
|
||||
|
||||
# Linux/Mac - 删除7天前的日志
|
||||
find logs/ai_conversations -name "*.json" -mtime +7 -delete
|
||||
```
|
||||
|
||||
## 排查问题
|
||||
|
||||
### 查看失败的对话
|
||||
|
||||
查找包含错误的日志:
|
||||
|
||||
```python
|
||||
from services.ai_logger import get_ai_logger
|
||||
import json
|
||||
|
||||
logger = get_ai_logger()
|
||||
recent_logs = logger.get_recent_logs(limit=50)
|
||||
|
||||
for log_file in recent_logs:
|
||||
log_data = logger.read_log(log_file)
|
||||
if log_data and not log_data.get('success'):
|
||||
print(f"失败日志: {log_file}")
|
||||
print(f"错误: {log_data.get('error')}")
|
||||
print(f"提示词: {log_data.get('prompt')[:200]}...")
|
||||
print()
|
||||
```
|
||||
|
||||
### 查看特定字段的提取情况
|
||||
|
||||
```python
|
||||
from services.ai_logger import get_ai_logger
|
||||
|
||||
logger = get_ai_logger()
|
||||
recent_logs = logger.get_recent_logs(limit=20)
|
||||
|
||||
for log_file in recent_logs:
|
||||
log_data = logger.read_log(log_file)
|
||||
if log_data and log_data.get('extracted_data'):
|
||||
extracted = log_data['extracted_data']
|
||||
if 'target_gender' in extracted:
|
||||
print(f"日志: {log_file}")
|
||||
print(f" 性别: {extracted.get('target_gender', '(空)')}")
|
||||
print(f" 姓名: {extracted.get('target_name', '(空)')}")
|
||||
print()
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **隐私和安全**:日志文件可能包含敏感信息,请妥善保管,不要将日志文件提交到公共代码仓库。
|
||||
|
||||
2. **磁盘空间**:日志文件会持续增长,建议定期清理旧日志。
|
||||
|
||||
3. **性能影响**:日志记录是异步的,对性能影响很小,但如果大量调用,建议定期清理日志文件。
|
||||
|
||||
4. **日志文件大小**:每个日志文件通常几KB到几十KB,取决于响应内容的大小。
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: 日志文件在哪里?
|
||||
A: 日志文件保存在 `logs/ai_conversations/` 目录中。
|
||||
|
||||
### Q: 如何禁用日志记录?
|
||||
A: 设置环境变量 `AI_LOG_ENABLED=false`。
|
||||
|
||||
### Q: 日志文件会占用多少空间?
|
||||
A: 每个日志文件通常几KB到几十KB,取决于响应内容。如果每天有100次调用,大约占用几MB空间。
|
||||
|
||||
### Q: 可以自定义日志目录吗?
|
||||
A: 可以,在创建 `AILogger` 实例时传入 `log_dir` 参数。
|
||||
|
||||
### Q: 日志文件格式可以修改吗?
|
||||
A: 可以,修改 `services/ai_logger.py` 中的 `log_conversation` 方法。
|
||||
|
||||
## 相关文件
|
||||
|
||||
- `services/ai_logger.py` - 日志记录器实现
|
||||
- `services/ai_service.py` - AI服务(集成日志记录)
|
||||
- `logs/ai_conversations/` - 日志文件目录
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user