网络软文推广网站成都科技网站建设电
2026/4/18 13:00:29 网站建设 项目流程
网络软文推广网站,成都科技网站建设电,手机wordpress建站教程,黑龙省建设厅网站这里写目录标题前言第一章#xff1a;DeepSeek Provider类的派生与初始化1.1 头文件定义1.2 初始化逻辑实现第二章#xff1a;HTTP通信与JSON处理核心实现2.1 依赖库安装#xff1a;cpp-httplib2.2 全量消息发送逻辑详解第三章#xff1a;基于Google Test的单元测试3.1 GTe…这里写目录标题前言第一章DeepSeek Provider类的派生与初始化1.1 头文件定义1.2 初始化逻辑实现第二章HTTP通信与JSON处理核心实现2.1 依赖库安装cpp-httplib2.2 全量消息发送逻辑详解第三章基于Google Test的单元测试3.1 GTest环境搭建3.2 编写测试用例3.3 构建配置与编译3.4 编译与运行前言在完成了SDK的底层架构设计与抽象基类LLMProvider的定义后接下来的核心任务是实现具体的模型接入逻辑。本文将以DeepSeek模型为例详细阐述如何通过C代码构建HTTP请求、处理API鉴权、解析JSON响应并通过严格的单元测试验证模块功能的正确性。如果文章中的代码存在问题可以直接去仓库拉取最新代码Ai_Model_SDKhttps://gitee.com/caijiuuyk/ai_-model_-sdk第一章DeepSeek Provider类的派生与初始化根据策略模式的设计我们需要创建一个继承自LLMProvider的具体实现类DeepSeekProvider。该类负责管理DeepSeek模型的生命周期、配置加载以及消息发送逻辑。1.1 头文件定义在include目录下创建DeepSeekProvider.h。该文件声明了DeepSeek提供者类重写了基类中的纯虚函数。可以看到除了基础的初始化和元数据获取接口外重点在于sendMessage全量返回和sendMessageStream流式返回的声明。SDK/include/DeepSeekProvider.h代码如下#includeLLMProvider.h#includestring.h#includemap#includevector#includecommon.hnamespacekk{// DeepSeekProvider类继承自抽象基类LLMProviderclassDeepSeekProvider:publicLLMProvider{public:// 初始化模型// modelConfig: 包含apiKey, endpoint等配置信息的映射virtualvoidinitModel(conststd::mapstd::string,std::stringmodelConfig);// 检查模型是否可用virtualboolisAvailable()const;// 获取模型名称virtualstd::stringgetModelName()const;// 获取模型描述virtualstd::stringgetModelDesc()const;// 发送消息 ---全量返回 非流式响应// messages: 上下文消息列表// requestParam: 运行时参数如temperature, maxTokensstd::stringsendMessage(conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParam);// 发送消息 ---全量返回 流式响应// callback: 回调函数用于处理增量返回的Tokenvirtualstd::stringsendMessageStream(conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParam,std::functionvoid(conststd::string,bool)callback);};}1.2 初始化逻辑实现在src目录下创建DeepSeekProvider.cpp。初始化的核心逻辑在于解析传入的配置参数modelConfig提取API Key和EndpointAPI接入点并设置模型的可用状态。这里使用了我们之前封装的myLog.h进行日志记录以便在初始化失败时快速定位问题。SDK/src/DeepSeekProvider.cpp初始化部分代码#include../include/DeepSeekProvider.h#include../include/util/myLog.hnamespacekk{// 初始化模型实现boolDeepSeekProvider::initModel(conststd::mapstd::string,std::stringmodelConfig){// 1. 初始化API keyautoitmodelConfig.find(apiKey);if(itmodelConfig.end())// 没找到apikey的话{ERR(DeepSeekProvider initModel:apiKey not found);// 打印错误日志returnfalse;}_apiKeyit-second;// 找到了赋值// 2. 初始化endpointitmodelConfig.find(endpoint);if(itmodelConfig.end())// 没找到endpoint的话{ERR(DeepSeekProvider initModel:endpoint not found);// 打印错误日志returnfalse;}_endpointit-second;// 找到了赋值_isAvailabletrue;// 标记模型可用// 初始化成功打印关键信息注意生产环境不要打印完整的KeyINFO(DeepSeekProvider initModel:success,apiKey:%s,endpoint:%s,_apiKey.c_str(),_endpoint.c_str());returntrue;}// 检测模型是否可用boolDeepSeekProvider::isAvailable()const{return_isAvailable;}// 获取模型名称std::stringDeepSeekProvider::getModelName()const{returndeepseek-chat;}// 获取模型的描述信息std::stringDeepSeekProvider::getModelDesc()const{returndeepseek-chat模型是一个基于Transformer架构的对话模型,由DeepSeek公司开发。它可以用于生成自然语言对话,支持多轮对话。;}// sendMessage 和 sendMessageStream 的具体实现将在下文详述}第二章HTTP通信与JSON处理核心实现为了实现sendMessage功能我们需要引入HTTP客户端库来发送网络请求并引入JSON库来处理数据交互。2.1 依赖库安装cpp-httplib本项目选用cpp-httplib作为HTTP客户端它是一个单头文件header-only的跨平台C库使用非常便捷。安装方式一Git克隆可以直接从GitHub克隆源码并将头文件复制到系统目录devdev-host:~/workspace$gitclone https://github.com/yhirose/cpp-httplib.git# 注意cpp-httplib是header-only库只需要一个头文件即可# 将httplib.h拷贝到系统目录下这样在程序中#include httplib.h时能直接找到bitbit08:~/cpp-httplib/cpp-httplib$sudocphttplib.h /usr/include安装方式二压缩包解压如果在服务器端Git网络受限可以通过上传压缩包的方式进行安装。unzipcpp-httplib-master.zip解压后的文件结构如下只需关注核心的httplib.h文件。2.2 全量消息发送逻辑详解sendMessage函数的实现是SDK的核心之一。其工作流程如下状态校验确认模型已初始化且可用。参数构造解析用户传入的requestParam如温度、MaxTokens设置默认值。JSON序列化使用jsoncpp库将消息历史vectorMessage和配置参数组装成符合DeepSeek API规范的JSON对象并序列化为字符串。HTTP请求构建实例化httplib::Client设置超时时间配置Header包含Bearer Token认证。发送与接收发送POST请求等待服务器的全量响应。错误处理检查HTTP状态码期望为200和网络错误。JSON反序列化解析API返回的JSON数据提取choices[0].message.content字段作为最终回复。以下是DeepSeekProvider.cpp中关于sendMessage的完整实现代码#include../include/DeepSeekProvider.h#include../include/util/myLog.h#includejsoncpp/json/json.h#includehttplib.hnamespacekk{// ... 前文的initModel等代码 ...// 发送消息 ---全量返回 非流式响应std::stringDeepSeekProvider::sendMessage(conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParam){// 1、检测模型是否可用if(!isAvailable()){ERR(DeepSeekProvider sendMessage:model not available);return;}// 2、构造请求参数doubletemperature0.7;// 默认温度intmaxTokens2048;// 默认最大tokenif(requestParam.find(temperature)!requestParam.end()){temperaturestd::stod(requestParam.at(temperature));}if(requestParam.find(maxTokens)!requestParam.end()){maxTokensstd::stoi(requestParam.at(maxTokens));}// 3、构造历史消息 JSON数组Json::ValuemessageArray(Json::arrayValue);for(constautomessage:messages){Json::ValuemessageJson(Json::objectValue);messageJson[role]message._role;messageJson[content]message._content;messageArray.append(messageJson);}// 4、构造整个请求体 JSON对象Json::ValuerequestBody(Json::objectValue);requestBody[model]getModelName();// 设置模型名称requestBody[messages]messageArray;// 设置上下文requestBody[temperature]temperature;requestBody[max_tokens]maxTokens;// 5、序列化将JSON对象转为字符串Json::StreamWriterBuilder writerBuilder;writerBuilder[indentation];// 设置缩进为空压缩数据传输量std::string requestBodyStrJson::writeString(writerBuilder,requestBody);INFO(DeepSeekProvider sendMessage:requestBody:%s,requestBodyStr.c_str());// 6、使用cpp-httplib库构造http客户端// _endpoint 需为 base url例如 https://api.deepseek.comhttplib::Clientclient(_endpoint.c_str());client.set_connection_timeout(30);// 连接超时30秒client.set_read_timeout(60,0);// 读取超时60秒防止大模型生成时间过长导致断连// 7、设置请求头httplib::Headers headers{{Authorization,Bearer _apiKey},// 鉴权的核心{Content-Type,application/json}};// 8、发送POST请求autoresponseclient.Post(/v1/chat/completions,headers,requestBodyStr,application/json);if(!response)// 网络层面的请求失败{ERR(DeepSeekProvider sendMessage:request failed,error message:{},httplib::to_string(response.error()));return;}INFO(DeepSeekProvider sendMessage:POST request success ,status code:{},response-status);INFO(DeepSeekProvider sendMessage:response body:{},response-body);// 9、检测HTTP响应状态if(response-status!200)return;// 10、解析响应体Json::Value responseBody;Json::CharReaderBuilder readerBuilder;std::string parseError;std::istringstreamresponseStream(response-body);// 解析JSON字符串if(Json::parseFromStream(readerBuilder,responseStream,responseBody,parseError)){// 导航至 message 内容responseBody[choices][0][message][content]if(responseBody.isMember(choices)responseBody[choices].isArray()!responseBody[choices].empty()){autochoiceresponseBody[choices][0];if(choice.isMember(message)choice[message].isMember(content)){std::string replyContentchoice[message][content].asString();INFO(DeepSeekProvider sendMessage:replyContent:{},replyContent);returnreplyContent;}}// JSON结构不符合预期ERR(DeepSeekProvider sendMessage:JSON parse failed,error message:{},parseError);returnjson parse failed;}returnjson parse failed;}// 占位实现流式响应将在后续章节详细讲解std::stringDeepSeekProvider::sendMessageStream(conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParam,std::functionvoid(conststd::string,bool)callback){returnstream not implemented yet;}}第三章基于Google Test的单元测试代码编写完成后必须进行严格的测试。本项目引入C领域最权威的单元测试框架Google Test (gtest)。3.1 GTest环境搭建在Ubuntu环境下可以通过apt快速安装GTest开发库sudoapt-getinstalllibgtest-dev3.2 编写测试用例在项目根目录下创建一个test文件夹并编写testLLM.cpp。测试用例的设计涵盖了从对象创建、初始化到发送消息的完整流程。为了安全起见API Key通过环境变量获取支持回退到硬编码的Key仅用于本地调试。test/testLLM.cpp代码#includegtest/gtest.h#include../SDK/include/DeepSeekProvider.h#include../SDK/include/util/myLog.h// 测试DeepSeekProvider的核心流程TEST(DeepSeekProviderTest,sendMessage){// 1. 创建Provider实例autoProviderstd::make_sharedkk::DeepSeekProvider();ASSERT_TRUE(Provider!nullptr);// 断言指针有效// 2. 准备初始化参数std::mapstd::string,std::stringmodelParam;constchar*env_apikeystd::getenv(deepseek_apikey);// 优先读取环境变量否则使用备用KeymodelParam[apiKey]env_apikey?env_apikey:sk-xxxxxxxxxxxxxxxxxxxxxxxx;// 支持配置自定义Endpoint例如中转站地址modelParam[endpoint]https://api.deepseek.com;// 3. 初始化并检查可用性Provider-initModel(modelParam);ASSERT_TRUE(Provider-isAvailable());// 4. 准备请求运行时参数std::mapstd::string,std::stringrequestParam{{temperature,0.5},{max_tokens,2048}};// 5. 构造测试消息std::vectorkk::Messagemessages;messages.push_back({user,你是谁});// 6. 调用核心接口并验证std::string responseProvider-sendMessage(messages,requestParam);ASSERT_TRUE(!response.empty());// 断言回复不为空}intmain(intargc,char**argv){// 初始化日志库开启DEBUG级别以便查看详细通信过程kk::Logger::initLogger(testLLM,stdout,spdlog::level::debug);INFO(Test start...);// 初始化GTest框架testing::InitGoogleTest(argc,argv);// 运行所有注册的TEST宏returnRUN_ALL_TESTS();}3.3 构建配置与编译在test目录下创建独立的CMakeLists.txt用于构建测试可执行文件。需要特别注意的是这里必须正确链接OpenSSL、JsonCpp、Fmt、Spdlog以及GTest库。test/CMakeLists.txt配置# 设置Cmake的最小版本为3.10 cmake_minimum_required(VERSION 3.10) # 项目名称 project(testLLM) # 设置C标准为C17 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_BUILD_TYPE Debug) # 添加可执行文件包含测试代码和SDK源码 add_executable(testLLM testLLM.cpp ../SDK/src/DeepSeekProvider.cpp ../SDK/src/util/myLog.cpp) # 设置输出目录 set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}) # 添加头文件搜索路径 include_directories(${CMAKE_PROJECT_INCLUDE_DIR}/ ../SDK/include) # 查找并链接OpenSSL find_package(OpenSSL REQUIRED) include_directories(${OPENSSL_INCLUDE_DIR}) # 宏定义告诉cpp-httplib支持HTTPS target_compile_definitions(testLLM PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT) # 链接所有依赖库 target_link_libraries(testLLM spdlog gtest jsoncpp fmt OpenSSL::Crypto OpenSSL::SSL)目录结构确认确保文件布局如下所示3.4 编译与运行进入test目录创建build文件夹并进行编译mkdirbuildcdbuild cmake..CMake配置成功后会生成Makefile执行make进行编译。在开发过程中可能会遇到库链接顺序或头文件缺失导致的编译错误需要根据报错信息仔细调整CMakeLists.txt。修复问题后编译成功运行生成的可执行文件./testLLM。可以看到控制台输出了请求的JSON Body、服务器返回的状态码以及解析后的回复内容。这里演示了通过自定义Endpoint连接API中转站的场景。至此我们已经成功实现了DeepSeek模型的全量消息发送功能并通过单元测试验证了从网络通信到JSON解析的完整链路。下一章将深入最具挑战性的部分——流式响应Streaming Response的实现。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询