当前位置: 首页 > news >正文

LiteLLM 实现 Claude Code 与 Azure OpenAI 无缝对接

1. 为什么非得用 LiteLLM 做这层“翻译官”?——直击 Claude Code 对接 Azure OpenAI 的真实堵点

你装好了 Claude Code,打开设置,想把后端模型换成自己 Azure 账户里已部署的gpt-4ogpt-35-turbo,结果卡在“API Endpoint”那一栏,反复试了十几种格式:https://your-resource.openai.azure.com/https://your-resource.openai.azure.com/openai/deployments/your-deployment/chat/completions?api-version=2024-06-01、甚至加了/v1后缀……全报错:“Invalid URL”、“Connection refused”、“Unauthorized”。不是 401 就是 404,再或者直接弹窗提示“Failed to fetch models”。

这不是你配置错了,而是根本性协议错位。

Claude Code(注意,不是 Anthropic 的 Claude,而是那个基于 VS Code 衍生、主打本地 AI 编程助手的开源项目)原生只认一种 API 格式:标准 OpenAI v1 接口规范。它发请求时,Header 里写的是Authorization: Bearer sk-xxx,Body 里是{ "model": "gpt-4", "messages": [...] },期待返回的 JSON 结构里必须有choices[0].message.content字段。而 Azure OpenAI 的接口,虽然也自称“兼容 OpenAI”,但骨子里是另一套逻辑:它要求 Header 里带api-key,URL 路径里必须硬编码 deployment name 和 api-version,返回体里choices[0].message.content是有的,但外层还裹着一层idcreatedobject等字段,且object值是chat.completion而非chat.completion(注意大小写差异,某些旧版 SDK 会校验这个)。更致命的是,Azure 的 endpoint 不接受model字段作为请求体参数——它只认 URL 路径里的 deployment name。

这就形成了一个经典“鸡生蛋还是蛋生鸡”的困境:Claude Code 说“我只吃标准 OpenAI 饭”,Azure 说“我只做 Azure 特供餐,不换盘子”。双方都“没错”,但就是无法坐上同一张饭桌。

LiteLLM 就是那个端着托盘、现场改菜、还能把两套餐具无缝切换的资深服务员。它不修改任何一方代码,只在中间加一层轻量级代理服务。你告诉 LiteLLM:“我后端有 Azure 的gpt-4o,部署名是my-gpt4o,key 是xxx,endpoint 是https://xxx.openai.azure.com/”,LiteLLM 就立刻给自己注册一个虚拟模型azure/gpt-4o。然后,当 Claude Code 发来一个标准 OpenAI 请求(POST /v1/chat/completions,model: "gpt-4o")时,LiteLLM 接住它,瞬间完成三步操作:

  1. model: "gpt-4o"替换成 Azure 实际需要的 deployment namemy-gpt4o
  2. Authorization: Bearer sk-xxx拆解,转成api-key: xxx放进 Header;
  3. 把 URL 重写为https://xxx.openai.azure.com/openai/deployments/my-gpt4o/chat/completions?api-version=2024-06-01,并确保返回体结构完全符合 OpenAI v1 规范。

整个过程对 Claude Code 透明,它以为自己真连上了 OpenAI 官方服务器;对 Azure 也透明,它收到的是一个完全合规的、带正确 deployment 和 key 的请求。LiteLLM 不是网关,不是反向代理,它是一个语义翻译器 + 协议适配器。这才是“丝滑对接”的底层逻辑——不是强行拉郎配,而是让双方在各自熟悉的语言体系里,自然对话。

提示:很多教程直接让你用 Nginx 做反向代理,这是典型误区。Nginx 只能转发 URL 和 Header,无法动态解析、改写请求体(Body)里的model字段,也无法根据model名称智能路由到不同 Azure deployment。它只能做“管道工”,而 LiteLLM 是“翻译官+调度员”。

2. 从零启动 LiteLLM 代理服务:避开 WSL、Docker、环境变量的三重陷阱

