宣布我们的 LlamaCloud 全面上线 (以及我们的 A 轮融资 $1900 万)!
LlamaIndex

LlamaIndex 2023-12-21

在本地使用 LlamaIndex 和 Ollama 运行 Mixtral 8x7

您可能听说过欧洲人工智能巨头 Mistral AI 的最新发布引起的热议:它被称为 Mixtral 8x7b,是一个“专家混合”模型——由八个专家组成,每个专家都使用 70 亿参数进行训练,因此得名。最初是作为一条令人瞩目的推文发布的,几天后他们又发布了一篇博客文章,展示了它在多项基准测试中与 GPT-3.5 相当或超越了后者,同时也超越了规模更大的 Llama2 70b。

在 LlamaIndex,我们天生就是开源软件的粉丝,因此像 Mixtral 这样拥有宽松许可的开源模型正是我们所擅长的。我们收到了一些关于如何在 LlamaIndex 中使用 Mixtral 的问题,因此本文旨在帮助您在一个完全本地化的模型上启动并运行。

第一步:安装 Ollama

以前,安装和运行本地模型非常麻烦,但随着 Ollama 的发布,一切变得突然轻松起来!它适用于 MacOS 和 Linux(即将支持 Windows,尽管您今天就可以通过 适用于 Linux 的 Windows 子系统 在 Windows 上使用它),Ollama 本身是开源的,并且可以免费下载

下载后,您可以使用一个命令获取 Mixtral

ollama run mixtral

第一次运行此命令时,它必须下载模型,这可能需要很长时间,所以去吃点零食吧。另外请注意,它需要巨大的 48GB 内存才能流畅运行!如果您的机器配置不足,请考虑使用它较小但仍然非常强大的近亲 Mistral 7b,其安装和运行方式相同

ollama run mistral

在本教程的其余部分,我们将假设您使用的是 Mixtral,但 Mistral 同样适用。

模型运行后,Ollama 会自动让您与之聊天。这很有趣,但是如果一个模型无法处理您的数据,那又有什么意义呢?这就是 LlamaIndex 的用武之地。接下来的几个步骤将逐行引导您了解代码,但如果您更喜欢跳过所有复制粘贴的步骤,所有这些代码都可以在一个开源仓库中找到,您可以克隆该仓库进行操作。

第二步:安装依赖项

显然,您需要安装 LlamaIndex!我们还将为您准备一些即将派上用场的其他依赖项

pip install llama-index qdrant_client torch transformers

第三步:冒烟测试

如果您已经运行了 Ollama 并正确安装了 LlamaIndex,以下这个简单的脚本将通过在一个独立的脚本中问它一个快速的“冒烟测试”问题来确保一切正常

# Just runs .complete to make sure the LLM is listening
from llama_index.llms import Ollama

llm = Ollama(model="mixtral")
response = llm.complete("Who is Laurie Voss?")
print(response)

第四步:加载数据并为其建立索引

现在您准备好加载一些真实数据了!您可以使用任何想要的数据;在本例中,我使用的是我自己的少量推文集合,您可以下载,或者使用您自己的数据!我们将把数据存储在精巧的开源向量数据库 Qdrant 中(这就是我们之前让您安装它的原因)。创建一个新的 Python 文件,并加载所有依赖项

from pathlib import Path
import qdrant_client
from llama_index import (
    VectorStoreIndex,
    ServiceContext,
    download_loader,
)
from llama_index.llms import Ollama
from llama_index.storage.storage_context import StorageContext
from llama_index.vector_stores.qdrant import QdrantVectorStore

然后使用来自我们便捷的开源数据连接器集合 LlamaHub 的精巧 JSONReader 从我们的 JSON 文件中加载推文。这将为您提供一堆准备好嵌入和索引的文档

JSONReader = download_loader("JSONReader")
loader = JSONReader()
documents = loader.load_data(Path('./data/tinytweets.json'))

通过初始化 Qdrant 并将其传递到我们稍后将使用的 Storage Context 中,使其准备就绪

client = qdrant_client.QdrantClient(
    path="./qdrant_data"
)
vector_store = QdrantVectorStore(client=client, collection_name="tweets")
storage_context = StorageContext.from_defaults(vector_store=vector_store)

现在设置我们的 Service Context。我们将 Mixtral 作为 LLM 传递给它,这样我们在完成索引后就可以测试一切是否正常;索引本身不需要 Mixtral。通过传递 embed_model="local",我们指定 LlamaIndex 将在本地嵌入您的数据,这就是您需要 torchtransformers 的原因。

