跳到主要内容

怎么放心上线 — 评测 / 追踪 / 红队

这条分支在货架里的位置: 总纲把这 195 个库的共性讲成一句话——「把一个只会吐文本的 LLM,包成能在循环里感知-动作、能被放心运营的程序」。前面几条分支讲怎么这个 agent(编码、框架、多智能体、记忆、检索、工具落地)。本章是**「怎么放心运营」的后半截「监工」:agent 造出来了、也能动作了,可它非确定性**、会幻觉、会被越狱/注入——你凭什么敢把它接上生产流量?这条分支就是回答这个问题的一整套工程:测它、盯它、攻它。

30 秒导读: 模型本身只保证「大概率说对」,而生产要的是「能被验收、能被追责」。这一档 17 个库把「监工」拆成三块——① 像 pytest 一样测 LLM 输出(评测:给不确定的输出定一个可打分、可回归的标准)、② 用 OTel 追踪长跑 agent 的每一步 + 盯成本(可观测:把黑盒变成可回放、可算钱的 span 树)、③ 主动越狱 / 注入去攻它(红队:在上线前替坏人把该干的坏事干一遍)。本章把这 17 个库横过来切,告诉你三块各有哪几种流派、代表库怎么做、以及怎么按需求选。

怎么读本章: 正文是给人读的白话综述,不出现路径行号。每个论断挂一个脚注 [^x],精确的 仓库/路径:行 + 符号名都在脚注里;对比矩阵单开一列「代码锚点」放引用。人读正文,agent 读脚注 / 锚点列。


1. 这条分支要解决什么(第一性原理)

承上:整个货架的共性是「给只会说话的 LLM 装手脚,让它能对世界采取动作,并被放心运营」。前面分支把「造 agent」讲透了;可造出来 ≠ 敢上线。本分支把「放心运营」里最硬的那一半单拎出来——监工

为什么单靠模型不够?因为 LLM 有三条改不掉的毛病,恰好卡死了传统软件的验收范式:

模型的毛病对传统「测试 / 运维 / 安全」意味着什么
非确定性同样输入两次跑,输出可能不同——assert output == "预期" 直接失效
会幻觉语法完全合法、事实凭空捏造——编译器 / linter 一个都拦不住
会被越狱 / 注入攻击面是自然语言,而不是 SQL / XSS——WAF 与静态扫描无从下手

于是这条分支的第一性问题就是:当被监工的对象本身不可靠、不可复现、攻击面是语言时,「测试、运维、安全」这三件传统工程各要重造成什么样子? 三块答案正好对上三个子分支:

  • 评测(测它): 输出没有唯一正确答案,就不能靠字符串相等断言。得改用「打分」——要么规则打分,要么请另一个 LLM 当裁判(LLM-as-judge),再把分数卡一个阈值当 pass/fail,像 pytest 一样跑、像 CI 一样挡回归。
  • 可观测(盯它): 一次 agent 调用不是一个函数,而是一棵「LLM 调用 → 工具调用 → 子 agent」的树,还烧真金白银的 token。得把每一步记成 span、串成 trace,顺带把 token 成本、延迟一并算清——这几乎就是 OpenTelemetry 的问题,只不过语义换成了 LLM。
  • 安全 / 红队(攻它): 坏人用的是自然语言 payload。防御方只能先扮坏人:自动合成越狱 / 注入攻击去打自己的 agent,看它招不招;上线后再挂一层实时护栏(guardrail)在入口 / 出口拦截。

一句话直觉: 前面分支让 agent「能动」,本分支让 agent「可信」。评测给不确定的输出定一把可回归的尺;可观测把黑盒长跑变成可回放、可算钱的 span 树;红队在坏人之前先把坏事干一遍。三者共用一条底线——别赌模型不出错,要在出错时能测出来、看得见、拦得住。

形态上,这 17 个库落在三种角色里:库 / SDK(你 import 进代码里跑:deepeval、promptfoo、deepteam、llamafirewall、nemo-guardrails、agentops、logfire、openllmetry、openlit、opik、evidently、mlflow),自托管平台(带后端 + UI 的一整套:langwatch、laminar、helicone、cozeloop、ai-infra-guard),不少库两副面孔都有(opik / langwatch 既能当库又是平台)。


2. 流派一:像 pytest 一样测 LLM 输出(评测)

第一块是评测——把「这条输出到底好不好」变成一个能打分、能卡阈值、能进 CI 的断言。难点只有一个:输出没有唯一正确答案。于是「怎么打这个分」分化出几个流派,从最不依赖模型到最依赖模型排开。

怎么读这张图: 从左到右是「打分时对 LLM 的依赖递增」。最左边是纯规则 / 字符串断言,完全确定;越往右越靠「请一个 LLM 当裁判」,越灵活也越不稳。