现在明确目标:在你本机(Windows/macOS/Linux)跑起一个 LiteLLM 服务,监听http://localhost:4000,让它成为 Claude Code 和 Azure 之间的唯一桥梁。很多人卡在这一步,不是因为命令不会敲,而是掉进了三个隐蔽极深的坑。

2.1 陷阱一:WSL 用户的 localhost “幻觉”

如果你用的是 Windows + WSL2(绝大多数开发者现状),执行litellm --model azure/gpt-4o --api-key "xxx" --api-base "https://xxx.openai.azure.com/"后,终端显示LiteLLM running on http://0.0.0.0:4000,你兴冲冲打开 Claude Code,填入http://localhost:4000/v1,点击测试——失败。错误日志里赫然写着Connection refused

原因?WSL2 的网络栈是 NAT 模式,localhost在 WSL 里指向 WSL 自身,而在 Windows 主机里指向 Windows 自身。你在 WSL 里启动的 LiteLLM 监听的是 WSL 的0.0.0.0:4000,但 Windows 上的 Claude Code 根本访问不到 WSL 的localhost:4000。这不是防火墙问题,是网络命名空间隔离。

破局方案:强制绑定到 Windows 可达地址。不要用默认的0.0.0.0,改用 WSL 的 host IP。在 WSL 终端里执行:

# 获取 Windows 主机在 WSL 网络中的 IP(通常是 172.x.x.1) cat /etc/resolv.conf | grep nameserver | awk '{print $2}' # 假设输出是 172.28.16.1,则启动命令为: litellm --host 172.28.16.1 --port 4000 --model azure/gpt-4o --api-key "xxx" --api-base "https://xxx.openai.azure.com/"

然后在 Claude Code 里填http://172.28.16.1:4000/v1。实测下来,比折腾.wslconfignetsh portproxy稳定十倍。

2.2 陷阱二:Docker 镜像的“版本幻影”

看到官方文档推荐docker run -p 4000:4000 ...,你立刻拉取最新镜像ghcr.io/berriai/litellm:latest,运行后发现 Azure 模型列表为空,或调用时报Model not found。查日志,LiteLLM 启动时只加载了openaianthropic等基础模型,azureprovider 根本没注册。

根源在于:LiteLLM 的 Docker 镜像分basefull两个版本。latest标签默认指向base,它只包含最精简依赖,不包含 Azure、Google Vertex、AWS Bedrock 等云厂商的专用 SDKazureprovider 需要azure-identityazure-mgmt-authorization等包,base镜像里没有。

破局方案:明确指定full镜像

docker run -d \ --name litellm-proxy \ -p 4000:4000 \ -e AZURE_API_KEY="xxx" \ -e AZURE_API_BASE="https://xxx.openai.azure.com/" \ -e AZURE_API_VERSION="2024-06-01" \ ghcr.io/berriai/litellm:full \ --model azure/gpt-4o

注意:环境变量名必须全大写,且AZURE_API_VERSION必须与你 Azure portal 里部署模型时选择的版本严格一致(新版推荐2024-06-01,旧版可能是2023-05-15),否则 Azure 会返回Unsupported api-version

2.3 陷阱三:环境变量的“作用域迷雾”

你按文档在终端里执行export AZURE_API_KEY="xxx",再运行litellm --model azure/gpt-4o,一切正常。但当你把命令写进start.sh脚本,用./start.sh运行,又报Missing API Key。或者,你用 VS Code 的终端运行成功,但用 Windows Terminal 就失败。

这是因为 Shell 环境变量只在当前 Shell 进程及其子进程中有效。./start.sh是新进程,不继承父进程的export;不同终端是独立进程,互不共享环境变量。

破局方案:用.env文件实现跨平台、跨终端统一管理。在 LiteLLM 启动目录下创建.env文件:

AZURE_API_KEY=your_actual_azure_api_key_here AZURE_API_BASE=https://your-resource-name.openai.azure.com/ AZURE_API_VERSION=2024-06-01

