C# 调用 ChatGPT API 实战指南:从零开始构建智能对话应用

1次阅读
没有评论

共计 4146 个字符,预计需要花费 11 分钟才能阅读完成。

image.webp

技术背景

OpenAI 的 API 采用标准的 RESTful 接口设计,使用 Bearer Token 进行身份验证。这种认证方式简单高效,只需要在 HTTP 请求的 Authorization 头中携带你的 API Key 即可。对于 C# 开发者来说,这意味着我们需要:

C# 调用 ChatGPT API 实战指南:从零开始构建智能对话应用

  • 安全地存储和管理 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;
    });
});

延伸思考

  1. 对话上下文管理
  2. 维护对话历史
  3. 实现多轮对话
  4. 上下文窗口管理

  5. 多模态扩展

  6. 图片生成 API 调用
  7. 语音转文本
  8. 多模态输入处理

总结

通过本文介绍的方法,你可以构建一个健壮的、生产就绪的 ChatGPT API 集成方案。关键点包括使用 HttpClientFactory 管理连接、实施合理的重试策略、优化 JSON 处理以及注意各种边界情况和性能考量。

随着项目复杂度增加,你还可以考虑添加更多高级功能,如速率限制、请求批处理、更精细的错误分类处理等。希望这篇指南能帮助你快速上手并避免常见的陷阱。

正文完
 0
评论(没有评论)