长春汽开区建设局网站如何建设一个商城网站
2026/2/3 1:26:49 网站建设 项目流程
长春汽开区建设局网站,如何建设一个商城网站,网站建设课程思政,2024年新闻摘抄C大模型SDK开发实录#xff1a;从架构设计到流式交互实现 在当今的人工智能应用开发中#xff0c;如何高效、统一地接入不同厂商的大语言模型#xff08;如DeepSeek、OpenAI、Gemini#xff09;是一个核心挑战。本项目旨在构建一个名为 ChatSDK 的C开发包#xff0c;屏蔽底…C大模型SDK开发实录从架构设计到流式交互实现在当今的人工智能应用开发中如何高效、统一地接入不同厂商的大语言模型如DeepSeek、OpenAI、Gemini是一个核心挑战。本项目旨在构建一个名为ChatSDK的C开发包屏蔽底层API差异提供统一的会话管理、全量与流式消息发送功能。本文将首先展示项目的最终形态与环境部署流程随后深入剖析从零开始构建该SDK的每一个技术细节涵盖API协议分析、数据架构设计、高性能日志系统封装以及策略模式在模型接入层中的应用。第一章成品演示与快速上手在深入底层代码之前首先展示ChatSDK的最终运行效果以及如何在服务器环境中部署和使用该SDK。1.1 项目功能与运行效果ChatSDK 旨在为C开发者提供一套简洁的接口支持以下核心功能多模型支持通过统一配置接入不同厂商模型。会话管理创建会话、获取列表、删除会话及历史消息回溯。双模式响应支持同步全量返回适合后台处理和异步流式返回适合打字机效果。下图展示了基于ChatSDK编写的终端演示程序Demo的运行界面。可以看到用户与模型进行了交互程序成功输出了DeepSeek模型的回复内容。1.2 环境依赖与构建工具链本项目基于Linux环境开发依赖一系列成熟的开源库来处理网络、日志、JSON解析及测试。基础依赖安装在服务器端推荐使用Trae CN连接首先需要配置C编译环境clangd, CMake Tools及以下系统库# gflags用于解析命令行参数sudoapt-getinstalllibgflags-dev# spdlog高性能C日志库提供异步日志支持sudoapt-getinstalllibspdlog-dev# fmt格式化库spdlog的核心依赖sudoapt-getinstallfmt# jsoncpp用于处理模型API交互中的JSON数据序列化与反序列化sudoapt-getinstalllibjsoncpp-dev# gtestGoogle单元测试框架sudoapt-getinstalllibgtest-dev# OpenSSL支持HTTPS加密通信保障API Key安全sudoapt-getinstalllibssl-dev# cmake跨平台构建系统sudoapt-getinstallcmake# pkg-config编译时库文件路径查找工具sudoaptinstallpkg-config# curl命令行网络工具用于初步测试API连通性sudoaptinstallcurl源码获取与目录结构获取SDK源码主要有两种方式通过Git克隆或直接上传压缩包。gitclone https://gitee.com/zhibite-edu/ai-model-acess-dev.git如果网络环境受限可将源码下载为Zip包上传至服务器并解压。如下图所示在服务器中创建ChatSDK文件夹解压后的源码位于SDK-source目录中。1.3 编译构建与排错流程项目采用 CMake 进行构建管理。标准的构建流程推荐采用“外部构建”方式即在源码目录外创建一个build文件夹以保持源码整洁。初始化构建目录进入SDK源码路径ChatSDK/SDK-source/ai-model-acess-tech-master/AIModelAcessTech/sdk执行以下命令mkdirbuildcdbuild生成Makefile在build目录下执行 CMake 配置命令读取上级目录的CMakeLists.txtcmake..编译与依赖修复执行make命令开始编译。在初次编译时系统抛出了错误提示找不到httplib.h。这是因为项目内部使用了cpp-httplib库但环境未安装。需执行以下命令补全依赖sudoapt-getupdatesudoapt-getinstall-y libcpp-httplib-dev修复后重新执行make编译成功。1.4 核心架构解析与安装ChatSDK 采用了清晰的分层架构核心逻辑代码位于src目录下其中util文件夹包含了模型接入的具体实现。核心框架类ChatSDK.cpp对外门面封装内部复杂性。LLMManager.cpp模型生命周期管理与路由。SessionManager.cpp会话状态与内存管理。DataManager.cpp基于SQLite的数据持久化层。模型提供者类ChatGPTProvider.cpp/GeminiProvider.cpp/DeepSeekProvider.cpp实现了具体的API调用逻辑支持自定义 Endpoint 以适配中转站。API 接口概览SDK提供了initModels初始化、createSession创建会话、sendMessage全量发送及sendMessageStream流式发送等标准接口。安装库文件编译完成后执行安装命令将头文件和库文件部署到系统目录sudomakeinstall验证安装结果头文件位于/usr/local/include/ai_chat_sdk/库文件位于/usr/local/lib/。1.5 客户端集成演示 (ChatDemo)为了验证SDK的可用性编写一个名为chatDemo.cpp的客户端程序。该程序演示了如何调用DeepSeek模型进行流式对话。#includeai_chat_sdk/chat_sdk.h#includeai_chat_sdk/my_logger.h//打印日志#includeiostream#includelimitsvoidsendMessageStream(ai_chat_sdk::ChatSDKchat_SDK,std::string session_id){std::cout-----------------------------发送消息-----------------------------std::endl;std::string message;std::getline(std::cin,message);//获取用户输入chat_SDK.sendMessageStream(session_id,message,[](conststd::stringresponse,booldone){std::coutassistant消息 responsestd::endl;if(done)//如果是最后一条消息{std::cout-----------------------------消息接收完成-----------------------------std::endl;}});//发送消息std::cout-----------------------------消息发送完成-----------------------------std::endl;std::cout请输入您的消息:std::endl;std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n);//清除输入缓冲区std::cout您输入的消息是:messagestd::endl;}intmain(){bite::Logger::init_logger(aiChatDemo,stdout,spdlog::level::info);//创建一个控制台日志记录器ai_chat_sdk::ChatSDK chatSDK;//创建一个SDK的对象//配置deepseek模型ai_chat_sdk::ApiConfig deepseek;//创建一个配置对象deepseek.api_keystd::getenv(deepseek_apikey);//设置API Keydeepseek.temperature0.7;//设置温a度deepseek.max_tokens2048;//设置最大token数deepseek.model_namedeepseek-chat;//设置模型名称std::vectorstd::shared_ptrai_chat_sdk::Configconfigs;//创建一个配置对象的向量configs.push_back(std::make_sharedai_chat_sdk::ApiConfig(deepseek));//添加Deepseek的配置对象//初始化模型chatSDK.initModels(configs);std::cout-----------------------------创建会话-----------------------------std::endl;std::string session_idchatSDK.createSession(deepseek-chat);//创建一个会话std::coutsession_id:session_idstd::endl;intuerOP1;//用户操作while(true){std::cout-------------------1、send message 0、exit------------------------std::endl;std::cinuerOP;if(uerOP0){break;}getchar();//输入用户操作选择之后需要接受到缓冲区中的回车sendMessageStream(chatSDK,session_id);//给会话发送消息}return0;}配合相应的CMakeLists.txt进行编译# 项目名称为AIChatDemo project(AIChatDemo) # 设置C标准使用C17标准进行编译REQUIRED表示编译器如果不支持C17则报错 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 设置构建类型为Debug set(CMAKE_BUILD_TYPE Debug) # 添加可执行文件 add_executable(AIChatDemo chatDemo.cpp) # 查找OpenSSL包 find_package(OpenSSL REQUIRED) # 将OpenSSL的头文件目录添加到编译器的搜索路径中 include_directories(${OPENSSL_INCLUDE_DIR}) # 设置库的目录链接器会在这个目录中查找需要的库文件ai_chat_sdk库文件 link_directories(/usr/local/lib) # 链接SDK target_link_libraries(AIChatDemo PRIVATE ai_chat_sdk fmt jsoncpp OpenSSL::SSL OpenSSL::Crypto gflags spdlog sqlite3 )运行编译后的程序即可实现本章开头展示的对话效果。第二章API 协议调研与调试 (DeepSeek)在开始编码实现SDK之前必须深入理解目标模型以DeepSeek为例的API交互协议。我们使用Postman工具进行预研。2.1 鉴权与环境配置首先将API Key配置在Postman的全局环境变量中避免硬编码确保安全性。在HTTP请求头Headers中设置Content-Type为application/json并配置Authorization字段值为Bearer {{api_key}}。2.2 接口参数与请求体DeepSeek的API兼容OpenAI规范。我们需要构建JSON格式的请求体Body包含模型名称、消息历史列表等。请求的URL Endpoint 设置为https://api.deepseek.com。2.3 响应模式测试流式响应 (Streaming)将stream参数设置为true。此时服务器通过 Server-Sent Events (SSE) 协议分块返回数据。在Postman中可以看到数据是逐步到达的每块数据包含一个 token。非流式响应 (Blocking)将stream参数设置为false。服务器会等待所有内容生成完毕后一次性返回一个完整的JSON对象。这一调研过程决定了SDK底层网络模块必须同时支持 HTTP 长连接读取用于流式和普通请求读取用于全量。第三章通用数据结构设计基于API调研结果我们抽象出一套通用的数据结构用于在SDK内部各个模块模型管理、会话管理、持久化之间传递数据。这些定义位于include/common.h。3.1 核心结构体定义为了适应不同模型我们提取了公共配置和描述信息#pragmaonce#includestring#includectime#includevectornamespaceai_chat_sdk{// 消息结构对应API中的message对象structMessage{std::string _id;std::string _role;// user, assistant, systemstd::string _content;// 消息内容std::time_t _timestamp;Message(conststd::stringrole,conststd::stringcontent):_role(role),_content(content){}};// 基础配置所有模型通用的参数structConfig{std::string _modelName;double_temperature0.7;// 控制随机性int_maxTokens2048;// 控制长度};// API配置继承自Config增加鉴权信息structAPIConfig:publicConfig{std::string _apiKey;};// 模型元数据用于服务发现和状态检查structModelInfo{std::string _modelName;std::string _modelDesc;std::string _provider;std::string _endpoint;bool_isAvailablefalse;ModelInfo(conststd::stringmodelName,conststd::stringmodelDesc,conststd::stringprovider,conststd::stringendpoint):_modelName(modelName),_modelDesc(modelDesc),_provider(provider),_endpoint(endpoint){}};// 会话结构管理对话上下文structSession{std::string _sessionId;std::string _modelName;std::vectorMessage_messages;// 消息历史std::time_t _createAt;std::time_t _updateAt;Session(conststd::stringmodelName):_modelName(modelName){}};}这些结构体构成了SDK的数据骨架Session对象将由SessionManager在内存中维护并由DataManager序列化到数据库中。第四章基础设施——spdlog日志库封装在C工程中std::cout无法满足多线程安全、日志分级Trace/Debug/Info/Error、文件持久化及格式化输出的需求。因此本项目基于spdlog进行了单例封装。4.1 封装优势与设计理念级别管理在开发期开启DEBUG生产期切换至INFO或ERROR避免日志文件膨胀。格式化自动注入时间戳、线程ID、文件名及行号便于定位问题。异步高性能利用独立线程处理磁盘I/O避免阻塞主业务线程。线程安全通过内部锁机制保证多线程并发写入不冲突。封装采用了单例模式Singleton Pattern确保全局只有一个日志管理器实例。4.2 实现代码解析头文件 (util/myLog.h)定义了Logger类及便捷宏。宏定义利用__FILE__和__LINE__自动捕获调用位置。#pragmaonce#includespdlog/spdlog.hnamespacekk{classLogger{public:// 初始化日志指定名称、文件路径、级别staticvoidinitLogger(conststd::stringloggerName,conststd::stringloggerFile,spdlog::level::level_enum logLevelspdlog::level::info);staticstd::shared_ptrspdlog::loggergetLogger();private:Logger();// 私有构造// 禁止拷贝Logger(constLogger)delete;Loggeroperator(constLogger)delete;private:staticstd::shared_ptrspdlog::logger_logger;staticstd::mutex _mutex;};// 宏定义示例自动格式化文件名与行号#defineDBG(format,...)kk::Logger::getLogger()-debug(std::string([{:10s}:{4d}])format,__FILE__,__LINE__,##__VA_ARGS__)//定义其他日志级别宏#defineTRACE(format,...)kk::Logger::getLogger()-log(spdlog::level::info,std::string([{:10s}:{4d}])format,__FILE__,__LINE__,##__VA_ARGS__)#defineINF(format,...)kk::Logger::getLogger()-info(std::string([{:10s}:{4d}])format,__FILE__,__LINE__,##__VA_ARGS__)#defineWRN(format,...)kk::Logger::getLogger()-warn(std::string([{:10s}:{4d}])format,__FILE__,__LINE__,##__VA_ARGS__)#defineERR(format,...)kk::Logger::getLogger()-error(std::string([{:10s}:{4d}])format,__FILE__,__LINE__,##__VA_ARGS__)#defineCRIT(format,...)kk::Logger::getLogger()-critical(std::string([{:10s}:{4d}])format,__FILE__,__LINE__,##__VA_ARGS__)}实现文件 (util/myLog.cpp)实现了双重检查锁定Double-Checked Locking以保证初始化的线程安全并配置异步线程池。#include../../include/util/mylog.h//将头文件包含进来#includememory#includespdlog/spdlog.h#includespdlog/sinks/basic_file_sink.h#includespdlog/sinks/stdout_color_sinks.h#includespdlog/async.hnamespacekk{std::shared_ptrspdlog::loggerLogger::_loggernullptr;//初始化日志器为空指针std::mutex Logger::_mutex;//初始化日志器互斥锁//构造函数Logger::Logger(){}voidLogger::initLogger(conststd::stringloggerName,conststd::stringloggerFile,spdlog::level::level_enum logLevel){if(nullptr_logger)//如果这个实例是空的说明我们的日志器还没有被创建{//创建一把锁std::lock_guardstd::mutexlock(_mutex);//再次检查是否为空因为在多线程环境下可能会有其他线程先创建了实例if(nullptr_logger){//设置全局刷新策略,当日志级别大于等于logLevel时,刷新日志spdlog::flush_on(logLevel);//启用异步日志即将日志信息存储放到队列中有后台线程负责写入//参数1队列大小参数2后台线程数spdlog::init_thread_pool(32768,1);//初始化线程池,32768个线程,1个队列if(stdoutloggerFile)//如果日志文件路径为stdout,则将日志输出到标准输出流就是控制台{//创建一个带颜色的输出到控制台的日志器_loggerspdlog::stdout_color_mt(loggerName);}else{//创建一个文件输出的日志器日志会被写入到指定的文件中_loggerspdlog::basic_logger_mtspdlog::async_logger(loggerName,loggerFile);//创建一个异步日志器}}//格式设置//[%H:%M:%S] 时间//[%n] 日志器名称//[%l] 日志级别,左对齐,宽度为7//[%v] 日志消息_logger-set_pattern([%H:%M:%S][%n] [%-7l] %v);//设置日志格式_logger-set_level(logLevel);//设置日志级别}}//获取日志器的方法std::shared_ptrspdlog::loggerLogger::getLogger(){return_logger;}}//end kk第五章核心抽象——Provider策略模式实现为了应对不同模型提供商DeepSeek, ChatGPT, Gemini的具体实现差异同时对上层业务保持接口统一我们采用了策略模式Strategy Pattern。5.1 抽象基类设计 (LLMProvider)我们定义了一个纯虚基类LLMProvider它规定了所有模型类必须实现的行为初始化、可用性检查、获取元数据以及发送消息。由于它是抽象类无法被直接实例化只能作为接口规范。头文件 (include/LLMprovider.h)#includestring.h#includemap#includevector#includecommon.hnamespacekk{classLLMProvider{public:// 纯虚函数初始化模型配置virtualvoidinitModel(conststd::mapstd::string,std::stringmodelConfig)0;// 纯虚函数检查模型是否可用virtualboolisAvailable()const0;// 纯虚函数获取模型元数据virtualstd::stringgetModelName()const0;virtualstd::stringgetModelDesc()const0;// 核心接口全量发送消息voidsendMessage(conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParam);// 核心接口流式发送消息通过回调函数(std::function)返回增量数据voidsendMessageStream(conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParam,std::functionvoid(conststd::string,bool)callback);private:bool_isAvailablefalse;std::string _apiKey;std::string _endpoint;};}5.2 派生类实现逻辑具体的模型类如DeepSeekProvider将继承该基类。在initModel中子类会解析配置参数API Key从配置中提取。Endpoint默认使用官方地址但允许通过配置覆盖从而支持API中转站Proxy。在sendMessageStream的实现中子类将构造特定的HTTP请求并利用curl或httplib的回调机制每当收到一段SSE数据块时就解析并调用上层传入的callback函数从而实现流式效果。通过这种设计当需要添加新模型例如Claude时只需新增一个继承自LLMProvider的类而无需修改现有的会话管理或界面代码完美符合开闭原则Open-Closed Principle。

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

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

立即咨询