笔记 | 【AI大模型接入SDK】LLMManager类架构与智能指针选型

这两天一直在研究这个话题,踩了几个坑,把遇到的东西整理成文,供有需要的朋友参考。

🎬 个人主页:艾莉丝努力练剑

❄专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

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


🎬 艾莉丝的简介:

文章目录

1.2 智能指针选型优化 1.3 unique_ptr 核心特性与容器适配 2 ~> 模型注册接口达成 3 ~> 模型初始化接口达成 4 ~> 模型查询与可用性检测 5 ~> 消息发送接口实现 5.2 流式增量消息接口 结尾

1 ~> LLMManager 类架构与智能指针选型

1.1 核心组件定义

1.1.1 类职责与成员变量

LLMManager 是大语言模型 SDK 的统一管理入口,负责 LLM 提供者的生命周期托管、注册状态维护、可用性校验与请求转发。

  • 私有成员:
std::map _providers:键为模型唯一名称,值为模型提供者实例的独占智能指针,所有权由 LLMManager 全权持有
  • std::map _modelInfos:键为模型名称,值为模型元信息集合,存储描述、端点、可用状态等数据

1.1.2 ModelInfo 元信息结构体

用于标准化描述 LLM 模型的基础属性,作为对外暴露模型信息的统一数据结构。

struct ModelInfo {
    std::string _modelName;    // 模型唯一标识名称
    std::string _modelDesc;    // 模型功能描述
    std::string _provider;     // 模型提供厂商
    std::string _endpoint;     // API服务基础端点
    bool _isAvailable = false; // 模型初始化完成、可服务状态标记

    ModelInfo(const std::string& modelName,
              const std::string& modelDesc,
              const std::string& provider,
              const std::string& endpoint)
        : _modelName(modelName),
          _modelDesc(modelDesc),
          _provider(provider),
          _endpoint(endpoint) {}
};

1.2 智能指针选型优化

1.2.1 初始方案缺陷

初始设计采用std::shared_ptr<LLMProvider>管理提供者实例,存在设计冗余:

  • LLMProvider 实例仅在 LLMManager 内部使用,无跨类共享场景
  • shared_ptr 的引用计数机制带来额外内存与性能开销
  • 不符合独占所有权的设计语义,存在意外共享导致生命周期错乱的风险

1.2.2 优化方案:unique_ptr 独占语义

替换为std::unique_ptr<LLMProvider>,完全匹配设计需求:

  • 严格遵循 RAII 独占所有权原则,资源由 LLMManager 唯一持有
  • 无引用计数开销,运行时性能更优
  • 编译期强制禁止拷贝,从语法层面保证资源唯一性

1.3 unique_ptr 核心特性与容器适配

1.3.1 拷贝语义禁用

  • C++11 标准:通过= delete显式删除拷贝构造函数与拷贝赋值运算符
  • C++98 兼容方案:将拷贝构造、拷贝赋值声明为 private 且不提供实现
  • 直接赋值 unique_ptr 会触发编译错误,务必通过移动语义完成所有权转移

1.3.2 容器插入方法

向 std::map 等容器插入 unique_ptr 时,务必通过std::move转移资源所有权,不能直接拷贝赋值。


2 ~> 模型注册接口实现

2.1 接口签名定义

namespace ai_chat_sdk {
class LLMManager {
public:
    // 注册LLM提供者实例
    // @param modelName 模型唯一标识
    // @param provider 模型提供者独占指针
    // @return 注册成功返回true,失败返回false
    bool registerProvider(const std::string& modelName,
                          std::unique_ptr provider);
private:
    std::map _providers;
    std::map _modelInfos;
};
}

2.2 执行流程

1. 参数合法性校验:检测 provider 是否为空指针,空指针直接终止流程并输出错误日志
2. 资源所有权转移:通过std::move将 provider 实例的所有权转移至_providers 容器
3. 元信息初始化:向_modelInfos 插入对应模型的初始元信息对象
4. 状态返回:注册完成输出信息日志,返回 bool 类型的注册结果

2.3 完整实现代码

#include "../include/LLMManager.h"
#include "../include/util/myLog.h"
#include "../include/Common.h"

namespace ai_chat_sdk {

bool LLMManager::registerProvider(const std::string& modelName,
                                  std::unique_ptr provider) {
    // 空指针校验:禁止注册无效提供者
    if (!provider) {
        ERR("cannot register nullptr provider, modelName={}", modelName);
        return false;
    }

    // 移动语义转移所有权,存入提供者容器
    _providers[modelName] = std::move(provider);

    // 初始化模型元信息
    _modelInfos[modelName] = ModelInfo(modelName);

    INFO("register provider success, modelName={}", modelName);
    return true;
	}
}


3 ~> 模型初始化接口实现

