当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > AI 网关怎样记录 token 用量而不泄露提示词

AI 网关怎样记录 token 用量而不泄露提示词

来源:17golang原创 2026-11-07 23:39:35 0浏览 收藏

AI 网关既要回答“这次请求用了多少 token”,又不能把客户提示词和模型回答原样写进日志。比较稳妥的做法,是把模型调用数据和观测数据拆成两条路径:原文只在请求转发链路中短暂存在,观测链路只接收 request_id、模型、延迟、状态和 usage 等结构化字段。

记录 token 用量不等于记录提示词。网关应在模型响应边界提取 input_tokens、output_tokens、total_tokens,生成脱敏事件,再写入指标或用量账本;默认不保存 prompt、response、完整请求体和调试异常原文。

下面按一个可迁移到不同模型供应商的架构来拆解。示例使用兼容 OpenAI 风格响应的字段名,字段实际名称应以当前供应商返回值为准。

先把“能计量”和“不能落盘”分开

网关面对的不是一个简单的日志开关,而是两类不同资产:

数据用途默认处理
input_tokens、output_tokens、total_tokens成本、配额、模型对比可以进入结构化用量事件
model、provider、tenant_id、request_id路由、追查、聚合按最小必要原则保留
prompt、response、instructions业务内容不进入普通日志和 spend 账本
API key、Cookie、用户标识身份与鉴权哈希、截断或完全丢弃

这里最容易犯的错,是先把完整请求对象交给通用 logger,再尝试在日志平台里“查询时隐藏”。这已经把泄露窗口扩大到了 SDK debug 日志、异常堆栈、重试记录、缓存和第三方 callback。脱敏要发生在网关把事件交给观测后端之前。

AI 网关从请求元数据和模型 usage 生成脱敏日志与聚合账本的结构图
图1:AI 网关的 token 用量账本结构示意图;原始提示词和回答不进入普通观测存储。

在响应边界提取 usage,而不是重新猜 token 数

最可靠的计量点通常是模型响应返回 usage 的位置。网关可以读取供应商返回的输入、输出和总 token 字段,并把它们复制到内部事件;不要把提示词再送进本地 tokenizer 后当成最终账单,因为不同模型的 tokenizer、系统消息、工具调用和缓存 token 规则可能不同。

type ProviderUsage struct {
	// 这些字段来自模型供应商的响应,不保存原始文本。
	InputTokens  int64 `json:"input_tokens"`
	OutputTokens int64 `json:"output_tokens"`
	TotalTokens  int64 `json:"total_tokens"`
}

type UsageEvent struct {
	// request_id 用于关联一次逻辑请求,不能拿提示词摘要代替。
	RequestID string `json:"request_id"`
	TenantID  string `json:"tenant_id"`
	Model     string `json:"model"`
	Status    string `json:"status"`
	LatencyMS int64  `json:"latency_ms"`
	Usage     ProviderUsage `json:"usage"`
}

func buildUsageEvent(requestID, tenantID, model, status string, latencyMS int64, u ProviderUsage) UsageEvent {
	// 只组装可聚合的标量字段;prompt 和 response 不作为参数传入。
	return UsageEvent{
		RequestID: requestID,
		TenantID:  tenantID,
		Model:     model,
		Status:    status,
		LatencyMS: latencyMS,
		Usage:     u,
	}
}

如果供应商只在流结束时返回 usage,就在流关闭或收到最终事件时写入一次;不要把每个增量片段都当成一次完整调用。非流式请求也应以网关最终收到的 usage 为准,并把缺失字段标记为 unknown,而不是用一个看似精确的估算值覆盖。

脱敏事件和用量账本应该是两层

日志适合回答“哪个请求在什么时候失败”,账本适合回答“某租户在这个时间桶用了多少 token”。把二者混成一张包含请求体的明细表,会让权限和保留期变得很难管理。

// 发送到观测后端的事件只包含结构化字段,不带 messages、input 或 output。
type RedactedEvent struct {
	RequestID    string `json:"request_id"`
	TenantHash   string `json:"tenant_hash"`
	Model        string `json:"model"`
	InputTokens  int64  `json:"input_tokens"`
	OutputTokens int64  `json:"output_tokens"`
	TotalTokens  int64  `json:"total_tokens"`
	Status       string `json:"status"`
	LatencyMS    int64  `json:"latency_ms"`
	CostEstimate int64  `json:"cost_micros"`
}

func redactForLog(e RedactedEvent) map[string]any {
	// 显式列出允许外发的字段,避免未来新增字段时把原文带入日志。
	return map[string]any{
		"request_id": e.RequestID,
		"tenant_hash": e.TenantHash,
		"model": e.Model,
		"input_tokens": e.InputTokens,
		"output_tokens": e.OutputTokens,
		"total_tokens": e.TotalTokens,
		"status": e.Status,
		"latency_ms": e.LatencyMS,
		"cost_micros": e.CostEstimate,
	}
}

