第 07 章
翻译质量评估
基于通义千问的五维质量评分(准确性 / 流畅性 / 一致性 / 完整性)、改进建议自动本地化、启发式降级评估与结果持久化。
7.1 评估机制总览
- 请求解析与语言检测
sourceLanguage为空或auto时,服务端先调用语言检测接口自动识别并回填;检测失败不中断,继续按auto评估。 - 调用大模型评估
将源文、译文、语言对组装为提示词,调用 DashScope(通义千问,引擎标识
QWEN)要求其仅返回 JSON:五个 0–100 整数分值 + 三组文字建议 + 评估详情。HTTP 超时:连接 10 秒 / 响应 120 秒。 - 解析与兜底
模型返回的各分值钳制到
[0, 100];overallScore缺失时按权重合成:准确×0.4 + 流畅×0.3 + 一致×0.2 + 完整×0.1。建议类字段为空时自动补默认建议(总分 < 85 时补维度建议)。 - 建议本地化
improvementSuggestions始终翻译为简体中文返回;attentionPoints与strengths仅当目标语言为中文(zh开头)时本地化。单条翻译失败保留原文,不影响整体返回。 - 可选持久化
save=true且提供translationRecordId时,评估结果落库(quality_assessment表,模式 AUTOMATIC);落库失败仅记日志,不影响响应。
质量等级(qualityLevel 映射规则)
overallScore ≥ 90 → "优秀" overallScore ≥ 80 → "良好" overallScore ≥ 70 → "中等" overallScore ≥ 60 → "及格" overallScore < 60 → "需要改进"
7.2 接口总览(前缀 /api/quality)
POST/api/quality/assess评估翻译质量(五维评分 + 建议)
💰 本接口不消耗点数、不校验会员额度(评估过程中的内部翻译调用不经过计费链路)。
7.3 请求字段(QualityAssessmentRequest)
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
sourceText | String | 必填 | — | 源文本(@NotBlank) |
targetText | String | 必填 | — | 待评估的译文(@NotBlank) |
sourceLanguage | String | 可选 | — | 源语言代码;为空或 auto 时自动检测,检测结果回填至响应 detectedSourceLanguage |
targetLanguage | String | 必填 | — | 目标语言代码(@NotBlank),同时决定建议文字的输出语言策略 |
mode | String | 可选 | AUTOMATIC | 评估模式;当前仅支持自动评估 |
translationRecordId | Long | 可选 | — | 关联的翻译记录 ID,save=true 时必填 |
save | boolean | 可选 | false | 是否将评估结果持久化到数据库 |
dimensions | List<String> | 可选 | — | 期望的评估维度列表;当前版本未参与实际评估,评估固定覆盖四维(准确性 / 流畅性 / 一致性 / 完整性),保留字段供扩展 |
⚠️ 未配置 DashScope API Key(ai.dashscope.api-key)时,评估入口直接抛 IllegalStateException → HTTP 409 ILLEGAL_STATE,提示「DashScope API Key 未配置」。
7.4 响应字段(QualityAssessmentResponse)
| 字段 | 类型 | 说明 |
|---|---|---|
overallScore | Integer | 综合得分(0–100);模型未返回时按四维加权合成 |
accuracyScore | Integer | 准确性得分 |
fluencyScore | Integer | 流畅性得分 |
consistencyScore | Integer | 一致性得分 |
completenessScore | Integer | 完整性得分 |
improvementSuggestions | List<String> | 改进建议(始终为简体中文) |
attentionPoints | List<String> | 注意事项(目标语言为中文时本地化) |
strengths | List<String> | 译文优点(目标语言为中文时本地化) |
assessmentDetails | Map | 模型返回的评估详情(自由结构,透传) |
assessmentTime | Long | 本次评估耗时(毫秒) |
assessmentEngine | String | 评估引擎,固定 QWEN |
qualityLevel | String | 质量等级:优秀 / 良好 / 中等 / 及格 / 需要改进 |
detectedSourceLanguage | String | 自动检测到的源语言(未触发检测时为 null) |
响应示例
{
"overallScore": 86, "accuracyScore": 88, "fluencyScore": 85,
"consistencyScore": 84, "completenessScore": 87,
"improvementSuggestions": ["统一「人工智能 / AI」等术语译法,保持全文一致"],
"attentionPoints": ["长句建议拆分后重译,可读性更佳"],
"strengths": ["整体语义传达准确,无明显漏译"],
"assessmentDetails": { },
"assessmentTime": 4200,
"assessmentEngine": "QWEN",
"qualityLevel": "良好",
"detectedSourceLanguage": "zh"
}
7.5 降级与异常行为
启发式降级评估(DashScope 调用失败时自动启用)
基础分:准确 78 / 流畅 76 / 一致 75 / 完整 74 // 长度比例修正(lengthRatio = 译文长度 / 源文长度): lengthRatio < 0.6 → completenessScore = max(60, 74 - 10) // 疑似漏译 lengthRatio > 1.4 → accuracyScore = max(60, 78 - 8) // 疑似过度翻译 assessmentDetails.note = "heuristic-evaluation" // 标记降级
降级评估同样返回完整五维分值与建议,assessmentDetails 中以 note=heuristic-evaluation 标记,
集成方可据此提示用户「本次为启发式评估结果」。
异常场景汇总
| 场景 | HTTP | 行为 |
|---|---|---|
| sourceText / targetText / targetLanguage 为空 | 400 | VALIDATION_ERROR,data 中含字段级错误信息 |
| DashScope API Key 未配置 | 409 | ILLEGAL_STATE,提示配置 ai.dashscope.api-key |
| 大模型调用 4xx / 5xx / 超时 | 200 | 自动降级为启发式评估,正常返回评分 |
| 建议本地化翻译失败 | 200 | 该条建议保留原文,不影响整体评估 |
| 评估结果落库失败 | 200 | 仅记录错误日志,响应不受影响 |
7.6 调用示例
# 基础评估(源语言自动检测) curl -X POST http://localhost:8090/api/quality/assess \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"sourceText":"人工智能正在改变世界。","targetText":"AI is changing the world.","targetLanguage":"en"}' # 关联翻译记录并保存评估结果 curl -X POST http://localhost:8090/api/quality/assess \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"sourceText":"人工智能正在改变世界。","targetText":"AI is changing the world.","sourceLanguage":"zh","targetLanguage":"en","translationRecordId":1001,"save":true}'
async function assessQuality(token, sourceText, targetText, targetLanguage) { const resp = await fetch('/api/quality/assess', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ sourceText, targetText, targetLanguage }) }).then(r => r.json()); if (!resp.success) throw new Error(resp.message); const { overallScore, qualityLevel, improvementSuggestions } = resp.data; console.log(`得分 ${overallScore}(${qualityLevel})`); improvementSuggestions.forEach(s => console.log('· ' + s)); return resp.data; }