
InferLLM大模型推理框架项目(13)——计算图的工厂方法实现(src/graph/graph_imp.cpp)
graph_imp.cpp 代码结构与功能实现分析
graph_imp.cpp
是 InferLLM 框架中的一个核心文件,主要实现了计算图的工厂方法,用于根据模型名称创建相应的计算图实例。这个文件虽然简短,但在整个框架中扮演着重要的角色。
1. 文件结构
graph_imp.cpp
文件包含以下几个部分:
-
头文件引入:
#include "chatGLM.h" #include "ggml_llama.h" #include "llama_like.h"
引入了三个头文件,分别对应不同的模型实现:
chatGLM.h
:包含 ChatGLM 系列模型的定义ggml_llama.h
:包含 GGML 格式的 Llama 模型定义llama_like.h
:包含类 Llama 架构的模型定义(如 Baichuan 和 Llama2)
-
命名空间声明:
using namespace inferllm;
使用 inferllm 命名空间,这是整个框架的主命名空间。
-
工厂方法实现:
std::shared_ptr<Graph> Graph::make_graph( UserConfig model_config, Device* device, const std::string& name) { // 根据模型名称创建相应的计算图实例 }
实现了
Graph
类的静态方法make_graph
,用于创建计算图实例。
2. 功能实现
2.1 工厂方法 make_graph
make_graph
方法是一个典型的工厂方法,根据传入的模型名称 name
创建相应的计算图实例:
std::shared_ptr<Graph> Graph::make_graph(
UserConfig model_config, Device* device, const std::string& name) {
if (name == "llama") {
return std::make_shared<GgmlLlamaGraph>(model_config, device, name);
} else if (name == "chatglm") {
return std::make_shared<ChatGLMGraph>(model_config, device, name);
} else if (name == "chatglm2") {
return std::make_shared<ChatGLMGraph2>(model_config, device, name);
} else if (name == "chatglm3") {
return std::make_shared<ChatGLMGraph3>(model_config, device, name);
} else if (name == "baichuan" || name == "llama2") {
return std::make_shared<LlamaLikeGraph>(model_config, device, name);
} else {
INFER_ASSERT(0, "unsupported model.");
}
}
该方法接收三个参数:
model_config
:用户配置,包含模型的各种配置参数device
:设备指针,指向执行计算的设备(如 CPU 或 GPU)name
:模型名称,用于确定创建哪种类型的计算图
根据模型名称,该方法创建以下几种计算图:
"llama"
:创建GgmlLlamaGraph
实例,用于处理 GGML 格式的 Llama 模型"chatglm"
:创建ChatGLMGraph
实例,用于处理 ChatGLM 模型"chatglm2"
:创建ChatGLMGraph2
实例,用于处理 ChatGLM2 模型"chatglm3"
:创建ChatGLMGraph3
实例,用于处理 ChatGLM3 模型"baichuan"
或"llama2"
:创建LlamaLikeGraph
实例,用于处理类 Llama 架构的模型
如果传入的模型名称不在上述列表中,则通过 INFER_ASSERT
宏触发断言,提示不支持该模型。
3. 设计模式分析
3.1 工厂模式
graph_imp.cpp
文件实现了典型的工厂模式,具体来说是简单工厂模式(Simple Factory Pattern):
- 工厂方法:
Graph::make_graph
是一个静态工厂方法,负责创建具体的产品(计算图实例) - 抽象产品:
Graph
是抽象产品,定义了计算图的接口 - 具体产品:
GgmlLlamaGraph
、ChatGLMGraph
、ChatGLMGraph2
、ChatGLMGraph3
和LlamaLikeGraph
是具体产品,实现了计算图的接口
这种设计有以下优点:
- 封装创建逻辑:客户端不需要知道如何创建具体的计算图,只需要提供模型名称
- 扩展性:可以方便地添加新的模型支持,只需在工厂方法中添加新的条件分支
- 统一接口:所有计算图都实现了相同的接口,客户端可以统一处理
3.2 策略模式
虽然不是直接在 graph_imp.cpp
中实现,但整个计算图系统也体现了策略模式(Strategy Pattern):
- 上下文:使用计算图的客户端代码
- 策略接口:
Graph
类定义的接口 - 具体策略:不同的计算图实现(如
ChatGLMGraph
、GgmlLlamaGraph
等)
这种设计使得客户端可以在运行时选择不同的计算图实现,而不需要修改客户端代码。
4. 与其他组件的交互
graph_imp.cpp
文件通过工厂方法与框架的其他组件进行交互:
-
与模型实现的交互:
- 引入不同模型的头文件(
chatGLM.h
、ggml_llama.h
、llama_like.h
) - 创建不同模型的计算图实例
- 引入不同模型的头文件(
-
与设备的交互:
- 接收
Device*
参数,将设备传递给计算图实例 - 计算图实例使用设备进行计算
- 接收
-
与用户配置的交互:
- 接收
UserConfig
参数,将用户配置传递给计算图实例 - 计算图实例根据用户配置调整行为
- 接收
5. 扩展性分析
graph_imp.cpp
文件的设计具有良好的扩展性:
-
添加新模型:
要添加新的模型支持,只需:- 创建新的计算图类,继承自
Graph
- 在
make_graph
方法中添加新的条件分支
- 创建新的计算图类,继承自
-
修改现有模型:
修改现有模型的实现不需要修改graph_imp.cpp
文件,只需修改相应的计算图类。
总结
graph_imp.cpp
文件虽然简短,但在 InferLLM 框架中扮演着重要的角色,实现了计算图的工厂方法,使得框架可以支持多种不同的模型。它采用了工厂模式和策略模式的设计,具有良好的封装性和扩展性,为框架提供了灵活的模型支持机制。
通过这个文件,我们可以看到 InferLLM 框架的模块化设计思想,以及如何通过设计模式实现灵活的组件组合。这种设计使得框架可以方便地支持新的模型,而不需要大幅修改现有代码。
