222 lines
8.9 KiB
Python
222 lines
8.9 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
完整错误信息诊断脚本
|
||
运行工作流并捕获完整的错误信息
|
||
"""
|
||
|
||
import sys
|
||
import os
|
||
import json
|
||
import traceback
|
||
from datetime import datetime
|
||
|
||
# 添加项目路径
|
||
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
sys.path.insert(0, project_root)
|
||
sys.path.insert(0, os.path.join(project_root, 'src'))
|
||
|
||
from langgraph.runtime import Runtime
|
||
from coze_coding_utils.runtime_ctx.context import Context, new_context
|
||
|
||
|
||
def run_test_with_full_error_capture():
|
||
"""运行测试并捕获完整错误信息"""
|
||
|
||
# 准备测试数据
|
||
test_data = {
|
||
"student_homework": [
|
||
{
|
||
"student_id": 1,
|
||
"student_name": "张三呀",
|
||
"homework_images": [
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/18/69baa4f5-4826-4901-00e1-c6e66f02947f.jpg?x-oss-process=image/resize,w_1000",
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/25/69c344ba-4826-4901-00e1-c6ff235a12b2.jpg?x-oss-process=image/resize,w_1000",
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/25/69c344ba-4826-4901-00e1-c7055a396422.jpg?x-oss-process=image/resize,w_1000",
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/25/69c344ba-4826-4901-00e1-c6fe7f9c07ef.jpg?x-oss-process=image/resize,w_1000"
|
||
]
|
||
},
|
||
{
|
||
"student_id": 2,
|
||
"student_name": "李四呀",
|
||
"homework_images": [
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/25/69c344ba-4826-4901-00e1-c70052d895e3.jpg?x-oss-process=image/resize,w_1000",
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/25/69c344ba-4826-4901-00e1-c6fc6ca7c4bf.png?x-oss-process=image/resize,w_1000",
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/25/69c33f31-4826-4901-00e1-c6fb50697e06.png?x-oss-process=image/resize,w_1000",
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/23/69c1029b-4826-4901-00e1-c6f614bc06d9.jpg?x-oss-process=image/resize,w_1000",
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/25/69c344ba-4826-4901-00e1-c6fd479e0a0e.jpg?x-oss-process=image/resize,w_1000",
|
||
"https://dpcclass.oss-cn-beijing.aliyuncs.com/umsupload/2026/03/23/69c1029b-4826-4901-00e1-c6f569b31a14.jpeg?x-oss-process=image/resize,w_1000"
|
||
]
|
||
}
|
||
],
|
||
"answer_doc_url": "https://dpc-oss.23544.com/umsupload/2026/03/25/69c353d0-4826-4901-00e1-c7081bcab988.docx",
|
||
"comment_max_length": 50,
|
||
"max_concurrent": 5,
|
||
"grade_standards": {}
|
||
}
|
||
|
||
print("=" * 80)
|
||
print("开始运行完整错误诊断测试")
|
||
print("=" * 80)
|
||
print(f"测试数据: {len(test_data['student_homework'])} 个学生")
|
||
total_images = sum(len(s['homework_images']) for s in test_data['student_homework'])
|
||
print(f"总图片数: {total_images}")
|
||
print(f"答案文档: {test_data['answer_doc_url'][:50]}...")
|
||
print("=" * 80)
|
||
print()
|
||
|
||
# 初始化上下文
|
||
ctx = new_context(method="run")
|
||
|
||
try:
|
||
# 导入主图
|
||
from graphs.graph import main_graph
|
||
|
||
print("✓ 成功导入主图")
|
||
print()
|
||
|
||
# 运行测试
|
||
print("开始运行工作流...")
|
||
print("-" * 80)
|
||
|
||
result = main_graph.invoke(test_data, config={"recursion_limit": 100})
|
||
|
||
print("-" * 80)
|
||
print()
|
||
print("=" * 80)
|
||
print("✓ 测试成功!")
|
||
print("=" * 80)
|
||
print()
|
||
|
||
# 输出结果摘要
|
||
if "student_results" in result:
|
||
for student_result in result["student_results"]:
|
||
# StudentResult 是 Pydantic 对象,使用属性访问而不是 .get()
|
||
student_name = getattr(student_result, "student_name", "未知")
|
||
total_images = getattr(student_result, "total_images", 0)
|
||
total_score = getattr(student_result, "total_score", 0)
|
||
full_score = getattr(student_result, "full_score", 0)
|
||
grade = getattr(student_result, "grade", "N/A")
|
||
|
||
print(f"学生: {student_name}")
|
||
print(f" 图片数: {total_images}")
|
||
print(f" 得分: {total_score}/{full_score}")
|
||
print(f" 等级: {grade}")
|
||
print()
|
||
|
||
# 保存完整结果到文件(先转换为 dict)
|
||
result_dict = result.model_dump() if hasattr(result, 'model_dump') else result
|
||
result_file = f"/tmp/diagnostic_result_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
||
with open(result_file, 'w', encoding='utf-8') as f:
|
||
json.dump(result_dict, f, ensure_ascii=False, indent=2)
|
||
print(f"完整结果已保存到: {result_file}")
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print("-" * 80)
|
||
print()
|
||
print("=" * 80)
|
||
print("✗ 测试失败!")
|
||
print("=" * 80)
|
||
print()
|
||
print("错误类型:", type(e).__name__)
|
||
print("错误消息:", str(e))
|
||
print()
|
||
print("完整堆栈跟踪:")
|
||
print("-" * 80)
|
||
traceback.print_exc()
|
||
print("-" * 80)
|
||
print()
|
||
|
||
# 保存错误信息到文件
|
||
error_file = f"/tmp/diagnostic_error_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
|
||
with open(error_file, 'w', encoding='utf-8') as f:
|
||
f.write(f"错误类型: {type(e).__name__}\n")
|
||
f.write(f"错误消息: {str(e)}\n")
|
||
f.write("\n完整堆栈跟踪:\n")
|
||
f.write("=" * 80 + "\n")
|
||
traceback.print_exc(file=f)
|
||
|
||
print(f"错误信息已保存到: {error_file}")
|
||
print()
|
||
|
||
# 分析错误类型
|
||
print("错误分析:")
|
||
print("-" * 80)
|
||
|
||
error_str = str(e).lower()
|
||
|
||
if "404" in error_str or "not found" in error_str:
|
||
print("⚠️ 404 错误:资源不存在")
|
||
print(" 可能原因:")
|
||
print(" 1. URL 已过期(签名 URL 有时效性)")
|
||
print(" 2. 文件已被删除或移动")
|
||
print(" 3. URL 拼写错误")
|
||
elif "403" in error_str or "forbidden" in error_str:
|
||
print("⚠️ 403 错误:禁止访问")
|
||
print(" 可能原因:")
|
||
print(" 1. 访问权限不足")
|
||
print(" 2. 需要 IP 白名单")
|
||
print(" 3. 需要认证")
|
||
elif "401" in error_str or "unauthorized" in error_str:
|
||
print("⚠️ 401 错误:未授权")
|
||
print(" 可能原因:")
|
||
print(" 1. API 密钥无效")
|
||
print(" 2. 认证失败")
|
||
print(" 3. Token 过期")
|
||
elif "timeout" in error_str:
|
||
print("⚠️ 超时错误")
|
||
print(" 可能原因:")
|
||
print(" 1. 网络连接慢")
|
||
print(" 2. 服务器响应慢")
|
||
print(" 3. 图片或文档太大")
|
||
elif "connection" in error_str or "network" in error_str:
|
||
print("⚠️ 网络连接错误")
|
||
print(" 可能原因:")
|
||
print(" 1. 无法连接到外部网络")
|
||
print(" 2. DNS 解析失败")
|
||
print(" 3. 防火墙阻止")
|
||
elif "html" in error_str:
|
||
print("⚠️ HTML 错误页面")
|
||
print(" 可能原因:")
|
||
print(" 1. URL 返回了 404/403/500 错误页面")
|
||
print(" 2. 网络重定向失败")
|
||
print(" 3. CDN 或代理返回错误")
|
||
elif "json" in error_str:
|
||
print("⚠️ JSON 解析错误")
|
||
print(" 可能原因:")
|
||
print(" 1. LLM 返回的不是有效的 JSON")
|
||
print(" 2. JSON 格式错误")
|
||
print(" 3. 缺少必需字段")
|
||
elif "llm" in error_str or "model" in error_str:
|
||
print("⚠️ LLM 调用错误")
|
||
print(" 可能原因:")
|
||
print(" 1. LLM 服务不可用")
|
||
print(" 2. 模型配置错误")
|
||
print(" 3. API 配额不足")
|
||
else:
|
||
print("⚠️ 未知错误类型")
|
||
print(" 请查看上面的错误详情和堆栈跟踪")
|
||
|
||
print()
|
||
return False
|
||
|
||
|
||
if __name__ == "__main__":
|
||
print()
|
||
print("=" * 80)
|
||
print("初中数学作业批改工作流 - 完整错误诊断")
|
||
print("=" * 80)
|
||
print()
|
||
|
||
success = run_test_with_full_error_capture()
|
||
|
||
print()
|
||
print("=" * 80)
|
||
if success:
|
||
print("诊断完成:工作流运行正常")
|
||
sys.exit(0)
|
||
else:
|
||
print("诊断完成:发现错误,请查看上面的错误详情")
|
||
sys.exit(1)
|