当前位置: 首页 > news >正文

Langfuse 本地 AI 调试台怎么给团队验收?我用 cpolar 开了一个短时观测入口

Langfuse 本地 AI 调试台怎么给团队验收?我用 cpolar 开了一个短时观测入口

AI Demo 跑通以后,最容易吵起来的不是模型能不能回答,而是“这次请求到底发生了什么”。

产品看到一句回答,测试看到一个失败用例,后端看到接口超时,算法同事想看 prompt 和 token。只靠终端日志,大家很快就开始互相截图、互相猜。

我现在的做法是:本地用 Docker 起一套 Langfuse,把测试请求打成 trace;验收时只用 cpolar 给 Langfuse Web 面板开一个临时 HTTPS 地址。团队看同一组脱敏 trace,确认 prompt、响应、耗时、token 和错误日志。验收结束,关掉 cpolar,公网入口立刻回收。

这篇不写大而全的 AI 平台搭建,只把一个闭环跑通:Langfuse 本地部署、最小 trace 上报、团队远程看面板、cpolar 短时 HTTPS 验收、安全边界和排错。

适用场景

这套流程用在 AI Demo 已经能调用模型,但还没进入正式环境的阶段,效果很直接。

比如你本机跑了一个客服问答、RAG 检索、提示词改写、Agent 工具调用,接口已经能返回结果。问题是团队验收时不能只看“最终回答”,还要看这次调用用了哪个 prompt、输入输出是什么、耗时卡在哪里、失败原因是模型报错还是业务代码报错。

可以用在这些场景里:

  • 本地 AI Demo 需要产品、测试、后端一起验收调用链
  • Prompt 改动后,要把新旧 trace 放在面板里对照
  • 测试同事要复现异常输入、超时、空回复、JSON 解析失败
  • 后端同事要确认 token 用量、延迟、错误日志是否完整
  • 公司内网机器能跑 Docker,但外部协作成员打不开本地面板
  • 验收数据已脱敏,只展示测试用户、测试 prompt、测试输出

重点不是把 Langfuse 长期挂公网。

重点是:本地观测面板只在验收窗口短时间开放,验收完马上关。

最终效果

跑完后,你会得到三样东西:

  • Langfuse 本地面板:http://localhost:3000
  • 一条能在 Langfuse 里看到的测试 trace
  • cpolar 临时 HTTPS 地址:形如https://xxxx.cpolar.top

团队验收链路是这样:

团队成员浏览器 | | HTTPS v cpolar 临时公网地址 | | 隧道转发 v 本机 Langfuse Web 面板 :3000 | v 查看脱敏 trace / prompt / latency / token / error

你在本机继续跑 AI Demo 和 Langfuse。团队成员打开 cpolar 地址,登录 Langfuse 面板后查看同一批 trace。

验收会议里不用再贴十几张日志截图。大家直接在 Langfuse 里点开一次请求,看输入、输出、耗时、metadata、level、status message,问题归因会快很多。

环境准备

本文命令以 macOS / Linux 为例。Windows 用户放到 WSL2 里执行也能跑。

需要准备:

  • Docker
  • Docker Compose v2
  • Git
  • Python 3.10+
  • cpolar 客户端和 authtoken

先检查 Docker 和 Git:

docker --version docker compose version git --version

检查 Python:

python3 --version

准备工作目录:

mkdir -p ~/ai-observe-demo cd ~/ai-observe-demo

如果你的机器内存比较紧,先关掉不用的容器。Langfuse v3 的 Docker Compose 会带 Web、Worker、Postgres、ClickHouse、Redis、MinIO 等组件,本地调试能跑,但别拿这套单机 Compose 当高可用生产方案。

Docker 启动 Langfuse

Langfuse 官方仓库已经提供 Docker Compose 文件。本地试跑最省事的方式就是直接拉仓库。

cd ~/ai-observe-demo git clone https://github.com/langfuse/langfuse.git cd langfuse

启动前先生成几组本地 secret。下面这段命令只是在终端里生成随机字符串,方便你替换配置里的默认值:

openssl rand -hex 32 openssl rand -hex 32 openssl rand -hex 32

打开docker-compose.yml,把里面明显的默认密钥替换掉。不同版本字段会有变化,看到NEXTAUTH_SECRETSALTENCRYPTION_KEY、数据库密码、ClickHouse 密码这类字段,都换成自己的值。