llm = Ollama(model="mixtral")
service_context = ServiceContext.from_defaults(llm=llm,embed_model="local")

现在将所有内容整合起来:使用您已经设置好的服务和存储上下文,从您加载的文档中构建索引,并给它一个查询

index = VectorStoreIndex.from_documents(documents,service_context=service_context,storage_context=storage_context)

query_engine = index.as_query_engine()
response = query_engine.query("What does the author think about Star Trek? Give details.")
print(response)

Ollama 需要启动 Mixtral 来回答查询,这可能需要一些时间,请耐心等待!您应该会得到类似这样的输出(但包含更多细节)

Based on the provided context information, the author has a mixed opinion about Star Trek.

验证我们的索引

现在为了证明这并非虚张声势,让我们使用我们预先构建好的索引。启动一个新的 Python 文件,再次加载依赖项

import qdrant_client
from llama_index import (
    VectorStoreIndex,
    ServiceContext,
)
from llama_index.llms import Ollama
from llama_index.vector_stores.qdrant import QdrantVectorStore

这次我们不需要加载数据,那一步已经完成了!我们将需要 Qdrant 客户端,当然还有 Mixtral

client = qdrant_client.QdrantClient(
    path="./qdrant_data"
)
vector_store = QdrantVectorStore(client=client, collection_name="tweets")

llm = Ollama(model="mixtral")
service_context = ServiceContext.from_defaults(llm=llm,embed_model="local")

这次,我们不从文档创建索引,而是使用 from_vector_store 直接从向量存储加载它。我们还向查询引擎传递了 similarity_top_k=20;这意味着它将一次获取 20 条推文(默认值为 2),以获取更多上下文并更好地回答问题。

index = VectorStoreIndex.from_vector_store(vector_store=vector_store,service_context=service_context)
query_engine = index.as_query_engine(similarity_top_k=20)
response = query_engine.query("Does the author like SQL? Give details.")
print(response)

构建一个小型的 Web 服务

拥有一个只作为脚本运行的索引是没有意义的!让我们用它构建一个 API。我们将需要两个新的依赖项

pip install flask flask-cors

像之前一样,将我们的依赖项加载到一个新文件中

from flask import Flask, request, jsonify
from flask_cors import CORS, cross_origin
import qdrant_client
from llama_index.llms import Ollama
from llama_index import (
    VectorStoreIndex,
    ServiceContext,
)
from llama_index.vector_stores.qdrant import QdrantVectorStore

加载向量存储、LLM 和索引

# re-initialize the vector store
client = qdrant_client.QdrantClient(
    path="./qdrant_data"
)
vector_store = QdrantVectorStore(client=client, collection_name="tweets")

# get the LLM again
llm = Ollama(model="mixtral")
service_context = ServiceContext.from_defaults(llm=llm,embed_model="local")
# load the index from the vector store
index = VectorStoreIndex.from_vector_store(vector_store=vector_store,service_context=service_context)

设置一个非常基本的 Flask 服务器

app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'

# This is just so you can easily tell the app is running
@app.route('/')
def hello_world():
    return 'Hello, World!'

并添加一个路由,该路由接受一个查询(作为表单数据),查询 LLM 并返回响应

@app.route('/process_form', methods=['POST'])
@cross_origin()
def process_form():
    query = request.form.get('query')
    if query is not None:
        query_engine = index.as_query_engine(similarity_top_k=20)
        response = query_engine.query(query)
        return jsonify({"response": str(response)})
    else:
        return jsonify({"error": "query field is missing"}), 400

if __name__ == '__main__':
    app.run()

注意最后两行,它们很重要! flask run 与 LlamaIndex 加载依赖项的方式不兼容,因此您需要像这样直接运行此 API(假设您的文件名为 app.py

python app.py

API 运行起来后,您可以使用 cURL 发送请求并验证它

curl --location '<http://127.0.0.1:5000/process_form>' \\
--form 'query="What does the author think about Star Trek?"'

您完成了!

我们在这里介绍了几点内容

  • 让 Ollama 在本地运行 Mixtral
  • 使用 LlamaIndex 查询 Mixtral 8x7b
  • 使用 Qdrant 向量存储构建并查询您数据的索引
  • 将您的索引封装到一个非常简单的 Web API 中
  • 所有内容都是开源、免费且在本地运行!

希望这是一个有趣、快速的 LlamaIndex 本地模型运行入门!