然后启动命令简化为:

litellm --model azure/gpt-4o --dotenv .env

LiteLLM 会自动读取.env并注入所有变量。这个文件可以 gitignore,安全又方便,无论你用 PowerShell、CMD、Bash 还是 VS Code 终端,只要在该目录下运行,就绝对生效。

3. Claude Code 的终极配置:Endpoint、Key、Model 三者如何精准咬合?

LiteLLM 服务跑起来了,curl http://localhost:4000/v1/models能返回gpt-4o列表,说明代理通了。但 Claude Code 里填什么?很多人在这里反复试错,填错一个字符就前功尽弃。我们拆解它的三个核心配置项,每个都对应一个精确的物理含义。

3.1 Endpoint:不是 URL,而是“服务入口地址”

在 Claude Code 设置里,API Endpoint这一栏,你填的不是 Azure 的地址,也不是 LiteLLM 的完整 URL,而是一个相对路径前缀。官方文档写https://api.openai.com/v1,这只是个示例。对你而言,它必须是http://<你的-litellm-host>:<端口>/v1

  • ✅ 正确示例(WSL 用户):http://172.28.16.1:4000/v1
  • ✅ 正确示例(macOS 本地):http://localhost:4000/v1
  • ❌ 错误示例:http://localhost:4000(缺/v1,Claude Code 会自动拼.../v1/chat/completions,但 LiteLLM 默认只监听/v1下的路径,根路径 404)
  • ❌ 错误示例:https://your-resource.openai.azure.com/openai/deployments/...(这是 Azure 原生地址,绕过 LiteLLM,必然失败)

关键点:Claude Code 的Endpoint是它发起请求的“基地”,所有请求都会以这个地址为根,拼上/v1/chat/completions/v1/models等后缀。LiteLLM 的/v1路由必须与之严格匹配。

3.2 API Key:一个被严重误解的“占位符”

API Key这一栏,在 Claude Code 里看似要填真实密钥,但在 LiteLLM 代理模式下,它只是一个“通行令牌”,可以是任意字符串。LiteLLM 默认开启--no-secure模式(即不校验传入的 key),它只关心你请求里model字段的值,然后去自己配置的后端列表里找对应模型。

所以,你可以填sk-123mykey、甚至留空(如果 LiteLLM 启动时加了--no-secure参数)。但为了符合 Claude Code 的 UI 逻辑和未来扩展性(比如你以后想加多模型轮询),强烈建议填一个有意义的、与你 Azure 模型强关联的字符串,例如azure-gpt4o-prod。这样,当你在 LiteLLM 日志里看到model=azure-gpt4o-prod,就能立刻知道流量走向。

注意:这个 key绝不等于你 Azure 的AZURE_API_KEY。后者是 LiteLLM 用来调用 Azure 的密钥,存在.env里,对 Claude Code 完全不可见。前者只是 Claude Code 发给 LiteLLM 的一个“标签”,用于 LiteLLM 内部路由决策(如果你配置了多个后端模型)。

3.3 Model Name:Claude Code 的“下单菜单”,LiteLLM 的“路由指令”

Model Name是整个链路里最精妙的一环。Claude Code 会把这个值,原封不动地塞进请求体的model字段,发送给 LiteLLM。LiteLLM 收到后,会拿着这个字符串,去自己的模型注册表里查找。

假设你在启动 LiteLLM 时用了:

litellm --model azure/gpt-4o --model azure/gpt-35-turbo

那么 LiteLLM 内部就注册了两个虚拟模型:azure/gpt-4oazure/gpt-35-turbo。此时,Claude Code 的Model Name必须填azure/gpt-4o,才能命中 Azure 的gpt-4o。填gpt-4o不行,填azure-gpt4o也不行,必须是启动命令里--model后面写的完整字符串

