跳到主要内容

回归测试与 CI/CD

当您对智能体(Agent)进行变更(如更新提示词、更换模型、重构工具)时,您需要确保这些变更不会悄无声息地破坏原有功能。获取这种信心最有效的方法与您在其他代码中采用的方法一致:编写测试,并在 CI 中运行它。

MLflow 允许您将智能体的行为测试和回归测试编写为普通的 pytest 函数。您可以使用 @mlflow.test 标记测试,利用 mlflow.genai.evaluate() 对智能体的输出运行评分器(内置或自定义、基于代码或 LLM 判别器),并断言其通过。会话中的每个测试都会记录在同一个 MLflow 运行(Run)下,因此绿色的 CI 检查和可浏览的通过/失败记录均来自同一个源头。

MLflow regression test run showing each test case as a row with a consolidated pass/fail result
python
# tests/regression/test_support_agent.py
import mlflow
from mlflow.genai.scorers import Guidelines


@mlflow.test
def test_answers_concisely_in_english(agent):
result = mlflow.genai.evaluate(
predict_fn=agent.invoke,
data=[{"inputs": {"question": "What are your support hours?"}}],
scorers=[
Guidelines(name="is_english", guidelines="The answer must be written in English."),
Guidelines(name="is_concise", guidelines="The answer must be a single sentence."),
],
)
assert result.passed, result.reason
bash
pytest tests/regression/test_support_agent.py

回归测试与数据集评估的区别

针对数据集运行评估是为了回答衡量问题:“我的智能体在整个数据集上的正确性/安全性/相关性得分是多少?”其输出是聚合指标(例如正确率为 82%,安全性为 95%)。

回归测试是为了回答门禁问题:“这个特定的行为是否被破坏了?”每个测试都源于您已经发现的特定故障模式,并将其转化为二进制的通过/失败检查,从而在每次变更时运行,确保该问题永远不会悄无声息地复现。您不是在追踪得分趋势,而是在对已知故障设置门禁,例如曾经导致系统提示词泄露的提示词注入,或是客户上周报告的三个问题。

@mlflow.test 专为此类门禁工作流而构建。它复用了相同的评分器和 evaluate() 引擎,但将结果调整为适用于通过/失败断言和 CI 流程的形式。

测试循环

最好的回归测试套件不是预先写好的,而是从真实的故障中成长起来的。每次您的智能体出现错误时,您都可以将该案例捕获为测试,这样它就永远不会再次悄无声息地退化。MLflow 支持整个循环。

设置

运行 `mlflow agent setup` 以将 MLflow 技能安装到您的编码智能体中并连接追踪(Tracing),确保每一次智能体运行都被捕获。

运行并观察

运行您的智能体并在 MLflow UI 中审查生成的追踪记录,以发现它在何处表现异常。

捕获故障

生产环境中的故障、点踩评价或在追踪中记录的反馈,都是您编写下一次测试的原始素材。

编写回归测试

将失败案例转化为 @mlflow.test:固定其输入并断言您实际预期的行为。

在 CI 中设置门禁

在每次拉取请求(Pull Request)时运行该套件,确保回归问题不会在不被察觉的情况下卷土重来。

快速入门

让您的编码智能体完成设置

在项目内部运行一次 mlflow agent setup,将 MLflow 技能安装到您的编码智能体(如 Claude Code, Codex 等)中。这些技能教会智能体 MLflow 追踪、评分器和 @mlflow.test 的工作原理,使其能够为您连接追踪并编写回归测试。

bash
uvx mlflow@latest agent setup

第 1 步:启用 pytest 插件

@mlflow.test 通过 pytest 插件运行。通过将其添加到 pyproject.toml 中来启用它:

toml
[tool.pytest.ini_options]
addopts = ["-p", "mlflow.pytest.plugin"]

或者使用 pytest -p mlflow.pytest.plugin 为单次运行启用它。

第 2 步:编写测试

