如何调用API Management后的Azure OpenAI服务?遇401鉴权问题
问题1:404错误(chat/completions路径重复)
原因
Azure.AI.OpenAI SDK 2.x版本与1.x版本的URL构造逻辑存在差异:
- 1.x版本需要手动拼接完整的
chat/completions路径到请求URL中 - 2.x版本的SDK会自动为聊天补全请求添加
chat/completions路径后缀
如果仍按照旧版文档构造包含chat/completions的APIM URL,会导致SDK再次追加该路径,最终请求路径变为{APIM地址}/chat/completions/chat/completions,触发404错误。
解决方案
构造APIM的基础URL时,仅保留APIM实例域名+OpenAI资源前缀(无需包含chat/completions),示例格式:
https://{你的APIM实例名}.azure-api.net/openai
注:openai为APIM中配置的OpenAI后端路径前缀,需根据实际配置调整。初始化OpenAIClient时直接使用该基础URL,SDK会自动补充chat/completions路径。
问题2:401错误(订阅密钥未正确传递)
原因
Azure API Management默认要求通过Ocp-Apim-Subscription-Key请求头传递订阅密钥,而Azure.AI.OpenAI SDK 2.x默认使用api-key头传递OpenAI密钥,二者不匹配导致身份验证失败。
解决方案
提供两种可行方案,可根据实际场景选择:
方案1:修改APIM策略,兼容SDK默认的api-key头
进入APIM实例,找到目标API的「策略」配置界面,添加或调整入站策略,将api-key头的值映射到Ocp-Apim-Subscription-Key,示例策略代码:
<inbound> <base /> <choose> <when condition="@(context.Request.Headers.ContainsKey("api-key"))"> <set-header name="Ocp-Apim-Subscription-Key" exists-action="override"> <value>@(context.Request.Headers.GetValueOrDefault("api-key"))</value> </set-header> </when> </choose> </inbound>
该策略会自动将SDK发送的api-key头替换为APIM要求的Ocp-Apim-Subscription-Key头,无需修改代码即可兼容。
方案2:在SDK中自定义请求头,传递APIM订阅密钥
通过自定义HttpPipelinePolicy向请求中注入Ocp-Apim-Subscription-Key头,示例C#代码:
using Azure; using Azure.AI.OpenAI; using Azure.Core.Pipeline; // 配置参数 string apimBaseUrl = "https://{你的APIM实例名}.azure-api.net/openai"; string apimSubscriptionKey = "你的APIM订阅密钥"; string openaiApiKey = "你的OpenAI API密钥"; // 若APIM已配置后端密钥转发,可省略 var clientOptions = new OpenAIClientOptions(); // 添加自定义策略注入APIM订阅密钥 clientOptions.AddPolicy(new HttpPipelineSynchronousPolicy((message, cancellationToken) => { message.Request.Headers.Add("Ocp-Apim-Subscription-Key", apimSubscriptionKey); // 若需转发OpenAI密钥,添加api-key头 if (!string.IsNullOrEmpty(openaiApiKey)) { message.Request.Headers.Add("api-key", openaiApiKey); } return Task.CompletedTask; }, HttpPipelinePosition.PerCall)); // 初始化客户端 OpenAIClient client = new OpenAIClient(new Uri(apimBaseUrl), new AzureKeyCredential(openaiApiKey), clientOptions); // 调用聊天补全接口 var chatOptions = new ChatCompletionsOptions { DeploymentName = "你的GPT-4o部署名", // 需与APIM中配置的后端部署名一致 Messages = { new ChatMessage(ChatRole.User, "测试请求") } }; Response<ChatCompletions> response = await client.GetChatCompletionsAsync(chatOptions);
内容的提问来源于stack exchange,提问作者OfirD

