大型语言模型 (LLM) 正在给各个行业带来革命性的变化。从客户服务聊天机器人到复杂的数据分析工具,这项强大技术的功能正在重塑数字交互和自动化的格局。
然而,LLM 的实际应用可能会受到对高性能计算的需求或对快速响应时间的需求的限制。这些模型通常需要复杂的硬件和广泛的依赖性,这使得它们很难在更受限的环境中采用。
这就是 LLaMa.cpp 发挥作用的地方,它为重量级框架提供了更轻、更便携的替代方案。
什么是 Llama.cpp?
LLaMa.cpp 由 Georgi Gerganov 开发。它以高效的 C/C++ 实现了 Meta 的 LLaMa 架构,是围绕 LLM 推理最活跃的开源社区之一,拥有超过 390 名贡献者、官方 GitHub 存储库上的 43000 多个 star 和 930 多个版本。
- 通用兼容性: Llama.cpp 的设计是 CPU 优先的 C++ 库,这意味着复杂性更低,并且可以无缝集成到其他编程环境中。这种广泛的兼容性加速了它在各种平台上的采用。
- 全面的功能集成:作为关键低级功能的存储库,Llama.cpp 反映了 LangChain 的高级功能方法,简化了开发流程,尽管未来可能面临可扩展性挑战。
- 重点优化: Llama.cpp 专注于单一模型架构,实现精确有效的改进。它通过 GGML 和 GGUF 等格式对 Llama 模型的承诺带来了显着的效率提升。
了解 Llama.cpp 后,本教程的下一部分将逐步介绍实现文本生成用例的过程。我们首先探索 LLama.cpp 基础知识,了解当前项目的整体端到端工作流程,并分析其在不同行业中的一些应用。
Llama.cpp 架构
Llama.cpp 的主干是原始的 Llama 模型,它也基于 Transformer 架构。 Llama 的作者利用了随后提出的各种改进,并使用了不同的模型,例如 PaLM。
LLaMa 架构与 Transformer 架构的主要区别:
- 预归一化(GPT3):用于通过使用 RMSNorm 方法对每个 Transformer 子层的输入进行归一化来提高训练稳定性,而不是对输出进行归一化。
- SwigGLU激活函数(PaLM):将原来的非线性ReLU激活函数替换为SwiGLU激活函数,从而带来性能提升。
- 旋转嵌入(GPTNeao):在删除绝对位置嵌入后,在网络的每一层添加旋转位置嵌入(RoPE)。
设置环境
开始使用 LLama.cpp 的先决条件包括:
Python
:能够运行 pip,即 Python 包管理器Llama-cpp-python
:llama.cpp 的 Python 绑定
创建虚拟环境
建议创建虚拟环境,以避免与安装过程相关的任何问题,conda 是创建环境的良好候选者。
本节中的所有命令都是从终端运行的。使用该conda create
语句,我们创建一个名为 的虚拟环境llama-cpp-env
。
conda create --name llama-cpp-env
成功创建虚拟环境后,我们使用语句激活上述虚拟环境conda activate
,如下:
conda activate llama-cpp-env
现在,我们可以llama-cpp-python
按如下方式安装该包:
pip install llama-cpp-python
or
pip install llama-cpp-python==0.1.48
执行成功则说明llama_cpp_script.py
该库已正确安装。
为了确保安装成功,让我们创建并添加语句import
,然后执行脚本。
- 首先,将 添加到文件
from llama_cpp import Llama
中llama_cpp_script.py
,然后 - 运行 python
llama_cpp_script.py
来执行该文件。如果库导入失败会抛出错误;因此,需要对安装过程进行进一步诊断。
了解 Llama.cpp 基础知识
在此阶段,安装过程应该会成功,让我们深入了解 LLama.cpp 的基础知识。
上面导入的 Llama 类是使用 Llama.cpp 时使用的主要构造函数,它需要多个参数,并且不限于以下参数。官方文档中提供了完整的参数列表:
model_path
:正在使用的 Llama 模型文件的路径- 提示:模型的输入提示。该文本被标记化并传递给模型。
- device:用于运行 Llama 模型的设备;这样的设备可以是CPU或GPU。
max_tokens
:模型响应中生成的最大令牌数- stop:将导致模型生成过程停止的字符串列表
- 温度:该值范围在 0 到 1 之间。值越低,最终结果越确定。另一方面,较高的值会导致更多的随机性,从而产生更加多样化和创造性的输出。
- top_p:用于控制预测的多样性,这意味着它选择累积概率超过给定阈值的最可能的标记。从零开始,较高的值会增加找到更好输出的机会,但需要额外的计算。
- echo:一个布尔值,用于确定模型是否在开头包含原始提示(True)或不包含它(False)
例如,假设我们要使用存储在当前工作目录中的名为 <MY_AWESOME_MODEL> 的大型语言模型,实例化过程将如下所示:
# Instanciate the model
my_aweseome_llama_model = Llama(model_path="./MY_AWESOME_MODEL")
prompt = "This is a prompt"
max_tokens = 100
temperature = 0.3
top_p = 0.1
echo = True
stop = ["Q", "\n"]
# Define the parameters
model_output = my_aweseome_llama_model(
prompt,
max_tokens=max_tokens,
temperature=temperature,
top_p=top_p,
echo=echo,
stop=stop,
)
final_result = model_output["choices"][0]["text"].strip()
模型的结果是一个字典,其中包含生成的响应以及一些附加元数据。本文的下一部分将探讨输出的格式。
构建第一个 Llama.cpp 项目
现在就可以开始实施文本生成项目了。启动一个新的 Llama.cpp 项目只需遵循上面的 python 代码模板即可,该模板解释了从加载感兴趣的大型语言模型到生成最终响应的所有步骤。
该项目利用Hugging Face 的Zephyr-7B-Beta 的 GGUF 版本。它是Mistralai/Mistral-7B-v0.1的微调版本,使用直接偏好优化 (DPO)在公开可用的合成数据集上进行了训练。
将模型下载到本地后,我们可以将其移动到文件夹中的项目位置model
。在深入实施之前,我们先了解一下项目结构:
第一步是使用Llama
构造函数加载模型。由于这是一个大型模型,因此指定要加载的模型的最大上下文大小非常重要。在这个具体项目中,我们使用了 512 个 token 。
from llama_cpp import Llama
# GLOBAL VARIABLES
my_model_path = "./model/zephyr-7b-beta.Q4_0.gguf"
CONTEXT_SIZE = 512
# LOAD THE MODEL
zephyr_model = Llama(model_path=my_model_path,
n_ctx=CONTEXT_SIZE)
加载模型后,下一步是使用原始代码模板的文本生成阶段,我们可以构建一个辅助函数generate_text_from_prompt
。
def generate_text_from_prompt(user_prompt,
max_tokens = 100,
temperature = 0.3,
top_p = 0.1,
echo = True,
stop = ["Q", "\n"]):
# Define the parameters
model_output = zephyr_model(
user_prompt,
max_tokens=max_tokens,
temperature=temperature,
top_p=top_p,
echo=echo,
stop=stop,
)
return model_output
在该__main__
子句中,可以使用给定的提示(prompt)来执行该函数。
if __name__ == "__main__":
my_prompt = "What do you think about the inclusion policies in Tech companies?"
zephyr_model_response = generate_text_from_prompt(my_prompt)
print(zephyr_model_response)
模型响应如下:
模型生成的响应为 ,<What do you think about the inclusion policies in Tech companies?>
并且模型的确切响应在橙色框中突出显示。
- 原来的提示有12个token
- 响应或完成令牌有 10 个token
- 总 token 数目为上述两个 token 之和,即22
尽管这个完整的输出可用于进一步使用,但我们可能只对模型的文本响应感兴趣。我们可以通过选择“text”
“元素的字段来格式化响应以获得这样的结果,choices”
如下所示:
final_result = model_output["choices"][0]["text"].strip()
该strip()
函数用于删除字符串中的所有前导和尾随空格,结果为:
Tech companies want diverse workforces to build better products.
结论
本文全面概述了如何通过 LLama.cpp 设置和使用大型语言模型,提供了详细的说明,用于了解 Llama.cpp 的基础知识、设置工作环境、安装所需的库以及实现文本生成(问答)用例,并为实际应用程序以及如何使用 Llama.cpp 有效解决根本问题提供了实用见解。