3.1 接口签名定义

namespace ai_chat_sdk {
class LLMManager {
public:
    // 初始化指定模型
    // @param modelName 目标模型名称
    // @param modelParam 模型初始化配置参数键值对
    // @return 初始化成功返回true,失败返回false
    bool initModel(const std::string& modelName,
                   const std::map& modelParam);
};
}

3.2 执行流程

1. 注册状态校验:在_providers 中查找目标模型,未注册则直接返回失败
2. 底层初始化调用:通过迭代器获取 LLMProvider 实例,调用其 initModel 方法传入配置
3. 状态更新:初始化成功后,更新_modelInfos 中的模型描述、可用状态标记
4. 错误处理:初始化失败时输出错误日志,向上层返回失败状态

3.3 完整实现代码

bool LLMManager::initModel(const std::string& modelName,
                           const std::map& modelParam) {
    // 校验模型是否已注册
    auto it = _providers.find(modelName);
    if (it == _providers.end()) {
        ERR("model provider not found, modelName={}", modelName);
        return false;
    }

    // 调用底层提供者执行初始化
    bool isSuccess = it->second->initModel(modelParam);
    if (!isSuccess) {
        ERR("init model failed, modelName={}", modelName);
        return false;
    }

    // 初始化成功,更新元信息与可用状态
    INFO("init model success, modelName={}", modelName);
    _modelInfos[modelName]._modelDesc = it->second->getModelDesc();
    _modelInfos[modelName]._isAvailable = true;

    return isSuccess;
}


4 ~> 模型查询与可用性检测

4.1 获取可用模型列表

  • 功能:返回所有已完成初始化、状态为可用的模型元信息集合
  • 实现逻辑:遍历_modelInfos 容器,筛选_isAvailable为 true 的条目存入 vector 返回
  • 实现代码:
std::vector LLMManager::getAvailableModels() const {
    std::vector models;
    for (const auto& pair : _modelInfos) {
        // 仅返回处于可用状态的模型
        if (pair.second._isAvailable) {
            models.push_back(pair.second);
        }
    }
    return models;
}

4.2 单模型可用性检测

  • 功能:查询指定名称的模型是否处于可服务状态
  • 实现逻辑:先校验模型是否存在,不存在直接返回 false;存在则返回其可用状态标记
  • 实现代码:
bool LLMManager::isModelAvailable(const std::string& modelName) const {
    auto it = _modelInfos.find(modelName);
    if (it == _modelInfos.end()) {
        return false;
    }
    return it->second._isAvailable;
}

5 ~> 消息发送接口实现

5.1 全量同步消息接口

5.1.1 接口定义

  • 功能:向指定模型发送对话消息,同步等待完整响应结果
  • 返回值:std::string类型的模型完整响应文本

5.1.2 前置校验机制

1. 校验模型是否已完成注册(_providers 中存在对应条目)
2. 校验模型是否已初始化且处于可用状态
3. 任意校验失败均输出错误日志并返回空字符串

5.1.3 实现代码

std::string LLMManager::sendMessage(const std::string& modelName,
                                    const std::vector& messages,
                                    const std::map& requestParam) {
    // 校验模型注册状态
    auto it = _providers.find(modelName);
    if (it == _providers.end()) {
        ERR("model provider not found, modelName={}", modelName);
        return "";
    }

    // 校验模型可用状态
    if (!it->second->isAvailable()) {
        ERR("model not available, modelName={}", modelName);
        return "";
    }

    // 转发请求到底层LLM提供者实现
    return it->second->sendMessage(messages, requestParam);
}

5.2 流式增量消息接口

5.2.1 接口定义

  • 功能:向指定模型发送流式对话请求,支持增量式返回响应内容
  • 返回值:bool类型标识流式请求是否成功启动

5.2.2 实现逻辑

  • 前置校验逻辑与全量接口完全一致
  • 校验通过后调用底层 LLMProvider 的sendMessageStream方法
  • 流式数据的拼接、回调输出由底层提供者具体实现,LLMManager 仅做转发

结尾

uu们,本文的内容到这里就全部完成了,艾莉丝在这里再次

艾莉丝努力练剑

C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主


👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。

❤️
【点赞】 让优质内容被更多人看见,让知识传递更有力量。


【收藏】 把核心知识点存好,在得时随时查、随时用。

💬
【评论】 分享各位的经验或疑问,评论区一起交流避坑!

不要忘记给博主“一键四连”哦!

“今日练剑达成!”

“技术之路难免有困惑,但同行的人会让前进更有方向。”

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

往期回顾

【AI大模型接入SDK】LLMManager架构设计与实现

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

本次分享就到这里。技术这东西越研究越有意思,后续有新的收获我也会继续更新。

评论 (0)

暂无评论