【AI大模型接入SDK】 —— Chatgpt接入封装
🌈欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK
- 🌍博客主页:张小姐的猫~江湖背景
- 🔥所属专栏:C++项目 ~ AI大模型接入SDK
- 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏

AI大模型接入SDK

GPT-6 Astra 是 OpenAI 最新一代的旗舰模型,定位是处理“复杂、需要连续完成很多步骤”的任务。
你可以把它理解成:
- 🧠 更强的推理:适合复杂数学、科学分析、决策和研究。
- 💻 更强的编程:不仅写代码,还能理解代码库、测试和排查问题。
- 🖥️ 会操作电脑:可以使用浏览器、软件和各种工具完成实际任务,比如填表、整理资料、做网站测试等。
- 📚 更适合长任务:可以把一个大目标拆成很多步骤,持续执行,而不是每一步都要你手把手告诉它。
- 📄 办公能力更强:能够制作和处理文档、表格、演示文稿,并尽量遵循你给的模板和格式。
- 🔐 安全能力也更强:同时它的网络安全能力已经非常强,因此 OpenAI 对它增加了更严格的安全监控。
🌍Chatgpt初始化 — 头文件
ChatgptProvider .h的实现
和deepseek的头文件差不多,把类名改成ChatgptProvider 就行
主要设置apikey以及OpenAI提供的应用编程接口的根端点(所有特定地址的起点和前缀,就像是某栋楼的地址本身,URL是根端点+路径+[查询参数])。apikey需要自己到OpenAI的官网申请,OpenAI提供的API根端点是:https://api.openai.com
这里我使用的是中转站的api,所以baseurl也会不太一样
#pragma once
#include <map>
#include <string>
#include <vector>
#include <functional>
#include "LLMProvider.h"
namespace ai_chat_sdk{
class ChatgptProvider : public LLMProvider{
public:
//初始化模型
bool initModel(const std::map<std::string, std::string>& config) override;
//检查模型是否可用
bool isAvailable() const override;
//获取模型名称
std::string getModelName() const override;
//获取模型描述
std::string getModelDesc() const override;
//发送消息 —— 全量返回
std::string sendMessage(const std::vector<Message>& messages, const std::map<std::string, std::string>& requestParam) override;
//发送消息 —— 增量返回, 流式返回
std::string sendMessageStream(const std::vector<Message>& messages,
const std::map<std::string, std::string>& requestParam,
std::function<void(const std::string&, bool)> callback) override;
};
}
ChatgptProvider .cpp的实现
#include "../include/util/ChatgptProvider.h"
#include "../include/util/myLog.h"
#include "jsoncpp/json/json.h"
#include "../include/util/httplib.h"
#include <sstream>
namespace ai_chat_sdk {
//初始化模型
bool ChatgptProvider::initModel(const std::map<std::string, std::string>& config){
//初始化API Key
auto it = config.find("_apikey");
if(it == config.end()){
ERR("ChatgptProvider initModel: _apikey not found in config");
return false;
}else{
_apikey = it->second;
}
//初始化Base URL
it = config.find("_endpoint");
if(it == config.end()){
ERR("ChatgptProvider initModel: _baseurl not found in config");
return false;
}else{
_endpoint = it->second;
}
_is_available = true;
INFO("ChatgptProvider initModel success, apikey: {}, endpoint: {}", _apikey.c_str(), _endpoint.c_str());
return true;
}
//检测模型是否可用
bool ChatgptProvider::isAvailable() const{
return _is_available;
}
//获取模型名称
std::string ChatgptProvider::getModelName() const{
return "gpt-5.6-sol";
}
//获取模型描述
std::string ChatgptProvider::getModelDesc() const{
return "gpt-5.6-sol是 OpenAI 最新一代的旗舰模型,定位是处理“复杂、需要连续完成很多步骤”的任务";
}
//发送消息 —— 全量返回
std::string ChatgptProvider::sendMessage(const std::vector<Message>& messages, const std::map<std::string, std::string>& requestParam)
{
return "";
}
//发送消息 —— 流式返回
std::string ChatgptProvider::sendMessageStream(const std::vector<Message>& messages,
const std::map<std::string, std::string>& requestParam,
std::function<void(const std::string&, bool)> callback)
{
return "";
}
} //end ai_chat_sdk
🌏ChatGPT提供API
ChatCompletion的官方参数文档:https://platform.openai.com/docs/api-reference/chat/create官方提供的参数比较多,此处仅介绍部分重要参数,红色表示后续项目中需要使用字段,具体含义如下:


Baseurl:https://api.openai.com
模型名称:gpt-5.6-sol
gpt-5.6-sol 模型的聊天补全接口设置如下:
请求URL:
POST /v1/chat/completions
请求头参数:

请求体参数:

返回响应 200 ok
🔥Responses API
对于新创建的项目,官方更推荐优先使用ResponsesAPI,以使用OpenAI平台的最新功能
ChatCompletionsAPI,是传统的聊天接口,简单好用,但只能处理文本
ResponsesAPI:以事件驱动,支持多模态和复杂交互,更适合做应用级AI
以下是两种不同类型API的对比:
| 对比项 | Chat Completions API | Responses API |
|---|---|---|
| 输入 | 聊天消息数组(messages: [{role, content}]) | 统一的 input(可包含文本、音频、图像等),更灵活 |
| 输出 | 一段完整的文本回复(可流式,但只有文字) | 通过事件流(semantic events) 输出:text.delta、audio.delta、completed、tool_call 等 |
| 流式能力 | 只支持文本流式(逐字符/逐 token 返回) | 支持多模态流式(文本、语音、工具调用、结构化消息),更细粒度 |
| 多模态支持 | 主要是文本(部分模型可输入图像) | 原生支持文本、音频、图像等,能生成文字边输出语音 |
| 可控性 | 一次请求 = 一次完整回复,过程中不可中断 | 可在生成中动态打断、分支,或让模型调用工具函数 |
| 典型场景 | 聊天机器人、FAQ、简单对话系统 | AI 助理、语音对话机器人、智能办公助手、多模态应用 |
| 生活示例 | 学生在比特答疑工具上提问: 学生: 我的 oj 题整你通过这部分用例,为什么? 老师: 我先看下题目…我在看下你的代码… 你代码中比较条件写错了… 应该这么写…你先修改下试试… | 你参加一个会议,智能助理会不断抛出“事件”: •“正在讲 PPT 第 3 页了”( output_text)• “这里有个视频片段要放”( output_audio)• “我需要查一下资料”( tool_call)• “会议结束”( completed) |
因此现在官方是比较推荐在新项目中使用ResponsesAPI
🔥API测试
同样的方式在apifox上进行测试:设置请求体和请求头


