ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

【AI大模型接入SDK】Provider分析与实现

2026/8/31 18:44:33 拓冰建站 浏览量
【AI大模型接入SDK】Provider分析与实现 个人主页艾莉丝努力练剑❄专栏传送门《C语言》《数据结构与算法》《C/C干货分享学习过程记录》《Linux操作系统编程详解》《笔试/面试常见算法从基础到进阶》《Python干货分享》⭐️为天地立心为生民立命为往圣继绝学为万世开太平 艾莉丝的简介文章目录1 ~ LLMProvider1.1 业务背景与需求分析1.1.1 业务场景1.1.2 模型调用原始操作步骤1.1.3 Provider 必须实现的能力集合1.1.4 共性与差异分析1.2 C 继承、多态与抽象类设计1.2.1 问题直接硬编码各个模型类的弊端1.2.2 解决方案抽取顶层抽象基类 LLMProvider1.2.3 C 多态调用1.3 底层设计模式策略模式1.3.1 策略模式核心定义1.3.2 通俗示例代码出行策略1.3.3 映射到本项目1.4 LLMProvider 抽象基类完整头文件实现1.5 派生实现类工作逻辑例如 DeepSeekProvider1.6 整体架构分层总览1.7 架构优势总结1.8 面试 / 考试易错考点结尾1 ~ LLMProvider基于 C 策略模式实现多大模型统一接入 SDK。1.1 业务背景与需求分析1.1.1 业务场景需要接入多款大模型DeepSeek、ChatGPT、Gemini、Ollama 本地模型等对外提供统一 SDK上层业务不需要感知底层模型厂商 API 差异。 前期已完成公共数据结构、日志库封装现在完成模型接入层架构设计。1.1.2 模型调用原始操作步骤获取模型厂商 API‑Key阅读厂商 HTTP API 文档程序内部发起 HTTP 请求调用模型接口1.1.3 Provider 必须实现的能力集合每一个模型接入实现类都必须具备以下功能模型初始化加载配置apikey、endpoint 等初始化状态检测判断模型是否配置合法、可用非流式消息发送streamfalse全量一次性返回完整应答流式消息发送streamtrue增量分片返回流式回调输出获取模型名称获取模型描述信息使用场景前端页面展示可用模型列表展示每个模型名称、简介、能力标签。1.1.4 共性与差异分析公共部分初始化、可用性检测、发送消息接口定义、持有 apikey/endpoint/ 可用状态标记差异部分每个模型的 base‑url (endpoint) 不同模型名称、描述文本不同HTTP 请求体参数结构不同HTTP 响应 JSON 解析逻辑不同1.2 C 继承、多态与抽象类设计1.2.1 问题直接硬编码各个模型类的弊端如果每个模型独立写一套完整类会出现大量重复代码业务层调用需要大量if‑else分支判断模型类型// 糟糕的if‑else写法 if(modelName deepseek) { DeepSeekProvider dp; dp.sendMessage(...); } else if(modelName chatgpt) { ChatGPTProvider gp; gp.sendMessage(...); } // 新增模型必须修改此处业务判断代码违反开闭原则1.2.2 解决方案抽取顶层抽象基类LLMProvider将所有模型公共接口抽至顶层基类将接口声明为纯虚函数virtual 函数签名 0;使LLMProvider成为抽象类。抽象类禁止实例化基类不绑定任何具体大模型实例化无业务意义只定义接口规范由子类完成全部业务实现。各个厂商模型实现类继承该抽象基类重写全部纯虚函数。继承关系基类LLMProvider抽象类 / 接口类只定义契约派生实现类DeepSeekProvider/ChatGPTProvider/GeminiProvider/OllamaDeepSeekProvider1.2.3 C 多态调用基类引用 / 基类指针可以指向派生类对象。业务函数只依赖抽象基类运行时传入不同子类对象自动调用对应子类实现消除大量 if‑else。// 业务层统一发送消息函数只依赖抽象基类 void SendMessage(LLMProvider provider) { // 根据传入对象的实际类型自动调用子类重写的sendMessage provider.sendMessage(...); }1.3 底层设计模式策略模式1.3.1 策略模式核心定义定义一系列算法 / 行为将每一套行为封装为独立类各个实现类可以互相替换通过抽象接口隔离调用方与具体实现运行时动态选择策略消除 if‑else 分支符合开闭原则。抽象策略抽象基类定义统一接口具体策略各个派生子类实现具体逻辑上下文业务调用方只操作抽象策略不感知底层实现1.3.2 通俗示例代码出行策略#include iostream // 抽象策略 class TransportStrategy{ public: virtual void go() 0; }; // 具体策略走路 class WalkStrategy : public TransportStrategy{ public: void go() override{ std::cout 走路去往目的地\n; } }; // 具体策略自行车 class BikeStrategy : public TransportStrategy{ public: void go() override{ std::cout 骑自行车去往目的地\n; } }; // 具体策略巴士 class BusStrategy : public TransportStrategy{ public: void go() override{ std::cout 坐巴士去往目的地\n; } }; // 上下文使用者 class Student{ private: TransportStrategy* m_strategy; public: void setStrategy(TransportStrategy* s){ m_strategy s; } void goToLab(){ m_strategy-go(); } }; int main() { Student me; me.setStrategy(new WalkStrategy()); me.goToLab(); me.setStrategy(new BusStrategy()); me.goToLab(); return 0; }1.3.3 映射到本项目抽象策略LLMProvider抽象基类定义所有模型必须实现的接口契约具体策略DeepSeekProvider、ChatGPTProvider等每一个模型实现类上下文SDK 上层、LLMManager管理器只和抽象基类交互运行时切换不同模型策略开闭原则新增模型只需要新增派生类不需要修改原有上层业务代码1.4 LLMProvider 抽象基类完整头文件实现文件路径sdk/include/LLMProvider.h#ifndef LLM_PROVIDER_H #define LLM_PROVIDER_H #include string #include map #include vector #include functional namespace ai_chat_sdk { // 消息结构体对话历史单元前置公共数据结构 struct Message{ std::string role; std::string content; }; /** * brief LLMProvider 大模型抽象基类(抽象接口) * 所有大模型接入都继承该类实现全部纯虚函数 * 不允许实例化定义统一的模型访问契约 */ class LLMProvider { public: // 虚析构多态继承场景必须提供虚析构保证子类析构被正确调用 virtual ~LLMProvider() default; /** * brief 初始化模型传入模型配置键值对 * param modelConfig key‑value配置apikey、endpoint等 */ virtual void initModel(const std::mapstd::string, std::string modelConfig) 0; /** * brief 检测模型是否初始化完成、可用 * return true可用false不可用 */ virtual bool isAvailable() const 0; /// brief 获取模型名称 virtual std::string getModelName() const 0; /// brief 获取模型描述信息 virtual std::string getModelDesc() const 0; /** * brief 发送消息非流式全量一次性返回结果 * param messages 完整对话上下文 * param requestParam 模型请求参数 temperature/max_tokens等 */ virtual void sendMessage(const std::vectorMessage messages, const std::mapstd::string, std::string requestParam) 0; /** * brief 发送消息流式增量返回 * param messages 对话上下文 * param requestParam 请求参数 * param callback 回调函数参数1分片字符串参数2是否为最后一块数据 * bool参数true代表还有后续分片false代表流式结束 */ virtual void sendMessageStream(const std::vectorMessage messages, const std::mapstd::string, std::string requestParam, std::functionvoid(const std::string, bool) callback) 0; protected: // 基类保护成员派生类可以直接访问 bool m_isAvailable false; /// 标记模型是否初始化可用 std::string m_apiKey; /// 模型厂商API密钥 std::string m_endpoint; /// API base‑url请求端点 }; } // namespace ai_chat_sdk #endif关键修正点说明增加虚析构函数virtual ~LLMProvider() default;多态继承场景必不可少防止子类析构不执行内存泄漏将成员变量修改为protected子类可以直接访问原文档写 private 子类无法读取配置修正原文档多处拼写笔误initodel → initModel、getodelDesc → getModelDesc回调std::function参数 const 引用避免不必要拷贝补充头文件保护宏#ifndef / #define / #endif。1.5 派生实现类工作逻辑例如 DeepSeekProviderDeepSeekProvider : public LLMProvider ├─ initModel从map读取apikey、endpoint赋值给继承而来的m_apiKey/m_endpoint设置m_isAvailable状态 ├─ isAvailable返回 m_isAvailable ├─ getModelName返回固定字符串 deepseek‑chat ├─ getModelDesc返回该模型的描述文本 ├─ sendMessage组装DeepSeek HTTP请求体发起HTTP调用解析完整JSON响应 └─ sendMessageStream组装请求开启stream读取SSE流式响应分片调用callback回调1.6 整体架构分层总览┌─────────────── LLMManager管理器───────────────┐ │ 业务层只操作抽象基类LLMProvider不感知具体模型 │ └───────────────────────┬──────────────────────────┘ ↓ ┌────────── LLMProvider(抽象基类) ──────────┐ │ 纯虚接口定义initModel / sendMessage / ...│ └───┬───────────────┬───────────────┬──────┘ ↓ ↓ ↓ DeepSeekProvider ChatGPTProvider GeminiProvider 实现厂商HTTP交互细节封装API差异1.7 架构优势总结消除大量 if‑else依靠 C 多态策略模式运行时动态切换模型实现。开闭原则新增大模型只需要新增继承LLMProvider的派生类原有上层代码不需要修改。统一 SDK 对外接口第三方使用者只需要依赖抽象接口不需要关心每家模型 HTTP 细节。接口强制约束抽象类纯虚函数强制派生类必须实现全部规定能力不会出现遗漏功能。兼容云端 API 模型、本地 Ollama 部署模型同一套框架复用。1.8 面试 / 考试易错考点抽象类含有纯虚函数不能实例化对象多态继承必须写虚析构函数否则 delete 基类指针时子类析构不会执行纯虚函数语法virtual 返回类型 函数名(参数) 0;策略模式核心封装可变行为运行时替换隔离调用方与具体实现protected 访问限定符基类成员希望子类可以访问、外部不能访问时使用不能设置为 private。结尾uu们本文的内容到这里就全部结束了艾莉丝在这里再次感谢您的阅读艾莉丝努力练剑C/C Linux 底层探索者 | 一个正在努力练剑的技术博主【关注】跟随我一起深耕技术领域见证每一次成长。❤️【点赞】让优质内容被更多人看见让知识传递更有力量。⭐【收藏】把核心知识点存好在需要时随时查、随时用。【评论】分享你的经验或疑问评论区一起交流避坑不要忘记给博主“一键四连”哦“今日练剑达成”“技术之路难免有困惑但同行的人会让前进更有方向。”结语希望对学习Linux相关内容的uu有所帮助不要忘记给博主“一键四连”哦往期回顾【AI大模型接入SDK】spdlog日志库封装博主在这里放了一只小狗大家看完了摸摸小狗放松一下吧૮₍ ˶ ˊ ᴥ ˋ˶₎ა