大模型应用的"最后一公里":Evaluation-Driven Development 实践方法论

Demo 跑通了不等于能上线。大模型应用从实验室到生产环境之间,隔着一道被严重低估的鸿沟——评估。本文提出 Evaluation-Driven Development(EDD)方法论,从指标定义、数据集构建、CI/CD 集成到持续监控,把评估变成和写单元测试一样日常的工程实践。

Demo 很酷,上线就崩

每个做大模型应用的团队都经历过这个场景。

产品经理兴冲冲地跑来看 Demo,连说"太牛了"。老板拍板说下周上线。开发团队信心满满,觉得最难的部分已经搞定了。

然后真上了线,用户骂声一片。

回答不准确、幻觉严重、答非所问、关键信息遗漏——Demo 里没踩到的坑,生产环境里一个没落。

这不是个别现象。根据行业内的交流反馈,超过 70% 的大模型应用在首次上线后都经历了严重的效果退化。Demo 阶段的"惊艳表现"和实际上线后的"灾难现场"之间的落差,是大模型工程化领域最普遍的痛点。

问题的根源不是模型不行,而是没人认真做过评估。


传统质量保障为什么失灵

传统软件开发有成熟的质量体系——单元测试、集成测试、端到端测试。测试覆盖率达标,CI 绿灯亮了,代码就可以放心发布。

但大模型应用打破了这套体系的基本假设。

相同的输入不再产生相同的输出。 大模型是概率性的,同一个 Prompt 跑十次,可能得到七八种不同的回答。传统的 assert 断言根本写不出来。

正确性没有明确标准。 一段回答可以有多种合理表述,很难用 if-else 来判定"对"还是"错"。

行为空间无法穷举。 传统软件可以通过边界值分析来覆盖测试场景。大模型的输入空间几乎是无限的。

三个假设同时崩塌,意味着我们不能简单地把传统测试方法搬过来用。需要一套新的方法论。


Evaluation-Driven Development:让评估驱动开发

EDD(Evaluation-Driven Development,评估驱动开发)的核心思想只有一句话:先定义什么叫"好",再动手写代码。

这听起来理所当然,但绝大多数团队的做法恰恰相反。他们先写 Prompt、调参数、看效果,等到要上线了才想起来"好像应该测一下"。这时候才发现,什么指标都没有定义,什么数据都没有积累,评估根本无从下手。

EDD 把评估前置到开发流程的最前面,贯穿整个生命周期。它包含四个核心环节:

1
定义指标 → 构建数据集 → CI/CD 集成 → 持续监控

这四个环节形成一个闭环。每一轮迭代都从指标出发,用数据验证,通过自动化流水线卡住质量关口,上线后持续监控是否退化。

下面逐一展开。


第一步:定义指标——搞清楚你要优化什么

别急着写代码,先把"好"量化出来

很多团队在评估大模型应用时,用的指标只有一个:“感觉对不对”。这不是指标,这是玄学。

定义指标需要回答三个问题:

  1. 这个应用的核心任务是什么?
  2. “做得好"在任务层面意味着什么?
  3. 怎么把"做得好"转化为可计算的数字?

以一个企业知识问答系统为例。它的核心任务是"根据企业内部文档回答员工问题”。“做得好"意味着回答准确、信息完整、没有编造内容。把这些转化为指标:

指标名称 定义 计算方式 达标线
忠实度(Faithfulness) 回答中的每个事实都能在检索到的文档中找到依据 由 LLM 逐句判断是否有依据,计算有依据的句子占比 ≥ 90%
答案相关性(Answer Relevancy) 回答与用户问题的语义匹配程度 由 LLM 对回答与问题的匹配度打分(1-5) ≥ 4.0
上下文精确度(Context Precision) 检索到的文档中,真正与问题相关的比例 相关文档数 / 检索到的文档总数 ≥ 70%
上下文召回率(Context Recall) 所有相关文档中,被检索到的比例 被检索到的相关文档数 / 所有相关文档总数 ≥ 80%

指标的层次化设计

一个成熟的大模型应用不会只用一组指标。指标应该是分层次的:

系统层指标:延迟、吞吐量、Token 消耗、错误率。这些是基础设施层面的,保证系统跑得动。

模型层指标:忠实度、相关性、幻觉率、安全性。这些衡量模型输出的质量。

业务层指标:用户满意度、任务完成率、人工介入率、平均解决时长。这些衡量应用是否真正产生了价值。

三个层次的指标缺一不可。系统跑得飞快但回答全是幻觉,没用。回答很准确但延迟 10 秒,用户也跑了。一切都好但用户就是不愿意用,那更没辙。

一个常见的陷阱是:只优化你最容易测量的指标,忽略最难测量但最重要的指标。忠实度容易量化,用户满意度难量化。但后者才是决定产品生死的关键。

选错指标比不选指标更危险。知识问答系统应该关注忠实度和召回率,内容生成系统应该关注风格一致性和创造性,代码生成系统应该关注功能正确性和安全性。用错指标,你会在错误的方向上越跑越远,还以为自己做得很好。


第二步:构建评估数据集——评估的质量取决于数据的质量

数据集才是你的核心资产

很多团队把精力花在调 Prompt、选模型、优化检索策略上,对评估数据集的态度是"随便搞几百条就行”。这是一个严重的认知错误。

评估数据集的质量,直接决定了你对系统质量的判断是否可信。 数据集有偏差,你的评估结果就有偏差。数据集覆盖面不够,你以为系统很好,实际上只是没测到那些会出问题的场景。

数据集的四种来源

来源一:人工构造。 这是质量最高的数据来源。让领域专家针对业务场景设计问题和标准答案。成本高,但数据质量最有保障。建议每个核心场景至少构造 20-30 条高质量样本。

来源二:生产日志挖掘。 系统上线后,用户的真实提问是最宝贵的评估数据。从日志中筛选出有代表性的问题,人工标注答案质量。这些数据最贴近真实分布。

来源三:对抗性生成。 故意设计一些"刁钻"的测试用例。比如多跳推理问题、需要否定推理的问题、包含干扰信息的问题。这些用例专门用来探测系统的边界和弱点。

来源四:LLM 辅助生成。 用大模型来批量生成测试问题和参考答案。成本最低,但需要人工审核。适合快速扩大数据集规模。

数据集的结构设计

一个好的评估数据集不是简单的"问题-答案"对。它应该包含足够的元信息来支持多维度分析:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
- id: eval_001
  question: "公司的年假政策是什么?入职不满一年怎么算?"
  reference_answer: "根据公司HR制度2024版,正式员工年假为..."
  reference_docs:
    - doc_id: hr_policy_2024_03
    - doc_id: hr_faq_leave
  category: "HR政策"
  difficulty: "medium"
  reasoning_type: "single_hop"
  expected_behavior: "准确引用制度条款,说明入职不满一年的折算规则"
  edge_case: false
  source: "expert_crafted"

每条数据都带有分类、难度、推理类型等标签。这样在评估结果出来后,你可以按维度切分,知道系统在哪些场景下表现好,哪些场景下还有差距。

数据集的规模经验

到底需要多少条评估数据?没有一个放之四海皆准的数字。但有一些经验法则:

数据集用途 建议规模 说明
开发阶段快速验证 50-100 条 快速迭代,看大方向对不对
发布前回归测试 200-500 条 覆盖所有核心场景和边界情况
线上持续评估 每日抽样 50-100 条 监控线上效果是否退化
模型选型基准测试 500-1000 条 在多个模型之间做横向对比

数据集不是一次性的工作。它需要随着业务发展持续扩充。每一个线上发现的 bad case,都应该被回填到评估数据集中。


第三步:CI/CD 集成——让评估像单元测试一样自动化

手工评估是最大的浪费

如果每次改了一行 Prompt,都需要人肉跑一遍评估数据集,那这个评估流程注定无法持续。人是最贵的资源,评估必须自动化。

目标是:每一次代码变更(包括 Prompt 变更、模型切换、检索策略调整),都自动触发一轮评估,结果以报告形式呈现,达标才能合并。

这和传统软件的单元测试是一模一样的逻辑。改了一行代码,CI 跑一遍测试,全绿了才能合并。EDD 只是把"测试"换成了"评估"。

