Compare commits
4 Commits
8f2bd92ee0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7202a6244 | ||
|
|
c6f64de4cc | ||
|
|
724e3e1073 | ||
|
|
b02f249166 |
@@ -41,6 +41,7 @@ UPLOAD_DIR=uploads
|
|||||||
COZE_OAUTH_CLIENT_ID=1114009328887
|
COZE_OAUTH_CLIENT_ID=1114009328887
|
||||||
COZE_OAUTH_PUBLIC_KEY_ID=GGs9pw0BDHx2k9vGGehUyRgKV-PyUWLBncDs-YNNN_I
|
COZE_OAUTH_PUBLIC_KEY_ID=GGs9pw0BDHx2k9vGGehUyRgKV-PyUWLBncDs-YNNN_I
|
||||||
COZE_OAUTH_PRIVATE_KEY_PATH=/app/secrets/coze_private_key.pem
|
COZE_OAUTH_PRIVATE_KEY_PATH=/app/secrets/coze_private_key.pem
|
||||||
|
COZE_WORKSPACE_ID=7461992708538974244
|
||||||
COZE_PRACTICE_BOT_ID=7602204855037591602
|
COZE_PRACTICE_BOT_ID=7602204855037591602
|
||||||
|
|
||||||
# Dify 工作流 API Key 配置
|
# Dify 工作流 API Key 配置
|
||||||
|
|||||||
@@ -734,14 +734,27 @@ async def end_practice_session(
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# 将 ORM 对象转换为响应格式,避免 DetachedInstanceError
|
||||||
|
session_data = PracticeSessionResponse(
|
||||||
|
id=session.id,
|
||||||
|
session_id=session.session_id,
|
||||||
|
user_id=session.user_id,
|
||||||
|
scene_id=session.scene_id,
|
||||||
|
scene_name=session.scene_name or "",
|
||||||
|
scene_type=session.scene_type,
|
||||||
|
conversation_id=session.conversation_id,
|
||||||
|
start_time=session.start_time,
|
||||||
|
end_time=session.end_time,
|
||||||
|
duration_seconds=session.duration_seconds or 0,
|
||||||
|
turns=session.turns or 0,
|
||||||
|
status=session.status,
|
||||||
|
created_at=session.created_at
|
||||||
|
)
|
||||||
|
|
||||||
return ResponseModel(
|
return ResponseModel(
|
||||||
code=200,
|
code=200,
|
||||||
message="会话已结束",
|
message="会话已结束",
|
||||||
data={
|
data=session_data
|
||||||
"session": session,
|
|
||||||
"exp_result": exp_result,
|
|
||||||
"new_badges": new_badges
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
@@ -815,19 +828,35 @@ async def analyze_practice_session(
|
|||||||
# 解析分析结果
|
# 解析分析结果
|
||||||
analysis_result = analysis_data.get("analysis", {})
|
analysis_result = analysis_data.get("analysis", {})
|
||||||
|
|
||||||
# 保存分析报告
|
# 检查报告是否已存在
|
||||||
report = PracticeReport(
|
existing_report = await db.execute(
|
||||||
session_id=session_id,
|
select(PracticeReport).where(PracticeReport.session_id == session_id)
|
||||||
total_score=analysis_result.get("total_score"),
|
|
||||||
score_breakdown=analysis_result.get("score_breakdown"),
|
|
||||||
ability_dimensions=analysis_result.get("ability_dimensions"),
|
|
||||||
dialogue_review=analysis_result.get("dialogue_annotations"),
|
|
||||||
suggestions=analysis_result.get("suggestions"),
|
|
||||||
workflow_run_id=f"{v2_result.ai_provider}_{v2_result.ai_latency_ms}ms",
|
|
||||||
task_id=None
|
|
||||||
)
|
)
|
||||||
|
report = existing_report.scalar_one_or_none()
|
||||||
|
|
||||||
|
if report:
|
||||||
|
# 更新现有报告
|
||||||
|
report.total_score = analysis_result.get("total_score")
|
||||||
|
report.score_breakdown = analysis_result.get("score_breakdown")
|
||||||
|
report.ability_dimensions = analysis_result.get("ability_dimensions")
|
||||||
|
report.dialogue_review = analysis_result.get("dialogue_annotations")
|
||||||
|
report.suggestions = analysis_result.get("suggestions")
|
||||||
|
report.workflow_run_id = f"{v2_result.ai_provider}_{v2_result.ai_latency_ms}ms"
|
||||||
|
logger.info(f"更新现有分析报告: session_id={session_id}")
|
||||||
|
else:
|
||||||
|
# 创建新报告
|
||||||
|
report = PracticeReport(
|
||||||
|
session_id=session_id,
|
||||||
|
total_score=analysis_result.get("total_score"),
|
||||||
|
score_breakdown=analysis_result.get("score_breakdown"),
|
||||||
|
ability_dimensions=analysis_result.get("ability_dimensions"),
|
||||||
|
dialogue_review=analysis_result.get("dialogue_annotations"),
|
||||||
|
suggestions=analysis_result.get("suggestions"),
|
||||||
|
workflow_run_id=f"{v2_result.ai_provider}_{v2_result.ai_latency_ms}ms",
|
||||||
|
task_id=None
|
||||||
|
)
|
||||||
|
db.add(report)
|
||||||
|
|
||||||
db.add(report)
|
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
logger.info(f"分析报告已保存: session_id={session_id}, total_score={report.total_score}")
|
logger.info(f"分析报告已保存: session_id={session_id}, total_score={report.total_score}")
|
||||||
@@ -883,7 +912,53 @@ async def get_practice_report(
|
|||||||
report = result.scalar_one_or_none()
|
report = result.scalar_one_or_none()
|
||||||
|
|
||||||
if not report:
|
if not report:
|
||||||
raise HTTPException(status_code=404, detail="分析报告不存在,请先生成报告")
|
# 报告不存在,自动生成
|
||||||
|
logger.info(f"报告不存在,自动生成: session_id={session_id}")
|
||||||
|
|
||||||
|
# 查询对话历史
|
||||||
|
result = await db.execute(
|
||||||
|
select(PracticeDialogue).where(
|
||||||
|
PracticeDialogue.session_id == session_id
|
||||||
|
).order_by(PracticeDialogue.sequence)
|
||||||
|
)
|
||||||
|
dialogue_list = result.scalars().all()
|
||||||
|
|
||||||
|
if not dialogue_list:
|
||||||
|
raise HTTPException(status_code=404, detail="没有对话记录,无法生成报告")
|
||||||
|
|
||||||
|
# 构建对话历史
|
||||||
|
dialogue_history = [
|
||||||
|
{"role": "user" if d.speaker == "user" else "assistant", "content": d.content}
|
||||||
|
for d in dialogue_list
|
||||||
|
]
|
||||||
|
|
||||||
|
# 调用分析服务
|
||||||
|
from app.services.ai.practice_analysis_service import PracticeAnalysisService
|
||||||
|
import json
|
||||||
|
|
||||||
|
practice_analysis_service = PracticeAnalysisService()
|
||||||
|
analysis_result = await practice_analysis_service.analyze(dialogue_history, db=db)
|
||||||
|
|
||||||
|
if not analysis_result.success:
|
||||||
|
raise HTTPException(status_code=500, detail=f"分析失败: {analysis_result.error}")
|
||||||
|
|
||||||
|
analysis_data = analysis_result.to_dict()
|
||||||
|
|
||||||
|
# 保存报告
|
||||||
|
report = PracticeReport(
|
||||||
|
session_id=session_id,
|
||||||
|
total_score=analysis_data.get("overall_score", 0),
|
||||||
|
score_breakdown=analysis_data.get("score_breakdown", []),
|
||||||
|
ability_dimensions=analysis_data.get("ability_dimensions", []),
|
||||||
|
dialogue_review=analysis_data.get("dialogue_review", []),
|
||||||
|
suggestions=analysis_data.get("suggestions", []),
|
||||||
|
summary=analysis_data.get("summary", ""),
|
||||||
|
raw_response=json.dumps(analysis_data, ensure_ascii=False)
|
||||||
|
)
|
||||||
|
db.add(report)
|
||||||
|
await db.commit()
|
||||||
|
await db.refresh(report)
|
||||||
|
logger.info(f"报告自动生成成功: session_id={session_id}, 总分={report.total_score}")
|
||||||
|
|
||||||
# 3. 查询完整对话记录(从数据库)
|
# 3. 查询完整对话记录(从数据库)
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
|
|||||||
@@ -309,6 +309,7 @@ class MistakeService:
|
|||||||
ExamMistake.question_type,
|
ExamMistake.question_type,
|
||||||
ExamMistake.knowledge_point_id,
|
ExamMistake.knowledge_point_id,
|
||||||
KnowledgePoint.name.label("knowledge_point_name"),
|
KnowledgePoint.name.label("knowledge_point_name"),
|
||||||
|
ExamMistake.mastery_status,
|
||||||
ExamMistake.created_at
|
ExamMistake.created_at
|
||||||
).select_from(ExamMistake).join(
|
).select_from(ExamMistake).join(
|
||||||
Exam, ExamMistake.exam_id == Exam.id
|
Exam, ExamMistake.exam_id == Exam.id
|
||||||
@@ -339,6 +340,7 @@ class MistakeService:
|
|||||||
"question_type": row.question_type,
|
"question_type": row.question_type,
|
||||||
"knowledge_point_id": row.knowledge_point_id,
|
"knowledge_point_id": row.knowledge_point_id,
|
||||||
"knowledge_point_name": row.knowledge_point_name,
|
"knowledge_point_name": row.knowledge_point_name,
|
||||||
|
"mastery_status": row.mastery_status,
|
||||||
"created_at": row.created_at
|
"created_at": row.created_at
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -583,7 +583,7 @@ const loadMistakes = async () => {
|
|||||||
id: item.id,
|
id: item.id,
|
||||||
type: item.question_type || 'single',
|
type: item.question_type || 'single',
|
||||||
difficulty: 'medium', // 暂无此字段
|
difficulty: 'medium', // 暂无此字段
|
||||||
masteryStatus: 'unmastered', // 暂无此字段
|
masteryStatus: item.mastery_status || 'unmastered',
|
||||||
title: item.question_content,
|
title: item.question_content,
|
||||||
yourAnswer: item.user_answer,
|
yourAnswer: item.user_answer,
|
||||||
correctAnswer: item.correct_answer,
|
correctAnswer: item.correct_answer,
|
||||||
|
|||||||
Reference in New Issue
Block a user