AI大模型接入SDK—LLMProvider实现 LLMProvider 接口与四类模型提供者实现一、策略模式设计概述项目采用**策略模式Strategy Pattern**设计 LLM 提供者层将不同模型的调用逻辑封装到独立的实现类中通过统一的接口对外暴露。设计目标统一接口所有模型提供者遵循相同的调用契约解耦扩展新增模型只需实现LLMProvider接口无需修改已有代码多态调用上层代码通过基类指针调用运行时动态分发到具体实现1.1 类图关系┌─────────────────────┐ │ LLMProvider │ (抽象策略接口) │ ─────────────────── │ │ initModel() │ │ isProviderAvailable() │ │ getProviderName() │ │ getProviderDesc() │ │ sendMessage() │ │ sendMessageStream() │ │ ─────────────────── │ │ # _isAvailable │ │ # _apiKey │ │ # _endpoint │ └──────────┬──────────┘ │ ┌───────────────────┼───────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ChatGPT │ │DeepSeek │ │Gemini │ │Provider │ │Provider │ │Provider │ └─────────────┘ └─────────────┘ └─────────────┘ ┌─────────────┐ │OllamaLLM │ │Provider │ │ ─────────── │ │ # _modelName│ │ # _modelDesc│ └─────────────┘二、LLMProvider 抽象接口2.1 接口定义classLLMProvider{public:// 初始化模型纯虚函数virtualboolinitModel(conststd::mapstd::string,std::stringmodelConfig)0;// 检查提供方是否可用virtualboolisProviderAvailable()const0;// 获取提供方名称/描述virtualstd::stringgetProviderName()const0;virtualstd::stringgetProviderDesc()const0;// 发送消息——全量返回virtualstd::stringsendMessage(conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParams)0;// 发送消息——流式返回virtualstd::stringsendMessageStream(conststd::vectorMessagemessages,conststd::mapstd::string,std::stringrequestParams,std::functionvoid(conststd::string,bool)callback)0;protected:bool_isAvailablefalse;// 提供方是否可用std::string _apiKey;// API 密钥std::string _endpoint;// API 端点地址};2.2 接口方法说明方法说明返回值initModel()初始化模型设置 API Key、Endpoint 等配置bool初始化是否成功isProviderAvailable()检查模型是否已初始化并可用boolgetProviderName()获取模型名称标识std::stringgetProviderDesc()获取模型描述信息std::stringsendMessage()发送消息并等待完整响应std::string完整回复内容sendMessageStream()流式发送消息通过回调逐步返回std::string聚合的完整回复2.3 纯虚函数与保护成员设计要点所有方法声明为纯虚函数 0强制子类实现_isAvailable、_apiKey、_endpoint声明为protected子类可直接访问子类可根据需要扩展额外的成员变量如OllamaLLMProvider的_modelName三、四类 Provider 实现详解3.1 DeepSeekProvider标准 OpenAI 兼容3.1.1 基本信息属性值模型名称deepseek-chatAPI 端点https://api.deepseek.comAPI 路径/v1/chat/completions协议格式OpenAI 兼容格式3.1.2 initModel 实现boolDeepSeekProvider::initModel(conststd::mapstd::string,std::stringmodelConfig){// 1. 提取 api_keyautoitmodelConfig.find(api_key);if(itmodelConfig.end()){ERR(api_key not found);returnfalse;}_apiKeyit-second;// 2. 提取 endpoint可选有默认值itmodelConfig.find(endpoint);if(itmodelConfig.end()){_endpointhttps://api.deepseek.com;// 默认端点}else{_endpointit-second;}_isAvailabletrue;returntrue;}特点endpoint参数可选提供默认值只需api_key即可完成初始化3.1.3 sendMessage全量返回实现流程┌──────────────────────────────────────────────────────────────┐ │ sendMessage 全量流程 │ ├──────────────────────────────────────────────────────────────┤ │ 1. 检查 _isAvailable │ │ │ │ │ ▼ │ │ 2. 提取请求参数temperature, max_tokens │ │ │ │ │ ▼ │ │ 3. 构造 JSON 请求体 │ │ { │ │ model: deepseek-chat, │ │ messages: [...], │ │ temperature: 0.7, │ │ max_tokens: 2048 │ │ } │ │ │ │ │ ▼ │ │ 4. 序列化 JSON │ │ │ │ │ ▼ │ │ 5. 创建 httplib::Client设置超时 │ │ │ │ │ ▼ │ │ 6. POST /v1/chat/completions │ │ │ │ │ ▼ │ │ 7. 检查响应状态码200 │ │ │ │ │ ▼ │ │ 8. 解析响应 JSON提取 choices[0].message.content │ │ │ │ │ ▼ │ │ 9. 返回回复内容 │ └──────────────────────────────────────────────────────────────┘请求体格式{model:deepseek-chat,messages:[{role:user,content:你好}],temperature:0.7,max_tokens:2048}响应体格式{choices:[{message:{role:assistant,content:你好有什么我可以帮助你的吗}}]}3.1.4 sendMessageStream流式返回实现流程┌──────────────────────────────────────────────────────────────┐ │ sendMessageStream 流式流程 │ ├──────────────────────────────────────────────────────────────┤ │ 1. 构造请求体添加 stream: true │ │ │ │ │ ▼ │ │ 2. 设置请求头 Accept: text/event-stream │ │ │ │ │ ▼ │ │ 3. 创建 httplib::Request 对象 │ │ │ │ │ ▼ │ │ 4. 设置 response_handler检查状态码 │ │ │ │ │ ▼ │ │ 5. 设置 content_receiver数据接收器 │ │ │ │ │ ├──▶ 追加数据到 buffer │ │ │ │ │ ├──▶ 按 \n\n 分割数据块 │ │ │ │ │ ├──▶ 解析 data: 前缀的 SSE 事件 │ │ │ │ │ ├──▶ 检测 [DONE] 结束标记 │ │ │ │ │ ├──▶ 提取 delta.content 增量内容 │ │ │ │ │ └──▶ 调用 callback(content, false) │ │ │ │ │ ▼ │ │ 6. 流结束调用 callback(, true) │ │ │ │ │ ▼ │ │ 7. 返回聚合的完整响应 │ └──────────────────────────────────────────────────────────────┘SSE 数据格式data: {choices:[{delta:{content:你}}]} data: {choices:[{delta:{content:好}}]} data: {choices:[{delta:{content:}}]} data: [DONE]流式处理关键代码// 设置数据接收处理器req.content_receiver[](constchar*data,size_t len,size_t offset,size_t totallength){buffer.append(data,len);// 按 \n\n 分割 SSE 事件size_t pos0;while((posbuffer.find(\n\n,pos))!std::string::npos){std::string chunkbuffer.substr(0,pos);buffer.erase(0,pos2);if(chunk.compare(0,6,data: )0){std::string modelDatachunk.substr(6);if(modelData[DONE]){streamFinishedtrue;returntrue;}// 解析 JSON 提取增量内容Json::Value modelDataJson;// ...std::string contentmodelDataJson[choices][0][delta][content].asString();fullResponsecontent;callback(content,false);}}returntrue;};3.2 ChatGPTProviderOpenAI 新 API 格式3.2.1 基本信息属性值模型名称gpt-4o-miniAPI 端点https://api.openai.comAPI 路径/v1/responses新 API代理设置http://127.0.0.1:7890硬编码3.2.2 与 DeepSeek 的主要差异差异点ChatGPTProviderDeepSeekProviderAPI 路径/v1/responses/v1/chat/completions请求字段input数组messages数组响应字段output[0].content[0].textchoices[0].message.content流式事件response.output_text_delta等data:delta.content代理强制设置代理无代理3.2.3 请求体格式差异ChatGPT 请求体{model:gpt-4o-mini,input:[// 注意使用 input 而非 messages{role:user,content:你好}],temperature:0.7,max_output_tokens:2048// 注意字段名不同}响应体格式{output:[{content:[{text:你好有什么我可以帮助你的吗}]}]}3.2.4 流式事件类型ChatGPT 使用**事件类型event type**区分不同阶段事件类型说明response.output_text_delta增量文本内容response.output_item.done单个输出项完成包含完整文本response.completed整个响应完成SSE 格式event: response.output_text_delta data: {delta: 你} event: response.output_item.done data: {item: {content: [{text: 你好}]}} event: response.completed data: {}3.2.5 代理设置硬编码// 硬编码代理地址client.set_proxy(http://127.0.0.1,7890);问题代理地址硬编码不同网络环境需要修改源码。3.3 GeminiProviderGoogle OpenAI 兼容模式3.3.1 基本信息属性值模型名称gemini-2.0-flashAPI 端点https://generativelanguage.googleapis.comAPI 路径/v1beta/openai/chat/completions协议格式OpenAI 兼容模式3.3.2 与 DeepSeek 的差异差异点GeminiProviderDeepSeekProviderAPI 路径/v1beta/openai/chat/completions/v1/chat/completions代理强制设置代理无代理响应格式OpenAI 兼容相同OpenAI 兼容相同3.3.3 initModel 特殊点// 注意配置键名是 api_Key大小写敏感autoapiKey_itmodelConfig.find(api_Key);autoendpointItmodelConfig.find(endpoint);if(apiKey_itmodelConfig.end()||endpointItmodelConfig.end()){ERR(api_Key or endpoint not found);returnfalse;}问题键名api_Key与其他 Provider 的api_key不一致大小写差异。3.3.4 流式响应与 DeepSeek 相同使用标准 SSE 格式通过delta.content提取增量内容。3.4 OllamaLLMProvider本地模型3.4.1 基本信息属性值模型名称用户指定如deepseek-r1:1.5bAPI 端点用户指定如http://localhost:11434API 路径/api/chat认证方式无需 API Key3.4.2 特殊成员变量protected:std::string _modelName;// 模型名称动态std::string _modelDesc;// 模型描述信息特点不使用_apiKey模型名称通过配置动态指定。3.4.3 initModel 实现boolOllamaLLMProvider::initModel(conststd::mapstd::string,std::stringmodelConfig){// 必需参数model_nameif(modelConfig.find(model_name)modelConfig.end()){ERR(model_name not found);returnfalse;}_modelNamemodelConfig.at(model_name);// 必需参数model_descif(modelConfig.find(model_desc)modelConfig.end()){ERR(model_desc not found);returnfalse;}_modelDescmodelConfig.at(model_desc);// 必需参数endpointif(modelConfig.find(endpoint)modelConfig.end()){ERR(endpoint not found);returnfalse;}_endpointmodelConfig.at(endpoint);_isAvailabletrue;returntrue;}必需配置项model_nameOllama 模型名称如deepseek-r1:1.5bmodel_desc模型描述用于展示endpointOllama 服务地址如http://localhost:114343.4.4 请求体格式{model:deepseek-r1:1.5b,messages:[{role:user,content:你好}],options:{temperature:0.7,num_ctx:1024},stream:false}差异使用options包装温度等参数使用num_ctx而非max_tokens3.4.5 响应体格式{message:{role:assistant,content:你好有什么我可以帮助你的吗}}差异响应结构与其他 API 不同没有choices数组。3.4.6 流式响应格式非 SSE关键差异Ollama 流式响应不使用 SSE 格式而是每行一个 JSON 对象{message:{content:你},done:false}{message:{content:好},done:false}{message:{content:},done:true}流式处理代码// 按 \n 分割而非 \n\nwhile((posbuffer.find(\n,pos))!std::string::npos){std::string chunkbuffer.substr(0,pos);buffer.erase(0,pos1);// 解析 JSONJson::Value chunkJson;// ...// 检查结束标记done 字段if(chunkJson.get(done,false).asBool()){streamFinishtrue;callback(,true);returntrue;}// 提取内容std::string deltachunkJson[message][content].asString();fullDatadelta;callback(delta,false);}四、四种 Provider 对比总结4.1 基础信息对比Provider模型名称API 路径协议格式认证方式DeepSeekProviderdeepseek-chat/v1/chat/completionsOpenAI 标准Bearer TokenChatGPTProvidergpt-4o-mini/v1/responsesOpenAI 新格式Bearer TokenGeminiProvidergemini-2.0-flash/v1beta/openai/chat/completionsOpenAI 兼容Bearer TokenOllamaLLMProvider用户指定/api/chatOllama 原生无4.2 初始化参数对比Provider必需参数可选参数DeepSeekProviderapi_keyendpoint有默认值ChatGPTProviderapi_key,endpoint无GeminiProviderapi_Key,endpoint无OllamaLLMProvidermodel_name,model_desc,endpoint无4.3 请求体格式对比// DeepSeek / GeminiOpenAI 标准{model:deepseek-chat,messages:[...],temperature:0.7,max_tokens:2048,stream:true}// ChatGPT新 API{model:gpt-4o-mini,input:[...],// 字段名不同temperature:0.7,max_output_tokens:2048,// 字段名不同stream:true}// Ollama原生格式{model:deepseek-r1:1.5b,messages:[...],options:{// 嵌套结构temperature:0.7,num_ctx:1024// 字段名不同},stream:true}4.4 流式响应处理对比Provider数据分割符结束标记增量内容路径DeepSeekProvider\n\ndata: [DONE]choices[0].delta.contentChatGPTProvider\n\nevent: response.completeddelta或output_item.doneGeminiProvider\n\ndata: [DONE]choices[0].delta.contentOllamaLLMProvider\ndone: truemessage.content