Hard-Earned Lessons from 2 Years of Improving AI Applications

两年改进AI应用的艰辛经验教训

标签
评估
AI
发布日期
2025年5月7日
作者
Shahul
 

引言

你的AI应用上线了,用户正在与之互动。响应并没有出错,但也不算优秀。用户反馈模糊,满意度评分平平,每一次新的提示词调整或模型替换都像是在黑暗中摸索。你尝试不同的工作流程,追查边缘情况,却仍然无法判断是否真的有所改进。最终,你停止了跟踪,开始凭感觉行事,然后照样发布。
 
不必如此。读完本文,你将获得一份清晰的指南,系统地利用评估(evals)来改进你的AI应用从设置到强大、自动化的评估循环,它们将超越用户的期望。这些见解源自我们在各种企业和数十家早期创业公司改进大型语言模型(LLM)应用的经验,以及构建Ragas本身的经验教训。
 

太长不看

改进AI应用不是艺术,而是科学。设定明确的指标,构建真实的测试集,收集人类反馈,并利用自动化的LLM评估进行扩展。本指南将带你了解完整的评估循环,从测试数据集创建到错误分析和整合用户反馈,让你停止猜测,开始系统地改进你的AI。
 

什么是评估?

评估衡量你的AI系统实现其预期目标的有效程度。
AI应用中的评估常与AI可观测性(observability)或安全护栏(guardrails)等相关概念混淆。评估是专门用于量化系统相对于明确目标的性能的。
评估有三个关键步骤:
  1. 构建一个真实的测试集:收集或生成你系统预期的输入。
  1. 清晰地定义成功:精确地指定什么才算是一个“好的”结果,以及为什么它是好的。
  1. 选择精确的指标:衡量每一个结果(通过/失败、得分、排名)。
 
另一个常见的误解是关于评估(evaluations)和基准测试(benchmarks)的。
评估与基准测试一样吗?不,它们不一样。LLM基准测试侧重于根据学术指标,在公开数据集上评估不同的模型。在大多数情况下,评估这些模型所用的数据或指标与你的系统、数据或任务没有任何关系。这也是为什么公开的基准测试或数据集无法帮助你评估和改进你的系统。
 

为什么AI工程师应该花时间在这上面?

科学实验/评估是系统地改进你的AI应用的唯一可靠方法。你可能想知道,为什么不直接大致检查一下响应然后快速部署更改呢?
以下是为什么评估优于“感觉良好检查”(vibe checks)的原因:
  • 可扩展性(Scale):你无法手动检查数百个边缘情况。现实世界的输入是杂乱的,模型会以随机检查无法发现的微妙方式失败。
  • 客观性(Objectivity):你的“直觉”可能与队友的不同。评估将主观印象转化为一致的、可重复的指标。
  • 沟通(Communication):说“感觉好多了”并不能帮助团队达成一致。评估提供具体数字:“新的提示词将任务完成率从50%提高到了70%。”
评估不仅仅是好的实践,它更是必不可少的基础设施。
 

从何开始?

 
notion image
对于基于LLM的系统,迭代速度快,但衡量影响速度慢。与传统机器学习工作流程(训练和数据准备占用了大部分时间)不同,AI应用开发通常归结为更改提示词、工具或路由逻辑。这些更改只需几分钟即可实现,但评估其影响需要更多时间来衡量,因为通常需要人工检查一组样本响应并对其进行评分/感觉评估。
 
事实上,我们发现评估在一个团队的迭代循环中占用了约30%的时间,尤其是在需要跨许多边缘情况测试提示词调整或检索更改时。我们并非孤军奋战:GitHub Copilot、Casetext和Notion等团队也撰文讨论了评估在其工作流程中日益重要的作用。[3]
那么,从何开始呢?
首先决定评估什么
  • 端到端评估(End-to-end evaluation):类似于集成测试或端到端测试。它们告诉你,当整个流程整合在一起时,是否真正提供了用户关心的结果。
  • 组件级评估(Component-wise evaluation):类似于单元测试。它们帮助你调试管道中的特定部分,例如检索器或重排序器,以确保每个部分都能独立工作。
端到端开始。这是用户所见的。一旦你对输出有信心,再深入评估那些最重要且不太可能被替换的组件或单元。
 

数据集构建

如果你已经读到这里,说明你是认真正改进你的AI系统的。第一步:构建一个好的测试数据集。
  • 上线前