这个设计带来巨大灵活性:你可以把 Azure 的gpt-4o映射为my-prod-model,把另一个测试用的gpt-35-turbo映射为my-dev-model,然后在 Claude Code 里只需切换Model Name,就完成了生产/开发环境的秒级切换,无需重启任何服务。

4. 实战排障:从日志第一行开始,定位 90% 的连接失败

即使你严格按照上述步骤配置,第一次点击“Test Connection”时,大概率还是会看到红色错误提示。别慌,LiteLLM 的日志就是你的 X 光机。我们按日志出现的顺序,逐行解读,告诉你每一行意味着什么,以及下一步该做什么。

4.1 日志起点:Starting proxy server...之后的三秒黄金窗口

LiteLLM 启动后,控制台会快速滚动几行初始化日志,然后停顿约 2-3 秒。这 3 秒,是它在后台尝试连接所有配置的后端模型(Azure、OpenAI 等)进行健康检查。如果这里卡住超过 5 秒,或者直接报错,问题一定出在 LiteLLM 到 Azure 的链路上。

典型错误日志

ERROR:litellm:Azure Exception: Authentication failed. Please check your API key and endpoint.

这表示 LiteLLM 用你.env里的AZURE_API_KEYAZURE_API_BASE去连 Azure,被拒了。99% 的原因是AZURE_API_BASE格式错误。请严格核对:

  • 必须以https://开头;
  • 必须是https://<your-resource-name>.openai.azure.com/结尾必须有/
  • 不能有多余的路径,如/openai/v1
  • AZURE_API_KEY必须是 Azure portal 里“Keys and Endpoint”页签下的KEY 1KEY 2的完整值,复制时别漏了最后几个字符。

验证方法:不用碰 Claude Code,直接用 curl 测试 LiteLLM 的健康检查:

curl -X GET "http://localhost:4000/v1/models" \ -H "Authorization: Bearer sk-123" \ -H "Content-Type: application/json"

如果返回{"object":"list","data":[...]},说明 LiteLLM 自身健康;如果返回{"error":{"message":"Authentication failed..."}},问题就在.env配置。

4.2 请求发起:Received request for model: azure/gpt-4o—— 成功的信号灯

当你在 Claude Code 里点击测试,LiteLLM 控制台会立刻打印一行:

INFO:litellm:Received request for model: azure/gpt-4o

恭喜,Claude Code 的请求已经成功抵达 LiteLLM!这行日志证明:

  • Endpoint 配置正确(网络可达);
  • Model Name 配置正确(LiteLLM 找到了注册的模型);
  • LiteLLM 的路由逻辑工作正常。

接下来,如果一切顺利,你会看到INFO:litellm:Azure call completed successfully,然后是完整的响应体。但如果卡在这里,或者紧接着报错,问题就出在 LiteLLM 到 Azure 的“最后一公里”。

典型错误日志

ERROR:litellm:Azure Exception: The request was rejected because the provided API version is invalid.

这说明AZURE_API_VERSION不匹配。登录 Azure portal,打开你的 OpenAI 资源 -> “Deployments”,点开gpt-4o部署详情,看右上角的“API version”字段,把它原样复制到.env里,重启 LiteLLM。

4.3 响应返回:Response from litellm proxy: {"object":"list","data":[...]}—— 最后的临门一脚

LiteLLM 成功拿到 Azure 的响应后,会把它转换成标准 OpenAI 格式,再发回给 Claude Code。这时,日志会显示Response from litellm proxy: ...。如果这个响应体里data数组为空,或者model字段是azure/gpt-4o而不是gpt-4o,说明 LiteLLM 的响应体转换出了问题。

根本原因:LiteLLM 的--model参数写法。如果你启动时写的是--model azure/gpt-4o,它会把 Azure 返回的model: "gpt-4o"原样透传。但 Claude Code 期望的model字段值,应该是它自己在 UI 里填的那个Model Name(即azure/gpt-4o),而不是 Azure 的原始值。这会导致 Claude Code 内部模型识别失败。