确定、便宜、只能测浅层 ───────────────────► 灵活、能测语义、但裁判本身会飘

┌────────────┐ ┌──────────────┐ ┌──────────────┐ ┌────────────────┐
│ ① 规则断言 │──►│ ② LLM 裁判 │──►│ ③ 带步骤/权重 │──►│ ④ 决策树 / DAG │
│ contains / │ │ llm-rubric │ │ 的裁判 G-Eval │ │ 确定性拆解裁判 │
│ 正则 / JSON │ │ (打分+理由) │ │ CoT+logprob │ │ 逐节点判定 │
└────────────┘ └──────────────┘ └──────────────┘ └────────────────┘

2.1 规则断言(不用模型,最确定)

最朴素:输出该包含什么、匹配什么正则、是不是合法 JSON、延迟 / 成本有没有超标——这些根本不用模型就能判,确定、便宜,但只能测「表层形状」,测不了「说得对不对」。

  • promptfoo 把评测做成一份 YAML 里的断言表:containsequalsis-jsonjavascriptcostlatency 各是一个 assertion 类型,声明式列出、跑一遍出 pass/fail。1 这是「配置即测试」流派的代表——不写代码也能给 prompt / agent 织一张回归网。
  • deepeval 走的是代码即测试:它明确对标 pytest,assert_test(test_case, metrics) 就是一句断言,可以直接放进 pytest 文件、进 CI。2

2.2 LLM 裁判(llm-as-judge,最主流)

规则测不了语义,于是主流做法是请另一个(通常更强的)LLM 当裁判:把「输出 + 评分标准」喂给裁判模型,让它打个分、给个理由,再拿分数卡阈值。这是本流派的核心机制,几乎每个库都有。

  • promptfoollm-rubric:给一条自然语言评分标准,裁判模型返回是否满足 + 理由。3
  • cozeloop 把裁判做成平台级能力,痛点也暴露得最清楚:模型返回的 JSON 常是脏的,于是它做了四级降级解析——直接解析 → jsonrepair 修 → 正则抠 score/reason → 只抠分数兜底,命中即停。4 这是「LLM 裁判在生产里最脏的那一环」的教科书处理。

2.3 带评分步骤 / 权重的裁判(G-Eval)

裸 llm-rubric 的分数会飘。学术界的改进(G-Eval)被广泛落地:让裁判先生成 chain-of-thought 评分步骤,再对离散分数按 logprob 加权求和,把「1 分还是 2 分」的抖动摊平成一个平滑分。

  • deepeval 的旗舰 metric 就是 G-Eval:CoT 评分步骤 + logprob 加权打分,是该库最招牌的实现。5 它也顺带暴露了这条路线的软肋——只有能吐 logprob 的模型才吃得到加权那一层,否则退化。

2.4 决策树 / DAG(把「主观打分」拆成确定性判定)

最激进的一支:干脆别让裁判一次性给一个模糊分,而是把评判拆成一棵决策树——每个节点问一个小的、二元的、好判的问题,顺着边走到叶子给结论。把「主观打分」重新变回「确定性流程」。

  • deepevalDAGMetric:节点分 TaskNode / BinaryJudgementNode / VerdictNode,逐节点判定、沿有向图汇聚成最终裁决。6 适合「评分标准能被明确拆成几步 yes/no」的场景,可复现性远好于一次性打分。

评测这块的领域智慧:能用规则就别用模型(便宜且确定);② 用模型当裁判是逃不掉的,但裁判本身会飘、会吐脏 JSON——所以 G-Eval 加 logprob、cozeloop 加四级降级解析、DAG 把它拆成 yes/no,本质都是在给「不稳的裁判」加确定性护栏;③ 无论哪种,最后都要卡一个阈值变成 pass/fail,才能像单测一样挡回归。


3. 流派二:OTel 追踪长跑 agent + 盯成本(可观测)

第二块是可观测。一次 agent 请求是一棵「LLM 调用 → 工具 → 子 agent」的树,跑几十步、烧一堆 token。出问题时你要能回放每一步,平时要能算清每一步花了多少钱 / 多少毫秒。分化点是:这棵 span 树靠什么标准、在哪一层被记下来?

怎么读这张图: 从左到右是「记录点离你的代码越来越远」——左边你在代码里手动埋点 / 装饰器,右边完全不改代码、在网关处旁路截流量。

埋在你代码里 ──────────────────────────────────► 完全不碰你代码

┌────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ ① OTel 原生埋点 │──►│ ② 自动插桩 │──►│ ③ 代理 / 网关旁路 │
│ @workflow/@task │ │ import 就挂钩 │ │ proxy 截 API 流量 │
│ 手动 span │ │ 各家框架/供应商 │ │ 一行 base_url 改 │
└────────────────┘ └──────────────────┘ └──────────────────┘