还没有用户?没问题。从编写10-30个真实的输入开始,这些输入应代表你在生产环境中预期的内容。你的目标是意图多样性,而不是数量。
合成数据在此非常有用,一旦你有了初始输入集,就可以使用合成数据生成流程对其进行外推和生成更多变体。需要记住的原则细节将在下面描述。
  • 上线后
已经有用户了?太好了。抽取30-50个真实的系统输入样本。手动审查它们——查找质量、多样性和边缘情况。你的目标是一组代表你在生产环境中看到的各种场景的输入。
尽管这是一个好的开始,但它可能无法代表足够多样化的系统输入。这里有一个你可以用来改进测试数据的最简单技术之一:
  • 从生产环境中抽取x%的系统输入样本。理想情况下,抽取1000个或更多样本。
  • 基于系统输入去重
  • 使用嵌入模型对这些系统输入进行嵌入。
  • 使用KNN或DBSCAN对嵌入进行聚类。
  • 从每个聚类中抽取一个或多个样本。检查它们,并添加到你的测试数据中。
在这两种情况下,都从小处开始,使其真实,并根据需要逐步扩展。你不想做的是陷入“书呆子式钻牛角尖”——在进行第一次评估之前就陷入设计完美测试集的泥潭。
 

生成高质量合成测试数据的技术

如果你缺乏真实输入或想生成现有输入的变体,LLM可以提供帮助。
通过对几个关键变量进行条件化,使用LLM生成高质量的合成数据。这些变量对于不同的应用可能不同,这里的原则是找到可以对LLM进行条件化的变量,以便生成足够多样化的输入。
以下是一个常见的AI聊天机器人应用的例子:
  • 角色(Persona):谁在提问?(例如,“一位研究癌症治疗的初级研究员”)
  • 主题(Topic):关于什么?(例如,“基因组学与个性化医疗”)
  • 查询复杂度(Query complexity):短 vs 长,模糊 vs 具体
提示词结构 + 示例 + 少量真实查询 → 优秀的合成数据。
使用LLM进行外推,使用人工进行验证。永远不要跳过审查。
你可以通过从向量数据库(vector DB)检索过去的真实查询,并在生成提示词中将其用作示例,进一步提升质量。
 
# Define some representative personas personas = [ "A PhD student early in their research journey, seeking help with literature reviews and forming hypotheses.", "An experienced academic looking for synthesis across papers and advanced insights.", "A specialist doctor (e.g. oncologist) using the assistant for rare case support and new treatment options." ] # Define query complexities and topics query_complexities = [ "long_form_summary", "comparative_analysis", "query_with_ambiguity" ] topics = [ "cancer_treatment", "clinical_trials", "genomics_and_personalized_medicine" ] # Prompt template to generate synthetic test queries prompt_template = """ You are helping build a test dataset for a healthcare AI assistant. Generate a user query based on: - Persona: {persona} - Query Complexity: {complexity} - Topic: {topic} Instructions: - Write a **realistic query** this persona might ask. - Reflect the specified complexity and keep it grounded in the topic. - Output only the query. No explanations or metadata. """ # Example usage (you would loop through combinations in practice) print(prompt_template.format( persona=personas[0], complexity=query_complexities[1], topic=topics[2] ))
 
我们曾使用电子表格或CSV文件来组织和维护这些数据集,但逐渐转向了Notion数据库,它提供了更好的用户体验(UX)和用于从代码读写数据集的API。
 

人工审查与标注

这是许多团队容易出错的地方。
他们低估了人工审查的关键性——同时高估了设置它的所需工作量。明确地说:如果你的目标是使你的AI系统与人类期望一致,你必须首先清晰地定义这些期望。LLMs无法读取你的思想。如果你不向它们展示“好”和“坏”是什么样的,它们可能永远也学不会。
 
步骤 1:定义要衡量什么
问自己:对于你的用例来说,一个好的响应关注哪些方面?
为每个输入-响应对选择1-3个维度。常见例子:
  • 对于RAG系统:关注响应的正确性和引用准确性。
  • 对于编程代理(SWE agent):关注语法正确性、运行时成功以及代码风格。
 
步骤 2:选择指标类型
对于每个维度,选择一个既易于应用又具有可操作性的指标。通常有三种类型:
  1. 二元(通过/失败):当可接受和不可接受之间有明确界限时使用。示例:代理完成了任务吗?是或否。
  1. 数值(例如 0-1):当部分得分有意义且你能清晰定义分数的含义时使用。示例:引用准确度为0.5 = 一半引用是错误的。
  1. 排名:当输出具有主观性且比较比绝对判断更容易时使用。示例:摘要A优于摘要B。
 