这里的白名单比“把字段名里含有 prompt 的键删掉”更可靠:嵌套消息、工具参数、异常上下文和自定义 metadata 都可能藏着业务文本。租户维度也不一定要原样保存,可以使用不可逆哈希或内部租户编号,并限制可查询的人员范围。

流式、重试和缓存会改变计量语义

真实网关中,token 统计最容易在边界条件下重复或缺失。建议先定义一条逻辑请求的生命周期:

  • 重试:用 request_id 表示用户发起的一次逻辑请求,用 attempt_id 表示每次供应商尝试。成本账本按实际成功或失败尝试汇总,但报表不要把一次重试误报成两次用户请求。
  • 流式响应:打开流时只记录 started,收到最终 usage 或连接失败时再写终态;连接中断不能把最后一个增量片段当作完整 output_tokens。
  • 缓存命中:命中缓存时要明确是“模型实际 token”还是“按策略估算的节省量”。两者不能共用 total_tokens 字段。
  • 错误响应:供应商拒绝、超时和网关限流都可以写 status 和 error_type,但不要把上游原始错误全文直接写入公共日志。

一个小的字段设计能避免后续争议,例如同时保留 request_count、provider_attempt_count、usage_source 和 is_cache_hit。这样财务、SRE 和产品看到的是同一套事实,但可以按不同维度聚合。

AI 网关把原始提示词与模型请求和脱敏事件分隔开的隐私边界结构图
图2:模型请求路径与观测路径的隐私边界示意图;观测后端只接收脱敏事件和聚合用量。

把权限、保留期和调试样本拆开

“日志没有 prompt”并不代表系统天然安全。仍要检查三种常被忽略的旁路:

  1. 网关进程的 debug 级别是否会打印完整请求或响应;
  2. 失败回调、重试中间件和 trace exporter 是否自动采集消息内容;
  3. 缓存键、死信队列、样本录制和人工排障工具是否复制了原始文本。

生产环境可以把数据划成三套权限:普通指标只看聚合 token;脱敏事件可由值班和成本管理员按 request_id 查询;必要的临时调试样本单独存放,设置短保留期、审批和自动删除。不要因为排障方便,就让所有开发账号都能读到第三套数据。

如果使用现成网关或观测集成,先确认它的默认日志行为、每请求覆盖开关和异常日志策略。例如 LiteLLM 的官方日志说明提供了关闭消息记录、保留 usage/cost 元数据和按请求控制脱敏的配置线索,但具体默认值和版本行为要以部署版本文档为准。

官方地址:https://docs.litellm.ai/docs/proxy/logging

上线前用一张清单判断是否真的“没泄露”

可以用下面的最小清单做设计评审:

  • 日志事件是否由允许字段白名单构造,而不是从完整请求对象复制?
  • input_tokens 和 output_tokens 是否来自供应商响应的 usage,而不是二次猜测?
  • 流式结束、重试、缓存命中和上游错误是否有独立状态与计量语义?
  • 普通日志、聚合账本、调试样本是否有不同的权限和保留期?
  • SDK debug、异常、trace、callback、缓存和队列是否都经过同一条脱敏政策?
  • 即使调用方传入“请记录原文”的 metadata,网关是否仍能强制保持默认保护?

最终的判断标准很简单:观测系统能回答“谁、何时、调用哪个模型、用了多少 token、结果怎样”,但拿不到“用户具体说了什么、模型具体回答了什么”。这就是 AI 网关记录用量与保护提示词之间比较稳定的边界。

相关问题

只保存 prompt 的哈希可以吗?可以用于去重或关联,但哈希不是脱敏万能药。短文本、低熵模板和可猜测的系统提示词仍可能被字典攻击,生产上还应限制访问和保留期。

没有 usage 字段时要不要自己计算?可以作为估算字段单独命名,例如 estimated_input_tokens,并保留估算算法与版本;不要把估算值冒充供应商最终计量。

排查单次模型质量问题怎么办?使用经过审批的短期调试样本,单独授权、加密、脱敏并自动过期;不要为了少写一套流程而打开全局 prompt logging。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
CNCF 生态怎样推进 Kubernetes 上的机器学习生命周期CNCF 生态怎样推进 Kubernetes 上的机器学习生命周期
上一篇
CNCF 生态怎样推进 Kubernetes 上的机器学习生命周期
CNCF 公告怎样看待云原生走向 AI 原生
下一篇
CNCF 公告怎样看待云原生走向 AI 原生
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    932次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    937次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1046次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1016次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    845次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码