【AI大模型接入SDK】ChatServer HTTP接口模块实现总览

🎬 个人主页 :艾莉丝努力练剑
❄专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》
《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:


文章目录

  • [1 ~> ChatServer HTTP接口模块实现总览](#1 ~> ChatServer HTTP接口模块实现总览)
    • [1.1 整体类结构(ChatServer.h头文件)](#1.1 整体类结构(ChatServer.h头文件))
      • [1.1.1 类成员与访问权限](#1.1.1 类成员与访问权限)
      • [1.1.2 必须引入的头文件](#1.1.2 必须引入的头文件)
    • [1.2 公共工具函数实现 buildResponse](#1.2 公共工具函数实现 buildResponse)
  • [2 ~> 各个HTTP接口业务实现](#2 ~> 各个HTTP接口业务实现)
    • [2.1 创建会话接口 handleCreateSessionRequest](#2.1 创建会话接口 handleCreateSessionRequest)
    • [2.2 获取会话列表 handleGetSessionListsRequest](#2.2 获取会话列表 handleGetSessionListsRequest)
    • [2.3 获取模型列表 handleGetModelListRequest](#2.3 获取模型列表 handleGetModelListRequest)
    • [2.4 删除会话 handleDeleteSessionRequest](#2.4 删除会话 handleDeleteSessionRequest)
    • [2.5 获取会话历史消息 handleGetHistoryMessagesRequest](#2.5 获取会话历史消息 handleGetHistoryMessagesRequest)
    • [2.6 发送消息‑全量返回 handleSendMessageRequest](#2.6 发送消息‑全量返回 handleSendMessageRequest)
  • [3 ~> SSE流式增量返回接口(核心难点)](#3 ~> SSE流式增量返回接口(核心难点))
    • [3.1 SSE协议基础概念](#3.1 SSE协议基础概念)
    • [3.2 sendMessageStreamRequest 流式发送消息实现](#3.2 sendMessageStreamRequest 流式发送消息实现)
  • [4 ~> 关键易错点汇总(面试/考试重点)](#4 ~> 关键易错点汇总(面试/考试重点))
    • [4.1 Jsoncpp库易错](#4.1 Jsoncpp库易错)
    • [4.2 httplib库易错](#4.2 httplib库易错)
    • [4.3 业务接口错误码规范](#4.3 业务接口错误码规范)
    • [4.4 代码复用优化思想](#4.4 代码复用优化思想)
    • [4.5 全量返回 vs SSE增量返回对比](#4.5 全量返回 vs SSE增量返回对比)
    • [4.6 SDK回调层原理补充](#4.6 SDK回调层原理补充)
  • 结尾


1 ~> ChatServer HTTP接口模块实现总览

基于httplib实现HTTP服务,封装AI聊天业务接口;分为头文件类声明、接口业务实现、公共工具函数、SSE流式增量返回四大模块;接口遵循REST风格,统一JSON报文格式,区分路径参数、Body请求参数;包含错误码、异常处理、代码复用抽象。

1.1 整体类结构(ChatServer.h头文件)

1.1.1 类成员与访问权限

  • public 对外接口
    • 构造:ChatServer(const ServerConfig& config);
    • 析构:~ChatServer();
    • bool start(); 启动http服务
    • void stop(); 停止http服务
    • bool isRunning() const; 查询服务运行状态
  • private 私有成员方法:HTTP请求处理器
    • 公共工具:std::string buildResponse(const std::string& message, bool success = false); 统一构造JSON响应字符串
    • void handleCreateSessionRequest(const httplib::Request& request, httplib::Response& response); 创建会话 POST /api/session
    • void handleGetSessionListsRequest(const httplib::Request& request, httplib::Response& response); 获取会话列表 GET /api/sessions
    • void handleGetModelListRequest(const httplib::Request& request, httplib::Response& response); 获取模型列表 GET /api/models
    • void handleDeleteSessionRequest(const httplib::Request& request, httplib::Response& response); 删除会话 DELETE /api/session/{session_id}
    • void handleGetHistoryMessagesRequest(const httplib::Request& request, httplib::Response& response); 获取历史消息 GET /api/session/{session_id}/history
    • void handleSendMessageRequest(const httplib::Request& request, httplib::Response& response); 发送消息全量返回 POST /api/message
    • void handleSendMessageStreamRequest(const httplib::Request& request, httplib::Response& response); 发送消息SSE增量流式返回 POST /api/message/async
  • private 私有成员变量
    • ServerConfig _config; 服务器配置
    • std::unique_ptr<httplib::Server> _chatServer{nullptr}; httplib http服务实例
    • std::shared_ptr<ai_chat_sdk::ChatSDK> _chatSDK{nullptr}; AI聊天SDK实例,完成底层模型交互
    • std::atomic<bool> _isRunning{false}; 原子布尔标记服务运行状态

1.1.2 必须引入的头文件

cpp 复制代码
#include "ChatServer.h"
#include <ai_chat_sdk/util/myLog.h>
#include <jsoncpp/json/forwards.h>
#include <jsoncpp/json/value.h>
#include <jsoncpp/json/reader.h>

1.2 公共工具函数实现 buildResponse

消除重复JSON序列化代码,统一构造success/message基础响应报文;返回序列化后的JSON字符串。

cpp 复制代码
// ChatServer.cpp
namespace ai_chat_server {

std::string ChatServer::buildResponse(const std::string& message, bool success)
{
    Json::Value responseJson;
    responseJson["success"] = success;
    responseJson["message"] = message;

    Json::StreamWriterBuilder writerBuilder;
    return Json::writeString(writerBuilder, responseJson);
}

}

2 ~> 各个HTTP接口业务实现

2.1 创建会话接口 handleCreateSessionRequest

  • 请求信息
    • URL:POST /api/session
    • 参数:http body JSON,model string 模型名称
    • 返回200;参数解析错误返回400;内部创建会话失败返回500
    • 返回JSON结构
    • { "success": true, "message": "create session success", "data": { "session_id": "string", "model": "string" } }
  • 业务执行流程
    • 获取request.body,使用Json::Reader反序列化请求体JSON;解析失败调用buildResponse返回错误,设置status=400。
    • 从json对象读取model字段,设置默认模型。
    • 调用_chatSDK->createSession(modelName)生成session_id;session_id为空代表内部错误,status=500返回错误。
    • 组装成功响应data对象,填充session_id、model;序列化json,status=200设置响应content-type为application/json。
cpp 复制代码
void ChatServer::handleCreateSessionRequest(const httplib::Request& request, httplib::Response& response)
{
    // 1.反序列化请求body
    Json::Value requestJson;
    Json::Reader reader;
    if (!reader.parse(request.body, requestJson))
    {
        std::string errStr = buildResponse("parse request body failed,json format error", false);
        response.status = 400;
        response.set_content(errStr, "application/json");
        return;
    }

    //2.读取model参数,设置默认值
    std::string modelName = requestJson.get("model", "deepseek‑chat").asString();

    //3.调用SDK创建会话
    std::string sessionID = _chatSDK->createSession(modelName);
    if (sessionID.empty())
    {
        std::string errStr = buildResponse("create session failed", false);
        response.status = 500;
        response.set_content(errStr, "application/json");
        return;
    }

    //4.组装成功返回报文
    Json::Value dataJson;
    dataJson["session_id"] = sessionID;
    dataJson["model"] = modelName;

    Json::Value respJson;
    respJson["success"] = true;
    respJson["message"] = "create session success";
    respJson["data"] = dataJson;

    Json::StreamWriterBuilder writerBuilder;
    std::string respStr = Json::writeString(writerBuilder, respJson);
    response.status = 200;
    response.set_content(respStr, "application/json");
}

2.2 获取会话列表 handleGetSessionListsRequest

  • 请求信息
    • URL:GET /api/sessions,无body参数
    • 返回200;data是会话对象数组
json 复制代码
{
    "success":true,
    "message":"get session lists success",
    "data":[
        {
            "id":"string",
            "model":"string",
            "created_at":1730000000,
            "updated_at":1730000100,
            "message_count":2,
            "first_user_message":"第一条用户消息内容"
        }
    ]
}
  • 业务流程
    • 调用SDK获取全部sessionId列表。
    • 创建Json数组Json::Value dataArray(Json::arrayValue);
    • 遍历每个sessionId,_chatSDK->getSession(sessionID)拿到会话智能指针;会话非空组装json对象。
    • 时间戳使用static_cast<int64_t>强转;消息非空取_messages.front()->_content第一条消息。
    • append到数组;组装外层responseJson,序列化返回。
cpp 复制代码
void ChatServer::handleGetSessionListsRequest(const httplib::Request& request, httplib::Response& response)
{
    std::vector<std::string> sessionIDs = _chatSDK->getSessionLists();
    Json::Value dataArray(Json::arrayValue);

    for(const auto& sessionID : sessionIDs)
    {
        auto session = _chatSDK->getSession(sessionID);
        if(!session) continue;

        Json::Value itemJson;
        itemJson["id"] = session->_sessionId;
        itemJson["model"] = session->_modelName;
        itemJson["created_at"] = static_cast<int64_t>(session->_createdAt);
        itemJson["updated_at"] = static_cast<int64_t>(session->_updatedAt);
        itemJson["message_count"] = static_cast<int>(session->_messages.size());

        if(!session->_messages.empty())
        {
            itemJson["first_user_message"] = session->_messages.front()._content;
        }
        dataArray.append(itemJson);
    }

    Json::Value respJson;
    respJson["success"] = true;
    respJson["message"] = "get session lists success";
    respJson["data"] = dataArray;

    Json::StreamWriterBuilder wb;
    std::string respStr = Json::writeString(wb, respJson);
    response.status = 200;
    response.set_content(respStr, "application/json");
}

2.3 获取模型列表 handleGetModelListRequest

  • 请求信息
    • URL:GET /api/models,无参数
    • 返回data数组,每一项包含name模型名,desc模型描述
json 复制代码
{
    "success":true,
    "message":"get model lists success",
    "data":[
        {"name":"deepseek‑chat","desc":"xxx描述"}
    ]
}
void ChatServer::handleGetModelListRequest(const httplib::Request& request, httplib::Response& response)
{
    auto modelList = _chatSDK->getAvailableModels();
    Json::Value dataArray(Json::arrayValue);

    for(const auto& info : modelList)
    {
        Json::Value item;
        item["name"] = info._modelName;
        item["desc"] = info._modelDesc;
        dataArray.append(item);
    }

    Json::Value respJson;
    respJson["success"] = true;
    respJson["message"] = "get model lists success";
    respJson["data"] = dataArray;

    Json::StreamWriterBuilder wb;
    std::string respStr = Json::writeString(wb, respJson);
    response.status = 200;
    response.set_content(respStr, "application/json");
}

2.4 删除会话 handleDeleteSessionRequest

  • 请求信息
    • URL:DELETE /api/session/{session_id},路径参数
    • httplib路径匹配捕获的参数保存在request.matches;matches1取session_id
    • 删除成功返回200;会话不存在返回404
json 复制代码
{
    "success":true,
    "message":"delete session success"
}
void ChatServer::handleDeleteSessionRequest(const httplib::Request& request, httplib::Response& response)
{
    std::string sessionId = request.matches[1];
    bool ok = _chatSDK->deleteSession(sessionId);
    if(ok)
    {
        std::string respStr = buildResponse("delete session success", true);
        response.status = 200;
        response.set_content(respStr, "application/json");
    }
    else
    {
        std::string respStr = buildResponse("delete session failed,session not found", false);
        response.status = 404;
        response.set_content(respStr, "application/json");
    }
}

2.5 获取会话历史消息 handleGetHistoryMessagesRequest

  • 请求信息
    • URL:GET /api/session/{session_id}/history,路径参数session_id
    • 会话不存在返回404;成功返回200,data数组存储消息
json 复制代码
{
    "success":true,
    "message":"get history messages success",
    "data":[
        {
            "id":"msg‑id",
            "role":"user/assistant",
            "content":"消息文本",
            "timestamp":1730000000
        }
    ]
}
void ChatServer::handleGetHistoryMessagesRequest(const httplib::Request& request, httplib::Response& response)
{
    std::string sessionId = request.matches[1];
    auto session = _chatSDK->getSession(sessionId);
    if(!session)
    {
        std::string err = buildResponse("session not found", false);
        response.status = 404;
        response.set_content(err, "application/json");
        return;
    }

    Json::Value dataArray(Json::arrayValue);
    for(const auto& msg : session->_messages)
    {
        Json::Value item;
        item["id"] = msg._messageId;
        item["role"] = msg._role;
        item["content"] = msg._content;
        item["timestamp"] = static_cast<int64_t>(msg._timestamp);
        dataArray.append(item);
    }

    Json::Value respJson;
    respJson["success"] = true;
    respJson["message"] = "get history messages success";
    respJson["data"] = dataArray;

    Json::StreamWriterBuilder wb;
    std::string respStr = Json::writeString(wb, respJson);
    response.status = 200;
    response.set_content(respStr, "application/json");
}

2.6 发送消息‑全量返回 handleSendMessageRequest

  • 请求信息
    • URL:POST /api/message
    • Body JSON参数:session_id会话id,message用户输入消息
    • 返回200;参数解析失败400;调用模型失败500
json 复制代码
{
    "success":true,
    "message":"send message success",
    "data":{
        "session_id":"xxx",
        "response":"模型完整回答文本"
    }
}
void ChatServer::handleSendMessageRequest(const httplib::Request& request, httplib::Response& response)
{
    Json::Value reqJson;
    Json::Reader reader;
    if(!reader.parse(request.body, reqJson))
    {
        std::string err = buildResponse("parse request body failed,json format error", false);
        response.status = 400;
        response.set_content(err, "application/json");
        return;
    }

    std::string sessionId = reqJson["session_id"].asString();
    std::string message = reqJson["message"].asString();
    if(sessionId.empty() || message.empty())
    {
        std::string err = buildResponse("session_id or message is empty", false);
        response.status = 400;
        response.set_content(err, "application/json");
        return;
    }

    std::string assistantMsg = _chatSDK->sendMessage(sessionId, message);
    if(assistantMsg.empty())
    {
        std::string err = buildResponse("Failed to send AI response message", false);
        response.status = 500;
        response.set_content(err, "application/json");
        return;
    }

    Json::Value dataJson;
    dataJson["session_id"] = sessionId;
    dataJson["response"] = assistantMsg;

    Json::Value respJson;
    respJson["success"] = true;
    respJson["message"] = "send message success";
    respJson["data"] = dataJson;

    Json::StreamWriterBuilder wb;
    std::string respStr = Json::writeString(wb, respJson);
    response.status = 200;
    response.set_content(respStr, "application/json");
}

3 ~> SSE流式增量返回接口(核心难点)

3.1 SSE协议基础概念

  • SSE(Server‑Sent Events):http长连接,服务器单向持续向客户端推送数据;不需要WebSocket。
  • 报文格式规范
    • 每一条推送:data: 内容\n\n;必须两个换行符作为分隔。
    • 流结束标记:data: [DONE]\n\n
  • http响应头配置
    • Cache‑Control: no‑cache:禁用缓存,实时下发
    • Connection: keep‑alive:维持长连接
    • 使用httplib set_chunked_content_provider开启分块传输;回调参数DataSink用于直接写入网络输出流。
  • 回调函数签名:bool(size_t offset, httplib::DataSink& sink)
    • 返回true代表还有后续数据;false终止流。
    • DataSink.write(buf, len)写入字节流;DataSink.done()结束流式输出。
  • 注意:chunk内容必须做json转义,防止内容内换行、引号破坏SSE协议格式,使用Json::valueToQuotedString。

3.2 sendMessageStreamRequest 流式发送消息实现

  • 请求信息
    • URL:POST /api/message/async
    • Body参数:session_id,message用户消息
    • HTTP状态码固定200;响应Content‑Type不是普通json,使用SSE分块输出
  • SDK回调说明:_chatSDK->sendMessageStream(sessionId, msg, callback(chunk, last))
    • chunk:模型返回的增量文本片段
    • last:bool,true代表整个流式输出结束
cpp 复制代码
void ChatServer::handleSendMessageStreamRequest(const httplib::Request& request, httplib::Response& response)
{
    // 1.解析请求体
    Json::Value reqJson;
    Json::Reader reader;
    if(!reader.parse(request.body, reqJson))
    {
        std::string err = buildResponse("parse request body failed,json format error", false);
        response.status = 400;
        response.set_content(err, "application/json");
        return;
    }

    std::string sessionId = reqJson["session_id"].asString();
    std::string message = reqJson["message"].asString();
    if(sessionId.empty() || message.empty())
    {
        std::string err = buildResponse("session_id or message is empty", false);
        response.status = 400;
        response.set_content(err, "application/json");
        return;
    }

    // 2.配置SSE响应头
    response.status = 200;
    response.set_header("Cache‑Control", "no‑cache");
    response.set_header("Connection", "keep‑alive");

    // 3.开启分块传输回调
    response.set_chunked_content_provider("text/event‑stream",
        [this, sessionId, message](size_t offset, httplib::DataSink& sink) -> bool
        {
            // SDK的chunk回调,把模型分片转为SSE报文写入DataSink
            auto writeChunk = [&sink](const std::string& chunk, bool last)
            {
                // json转义,避免特殊字符破坏SSE协议
                std::string escaped = Json::valueToQuotedString(chunk.c_str());
                std::string sseFrame = "data:" + escaped + "\n\n";
                sink.write(sseFrame.data(), sseFrame.size());

                if(last)
                {
                    std::string doneFrame = "data:[DONE]\n\n";
                    sink.write(doneFrame.data(), doneFrame.size());
                    sink.done();
                }
            };

            // 先发空帧,防止客户端长时间阻塞等待
            writeChunk("", false);

            // 调用SDK流式接口,传入分片回调
            _chatSDK->sendMessageStream(sessionId, message, writeChunk);

            return true;
        }
    );
}

4 ~> 关键易错点汇总(面试/考试重点)

4.1 Jsoncpp库易错

  1. Json::Reader::parse():传入request.body字符串,输出到外部Json::Value&;解析失败返回false,必须返回400错误。
  2. Json::StreamWriterBuilder用于序列化C++对象到json字符串。
  3. Json::valueToQuotedString:字符串转义,SSE场景必须使用,否则内容的"、\n会破坏协议帧。
  4. 创建json数组必须显式:Json::Value arr(Json::arrayValue);,否则默认是object对象。

4.2 httplib库易错

  1. 路径参数获取 :DELETE/get历史消息接口,路径捕获值存放在request.matches数组,下标从1开始。
  2. set_chunked_content_provider
    1. content‑type SSE标准是text/event‑stream,不能写application/json。
    2. 回调函数捕获变量注意生命周期;lambda捕获this访问类成员。
    3. DataSink.write直接写原始字节;不要使用response.set_content,流式场景无效。
    4. sink.done()标记流结束。返回true表示还存在后续数据。
  3. response.status修改状态码,set_content(字符串, content‑type)设置普通http body。

4.3 业务接口错误码规范

http状态码 业务含义
200 请求业务处理成功(不管是普通json还是sse流)
400 请求体JSON解析失败 / 请求参数为空、非法
404 session_id不存在,找不到会话资源
500 服务器内部业务错误:创建会话失败、调用大模型返回空

4.4 代码复用优化思想

  • 原始代码每个接口重复编写errorJson + StreamWriterBuilder序列化逻辑。
  • 抽离buildResponse(message, success)公共工具函数,统一生成success/message结构JSON字符串,消除大量重复样板代码。
  • 创建会话、删除会话、历史消息全部复用该工具。

4.5 全量返回 vs SSE增量返回对比

维度 全量返回 sendMessage SSE增量返回 sendMessageStream
返回时机 等待模型完整全部回答完成一次性返回 模型每产生一段分片,立刻推送客户端
http模式 普通一次性响应 chunked分块长连接,SSE协议
适用场景 后端脚本、服务间调用 web前端聊天页面,打字机实时输出效果
结束标识 http连接正常关闭 服务主动下发data:[DONE]\n\n帧

4.6 SDK回调层原理补充

sendMessageStream内部是异步事件回调:

  1. SDK底层发起http请求访问大模型服务。
  2. 收到SSE分片数据,解析chunk。
  3. 执行上层传入回调函数,将分片交付ChatServer层。
  4. ChatServer层将分片封装SSE帧,写入httplib的DataSink推送给浏览器客户端。
  5. 模型流结束时,回调参数last=true,服务发送[DONE]帧调用sink.done()关闭客户端长连接。

注意: 需要先发空分片给客户端,解决客户端请求发出之后,模型思考时间较长导致浏览器假死无响应的交互问题。


结尾

uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 艾莉丝努力练剑 C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主 *** ** * ** *** 👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。 ❤️ 【点赞】 让优质内容被更多人看见,让知识传递更有力量。 ⭐ 【收藏】 把核心知识点存好,在需要时随时查、随时用。 💬 【评论】 分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主"一键四连"哦! "今日练剑达成!" "技术之路难免有困惑,但同行的人会让前进更有方向。" |

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!

往期回顾:

【AI大模型接入SDK】ChatServer接口设计规范

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა

相关推荐
Purple Coder1 小时前
参考论文汇总
人工智能
坤坤子吖1 小时前
Linux 线程概念与控制——线程创建、退出与等待
linux·开发语言·c++·笔记·学习
tq10861 小时前
从信息到生产力
人工智能
袁俪1 小时前
具身智能环境交互
人工智能
weixin_307779131 小时前
C++代码实现MATLAB中的fitnlm函数功能
开发语言·c++·算法·matlab
m4Rk_1 小时前
【论文阅读】Agent 记忆机制(103):Dynamic Coding Memory——记忆为何让 Agent 更可靠,却可能更平庸
论文阅读·人工智能·学习·开源·github
雪落漂泊1 小时前
C++算法:双指针篇(下)
数据结构·c++·算法
回眸&啤酒鸭1 小时前
【回眸】Jockey By TwelveLabs 视频智能体应用场景大纲
人工智能