OpenAI接口接入调试


OpenAI接口接入调试

OpenAI接口接入调试记录

完成的功能

  1. 制作基于流式传输的OpenAI接口调用工具
  2. 制作关于剧情生成的提示词

过程中遇到的问题

  1. 调用流式传输接口等待时间过长
    原因HttpCompletionOption指示HttpClient操作是在响应可利用时立即视为已完成,还是在读取包含上下文的整个答案信息之后才视为已完成,默认问HttpCompletionOption.ResponseContentRead,这会使在所有响应结束之后才视为完成,而实际只需要在响应可利用时返回,所以需要修改为HttpCompletionOption.ResponseHeadersRead
    //修改前
    //此处测试耗时基本在80s以上
    var requestTimer = Stopwatch.StartNew();
    //PostAsJsonAsync 本身不支持直接传入 HttpCompletionOption
    HttpResponseMessage httpResponseMessage = await client.PostAsJsonAsync<AIChat>("", aiChat);
    requestTimer.Stop();

    //修改后
    var requestContent = JsonContent.Create(aiChat, mediaType: new MediaTypeHeaderValue("application/json"));
    using var request = new HttpRequestMessage(HttpMethod.Post, "")
    {
        Content = requestContent,
        VersionPolicy = HttpVersionPolicy.RequestVersionExact
    };
    //此时平均响应在1s左右
    var sw = Stopwatch.StartNew();
    using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
    sw.Stop();
  1. 流式传输的底层逻辑
    所谓流式传输就是http建立socket协议之后不立即断开连接,而是按照一定的协议,在socket断开之前一直保持连接,直到服务端发送完毕,客户端接收完毕,才断开连接,即客户端会收到多次返回消息,需按约定格式一一处理
    // 持续读取流数据直到结束
    while (!reader.EndOfStream)
    {
        // 异步读取一行数据
        var line = await reader.ReadLineAsync();
        
        // 跳过空行处理
        if (string.IsNullOrEmpty(line)) continue;
        
        // 检测流结束标记
        if (line == "data: [DONE]")
        {
            Console.WriteLine("\nStream completed");
            break; // 终止循环
        }

        // 处理有效数据行(服务端返回的SSE格式数据)
        if (line.StartsWith("data: "))
        {
            try
            {
                // 提取有效JSON部分(去除开头的"data: ")
                var json = line["data: ".Length..];
                
                // 反序列化JSON为响应对象
                var responsejson = JsonSerializer.Deserialize<StreamResponse>(json);
                
                // 解析模型思考过程内容(如模型内部推理过程)
                var think = responsejson?.choices.FirstOrDefault()?.delta?.reasoning_content ?? "";
                
                // 处理思考内容输出
                if (!string.IsNullOrEmpty(think))
                {
                    // 状态切换:当开始思考时输出提示
                    if (!bThinking)
                    {
                        fileWriter.WriteLine("\nThinking...");  // 写入思考提示
                        bThinking = !bThinking;                 // 切换状态标志
                    }
                    fileWriter.Write(think);  // 持续写入思考内容
                }

                // 解析实际响应内容(模型最终输出的对话内容)
                var chunk = responsejson?.choices.FirstOrDefault()?.delta?.content ?? "";
                
                // 处理最终内容输出
                if (!string.IsNullOrEmpty(chunk))
                {
                    // 状态切换:当开始输出正式内容时输出提示
                    if (bThinking)
                    {
                        fileWriter.WriteLine("\nSay:");         // 写入内容提示
                        bThinking = !bThinking;                 // 重置状态标志
                    }
                    fileWriter.Write(chunk);  // 持续写入对话内容
                }
            }
            catch (Exception ex)
            {
                // 异常处理:输出解析错误信息(保留控制台输出用于调试)
                Console.WriteLine($"Parse error: {ex.Message}");
            }
        }
    }

未解决的问题

  1. 模型输出的文本符合json格式,但是会在json前后添加markdown的json标记,目前暂无法消除,需要进一步研究
  2. 文档中response_format可以指定模型输出json格式的内容,但是事实上模型经常输出错误的格式


已发布

分类

来自

标签: