
TensorZero 模型提供商架构与 Prompt Caching 支持指南从 AGENTS.md 到 cache.rs 的源码级解析【免费下载链接】tensorzeroTensorZero is an open-source LLMOps platform that unifies an LLM gateway, observability, evaluation, optimization, and experimentation.项目地址: https://gitcode.com/GitHub_Trending/te/tensorzeroTensorZero 作为一个统一 LLM 网关、可观测性、评测与优化能力的 LLMOps 平台其核心引擎tensorzero-core需要对接 OpenAI、Anthropic、AWS Bedrock、Google Gemini、DeepSeek 等数十家模型提供商而每家提供商的用量Usage与缓存Prompt Caching上报格式又各不相同。本文以 crates/tensorzero-core/src/providers/AGENTS.md 为骨架深入解析 TensorZero 如何通过独立的tensorzero-types-providerscrate 管理提供商线格式类型并以 crates/tensorzero-types-providers/src/cache.rs 作为单一事实来源统一各提供商的缓存 token 映射。读完本文你将掌握 TensorZero 提供商模块的架构分层、全部提供商缓存字段的映射关系、从 ProviderUsage 到内部 Usage 的转换链路以及为新增提供商接入缓存支持并运行 e2e 验证的完整流程。一、提供商模块的组织方式与迁移策略在 TensorZero 的源码树中所有与外部模型提供商通信的实现代码位于 crates/tensorzero-core/src/providers其中每个文件或子目录对应一个或一组提供商anthropic.rs、aws_bedrock.rs、aws_sagemaker.rs、azure.rs、deepseek.rs、dummy.rs、groq.rs、mistral.rs、openrouter.rs、tgi.rs、together.rs、vllm.rs、xai.rs、hyperbolic.rs、sglang.rs目录形式的有fireworks/、gcp_vertex_gemini/、openai/以及gcp_vertex_anthropic.rs、google_ai_studio_gemini.rs等另有chat_completions.rs、aws_common.rs、helpers.rs、helpers_thinking_block.rs等公共辅助模块以及test_helpers.rs测试辅助providers/AGENTS.md 首先给出的架构约定是与模型提供商 API 通信相关的类型正在逐步迁移到一个独立的 crate——tensorzero-types-providers。其迁移原则非常明确如果你要创建新类型例如MyProviderUsage优先在tensorzero-types-providers下创建再通过 import 引用而不是直接放进tensorzero-core。这套策略的动机可以从 crate 的文档注释中读出tensorzero-types-providers是一个纯 serde 类型库只负责外部提供商 API 的线上格式类型wire format types见 crates/tensorzero-types-providers/src/lib.rs。把请求/响应的线格式类型与请求发送、流式解析、重试等运行时逻辑解耦好处是编译边界清晰改一个提供商的新字段不会牵连tensorzero-core中大量业务逻辑重编译可独立测试serde 反序列化、字段映射可以在无网关运行时环境下单独验证例如 crates/tensorzero-types-providers/src/conversions.rs 内就内嵌了大量转换单测方便未来被其他 crate 复用如tensorzero-node等绑定层。当前该 crate 的模块清单见 lib.rsaws_bedrock、cache、conversions、deepseek、fireworks、groq、mistral、openai、openrouter、serde_util、together、xai覆盖了 OpenAI 兼容系、Anthropic 系、Gemini 系、DeepSeek、Fireworks、Mistral 等主流提供商与tensorzero-core/src/providers下的实现文件一一对应。二、Prompt Caching 的单一事实来源cache.rsAGENTS.md 给出的第二条、也是最重要的架构约定是关于prompt caching 支持请参见tensorzero-types-providers/src/cache.rs。它是哪些提供商支持缓存、它们的 API 字段名是什么、如何映射到 TensorZero 内部Usage结构体的单一事实来源single source of truth。在为一个提供商新增或修改缓存 token 支持时请遵循其中的清单checklist。cache.rs自述为文档专用模块documentation-only实际缓存相关类型仍定义在各提供商模块中如openai::OpenAIPromptTokensDetails但它承载了全部映射决策的权威描述见 crates/tensorzero-types-providers/src/cache.rs。2.1 内部 Usage 的两个缓存字段TensorZero 内部统一的用量结构体Usage定义在 crates/tensorzero-types/src/usage.rs除input_tokens、output_tokens、cost外与缓存相关的字段只有两个字段含义provider_cache_read_input_tokens从缓存中读取命中的 token 数成本更低provider_cache_write_input_tokens写入缓存的 token 数可能成本更高这两个字段都声明为Optionu32且带#[serde(default, skip_serializing_if Option::is_none)]序列化时省略。它们遵循一套严格的空值语义None 该提供商不报告这一指标可能完全不支持缓存也可能支持但响应里没带Some(0) 提供商支持缓存但本次请求没有任何 token 命中缓存。这一点在Usage::zero()中体现得很清楚核心字段归零但两个缓存字段初始化为None未报告因为不是所有提供商都支持 prompt caching聚合工具函数会保留遇到的任何Some值而不是被None污染见 crates/tensorzero-types/src/usage.rs。三、各提供商的缓存字段映射全表cache.rs按提供商响应的格式族分组给出了完整的字段来源映射。下面按类别展开并结合仓库源码逐一印证。3.1 OpenAI 兼容系prompt_tokens_details.cached_tokensOpenAI、Groq、xAI、OpenRouter 都遵循 OpenAI chat completions 响应格式统一复用OpenAIPromptTokensDetails结构体。该结构体定义于 crates/tensorzero-types/src/usage.rs仅有cached_tokens: Optionu32一个字段并被 re-export 到 crates/tensorzero-types-providers/src/openai.rs 供各兼容提供商使用。提供商cache_read来源cache_write来源机制OpenAIprompt_tokens_details.cached_tokens—自动 1024 tokensGroqprompt_tokens_details.cached_tokens—自动xAIprompt_tokens_details.cached_tokens—自动OpenRouterprompt_tokens_details.cached_tokens—取决于底层提供商注意这一类提供商只报告读缓存cache_readcache_write一律为None。转换逻辑在 crates/tensorzero-types-providers/src/conversions.rsprovider_cache_read_input_tokens取自prompt_tokens_details.and_then(|d| d.cached_tokens)provider_cache_write_input_tokens恒为None。OpenAI 系转换的完整实现可对照 crates/tensorzero-types/src/usage.rs 中的FromOpenAIUsage for Usage。3.2 Anthropic 格式系显式缓存控制Anthropic 与 GCP Vertex Anthropic 使用cache_control显式标记缓存点响应中同时给出读写两个字段AWS Bedrock 使用cachePoint显式标记字段名改为驼峰式。提供商cache_read来源cache_write来源机制Anthropiccache_read_input_tokenscache_creation_input_tokens显式cache_controlGCP Vertex Anthropiccache_read_input_tokenscache_creation_input_tokens显式cache_controlAWS BedrockcacheReadInputTokenCountcacheWriteInputTokenCount显式cachePoint以 Anthropic 为例其用法结构体中的cache_creation_input_tokens与cache_read_input_tokens均为Optionu32在FromAnthropicUsage for Usage中直接一对一映射provider_cache_read_input_tokens cache_read_input_tokens、provider_cache_write_input_tokens cache_creation_input_tokens见 crates/tensorzero-core/src/providers/anthropic.rs。同文件内还有大量针对该映射的单测如cache_creation_input_tokens: Some(100)与cache_read_input_tokens: Some(200)映射到内部两个字段的断言见 anthropic.rs并且严格区分了Some(0)与None两种语义见 anthropic.rs。AWS Bedrock 的线格式类型定义在 crates/tensorzero-types-providers/src/aws_bedrock.rs字段为cache_read_input_tokens/cache_write_input_tokensOptioni32经 serde 驼峰化后即文档表格中的cacheReadInputTokenCount/cacheWriteInputTokenCount在 crates/tensorzero-core/src/providers/aws_bedrock.rs 的转换中同样映射到内部Usage的读写字段非流式与流式分支均有对应处理。3.3 Google Gemini 系cachedContentTokenCount提供商cache_read来源cache_write来源机制GCP Vertex GeminiusageMetadata.cachedContentTokenCount—隐式2.5/ 显式CachedContent APIGoogle AI Studio GeminiusageMetadata.cachedContentTokenCount—隐式2.5/ 显式CachedContent APIGemini 系只报告 cache_read不报告 cache_write。源码注释印证了这一字段名GCP Vertex Gemini 的实现注释写明Gemini 将缓存内容 token 报告为cachedContentTokenCount见 crates/tensorzero-core/src/providers/gcp_vertex_gemini/mod.rsGoogle AI Studio 的实现注释也完全一致见 crates/tensorzero-core/src/providers/google_ai_studio_gemini.rs。cache.rs还特别记录了一个重要的现实差异截至文档标注的 2026 年 3 月GCP Vertex Geminiaiplatform.googleapis.com在缓存命中时会返回cachedContentTokenCount但只是机会性opportunistically返回——即使 prompt 完全相同也不保证一定出现Google AI Studiogenerativelanguage.googleapis.com完全不会返回该字段两个提供商都能在字段存在时正确解析它。这一提示对依赖 Gemini 缓存指标做成本核算的用户至关重要字段缺失不代表缓存未生效只是提供商未上报。3.4 DeepSeek独特的顶层字段格式DeepSeek 不使用 OpenAI 的prompt_tokens_details而是在 usage 顶层直接暴露两个缓存字段提供商cache_read来源cache_write来源机制DeepSeekprompt_cache_hit_tokensprompt_cache_miss_tokens自动对应的线格式类型DeepSeekUsage定义在 crates/tensorzero-types-providers/src/deepseek.rs其文档注释明确指出DeepSeek 的 usage 使用顶层prompt_cache_hit_tokens和prompt_cache_miss_tokens而不是标准的 OpenAIprompt_tokens_details.cached_tokens。字段语义上prompt_cache_hit_tokens是从自动缓存中读取的 tokenprompt_cache_miss_tokens是不在缓存中、将供后续请求写入的 token。转换时二者分别映射到provider_cache_read_input_tokens与provider_cache_write_input_tokens见 crates/tensorzero-types-providers/src/conversions.rs。这是全表中唯一将缓存未命中misstoken直接视为 write 来源的映射与 DeepSeek 官方计费模型一致。3.5 Fireworks缓存信息在 HTTP 响应头而非 JSON 体提供商cache_read来源cache_write来源机制FireworksHTTP 头fireworks-cached-prompt-tokens—自动Fireworks 是最特殊的映射缓存 token 数不写在 JSON body 里而是放在 HTTP 响应头fireworks-cached-prompt-tokens中。tensorzero-core中负责提取该头的函数是extract_fireworks_cached_prompt_tokens见 crates/tensorzero-core/src/providers/fireworks/mod.rs它会读取响应头并解析为Optionu32随后赋值给usage.provider_cache_read_input_tokens见 fireworks/mod.rs。该函数自带单元测试覆盖了无该头返回 None、fireworks-cached-prompt-tokens: 42解析为 Some(42)以及非法值返回 None三种场景见 fireworks/mod.rs。3.6 Mistral提供商cache_read来源cache_write来源机制Mistralprompt_tokens_details.cached_tokens—自动Mistral 走 OpenAI 兼容格式复用OpenAIPromptTokensDetails只报告 cache_read。3.7 尚未在 JSON 响应中暴露缓存的提供商提供商说明Together透明后端缓存响应中无 token 计数Hyperbolic不支持 prompt cachingvLLM按 OpenAI 兼容格式解析prompt_tokens_details.cached_tokens但并非所有部署都会上报SGLang按 OpenAI 兼容格式解析prompt_tokens_details.cached_tokens但并非所有部署都会上报对于这四类提供商cache_read/cache_write通常会落到None——即便底层实际发生了缓存也因响应未暴露指标而无法统计。这一诚实上报的设计避免了把猜测数据写进观测系统。四、从 ProviderUsage 到内部 Usage 的转换链路cache.rs的映射表要落地依赖每个提供商实现的FromProviderUsage for Usage转换。这条链路在代码中分为两层线格式层tensorzero-types-providers定义各提供商响应的 serde 结构体如OpenAIUsage、DeepSeekUsage、OpenAIPromptTokensDetails只负责把 JSON 正确反序列化转换层实现FromProviderUsage for Usage把线格式字段映射进统一的内部Usage。对于 OpenAI 兼容系与 DeepSeek转换集中在 crates/tensorzero-types-providers/src/conversions.rs且每个转换都配有单测。例如其中针对 xAI 的测试覆盖了省略prompt_tokens_details时 cache_read 应为 None与带cached_tokens时正确取值两种分支见 conversions.rs。对于 Anthropic 这类非 OpenAI 格式的提供商转换实现仍保留在tensorzero-core的提供商模块中如 anthropic.rs。从代码结构看这正是 AGENTS.md 所述逐步迁移过程中的中间状态新类型优先放入独立 crate历史实现按需迁移。五、新增提供商缓存支持的 5 步清单cache.rs为开发者提供了一份明确的操作清单见 crates/tensorzero-types-providers/src/cache.rs当需要为某个提供商接入或修改缓存 token 支持时按此顺序执行更新映射表在上文对应的分组表格中为提供商添加一行复用公共类型如果提供商使用prompt_tokens_details.cached_tokens格式直接在它的 usage 结构体中复用OpenAIPromptTokensDetails从tensorzero-types-providers导入不要重复定义实现字段映射在该提供商的FromProviderUsage for Usage实现中把线格式字段映射到provider_cache_read_input_tokens/provider_cache_write_input_tokens并遵守None不报告与Some(0)支持但零命中的语义接入 e2e 测试在 e2e 测试配置中把该提供商加入cache_input_tokens_inference列表运行缓存 token 的 e2e 测试验证跑通非流式与流式两条用例。六、e2e 如何验证缓存 token 映射缓存映射不是只靠单元测试TensorZero 还为每个提供商跑了真实的端到端验证。测试配置层面每个提供商的 e2e 测试都会定义cache_input_tokens_inference: VecE2ETestProvider字段见 crates/tensorzero-core/tests/e2e/providers/common.rs例如 OpenAI、Anthropic、Groq、xAI、Mistral、DeepSeek、Fireworks、Together、Hyperbolic、vLLM、SGLang、Azure、GCP Vertex Gemini、Google AI Studio 等都在各自测试文件中填充了该列表如 mistral.rs、deepseek.rs、fireworks.rs 等。而像 SageMaker TGI 这种输入不够大且不支持缓存的组合则显式留空并注释原因见 aws_sagemaker_tgi.rs。测试宏会把该列表注入两个用例test_cache_input_tokens_non_streaming与test_cache_input_tokens_streaming见 common.rs分别调用 commonv2/cache_input_tokens.rs 中的test_cache_input_tokens_non_streaming_with_provider与流式版本。以非流式用例为例其验证策略见 cache_input_tokens.rs非常直观两次推理共享同一大段 system promptLARGE_SYSTEM_PROMPT被内嵌进测试见 cache_input_tokens.rs但 user 消息不同以确保代理服务器记录两次独立响应第一次请求触发缓存写入cache write第二次请求命中缓存cache read断言两次请求的input_tokens都大于 4000证明缓存 token 被计入 input_tokens若未计入首次写入请求的 token 数不会这么大见 cache_input_tokens.rs 的断言注释首次请求的缓存字段只记录不硬断言——因为自动缓存类提供商OpenAI、Groq、xAI在首次写入时可能不返回prompt_tokens_details而显式缓存类提供商Anthropic、Bedrock会返回cache_write第二次请求则必须报告cache_read。测试还通过cache_control_extra_body()见 cache_input_tokens.rs按模型名注入所需的显式缓存标记Anthropic / GCP Vertex Anthropic 使用/system/0/cache_control指针注入{type: ephemeral}AWS Bedrockclaude-haiku-4-5、deepseek-r1、nova-lite-v1使用/system/-指针注入{cachePoint: {type: default}}而自动缓存的 OpenAI、Groq、xAI 不需要任何标记也能跑通测试见 cache_input_tokens.rs 的注释。七、实践要点与小结结合 AGENTS.md 与 cache.rs可以总结出 TensorZero 提供商缓存支持的三条核心实践准则以 cache.rs 为唯一权威任何关于哪个提供商支持缓存、字段叫什么、映射到哪的改动都必须先更新 crates/tensorzero-types-providers/src/cache.rs 中的映射表保证文档与实现不漂移新类型进独立 crate新建提供商相关类型一律放入tensorzero-types-providers参考 lib.rs 的模块组织并尽量复用OpenAIPromptTokensDetails这类公共线格式类型用 e2e 兜底字段映射是否正确最终以 commonv2/cache_input_tokens.rs 的非流式/流式用例为准新增提供商必须加入cache_input_tokens_inference列表并跑通验证。这套独立类型 crate 单一事实来源映射表 转换实现 e2e 验证的四层结构既保证了 TensorZero 对多提供商差异的兼容性也让新增提供商成为一项有明确清单、可验证、可追踪的工程任务。对于希望为自家私有化模型或新厂商接入 TensorZero 的开发者这份清单就是最直接的入手指南。【免费下载链接】tensorzeroTensorZero is an open-source LLMOps platform that unifies an LLM gateway, observability, evaluation, optimization, and experimentation.项目地址: https://gitcode.com/GitHub_Trending/te/tensorzero创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考