3.1 OTel 原生 + 装饰器埋点

当代共识:别自造追踪格式,直接用 OpenTelemetry,把 LLM 语义塞进标准 span。给你装饰器,你在关键函数上一挂,就自动开 span、串 trace。

  • openllmetry(Traceloop)提供 @workflow / @task / @agent 装饰器,底层就是 OTel span,能导出到任何 OTel 后端7
  • agentops 用一个装饰器工厂统一生成 @trace / @agent / @task / @tool,靠 SpanKind 路由;并把「一次 session 当作根 span」,还专门算 token 成本8
  • logfire(Pydantic)是 OTel 之上的观测 SDK,给一组 instrument_openai / instrument_anthropic / instrument_pydantic_ai 一键为各家 LLM SDK 埋点。9
  • laminar 定位就是「为长跑 agent 而生的 OTel-native 观测平台」,自托管一整套后端 + UI 收 span。10

3.2 自动插桩(import 就挂钩,零侵入)

比装饰器更省:你什么都不改,库在 import 时就给主流框架 / 供应商打好了钩子,自动把它们的调用记成 span。

  • openllmetry 除装饰器外,为一大票框架 / 供应商各出一个 instrumentation 包(openai、anthropic、langchain、llamaindex、crewai……),装上即自动出 trace。11
  • agentops零侵入 import hooking,并处理一个微妙问题:框架(如 CrewAI)和底层供应商(如 OpenAI)会重复记录,于是它一旦检测到框架就把供应商那层反插桩,避免重复 span。12
  • mlflow 在老 ML 平台上加了 agent/LLM tracing 与 OTel 自动插桩,把 LLM trace 纳入它那套 experiment / run 体系。13
  • openlitOTel-native 的 LLM 观测,还顺带监控 GPU、内建 guardrail 与 evals。14

3.3 代理 / 网关旁路(不碰代码,截流量)

最省侵入:把观测挪到网络层。你只把 LLM 的 base_url 指向一个代理,所有请求 / 响应流经它被记下——一行配置,零代码改动,天然还能做限流 / 缓存 / 计费。

  • helicone 就是这条路的代表:一个 LLM 观测代理,请求经它转发的同时被记录,「一行代码接入」。15

3.4 平台化的可观测(观测 + 评测合流)

很多库不满足于「只记 span」,而把观测和评测缝在一起:线上 trace 直接喂给评测器打分,叫「online / 在线评测」——不重跑 agent,拿生产里已经录下的输出来评。

  • opik(Comet)把 tracing + 自动评测 + 监控做成一体,线上 trace 可挂在线评分规则。16
  • langwatch 是「评测 + 观测 + agent 测试」的自托管平台,同一份 trace 既看又评。17
  • cozeloop 更进一步:线上评测时,「record-only」的目标跳过真正执行,直接拿预先录下的 trace 输出来评——省掉在生产 trace 上重跑 agent 的成本。18

可观测这块的领域智慧:收敛到 OTel 已是共识——自造格式的越来越少,logfire / openllmetry / laminar / openlit / mlflow 全押 OTel 语义;② 记录点在「代码内埋点 ↔ import 自动插桩 ↔ 网关旁路」之间按侵入度取舍,越省侵入越不精细;③ 自动插桩最大的坑是框架 × 供应商双层重复记录(agentops 专门处理);④ 观测天然和评测合流成「在线评测」,而线上评测的关键优化是别重跑 agent、直接吃录好的 trace


4. 流派三:越狱 / 注入红队 + 实时护栏(安全)

第三块是安全。攻击面是自然语言,传统 WAF / 静态扫描无从下手,只能自己既当攻方又当守方。这块天然分两半——上线前的红队攻击 vs 上线时的实时护栏

怎么读这张图: 上半是「主动攻」(离线,替坏人先打一遍),下半是「被动防」(在线,请求流经时逐条拦)。

── 上线前:红队(主动攻自己)───────────────────────────────
┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ 漏洞类型 │ + │ 攻击手法 │ → │ 合成 payload 打靶 │
│ 注入/越狱/PII │ │ base64/角色扮演/ │ │ 再用裁判判它招没招 │
│ /越权/幻觉 │ │ crescendo 多轮 │ │ │
└──────────────┘ └──────────────────┘ └──────────────────┘

── 上线时:护栏(被动逐条拦)───────────────────────────────
┌────────────────────────────────────────────────────────────┐
│ 输入/输出/工具调用 每一处过一遍 scanner → ALLOW/BLOCK/人工 │
└────────────────────────────────────────────────────────────┘

4.1 红队:漏洞 × 攻击手法 → 合成 payload → 裁判判定