评估流水线的架构设计

一个典型的 EDD 评估流水线包含以下环节:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
代码变更触发
构建评估环境(加载模型、检索索引、配置参数)
运行评估数据集(批量调用,记录输入输出)
计算各项指标(忠实度、相关性、召回率等)
与基线对比(本次结果 vs 上一次发布的版本)
生成评估报告(指标卡片、对比图表、bad case 列表)
门禁判断(核心指标是否达标 / 是否出现退化)
  ├─ 达标 → 允许合并/发布
  └─ 不达标 → 阻断,通知相关人员

评估工具链选型

目前市面上有不少开源的评估框架可以用:

工具 特点 适用场景 上手难度
Ragas 专注 RAG 评估,指标体系完善 RAG 系统评估
DeepEval 类 pytest 接口,CI 友好 通用 LLM 评估
LangSmith 全链路可观测,可视化强 LangChain 生态
Promptfoo 红队测试能力强,支持多模型对比 模型选型与安全测试
自研框架 完全定制,贴合业务 特殊场景

选择工具的核心标准不是功能多不多,而是能不能顺畅地嵌入你的 CI/CD 流程。一个功能强大但跑一次要两小时的工具,不如一个轻量但 5 分钟出结果的工具实用。

评估的执行策略

不是每次变更都需要跑全量评估。可以根据变更的影响范围,设计分级策略:

轻量评估(每次提交触发):跑 50 条核心 case,只检查最关键的 2-3 个指标。耗时 5 分钟以内。目的是快速反馈,不让明显的问题溜进去。

标准评估(PR 合并前触发):跑 200-500 条数据,检查所有指标,与基线版本做对比。耗时 15-30 分钟。目的是确保这次变更不会导致效果退化。

全量评估(发布前触发):跑全部评估数据集,包括对抗性测试和边界用例。耗时可能 1-2 小时。目的是对即将发布的版本做一次全面的体检。

分级执行的关键在于平衡。评估太重,开发效率被拖累,大家会想方设法规避评估。评估太轻,问题漏过去了,等于白评。

处理评估中的不确定性

大模型评估有一个传统测试没有的难题:同一个评估用例,跑两遍可能得到不同的结果,评估分数会有波动。

处理这个问题有几个实践策略:

多次采样取均值。 每条用例跑 3 次,取指标均值作为最终分数。这能有效降低随机性带来的噪声,但成本也翻了三倍。

设置容忍区间。 不要求指标精确达标,而是设置一个容忍范围。比如忠实度的达标线是 90%,容忍区间是 ±2%。那么 88% 以上都算通过。这避免了因为随机波动导致的误拦截。

关注趋势而非单点。 单次评估的结果可能有偏差,但连续多次评估的趋势是可靠的。如果忠实度在过去 10 次评估中持续下降,即使当前还在达标线以上,也应该引起警觉。


第四步:持续监控——上线不是终点,是另一个起点

线上效果和线下评估的差异

即使 CI/CD 中的评估全部通过,线上效果仍然可能出问题。原因有很多:

  • 用户的提问方式和评估数据集中的不一样
  • 知识库更新了,但评估数据没有同步更新
  • 底层模型 API 做了静默升级,输出分布发生了变化
  • 并发量增大后,部分请求走了降级策略,效果变差

这些情况在线下评估中很难完全覆盖。所以线上监控是 EDD 闭环中不可或缺的一环。

监控什么

线上监控的核心指标和线下评估基本一致,但需要增加几个运维维度:

监控维度 具体指标 告警阈值建议
输出质量 忠实度、相关性(抽样评估) 连续 3 天均值下降超 5%
用户反馈 点赞/点踩比例、投诉量 点踩比例超过 15%
行为信号 重复提问率、人工转接率 重复提问率超过 20%
系统性能 P99 延迟、错误率、Token 用量 P99 延迟超过 5 秒
数据漂移 用户问题分布变化 新类型问题占比超过 10%

抽样评估的实施方式

线上全量评估不现实(成本太高),抽样评估是标准做法。

