去年我在做一个法律合同审查项目时,一晚上跑下来账单直接超了 1200 元。复盘的时候我发现,根本没有任何工具告诉我"到底哪一段 prompt 烧了最多 token"。从那天起,我就决定自己搭一套 Token 消耗仪表盘,把所有调用成本可视化、可追溯、可优化。

在动手之前,先看一眼 2026 年主流模型在 HolySheep AI 上的真实报价(output 价格,/MTok,¥1=$1 无损结算):

模型官方 $价官方 ¥价(汇率7.3)HolySheep ¥价每月 100 万 token 节省
GPT-4.1$8.00¥58.40¥8.00¥50.40(-86.3%)
Claude Sonnet 4.5$15.00¥109.50¥15.00¥94.50(-86.3%)
Gemini 2.5 Flash$2.50¥18.25¥2.50¥15.75(-86.3%)
DeepSeek V3.2$0.42¥3.07¥0.42¥2.65(-86.3%)

单看 100 万 token 差距不大,可一旦业务量上来——比如每天 500 万 token、连续跑 30 天——Claude Sonnet 4.5 用官方渠道一个月要 ¥3285,HolySheep 只要 ¥450,单模型一年就能省下 ¥3.4 万。这就是为什么必须在用中转站的同时,自己再叠一层精细化的成本监控:既要"省钱",也要"省得明白"。

一、为什么需要自建 Token 仪表盘?

二、整体架构

我用三段式架构,部署在自己 2C2G 的小服务器上跑得很稳:

  1. 埋点 SDK(Python):包装 OpenAI 兼容客户端,自动记录每次调用的 model、token、延迟、花费
  2. 数据接收服务(FastAPI + SQLite):把埋点数据落库,提供 REST 查询接口
  3. 可视化仪表盘(Streamlit + Plotly):实时刷新花费趋势、模型占比、TOP 10 烧钱 prompt

三、核心代码实现

3.1 埋点 SDK:自动拦截所有 OpenAI 兼容调用

这个类可以直接 import 到你现有业务代码里,无需修改调用逻辑:

import time
import sqlite3
from openai import OpenAI

HolySheep 中转配置,国内直连 < 50ms

client = OpenAI( base_url="https://api.holysheep.ai/v1", api_key="YOUR_HOLYSHEEP_API_KEY", )

2026 主流模型 output 价格(/MTok),HolySheep ¥1=$1 结算

PRICE_MAP = { "gpt-4.1": 8.00, "claude-sonnet-4.5": 15.00, "gemini-2.5-flash": 2.50, "deepseek-v3.2": 0.42, } class TokenTracker: def __init__(self, db_path="token_usage.db"): self.db_path = db_path self._init_db() def _init_db(self): with sqlite3.connect(self.db_path) as conn: conn.execute(""" CREATE TABLE IF NOT EXISTS usage ( id INTEGER PRIMARY KEY AUTOINCREMENT, ts REAL, model TEXT, user_tag TEXT, prompt_tokens INTEGER, completion_tokens INTEGER, cost_cny REAL, latency_ms REAL ) """) def record(self, model, user_tag, pt, ct, latency_ms): price = PRICE_MAP.get(model, 2.50) cost = (ct / 1_000_000) * price # 直接用 ¥ 结算 with sqlite3.connect(self.db_path) as conn: conn.execute( "INSERT INTO usage (ts, model, user_tag, prompt_tokens, completion_tokens, cost_cny, latency_ms) VALUES (?,?,?,?,?,?,?)", (time.time(), model, user_tag, pt, ct, round(cost, 6), round(latency_ms, 2)) ) return cost tracker = TokenTracker() def chat_tracked(model, messages, user_tag="default", **kwargs): start = time.perf_counter() resp = client.chat.completions.create( model=model, messages=messages, **kwargs ) latency_ms = (time.perf_counter() - start) * 1000 cost = tracker.record( model=model, user_tag=user_tag, pt=resp.usage.prompt_tokens, ct=resp.usage.completion_tokens, latency_ms=latency_ms, ) return resp, cost

业务里直接这样用,完全无感

resp, cost = chat_tracked("gpt-4.1", [{"role":"user","content":"你好"}], user_tag="contract-review") print(f"本次 ¥{cost:.4f},延迟 {resp.usage.completion_tokens} tokens")

3.2 数据接收服务:FastAPI + SQLite

如果你的服务部署在多台机器上,建议把埋点改成 HTTP 上报,统一进一个数据库:

from fastapi import FastAPI
from pydantic import BaseModel
import sqlite3, time

app = FastAPI(title="HolySheep Token 监控后端")

class UsageEvent(BaseModel):
    model: str
    user_tag: str
    prompt_tokens: int
    completion_tokens: int
    latency_ms: float

PRICE_MAP = {
    "gpt-4.1": 8.00,
    "claude-sonnet-4.5": 15.00,
    "gemini-2.5-flash": 2.50,
    "deepseek-v3.2": 0.42,
}

def init_db():
    with sqlite3.connect("usage.db") as conn:
        conn.execute("""
            CREATE TABLE IF NOT EXISTS usage (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                ts REAL, model TEXT, user_tag TEXT,
                prompt_tokens INTEGER, completion_tokens INTEGER,
                cost_cny REAL, latency_ms REAL
            )
        """)
init_db()

@app.post("/log")
async def log_usage(ev: UsageEvent):
    price = PRICE_MAP.get(ev.model, 2.50)
    cost = (ev.completion_tokens / 1_000_000) * price
    with sqlite3.connect("usage.db") as conn:
        conn.execute(
            "INSERT INTO usage VALUES (NULL,?,?,?,?,?,?,?)",
            (time.time(), ev.model, ev.user_tag,
             ev.prompt_tokens, ev.completion_tokens,
             round(cost, 6), round(ev.latency_ms, 2))
        )
    return {"cost_cny": round(cost, 6), "model": ev.model}