本地教程里偷懒不换密钥,短时间也许看不出问题,但一旦你后面用 cpolar 暴露面板,默认密钥就是很糟糕的习惯。

启动 Langfuse:

docker compose up -d

查看容器状态:

docker compose ps

看 Web 容器日志:

docker compose logs -f langfuse-web

等日志里出现服务 ready 相关信息后,打开:

http://localhost:3000

第一次进入面板,按页面提示注册本地管理员账号。然后创建一个项目,比如:

Project name: local-ai-acceptance

进入项目后,在项目设置里创建 API Keys。你会拿到:

LANGFUSE_PUBLIC_KEY=pk-lf-xxxx LANGFUSE_SECRET_KEY=sk-lf-xxxx LANGFUSE_HOST=http://localhost:3000

这三个值后面会给最小示例使用。

接入最小示例:先生成一条 trace

为了让教程可以直接跑,我这里不用真实模型 API。先写一个“假 LLM 调用”,重点验证 Langfuse trace 能不能上报。

新建一个目录:

cd ~/ai-observe-demo mkdir -p langfuse-client-demo cd langfuse-client-demo python3 -m venv .venv source .venv/bin/activate pip install -U langfuse

写环境变量文件:

cat > .env <<'EOF' LANGFUSE_PUBLIC_KEY=替换成你的_public_key LANGFUSE_SECRET_KEY=替换成你的_secret_key LANGFUSE_HOST=http://localhost:3000 EOF

让 shell 读取它:

set -a source .env set +a

写一个最小脚本demo_trace.py

cat > demo_trace.py <<'PY' import os import time from langfuse import Langfuse langfuse = Langfuse( public_key=os.environ["LANGFUSE_PUBLIC_KEY"], secret_key=os.environ["LANGFUSE_SECRET_KEY"], host=os.environ.get("LANGFUSE_HOST", "http://localhost:3000"), ) trace = langfuse.trace( name="local-ai-acceptance-demo", user_id="test-user-001", session_id="acceptance-session-20260714", input={ "question": "用户问:订单 12345 为什么还没发货?", "env": "local-demo", }, metadata={ "app": "customer-service-demo", "git_branch": "feature/langfuse-trace", "tester": "qa-local", }, tags=["local", "acceptance", "cpolar-demo"], ) start = time.time() prompt = """你是客服助手。请根据订单状态给出简短回复。 订单号:12345 订单状态:仓库已打包,等待快递揽收 """ # 这里模拟一次 LLM 返回,先不依赖任何外部模型服务 answer = "订单 12345 已完成打包,正在等待快递揽收。揽收后会自动更新物流信息。" time.sleep(0.8) latency_ms = int((time.time() - start) * 1000) trace.generation( name="mock-llm-call", model="mock-gpt-local", input=prompt, output=answer, usage={ "input": 42, "output": 31, "total": 73, }, metadata={ "latency_ms": latency_ms, "temperature": 0.2, }, ) trace.update( output={"answer": answer}, metadata={"result": "accepted", "latency_ms": latency_ms}, ) langfuse.flush() print(f"trace sent, latency_ms={latency_ms}") PY

运行:

python demo_trace.py

看到类似输出:

trace sent, latency_ms=801

回到 Langfuse 面板,进入项目的 Traces 页面,应该能看到local-ai-acceptance-demo

点进去后,能看到:

  • trace 名称
  • user_id / session_id
  • input / output
  • generation 名称
  • prompt 内容
  • mock 模型名
  • token usage
  • latency metadata
  • tags

到这里,本地 trace 链路已经通了。

再加一条失败 trace,验收时更有用

只看成功请求没什么价值。团队验收时,失败请求反而更能说明观测是否完整。

再写一个失败脚本demo_error_trace.py

cat > demo_error_trace.py <<'PY' import os from langfuse import Langfuse langfuse = Langfuse( public_key=os.environ["LANGFUSE_PUBLIC_KEY"], secret_key=os.environ["LANGFUSE_SECRET_KEY"], host=os.environ.get("LANGFUSE_HOST", "http://localhost:3000"), ) trace = langfuse.trace( name="local-ai-acceptance-error-demo", user_id="test-user-002", session_id="acceptance-session-20260714", input={"question": "请查询订单:空字符串"}, metadata={"app": "customer-service-demo", "case": "empty_order_id"}, tags=["local", "acceptance", "error-case"], ) trace.event( name="validate-input", input={"order_id": ""}, output={"ok": False, "reason": "order_id is empty"}, level="ERROR", status_message="订单号为空,业务校验未通过", ) trace.update( output={"error": "order_id is empty"}, metadata={"result": "rejected"}, ) langfuse.flush() print("error trace sent") PY