随机抽样:从每天的请求中随机抽取 1%-5%,进行自动评估。这是最基础的监控方式,可以发现整体质量的变化趋势。

分层抽样:按问题类型、用户等级、业务线等维度分层抽样。确保每个关键场景都有足够的监控覆盖。

异常触发抽样:对于用户点踩的、重复提问的、触发了降级策略的请求,优先纳入评估。这些是最可能出问题的请求。

抽样评估的结果需要和线下评估结果做关联分析。如果线上忠实度持续低于线下评估结果,说明评估数据集的分布和真实用户的分布存在偏差,需要更新数据集。

建立反馈闭环

监控的价值不在于发现问题,而在于推动问题的修复。一个有效的反馈闭环应该包含:

  1. 自动告警:指标异常时,自动通知到相关负责人
  2. Bad case 归档:将线上发现的问题自动归档到 bad case 库
  3. 根因分析:对 bad case 进行分类分析,定位是检索问题、生成问题还是知识库问题
  4. 数据集更新:将修复后的 bad case 回填到评估数据集,防止同类问题再次出现
  5. 回归验证:修复后跑一轮评估,确认问题已解决且没有引入新问题

这个闭环跑通了,评估数据集会越来越完善,系统质量会越来越高。这才是 EDD 的真正威力所在。


EDD 的组织落地:不只是技术问题

评估应该谁来负责

很多团队把评估工作扔给算法工程师。这是一个组织层面的错误。

EDD 是一个跨职能的工作。算法工程师负责评估框架和指标计算。领域专家负责构造评估数据和定义达标标准。产品经理负责定义业务层指标和用户体验标准。QA 工程师负责评估流程的自动化和持续运行。

每个角色都有自己的职责。缺少任何一个,评估体系都不完整。

评估的投入产出

“评估太花时间了"是最常见的反对理由。确实,构建和维护一套评估体系需要持续投入。但不评估的代价更大。

算一笔账:一个没有评估的大模型应用上线后,客服团队每天花 2 小时处理用户投诉,产品经理每天花 1 小时分析 bad case,算法工程师每天花 3 小时在线上排查问题。一天就是 6 个小时的人力浪费。

而建立一套基本的评估体系,初始投入大概 2-3 人周。之后每周的维护成本不超过半天。这笔账怎么算都划算。

从小做起,逐步完善

不要试图一步到位。EDD 的落地可以从最小可行评估开始:

第一阶段(1-2 周):人工构造 50 条核心评估数据,用现成工具跑一轮评估,了解系统当前的基线水平。

第二阶段(2-4 周):把评估脚本接入 CI,每次 Prompt 变更自动触发轻量评估。建立基本的门禁机制。

第三阶段(1-2 月):扩充数据集到 200+ 条,覆盖更多场景。接入线上日志,开始抽样监控。

第四阶段(持续):不断丰富数据集,优化指标体系,完善反馈闭环。让评估成为团队的日常习惯。


EDD 不是要替代 TDD

一个成熟的大模型应用,应该是 TDD + EDD 的混合体。确定性部分用 TDD,概率性部分用 EDD。两套体系并行运作,共同保障整体质量。


几个容易踩的坑

坑一:把评估指标当成优化目标。 当忠实度成为 KPI,团队就会开始"刷分”——在 Prompt 里加一句"如果不确定就说不知道",忠实度指标好看了,但系统的实用性大打折扣。指标是用来监控的,不是用来优化的。真正的优化目标应该是用户体验和业务价值。

坑二:评估数据集长期不更新。 业务在变,知识库在变,用户的问题也在变。半年前的评估数据集,今天可能已经严重过时。建议每季度至少做一次数据集审计,淘汰过时的用例,补充新的场景。

坑三:只评估"正常"场景。 大多数团队构造的评估数据集,覆盖的都是"正常提问-正常回答"的场景。但真正出问题的是边界情况:用户提了一个知识库里没有的问题、用户的提问有歧义、用户连续追问了十轮。这些边界场景才是评估的重点。

坑四:评估结果不透明。 评估报告只给算法工程师看,产品经理和业务方看不到。这导致评估变成了技术团队的自嗨,无法与业务目标对齐。评估结果应该对所有人可见,用所有人都能理解的方式呈现。