@app.get("/stats")
async def stats(days: int = 7, user_tag: str | None = None):
    since = time.time() - days * 86400
    sql = "SELECT model, SUM(completion_tokens), SUM(cost_cny), AVG(latency_ms), COUNT(*) FROM usage WHERE ts>?"
    params: list = [since]
    if user_tag:
        sql += " AND user_tag=?"
        params.append(user_tag)
    sql += " GROUP BY model"
    with sqlite3.connect("usage.db") as conn:
        rows = conn.execute(sql, params).fetchall()
    return {"data": [
        {"model": r[0], "tokens": r[1], "cost_cny": round(r[2], 4),
         "avg_latency_ms": round(r[3], 2), "calls": r[4]} for r in rows
    ]}

跑起来:uvicorn monitor:app --host 0.0.0.0 --port 8000,国内直连 HolySheep 整体往返基本在 80~120ms。

3.3 Streamlit 可视化仪表盘

一行命令启动:streamlit run dashboard.py

import streamlit as st
import sqlite3, pandas as pd
import plotly.express as px

st.set_page_config(page_title="HolySheep Token 仪表盘", layout="wide")
st.title("🐑 HolySheep Token 成本监控仪表盘")

conn = sqlite3.connect("usage.db")
df = pd.read_sql_query("SELECT * FROM usage ORDER BY ts DESC LIMIT 5000", conn)
conn.close()

if df.empty:
    st.info("暂无调用数据,去跑两轮 API 吧~")
    st.stop()

c1, c2, c3, c4 = st.columns(4)
c1.metric("总花费(¥)", f"{df['cost_cny'].sum():.2f}")
c2.metric("总 Completion Token", f"{int(df['completion_tokens'].sum()):,}")
c3.metric("平均延迟(ms)", f"{df['latency_ms'].mean():.1f}")
c4.metric("调用次数", f"{len(df):,}")

st.subheader("各模型花费占比")
fig1 = px.pie(df.groupby("model", as_index=False)["cost_cny"].sum(),
              values="cost_cny", names="model", hole=0.45)
st.plotly_chart(fig1, use_container_width=True)

st.subheader("近 30 天每日成本趋势")
df["date"] = pd.to_datetime(df["ts"], unit="s").dt.date
daily = df.groupby("date", as_index=False)["cost_cny"].sum()
fig2 = px.line(daily, x="date", y="cost_cny", markers=True)
st.plotly_chart(fig2, use_container_width=True)

st.subheader("按业务线 user_tag 排行")
tag_df = df.groupby("user_tag", as_index=False).agg(
    cost=("cost_cny","sum"), tokens=("completion_tokens","sum")
).sort_values("cost", ascending=False).head(10)
st.dataframe(tag_df, use_container_width=True)

四、几个落地小建议

常见报错排查

常见错误与解决方案

错误 1:流式响应拿不到 token

症状:resp.usageAttributeError。修复:

def chat_tracked_stream(model, messages, user_tag="default", **kwargs):
    start = time.perf_counter()
    stream = client.chat.completions.create(
        model=model, messages=messages, stream=True, **kwargs
    )
    pt = ct = 0
    content = []
    for chunk in stream:
        if chunk.usage:
            pt = chunk.usage.prompt_tokens
            ct = chunk.usage.completion_tokens
        if chunk.choices and chunk.choices[0].delta.content:
            content.append(chunk.choices[0].delta.content)
    latency_ms = (time.perf_counter() - start) * 1000
    cost = tracker.record(model, user_tag, pt, ct, latency_ms)
    return "".join(content), cost

错误 2:多进程写 SQLite 锁死

症状:database is locked 报错。修复:

import sqlite3, threading
from queue import Queue

_write_q = Queue()
def _writer_loop(db_path):
    conn = sqlite3.connect(db_path, check_same_thread=False)
    while True:
        sql, params = _write_q.get()
        try:
            conn.execute(sql, params); conn.commit()
        except Exception as e:
            print("write err:", e)

threading.Thread(target=_writer_loop, args=("usage.db",), daemon=True).start()

业务里只投递任务

def safe_record(model, user_tag, pt, ct, latency_ms): price = PRICE_MAP.get(model, 2.50) cost = (ct / 1_000_000) * price _write_q.put(( "INSERT INTO usage (ts,model,user_tag,prompt_tokens,completion_tokens,cost_cny,latency_ms) VALUES (?,?,?,?,?,?,?)", (time.time(), model, user_tag, pt, ct, round(cost,6), round(latency_ms,2)) )) return cost

错误 3:账单和实际余额对不上

症状:用官方价格算出来 ¥3285,用脚本算出来 ¥450,差距巨大——其实是把官方 $价直接当 ¥价算了。修复:

# ❌ 错误写法
cost = (completion_tokens / 1_000_000) * usd_price  # 当成 ¥,多算 7.3 倍

✅ 正确写法(HolySheep ¥1=$1)

cost = (completion_tokens / 1_000_000) * PRICE_MAP[model]

例如 gpt-4.1 100 万 token:¥8.00,绝不是 $8.00

五、总结

这套仪表盘我自己已经稳定跑了 4 个月,最直接的收益有三个:

  1. 砍掉了 3 个无效的 prompt 模板,每月省 ¥600+
  2. 发现 Claude Sonnet 4.5 在合同抽取任务上性价比不如 GPT-4.1,整体切到 GPT-4.1
  3. 用 HolySheep 中转,微信/支付宝就能充值,¥1=$1 实打实省下 85%+

👉 免费注册 HolySheep AI,获取首月赠额度