无论使用哪种指标,务必同时收集理由。
没有理由的“失败”是没有帮助的。添加上下文,如“响应捏造了事实”“遗漏了关键点”。这些理由将成为你后续的LLM评审(LLM-as-judge)的重要训练数据。
 
提示:自定义UI,使标注/人工审查更顺畅
查看数据可能很繁琐,但通过这个简单的技巧,你可以使其不那么繁琐,效率更高。最好的方法是针对具体用例定制数据查看器。
你的数据查看器应该
  • 根据你的用例量身定制(RAG、摘要、代理等)
  • 标注速度快
  • 结构化程度高,能够一致地存储数据和反馈
 
a simple annotation UI for a RAG use-case
一个用于RAG用例的简单标注界面
我们使用基于Claude Sonnet构建的轻量级网页UI——它在快速生成自定义界面方面出奇地好用。一旦构建好,当你需要领域专家进行新的标注时,就可以复用这个UI。
 

利用LLM作为评审进行扩展

一旦你构建了一个包含人工标注的坚实测试集,下一个挑战就是扩展你的评估工作。每次更改提示词、检索器或重排序器时,手动重新标注所有内容都会非常痛苦。这使得人工审查成为瓶颈——并减慢了迭代速度。
这就是LLM评审的作用所在。
目标很简单:用自动化评估取代重复的人工审查,由LLM驱动,这些LLM被提示模仿你的领域专家行为。理想情况下,你的LLM评审应该与你的专家标签一致至少80%的时间
 
 An llm as judge with 66.6% agreement
一个LLM评审达到66.6%一致性
步骤 1:设置
你已经定义了要衡量什么(例如,正确性、引用准确性)。现在,编写提示词,指示LLM根据这些维度对响应进行评分或分类。
 
步骤 2:与人工判断对齐
在已标注的测试集上运行你的LLM评审。将其输出与专家标签进行比较。迭代改进提示词质量和少样本示例,直到你持续看到高一致性。
实践中效果最好的方法
  • 使用高质量示例进行少样本提示(few-shot prompting)
  • 基于检索的提示(retrieval-based prompting):从数据集中获取类似的已审查样本,并将其提供给评审
  • 包含你在标注时写的文字反馈——这有助于评审更好地进行推理
 
通过强大的反馈循环,你的LLM评审会随着时间推移而改进。你可以使用相关性分析方法,如斯皮尔曼秩相关系数(Spearman’s rank correlation)或Cohen’s kappa系数,来衡量LLM评审输出与人工评估者评分之间的一致性。
def judge_response(input, response): # Embed the input + response to find similar, labeled examples embedding = embedding_model.embed(f"{input} - {response}") examples = get_similar(embedding, labeled_index) # Construct a few-shot prompt prompt = f""" Check if the response is relevant to the input. Output: Pass or Fail. ### Examples {examples} ### Input {input} ### Response {response} """ return llm.generate(prompt)
如果你愿意,也可以尝试类似Dspy的优化或微调评估模型。话虽如此,在大多数情况下,这并非必需。手动精心制作的示例 + 基于检索的提示通常就足够了。
如果你有一个良好的系统来审查LLM评审的结果,随着时间推移,你的LLM评审将变得越来越好——越来越接近人工判断——而无需持续的人工监督。
 

错误分析

评估告诉你你的系统在哪里失败。错误分析帮助你理解为什么失败以及接下来该做什么。
评估 = 衡量
错误分析 = 诊断
假设你的测试集显示30%的样本失败了。怎么办?
在你修复任何问题之前,你需要可视化(visibility)。这意味着检查输入、中间输出以及组件日志数据、检索器、重排序器、LLM调用、代码逻辑、外部工具等。
这就是可观测性工具(observability tools)发挥作用的地方。你可以使用现有的可观测性技术栈,如SentryDatadog,或采用专门的LLM可观测性工具[5]来跟踪和记录所有你需要的信息.
 
错误分析主要包括两个步骤:
  • 步骤 1:错误假设
手动检查每个表现不佳样本的日志,然后问自己:这里出了什么问题?用简单的语言写下一行假设。
  • 步骤 2:错误分类
将这些假设分组到不同的类别,以便你可以优先处理和修复它们。你可以手动完成,或者提示LLM为你进行聚类。
 
error_hypothesis = [ "document was not retrieved", "document had paywall", "retrieved doc had a paywall", "doc not retrieved", "paywall in document" ] prompt = f""" Given the following error hypotheses, generate a set of error categories. Then classify each hypothesis under one of these categories. {error_hypothesis} """ # Expected output: { "retrieval_issues": ["document was not retrieved", "doc not retrieved"], "paywall_issues": ["document had paywall", "retrieved doc had a paywall", "paywall in document"] }
 
 
notion image
 
