一个好的 trace 看起来是什么样?
你看到 traces 出现在 Langfuse 中,但你怎么知道是否做得好?这里有几件你可以查看和优化的事情。
Trace 结构不仅仅是美观——许多 Langfuse 功能构建在其之上:
- LLM-as-a-judge 评估器按名称和类型定位 observations,并读取它们的输入和输出。
- 仪表盘按 trace 和 observation 名称过滤和聚合指标。
- 数据集实验跨运行对比 trace 输入和输出。
- 追踪表上的保存视图引用名称和属性。
结构良好的 trace 让今天的调试更快,而稳定的名称和有意义的输入/输出让你的评估器、仪表盘和实验在应用演进时继续工作。
一个 trace 的范围是什么?
Langfuse 的数据模型有三个分组级别:observations(单个步骤)通过 trace_id 分组为 traces,traces 可以通过 session_id 分组为 sessions。
一个 trace 代表你应用中一个自包含的工作单元。典型 trace 的好例子:
- 一个聊天机器人回合(用户发送消息,你的应用检索上下文、调用 LLM、返回响应)
- 一次 agent 运行(agent 接收任务、推理、调用工具并产生结果)
- 一次流水线执行(一个文档进来,被分块、嵌入并存储)
如果其中多个按顺序发生,例如多轮对话,或馈入最终报告的几次 agent 运行,那就是 sessions 的用武之地。每一步都是自己的 trace,而 session 将它们绑在一起。对于聊天机器人,这意味着每回合一个 trace、每对话一个 session——你无法预先知道对话何时结束,而每回合模型保持 traces 小巧且易于在 session 视图中导航。
一个 trace 在 Langfuse UI 中显示为 trace 树和 agent 图:


查看 trace 树
当你点击一个 trace 时,你会看到 trace 树。有两件事你可以检查:
正确的步骤是否显示出来?
你应该看到你的 LLM 调用、工具调用和其他重要步骤在树中表示。它们应该有正确的 observation 类型。
例如
- 一个 LLM 调用应显示为
generation。这很重要,因为generation可以携带成本、token 用量和模型信息。 - 一个工具调用应显示为
tool。然后你可以在创建 LLM-as-a-judge 评估器时过滤工具调用 observations。
框架集成通常会自动设置这些类型。如果你手动埋点,可以通过 as_type 参数(Python)或 asType(JS/TS)设置它们。完整列表参见 observation 类型文档。
嵌套是否正确?
工具调用应嵌套在编排该步骤的 agent 或 span 下,作为请求它的 generation 的兄弟节点,这样树就能显示每个动作属于哪个步骤,而不是让工具调用悬在 trace 根。
框架集成通常会自动做对。如果你手动埋点,参见嵌套 observations。
是否有你不需要的噪声?
并非树中的每个 observation 都对理解你的应用做了什么有用。HTTP spans、数据库查询和框架内部通常会增加混乱,而不给你有意义的洞察。如果你看到像这样的 observations 污染你的 trace 树,你可以将它们过滤掉。

选择好的名称
Observation 和 trace 名称在许多地方使用:
- 设置 LLM-as-a-judge 评估器时,你按名称定位特定 observations。
- 在仪表盘中,你可以按 observation 名称过滤和聚合指标。
- 在追踪表中,名称帮助你快速识别每个步骤做什么。
由于名称在所有这些地方被引用,请像对待 API 一样对待它们:当名称更改时,针对旧名称的评估器、仪表盘查询和保存的过滤器会静默停止匹配。刻意选择名称,并期望保持它们稳定。
使用主动语态。 以 observation 执行的动作命名,动词在前:classify-intent、retrieve-context、generate-response、summarize-results。这让 trace 树读起来像你应用所做事情的描述,并使过滤特定步骤更容易。
将动态值排除在名称之外。 使用 process-order,而非 process-order-8945 或 generate-response-retry-2。名称应标识操作,而非它的单次执行——否则每个 trace 都会产生新名称,你无法再分组、过滤或定位它们。将运行特定的值放在元数据中。(这与 OpenTelemetry 对 span 名称推荐的低基数规则相同。)
尽量不要以使用的 AI 模型命名 observations(
gpt-4o、claude-sonnet)。一旦你更换模型,所有引用该名称的过滤器、评估器和仪表盘都会失效。模型已经是generationobservations 上的单独属性,请改用那个。
选择有意义的输入和输出
通常,建议操作具有输入和/或输出。如果一个 observation 两者都没有,问问自己该 observation 是否真的有用,或者你是否可以删除它。
根 observation 值得最多关注:trace 级输入和输出派生自它。它们显示在追踪表中,被评估器读取,并在数据集实验中跨运行对比。将它们设置为审阅者一眼所需的内容——对于聊天机器人,输入为用户消息,输出为助手响应——而非函数参数的原始 JSON blob。如果你需要原始负载用于调试,请将它放在元数据中。
对于你最常查看的 observations,多花点心思设置它们。你可能会在追踪和 session 屏幕上创建预过滤视图。你在这里过滤的 observations 将是被查看最多的。对于这些,问问自己:我需要什么才能一眼快速评估一个 trace/session?

