前言

gpt的接入其实和deepseek的接入是类似的,也是参考官方文档进行接入。

一:大模型的初始化

大模型的初始化主要是设置模型的根端点和api key,openai提供的根端点是https://api.openai.com

//初始化模型
//这里传入的参数就是api_key 和 endpoint
bool ChatgptProvider::initModel(const std::map<std::string,std::string>& modelConfig)
{
    auto it1 = modelConfig.find("api_key");
    if(it1 == modelConfig.end())
    {
        ERR("api_key not find!");
        return false;
    }
    else
    {
        _apiKey = it1->second;
    }

    auto it2 = modelConfig.find("endpoint");
    if(it2 == modelConfig.end())
    {
        ERR("endPoint not find!");
        return false;
    }
    else
    {
        _endPoint = it2->second;
    }
    
    _isAvailable = true;
    INFO("model innit sucess!");
    return true;
}

//2. 检测模型是否有效
bool ChatgptProvider::isAvailable() const
{
    //直接返回_isAvailable就行
    return _isAvailable;
}


//4. 获取模型名称
std::string ChatgptProvider::getModelName() const
{
    return "gpt-4o-mini";
}
//5. 获取模型描述
std::string ChatgptProvider::getModelDesc() const
{
    return "我可以回答各种问题,提供建议,帮助学习新知识,或者进行有趣的对话。我的目标是为用户提供准确和有用的支持。如果你有任何问题或需要帮助,随时可以问我!";
}

二:ChatGPT的参数

ChatGPT的参数文档的地址是:https://platform.openai.com/docs/api-reference/chat/create

官方文档提供的参数十分多,我们这里只是选一些必要的参数 。。

model(string) :模型名称
message (array):历史对话,里面的参数包含了role和content字段
role(string):角色
content(string):对话
temperature(double):温度值,用来控制模型回答的准确性,默认值越低,模型回答的就越准确(有默认值)
stream(boolean):流式响应(默认未开启)
max_tokens(integer):⽣成内容的最⼤token数

请求头参数:

字段名称字段类型说明
Content-Typestring固定为 application/json
Authorizationstring认证信息,格式:Bearer {api_key}

请求体参数:

字段名称字段类型说明
modelstring使用的模型名称
messagearray历史对话列表,数组元素为 object
temperaturestring采样温度,控制随机性
max_tokensinteger生成内容的最大 token 数

Responses API

对于新创建的项⽬,官⽅更推荐优先使⽤Responses API。
官方文档:https://platform.openai.com/docs/api-reference/responses/create

Chat Completions API:是传统的聊天接,简单好⽤,但只能处理⽂本。
Responses API:以事件驱动,⽀持多模态和复杂交互,更适合做应⽤级AI。

两者的参数的区别:

对比维度Chat Completions APIResponses API
定位面向对话生成,典型是聊天机器人、客服问答面向多模态智能助理,统一承载文本、语音、图像、工具调用
输入形式messages 数组:[{ role, content }]统一的 input,可混合文本、音频、图像等,更灵活
输出形式一段完整文本(可流式,但只有文字)事件流(semantic events):text.deltaaudio.deltatool_callcompleted
流式能力仅支持文本逐 token / 逐字符返回原生支持多模态流式,粒度更细
多模态支持主要是文本(部分模型支持图像输入)原生支持文本、音频、图像,能边生成文字边输出语音
可控性一次请求 = 一次完整回复,中途不可干预生成过程中可打断、分支、调用工具
典型场景聊天机器人、FAQ、简单问答系统AI 助理、语音对话机器人、智能办公、多模态应用
生活化示例老师一次性看题、看代码、给完整解释助理像“事件驱动系统”,不断抛出状态和动作

Responses API :
URL:https://api.openai.com+/v1/responses

三:模型全量返回

代码:

//3. 发送消息给模型
//1-全量返回
std::string ChatgptProvider::sendMessage(const std::vector<Message>& message,std::map<std::string,std::string>& requestParam)
{
//检测模型是否有效
if(isAvailable() == false)
{
   ERR("model is mot available!!!");
   return "";
}
//构造请求参数,模型名称,消息列表,温度值,maxtokens数,是否开启流式响应
double temperature = 0.7;//设置一个默认模型温度值
int max_output_tokens = 2048;//设置模型回复最大token数
auto it1 = requestParam.find("temperature");
if(it1 != requestParam.end())
{
   temperature = std::stod(it1->second);
}

auto it2 = requestParam.find("max_output_tokens");
if(it2 != requestParam.end())
{
   max_output_tokens = std::stod(it2->second);
}
//构建消息列表
Json::Value messageArray(Json::arrayValue);
for(auto messages : message)
{
   Json::Value messageJson(Json::objectValue);
   messageJson["role"] = messages._role;
   messageJson["content"] = messages._content;
   messageArray.append(messageJson);
}

//构造请求体
Json::Value requestBody;
requestBody["model"] = getModelName();
requestBody["input"] = messageArray;
requestBody["temperature"] = temperature;
requestBody["max_output_tokens"] = max_output_tokens;


//序列化
Json::StreamWriterBuilder writerBuilder;
writerBuilder["indentation"] = "";
std::string requestBodyStr = Json::writeString(writerBuilder,requestBody);


//创建http客户端
httplib::Client client(_endPoint.c_str());
client.set_connection_timeout(30,0);
client.set_read_timeout(30,0);

//设置代理服务
client.set_proxy("127.0.0.1", 7890);

//设置请求头参数
httplib::Headers headers = 
{
   {"Authorization","Bearer "+ _apiKey},
   //{"Content-Type","application/json"}
};

//发送post请求
auto response = client.Post("/v1/responses",headers,requestBodyStr,"application/json");
if(!response)
{
   ERR("chatgpt response return fasle");
   return "";
}

//检测响应是否成功
if(response->status != 200)
{
   ERR("chatgpt response return fasle:{}",response->status);
   return "";
}

INFO("ChatGPTProvider API reponse body : {}",response->body);

//反序列化
Json::CharReaderBuilder reader;
std::istringstream responseStream(response->body);
std::string errorJson;
Json::Value responseJson;
if(!Json::parseFromStream(reader, responseStream , &responseJson, &errorJson))
{
   ERR("ChatProvider sendMessage parse response body failed");
   return "";
}

// 8. 从响应体中提取模型返回的消息内容
if (responseJson.isMember("output") && responseJson["output"].isArray() && !responseJson["output"].empty()) 
{
   // 模型的回复刚好是 output 数组的第 0 个元素
   auto output = responseJson["output"][0];
   
   if (output.isMember("content") && output["content"].isArray() && !output["content"].empty() && output["content"][0].isMember("text")) 
   {
       std::string replyString = output["content"][0]["text"].asString();
       INFO("ChatProvider sendMessage replyString: {}", replyString);
       return replyString;
   }
}


ERR("ChatGPTProvider sendMessage parse response body failed, errorJson: {}",errorJson);
return "";

            }