运行:

python demo_error_trace.py

回到 Langfuse,把 tags 过滤到error-case,就能看到失败样例。验收时让测试同事重点看这一条:输入是否脱敏、错误原因是否明确、错误等级是否正确、业务字段是否足够定位问题。

接真实 OpenAI 兼容接口时怎么写

上面的 mock 示例用来验证链路。接真实模型时,思路不变:在发起 LLM 请求前后,把 prompt、输出、usage、耗时写进 generation。

下面是一个 OpenAI 兼容接口的写法。你可以接 OpenAI、通义兼容接口、硅基流动,或者公司内部网关。

pip install -U openai langfuse
import os import time from openai import OpenAI from langfuse import Langfuse client = OpenAI( api_key=os.environ["OPENAI_API_KEY"], base_url=os.environ.get("OPENAI_BASE_URL"), ) langfuse = Langfuse( public_key=os.environ["LANGFUSE_PUBLIC_KEY"], secret_key=os.environ["LANGFUSE_SECRET_KEY"], host=os.environ.get("LANGFUSE_HOST", "http://localhost:3000"), ) trace = langfuse.trace( name="real-llm-call-demo", user_id="test-user-003", input={"question": "用一句话解释 Langfuse trace 的价值"}, tags=["real-llm", "acceptance"], ) messages = [ {"role": "system", "content": "你是一个技术文档助手,回答要短。"}, {"role": "user", "content": "用一句话解释 Langfuse trace 的价值"}, ] start = time.time() resp = client.chat.completions.create( model=os.environ.get("OPENAI_MODEL", "gpt-4o-mini"), messages=messages, temperature=0.2, ) latency_ms = int((time.time() - start) * 1000) answer = resp.choices[0].message.content usage = resp.usage trace.generation( name="chat-completion", model=os.environ.get("OPENAI_MODEL", "gpt-4o-mini"), input=messages, output=answer, usage={ "input": usage.prompt_tokens if usage else 0, "output": usage.completion_tokens if usage else 0, "total": usage.total_tokens if usage else 0, }, metadata={"latency_ms": latency_ms}, ) trace.update(output={"answer": answer}) langfuse.flush() print(answer)

这里有个小细节:不要把真实用户手机号、身份证、合同内容、内部系统 token 原样写进 trace。验收样例用测试数据,线上数据做脱敏字段。

Langfuse 做 LLM 可观测很顺手,但观测系统本身也会沉淀敏感信息。这个边界必须提前说清楚。

观测面板验收看什么

Trace 能上报以后,就可以准备团队验收了。别把链接一丢就结束,最好提前准备一个检查清单。

我一般让团队看这些项:

验收项在 Langfuse 里怎么看
请求是否进入系统Traces 列表能看到目标 trace
输入是否脱敏点开 trace,看 input 和 generation input
输出是否符合预期看 trace output 和 generation output
Prompt 是否是当前版本看 generation input 或 metadata 里的 git_branch
token 是否有记录看 generation usage
耗时是否可解释看时间线和 latency metadata
失败是否能定位看 level、status_message、error-case tag
是否能按用户或会话追踪看 user_id、session_id
是否能按版本筛选看 tags、metadata、branch 信息

验收时可以准备三类 trace:

  • 成功请求:证明主链路通
  • 业务失败:比如参数为空、知识库无命中、权限不足
  • 模型失败:比如模型接口超时、JSON 输出不合法、内容被拦截

这样产品、测试、后端看到的是同一套证据,而不是各看各的日志。

用 cpolar 临时开放 Langfuse HTTPS 面板

本地面板只能你自己打开。团队远程验收时,用 cpolar 把localhost:3000临时映射成 HTTPS。

安装 cpolar 后,先登录并配置 authtoken。token 在 cpolar 控制台里复制:

cpolar authtoken 替换成你的_cpolar_authtoken

启动临时隧道:

cpolar http 3000

终端会输出一个公网地址,类似:

Forwarding https://xxxx.cpolar.top -> http://localhost:3000

把这个 HTTPS 地址发给团队成员。对方打开后,看到的就是你本机的 Langfuse Web 面板。