@mlflow.test 标记测试,使用您的智能体和编码了您所关注行为的评分器来调用 mlflow.genai.evaluate(),然后对结果进行断言。

在此处,agent 是您定义的 pytest fixture,它返回您的应用程序,因此 agent.invoke 是 MLflow 为每个输入调用的入口点。

python
# tests/regression/test_support_agent.py
import mlflow
from mlflow.genai.scorers import Guidelines


@mlflow.test
def test_answers_concisely_in_english(agent):
result = mlflow.genai.evaluate(
predict_fn=agent.invoke,
data=[{"inputs": {"question": "What are your support hours?"}}],
scorers=[
Guidelines(name="is_english", guidelines="The answer must be written in English."),
Guidelines(name="is_concise", guidelines="The answer must be a single sentence."),
],
)
assert result.passed, result.reason

仅当每个评分器对每一行数据都通过时,result.passed 才为 Trueresult.reason 会列出失败的评分器及其理由,因此当断言失败时,pytest 会直接向您展示原因,无需再次运行测试。

您可以在此处使用全套 MLflow 评分器,包括 内置 LLM 判别器自定义判别器基于代码的评分器

第 3 步:运行它

bash
pytest tests/regression/test_support_agent.py

像运行任何其他 pytest 套件一样运行它。整个会话将被记录为单个 MLflow 运行。打开 MLflow UI 中的 Evaluation runs 页面,选择该运行以检查每个测试用例,包括对话、追踪和断言结果。

Regression test run detail showing a test case's conversation and per-assertion pass/fail results

并行运行套件

智能体测试很慢:每个测试都会运行您的真实智能体及其 LLM 判别器。pytest 默认按顺序运行测试,因此即使是中等规模的测试套件也会很快累积到数分钟的运行时间。pytest-xdist 可将测试分布在工作进程中,从而缩短时间。

首先,安装它并向您的 conftest.py 添加一个钩子(hook),以便每个工作进程都向同一个 MLflow 运行报告。如果没有这个钩子,每个工作进程都会记录自己的运行,导致结果分散在每个进程的独立运行中。

bash
pip install pytest-xdist
python
# conftest.py
import os
import mlflow


def pytest_configure(config):
# Put every worker's test cases on a single MLflow run.
if not hasattr(config, "workerinput"): # controller only
run = mlflow.start_run(run_name="regression-suite")
mlflow.end_run()
os.environ["MLFLOW_RUN_ID"] = run.info.run_id

然后并行运行该套件。

bash
pytest -n auto # one worker per CPU core
pytest -n 4 # fixed number of workers

在 CI 中运行

由于这些是普通的 pytest 测试,在 CI 中运行它们只需运行 pytest。将 MLFLOW_TRACKING_URI 指向持久化的跟踪服务器(或 Databricks 工作区),以便在作业完成后记录并审查运行及其追踪。如果您的测试使用 LLM 判别器评分器,请使用 MLFLOW_GENAI_JUDGE_DEFAULT_MODEL 固定判别器模型,以便每次运行都使用相同的模型进行评分。使用 -n auto 标志并行运行套件,并利用上一节中提到的 conftest.py 将所有结果保持在同一个运行中。

yaml
# .github/workflows/agent-regression.yml
name: Agent regression tests
on: [pull_request]

jobs:
regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install "mlflow>=3.14" pytest pytest-xdist
- name: Run regression tests
env:
MLFLOW_TRACKING_URI: ${{ secrets.MLFLOW_TRACKING_URI }}
# Judge model for built-in / LLM-judge scorers (or pass model= to each scorer).
MLFLOW_GENAI_JUDGE_DEFAULT_MODEL: "openai:/gpt-5-mini"
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: pytest -n auto tests/regression

断言失败会导致 pytest 作业失败,从而导致检查失败,进而阻断拉取请求,这与单元测试完全一致。当测试失败时,pytest 输出中的 result.reason 消息会告诉您哪个评分器标记了该输出及其原因,录制的 MLflow 运行则允许您打开完整的追踪进行调试。

后续步骤