红队框架的通用结构是一个两维笛卡尔积:一批漏洞类型(你怕它犯什么错)× 一批攻击手法(用什么话术骗它),叉乘出一堆 payload 打向目标,再用一个裁判判「它是不是招了」。

  • deepteam 是这套结构的标准实现:入口 red_team(model_callback, vulnerabilities, attacks) 就是「漏洞 × 攻击」两个列表。19 漏洞侧覆盖 prompt injection、excessive agency、goal theft、PII、bias 等一长串;攻击侧从单轮的 base64 / 角色扮演 / prompt injection 到多轮的 crescendo(逐步升级绕过)。每个攻击是一个 enhance(),把朴素恶意请求「包装」成更能骗过模型的形态。20
  • promptfoo 把红队做成它评测能力的延伸:一大排 redteam strategy(base64、leetspeak、rot13、crescendo、goat、mathPrompt、prompt-injection……),生成对抗输入去打目标,再用它自己的 grader 判。21 「同一套框架既做常规评测又做红队」是它的卖点。
  • ai-infra-guard(腾讯)是平台级红队:内部直接内嵌了一份 deepteam 当红队引擎,外面再包 agent / MCP / skills 扫描与越狱评测,并有「先用无害探针试探目标吃不吃某种编码攻击、再筛掉没用的攻击」这类工程优化。22

4.2 实时护栏:每一处过一遍 scanner,判 ALLOW / BLOCK

红队是上线的一次性攻击;上线还要挂一层实时护栏——请求进来、响应出去、甚至每次工具调用,都过一遍检测器,当场放行 / 拦截 / 转人工。

  • llamafirewall(Meta)是这条路的标杆:按 角色(TOOL / USER / ASSISTANT / MEMORY / SYSTEM)分别配 scanner,把 PromptGuard(BERT 分类)、AlignmentCheck(LLM 审对齐)、CodeShield(静态代码分析)、正则等异构检测器合成一个 ALLOW / BLOCK / HUMAN_IN_THE_LOOP 决策;还能 scan_replay整条多轮 trace,抓那种只在跨轮里才显形的目标劫持。23
  • nemo-guardrails(NVIDIA)用一套 Colang DSL + YAML 配置,把护栏分成 input / dialog / retrieval / execution / output 五类 rail,在请求 / 响应管线的不同点各自拦截或改写;library/ 里预置了 jailbreak / injection 检测、self-check、第三方审核等一堆现成 rail 可组合。24
  • deepteam 除红队外也提供轻量 guard_input / guard_output 护栏,红队用的漏洞知识可反哺护栏规则。25
  • openlit 的 SDK 里内建一组 guard(prompt injection / PII / 敏感话题 / topic 限制),和它的观测能力同一套里出。26

安全这块的领域智慧: ① 红队的通吃结构是漏洞 × 攻击手法的笛卡尔积 + 一个裁判——deepteam 与 promptfoo 都是这个骨架;② 攻击手法本质是一堆 enhance() 变换(编码、角色扮演、多轮升级),防御方要覆盖的就是这张不断加长的手法表;③ 护栏是分角色 / 分管线位置的多 scanner 合流,难点在把异构检测器(BERT / LLM / 静态分析 / 正则)的结论归约成一个决策,并处理「拦不准」——所以 llamafirewall 留了 HUMAN_IN_THE_LOOP 这一档;④ 最狠的攻击(与最难的防御)都在跨多轮——单条消息看着无害,连起来才是攻击,所以要 scan_replay 扫整条 trace。


5. 对比矩阵(逐格接地)

维度:主打的块(评测 / 可观测 / 红队安全)、核心机制(白话)、追踪标准形态。描述列写白话,精确 path:line+符号 全在最右「代码锚点」列。 表示该维度对此库不适用或非主打。

