LLMManager不是银弹:是工具而非魔法

文章配图


🎬 艾莉丝的简介:


文章目录

  • 1 ~> LLMManager 类架构与智能指针选型
    • 1.1 核心组件定义
      • 1.1.1 类职责与成员变量
    • 1.1.2 ModelInfo 元信息结构体
    • 1.2 智能指针选型优化
      • 1.2.1 初始方案缺陷
    • 1.2.2 优化方案:unique_ptr 独占语义
    • 1.3 unique_ptr 核心特性与容器适配
      • 1.3.1 拷贝语义禁用
    • 1.3.2 容器插入方式
  • 2 ~> 模型注册接口实现
    • 2.1 接口签名定义
    • 2.2 执行流程
    • 2.3 完整实现代码
  • 3 ~> 模型初始化接口实现
    • 3.1 接口签名定义
    • 3.2 执行流程
    • 3.3 完整实现代码
  • 4 ~> 模型查询与可用性检测
    • 4.1 获取可用模型列表
    • 4.2 单模型可用性检测
  • 5 ~> 消息发送接口实现
    • 5.1 全量同步消息接口
      • 5.1.1 接口定义
    • 5.1.2 前置校验机制
    • 5.1.3 实现代码
    • 5.2 流式增量消息接口
      • 5.2.1 接口定义
    • 5.2.2 实现逻辑
  • 结尾


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

1.1 核心组件定义

1.1.1 类职责与成员变量

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

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

1.1.2 ModelInfo 元信息结构体

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

struct ModelInfo {
    std::string _modelName;    
    std::string _modelDesc;    
    std::string _provider;     
    std::string _endpoint;     
    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:

    bool registerProvider(const std::string& modelName,
                          std::unique_ptr<LLMProvider> provider);
private:
    std::map<std::string, std::unique_ptr<LLMProvider>> _providers;
    std::map<std::string, ModelInfo> _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<LLMProvider> 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:

    bool initModel(const std::string& modelName,
                   const std::map<std::string, std::string>& modelParam);
};
}

3.2 执行流程

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

3.3 完整实现代码

bool LLMManager::initModel(const std::string& modelName,
                           const std::map<std::string, std::string>& 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<Message>& messages,
                                    const std::map<std::string, std::string>& 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 "";
    }

    return it->second->sendMessage(messages, requestParam);
}

5.2 流式增量消息接口

5.2.1 接口定义

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

5.2.2 实现逻辑

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

结尾

0

评论0

请先
显示验证码
没有账号?注册  忘记密码?