−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 volume 裡: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»。

評論

目前還沒有評論。歡迎成為第一位。

發表評論

評論在顯示前會經過審核。