库 (id)主打块核心机制追踪标准形态代码锚点
promptfoo评测 + 红队YAML 声明式断言(规则 + llm-rubric)+ 一排 redteam strategy 生成对抗输入库 / CLI(TS)src/assertions/llmRubric.ts:6(handleLlmRubric);src/redteam/strategies/(base64/crescendo/…),promptInjections/index.ts:5(addInjections)
deepeval评测对标 pytest 的 assert_test;G-Eval(CoT+logprob)+ DAG 决策树 metric库(Py)deepeval/evaluate/evaluate.py:67(assert_test);metrics/g_eval/g_eval.py(GEval);metrics/dag/dag.py:23(DAGMetric)
cozeloop评测 + 可观测LLM 裁判四级降级解析脏 JSON;线上评测 record-only 跳过重跑;trace 异步入 MQ自有 trace自托管平台(Go)backend/modules/evaluation/domain/service/evaluator_source_prompt_impl.go:371(jsonRe 正则),jsonrepair 兜底
evidently评测 + 可观测LLM judge descriptor + 文本 / RAG 评测,兼 ML 监控 / 漂移库(Py)src/evidently/descriptors/llm_judges.py;src/evidently/llm/
opik可观测 + 评测tracing + 自动评测 + 监控一体;线上 trace 挂在线评分OTel / 自有库 + 平台(Py)sdks/python/src/opik/evaluation/evaluator.py(evaluate)
langwatch可观测 + 评测评测 + 观测 + agent 测试同一份 trace 既看又评OTel自托管平台(TS)packages/(平台源);card entryPoints
laminar可观测OTel-native、为长跑 agent 而生的观测平台,收 span + UI 回放OTel自托管平台(TS)README.md(OTel-native 定位);packages/
openllmetry可观测@workflow/@task/@agent 装饰器 + 一大票框架/供应商自动插桩,导任意 OTel 后端OTel库 / SDK(Py)packages/traceloop-sdk/traceloop/sdk/decorators/__init__.py:73/:90/:107(task/workflow/agent);packages/opentelemetry-instrumentation-*
agentops可观测装饰器工厂按 SpanKind 生成 @trace/@agent/@task/@tool;session=根 span;算 token 成本;零侵入 import hookOTel库 / SDK(Py)agentops/sdk/decorators/factory.py:25(create_entity_decorator);sdk/core.py:151(TracingCore);instrumentation/__init__.py(框架↔供应商去重)
logfire可观测OTel 观测 SDK;instrument_openai/anthropic/pydantic_ai 一键为各 LLM SDK 埋点OTel库 / SDK(Py)logfire/_internal/main.py:1247(instrument_openai)/:1119(instrument_pydantic_ai)/:1351(instrument_anthropic)
openlit可观测 + 安全OTel-native LLM 观测 + GPU 监控;SDK 内建 guard(注入/PII/话题)+ evalsOTel库 / SDK(TS/Py)sdk/python/src/openlit/guard/prompt_injection.py;.../evals/offline.py
mlflow可观测 + 评测老 ML 平台加 agent/LLM tracing、evaluation、OTel 自动插桩,纳入 run/experimentOTel库 / 平台(Py)README.md(tracing + OTel auto-instrument 定位);card summary
helicone可观测LLM 观测代理:改一行 base_url,请求流经被记录,天然可缓存/限流代理旁路自托管代理(TS)worker/src/index.ts:391(export default { async fetch } 代理入口)
deepteam红队 + 安全red_team(漏洞×攻击) 笛卡尔积合成 payload + 裁判判定;guard_input/output 护栏库(Py)deepteam/red_team.py:12(red_team);red_teamer/red_teamer.py:50(RedTeamer);attacks/single_turn/base64/base64.py:14(enhance);guardrails/guardrails.py:43(Guardrails)
ai-infra-guard红队 + 安全平台级红队(内嵌 deepteam 引擎)+ agent/MCP/skills 扫描;探针预筛编码攻击自托管平台(Py)AIG-PromptSecurity/deepteam(内嵌引擎);cli/red_team_runner.py(探针预筛 :181-203)
llamafirewall安全(护栏)分角色多 scanner(PromptGuard/AlignmentCheck/CodeShield/regex)合成 ALLOW/BLOCK/HUMAN;scan_replay 扫整条 trace库(Py)LlamaFirewall/src/llamafirewall/llamafirewall.py:87/:107/:184(类/scan/scan_replay);..._data_types.py:22(ScanDecision)/:34(Role)
nemo-guardrails安全(护栏)Colang DSL + YAML 配 五类 rail(input/dialog/retrieval/execution/output);library/ 预置 jailbreak/injection 检测库(Py)nemoguardrails/rails/llm/llmrails.py:136/:1482(LLMRails/generate);library/jailbreak_detectionlibrary/injection_detection

矩阵里反复出现两条「合流线」:评测 ↔ 可观测(opik / langwatch / cozeloop / mlflow / evidently 都把「记 trace」和「评 trace」缝在一起,催生在线评测)与 红队 ↔ 护栏(deepteam、openlit 用同一套漏洞知识既攻又防;ai-infra-guard 直接内嵌 deepteam)。纯单块的库反而是少数(promptfoo 偏评测+红队、helicone 偏纯代理观测、laminar 偏纯观测)。


6. 模式与权衡(可带走的领域智慧)