现在,按频率对你的类别进行排序。首先解决最常见的问题。这为你提供了调试和迭代的清晰路线图。
 
error categories ordered by number of occurrences
按出现次数排序的错误类别
既然你已经确定了故障点,是时候进行实验了——做出更改,运行评估,并衡量什么能真正改进你的流程。这就是接下来我们要讨论的内容。
 

实验

既然你已经识别出了导致系统表现不佳的错误模式,你可能会有很多改进它的想法。这就是实验发挥作用的地方。
什么是实验?
一个实验是对你的AI系统进行的结构化更改,旨在观察其对一个或多个评估指标的影响。
一个好的实验是这样的:
  • 更改:调整管道中的单个组件(例如,提示词调整、替换检索器、添加重排序器)。
  • 评估:使用现有的测试数据运行,并记录新的响应和指标。
  • 比较:将其与基线进行基准测试。手动审查和比较更改。
  • 决定:如果指标和响应有显著改进,就部署它或尝试不同的解决方案。
 
假设你有五个改进系统的想法。尝试每一个,记录结果,进行评估和比较。这个过程消除了迭代中的猜测,让你有信心发布最好的版本。
 
但这是否就结束了呢?如果你已经在生产环境中部署了AI应用,你肯定会知道,无论你如何努力,每周都会在生产环境中出现新的边缘情况,影响客户体验。这引出了我们下一节的内容。
 

机器学习反馈循环

你已经进行了实验,发布了改进,并部署了你的AI系统。循环到此结束了吗?还没完全结束。
AI问题具有长尾特性(long-tailed)。真正的挑战不在于前80%,而在于最后的20%。
在生产环境中,新的边缘情况会定期出现。这是因为你的系统现在遇到了各种各样罕见的、不可预测的场景。而最好的AI系统是那些能够从中快速学习的系统。
想象一个只处理常见问题解答(FAQs)的客户支持机器人。这只是基本配置(table stakes)。真正的差异化因素是什么?是处理那怪异、意外、非结构化的20%。
  the long tail problem in AI
AI中的长尾问题
步骤 1:从生产环境中捕获信号
为了捕获实际使用中的故障,你需要一个信号管道。这些信号可以是:
  • 显式反馈(Explicit feedback)——来自用户的直接输入(例如,点踩,1星评价)
  • 隐式反馈(Implicit feedback)——行为信号(例如,用户不复制输出,重试相同输入,放弃会话)
示例:在一个文本到SQL系统中,用户没有复制结果。这是一个隐式信号,表明出现了问题——即使他们没有给出差评。
 
步骤 2:仔细解释反馈
并非所有反馈都意味着你所想的那样。
  • 一个点踩可能不是因为质量问题,而是因为延迟。
  • 用户可能没有复制输出,因为他们只是在复核自己的SQL语句。
所以:不要照单全收原始反馈。建立一个轻量级的审查流程,无论是手动的还是利用LLM评审的,以从噪音中过滤出真实信号。
 
步骤 3:闭合循环
当你识别出真正的故障时:
  1. 将其添加到你的测试数据集中
  1. 专门针对该场景运行实验
  1. 发布改进版本
notion image
 
 

结论

最好的AI产品——那些真正受到用户喜爱的产品——是由那些深入关注于以下方面的团队构建的:实验、评估和迭代以提高其可靠性。这就是它们与竞争对手的区别所在。
 
Ragas,我们正在构建基础设施,用评估循环取代“感觉良好检查”。我们正在将所有这些经验转化为构建下一代Ragas。如果你有兴趣与我们合作解决这个问题,我们非常乐意与你交流。
🔗 预约或加入等候名单
 

资源

  1. LLM评估的评分说明
  1. Hamels的博客
  1. Ragas的博客
  1. 数据分布漂移与监控
  1. 提供LLM可观测性的开源工具列表。
    1. Langfuse
    2. Pheonix
    3. Helicone
    4. Laminar
    5. traceloop
    6. OpenLit
  1. 顶级AI产品构建者的故事
    1. 评估Github Copilot
    2. Casetext如何让GPT-4以零错误担任法律助理的秘诀
    3. 我们如何构建 ellipsis
    4. LLM时代的评估范式转变
    5. Notion如何迭代其Notion AI
    6. OpenAI的企业AI报告
  1. 吴恩达的错误分析