创建完整的评估生命周期以构建高(四)
我们的系统必须做好适应的准备。一个真实的系统会使用专门的日志服务,但在我们的示例中,一个简单的写入 JSONL(JSON 行)文件的函数就足以完美地演示这个概念。这促使我们设计出一个更智能的V1智能体,它拥有强大的模型、用于数学验证的工具使用能力,以及一个用于上下文推理的RAG系统。现在,让我们创建一张全新的、有挑战性的收据,我们的V1代理从未接受过此类收据的训练,很可能会误解它。这证实了我们在准
CI/CD、PromptOps和持续监控
我们已经成功构建并评估了一个高度准确的V1代理。然而,将代理投入生产仅仅是个开始。现实世界是动态的。新类型的收据将会出现(数据漂移),公司政策也会改变(概念漂移)。我们的系统必须做好适应的准备。
评估不仅仅适用于开发阶段。生产系统需要一个强大的MLOps框架来处理整个生命周期。提示词和配置应该像代码一样进行版本控制(提示词操作),变更应触发自动化评估管道(CI/CD)。
最重要的是,我们必须建立一个反馈循环,以捕捉生产故障,并将其转化为新的高价值测试用例,从而推动持续改进。
让我们将这个理论付诸实践。我们将模拟一个现实场景:我们的 V1 代理遇到了一种它从未见过的新型收据,犯了一个错误,然后人类审核员提供了反馈。然后,我们将编写代码,把这个反馈转化为评估套件中的一个新的永久性测试用例。
步骤1:模拟生产测井
首先,我们需要一种机制来记录我们的代理在生产环境中的活动。一个真实的系统会使用专门的日志服务,但在我们的示例中,一个简单的写入 JSONL(JSON 行)文件的函数就足以完美地演示这个概念。
import uuid
def production_logger(image_path: Path, predicted_audit: AuditDecision, log_file: str = "production_log.jsonl"):
"""模拟将生产事务记录到文件中。"""
log_entry = {
"log_id": str(uuid.uuid4()),
"timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
"input_file": image_path.name,
"prediction": predicted_audit.model_dump(),
}
with open(log_file, "a") as f:
f.write(json.dumps(log_entry) + "\n")
print(f"[日志记录器]: 已将日志条目 {log_entry['log_id']} 写入 {log_file}")
return log_entry
此生产日志记录器函数会捕获每个事务的关键信息:唯一ID、时间戳、输入文件以及代理的完整预测输出。写入JSONL文件是一种常见做法,因为这样便于追加新条目并在后续进行解析。
步骤2:模拟生产故障
现在,让我们创建一张全新的、有挑战性的收据,我们的V1代理从未接受过此类收据的训练,很可能会误解它。这张收据包含一张“礼品卡”,根据大多数公司的政策,礼品卡不应被批准为费用。
# 创建一个我们系统尚未见过的、具有挑战性的新收据。
new_receipt_content = "Corporate Gifts Inc.\n789 Gifty Lane, Boston, MA\nAmazon Gift Card: 1 @ $50.00 = $50.00\nTax: $0.00\nTotal: $50.00"
new_receipt_path = IMAGE_DIR / "receipt_6.txt"
new_receipt_path.write_text(new_receipt_content)
print(f"在新收据上运行 V1 管道: {new_receipt_path.name}...")
_, failed_audit_decision = await run_v1_pipeline(new_receipt_path)
print("\n--- 新收据的 V1 审计决策 ---")
print(failed_audit_decision)# 记录本次生产运行。
logged_failure = production_logger(new_receipt_path, failed_audit_decision)
我们在这张新收据上运行V1管道并记录结果。让我们来检查一下代理的决策。
####### 输出 ###########
正在新收据 receipt_6.txt 上运行 V1 管道...
[工具调用]: 计算 总和 [50.0, 0.0]
[RAG 检索器]: 搜索 与以下相关的政策: '公司礼品公司亚马逊礼品卡'
--- 新收据的 V1 审计决策 ---
AuditDecision(
not_travel_related=False,
amount_over_limit=False,
math_error=False,
handwritten_x=False,
推理="该费用是用于公司礼品,差旅政策中未明确涵盖此项。不过,金额在75美元限额之内,且没有其他警示信号。该费用似乎合理。",
需要审计=False,
)
[日志记录器]: 已将日志条目5f8b3c2a-....写入production_log.jsonl
明显的失误!我们的代理错误地批准了礼品卡购买(needs_audit=False)。其推理过程揭示了问题所在:它在RAG知识库中未找到与“礼品卡”相关的政策,于是默认做出了宽松的决策。这是概念漂移的典型例子,即生产数据引入了系统未知的新业务规则。
步骤3:通过人工反馈闭环
在实际系统中,人类审计员最终会审查这笔交易,并将其标记为错误。我们现在需要一种方法来捕捉他们的专业判断,并利用它来创建一个新的、永久性的测试用例。
def create_new_test_case_from_feedback(log_entry: dict, human_feedback: AuditDecision, gt_dir: Path):
"""根据记录的失败情况和人工的正确标签创建一个新的地面实况文件。"""
sample_id = Path(log_entry["input_file"]).stem
new_gt_path = gt_dir / f"{sample_id}.json"
# 我们需要完整的地面实况,包括正确的细节提取。
# 对于这个模拟,我们将假设细节提取是正确的。
# 一个真实的系统可能也需要人工来纠正细节。
correct_details = ReceiptDetails(
merchant="Corporate Gifts Inc.",
location=Location(city="Boston", state="MA"),
items=[LineItem(description="Amazon Gift Card", quantity=1, price=50.0, total=50.0)],
tax=0.0,
total=50.0
)
new_ground_truth = {
"details": correct_details.model_dump(),
"audit": human_feedback.model_dump()
}
new_gt_pathwrite_text(json. dump ps(new_ground_truth,indent=2))
print(f"\n[反馈循环]:新的地面实况文件创建于:{new_gt_path}")
返回new_gt_path
#这是我们圈中人提供的“专家标签”。
human_corrected_audit=审计决策(
not_travel_related=真的,礼品卡不是旅行
amount_over_limit=False,
math_error=False,
handwritten_x=False,
推理="礼品卡不是允许的旅行费用,需要审计。",
needs_audit=True,
)
# 通过创建新的测试用例来闭环。
new_test_file = create_new_test_case_from_feedback(logged_failure, human_corrected_audit, GROUND_TRUTH_DIR)
# 让我们检查一下刚刚创建的文件。
print("\n--- 新测试用例的内容 ---")
print(json.loads(new_test_file.read_text()))
create_new_test_case_from_feedback函数是我们反馈循环的实际实现。它接收记录的生产故障和human_corrected_audit决策,并以编程方式生成一个新的、正确标记的地面实况文件。
######## 输出 #######
[反馈循环]:新的地面实况文件已创建于:temp_data/ground_truth/receipt_6.json
--- 新测试用例内容 ---
{
"细节": {"商家": "Corporate Gifts Inc.",... "总计": 50.0, "手写笔记": []},
"审计": {"与旅行无关": true,... "理由": "礼品卡不是允许的旅行费用,需要审计。", "需要审计": true}
}
我们已成功闭环。生产故障已被捕获,由人工修正,并转化为永久性的自动化测试用例。
这个新文件receipt_6.json现在将被提交到我们的版本控制ground_truth目录中。下次我们的CI/CD管道运行评估时,这个新案例将被包含在内。我们的V1代理将在这个测试中失败,这将迫使下一位开发人员更新系统(例如,通过在RAG知识库中添加关于 "礼品卡 "的新策略),以使测试通过。这就是评估驱动开发的良性循环在起作用,确保我们的系统不断学习并适应现实世界。
总结评估驱动开发的周期
我们运用严谨的数据驱动方法论,指导每一步,从高层次的业务问题出发,一路发展到复杂的多组件智能体。这个项目展示了一个强大且结构化的工作流程,用于构建不仅智能,而且可靠、高效并与现实世界业务目标相一致的AI系统。
让我们总结一下我们已经付诸实践的评估驱动开发工作流程的关键原则:
-
范围与模型先行:我们不是从代码开始,而是从对业务问题的清晰定义和财务模型入手。这一关键的第一步使我们能够将代理的技术表现直接转化为商业价值,为整个项目提供了明确的指引。
-
简单起步(V0):我们使用一个快速、低成本的模型构建了尽可能基础的端到端系统。这并非试图解决问题,而是为了建立性能基线并迅速找出最明显的故障模式。
-
广泛评估,深入分析:我们最初的评估套件立即显示,我们的V0系统过于脆弱,存在提取和推理失败的问题。通过深入研究具体的失败案例,我们从知道它失败了转变为理解它为什么失败。
-
针对性改进(V1):我们从V0评估中获得的见解使我们能够形成具体的、有针对性的改进假设。这促使我们设计出一个更智能的V1智能体,它拥有强大的模型、用于数学验证的工具使用能力,以及一个用于上下文推理的RAG系统。
-
精确评估(V1评估):我们通过运营指标(成本、延迟)和数据切片增强了评估套件。这证实了我们在准确性方面的改进,但也立即揭示了一个新的关键瓶颈:我们的V1代理虽然正确,但在生产环境中速度太慢。
-
闭环管理:最后,我们展示了如何构建生产反馈循环,将模拟的生产故障转化为新的永久性测试用例。这是持续改进的动力,确保系统随着时间的推移不断适应并变得更加健壮。
这一迭代过程将AI开发从一种主观调整提示的艺术转变为一门可衡量、持续改进的科学。这一征程并未就此结束。评估驱动开发的原则具有可扩展性,几乎适用于任何基于大语言模型(LLM)的应用。通过将客观、多维度的评估作为开发过程的核心,你可以构建真正兑现承诺的AI系统。

为武汉地区的开发者提供学习、交流和合作的平台。社区聚集了众多技术爱好者和专业人士,涵盖了多个领域,包括人工智能、大数据、云计算、区块链等。社区定期举办技术分享、培训和活动,为开发者提供更多的学习和交流机会。
更多推荐
所有评论(0)