读完矩阵,几条横跨全分支的规律浮出来:

  • 「断言」的责任在从字符串相等,迁移到「打分 + 卡阈值」。 传统 assert == 对非确定输出失效,于是规则断言(promptfoo)只能兜浅层,深层语义几乎必然落到 LLM-as-judge。代价是裁判自己也不稳——所以 G-Eval 用 logprob 加权、DAG 拆成 yes/no、cozeloop 加四级降级解析,全是在给裁判打确定性补丁。容错放哪儿,是评测这块的核心设计决策。

  • 可观测正强力收敛到 OpenTelemetry。 logfire / openllmetry / laminar / openlit / mlflow / opik 全押 OTel 语义,自造格式的越来越少。好处是能接任何 OTel 后端、不锁死;这是这条子分支最明确的趋势。

  • 侵入度是可观测的取舍轴。 代码内装饰器(最精细、最费手)→ import 自动插桩(零改动、但会框架×供应商双记)→ 网关代理旁路(helicone,完全不碰代码、但最粗)。越省侵入,越不精细,没有免费的午餐。

  • 红队 = 漏洞 × 攻击手法 + 裁判,这个骨架是通吃的。 deepteam 和 promptfoo 结构惊人一致;攻击手法本质是一堆 enhance() 变换,防御方要追的就是这张越来越长的手法表。攻和防共用同一份漏洞知识——所以红队库顺手就能出护栏,反之亦然。

  • 护栏难在「把异构检测器归约成一个决策」并接受「拦不准」。 llamafirewall 把 BERT / LLM / 静态分析 / 正则合成一个裁决,还专门留 HUMAN_IN_THE_LOOP 一档——承认自动判不了就转人工,比硬判更工程。

  • 最难的攻防都在跨多轮 / 线上真实流量。 单条消息无害、连起来才是攻击(scan_replay 扫整条 trace);离线评测再全也不等于线上表现,所以「在线评测」直接吃生产 trace、而且别重跑 agent(cozeloop record-only)才划算。


7. 演化趋势(这条分支往哪走)

把时间轴拉出来,三条趋势很清楚:

  1. 三块在合流成一个平台。 早期评测(deepeval / promptfoo)、观测(logfire / openllmetry)、红队(deepteam)各是独立库;新一代平台(langwatch / opik / cozeloop / ai-infra-guard)把「记 trace + 评 trace + 攻 agent」缝成一套后端 + UI。在线评测(拿生产 trace 直接打分、不重跑)是这次合流最典型的产物。

  2. 观测格式收敛到 OTel,红队 payload 库不断扩张。 观测这边越来越统一(全押 OpenTelemetry);安全这边正相反——攻击手法(编码、角色扮演、多轮升级 crescendo/goat、间接注入)和漏洞类型(excessive agency、goal theft、agent identity abuse)随 agent 能力变强而越列越长,这是一场没有终点的军备竞赛。

  3. 护栏从「单点过滤」走向「分角色 + 全 trace + 转人工」。 早期护栏是入口一道正则;现在 llamafirewall 分 TOOL/USER/ASSISTANT/MEMORY/SYSTEM 各配 scanner、scan_replay 扫整条对话、并把判不准的显式转 HUMAN_IN_THE_LOOP。护栏正从「一个过滤器」长成「一个分层决策系统」。

三条趋势同源:agent 越自主、越长跑、攻击面越大,监工就越要「贯穿全生命周期 + 覆盖每一步 + 在判不准时诚实转人工」。这也呼应总纲的共性:把 LLM 包成可信程序,关键不在模型多聪明,而在你能不能测出它错、看见它错、拦住它错


8. 代表作 + 深入读哪些

按流派点名代表作,想深入就从这里下钻:

想学的东西代表作入口
pytest 式评测 + G-Eval + DAG metric(评测必修)deepeval克隆 deepeval/evaluate/evaluate.pymetrics/g_eval/metrics/dag/
声明式断言 + 红队 strategy(配置即测试)promptfoo克隆 src/assertions/src/redteam/strategies/
LLM 裁判脏 JSON 的四级降级解析cozeloop克隆 backend/modules/evaluation/domain/service/evaluator_source_prompt_impl.go
OTel 装饰器 + 全家桶自动插桩openllmetry克隆 packages/traceloop-sdk/packages/opentelemetry-instrumentation-*
装饰器工厂 + 框架×供应商去重 + 成本agentops克隆 agentops/sdk/decorators/factory.pysdk/core.py
各 LLM SDK 一键 instrumentlogfire克隆 logfire/_internal/main.py(instrument_*)
长跑 agent 的 OTel-native 观测平台laminar克隆 README + packages/
一行 base_url 的观测代理helicone克隆 worker/src/index.ts
漏洞×攻击 红队框架 + 护栏deepteam克隆 deepteam/red_team.pyattacks/guardrails/
分角色多 scanner 护栏 + 扫整条 tracellamafirewall克隆 LlamaFirewall/src/llamafirewall/llamafirewall.pyscanners/
Colang DSL 的五类 railnemo-guardrails克隆 nemoguardrails/rails/nemoguardrails/library/
平台级红队 + agent/MCP 扫描ai-infra-guard克隆 AIG-PromptSecurity/
观测 + 评测合流(在线评测)opik · langwatchopik sdks/python/src/opik/evaluation/;langwatch packages/
ML 平台顺带做 LLM tracingmlflow · evidentlymlflow README;evidently src/evidently/descriptors/

