add /api/report-callback
This commit is contained in:
parent
8583f4c607
commit
3583a50695
15
bruno/survey/report-callback.bru
Normal file
15
bruno/survey/report-callback.bru
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
meta {
|
||||||
|
name: report-callback
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: http://120.26.23.172/api/report-callback
|
||||||
|
body: none
|
||||||
|
auth: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
settings {
|
||||||
|
encodeUrl: true
|
||||||
|
}
|
||||||
@ -176,36 +176,22 @@ class ReportGenerator:
|
|||||||
analysis_data = self.generate_analysis_text({'id': session_id})
|
analysis_data = self.generate_analysis_text({'id': session_id})
|
||||||
|
|
||||||
# 调用自定义API生成报告
|
# 调用自定义API生成报告
|
||||||
report_result = self.call_report_api(analysis_data)
|
# 构造回调URL
|
||||||
|
report_result = self.call_report_api(analysis_data, session_id)
|
||||||
|
|
||||||
if report_result:
|
if report_result and report_result.get('success'):
|
||||||
# 提取学员信息用于更新报告数据
|
# API调用成功,异步生成中
|
||||||
student_info = analysis_data['student_info']
|
# 保存分析数据用于后续回调处理
|
||||||
report_result['studentInfo']['name'] = student_info.get('name', '未知')
|
self.save_analysis_data_for_regeneration(session_id, analysis_data)
|
||||||
report_result['studentInfo']['school'] = student_info.get('school', '未知')
|
|
||||||
report_result['studentInfo']['grade'] = student_info.get('grade', '未知')
|
|
||||||
report_result['studentInfo']['subject'] = '科学'
|
|
||||||
report_result['studentInfo']['testDate'] = get_east8_time().strftime('%Y年%m月%d日')
|
|
||||||
|
|
||||||
# 构造报告数据
|
|
||||||
report_data = {
|
|
||||||
'studentInfo': report_result['studentInfo'],
|
|
||||||
'report': report_result['report'],
|
|
||||||
'generated_at': get_east8_time().isoformat(),
|
|
||||||
'session_id': session_id,
|
|
||||||
'analysis_data': analysis_data
|
|
||||||
}
|
|
||||||
|
|
||||||
# 保存报告到数据库
|
|
||||||
self.save_report_to_db(session_id, report_data, analysis_data)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'success': True,
|
'success': True,
|
||||||
'report_data': report_data,
|
'message': '报告异步生成中',
|
||||||
|
'session_id': session_id,
|
||||||
'analysis_data': analysis_data
|
'analysis_data': analysis_data
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
raise Exception("API返回空内容")
|
raise Exception("API调用失败")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"生成报告失败: {e}")
|
print(f"生成报告失败: {e}")
|
||||||
@ -218,87 +204,42 @@ class ReportGenerator:
|
|||||||
'can_regenerate': True
|
'can_regenerate': True
|
||||||
}
|
}
|
||||||
|
|
||||||
def call_report_api(self, analysis_data):
|
def call_report_api(self, analysis_data, session_id):
|
||||||
"""调用自定义报告API生成报告"""
|
"""调用自定义报告API生成报告"""
|
||||||
# 构建请求数据
|
# 构建请求数据
|
||||||
request_data = {
|
request_data = {
|
||||||
"analysis_text": analysis_data['analysis_text']
|
"analysis_text": analysis_data['analysis_text'],
|
||||||
|
"session_id": session_id
|
||||||
}
|
}
|
||||||
|
|
||||||
# 实现重试机制
|
# 实现重试机制
|
||||||
max_retries = 3
|
max_retries = 3
|
||||||
retry_delay = 2 # 秒
|
retry_delay = 2 # 秒
|
||||||
|
|
||||||
for attempt in range(max_retries):
|
|
||||||
try:
|
try:
|
||||||
print(f"调用报告生成API (尝试 {attempt + 1}/{max_retries})...")
|
print(f"调用报告生成API...")
|
||||||
print(f" API端点: {self.api_url}")
|
print(f" API端点: {self.api_url}")
|
||||||
|
print(f" Session ID: {session_id}")
|
||||||
print(f" 数据长度: {len(request_data['analysis_text'])} 字符")
|
print(f" 数据长度: {len(request_data['analysis_text'])} 字符")
|
||||||
|
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
self.api_url,
|
self.api_url,
|
||||||
headers=self.headers,
|
headers=self.headers,
|
||||||
json=request_data,
|
json=request_data,
|
||||||
timeout=self.timeout
|
timeout=10 # 简化超时时间
|
||||||
)
|
)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
result = response.json()
|
result = response.json()
|
||||||
|
print(f"✅ API调用成功,已提交异步报告生成请求")
|
||||||
# 验证响应格式
|
|
||||||
if 'studentInfo' in result and 'report' in result:
|
|
||||||
print(f"✅ API调用成功,生成报告数据")
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
print(f"⚠️ API响应格式异常,但继续处理")
|
|
||||||
print(f" 响应内容: {str(result)[:200]}...")
|
print(f" 响应内容: {str(result)[:200]}...")
|
||||||
return result
|
return {"success": True, "message": "异步报告生成请求已提交"}
|
||||||
|
|
||||||
elif response.status_code == 401:
|
|
||||||
raise Exception("API密钥无效或已过期")
|
|
||||||
|
|
||||||
elif response.status_code == 429:
|
|
||||||
# 速率限制,增加等待时间
|
|
||||||
wait_time = retry_delay * (2 ** attempt)
|
|
||||||
print(f"API速率限制,等待 {wait_time} 秒后重试...")
|
|
||||||
time.sleep(wait_time)
|
|
||||||
continue
|
|
||||||
|
|
||||||
elif response.status_code >= 500:
|
|
||||||
# 服务器错误,重试
|
|
||||||
wait_time = retry_delay * (2 ** attempt)
|
|
||||||
print(f"API服务器错误 ({response.status_code}),{wait_time} 秒后重试...")
|
|
||||||
time.sleep(wait_time)
|
|
||||||
continue
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception(f"API调用失败: HTTP {response.status_code} - {response.text}")
|
raise Exception(f"API调用失败: HTTP {response.status_code} - {response.text}")
|
||||||
|
|
||||||
except requests.exceptions.Timeout:
|
|
||||||
wait_time = retry_delay * (2 ** attempt)
|
|
||||||
print(f"API请求超时,{wait_time} 秒后重试...")
|
|
||||||
if attempt < max_retries - 1:
|
|
||||||
time.sleep(wait_time)
|
|
||||||
else:
|
|
||||||
raise Exception(f"API请求超时,已达到最大重试次数 ({self.timeout}秒)")
|
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError:
|
|
||||||
wait_time = retry_delay * (2 ** attempt)
|
|
||||||
print(f"API连接错误,{wait_time} 秒后重试...")
|
|
||||||
if attempt < max_retries - 1:
|
|
||||||
time.sleep(wait_time)
|
|
||||||
else:
|
|
||||||
raise Exception("API连接失败,已达到最大重试次数")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if attempt == max_retries - 1:
|
print(f"API调用出错: {e}")
|
||||||
raise Exception(f"API调用失败: {str(e)}")
|
raise Exception(f"报告生成API调用失败: {str(e)}")
|
||||||
else:
|
|
||||||
wait_time = retry_delay * (2 ** attempt)
|
|
||||||
print(f"API调用出错: {e},{wait_time} 秒后重试...")
|
|
||||||
time.sleep(wait_time)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def save_report_to_db(self, session_id, report_data, analysis_data):
|
def save_report_to_db(self, session_id, report_data, analysis_data):
|
||||||
"""保存报告到数据库"""
|
"""保存报告到数据库"""
|
||||||
@ -499,7 +440,7 @@ class EnhancedSurveySystem:
|
|||||||
analysis_data = json.loads(result[0])
|
analysis_data = json.loads(result[0])
|
||||||
|
|
||||||
# 调用API生成报告
|
# 调用API生成报告
|
||||||
report_result = self.report_generator.call_report_api(analysis_data)
|
report_result = self.report_generator.call_report_api(analysis_data, session_id)
|
||||||
|
|
||||||
if report_result:
|
if report_result:
|
||||||
# 提取学员信息用于更新报告数据
|
# 提取学员信息用于更新报告数据
|
||||||
|
|||||||
80
main.py
80
main.py
@ -14,7 +14,7 @@ from pydantic import BaseModel
|
|||||||
from typing import Dict, List, Optional, Any
|
from typing import Dict, List, Optional, Any
|
||||||
import asyncio
|
import asyncio
|
||||||
import threading
|
import threading
|
||||||
from enhanced_survey_system import enhanced_system, get_east8_time_string
|
from enhanced_survey_system import enhanced_system, get_east8_time_string, get_east8_time
|
||||||
|
|
||||||
app = FastAPI(title="Enhanced Survey System")
|
app = FastAPI(title="Enhanced Survey System")
|
||||||
|
|
||||||
@ -49,6 +49,10 @@ class SaveAnswersRequest(BaseModel):
|
|||||||
class GenerateReportRequest(BaseModel):
|
class GenerateReportRequest(BaseModel):
|
||||||
sessionId: str
|
sessionId: str
|
||||||
|
|
||||||
|
class ReportCallbackRequest(BaseModel):
|
||||||
|
session_id: str
|
||||||
|
data: Dict[str, Any]
|
||||||
|
|
||||||
class SessionResponse(BaseModel):
|
class SessionResponse(BaseModel):
|
||||||
success: bool
|
success: bool
|
||||||
sessionId: str
|
sessionId: str
|
||||||
@ -1030,6 +1034,80 @@ def generate_quiz_page(session_data: sqlite3.Row, session_id: str) -> str:
|
|||||||
</body>
|
</body>
|
||||||
</html>'''
|
</html>'''
|
||||||
|
|
||||||
|
@app.post("/api/report-callback", response_model=ApiResponse)
|
||||||
|
async def report_callback(request: ReportCallbackRequest):
|
||||||
|
"""接收异步报告生成完成的回调数据"""
|
||||||
|
session_id = request.session_id
|
||||||
|
report_data = request.data
|
||||||
|
|
||||||
|
if not session_id or not report_data:
|
||||||
|
raise HTTPException(status_code=400, detail="session_id和data不能为空")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 验证会话是否存在
|
||||||
|
conn = sqlite3.connect('data/survey.db')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT id FROM quiz_sessions WHERE id = ?
|
||||||
|
''', (session_id,))
|
||||||
|
|
||||||
|
session_exists = cursor.fetchone()
|
||||||
|
if not session_exists:
|
||||||
|
conn.close()
|
||||||
|
raise HTTPException(status_code=404, detail="会话不存在")
|
||||||
|
|
||||||
|
# 获取分析数据(如果有保存的话)
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT analysis_data FROM temp_analysis_data
|
||||||
|
WHERE session_id = ?
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT 1
|
||||||
|
''', (session_id,))
|
||||||
|
|
||||||
|
analysis_result = cursor.fetchone()
|
||||||
|
analysis_data = json.loads(analysis_result[0]) if analysis_result else {}
|
||||||
|
|
||||||
|
# 构造完整的报告数据
|
||||||
|
full_report_data = {
|
||||||
|
'studentInfo': report_data.get('studentInfo', {}),
|
||||||
|
'report': report_data.get('report', {}),
|
||||||
|
'generated_at': get_east8_time().isoformat(),
|
||||||
|
'session_id': session_id,
|
||||||
|
'analysis_data': analysis_data
|
||||||
|
}
|
||||||
|
|
||||||
|
# 保存报告到数据库
|
||||||
|
report_id = str(uuid.uuid4())
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT INTO reports (id, session_id, report_data, analysis_data, generated_at)
|
||||||
|
VALUES (?, ?, ?, ?, ?)
|
||||||
|
''', (report_id, session_id, json.dumps(full_report_data), json.dumps(analysis_data), get_east8_time_string()))
|
||||||
|
|
||||||
|
# 更新会话状态为已完成
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE quiz_sessions
|
||||||
|
SET status = 'completed', completed_at = ?
|
||||||
|
WHERE id = ?
|
||||||
|
''', (get_east8_time_string(), session_id))
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
print(f"✅ 回调处理成功: {session_id}")
|
||||||
|
print(f" 报告ID: {report_id}")
|
||||||
|
|
||||||
|
return ApiResponse(
|
||||||
|
success=True,
|
||||||
|
message='回调数据处理成功'
|
||||||
|
)
|
||||||
|
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 回调处理失败: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail=f"回调处理失败: {str(e)}")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import uvicorn
|
import uvicorn
|
||||||
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|
||||||
Loading…
Reference in New Issue
Block a user