这里有几个操作我会固定做:

  • 给团队单独创建验收账号,不共用你的管理员账号
  • 验收前确认 trace 数据是脱敏样例
  • 只开放3000Web 面板端口
  • 不开放 Postgres、ClickHouse、Redis、MinIO、模型服务、公司内网 API
  • 验收窗口结束后立刻Ctrl+C停掉 cpolar

如果你使用的是固定域名隧道,也要给它明确的使用窗口。别因为“链接还能打开”就一直挂着。

安全边界:这几条别偷懒

Langfuse 面板里会沉淀 prompt、用户输入、模型输出、token 用量、错误信息、内部接口路径。它不是一个普通静态页面。

所以 cpolar 在这里的角色是“短时验收入口”,不是长期公网发布方案。

我会按下面这几条做:

  • 只使用测试项目,不把生产 trace 混进验收项目
  • prompt、用户输入、模型输出提前脱敏
  • API Key、Cookie、Authorization Header 不写入 trace
  • 创建单独验收账号,验收后禁用或删除
  • 只开放 Langfuse Web 端口3000
  • 数据库、ClickHouse、Redis、MinIO、模型网关全部留在内网
  • cpolar 终端窗口保持可见,验收结束马上关闭
  • 验收结束后清理测试 trace 或删除测试项目

还有一点很容易忽略:截图也算数据外发。

如果团队要把 Langfuse 页面截图贴到群里,先确认里面没有真实用户问题、内部 prompt、供应商 Key、订单号、手机号、邮箱、合同文本。很多泄露不是发生在公网入口,而是发生在“随手截个图”。

常见问题和排错

1.docker compose up -d后面板打不开

先看容器状态:

cd ~/ai-observe-demo/langfuse docker compose ps

再看 Web 日志:

docker compose logs --tail=100 langfuse-web

如果 Web 容器不断重启,通常是 secret、数据库连接、端口占用、依赖容器没起来。先确认3000没被占用:

lsof -i :3000

被占用就停掉旧服务,或者调整 Compose 里的端口映射。

2. Python 脚本运行成功,但 Langfuse 看不到 trace

按这个顺序查:

echo $LANGFUSE_HOST echo $LANGFUSE_PUBLIC_KEY echo $LANGFUSE_SECRET_KEY

确认LANGFUSE_HOST是:

http://localhost:3000

然后确认脚本最后执行了:

langfuse.flush()

Langfuse SDK 会异步发送数据,不 flush 的话,短脚本结束太快,trace 还没来得及发出去。

还要检查 API Key 属于当前项目。很多人会在 Langfuse 里建两个项目,然后拿 A 项目的 Key 去 B 项目里找 trace,当然找不到。

3. token usage 为空

mock 示例里我手动写了 usage。真实模型接口里,要看供应商是否返回 usage 字段。

OpenAI 兼容接口一般会返回:

resp.usage.prompt_tokens resp.usage.completion_tokens resp.usage.total_tokens

如果你的网关没返回 usage,可以先在 metadata 里记录估算值,或者让网关层补齐 token 统计。验收时要把“真实统计”和“估算统计”区分清楚。

4. trace 里时间不对

本地容器、浏览器、服务器时区不一致时,列表时间看起来会很怪。

先看宿主机时间:

date

再看容器时间:

docker exec -it langfuse-langfuse-web-1 date

容器名以docker compose ps输出为准。验收结论里统一写北京时间或 UTC,别让大家用各自电脑显示的时间互相对。

5. cpolar 地址能打开,但登录后页面异常

先确认本地http://localhost:3000是否正常。如果本地都异常,先修 Langfuse。

如果本地正常,cpolar 页面异常,检查隧道是不是映射到了正确端口:

cpolar http 3000

不要映射到数据库端口,也不要映射到 ClickHouse、Redis、MinIO。团队只需要看 Web 面板。

6. 团队成员能看到不该看的 trace

这是权限和数据隔离问题,不是 cpolar 的问题。

处理方式很直接:新建一个专门验收项目,只导入或生成脱敏 trace;不要把生产项目拿来共享。验收账号只给这个项目权限,验收完禁用账号、删除测试项目或清理 trace。

7. 端口 3000 被别的服务占了

查占用:

lsof -i :3000

停掉占用进程,或者修改 Compose 端口映射。比如把宿主机端口换成3100

ports: - "3100:3000"

然后本地访问:

