fix(流程图): 老提交重新评分后四项明细全显示「0 / 0」
Deploy / deploy (push) Canceled after 0s

老办法(四项打总分)的 prompt 只写了 "criteria_details":{},模型换成 deepseek-flash
之后直接给 {"逻辑正确性": 32} 这样的裸数字,详情页读不到 score / max。prompt 里把
四项的形状写全,存之前按 { score, max, comment } 收好(缺满分按 40/30/20/10 补);
0036 把线上已经存进去的 4 条改回来。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-19 21:11:35 +08:00
1 parent d8e0efd05e
commit 67b13a9345
4 files changed
+3898 -2

No files matched your search

@@ -0,0 +1,32 @@
-- 流程图老办法(四项打总分)的明细,模型有时给成 {"逻辑正确性": 32, ...} 这样的裸数字,
-- 提交详情读不到 score / max,四项全显示「0 / 0」。2026-10-19 重新评分老提交时线上撞上 4 条
-- (模型换成 deepseek-flash 之后)。裸数字改成 { score, max, comment },满分按 40 / 30 / 20 / 10;
-- 本来就是对象的项原样不动。新评的由 flowchart/run.ts 的 normalizeCriteria 收好再存。
UPDATE "flowchart_submission" AS target
SET "ai_criteria_details" = fixed.details
FROM (
SELECT f."id",
jsonb_object_agg(
e.key,
CASE
WHEN jsonb_typeof(e.value) = 'number' THEN jsonb_build_object(
'score', e.value,
'max', CASE e.key
WHEN '逻辑正确性' THEN 40
WHEN '完整性' THEN 30
WHEN '规范性' THEN 20
WHEN '清晰度' THEN 10
ELSE 100
END,
'comment', ''
)
ELSE e.value
END
) AS details
FROM "flowchart_submission" f, jsonb_each(f."ai_criteria_details") e
WHERE NOT f."ai_criteria_details" ? 'version'
AND jsonb_typeof(f."ai_criteria_details") = 'object'
GROUP BY f."id"
HAVING bool_or(jsonb_typeof(e.value) = 'number')
) AS fixed
WHERE target."id" = fixed."id";
File diff suppressed because it is too large. Load diff
+7
View File
@@ -253,6 +253,13 @@
"when": 1792130722120, "when": 1792130722120,
"tag": "0035_recount_solved_metrics", "tag": "0035_recount_solved_metrics",
"breakpoints": true "breakpoints": true
},
{
"idx": 36,
"version": "7",
"when": 1792415463343,
"tag": "0036_fix_flowchart_criteria_numbers",
"breakpoints": true
} }
] ]
} }
+27 -2
View File
@@ -163,11 +163,36 @@ function evaluationPrompt(problem: Problem) {
return `你是专业的编程教学助手,负责评估学生的 Mermaid 流程图。 return `你是专业的编程教学助手,负责评估学生的 Mermaid 流程图。
评分:逻辑正确性40分、完整性30分、规范性20分、清晰度10分。 评分:逻辑正确性40分、完整性30分、规范性20分、清晰度10分。
不要评价系统生成的节点ID。feedback不超过100字;suggestions最多3条且只针对真实问题。 不要评价系统生成的节点ID。feedback不超过100字;suggestions最多3条且只针对真实问题。
返回纯 JSON:{"score":85,"grade":"A","feedback":"...","suggestions":"...","criteria_details":{}}。 返回纯 JSON:{"score":85,"grade":"A","feedback":"...","suggestions":"...","criteria_details":{"逻辑正确性":{"score":34,"max":40,"comment":"..."},"完整性":{"score":26,"max":30,"comment":"..."},"规范性":{"score":17,"max":20,"comment":"..."},"清晰度":{"score":8,"max":10,"comment":"..."}}}。
等级:S=90-100,A=80-89,B=70-79,C=0-69。 等级:S=90-100,A=80-89,B=70-79,C=0-69。
题目:${problem.title}\n${problem.description.slice(0, 2000)}` 题目:${problem.title}\n${problem.description.slice(0, 2000)}`
} }
const CRITERIA_MAX: Record<string, number> = { 逻辑正确性: 40, 完整性: 30, 规范性: 20, 清晰度: 10 }
/**
* 四项明细收成 `{ 项名: { score, max, comment } }`,提交详情和统计都按这个形状读。
* 原来 prompt 里只写了 `"criteria_details":{}`,模型有时直接给 `"逻辑正确性": 34`,
* 存进去页面上四项全是「0 / 0」(2026-10 重新评分老提交时撞上的)。缺 max 的按满分表补
*/
function normalizeCriteria(raw: unknown) {
return Object.fromEntries(
Object.entries(asRecord(raw)).map(([key, value]) => {
const item = asRecord(value)
const score = typeof value === "number" ? value : Number(item.score)
const max = Number(item.max)
return [
key,
{
score: Number.isFinite(score) ? score : 0,
max: Number.isFinite(max) && max > 0 ? max : (CRITERIA_MAX[key] ?? 100),
comment: typeof item.comment === "string" ? item.comment : "",
},
]
}),
)
}
function parseEvaluation(value: string): Evaluation { function parseEvaluation(value: string): Evaluation {
const block = value.match(/```(?:json)?\s*([\s\S]*?)```/)?.[1] const block = value.match(/```(?:json)?\s*([\s\S]*?)```/)?.[1]
const json = block ?? value.match(/\{[\s\S]*\}/)?.[0] const json = block ?? value.match(/\{[\s\S]*\}/)?.[0]
@@ -181,7 +206,7 @@ function parseEvaluation(value: string): Evaluation {
grade: gradeForScore(score), grade: gradeForScore(score),
feedback: typeof data.feedback === "string" ? data.feedback : "", feedback: typeof data.feedback === "string" ? data.feedback : "",
suggestions: typeof data.suggestions === "string" ? data.suggestions : "", suggestions: typeof data.suggestions === "string" ? data.suggestions : "",
criteria: asRecord(data.criteria_details), criteria: normalizeCriteria(data.criteria_details),
} }
} }