解决方案:强制覆盖响应体 model 字段。启动 LiteLLM 时,加上--set-model-name参数:

litellm --model azure/gpt-4o --set-model-name gpt-4o --dotenv .env

这样,LiteLLM 在返回给 Claude Code 之前,会把响应体里的"model": "gpt-4o"强制改成"model": "gpt-4o"(看起来一样,但这是为了确保与 Claude Code 的内部模型注册表一致)。实测下来,这是解决“Test Connection 通过但实际调用无响应”的终极钥匙。

5. 进阶实战:一个 LiteLLM 实例,同时驱动 Claude Code 和 Cursor

LiteLLM 的价值远不止于“救活一个 Claude Code”。当你把它跑起来,它就是一个可编程的 AI 模型路由中枢。我们可以用它,让同一个 Azure 账户,同时服务多个本地 AI 工具,且互不干扰。

5.1 场景还原:Claude Code 用gpt-4o,Cursor 用gpt-35-turbo

假设你有两个需求:

  • 在 Claude Code 里,专注写代码,用最强的gpt-4o
  • 在 Cursor 里,做日常聊天、文档总结,用更便宜的gpt-35-turbo

你不想开两个 LiteLLM 实例,也不想每次切换工具就改配置。目标:一个 LiteLLM,一个端口,靠Model Name自动分流。

配置步骤

  1. .env里,定义两个 Azure deployment 的完整信息:

    AZURE_API_KEY=your_main_key AZURE_API_BASE=https://your-resource.openai.azure.com/ AZURE_API_VERSION=2024-06-01 # 为 gpt-35-turbo 单独定义一个 deployment name AZURE_DEPLOYMENT_NAME_GPT35=gpt35turbo-prod # 为 gpt-4o 单独定义一个 deployment name AZURE_DEPLOYMENT_NAME_GPT4O=gpt4o-prod
  2. 启动 LiteLLM,注册两个模型,并指定各自的 deployment:

    litellm \ --model azure/gpt-4o --azure-deployment-name gpt4o-prod \ --model azure/gpt-35-turbo --azure-deployment-name gpt35turbo-prod \ --dotenv .env \ --set-model-name gpt-4o --set-model-name gpt-35-turbo

    注意:--azure-deployment-name参数必须紧跟在对应的--model后面,LiteLLM 会按顺序将它们一一绑定。

  3. 在 Claude Code 设置里,Model Nameazure/gpt-4o;在 Cursor 的设置里(Settings > AI > Provider > Custom OpenAI),Modelazure/gpt-35-turbo

原理揭秘:LiteLLM 的模型注册表是一个字典,键是--model的值(azure/gpt-4o),值是包含azure-deployment-nameapi-key等完整配置的对象。当请求进来,它先查键,再用键对应的值去调用 Azure。整个过程毫秒级,你感觉不到任何延迟。

5.2 安全加固:用 Master Key 实现“单点登录,多端授权”

上面的方案有个隐患:Claude Code 和 Cursor 的API Key都是明文填在 UI 里的,万一被截图泄露,攻击者就能用你的 LiteLLM 实例调用 Azure,产生费用。LiteLLM 提供了--master-key机制,完美解决。

操作流程

  1. 启动 LiteLLM 时,加上--master-key "sk-my-super-secret-master-key"
  2. 在 Claude Code 的API Key栏,不再填任意字符串,而是填这个 master key:sk-my-super-secret-master-key
  3. 在 Cursor 里,同样填这个 master key。

效果:LiteLLM 会校验每一个请求的AuthorizationHeader。只有持有这个 master key 的请求,才会被放行。它就像一把总钥匙,打开了 LiteLLM 这扇大门,至于进门后你想调用哪个模型(azure/gpt-4o还是azure/gpt-35-turbo),则由Model Name决定。这样,你只需要保护好这一把 master key,就守住了整个 Azure 账户的安全。