GENERATION observations 的典型输入/输出:
- 对于聊天机器人:用户消息(输入)和助手响应(输出)。
- 对于 RAG 流水线:用户查询和生成的答案。
- 对于分类任务:被分类的文本和预测的标签。
大多数输入/输出可以渲染为可读的、带角色标签的对话,而非原始 JSON blob。如果你的显示为原始 JSON,你可以查看格式:它应该是标准 OpenAI 格式的消息列表(每个带
role和content),并且仅当工具调用位于 assistant 消息的tool_calls数组中、且每个调用的arguments作为 JSON 编码字符串给出时(例如""),才将它们渲染为卡片。
如果你的输入和输出字段意外显示为空,参见为什么我的 trace 的输入和输出为空?
有用的属性
Observations 有许多对你的用例可能有用的属性。这些将让你能够在过滤、打分和制作仪表盘方面走得更远。
为上下文添加元数据
元数据是每个 observation 上灵活的键值存储。它是任何有用上下文但不属于名称或输入/输出的内容的合适位置。实践中有用的元数据示例:
- 评估上下文:标准答案、预期行为,或 LLM-as-a-judge 评估器 需要但不属于实际输入/输出的其他上下文。评估器可以在其变量映射中引用元数据字段。
- 请求上下文:内部请求 ID、处理请求的 API 路由或应用版本,或活动的实验变体/功能标志。这让你能够将 trace 与你的其他系统关联,并按发布过滤。
- 检索上下文:对于 RAG 步骤,如数据源、检索的块数或查询的索引——在调试为什么检索步骤返回糟糕结果时很有用。
- 原始负载:会使输入/输出字段混乱但偶尔需要用于调试的完整请求/响应对象。
- 标注上下文:进行人工审阅时,元数据为标注者提供额外信息以做出更好的判断。
你可以在 Langfuse UI 中按元数据键过滤,当你需要查找具有特定特征的 traces 时这很有帮助。
在 generations 上追踪模型、tokens 和成本
如果你想了解你的 LLM 使用成本,按模型、按用户、按功能细分,你需要在你的 generation observations 上有三样东西:
- 模型名称:Langfuse 用它来查找模型定价表中的定价。如果模型名称不匹配,Langfuse 无法自动计算成本。
- 用量详情:输入 tokens、输出 tokens,以及可选的缓存 tokens。这是驱动仪表盘中 token 用量视图的内容。
- 成本详情(可选):如果你想覆盖 Langfuse 的自动定价——例如,如果你有自定义定价协议——你可以显式传递成本。
大多数集成会自动捕获所有这些。如果你手动埋点,参见 token 和成本追踪文档。
你可以在 Langfuse UI 中的 GENERATION observation 上看到这些属性。

将标签用于业务级维度
标签支持跨对你业务重要的维度进行过滤和指标细分。好的标签回答诸如"我们的 web 和 api 用户之间的延迟有何不同?"之类的问题。
标签的一个属性是它们不可变且必须在 observation 创建时设置。这使它们非常适合你预先知道的事情(请求来自哪里、它属于哪个功能),但不适合你后来才知道的事情。
如果你需要基于事后确定的事情标记 traces,例如 LLM-as-a-judge 评估结果,请改用分数。
将提示词关联到 traces
如果你在 Langfuse 中管理提示词,你可以将它们关联到你的 generations。这让你能够看到给定 trace 使用了哪个提示词版本,并追踪指标如何跨提示词版本变化。当你迭代提示词并想对比性能时很有用。
设置环境
设置 environment 属性(production、staging、development),以便你的测试 traces 不会污染生产仪表盘和评估。
用用户 ID 追踪用户
设置用户 ID 将 traces 连接到特定用户,从而解锁 Langfuse 中的每用户视图。如果你想回答以下问题,这很有用:
- 哪些用户花费我们最多?
- 输出质量如何在用户之间变化?
- 特定用户的用量模式是什么样的?
用 session ID 分组相关 traces
如果你的应用涉及逻辑上属于一起的多个 traces,将它们分组为一个 session。这给你一个 session 回放视图,你可以在其中按顺序看到完整的交互。
这在以下情况有意义:
- 你在构建聊天机器人(每个用户消息创建新 trace,但整个对话是一个 session)
- 你有多个 agent,每个都对最终输出有贡献(例如五个协作产生报告的 agents)
- 你的工作流跨多个请求,中间有人工参与步骤
如果你的应用是单请求/单响应,调用之间没有连续性,你可能不需要 sessions。