http://localhost:3100

cpolar 也跟着换:

cpolar http 3100

关闭公网入口和清理现场

验收结束后,我会按这个顺序收尾。

停掉 cpolar:

在运行 cpolar 的终端按 Ctrl+C

确认外部 HTTPS 地址已经打不开。

如果只是结束远程验收,Langfuse 可以继续留在本机。但如果这次只是临时演示,也可以停掉整套容器:

cd ~/ai-observe-demo/langfuse docker compose down

如果要连测试数据一起清理,执行前先确认没有要保留的 trace:

docker compose down -v

-v会删除 Compose 创建的数据卷,Postgres、ClickHouse、MinIO 里的本地数据都会被清掉。这个命令用于临时演示环境,不要在需要保留数据的机器上随手敲。

最后,把验收账号禁用或删除,把临时 API Key 作废,把发到群里的 cpolar 链接标记为已关闭。

写在最后

Langfuse 的价值不只是“看日志”。它真正解决的是 AI 应用验收里的证据问题:一次回答背后的 prompt、输入、输出、耗时、token、错误,能不能被团队一起看见。

cpolar 在这个流程里也不是为了把内网服务永久暴露出去,而是给本地调试台开一个短时、可回收的 HTTPS 验收窗口。

我的经验是,只要把脱敏 trace 准备好,再把安全边界讲清楚,一场 AI Demo 验收会顺很多。大家不用围着截图猜问题,直接点开 trace 看事实。

验收完记得关入口。

这一步看着简单,但它决定了“临时分享”到底是工程流程,还是安全事故的开头。

http://www.jsqmd.com/news/1206022/

相关文章:

  • CANN/asc-devkit:h2sqrt平方根函数
  • OpenVLA开源机器人决策模型:7B参数实现高泛化视觉-语言-动作控制
  • 浪琴大陆售后维修网络汇总|全新网点信息权威更新启用(2026年7月最新) - 浪琴中国服务中心
  • Ascend C SIMT API bfloat16转换函数
  • 浪琴中国大陆售后指南|权威公示维修地址及官方热线(2026年7月最新) - 浪琴中国服务中心
  • Obsidian技能集完全指南:如何让AI助手智能管理你的知识库
  • Windows下OpenClaw安装实战:Node.js 24与npm环境配置全指南
  • 浪琴中国区售后体系指南|官方通告最新正规维修渠道(2026年7月最新) - 浪琴中国服务中心
  • Ubuntu时间同步配置与NTP服务详解
  • 2026毓典奢品汇天津手表回收,二手名表溢价秘籍与正规渠道 - 二奢行情速报
  • 2026 荆门主城三区黄金回收横向实测测评 - 不晚生活号
  • Linux nohup命令详解:后台运行与进程守护
  • 2026年7月最新亨得利官方服务项目及价格查询|详细地址及24小时热线权威信息通告 - 亨得利官方
  • Python EXE逆向分析实战:从打包原理到源码提取全解析
  • CC Switch:AI CLI工具统一操作系统与热切换实践
  • 2026 梅州靠谱全屋定制选购全指南:本土工厂实测 + 全流程避坑,自装业主不踩雷 - 刘不刘
  • 福州劳力士售后资质核验全解|官网认证维保渠道全新更新(2026年7月最新) - 劳力士售后服务官网
  • Mac开发环境配置全攻略:从终端优化到工具链搭建
  • OCRmyPDF终极指南:3分钟让扫描PDF变可搜索文档
  • 股票短线交易实盘记录:从1万到100万的高胜率策略解析
  • MacOS开发环境配置与效率优化全指南
  • 眉山黄金回收6家正规门店实时金价对比 - 余生黄金回收
  • 降压DC-DC转换器工作原理与选型设计指南
  • 西安商铺装修怎么选?本地工装企业深度盘点、避坑指南与主流商家客观对比 - 国麟测评
  • 2026年全自动铜铝排折弯机供应商推荐:选型指南 - 全域品牌推荐
  • 2026年7月最新卡地亚上海国金中心(IFC)维修保养服务电话 - 卡地亚官方售后中心
  • CentOS 7静态IP配置指南与网络优化技巧
  • 2026年电解水杀虫设备生产厂家行业优选指南 - 谁都没有我好看
  • 重新定义科学探索:AI Scientist-v2如何通过代理树搜索实现全自动研究
  • Linux软件包管理:Yum命令详解与实战技巧