如果你正在开发基于大语言模型的应用,可能已经发现一个现象:模型调用本身只是整个系统的一小部分。一个典型的 LLM 应用往往包含检索、预处理、后处理、工具调用等多个步骤。当用户反馈"回答不对"时,你很难一眼看出是检索环节没找到相关文档,还是提示词组装出了问题,又或者是模型本身在胡编。这时候,追踪就成了必不可少的工具。
Opik 提供了一套完整的追踪方案,不仅能记录所有的 LLM 调用,还能追踪应用中的其他步骤。它支持 TypeScript SDK、Python SDK、OpenTelemetry 以及 REST API。这篇文章会从零开始,带你了解如何给应用加上 Opik 追踪,并深入一些高级用法。如果你刚开始接触 Opik,建议先看看快速入门指南,跑通第一个 LLM 调用。本文不会涉及聊天对话的追踪,那部分有单独的指南。

为什么需要追踪?
LLM 应用和传统软件有一个很大的不同:它的行为往往不是确定性的。同样的输入可能产生不同的输出,而且内部步骤多、嵌套深。如果没有追踪,你就像在一个黑盒里调试,只能靠猜。追踪能帮你理解应用的流程,并定位到具体是哪个环节出了问题。
Opik 的追踪功能可以记录每一次 LLM 调用,也可以记录检索、数据转换、外部 API 调用等步骤。每个追踪(trace)代表一次完整的交互,内部的每个步骤称为跨度(span)。跨度可以嵌套,形成一棵调用树。这样你就能一层层往下钻,直到看清最细粒度的操作。
安装和配置 SDK
在给应用添加可观测性之前,需要先安装并配置 Opik SDK。根据你使用的语言和框架,有几种选择。
TypeScript SDK
如果你用 TypeScript,可以通过 npm 安装:
bash
npm install opik
然后在 .env 文件里设置环境变量:
bash
OPIK_API_KEY=your_api_key_here
OPIK_WORKSPACE=your_workspace_name
OPIK_URL_OVERRIDE=https://www.comet.com/opik/api
OPIK_URL_OVERRIDE 是可选的,如果你用的是 Opik Cloud,可以设置成上面的地址。如果自托管,就换成你自己的实例地址。
Python SDK
Python 用户可以通过 pip 安装:
bash
pip install opik
安装完成后,可以用 opik configure 命令行工具进行配置,也可以在 Jupyter Notebook 里调用 opik.configure。配置过程会提示你输入 API key 或 Opik 服务器地址。
OpenTelemetry
如果你已经在使用 OpenTelemetry,可以直接把数据导出到 Opik。需要设置两个环境变量:
bash
export OTEL_EXPORTER_OTLP_ENDPOINT=https://www.comet.com/opik/api/v1/private/otel
export OTEL_EXPORTER_OTLP_HEADERS='Authorization=<your-api-key>,Comet-Workspace=default'
如果自托管,把 endpoint 换成 http://localhost:5173/api/v1/private/otel。
Opik 是开源的,可以用 Docker 在本地托管。官方也提供了托管平台,注册 Comet 账号即可使用。
选择集成方式
安装并配置好 SDK 后,就可以开始追踪 agent 调用了。Opik 提供了 40 多个集成,覆盖大多数流行的框架和库。你可以从集成总览页面找到完整列表。下面挑几个常见的例子说明。
OpenAI(TypeScript)
如果你用 OpenAI 的 TypeScript SDK,先安装 Opik 的 OpenAI 集成包:
bash
npm install opik-openai
配置环境变量:
bash
export OPIK_API_KEY="<your-api-key>"
export OPIK_URL_OVERRIDE="https://www.comet.com/opik/api"
然后用 trackOpenAI 包装你的 OpenAI 客户端:
typescript
import OpenAI from "openai";
import { trackOpenAI } from "opik-openai";
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const trackedOpenAI = trackOpenAI(openai);
const completion = await trackedOpenAI.chat.completions.create({
model: "gpt-4",
messages: [{ role: "user", content: "Hello, how can you help me today?" }],
});
console.log(completion.choices[0].message.content);
await trackedOpenAI.flush();
所有通过 trackedOpenAI 发起的调用都会自动记录到 Opik。记得在程序结束前调用 flush(),确保数据发送完毕。
OpenAI(Python)
Python 的用法类似。先安装 Opik:
bash
pip install opik
然后运行 opik configure 进行配置。接着用 track_openai 包装客户端:
python
from opik.integrations.openai import track_openai
from openai import OpenAI
openai_client = OpenAI()
openai_client = track_openai(openai_client)
之后所有通过 openai_client 的调用都会被记录。
AI Vercel SDK
如果你用 Vercel 的 AI SDK,可以安装 opik-vercel:
bash
npm install opik-vercel
配置环境变量后,初始化 OpikExporter:
typescript
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OpikExporter } from "opik-vercel";
const sdk = new NodeSDK({
traceExporter: new OpikExporter(),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
const result = await generateText({
model: openai("gpt-4o"),
prompt: "What is love?",
experimental_telemetry: { isEnabled: true },
});
console.log(result.text);
所有启用了 experimental_telemetry 的调用都会被记录。
ADK
如果你用 ADK,先安装 Opik 并配置,然后用 OpikTracer 包装 agent:
python
from opik.integrations.adk import OpikTracer, track_adk_agent_recursive
opik_tracer = OpikTracer()
track_adk_agent_recursive(agent, opik_tracer)
LangGraph
LangGraph 的集成也很直接:
python
from opik.integrations.langchain import OpikTracer
graph = ...
app = graph.compile(...)
opik_tracer = OpikTracer(graph=app.get_graph(xray=True))
result = app.invoke(
{"messages": [HumanMessage(content="How to use LangGraph ?")]},
config={"callbacks": [opik_tracer]}
)
函数装饰器
如果你不想依赖特定框架,可以用 @track 装饰器。Python 里这样写:
python
from opik import track
@track
def my_function(input: str) -> str:
return input
所有对 my_function 的调用都会被记录。它支持嵌套函数,也兼容大多数集成。只要把父函数用 @track 装饰一下,内部的调用会自动形成嵌套跨度。
AI Wizard
Opik 还提供了一个预构建的提示,可以配合 Cursor 等编辑器快速完成集成。点击按钮会打开 Cursor,并引导你完成 SDK 安装和代码插桩。它支持 Python 和 TypeScript,其他语言也可以联系官方获得帮助。集成完成后,运行应用就能在 Opik 仪表板里看到追踪数据。
其他框架
Opik 支持 30 多个集成,比如 Dify、Agno、Ollama 等。如果你的框架不在列表里,仍然可以用函数装饰器或低级 SDK 来记录追踪。
在 Opik 中分析 agent
启用可观测性后,你就可以在 Opik UI 里查看每次 agent 调用。可以看到 agent 图、所有工具调用、每个跨度的输入输出和耗时。这些数据对于调试和优化非常有价值。
高级用法
函数装饰器详解
函数装饰器是给现有应用添加 Opik 日志的好方法。给函数加上 @track 后,Opik 会为这次调用创建一个跨度,并记录输入参数和输出。如果被装饰的函数在另一个被装饰的函数内部调用,Opik 会自动创建嵌套跨度。
TypeScript 也支持装饰器,不过目前还是实验性的。下面是一个例子:
typescript
import { track } from "opik";
class TranslationService {
@track({ type: "llm" })
async generateText() {
return "Generated text";
}
@track({ name: "translate" })
async translate(text: string) {
return `Translated: ${text}`;
}
@track({ name: "process", projectName: "translation-service" })
async process() {
const text = await this.generateText();
return this.translate(text);
}
}
Python 的例子更常见。你可以追踪 LLM 调用,也可以追踪检索、后处理等步骤:
python
import opik
import openai
client = openai.OpenAI()
@opik.track
def retrieve_context(input_text):
context = [
"What specific information are you looking for?",
"How can I assist you with your interests today?",
"Are there any topics you'd like to explore?",
]
return context
@opik.track
def generate_response(input_text, context):
full_prompt = (
f" If the user asks a non-specific question, use the context to provide a relevant response.\n"
f"Context: {', '.join(context)}\n"
f"User: {input_text}\n"
f"AI:"
)
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": full_prompt}]
)
return response.choices[0].message.content
@opik.track(name="my_llm_application")
def llm_chain(input_text):
context = retrieve_context(input_text)
response = generate_response(input_text, context)
return response
result = llm_chain("Hello, how are you?")
print(result)
使用装饰器时,可以通过 opik_args 参数或 opik_context 模块自定义 trace 和 span 的数据。比如设置标签、元数据、线程 ID、反馈分数。opik_args 不会传递给函数本身,只用于 Opik 配置。如果指定了 opik_args,配置会传播到嵌套函数。
低级 SDK
如果你需要完全控制日志记录过程,可以使用低级 SDK。TypeScript 里这样写:
typescript
import { Opik } from "opik";
const client = new Opik({
apiUrl: "https://www.comet.com/opik/api",
apiKey: "your-api-key",
projectName: "your-project-name",
workspaceName: "your-workspace-name",
});
const trace = client.trace({
name: `Trace`,
input: { prompt: `Hello!` },
output: { response: `Hello, world!` },
});
const span = trace.span({
name: `Span`,
type: "llm",
input: { prompt: `Hello, world!` },
output: { response: `Hello, world!` },
});
await client.flush();
Python 的用法:
python
from opik import Opik
client = Opik(project_name="Opik client demo")
trace = client.trace(
name="my_trace",
input={"user_question": "Hello, how are you?"},
output={"response": "Comment ça va?"}
)
trace.span(
name="Add prompt template",
input={"text": "Hello, how are you?", "prompt_template": "Translate the following text to French: {text}"},
output={"text": "Translate the following text to French: hello, how are you?"}
)
trace.span(
name="llm_call",
type="llm",
input={"prompt": "Translate the following text to French: hello, how are you?"},
output={"response": "Comment ça va?"}
)
trace.end()
建议在完成 trace 和 span 后调用 end(),确保结束时间正确记录。Opik 的日志功能设计用于生产环境,所有操作在后台线程执行。如果需要确保程序退出前所有数据都发送完毕,可以调用 flush()。
上下文管理器
Python 还提供了上下文管理器,让代码更简洁:
python
import opik
with opik.start_as_current_trace("my-trace", project_name="my-project") as trace:
trace.input = {"user_query": "What is the weather?"}
trace.output = {"response": "It's sunny today!"}
trace.tags = ["weather", "api-call"]
trace.metadata = {"model": "gpt-4", "temperature": 0.7}
start_as_current_span 类似:
python
with opik.start_as_current_span("llm-call", type="llm", project_name="my-project") as span:
span.input = {"prompt": "Explain quantum computing"}
span.output = {"response": "Quantum computing is..."}
span.model = "gpt-4"
span.provider = "openai"
span.usage = {
"prompt_tokens": 10,
"completion_tokens": 50,
"total_tokens": 60
}
上下文管理器可以嵌套,形成层次结构。它们也会自动处理错误,确保 trace 被正确关闭和记录。你可以动态更新参数,控制 flush 时机。最佳实践包括:使用描述性名称、设置合适的类型、添加相关元数据、优雅处理错误、按项目组织、考虑性能(只在需要时使用 flush=True)。
项目和环境管理
默认情况下,trace 会记录到 Default Project。你可以通过几种方式指定项目。
TypeScript 里可以用 OPIK_PROJECT_NAME 环境变量,或者在 Opik 客户端构造函数里传 projectName。
Python 里可以用环境变量,或者在 @track(project_name="my_project") 里指定,或者在 Opik(project_name="my_project") 里指定。
项目名称的解析顺序分两种情况。如果没有活动项目上下文,顺序是:显式参数、客户端配置、默认值 Default Project。一旦某个 @track(project_name=...) 或 opik.project_context(...) 建立了活动项目上下文,所有嵌套操作都会使用这个项目名。嵌套函数即使指定了不同的项目名,也会被忽略,并记录警告。opik.project_context() 可以为代码块设置项目名。
有一个警告:当脚本同时使用 @track 和其他 Opik API 调用(如 evaluate()、get_or_create_dataset()、Prompt())时,如果项目名不一致,trace 和 API 对象可能落到不同项目。确保 opik.configure(project_name=...) 的值与每个 API 调用显式传递的 project_name 一致。
环境让你给 trace 打上生命周期标签,比如 development、staging、production。TypeScript 里可以在 client.trace(environment: ...) 里指定,或用 OPIK_ENVIRONMENT 环境变量。Python 里可以用 @track(environment="production") 或 client.trace(environment="production")。你还可以用 createEnvironment、getEnvironments、updateEnvironment、deleteEnvironment 管理环境。过滤时可以用 filter_string='environment = "production"',支持 =、!=、in、not_in。
刷新和禁用追踪
对于短生命周期的脚本,可能需要手动刷新。TypeScript 用 client.flush(),Python 用 client.flush() 或 @track(flush=True)。
如果想全局禁用日志,TypeScript 可以用 OPIK_TRACK_DISABLE 环境变量、trackDisable 配置或 setTracingActive(false)。Python 可以用 OPIK_TRACK_DISABLE 或 opik.set_tracing_active(False)。禁用后,装饰器、集成和手动 client.trace() 调用都会停止发送数据。
下一步
设置好可观测性后,你还可以进一步记录聊天对话、用户反馈,以及设置在线评估指标。这些功能能帮你更全面地理解和优化 LLM 应用。
追踪不是可有可无的装饰品,而是 LLM 应用开发的基础设施。Opik 把这套东西做得足够简单,从安装到集成,再到高级用法,都有清晰的路径。花点时间跑通第一条追踪记录,你会发现后续的开发和调试效率会有质的提升。