Published on

Token统计

Authors
  • avatar
    Name
    Shelton Ma
    Twitter

在调用 ChatGPT、Replicate 或自部署的大模型时,为了实现监控成本、优化性能,和添加计费机制, 需要统计用户请求和返回的 token 数量.

1. 常用统计方案

1. 使用 OpenAI API 的 usage 字段 (适用于 OpenAI GPT 模型)

OpenAI API 会自动在响应中附带 token 统计信息.

import axios from 'axios';

async function chatWithGPT(prompt: string) {
  const response = await axios.post(
    'https://api.openai.com/v1/chat/completions',
    {
      model: 'gpt-4',
      messages: [{ role: 'user', content: prompt }],
    },
    {
      headers: {
        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
        'Content-Type': 'application/json',
      },
    }
  );

  console.log('Response:', response.data.choices[0].message.content);
  console.log('Tokens used:', response.data.usage); // 统计信息
}

chatWithGPT('你好,帮我讲个笑话');

2. 使用 tiktoken (适用于 OpenAI 模型本地统计)

通过 tiktoken 计算 token 数量,适用于请求前统计,避免请求失败时丢失 token 信息.

import { encoding_for_model } from 'tiktoken';

const encoder = encoding_for_model('gpt-4'); // 模型类型

function countTokens(text: string) {
  const tokens = encoder.encode(text);
  console.log(`Token count: ${tokens.length}`);
}

countTokens('你好,帮我讲个笑话');

3. 使用 replicate API 的 meta 字段 (适用于 Replicate 平台)

Replicate 提供 meta 字段来跟踪 token 消耗或其他使用指标.

import axios from 'axios';

async function chatWithReplicate(prompt: string) {
  const response = await axios.post(
    'https://api.replicate.com/v1/predictions',
    {
      model: 'replicate/gpt-4',
      input: { prompt },
    },
    {
      headers: {
        Authorization: `Token ${process.env.REPLICATE_API_KEY}`,
        'Content-Type': 'application/json',
      },
    }
  );

  console.log('Response:', response.data.output);
  console.log('Usage info:', response.data.meta); // Token 统计
}

chatWithReplicate('帮我解释下量子力学');

4. 自我部署模型 (如 DeepSeek, Qwen 等)

在自我部署模型中,可以利用模型的 tokenizer 来手动统计 token 数量.

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen-14B")

prompt = "你好,帮我讲个笑话"
encoded = tokenizer.encode(prompt)
print(f"Token count: {len(encoded)}")

5. 流式响应统计 (Streaming Responses)

流式数据中每次 chunk 的 token 数量较难统计,但可以使用字符数估算.

import axios from 'axios';

async function chatWithStreaming(prompt: string) {
  const response = await axios.post(
    'https://api.openai.com/v1/chat/completions',
    {
      model: 'gpt-4',
      messages: [{ role: 'user', content: prompt }],
      stream: true,  // 流式响应
    },
    { responseType: 'stream' }
  );

  let totalTokens = 0;
  response.data.on('data', (chunk: Buffer) => {
    const chunkData = chunk.toString();
    totalTokens += chunkData.length; // 粗略统计
    console.log(`Received chunk: ${chunkData}`);
  });

  response.data.on('end', () => {
    console.log(`Total tokens: ${totalTokens}`);
  });
}

chatWithStreaming('告诉我一些关于宇宙的有趣事实.');

2. 同时统计用户请求和返回的所有 token 数

1. 为什么要同时统计请求和返回的 token 数?

  1. 成本控制

    • OpenAI、Replicate 等平台的费用通常按总 token 数计费(prompt_tokens + completion_tokens).
    • 统计请求和响应 token 可帮助你更精准地估算和控制成本.
  2. 性能优化

    • 请求 token 数较多时,可能会引发:
    • 响应延迟:输入较长导致模型推理时间增长.
    • 截断风险:请求或响应超过模型上限,导致意外中断.
    • 通过对请求 token 进行监控,可以动态调整输入策略.
  3. 用户行为分析

    • 请求 token 数可衡量用户提交的问题复杂度.
    • 返回 token 数可衡量模型的输出倾向(如偏好简短或冗长回答).
    • 结合这两者,能为优化模型提示词 (Prompt Engineering) 提供数据支撑.
  4. 功能完善 (如计费、速率限制)

    • 许多应用按 token 数计费.仅记录响应 token 会导致用户利用「超长输入」规避收费.
    • 通过统计请求和响应的 token,可以更准确地为用户设定配额或流量限制.
  5. 示例场景

    • 在 AI 聊天应用中,设置合理的输入长度限制,确保流畅对话.
    • 在 SaaS 平台中,为不同用户等级设定 token 配额,防止恶意滥用.
    • 在企业知识库查询系统中,结合请求 token 控制搜索深度,避免性能瓶颈.

2. 使用案例

import axios from 'axios';

async function chatWithGPT(prompt: string) {
  const response = await axios.post(
    'https://api.openai.com/v1/chat/completions',
    {
      model: 'gpt-4',
      messages: [{ role: 'user', content: prompt }],
    },
    {
      headers: {
        Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
        'Content-Type': 'application/json',
      },
    }
  );

  const { prompt_tokens, completion_tokens, total_tokens } = response.data.usage;

  console.log(`Prompt tokens: ${prompt_tokens}`);
  console.log(`Completion tokens: ${completion_tokens}`);
  console.log(`Total tokens used: ${total_tokens}`);

  if (total_tokens > 4096) {
    console.warn('⚠️ Token count exceeds safe limit, consider truncating input.');
  }
}

3. 最佳实践

  1. 请求前预估 token 数 (使用 tiktoken) 判断是否超出模型的 token 上限,避免不必要的请求失败.
  2. 请求后记录真实 token 使用量 (使用 API 的 usage 字段) 用于成本控制、用户配额管理等.
  3. 动态提示词优化 (Prompt Engineering) 若发现请求 token 数持续偏大,可优化提示词,提高 token 利用率.
  4. 流式响应需累计 token 数 对于流式数据,每个 chunk 可能仅包含少量 token,需累计统计.