共计 4146 个字符,预计需要花费 11 分钟才能阅读完成。
技术背景
OpenAI 的 API 采用标准的 RESTful 接口设计,使用 Bearer Token 进行身份验证。这种认证方式简单高效,只需要在 HTTP 请求的 Authorization 头中携带你的 API Key 即可。对于 C# 开发者来说,这意味着我们需要:

- 安全地存储和管理 API Key
- 正确构造 HTTP 请求头
- 处理各种可能的响应状态码
核心实现
1. 使用 HttpClientFactory 实现 API 客户端
HttpClientFactory 是 .NET Core 引入的用于管理 HttpClient 生命周期的好方法。它可以:
- 避免套接字耗尽问题
- 提供中心化的配置管理
- 支持命名客户端和类型化客户端
以下是创建类型化客户端的示例:
public class OpenAIClient
{
private readonly HttpClient _httpClient;
public OpenAIClient(HttpClient httpClient)
{
_httpClient = httpClient;
_httpClient.BaseAddress = new Uri("https://api.openai.com/v1/");
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "your-api-key");
}
// 其他方法...
}
2. JSON 处理优化
System.Text.Json 是 .NET 的高性能 JSON 序列化库。相比 Newtonsoft.Json,它在处理 ChatGPT API 的请求和响应时效率更高:
var request = new ChatRequest
{
Model = "gpt-3.5-turbo",
Messages = new[] { new Message { Role = "user", Content = "Hello!"} }
};
var jsonOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
var content = JsonContent.Create(request, options: jsonOptions);
3. 实现带退避策略的重试机制
使用 Polly 库可以轻松实现复杂的重试策略:
var retryPolicy = Policy
.Handle<HttpRequestException>()
.OrResult<HttpResponseMessage>(r =>
(int)r.StatusCode >= 500 || r.StatusCode == HttpStatusCode.TooManyRequests)
.WaitAndRetryAsync(3, retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
var response = await retryPolicy.ExecuteAsync(async () =>
await _httpClient.PostAsync("chat/completions", content));
完整代码示例
对话请求封装类
public class OpenAIChatService
{
private readonly HttpClient _httpClient;
private readonly ILogger<OpenAIChatService> _logger;
public OpenAIChatService(HttpClient httpClient, ILogger<OpenAIChatService> logger)
{
_httpClient = httpClient;
_logger = logger;
}
/// <summary>
/// 发送聊天请求并获取响应
/// </summary>
/// <param name="messages"> 对话消息列表 </param>
/// <param name="model"> 模型名称 </param>
/// <param name="temperature"> 生成温度 </param>
/// <param name="maxTokens"> 最大 token 数 </param>
/// <param name="stream"> 是否启用流式响应 </param>
public async Task<ChatResponse> SendChatRequestAsync(
IEnumerable<Message> messages,
string model = "gpt-3.5-turbo",
float temperature = 0.7f,
int? maxTokens = null,
bool stream = false)
{
try
{
var request = new ChatRequest
{
Model = model,
Messages = messages.ToArray(),
Temperature = temperature,
MaxTokens = maxTokens,
Stream = stream
};
var response = await _httpClient.PostAsJsonAsync("chat/completions", request);
if (!response.IsSuccessStatusCode)
{var errorContent = await response.Content.ReadAsStringAsync();
_logger.LogError("API 请求失败: {StatusCode} - {Error}",
response.StatusCode, errorContent);
throw new OpenAIException(response.StatusCode, errorContent);
}
return await response.Content.ReadFromJsonAsync<ChatResponse>();}
catch (Exception ex)
{_logger.LogError(ex, "调用 OpenAI API 时发生异常");
throw;
}
}
}
性能优化
1. 连接池配置
在 Startup.cs 中配置 HttpClient:
services.AddHttpClient<OpenAIChatService>(client =>
{client.BaseAddress = new Uri("https://api.openai.com/v1/");
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Configuration["OpenAI:ApiKey"]);
client.DefaultRequestVersion = HttpVersion.Version20;
// 优化连接池设置
client.DefaultRequestHeaders.ConnectionClose = false;
})
.SetHandlerLifetime(TimeSpan.FromMinutes(5)); // 适当延长 Handler 生命周期
2. 响应缓存
对于相对静态的查询结果,可以添加缓存层:
services.AddMemoryCache();
// 在服务中使用
public async Task<ChatResponse> GetCachedResponseAsync(string cacheKey, Func<Task<ChatResponse>> factory)
{if (_memoryCache.TryGetValue(cacheKey, out ChatResponse cachedResponse))
return cachedResponse;
var response = await factory();
_memoryCache.Set(cacheKey, response, TimeSpan.FromMinutes(10));
return response;
}
避坑指南
1. Token 计算
- 输入的 token 数 + max_tokens 不能超过模型上限 (通常 4096)
- 中文通常 1 个 token 对应 1 - 2 个汉字
- 可以使用 OpenAI 的 tokenizer 工具预先计算
2. 异步上下文死锁
避免在 UI 线程或同步上下文中调用 .Result 或 .Wait():
// 错误示例 - 可能导致死锁
var response = _chatService.SendChatRequestAsync(messages).Result;
// 正确做法
var response = await _chatService.SendChatRequestAsync(messages);
3. 敏感信息过滤
在日志中过滤 API Key:
// 在 Startup.cs 中配置
services.AddLogging(builder =>
{builder.AddFilter((provider, category, logLevel) =>
{
if (logLevel >= LogLevel.Information &&
!string.IsNullOrEmpty(logState.ToString()) &&
logState.ToString().Contains("sk-"))
{return false;}
return true;
});
});
延伸思考
- 对话上下文管理 :
- 维护对话历史
- 实现多轮对话
-
上下文窗口管理
-
多模态扩展 :
- 图片生成 API 调用
- 语音转文本
- 多模态输入处理
总结
通过本文介绍的方法,你可以构建一个健壮的、生产就绪的 ChatGPT API 集成方案。关键点包括使用 HttpClientFactory 管理连接、实施合理的重试策略、优化 JSON 处理以及注意各种边界情况和性能考量。
随着项目复杂度增加,你还可以考虑添加更多高级功能,如速率限制、请求批处理、更精细的错误分类处理等。希望这篇指南能帮助你快速上手并避免常见的陷阱。
正文完
发表至: 未分类
近两天内