测试返回的响应结构体是:
{
"id": "resp_0dc4e3eaa553dd5b016a9ec40016c887d1a0a92b5a9634e255",
"object": "response",
"created_at": 1788789760,
"status": "completed",
"background": false,
"completed_at": 1788789761,
"error": null,
"frequency_penalty": 0.0,
"incomplete_details": null,
"max_output_tokens": null,
"max_tool_calls": null,
"model": "gpt-5.6-sol",
"moderation": null,
"output": [
{
"id": "msg_0dc4e3eaa553dd5b016a9ec40135a487d1889ab21cf0786ae9",
"type": "message",
"status": "completed",
"content": [
{
"type": "output_text",
"annotations": [],
"logprobs": [],
"text": "我是 Codex,一个在你的工作区里协作的软件工程助手。我可以阅读和修改代码、运行命令和测试、排查问题、实现功能,并直接完成工程任务。"
}
],
"phase": "final_answer",
"role": "assistant"
}
],
"parallel_tool_calls": true,
...
api测试没有问题,进行下一步
🌍发送消息 - 全量返回
在向大模型提问时,模型将回答文本一次性返回
URL: /v1/chat/completions

全量返回的步骤:
- 检测模型是否可用
- 构造请求参数:模型名称、消息列表、温度值、最大token数 —
Json - 构造历史信息数组 - 把过往的回复都存进一个数组
- 对
Json对象进行序列化 - 创建HTTP客户端,设置请求头:content-type,认证方式
- 给模型发送请求,等待模型回复
- 解析模型的响应结果 —— 反序列化:按照deepseek返回的json格式组织
- 返回模型发送消息的内容
这里与DS接入有区别的是
- 最大tokens数名称变了 ——
max_input_tokens - 消息列表字段变成了
input - 设置HTTP客户端的时候,需要额外的设置一个代理
set_proxy - 发送消息时POST的请求路径要变化
bool ChatgptProvider::initModel(const std::map<std::string, std::string>& config){
//初始化API Key
auto it = config.find("_apikey");
if(it == config.end()){
ERR("ChatgptProvider initModel: _apikey not found in config");
return false;
}else{
_apikey = it->second;
}
//初始化Base URL
it = config.find("_endpoint");
if(it == config.end()){
ERR("ChatgptProvider initModel: _baseurl not found in config");
return false;
}else{
_endpoint = it->second;
}
_is_available = true;
INFO("ChatgptProvider initModel success, apikey: {}, endpoint: {}", _apikey.c_str(), _endpoint.c_str());
return true;
}
//检测模型是否可用
bool ChatgptProvider::isAvailable() const{
return _is_available;
}
//获取模型名称
std::string ChatgptProvider::getModelName() const{
return "gpt-5.6-sol";
}
//获取模型描述
std::string ChatgptProvider::getModelDesc() const{
return "gpt-5.6-sol是 OpenAI 最新一代的旗舰模型,定位是处理“复杂、需要连续完成很多步骤”的任务";
}
//发送消息 —— 全量返回
std::string ChatgptProvider::sendMessage(const std::vector<Message>& messages, const std::map<std::string, std::string>& requestParam)
{
//1.检测模型是否可用
if(!_is_available){
ERR("ChatgptProvider sendMessage: model is not available");
return "";
}
//2.构建请求参数
double temperature = 0.7;
int maxOutputParam = 2048;
if(requestParam.find("max_input_tokens") != requestParam.end()){
maxOutputParam = std::stoi(requestParam.at("max_tokens"));
}
if(requestParam.find("temperature") != requestParam.end()){
temperature = std::stod(requestParam.at("temperature"));
}
//3.构造历史信息数组
Json::Value messageArray(Json::arrayValue);
for(const auto& msg : messages){
Json::Value message;
message["role"] = msg._role;
message["content"] = msg._content;
messageArray.append(message);
}
//4.构造请求体
Json::Value requestBody;
requestBody["model"] = "codex";
requestBody["input"] = messageArray; //注意gpt这里是input
requestBody["temperature"] = temperature;
requestBody["max_output_tokens"] = maxOutputParam;
requestBody["stream"] = false; //默认是false,非流式传递
//5.序列化
Json::StreamWriterBuilder writerBuilder;
writerBuilder["indentation"] = "";
std::string requestBodyStr = Json::writeString(writerBuilder, requestBody); //工厂对象,要进行处理的Json对象
//6.创建HTTP客户端
httplib::Client client(_endpoint);
client.set_connection_timeout(30); // 30秒连接超时
client.set_read_timeout(60); // 60秒读取超时
client.set_proxy("127.0.0.1", 7890); // 设置代理
//7.设置请求头参数
httplib::Headers headers = {
{"Authorization", "Bearer " + _apikey}, //认证令牌
{"Content-Type", "application/json"} //JSON格式
};
//8.发送POST请求
httplib::Result response = client.Post("/v1/responses", headers, requestBodyStr, "application/json");
if(!response){
ERR("DeepSeekProvider sendMessage: HTTP请求失败");
return "";
}
//检测是否响应成功
if(response->status != 200)
{
ERR("ChatgptProvider sendMessage: HTTP响应失败, status: {}", response->status);
return "";
}
INFO("ChatgptProvider sendMessage: HTTP响应成功, status: {}", response->status);
INFO("ChatgptProvider sendMessage: HTTP响应体: {}", response->body);
//反序列化 模型返回的响应结果
Json::CharReaderBuilder readerBuilder;
Json::Value responseBody; //存放解析的结果
std::string errors;
std::istringstream responseStream(response->body); // 响应流,把响应体转换为字符串输入流
if(!Json::parseFromStream(readerBuilder, responseStream, &responseBody, &errors))
ERR("ChatgptProvider sendMessage: 解析HTTP响应结果失败");
return "";
}
💥重点
接下来变化比较大的点在:怎么把有效信息从返回的响应体中提取出来

解析的流程:
- 检测responseBody是否包含
"output"字段 - 检测
responseBody["output"]是否为一个Json数组 - 检测这个Json数组是否为空?
- 如果上述的条件都成立,取出
responseBody["output"][0]~ 也是一个Json对象Output- 继续检测
Output对象中是否包含"content"字段 - 检测
Output是否为Json数组 - 检测
Output是否为空? - 检测
Output是否包含"text"字段即可 - 如果上述都检测没问题,就能拿到返回的有效数据
- 继续检测
string reply = output["content"][0]["text"].asString
//从响应体中提取出返回的文本内容 - responseBody
if(responseBody.isMember("output") && responseBody["output"].isArray() && responseBody["output"].size() > 0)
{
//模型的回复刚好是output的第0个
auto output = responseBody["output"][0];
if(output.isMember("content") && output["content"].isArray() && output["content"].size() > 0 && output["content"][0].isMember("text"))
{
auto replyString = output["content"][0]["text"].asString();
INFO("ChatgptProvider sendMessage: 模型回复: {}", replyString);
return replyString;
}
}
//10.处理模型返回结构异常问题
ERR("ChatgptProvider sendMessage parse failed, errors: {}", errors);
return "";
🌍发送消息 - 全量返回测试
在之前的testLLM.cpp文件下多添加一个测试用例TEST(ChatgptProvider, sendMessage)
//Chatgpt测试
TEST(ChatgptProvider, sendMessage)
{
//实例化ChatgptProvider的对象
auto provider = std::make_shared<ai_chat_sdk::ChatgptProvider>();
ASSERT_TRUE(provider != nullptr); //不报错就是成功
std::map<std::string, std::string> modelParams;
modelParams["_apikey"] = std::getenv("CHATGPT_API_KEY");
modelParams["_endpoint"] = "https://portdan.com";
//初始化对象
provider->initModel(modelParams);
ASSERT_TRUE(provider->isAvailable()); //
//因为调用sendMessage方法需要传入参数:requestParam、message
const std::map<std::string, std::string> requestParam = {
{"temperature", "0.7"},
{"max_output_tokens", "2048"}
};
//调用sendMessage方法,发送消息
std::vector<ai_chat_sdk::Message> messages;
messages.push_back(ai_chat_sdk::Message("user", "你是谁?"));
std::string fulldata = provider->sendMessage(messages, requestParam);
ASSERT_FALSE(fulldata.empty()); //响应不为空false,就是符合预期
INFO("response: {}", fulldata);
}
首先执行下面的命令,看看是否和外网连接成功?
curl -I http://openai.com

正常来说:如果我们接入的是api访问的是我openai的官网,是需要在Linux环境下去设置代理的
- 但是我们这里接入的是中转站的
API,所以省略了配置环境这一步

🍀发送消息 - 流式返回
在发送 /v1/responses 如果在请求参数中带上 stream=true 时,表示开启流式响应。OpenAI预定义了一些事件类型,每个响应都有特定的事件类型:

一般数据格式是如下图:DeepSeek的事件类型event全是设置成message

ChatGPT的responses API的流式响应是基于事件机制的
response.create:表示响应对象创建好了response.in_progress:表示模型开始工作response.output_text.delta:表示一段段文字实时流出 — 这个事件内容是模型返回的增量数据!response.output_item.done:表示该输出块结束 — 一个输出单元结束,但output_item中,在流式过程中可能会包含多个delta字段(多个增量数据的内容)response.completed:表示整个响应结束,流式响应过程全部正式结束
可以把事件想象成大厨在做菜:
delta就是对应的一道道菜!所有的菜都上完了之后输出item.done:表示菜已经上齐了,上齐之后服务员会跟顾客说菜已经上齐对应response.completed
与DeepSeek的流式返回的重复部分如下:
//发送消息 —— 流式返回
std::string ChatgptProvider::sendMessageStream(const std::vector<Message>& messages,
const std::map<std::string, std::string>& requestParam,
std::function<void(const std::string&, bool)> callback)
{
//1.检测模型是否可用
if(!_is_available){
ERR("ChatgptProvider sendMessageStream: model is not available");
return "";
}
//2.构建请求参数
double temperature = 0.7;
int maxOutputParam = 2048;
if(requestParam.find("max_output_tokens") != requestParam.end()){
maxOutputParam = std::stoi(requestParam.at("max_output_tokens"));
}
if(requestParam.find("temperature") != requestParam.end()){
temperature = std::stod(requestParam.at("temperature"));
}
//3.构造历史信息数组
Json::Value messageArray(Json::arrayValue);
for(const auto& msg : messages){
Json::Value message;
message["role"] = msg._role;
message["content"] = msg._content;
messageArray.append(message);
}
//4.构造请求体
Json::Value requestBody;
requestBody["model"] = "gpt-5.6-sol";
requestBody["input"] = messageArray;
requestBody["temperature"] = temperature;
requestBody["max_output_tokens"] = maxOutputParam;
requestBody["stream"] = true;
//5.序列化
Json::StreamWriterBuilder writerBuilder;
writerBuilder["indentation"] = "";
std::string requestBodyStr = Json::writeString(writerBuilder, requestBody);
//6.创建HTTP客户端
httplib::Client client(_endpoint);
client.set_connection_timeout(60, 0); // 30秒连接超时
client.set_read_timeout(300, 0);
//此处不使用代理 —— 我们是中转站
//7.设置请求头
httplib::Headers headers = {
{"Authorization", "Bearer " + _apikey},
{"Content-Type", "application/json"}, //此处要加上内容类型, 因为是用send方式发送, 不再是POST中带上application/json
{"Accept", "text/event-stream"} //接受流式响应
};
//流式处理的变量
std::string buffer; //接收流式响应的数据块
bool gotError = false; //标记响应是否成功
std::string errMsg; //错误描述符
int statusCode = 0; //响应状态码
bool streamFinished = false; //标记流式响应是否结束
std::string fullResponse; //最终累计完整的响应内容
//创建请求对象 与全量返回方式不一样
httplib::Request request; //请求对象
request.method = "POST"; //请求方法
request.path = "/v1/responses"; //请求路径
request.headers = headers; //请求头
request.body = requestBodyStr;
//客户端提前准备好响应处理器
request.response_handler = [&](const httplib::Response& req){ //响应处理器
statusCode = req.status;
if(statusCode != 200){
gotError = true;
errMsg = "HTTP status code: " + std::to_string(statusCode);
return false; // 中止请求
}
return true;
};
//设置内容接收处理器
request.content_receiver = [&](const char* data, size_t datalen, size_t offset, size_t totallength)->bool{ //数据接收处理器
//提前检测响应头是否出错,如果http出错,没有必要继续处理数据
if(gotError){
return false;
}
buffer.append(data, datalen);
INFO("ChatgptProvider sendMessageStream receive data:{}", buffer);
//处理所有的流式响应数据块,注意数据块之间是\n\n分隔的
size_t pos = 0;
while(pos = buffer.find("\n\n") != std::string::npos) //找到数据块的结束符
{
std::string event = buffer.substr(0, pos);
buffer.erase(0, pos + 2); //删除已处理的数据块,变成一个新buffer
//后面补充
}
return true; //继续接收后续数据块
};
//发送请求
auto result = client.send(request);
if(!result)
{
ERR("ChatgptProvider sendMessageStream: request failed, error: {}", to_string(result.error()));
return "";
}
//确保流式操作正确结束 —— 防止出现收不到complete的情况
if(!streamFinished)
{
WARN("stream ended without response.completed");
callback("", true); //告诉用户,事件已经结束
return "";
}
return "";
}
此时这个版本还没有对事件的类型做具体的解析! 也就是只拿到 了data数据,但是数据内部是什么样的?怎么样使用这些数据还没进行处理
我们这里先简单的进行一次测试,看看测试的结果如何!
[19:55:20] [testLLM][info ] [/home/lbw/SDK/ai-model/AIModelAcessTech/SDK/src/util/ChatgptProvider.cpp:232 ]ChatgptProvider sendMessageStream receive data:event: response.created
data: {"type":"response.created","response":{"id":"resp_0c6578bda96fd936016a9ff7a24ea087d2849f5ed30b101393","object":"response","created_at":1788868519,"model":"gpt-5.6-sol","status":"in_progress","output":[],"service_tier":"auto"}}
event: response.output_item.added
data: {"item":{"content":[{"text":"","type":"output_text"}],"id":"item_16e6790121a73833f9c18d48","role":"assistant","status":"in_progress","type":"message"},"output_index":0,"sequence_number":1,"type":"response.output_item.added"}
event: response.content_part.added
data: {"content_index":0,"item_id":"item_16e6790121a73833f9c18d48","output_index":0,"part":{"annotations":[],"logprobs":[],"text":"","type":"output_text"},"sequence_number":2,"type":"response.content_part.added"}
event: response.output_text.delta
data: {"content_index":0,"delta":"我是","item_id":"item_16e6790121a73833f9c18d48","output_index":0,"sequence_number":3,"type":"response.output_text.delta"}
event: response.output_item.done
data: {"item":{"content":[{"text":"我是 Codex,一个基于 GPT-5 的编程助手。我可以协助你阅读、修改和测试代码,也能分析项目结构、定位问题并实现功能。","type":"output_text"}],"id":"item_16e6790121a73833f9c18d48","role":"assistant","status":"completed","type":"message"},"output_index":0,"sequence_number":41,"type":"response.output_item.done"}
[19:55:21] [testLLM][info ] [/home/lbw/SDK/ai-model/AIModelAcessTech/SDK/src/util/ChatgptProvider.cpp:232 ]ChatgptProvider sendMessageStream receive data:event: response.completed
data: {"type":"response.completed","response":{"id":"resp_0c6578bda96fd936016a9ff7a24ea087d2849f5ed30b101393","object":"response","created_at":1788868519,"model":"gpt-5.6-sol","status":"completed","output":[{"type":"message","id":"item_16e6790121a73833f9c18d48","role":"assistant","content":[{"type":"output_text","text":"我是 Codex,一个基于 GPT-5 的编程助手。我可以协助你阅读、修改和测试代码,也能分析项目结构、定位问题并实现功能。"}],"status":"completed"}],"usage":{"input_tokens":15122,"output_tokens":52,"total_tokens":15174,"input_tokens_details":{"cached_tokens":7488}},"service_tier":"default"},"sequence_number":42}
data: [DONE]
我们可以看到gpt返回给我们的结果格式都是:
event:xxxx
data:{....}
event:xxxx
data:{....}
...

我们截取出来的数据如上图所示,这是 SSE 数据流,不是纯 JSON
数据块是两层结构 :
- 外层是
SSE文本流:用event:和data:进行组织,事件之间用\n\n分隔 - 内层 data: 的值才是
JSON:{“content_index”:0,“delta”:“分析”,…}
SSE 事件块
↓ 按行拆分
event: response.output_text.delta → 提取 eventType
data: {"delta":"分析",...} → 提取 eventData(纯 JSON)
↓ 只把 eventData 给 Json 解析
{"delta":"分析",...} → 解析成功 → 取 delta 字段
于是代码实现如下:
//解析 event 与 data 行(SSE 格式,不是 JSON)
std::istringstream eventStream(event);
std::string eventType;
std::string eventData;
std::string line;
while(std::getline(eventStream, line)){
if(line.substr(0, 7) == "event: ")
eventType = line.substr(7);
else if(line.substr(0, 6) == "data: ")
eventData = line.substr(6);
}
走到这一步,就进一步的筛选出我们要用的字段,比如类型等于"response.output_text.delta"、"response.output_item.done"、"response.completed"等
对于response.output_text.delta类型

在上面的data数据里,我们只需要找出对应的delta即可
而对于response.output_item.done类型

一步步的解析出对应的text数据和delta数据
//只把 data 行的 JSON 字符串给 Json 解析
Json::CharReaderBuilder readerBuilder;
Json::Value chunk;
std::string errors;
std::istringstream deltaStream(eventData);
if(!Json::parseFromStream(readerBuilder, deltaStream, &chunk, &errors))
{
ERR("ChatgptProvider sendMessageStream: parse delta json failed, errors: {}", errors);
continue; // 只是一个处理失败 ,继续处理下一个数据块
}
//按照事件类型来进行分析
if(eventType == "response.output_text.delta"){ //对delta类型数据进行处理
if(chunk.isMember("delta") && chunk["delta"].isString()){
std::string delta = chunk["delta"].asString();
callback(delta, false);
}
}
else if(eventType == "response.output_item.done"){
//表示一个输出项完成了,将其完整的数据拼接到fullResponse中
if(chunk.isMember("item") && chunk["item"].isObject())
{
Json::Value item = chunk["item"];
if(item.isMember("content") && item["content"].isArray() && item["content"].size() > 0 && item["content"][0].isMember("text") && item["content"][0]["text"].isString()){
fullResponse += item["content"][0]["text"].asString();
}
}
}
else if(eventType == "response.completed"){ //对completed类型数据进行处理
streamFinished = true;
callback("", true);
return true;
}
注意在截取子串取event时的比较:与这个
"event: "进行比较,后续再做类型区分的时候,才是纯类型的比较 —— 不要把空格也截取进去类型里了(容易出错)
🍀发送消息 - 流式返回测试
#include <gtest/gtest.h>
#include "../SDK/include/util/DeepSeekProvider.h"
#include "../SDK/include/util/ChatgptProvider.h"
#include <iostream>
#include <cstdlib>
#include "../SDK/include/util/myLog.h"
//DeepSeek测试
//测试名, 测试用例名
#if 0
TEST(DeepSeekProvider, sendMessage)
{
//实例化DeepSeekProvider的对象
auto provider = std::make_shared<ai_chat_sdk::DeepSeekProvider>();
ASSERT_TRUE(provider != nullptr); //不报错就是成功
//
std::map<std::string, std::string> modelParams;
modelParams["_apikey"] = std::getenv("DEEPSEEK_API_KEY");
modelParams["_endpoint"] = "https://api.deepseek.com";
//初始化对象
provider->initModel(modelParams);
ASSERT_TRUE(provider->isAvailable()); //
//因为调用sendMessage方法需要传入参数:requestParam、message
const std::map<std::string, std::string> requestParam = {
{"temperature", "0.7"},
{"max_tokens", "2048"}
};
//调用sendMessage方法,发送消息
std::vector<ai_chat_sdk::Message> messages;
messages.push_back(ai_chat_sdk::Message("user", "你是谁?"));
std::string fulldata = provider->sendMessage(messages, requestParam);
ASSERT_FALSE(fulldata.empty()); //响应不为空false,就是符合预期
INFO("response: {}", fulldata);
}
#endif
//Chatgpt测试
TEST(ChatgptProvider, sendMessage)
{
//实例化ChatgptProvider的对象
auto provider = std::make_shared<ai_chat_sdk::ChatgptProvider>();
ASSERT_TRUE(provider != nullptr); //不报错就是成功
std::map<std::string, std::string> modelParams;
modelParams["_apikey"] = std::getenv("CHATGPT_API_KEY");
modelParams["_endpoint"] = "https://portdan.com";
//初始化对象
provider->initModel(modelParams);
ASSERT_TRUE(provider->isAvailable()); //
//因为调用sendMessage方法需要传入参数:requestParam、message
const std::map<std::string, std::string> requestParam = {
{"temperature", "0.7"},
{"max_output_tokens", "2048"}
};
//调用sendMessage方法,发送消息
std::vector<ai_chat_sdk::Message> messages;
messages.push_back(ai_chat_sdk::Message("user", "你是谁?"));
//全量返回测试
// std::string fulldata = provider->sendMessage(messages, requestParam);
//流式响应
auto writechunk = [&](const std::string& chunk, bool last) {
INFO("chunk: {}", chunk);
if (last) {
INFO("[Done]");
}
};
std::string fulldata = provider->sendMessageStream(messages, requestParam, writechunk);
ASSERT_FALSE(fulldata.empty()); //期待响应是false,如果fulldata是有数据的,没问题;反之数据为空会导致测试失败,报错
INFO("response: {}", fulldata);
}
int main(int argc, char** argv)
{
//初始化日志库 —— 因为DeepSeekProvider.cpp 中使用了日志库
bite::Logger::initLogger("testLLM", "stdout", spdlog::level::level_enum::debug);
//初始化Google Test
testing::InitGoogleTest(&argc, argv);
//运行所有测试用例
return RUN_ALL_TESTS();
}
看看测试效果如何——

📢写在最后
接下来登场的是 接入Gemini

更多推荐




所有评论(0)