Headroom 接入 Vertex AI:用 Proxy Passthrough 让 Gemini 与 Anthropic 发布端点获得上下文压缩
本文基于仓库文档 wiki/vertex.md 展开,说明 Headroom 如何以代理透传(passthrough)方式接入 Google Cloud Vertex AI 的 publisher 端点:如何配置区域性 Vertex 主机、Gemini 的 generateContent/streamGenerateContent/countTokens 三个动词如何原样穿过代理、Anthropic-on-Vertex 的 rawPredict/streamRawPredict 在 Python 与 Rust 两条代理路径上的认证差异,以及带 Headroom 压缩运行 Claude Code 的已验证路径。读完本文,你可以独立完成 Vertex 代理配置、用 curl 验证透传链路,并理解从路由注册到 GCP ADC 令牌解析的源码级实现。
Headroom 与 Vertex AI 的对接方式
Headroom 通过代理的 passthrough 表面支持 Vertex AI 的 publisher 端点:把代理指向某个区域的 Vertex base URL,之后所有常规的 Vertex REST 请求都经由 Headroom 转发。Google 官方文档描述 Gemini on Vertex 的生成入口为 generateContent 与 streamGenerateContent,请求体采用 Vertex/Gemini 的 contents 形状;Vertex REST 调用使用 bearer access token 认证,本地开发可用 gcloud auth print-access-token 或 gcloud auth application-default print-access-token 获取令牌,Application Default Credentials(ADC)按 GOOGLE_APPLICATION_CREDENTIALS、本地 ADC 文件、挂载的服务账号这一顺序查找凭据(细节见 Google Cloud 官方认证与模型推理参考文档)。
在源码中,这条链路的路由注册位于 headroom/providers/proxy_routes.py,五个 Vertex 端点模板都形如 /{api_version}/projects/{project}/locations/{location}/publishers/{publisher}/models/{model}:<verb>,注册时不要求预先配置上游 URL——即路由始终存在,只有 google 与 anthropic 两个 publisher 会被分发到专用处理器,其余 publisher 一律走 vertex_publisher_passthrough 原样透传。
配置:显式指定区域性 Vertex 主机
启动代理时显式设置 Vertex 区域主机:
headroom proxy --vertex-api-url https://us-central1-aiplatform.googleapis.com
同一设置也可以通过环境变量 VERTEX_TARGET_API_URL 提供。该 CLI 选项定义在 headroom/cli/proxy.py,帮助文本明确标注了其环境变量来源,选项值随后经由 provider API overrides 传入代理配置(同文件约 L1091、L1235、L1307 处可见 vertex_api_url 的传递链)。
上游目标如何从“配置值”变成“实际转发地址”,由 headroom/providers/vertex/runtime.py 中的 vertex_target_for_location 决定,规则是:
- 如果配置了
--vertex-api-url且不同于DEFAULT_VERTEX_API_URL(定义于 headroom/providers/registry.py),一律使用配置值——这允许把代理指向私有 Vertex 网关而非 Google 官方主机; - 否则按请求路径中的
location推导:global或空值映射到https://aiplatform.googleapis.com,其余区域映射为https://{location}-aiplatform.googleapis.com。
这意味着即使不传 --vertex-api-url,代理也能根据每条请求自带的 region 段自动路由到对应区域主机,多区域与 global 请求都能正确落位。
Gemini On Vertex:原样透传的 publisher 路径
把 Vertex publisher 路径直接发给代理即可,代理不会改动路径结构:
ACCESS_TOKEN="$(gcloud auth print-access-token)"
curl -sS \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
http://127.0.0.1:8787/v1/projects/PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.0-flash:generateContent \
-d '{
"contents": [
{
"role": "user",
"parts": [{"text": "Summarize this repository in one paragraph."}]
}
]
}'
代理监听的默认端口即 8787,请求携带调用方自己的 GCP bearer 令牌,Headroom 原样保留并转发。
文档列出的受支持透传动词为:
generateContentstreamGenerateContentcountTokens
对应源码里,这三个路由的注册函数分别是 vertex_generate_content、vertex_stream_generate_content 与 vertex_count_tokens(见 headroom/providers/proxy_routes.py)。对 publishers/google,请求会分发到 proxy.handle_gemini_generate_content / proxy.handle_gemini_count_tokens,并带上 VERTEX_GOOGLE_PROVIDER_NAME(即 vertex:google)标签;对其它 publisher 则退化为透传。动作常量与 force_stream 语义集中定义在 headroom/providers/vertex/runtime.py:VERTEX_GENERATE_CONTENT、VERTEX_STREAM_GENERATE_CONTENT、VERTEX_COUNT_TOKENS,以及 Anthropic 侧的 VERTEX_RAW_PREDICT、VERTEX_STREAM_RAW_PREDICT(后者 force_stream=True)。
Anthropic Publisher On Vertex:rawPredict 与 streamRawPredict
Headroom 同样转发 Vertex 上的 Anthropic publisher 调用:
rawPredictstreamRawPredict
两条代理路径的认证处理不同:
- Python 代理保留调用方自带的 Google bearer 认证,不做替换;
- 原生 Rust 代理路径会额外解析 GCP ADC 并为 Anthropic publisher 路由注入 bearer 令牌。
Rust 侧的实现集中在 crates/headroom-proxy/src/vertex/mod.rs。几个值得注意的实现事实:
- 路由解析:Vertex 路径以冒号后缀动词结尾(如
claude-3-5-sonnet@20240620:rawPredict),而 axum 的参数语法把:保留为参数符号。为此路由注册为单个捕获尾段{model_action}的参数,处理器内用split_model_action(按最后一个冒号rsplit_once)拆出模型 ID 与动词;无法解析的形状会记录vertex_path_parse_failed事件并返回 404,未识别的动词记录vertex_unknown_verb后 404,绝不静默回退到默认动词(mod.rs)。 - 请求体形状:Vertex 版 Anthropic 请求体与标准 Anthropic Messages 信封基本一致,只有两处差异——携带
anthropic_version字段(如vertex-2023-10-16)且没有model字段,模型 ID 走 URL 路径。原生命令模块会把路径中的模型 ID 合成为model字段喂给与/v1/messages相同的 live-zone Anthropic 分发器(保证块元数据查找、压缩管线一致),出站时再把合成字段剔除,因此messages、system、tools、cache_control、thinking等字段可以按字节往返(模块头注释见 mod.rs)。 - ADC 令牌解析:crates/headroom-proxy/src/vertex/adc.rs 定义了
TokenSource抽象,生产实现GcpAdcTokenSource从 ADC 提供者链(gcloud 用户凭据、GCE/GKE 元数据服务器、GOOGLE_APPLICATION_CREDENTIALS服务账号 JSON、workload-identity 等)取短时令牌,测试用StaticTokenSource。令牌在剩余寿命低于REFRESH_AHEAD_SECS(60 秒)时提前刷新,避免到期瞬间请求与上游时钟竞争;默认 OAuth scope 为https://www.googleapis.com/auth/cloud-platform。ADC 获取失败时处理器返回结构化 5xx 并记录vertex_adc_fetch_failed事件,而不是“不带令牌静默转发”——后者只会换来一个更难排查的上游 401。 - 流式:Vertex 的
streamRawPredict使用 SSE(不同于 Bedrock 的二进制 EventStream),由既有的 Anthropic 流状态机驱动遥测 tee(mod.rs)。
Python 侧对应的路由注册同样在 headroom/providers/proxy_routes.py:publishers/anthropic 的 rawPredict 分发到 proxy.handle_anthropic_messages 并带上 VERTEX_ANTHROPIC_PROVIDER_NAME(vertex:anthropic);同文件还注册了一个不带 API 版本段的路由变体,经 vertex_anthropic_target(..., versionless_route=True) 处理目标 URL(runtime.py 中该函数在 versionless 时向 base URL 追加 /v1)。
Claude Code 经 Headroom 压缩跑 Claude-on-Vertex(已验证)
wiki/vertex.md 给出的已验证短路径是:让 Claude Code 保持常规 Anthropic 模式(ANTHROPIC_BASE_URL 指向 Headroom 代理),启动代理时使用:
headroom proxy --backend litellm-vertex_ai --region <location> --code-aware
这样 Headroom 持有 GCP ADC 凭据并代为调用 Vertex,Claude Code 侧无需感知 Google 认证。
文档同时给出两条容易踩坑的要求,必须保留原文语义:
- 不要把 Claude Code 切到 Vertex 模式再把
ANTHROPIC_VERTEX_BASE_URL指向该代理。Claude Code 客户端的模型探测会拒绝任何非 Google Vertex URL,在发出请求前就报错(“model … not available on your vertex deployment”),请求根本到不了代理; - 两个易被忽略的前置条件:
pip install "google-cloud-aiplatform>=1.38"(LiteLLMvertex_aiprovider 的依赖)与--code-aware标志(代码压缩默认关闭)。缺了它们会得到 500 或tokens_saved: 0。
此外,仓库文档目录中还有一篇专门 runbook docs/content/docs/claude-code-vertex.mdx,描述的是另一种部署形态:Claude Code 以原生 Vertex 模式运行(CLAUDE_CODE_USE_VERTEX=1 + ANTHROPIC_VERTEX_PROJECT_ID + CLOUD_ML_REGION),通过 pip install headroom-ai 后执行 headroom wrap claude,由 wrapper 自动拉起代理并把 ANTHROPIC_VERTEX_BASE_URL 指向 http://127.0.0.1:8787,Claude Code 自带的 ADC 令牌被原样透传。该 runbook 还给出了验证压缩是否生效的方法:打开 http://localhost:8787/dashboard 观察 “Tokens saved” 曲线,或查看响应头 x-headroom-tokens-before、x-headroom-tokens-after、x-headroom-tokens-saved;并附带故障排查条目(CLAUDE_CODE_USE_VERTEX 未在同一 shell 导出导致流量直连 Google、CLOUD_ML_REGION 与模型可用区域不匹配导致 404、认证错误按“裸跑 Claude Code 能用则代理后也能用”判断)。两份文档描述的接入形态不同(Anthropic 模式 + LiteLLM 后端 vs 原生 Vertex 模式 + wrap),实际选型时建议以当前仓库版本中两者各自的环境要求为准,并注意 wiki 文档对“Vertex 模式直连代理”的客户端探测限制警告。
验证依据与测试入口
上述行为在仓库中有对应的测试覆盖,可作为变更或排障时的回归入口:
- tests/test_provider_proxy_routes.py、tests/test_provider_route_specs.py:路由注册与 provider 路由规格;
- tests/test_provider_vertex_runtime.py:
vertex_target_for_location等区域推导公式; - tests/test_vertex_claude_compression.py、tests/test_banner_upstream_targets.py:Vertex 上的 Claude 压缩链路与上游目标横幅;
- Rust 侧 crates/headroom-proxy/tests/integration_vertex_raw_predict.rs 与 crates/headroom-proxy/tests/e2e_simulators.rs:
rawPredict/streamRawPredict的集成与仿真端到端验证。
小结:对 Vertex 场景,Headroom 的设计原则是“路径原样、认证尊重调用方(Rust 原生路径除外,其负责 ADC 解析)、区域从请求自身推导”。配置上只需 --vertex-api-url/VERTEX_TARGET_API_URL 一个旋钮;Gemini 三动词与 Anthropic 两动词各有独立路由与处理器;Claude Code 接入则按 wiki 的已验证路径保持 Anthropic 模式并开启 --code-aware,即可在 Vertex 账单上看到实际的输入 token 下降。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00