给 LLM 应用接一套可观测性:用 Opik 自托管做 trace / 评估 / production 监控的全流程记录

背景

手上有一个用 LangChain 搭的 RAG 客服助手,跑在生产环境大概三个月了。一直缺一套能把 prompt 版本、retrieval 命中、LLM 调用、用户反馈都串起来的工具——之前靠 LangSmith,但 1.5k+ stars 的开源替代品 comet-ml/opik 最近被同事反复安利,趁着周末把它从零跑了一遍,把过程和坑记下来。

1. 部署:本地 Docker Compose 一条命令

仓库 19.7k stars(2026-06-16 实测),Apache-2.0,Python 为主。文档说日均能扛 40M+ traces,这个量级对我们这种中小团队很够用了。

git clone https://github.com/comet-ml/opik.git
cd opik
./opik.sh

执行完默认会拉起一整套(前端、后端、MySQL、ClickHouse、Redis、Ollama 等),UI 跑在 http://localhost:5173 。脚本支持服务 profile,这是个细节:

./opik.sh --infra          # 只起基础设施,适合只想跑评估任务的时候
./opik.sh --backend        # 基础设施 + 后端服务,不带前端
./opik.sh --guardrails     # 全套 + Guardrails

我用 --infra 先验证环境,确认 ClickHouse 起来了再 --backend 加服务。坑 1:在内存 16G 的机器上默认 profile 会被前端构建+ClickHouse 一起压到 swap,启动会很慢。我把前端单独用 host 网络跑 dev server,后端走 Docker,资源立刻回来了。

2. Python SDK 接入:@opik.track 装饰器最省事

import opik

opik.configure(use_local=True)

@opik.track
def answer_question(user_question: str) -> str:
    docs = retrieve(user_question)
    return llm_call(user_question, docs)

被装饰的函数每次调用都会作为一个 span 上报到本地服务,UI 里能看到完整调用树。坑 2:如果函数嵌套调用,装饰器会按调用栈自动建父子 span,不需要手动传 parent_id。但异步函数要在外层加 asyncio 适配,不然 trace 会丢一半——这是 README 里没明说的。

Opik 对主流框架有原生集成,覆盖大概 50 多个,关键的几个我标一下:LangChain / LangGraph / LlamaIndex / OpenAI / Anthropic / Bedrock / Cohere / Ollama / OpenTelemetry / DSPy / CrewAI / AutoGen。最近新加的 Google ADK 和 Flowise AI 也都在列。

3. LLM-as-a-judge:幻觉检测的一个最小例子

生产里我特别关心 RAG 的"答非所问"和"幻觉",Opik 内置的几个 judge metric 正好覆盖:

from opik.evaluation.metrics import Hallucination

metric = Hallucination()
score = metric.score(
    input="What is the capital of France?",
    output="Paris",
    context=["France is a country in Europe."]
)
print(score)  # 0.0 ~ 1.0,越小越好

还有几个常用的:AnswerRelevanceContextPrecision(RAG 检索质量)、Moderation坑 3:judge 自身也是个 LLM 调用,默认走 OpenAI gpt-4o——也就是说你得有 OpenAI API key,而且每条评估都要钱。我们生产 trace 量级一天 8k 条左右,如果全跑 judge 一天就是 $30+ 的额外开销。后来我把 judge 限到 5% 采样 + 触发式(只在用户给负反馈时跑),成本压到 $5/天以内。

4. 实验管理:Dataset + Experiment 跑回归

Opik 的 Dataset/Experiment 模式很像 ML 里的 train/eval split,但对象是 prompt:

from opik import Opik

client = Opik()
ds = client.get_or_create_dataset("rag-qa-v1")

# 灌测试集
ds.insert([
    {"input": "...", "expected_output": "..."},
    ...
])

# 在 Playground 切换 prompt / model 跑对比
# UI 里直接看到每个实验的 metric 分布

坑 4:Dataset insert 默认走 HTTP,如果一次性塞 5k+ 条,SDK 不会自动分批,得自己 chunk(我用了 500 一批 + tqdm)。第二个坑是 Playground 里切换 base_url 比较麻烦,本地用 Ollama 测 prompt 时,要先把 Ollama 启在 11434,Opik 才能在下拉里识别到。

5. 生产监控:Online Evaluation Rules

这是 Opik 相对 LangSmith 让我眼前一亮的部分——可以配规则,生产 trace 触发条件就自动跑 judge 并发告警:

# production_rules.yaml 示例
rules:
  - name: high-hallucination-alert
    sample_rate: 0.1
    metric: hallucination
    threshold: 0.7
    action: slack_alert

我配了三条规则:幻觉率 > 0.7 触发 Slack、retrieval 命中率 < 0.5 触发 PagerDuty、单条 trace token > 8000 触发成本告警。坑 5:规则生效是异步的,有大概 30s-1min 的延迟,不能拿它做实时拦截(Guardrails 模块可以做,但默认不开)。

6. 自认的局限

跑了一周后,我对这套的边界有了点判断:

  1. Docker 资源消耗偏高。即使只是 --infra profile,ClickHouse + MySQL + Redis + 后端一起起来,空载内存 ~4G。轻量场景(单机 demo)其实只需要 trace 落 SQLite + 简单 web,Opik 没有提供更瘦的"single binary"模式。
  2. judge metric 全英文 prompt。对中文业务场景,直接用 Hallucination metric 评估中文回答,分数会偏高(judge 自己对中文"幻觉"的判定没英文敏感)。我在 fork 上把 judge prompt 改成双语对比,效果稳定了一些。
  3. OpenTelemetry 集成还在 beta。我有个 .NET 服务想接入,SDK 还不完善,最后走了 HTTP exporter 自定义 trace 才解决。如果你是 polyglot 团队,这块要预留适配时间。
  4. Dashboard 没有 RBAC。所有登录账号都能看到全部 project,生产环境要么前置一层 SSO,要么干脆只在内网跑。这点 LangSmith 和 Helicone 都做得更成熟。
  5. judge 采样策略要自己定。官方文档没给一个"XX 量级用多少采样率"的参考,我现在的 5% 阈值也是拍脑袋,后续想拿一周的历史 trace 做一次校准。

适用场景建议

如果你符合下面任意一条,我觉得 Opik 是值得试的:

  • 已经在 LangChain / LlamaIndex 写过生产 RAG,想补 trace 和回归评估
  • 团队没预算买 LangSmith Enterprise,又想自托管一套 LLM 观测
  • 需要做 prompt 版本的 A/B 对比,Experiment UI 真的省事
  • 单日 trace 量在 100 万以内(40M+ 是分布式部署上限,单机别信)

如果你只是单机玩玩、用 Ollama 跑 demo,直接 opik.configure(use_local=True) + @opik.track 就够了,不用拉整套 Docker。

参考

posted @ 2026-06-16 19:09  Ninghg  阅读(57)  评论(0)    收藏  举报