提示:master key 可以用openssl rand -hex 32生成一个 64 位随机字符串,存进.env文件,启动时用--master-key $(cat .env | grep MASTER_KEY | cut -d'=' -f2)读取,彻底避免硬编码。

5.3 效能监控:用 LiteLLM Metrics 看清每一次调用的成本

你可能关心:gpt-4o一次调用花了多少钱?今天总共调用了多少次?哪些模型最耗 token?LiteLLM 内置了 Prometheus metrics,只需加一个参数就能开启。

启动命令追加--metrics

litellm --model azure/gpt-4o --metrics --dotenv .env

然后,访问http://localhost:4000/metrics,你会看到类似这样的文本:

# HELP litellm_total_requests_total Total number of requests # TYPE litellm_total_requests_total counter litellm_total_requests_total{model="azure/gpt-4o"} 127 # HELP litellm_request_cost_total Total cost of requests (USD) # TYPE litellm_request_cost_total counter litellm_request_cost_total{model="azure/gpt-4o"} 0.0234

这些指标可以直接接入 Grafana,画出实时调用曲线、成本热力图。对于个人开发者,一个简单的curl http://localhost:4000/metrics | grep cost就能随时掌握今日开销。这才是真正“丝滑”背后的理性支撑——不盲目,不浪费,每一分算力都花在刀刃上。

http://www.cnnetsun.cn/news/3227747.html

相关文章:

  • SPT-AKI存档编辑器终极指南:5分钟掌握塔科夫离线版存档修改技巧
  • DLSS Swapper终极指南:如何一键智能切换DLSS版本,彻底释放显卡性能
  • Codex CLI工具链:本地化AI编程工作流实战指南
  • REPENTOGON终极指南:3分钟快速上手《以撒的结合》最强脚本扩展器
  • OpenClaw工作流智能体框架:生产级部署与安全加固指南
  • LangGraph StateGraph实战:从零构建可调试、可重试的智能体工作流
  • 终极指南:如何用FigmaToCode在5分钟内将设计稿变成可运行代码
  • TRAE SOLO:VS Code 深度集成的 AI 编程协作者
  • Trae本地模型代理:Go实现OpenAI协议兼容的反向代理
  • umy-ui:Vue大数据表格的虚拟滚动与高性能渲染机制解析
  • Windows本地部署OpenClaw+飞书Agent实战指南
  • 如何在Windows 10/11上直接安装Android应用:APK Installer终极指南
  • OpenCV 4.8 车牌识别实战:结合 PaddleOCR v3 实现 90%+ 准确率
  • 转型 AI 后的第一个生产系统:选型比写代码更关键
  • 机器人操作基准测试为何测不准真实能力?四大失效模式诊断
  • 基于arduino单片机超声波测距 频率可变 倒车雷达 汽车防撞报警31(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_
  • 低成本轮腿机器人控制系统架构设计:5大核心模块深度解析与性能优化
  • 全面解决macOS系统下SMAPI启动失败的3大核心方案
  • AI Agent 上下文窗口管理:对话长了,怎么自动裁剪不丢关键信息
  • 5分钟快速指南:使用DDrawCompat在现代Windows上完美运行经典DirectX游戏
  • 设备树 Overlay 机制实战详解:运行时动态加载硬件配置而不重新编译内核的方案
  • Anaconda3安装指南:Python科学计算环境搭建全解析
  • SD-PPP:Photoshop AI插件的终极指南,5分钟让设计工作流智能化
  • 蓝牙5.4音频模块与PIC32微控制器的嵌入式开发实践
  • A3908与STM32F446ZE高精度运动控制系统设计
  • Scikit-learn 1.5.2 实战:3种集成算法对比,Kaggle房价预测准确率提升5%
  • Cursor 3:从代码编辑器到开发者智能体操作系统
  • OpenClaw龙虾:面向本地化部署的AI Agent运行时框架
  • Windsurf+Flux MCP:编辑器原生AI图像生成工作流
  • MP2672A芯片与STM32的智能电池平衡系统设计