给入门者的学习路径: 先把 deepeval 读透(它把「pytest 式评测 + LLM 裁判 + 让裁判变确定」三件事讲得最完整)→ 再看 openllmetry / agentops 理解「OTel span 树 + 成本」这套可观测内核 → 想看攻防就读 deepteam(红队骨架)与 llamafirewall(护栏合流)→ 最后用 langwatch / opik / cozeloop 看这三块怎么在平台里合流成「在线评测」。读完回总纲 index.md,你会发现这条「监工」分支和前面几条「造 agent」分支是同一个共性的两半:一半让 agent 能动,一半让它能被放心运营。


9. 代码地图(导航索引)

给 agent 的精确入口表(库 / 路径 / 符号),按主题排:

主题路径符号
pytest 式断言(deepeval)deepeval/deepeval/evaluate/evaluate.py:67assert_test
G-Eval(CoT + logprob)deepeval/deepeval/metrics/g_eval/g_eval.pyGEval
DAG 决策树 metricdeepeval/deepeval/metrics/dag/dag.py:23DAGMetric / TaskNode / BinaryJudgementNode
LLM 裁判(promptfoo)promptfoo/src/assertions/llmRubric.ts:6handleLlmRubric
G-Eval 断言(promptfoo)promptfoo/src/assertions/geval.ts:9handleGEval
红队 strategy(promptfoo)promptfoo/src/redteam/strategies/promptInjections/index.ts:5addInjections
裁判脏 JSON 四级解析cozeloop/backend/modules/evaluation/domain/service/evaluator_source_prompt_impl.go:371jsonRe / jsonrepair
OTel 装饰器(openllmetry)openllmetry/packages/traceloop-sdk/traceloop/sdk/decorators/__init__.py:73task / workflow / agent
装饰器工厂(agentops)agentops/agentops/sdk/decorators/factory.py:25create_entity_decorator
追踪核心 / session 根 spanagentops/agentops/sdk/core.py:151TracingCore
LLM SDK 一键插桩(logfire)logfire/logfire/_internal/main.py:1247instrument_openai
观测代理入口(helicone)helicone/worker/src/index.ts:391export default { async fetch }
红队入口(deepteam)deepteam/deepteam/red_team.py:12red_team(vulnerabilities, attacks)
红队评测循环deepteam/deepteam/red_teamer/red_teamer.py:50RedTeamer
攻击变换 enhance(deepteam)deepteam/deepteam/attacks/single_turn/base64/base64.py:14Base64.enhance
轻量护栏(deepteam)deepteam/deepteam/guardrails/guardrails.py:43Guardrails / guard_input / guard_output
分角色多 scanner 护栏llamafirewall/LlamaFirewall/src/llamafirewall/llamafirewall.py:107LlamaFirewall.scan / scan_replay
护栏决策枚举llamafirewall/LlamaFirewall/src/llamafirewall/llamafirewall_data_types.py:22ScanDecision(ALLOW/BLOCK/HUMAN_IN_THE_LOOP) / Role
五类 rail 引擎(nemo)nemo-guardrails/nemoguardrails/rails/llm/llmrails.py:136LLMRails.generate
内建 guard(openlit)openlit/sdk/python/src/openlit/guard/prompt_injection.pyguard.prompt_injection
平台级红队(ai-infra-guard)ai-infra-guard/AIG-PromptSecurity/cli/red_team_runner.pyred_team_runner(探针预筛 :181-203)

