本地大模型LocalAI使用教程指南
LocalAI是 OpenAI 的开源替代品,它能在本地计算机上运行 LLM。不需要 GPU,消费级硬件就足够了
如果您可以使用与 OpenAI 相同的 Rest API 在本地运行模型,那不是很棒吗?嗯,这正是LocalAI必须为您提供的!
LocalAI 是 OpenAI 的开源替代方案,具有与 OpenAI API 规范兼容的 Rest API。除此之外,不需要 GPU,您可以在消费级硬件上运行它。不过,建议使用 GPU,因为它的速度大约快 20 倍。
此处描述了 LocalAI for CPU 的安装。
1、克隆 LocalAI git 存储库。
$ git clone https://github.com/go-skynet/LocalAI
2、导航到存储库目录。
$ cd LocalAI
3、存储库包含.env您需要自定义的文件。
- 取消注释THREADS:并将数字调整为您拥有的物理核心数量(在我的例子中为 12);
- 取消注释GALLERIES:并将其调整为安装指南中所述的galleries 。
## Set number of threads. |
4、启动 Docker 容器。
Docker 镜像引用的是最新标签,在撰写本文时,LocalAI 的 v2.0.0 是最新标签。你可以导航到镜像仓库,搜索最新标签,复制清单哈希值,然后搜索复制的清单哈希值。
$ docker compose up -d --pull always
请耐心等待,这需要一些时间。镜像文件约为 70GB。上一版本 v1.40.0 大约为 14GB。
当容器成功启动后,你应该可以检索到可用的模型:
$ curl http://localhost:8080/models/available
安装模型
首先,您需要安装一个模型。您可以通过应用程序接口的模型图库进行安装,但在撰写本文时,这仍处于试验阶段。我更喜欢手动添加模型。说明可以在这里找到,但要知道,随着时间的推移,说明可能会发生变化,所以不要完全依赖本段的内容。
在 models 目录下创建 lunademo.yaml 文件。将线程数改为你机器上的物理内核数。
name: lunademo |
模型指的是包含模型的文件。从 HuggingFace 将文件下载到模型目录。HuggingFace 包含许多您可以使用的开源模型,但在本示例中,您将使用基于 Llama 2 的模型,Llama 2 是由 Meta 创建的人工智能模型。请注意,在 "模型卡 "中,模型与其用例一起列出。此外,用例中还说明了建议使用的模型。请注意只能使用 GGUF 模型,Llama 2 不再支持 GGML。
还要注意的是,模型的配置文件中定义了两个模板。一个是聊天模板,另一个是完成模板。
在模型目录中创建一个文件 lunademo-chat.tmpl。该模板来自 HuggingFace 的模型卡(搜索 Prompt 模板)。
USER: {{.Input}} |
在模型目录下创建 lunademo-completion.tmpl 文件。
Complete the following sentence: {{.Input}} |
重启 Docker 容器以加载模型。
$ docker compose restart
提问
既然模型已经加载,您就可以开始提问了。您可以查看 OpenAPI 规范,以下是一些示例,以验证本地模型的响应情况和准确性。
你好吗?
作为第一个简单的例子,您可以询问模型感觉如何。在请求中,您可以提及要使用的模型、信息,还可以设置温度。温度越高,模型就越有创造力。模型回答说它做得很好。
$ curl http://localhost:8080/v1/chat/completions -H "Content-Type: application/json" -d '{ |
集成LangChain4j
上面展示了如何通过 LocalAI 运行类似于 OpenAI 的大型语言模型 (LLM)。
使用 OpenAI 的 Rest API 来与 LocalAI 交互。将这些功能集成到 Java 应用程序中可能会很麻烦。
LangChain4j 为您提供了与大模型集成的简化方法。它基于 Python 库LangChain。
LangChain4j 示例存储库中提供了许多示例。特别是,目录中的示例other-examples已被用作此博客的灵感。
本博客中使用的资源可以在GitHub上找到。
为了将 LangChain4j 与 LocalAI 结合使用,您需要将langchain4j-local-ai依赖项添加到 pom 文件中。
<dependency> |
为了与 LocalAI 集成,您需要创建一个指定以下项目的 ChatLanguageModel:
- 可访问 LocalAI 实例的 URL;
- 您希望在 LocalAI 中使用的模型名称;
- 温度,温度越高,模型的响应越有创意。
然后,要求模型生成问题的答案并打印出来。
ChatLanguageModel model = LocalAiChatModel.builder() |
启动 LocalAI 并运行上述示例。
响应与预期一致。
I'm doing well, thank you. How about yourself?
LanguageModel 和 ChatLanguageModel 之间的区别
这两个类在 LangChain4j 中都有,那么该选哪个呢?
- 聊天模型是语言模型的一种变体。如果您需要 "文本输入,文本输出 "功能,您可以选择 LanguageModel。
- 如果还想使用 "聊天信息 "作为输入和输出,则应使用 ChatLanguageModel。
在上面的示例中,你可以只使用 LanguageModel,它的表现也会类似。
嵌入文档
嵌入文档的最简单方法是阅读文档,将其分割成块,然后嵌入这些块。嵌入意味着将文本转换为向量(数字)。您要提出的问题也需要嵌入。
矢量存储在一个矢量存储库中,该存储库能找到与您的问题最接近的结果,并用这些结果作出回应。源代码source code由以下部分组成:
- 文本需要嵌入。为此需要一个嵌入模型,为简单起见,您可以使用 AllMiniLmL6V2EmbeddingModel。该模型使用 BERT 模型,这是一种流行的嵌入模型。
- 嵌入需要存储在一个嵌入存储库中。通常情况下,矢量数据库会被用于此目的,但在这种情况下,你可以使用内存中的嵌入存储。
- 读取两个文档并将其添加到 DocumentSplitter 中。在这里,您将定义将文档分割成 500 个字符且不重叠的片段。
- 通过文档分割器,文档被分割成文本段。
- 嵌入模型用于嵌入文本段。TextSegments 及其嵌入的对应内容都存储在嵌入存储区中。
- 问题也使用相同的模型嵌入。
- 要求嵌入存储查找与嵌入问题相关的嵌入片段。您可以定义存储应检索多少个结果。
在本例中,只要求一个结果:如果找到匹配结果,控制台将打印以下信息:
- The score得分:表示结果与问题匹配程度的数字;
- The original text原文:片段的文本;
- The meta data元数据:将显示片段来自哪个文档。
private static void askQuestion(String question) { |
问题如下,是文件中可以找到的一些事实:
public static void main(String args) { |
嵌入 Markdown 文档
将 PDF 文档转换成 Markdown 文件后会有什么变化?在 Markdown 文件中识别表格可能比在 PDF 文档中更好,而且它允许你在行级而不是任意的块大小上分割文档。只有文档中包含问题答案的部分才会被转换。这意味着唱片目录中的录音室专辑和合辑以及录制的歌曲列表。
分割过程如下
- 逐行分割文档;
- 在变量 dataOnly 中读取表格数据;
- 在变量 header 中保存表头;
- 为 dataOnly 中的每一行创建一个文本段,并将页眉添加到文本段中。
source code :
List<Document> documents = loadDocuments(toPath("markdown-files")); |
到目前为止得出的结论是
- 文件格式以及文件分割和嵌入的方式对结果有很大影响;
- 如果问题使用的术语与文档中的数据接近,则会取得更好的结果。
- 读取和嵌入文档的方式似乎对结果影响最大。这种方法的优点是可以显示多个结果。这样,您就可以确定哪个结果是正确的。
- 更改您的问题,使其使用文本段中使用的术语,有助于获得更好的结果。矢量存储的查询速度非常快。嵌入需要花费一些时间,但只需要做一次。
- 在不使用 GPU 的情况下,使用 LLM 获取结果需要更多时间。
可以使用 Weaviate、LangChain4j 和 LocalAI 实现 RAG,结果是相当惊人的。以正确的方式嵌入文档、过滤结果并将其提供给大模型是一个非常强大的组合,可用于许多用例。
步骤:
- 文档嵌入并存储在 Weaviate 中;
- 嵌入问题并使用 Weaviate 执行语义搜索;
- Weaviate 返回语义搜索结果;
- 结果被添加到提示中并馈送到 LocalAI,后者使用 LangChain4j 运行 LLM;
- LLM返回问题的答案。
在GitHub上找到实现源码