−25%

Windows 按年付费,截至 10 月 31 日。 查看套餐

EQVPS
开始使用

Langfuse VPS:看清你的 AI 智能体做了什么

自托管 Langfuse,追踪无人值守智能体的每次 LLM 调用和每个工具步骤。经过实测的 Docker Compose、真实内存数据和合适的套餐。

凌晨三点无人值守的智能体,价值取决于你事后能否还原它做了什么。“一夜烧掉 38 $ 的 token”是个糟糕的早晨。“因为搜索工具返回了空页面、规划器重试了 400 次,所以烧掉 38 $”则是一个午饭前就能修好的 bug。第二句话需要追踪数据。

Langfuse 把每次 LLM 调用、每个提示词、工具步骤、token 数和延迟记录成一棵可以点开查看的树。自托管时,这些提示词和回复——里面常常有客户数据、API 输出,偶尔还有不小心混进去的密钥——留在你自己掌控的服务器上,而不是别人的面板里。

运行成本

Langfuse v4 不是一个小小的二进制文件,而是六个容器:Web 应用、后台 worker、Postgres、存事件的 ClickHouse、Redis 和存文件的 MinIO。我们把它装在测试服务器上,空项目时测得约 3.5 GB 内存占用。会持续增长的是 ClickHouse,因为你发送的每个 span 都存在那里。

负载套餐
几个智能体,数周的追踪数据Medium-IP:6 vCPU、6 GB、45 GB(每月 $20)
智能体集群,数月的历史Pro 套餐,32 GB 内存起 — 按需申请

更小的套餐也能装上,但只要 ClickHouse 和 worker 同时要内存就会吃力。我不会选低于 6 GB 的。

智能体在哪里?如果在别的机器上运行,就选带独立 IPv4 的套餐:它们需要 HTTPS 端点,而 NAT 套餐的出站地址不是你独有的,从外部只能访问 SSH 端口。如果智能体就在这台服务器上运行,Langfuse 根本不必暴露到互联网:试用的话 NAT 版 Medium(每月 $12)就够了。共有两个机房位置:德国和芬兰;下单时可看到是否有货。选离智能体近的,而不是离你近的。服务器用加密货币付款,无需 KYC。

安装

在一台全新的 Ubuntu 24.04 或 Debian 12 服务器上,以 root 身份操作。先装 Docker:

curl -fsSL https://get.docker.com | sh

然后是 Langfuse,用真正的密钥替换 compose 文件里的默认值:

git clone --depth 1 https://github.com/langfuse/langfuse.git
cd langfuse

PG=$(openssl rand -hex 16); MINIO=$(openssl rand -hex 16)
cat > .env <<EOF
NEXTAUTH_URL=https://langfuse.example.com
NEXTAUTH_SECRET=$(openssl rand -hex 32)
SALT=$(openssl rand -hex 32)
ENCRYPTION_KEY=$(openssl rand -hex 32)
POSTGRES_PASSWORD=$PG
DATABASE_URL=postgresql://postgres:$PG@postgres:5432/postgres
CLICKHOUSE_PASSWORD=$(openssl rand -hex 16)
MINIO_ROOT_PASSWORD=$MINIO
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY=$MINIO
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY=$MINIO
LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY=$MINIO
REDIS_AUTH=$(openssl rand -hex 16)
TELEMETRY_ENABLED=false
EOF
chmod 600 .env

其中两个密码是成对的:Postgres 密码也写在 DATABASE_URL 里,MinIO 密码必须与三行 S3_..._SECRET_ACCESS_KEY 一致。所以每个密码都只取自一个变量。

接下来是个坑。compose 文件把 Web 应用发布在 3000 端口、MinIO 发布在 9090 端口,而且是所有网卡;Docker 发布的端口会绕过 ufw。把两者都绑定到 localhost,让反向代理成为唯一入口:

sed -i 's/- 3000:3000/- 127.0.0.1:3000:3000/; s/- 9090:9000/- 127.0.0.1:9090:9000/' docker-compose.yml
docker compose up -d
curl -s http://127.0.0.1:3000/api/public/health

最后一条命令应输出 {"status":"OK", ...}。首次启动会执行数据库迁移;在我们的测试中,容器启动约 15 秒后健康检查通过。

前置 HTTPS

把 langfuse.example.com 解析到服务器 IP,然后:

apt install -y caddy
cat > /etc/caddy/Caddyfile <<'EOF'
langfuse.example.com {
    reverse_proxy 127.0.0.1:3000
}
EOF
systemctl reload caddy
ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw enable

Caddy 会自动申请证书。打开网站,创建账号(它会成为第一个组织),添加一个项目,复制它的公钥和私钥。

然后随手关门。Langfuse 认识 AUTH_DISABLE_SIGNUP,但默认的 compose 文件不会把它传给 web 容器,所以要在 langfuse-web 下多加一行:

sed -i 's|^      NEXTAUTH_SECRET: \(.*\)$|      NEXTAUTH_SECRET: \1\n      AUTH_DISABLE_SIGNUP: ${AUTH_DISABLE_SIGNUP:-false}|' docker-compose.yml
echo "AUTH_DISABLE_SIGNUP=true" >> .env
docker compose up -d

此后任何注册尝试都会收到 «Sign up is disabled»。同事请在项目内部添加。

从智能体发送追踪数据

Python SDK 会包装你的函数,嵌套调用会变成嵌套的 span:

python3 -m venv venv && . venv/bin/activate
pip install langfuse
export LANGFUSE_PUBLIC_KEY=pk-lf-...
export LANGFUSE_SECRET_KEY=sk-lf-...
export LANGFUSE_BASE_URL=https://langfuse.example.com
from langfuse import get_client, observe

langfuse = get_client()  # 读取 LANGFUSE_* 变量

@observe(name="fetch-prices")
def fetch_prices(pair: str) -> dict:
    return {"pair": pair, "bid": 64210.5}

@observe(name="nightly-agent-run")
def run() -> str:
    data = fetch_prices("BTC/USDT")
    return f"done: {data['pair']}"

print(run())
langfuse.flush()  # 短脚本会在后台发送完成前退出

不要漏掉 LANGFUSE_BASE_URL。没有它,SDK 会悄悄把所有数据发到 Langfuse 云端,你的密钥在那里不存在,你只能对着空面板发呆。

在终端里确认 span 已经到达:

curl -s -u "$LANGFUSE_PUBLIC_KEY:$LANGFUSE_SECRET_KEY" \
  "$LANGFUSE_BASE_URL/api/public/v2/observations?limit=5"

在 v4 中,旧端点 /api/public/traces 会返回一个关于 events-only 模式的错误。这是预期行为,不是安装出了问题。在真实的智能体里,你用同样的方式包装 LLM 调用和每个工具;此外 Langfuse 自带对常用 LLM SDK 和智能体框架的集成,很多时候改一行 import 就行,不必到处加装饰器。

需要留意的

  • 磁盘。 ClickHouse 和 MinIO 会保存你发送的一切。docker system df -v 能看出空间去了哪里。如果追踪的是很长的提示词和回复,Medium-IP 的 45 GB 会在几周而不是几年内用满。每月检查一次;不够用时,400 GB 及以上的 Pro 套餐可按需申请。
  • 更新。 compose 文件固定了主版本(:4)。docker compose pull && docker compose up -d 会拉取该版本内的修复。升级主版本前请先读 changelog:追踪端点正是在 v4 消失的。
  • 备份。 重要的东西都在 Docker 卷里:Postgres 存用户、项目和密钥;ClickHouse 和 MinIO 存追踪数据本身。按计划把它们复制到服务器之外。

每月 $20 值不值?如果你的智能体在 token 上花得比这多——大多数无人值守的智能体都是如此——那么知道 token 花到了哪里,第一次遇到循环失控时就能回本。每天只跑一次的小智能体用不上这些:一个日志文件加一个 token 计数器就够了。

相关内容

准备好部署了?加密货币付款、无需KYC——约一分钟上线。

立即部署 →

常见问题

自托管 Langfuse 需要多少内存?

在我们的测试服务器上,Langfuse v4 以六个容器运行——web、worker、Postgres、ClickHouse、Redis 和 MinIO——空项目时占用约 3.5 GB 内存。ClickHouse 会随着你发送的每个 span 增长。Medium-IP(6 GB 内存、45 GB 磁盘)跑几个智能体绰绰有余;保存数月历史的整个智能体集群则需要 Pro 套餐,可按需申请。

Langfuse 需要独立 IP 地址吗?

只有当智能体运行在别处、通过互联网发送追踪数据时才需要:它们需要一个 HTTPS 端点,而 NAT 套餐从外部只接受你的 SSH 端口。如果智能体就在同一台服务器上,Langfuse 可以只监听 localhost,面板通过 SSH 隧道打开;这种情况下 NAT 版 Medium 套餐就够了。

代码能跑,但面板一直是空的。为什么?

几乎总是因为没设置 LANGFUSE_BASE_URL。没有它,SDK 会把所有数据发到 Langfuse 自己的云端,你自托管实例的密钥在那里不存在,你的服务器什么也收不到。把变量设成你自己的地址。

/api/public/traces 端点返回错误。安装坏了吗?

没有。Langfuse v4 运行在 events-only 模式下,该端点在此模式中被禁用。请通过 /api/public/v2/observations 读取数据——我们正是用这个调用确认测试 span 已经到达。

如何阻止陌生人在我的实例上注册?

Langfuse 会读取 AUTH_DISABLE_SIGNUP,但默认的 docker-compose.yml 不会把这个变量传给 web 容器,所以只写在 .env 里没有用。在 langfuse-web 的 environment 中加一行(命令见下文),创建好自己的账号后设为 true,之后的注册请求都会收到 «Sign up is disabled»。

评论

暂无评论。来做第一个吧。

发表评论

评论在显示前会经过审核。