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

AI大模型接入SDK
- [🌈欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK](#🌈欢迎来到实战项目专栏 ~~ 从零实现AI大模型接入SDK)
- 🌏前端页面
- 🌏SessionManager线程安全问题
- 🌏遇到的Bugs
- 🌏项目拓展
- 🌏项目总结
- 📢写在最后

🌏前端页面
前端页面直接让ai生成,提示词可以参考⼀下内容
假设你是一个具有十年前端的开发经验的资深工程师,请帮我按照如下要求实现一个前端页面。
我实现了一个智能聊天助手的服务器,服务器地址是192.168.100.238,端口是8080。
服务端代码以及所有接口均进行了严格的测试,没有问题。
服务器提供以下功能:
- 获取所有会话列表
- 获取可用模型
- 创建新会话
- 获取会话历史消息
- 发送消息 - 流式响应
- 删除会话
接口的请求和响应参数以json格式组织,接口具体定义如下:
1. 获取会话列表
请求URL:GET /api/sessions
返回响应:200 OK
响应格式:
json
{
"success" : "bool", // 是否成功
"message" : "string", // 结果描述
"data": [ // 响应数据
{
"id" : "string", // 会话id
"model" : "string", // 模型名称
"created_at" : "int64_t", // 会话创建时间
"updated_at" : "int64_t", // 会话更新时间
"message_count" : "int", // 对话次数
"first_user_message" : "string" // 第一条正文消息
}
]
}
2. 获取可用模型
请求URL:GET /api/models
返回响应:200 OK
响应格式:
json
{
"success" : "bool", // 是否成功
"message" : "string", // 结果描述
"data": [ // 响应数据
{
"name" : "string", // 模型名称
"desc" : "string" // 模型描述
}
]
}
3. 创建新会话
请求URL:POST /api/session
请求参数:
json
{
"model" : "string" // 模型名称
}
返回响应:200 OK
响应格式:
json
{
"success" : "bool", // 是否成功
"message" : "string", // 结果描述
"data": { // 响应数据
"session_id" : "string", // 会话id
"model" : "string" // 模型名称
}
}
4. 发送消息 - 流式响应
请求URL:POST /api/message/async
请求参数:
json
{
"session_id" : "string", // 会话id
"message" : "string" // 消息内容
}
返回响应:200 OK
流式响应,格式如下:
data: 正文\n\n
data: 正文\n\n
data: 正文\n\n
data: [DONE]
5. 删除会话
请求URL:DELETE /api/session/${session_id}
返回响应:200 OK
响应格式:
json
{
"success" : "bool", // 是否成功
"message" : "string" // 结果描述
}
6. 获取会话历史
请求URL:GET /api/session/${session_id}/history
返回响应:200 OK
响应格式:
json
{
"success" : "bool",
"message" : "string",
"data": [
{
"id" : "string",
"role" : "string",
"content" : "string",
"timestamp" : 0
}
]
}
结合以上内容帮我生成一个前端页面,类似于deepseek的网页聊天助手,页面要求如下:
-
前端页面的html、JavaScript、css等代码分开存放
-
页面左上角有一个AIChat图标,图标之后跟 "AI聊天助手" 的文本,文本之后紧跟一个按钮,按钮上文本为"新建对话",点击按钮之后,会创建新会话。
-
页面左侧栏为历史会话列表,每条会话信息展示:会话更改时间、会话第一条消息、模型名称、以及删除会话按钮,按钮文本为"...",点击删除按钮会删除该会话,同步删除服务器上session_id的会话
-
网页右侧默认为一个图标,图标下是一段文本,"选择一个历史对话继续,或创建新的对话,开启您的AI之旅",文本下是一个按钮,按钮文本是"新建对话",点击按钮会创建新会话
-
点击新建对话按钮,要弹出一个无边框窗口,窗口内部以网格方式展示所支持的模型,支持所有模型在会话中以单选按钮展示且包含模型描述,用户需要选择本次会话的模型,选择好之后点击确定按钮,本次会话就创建完成,模型选择窗口关闭;点击取消按钮则不创建会话,模型选择窗口也自动关闭。注意:每次只能选择一个模型
-
会话创建成功之后,主页面85%高度为聊天消息显示区域,消息展示区域左侧展示模型消息,右侧展示用户消息,每条消息下方紧跟消息收发时间
-
消息显示区域下方为用户输入问题的编辑框,在未输入文本时,框内提示"请输入您的消息...(Enter发送,Shift+Enter换行)",用户输入文本后提示消失,消息编辑框右侧为发送按钮,按钮下显示用户消息文本总字数/输入文本最大限制(最大限制2000字)
-
从服务器获取到index.html之后,客户端需自动到服务器获取会话列表,将会话列表信息显示在页面左侧
-
点击页面左上角和右侧偏下位置"新建对话"按钮时,需要到服务器获取支持的模型列表,用户选择模型并点击确定按钮之后,创建新会话,将该会话加入页面左侧,开始新一轮会话
-
对于流式消息,服务器返回的是标准SSE格式,比如:
data: 文本数据\n\n
data: 文本数据\n\n
data: [DONE]
对服务器返回的流式数据以markdown格式解析,代码放到代码块中语法高亮显示,代码支持一键复制
注意:服务器返回的流式数据可能会较多,避免数据过长而导致界面变形或者乱码
- 要求整个页面协调美观,颜色搭配舒适
生成提示词
生成页面

🌏SessionManager线程安全问题
通过查看vector的实现细节,我们发现容器都不是线程安全的,之前我们在实现的时候并没有考虑到,所以现在要进行修改!
cpp
//通过会话id获取会话信息
std::shared_ptr<Session> SessionManager::getSession(const std::string &sessionId) {
//先在内存中对_sessions进行查找
std::lock_guard<std::mutex> lock(_mutex); //自动加锁和解锁
auto it = _sessions.find(sessionId);
if(it != _sessions.end())
{
//获取当前会话的历史信息:从数据库中补充缺失的消息_messages
it->second->_messages = _dataManager.getMessages(sessionId);
return it->second;
}
//在内存中找不到,则从数据库中获取
auto session = _dataManager.getSession(sessionId);
if(session)
{
auto it = _sessions.find(sessionId);
if (it == _sessions.end()) { //在内存确实没有找到,将会话添加到会话列表中
_sessions[sessionId] = session; //懒加载缓存,如果不写回,下次获取时还是没有
}
//不需要从数据库中补充缺失的消息,getSession中已经获取了
return session;
}
WARN("Session not found: {}", sessionId);
return nullptr;
}
也就是要把解锁放在对容器的操作之后,而不是之前...
又发现日志打印也有可能被多个线程执行,所以此处干脆改成一个RAII的锁即可
对于SessionManager的其他函数逐个分析
generateSessionId:生成会话id,是在创建会话函数里实现的,已经在一个加锁环境里了generateMessageId:生成消息id同理,发送新消息里创建的,也已经加锁createSession:创建会话,要注意因为insertSession操作是加了锁的,所以这个函数我们手动的加锁getHistoryMessages:同上
剩余函数的逻辑都没有怎么变,只有getSession这里的线程有问题
🌏遇到的Bugs
这里遇到的bug还是挺多的:
- 没有考虑到函数的出口出错的问题等等...
Markdown格式解析- 代码块复制问题 & 模型不响应等等
通过这些bugs可以回看之前写的代码,加强了对项目的理解吧
🌏项目拓展
1️⃣可以尝试接入一下其他的大模型
2️⃣支持用户注册的功能
3️⃣支持ToolCalling,比如发送邮件、查询数据库。让大模型能够自动调用工具完成具体的事宜
🌏项目总结
1️⃣从零开始,使用C++语言接入DeepSeek-v4-flash、gemini-3.7-flash、gpt-5.6-sol 三种云端模型 ,以及通过ollama接入本地下载 的deepseek-r1:1.5b,并且将模型接入代码封装成了SDK
2️⃣利用封装好的SDK实现了一个智能聊天助手的应用
-
掌握AI相关的基础知识:大模型相关的名词、不同大模型产品的使用介绍、大模型相关岗位
-
掌握trae、apifox、cmake、ollama
-
掌握spdlog、gflags、gtest、jsoncpp、httplib等第三方库在项目中的使用
-
掌握大模型接入的思路
- 到官方申请apikey
- 查看官方文档中提供访问模型的API接口,了解接口的功能,以及熟悉接口的请求参数格式、以及响应的格式
-
使用第三方工具对接口进行快速验证:apifox、curl
- 编码开发
-
掌握单例模式、策略模式的使用
-
掌握流式响应处理,SSE数据格式,如何通过httplib库实现流式响应
-
掌握ollama工具的使用,比如如何下载模型、查看下载模型、当前运行模型,以及运行模型...
-
掌握sqlite数据的使用,以及如何使用C++代码操作sqlite数据库
-
掌握什么是SDK,如何封装SDK,SDK的安装,以及cmake文件的编写
-
掌握如何让大模型帮助我们生成代码,提示词,如何与大模型交互解决项目中的问题
📢写在最后
完结撒花