坑五:追求完美评估而迟迟不行动。 “我们的评估体系还不够完善,等完善了再开始评估。“这是拖延症的另一种表现形式。一个粗糙的评估方案,也比没有评估方案强一百倍。先做起来,再做好。


评估工具链实践示例

为了让 EDD 更具体,下面给出一个简化的实践示例。假设我们用 Python + DeepEval 来为一个 RAG 系统搭建评估流水线。

评估数据集的格式(YAML):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
eval_cases:
  - question: "公司出差报销的上限是多少?"
    reference: "根据公司财务制度,国内出差住宿上限为500元/晚..."
    contexts:
      - "财务报销制度_v3.pdf#page=12"
    metadata:
      category: "财务制度"
      difficulty: "easy"

  - question: "如果项目延期超过两周,需要走什么审批流程?"
    reference: "项目延期超过两周需提交延期说明报告,经部门总监审批后..."
    contexts:
      - "项目管理办法_2024.pdf#page=7"
      - "审批流程手册.pdf#page=23"
    metadata:
      category: "项目管理"
      difficulty: "medium"

评估脚本的核心逻辑:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from deepeval import evaluate
from deepeval.metrics import FaithfulnessMetric, AnswerRelevancyMetric
from deepeval.test_case import LLMTestCase

def build_test_cases(dataset_path):
    """加载评估数据集,构建测试用例"""
    cases = load_yaml(dataset_path)
    return [
        LLMTestCase(
            input=c["question"],
            actual_output=rag_pipeline.answer(c["question"]),
            expected_output=c["reference"],
            retrieval_context=fetch_contexts(c["contexts"])
        )
        for c in cases["eval_cases"]
    ]

def run_evaluation(test_cases, thresholds):
    """运行评估,返回各项指标"""
    faithfulness = FaithfulnessMetric(threshold=thresholds["faithfulness"])
    relevancy = AnswerRelevancyMetric(threshold=thresholds["relevancy"])

    results = evaluate(test_cases, [faithfulness, relevancy])
    return results

def check_gate(results, baseline):
    """门禁检查:与基线对比,判断是否允许发布"""
    for metric in results:
        if metric.score < baseline[metric.name] * 0.95:
            return False, f"{metric.name} 退化超过 5%"
    return True, "所有指标在容忍范围内"

这套代码不复杂,但它把 EDD 的核心流程都串起来了:加载数据集 → 执行评估 → 门禁检查 → 生成报告。任何一次 Prompt 变更或模型切换,都会自动触发这个流程。


让评估成为习惯,而不是负担

EDD 的终极目标,不是建立一套复杂的评估系统,而是让评估成为团队的一种本能反应。

就像资深开发者写完代码会下意识地写单元测试一样,做大模型应用的人应该在改完 Prompt 之后,下意识地想:“这次改动会让忠实度下降吗?让相关性变差吗?我需要跑一轮评估看看。”

当这种意识成为团队文化的一部分,EDD 就不再是一个需要推行的方法论,而是融入日常工作的一种工程习惯。

大模型应用的"最后一公里"不是技术问题。它是工程纪律问题。是愿不愿意在"看起来很酷"和"真正可靠"之间,多走一步、多做一步验证的问题。

能走好这一步的团队,才能真正把大模型从实验室搬到生产环境,从 Demo 变成产品,从话题变成价值。

本博客文章采用 CC BY-NC-SA 4.0 许可协议
服务器推荐

腾讯云 · 新用户专属优惠

本博客部署在腾讯云服务器,稳定运行一年多。如果你是新用户或想搭建个人项目,推荐试试腾讯云的优惠活动。

查看优惠详情 →
阅读
上一篇
Java 21+ 的 Pattern Matching:如何用密封类和记录类重构业务规则引擎
广告

📚 关注公众号,免费获取技术材料

扫码关注公众号,回复「资料」领取:

  • 📘 企业架构设计模板
  • 📗 数据治理实施指南
  • 📙 工业软件技术白皮书
公众号二维码

长按或扫描二维码