Appearance
课 2 · LLM-as-a-judge
本课目标
用 LLM 自动评估答案质量,实现 Faithfulness、Answer Relevance、Context Precision 三个核心指标。
关键理解:LLM-as-a-judge 不是让 LLM 猜答案对不对,而是给它明确的评分标准和结构化输出格式。
为什么需要答案质量评测
检索指标只能说"找到了正确文档",但找到了文档不代表答案就好:
- 找到了相关文档,但答案从其他地方瞎编了(低 Faithfulness)
- 文档相关,答案也忠实,但没回答用户真正的问题(低 Answer Relevance)
- 检索到了 5 个文档,但真正有用的只有 1 个(低 Context Precision)
这三个指标是 RAGAS 框架提出的,业界广泛使用。
Faithfulness(忠实度)
定义:答案中的每个声明都能在检索到的文档中找到依据。
typescript
// packages/eval-core/src/answer-eval.ts
import { generateObject } from 'ai'
import { z } from 'zod'
const faithfulnessSchema = z.object({
statements: z.array(
z.object({
statement: z.string(),
supported: z.boolean(),
evidence: z.string().optional(),
})
),
score: z.number().min(0).max(1),
})
export async function evaluateFaithfulness(
answer: string,
contexts: string[],
) {
const { object } = await generateObject({
model: getModel(),
schema: faithfulnessSchema,
prompt: `
你是一个答案忠实度评估助手。判断答案中每个声明是否有文档支撑。
参考文档:
${contexts.join('\n\n---\n\n')}
答案:
${answer}
对答案中每个独立声明判断:它是否可以从参考文档中直接推断出来?
计算 score = 有文档支撑的声明数 / 总声明数。
`.trim(),
})
return {
score: object.score,
statements: object.statements,
}
}Answer Relevance(答案相关性)
定义:答案是否真正回答了用户的问题。
typescript
const relevanceSchema = z.object({
score: z.number().min(0).max(1),
reason: z.string(),
isAnswered: z.boolean(),
})
export async function evaluateAnswerRelevance(
question: string,
answer: string,
) {
const { object } = await generateObject({
model: getModel(),
schema: relevanceSchema,
prompt: `
评估以下答案是否真正回答了问题。
问题:${question}
答案:${answer}
打分标准:
1.0 = 完整、直接地回答了问题
0.5 = 部分回答,或回答了但不够直接
0.0 = 没有回答问题,或答非所问
`.trim(),
})
return object
}Context Precision(上下文精度)
定义:检索到的文档中,真正有用的比例。
typescript
const contextPrecisionSchema = z.object({
relevanceScores: z.array(
z.object({
contextIndex: z.number(),
isRelevant: z.boolean(),
reason: z.string(),
})
),
score: z.number().min(0).max(1),
})
export async function evaluateContextPrecision(
question: string,
contexts: string[],
) {
const { object } = await generateObject({
model: getModel(),
schema: contextPrecisionSchema,
prompt: `
判断以下每个检索到的文档片段对于回答问题是否真正有帮助。
问题:${question}
${contexts.map((ctx, i) => `文档片段 ${i + 1}:\n${ctx}`).join('\n\n---\n\n')}
对每个片段判断是否真正有助于回答问题(而不只是主题相关)。
计算 score = 相关片段数 / 总片段数。
`.trim(),
})
return object
}批量评测
typescript
// packages/eval-core/src/batch-eval.ts
export interface AnswerEvalResult {
questionId: string
question: string
faithfulness: number
answerRelevance: number
contextPrecision: number
}
export async function batchEvalAnswers(
cases: Array<{
id: string
question: string
answer: string
contexts: string[]
}>,
): Promise<AnswerEvalResult[]> {
const results: AnswerEvalResult[] = []
for (const c of cases) {
const [faithfulness, relevance, precision] = await Promise.all([
evaluateFaithfulness(c.answer, c.contexts),
evaluateAnswerRelevance(c.question, c.answer),
evaluateContextPrecision(c.question, c.contexts),
])
results.push({
questionId: c.id,
question: c.question,
faithfulness: faithfulness.score,
answerRelevance: relevance.score,
contextPrecision: precision.score,
})
}
return results
}评测报告
typescript
// scripts/run-answer-eval.ts
const results = await batchEvalAnswers(testCases)
const avg = (arr: number[]) => arr.reduce((a, b) => a + b, 0) / arr.length
console.log('=== 答案质量评测 ===')
console.log(`Faithfulness: ${(avg(results.map(r => r.faithfulness)) * 100).toFixed(1)}%`)
console.log(`Answer Relevance: ${(avg(results.map(r => r.answerRelevance)) * 100).toFixed(1)}%`)
console.log(`Context Precision: ${(avg(results.map(r => r.contextPrecision)) * 100).toFixed(1)}%`)
// 写入报告文件
const report = { timestamp: new Date().toISOString(), metrics: {...}, details: results }
writeFileSync('datasets/eval/report.json', JSON.stringify(report, null, 2))本节产物
packages/eval-core/src/
answer-eval.ts # Faithfulness / Answer Relevance / Context Precision
batch-eval.ts # 批量评测
scripts/
run-answer-eval.ts
datasets/eval/
report.json # 评测报告面试追问
LLM-as-a-judge 本身会不会产生幻觉导致评分不准?
会。LLM 评判结果有偏差,不能完全信任。实践中的缓解方式:1)用强力模型(GPT-4o、Claude 3.5)当裁判,比被评测的模型能力更强;2)给明确的评分标准,用结构化输出避免模棱两可;3)对关键判断加 double-check(正反两问比较);4)抽样人工复核,校准自动评分准确率。
问答机器人准确率如何保证?
分两层:检索准确率(Recall@K、Hit Rate)和答案准确率(Faithfulness、Answer Relevance)。提升路径:先看 Bad Case 属于哪层问题(是没找到文档,还是找到了但回答错了),针对性改进检索策略或 prompt,用评测集量化改进效果,建立回归测试防止退化。