Footnotes

  1. promptfoo 的 assertion 类型各是 src/assertions/ 下一个文件(contains.ts/equals.ts/json.ts/javascript.ts/cost.ts/latency.ts),声明在 YAML 的 assert 列表里。

  2. deepeval/deepeval/evaluate/evaluate.py:67 assert_test(test_case, metrics, ...),明确对标 pytest、可直接放进 pytest 文件。

  3. promptfoo/src/assertions/llmRubric.ts:6 handleLlmRubric(裁判模型对自然语言 rubric 返回是否满足 + 理由)。

  4. cozeloop/backend/modules/evaluation/domain/service/evaluator_source_prompt_impl.go:371 jsonRe 正则;:19 引 kaptinlin/jsonrepair;:418 parseRepairedJSON——直接解析 → jsonrepair → 正则抠 → 只抠分数,四级降级、命中即停。

  5. deepeval/deepeval/metrics/g_eval/g_eval.py GEval(CoT 评分步骤 + logprob 加权 calculate_weighted_summed_score;no_log_prob_support 处理不吐 logprob 的模型退化)。

  6. deepeval/deepeval/metrics/dag/dag.py:23 DAGMetric;nodes.py:267 TaskNode、:395 BinaryJudgementNode,沿有向图逐节点判定汇聚裁决。

  7. openllmetry/packages/traceloop-sdk/traceloop/sdk/decorators/init.py:73 task、:90 workflow、:107 agent,底层 OTel span,导出任意 OTel 后端。

  8. agentops/agentops/sdk/decorators/factory.py:25 create_entity_decoratorSpanKind 路由生成 @trace/@agent/@task/@tool;sdk/core.py:151 TracingCore、:382 session 作根 span;卡片记其算 token 成本。

  9. logfire/logfire/_internal/main.py:1247 instrument_openai、:1119 instrument_pydantic_ai、:1351 instrument_anthropic,OTel 之上为各家 LLM SDK 一键埋点。

  10. laminar(lmnr-ai/lmnr)README 定位「OpenTelemetry-native observability platform purpose-built for long-running AI agents」;自托管平台 packages/

  11. openllmetry/packages/opentelemetry-instrumentation-{openai,anthropic,langchain,llamaindex,crewai,…} 各一个 instrumentation 包,import 即自动插桩。

  12. agentops/agentops/instrumentation/init.py 零侵入 import hooking;卡片 gotcha:检测到框架(CrewAI)即把供应商(OpenAI)那层反插桩,避免框架×供应商重复 span。

  13. mlflow(mlflow/mlflow)README 定位「adding agent/LLM tracing, evaluation and OTel auto-instrumentation」,纳入 run/experiment 体系。

  14. openlit(openlit/openlit)README 定位「OTel-native LLM observability, GPU monitoring, guardrails and evaluations」。

  15. helicone/worker/src/index.ts:391 export default { async fetch } 代理入口——改 base_url 转发时记录,一行接入。

  16. opik/sdks/python/src/opik/evaluation/evaluator.py 评测入口;卡片记其 tracing + 自动评测 + 监控一体、线上 trace 挂在线评分。

  17. langwatch(langwatch/langwatch)卡片定位「LLM evaluations, observability and AI agent testing」自托管平台;packages/

  18. cozeloop 卡片 gotcha:record-only(*Online)目标在线评测时跳过真正执行,用预先录下的 trace 输出评,省掉在生产 trace 上重跑 agent。

  19. deepteam/deepteam/red_team.py:12 red_team(model_callback, vulnerabilities, attacks, framework, ...);red_teamer/red_teamer.py:50 RedTeamer、:93 red_team、:597 _a_attack、:704 _a_evaluate_vulnerability_type

  20. deepteam/deepteam/attacks/single_turn/(base64/prompt_injection/roleplay/…)与 multi_turn/(crescendo 等);每个攻击一个 enhance(),如 base64/base64.py:14 Base64.enhance、prompt_injection/prompt_injection.py:35 PromptInjection.enhance;漏洞在 vulnerabilities/(prompt_injection/excessive_agency/goal_theft/agent_identity_abuse/bias/…)。

  21. promptfoo/src/redteam/strategies/(base64.ts/leetspeak.ts/rot13.ts/crescendo.ts/goat.ts/mathPrompt.ts/promptInjections/…);promptInjections/index.ts:5 addInjections;grader 见 src/redteam/graders.ts。

  22. ai-infra-guard(Tencent/AI-Infra-Guard)AIG-PromptSecurity/deepteam 内嵌 deepteam 当红队引擎;cli/red_team_runner.py:181-203 无害探针预筛编码攻击(卡片 gotcha)。

  23. llamafirewall/LlamaFirewall/src/llamafirewall/llamafirewall.py:87 LlamaFirewall、:107 scan、:164 scan_async、:184 scan_replay;scanners/(prompt_guard/code_shield/regex/hidden_ascii + experimental alignment);llamafirewall_data_types.py:22 ScanDecision(ALLOW/HUMAN_IN_THE_LOOP_REQUIRED/BLOCK)、:34 Role(TOOL/USER/ASSISTANT/MEMORY/SYSTEM)

  24. nemo-guardrails/nemoguardrails/rails/llm/llmrails.py:136 LLMRails、:1482 generate、:927 generate_async;config.py:1711 RailsConfig;五类 rail(input/dialog/retrieval/execution/output);library/(jailbreak_detection/injection_detection/self_check/…)预置 rail。

  25. deepteam/deepteam/guardrails/guardrails.py:43 Guardrails、:108 guard_input、:160 guard_output;:11 GuardVerdict、:20 GuardResult

  26. openlit/sdk/python/src/openlit/guard/(prompt_injection.py/pii.py/sensitive_topic.py/topic_restriction.py);evals/offline.py 离线 evals。