四:模型流式返回

            //2-流式返回
        std::string ChatgptProvider::sendMessagestream(const std::vector<Message>& message,
            std::map<std::string, std::string>& requestParam,
            std::function<void(const std::string&, bool)> callBack)
            {
                //判读模型是否有效
                if(!isAvailable())
                {
                    ERR("Chat GPT is not available");
                    return "";
                }

                //构造请求参数
                double temperature = 0.7;
                int max_output_tokens = 2048;
                auto it1 = requestParam.find("temperature");
                if(it1 != requestParam.end())
                {
                    temperature = std::stod(it1->second);
                }

                auto it2 = requestParam.find("max_output_tokens");
                if(it2 != requestParam.end())
                {
                    max_output_tokens = std::stod(it2->second);
                }
                //构建消息列表
                Json::Value messageArray(Json::arrayValue);
                for(auto messages : message)
                {
                    Json::Value messageJson(Json::objectValue);
                    messageJson["role"] = messages._role;
                    messageJson["content"] = messages._content;
                    messageArray.append(messageJson);
                }
                
                //构造请求体
                Json::Value requestBody;
                requestBody["model"] = getModelName();
                requestBody["input"] = messageArray;
                requestBody["temperature"] = temperature;
                requestBody["max_output_tokens"] = max_output_tokens;
                requestBody["stream"] = true;

                //序列化
                Json::StreamWriterBuilder writerBuilder;
                writerBuilder["indentation"] = "";
                std::string requestBodyStr = Json::writeString(writerBuilder,requestBody);


                //创建http客户端
                httplib::Client client(_endPoint.c_str());
                client.set_connection_timeout(30,0);
                client.set_read_timeout(30,0);
                //设置代理服务
                client.set_proxy("127.0.0.1", 7890);

                //设置请求头参数
                // 设置请求头参数
                httplib::Headers headers = 
                {
                {"Authorization", "Bearer " + _apiKey},
                {"Content-Type", "application/json"},
                {"Accept", "text/event-stream"},
                };  

                //流式处理相关变量

                std::string buffer;//用于存储当前处理的部分数据
                bool gotError = false;//是否遇到错误
                std::string errorMsg;//错误信息
                int statusCode = 0;//http状态码
                bool streamFinish = false;//fasle代表流式响应未结束
                std::string fullResponse; //用于存储完整的响应内容


                //创建请求对象
                httplib::Request request;
                request.method = "POST";
                request.path = "/v1/responses";
                request.body = requestBodyStr;
                request.headers = headers;

                //设置响应处理器
                request.response_handler = [&](const httplib::Response& res)->bool
                {
                    statusCode = res.status;
                    if(statusCode != 200)
                    {
                        gotError = true;
                        errorMsg = "ChatGPTProvider sendMessageStream POST request failed, http status code: "+std::to_string(statusCode);
                        return false; //返回false代表请求失败
                    }
                    return true; //返回true代表请求成功
                };
                

                //设置内容接受处理器
                request.content_receiver = [&](const char* data, size_t dataLength,size_t offset,size_t totalLength)->bool
                {
                    //如果http接收失败,就不用接收后面的数据
                    if(gotError)
                    {
                        return false;
                    }
                    buffer.append(data,dataLength); //将当前数据追加到缓冲区
                    INFO("ChatGPTProvider sendMessageStream content_receiver data:{}",buffer);
                    //检查是否收到完整的事件流数据
                    size_t pos = 0;
                    while((pos = buffer.find("\n\n",pos))!=std::string::npos)
                    {
                        std::string event = buffer.substr(0,pos);//提取当前事件
                        buffer.erase(0,pos+2); //删除已处理的部分

                        //解析事件类型和具体数据的位置
                        std::istringstream eventStream(event); //将事件字符串转换为流
                        std::string eventType;   //事件类型
                        std::string eventData;   //事件数据
                        std::string line; //用于存储当前行数据

                        while(std::getline(eventStream, line))
                        {
                            if(line.empty())//如果当前行为空行,跳过
                            {
                                continue;
                            }
                            if(line.compare(0,6,"event:")==0)//如果当前行为事件类型行
                            {
                                eventType = line.substr(7);//提取事件类型 //从第7个字符开始提取,因为"event:"占6个字符
                            }
                            else if(line.compare(0,5,"data:")==0)//如果当前行为事件数据行
                            {
                                eventData = line.substr(6);//提取事件数据
                            }
                        }

                        //对模型的结果进行序列化
                        Json::Value chunk;
                        Json::CharReaderBuilder reader;
                        std::string errs;
                        std::istringstream eventDataStream(eventData); //将事件数据字符串转换为流
                        //parseFromStream 尝试从流中解析JSON数据,返回false代表解析失败,true代表解析成功
                        if(!Json::parseFromStream(reader,eventDataStream,&chunk,&errs))
                        {
                            gotError = true;//标记遇到错误
                            ERR("ChatGPTProvider sendMessageStream parseFromStream failed, errorMsg: {}",errs);//记录错误信息
                            continue;//跳过当前事件,继续处理下一个事件
                        }

                        if(eventType == "response.output_text.delta")
                        {
                            if(chunk.isMember("delta")&&chunk["delta"].isString())//如果delta字段存在且是字符串类型
                            {
                                std::string delta = chunk["delta"].asString();//提取delta字段的字符串值
                                callBack(delta,false);//将delta返回给调用者,false表示不是完整响应
                            }
                        }
                        else if(eventType == "response.output_item.done")
                        {
                            if(chunk.isMember("item")&&chunk["item"].isObject())//如果item字段存在且是对象类型
                            {
                                Json::Value item = chunk["item"];//提取item字段的对象值
                                if(item.isMember("content")&&item["content"].isArray()&&!item["content"].empty()&&item["content"][0].isMember("text")&&item["content"][0]["text"].isString())
                                {
                                    fullResponse+=item["content"][0]["text"].asString();//将文本内容追加到完整响应中
                                }
                            }
                        }
                        else if(eventType == "response.completed")
                        {
                            streamFinish = true;//标记流完成
                            callBack("",true);//将完整响应返回给调用者,true表示是完整响应
                            return true;//返回成功
                        }


                    }

                    return true;//返回成功
                };

                //发送POST请求
                auto result = client.send(request);
                if(!result)
                {
                    //发送POST请求失败
                    ERR("ChatGPTProvider sendMessageStream POST request failed, error: {}",to_string(result.error()));//记录错误信息
                    return "";
                }

                //确保流完成
                if(!streamFinish)
                {
                    WARN("stream ended without response.completion.done event");//记录警告信息
                    callBack("",true);//将完整响应返回给调用者,true表示是完整响应
                    return "";
                }
                return fullResponse;//返回成功
            }
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