使用 LangChain 实现语义搜索

    在本指南中,您将使用 OpenAI 的文本嵌入来衡量文档属性之间的相似性。然后,您将使用 LangChain 框架无缝集成 Meilisearch 并创建一个具有语义搜索的应用程序。

    要求

    本指南假定您对 Python 和 LangChain 有基本的了解。LangChain 的初学者仍然会觉得本教程容易理解。

    在 Meilisearch Cloud 上,通过项目的“设置”页面启用向量存储功能。

    A section of the project overview interface titled "Experimental features". There are two options: "Score details" and "Vector store". "Vector store" is turned on.

    如果您正在使用自托管的 Meilisearch 实例,请使用 API 路由激活向量存储。

    创建应用程序

    为您的应用程序创建一个文件夹,其中包含一个空的 setup.py 文件。

    在编写任何代码之前,请安装必要的依赖项

    pip install langchain openai meilisearch python-dotenv
    

    首先创建一个 .env 来存储我们的凭据

    # .env
    
    MEILI_HTTP_ADDR="your Meilisearch host"
    MEILI_API_KEY="your Meilisearch API key"
    OPENAI_API_KEY="your OpenAI API key"
    

    现在您已经有了可用的环境变量,创建一个 setup.py 文件,其中包含一些样板代码

    # setup.py
    
    import os
    from dotenv import load_dotenv # remove if not using dotenv
    from langchain.vectorstores import Meilisearch
    from langchain.embeddings.openai import OpenAIEmbeddings
    from langchain.document_loaders import JSONLoader
    
    load_dotenv() # remove if not using dotenv
    
    # exit if missing env vars
    if "MEILI_HTTP_ADDR" not in os.environ:
        raise Exception("Missing MEILI_HTTP_ADDR env var")
    if "MEILI_API_KEY" not in os.environ:
        raise Exception("Missing MEILI_API_KEY env var")
    if "OPENAI_API_KEY" not in os.environ:
        raise Exception("Missing OPENAI_API_KEY env var")
    
    # Setup code will go here 👇
    

    导入文档和嵌入

    现在项目已准备就绪,在 Meilisearch 中导入一些文档。首先,下载这个小的电影数据集

    movies-lite.json

    然后,更新 setup.py 文件以加载 JSON 并将其存储在 Meilisearch 中。您还将使用 OpenAI 文本搜索模型来生成向量嵌入。

    要使用向量搜索,我们需要设置嵌入器索引设置。在这种情况下,您使用的是 userProvided 源,该源需要在一个 dimensions 字段中指定向量的大小。OpenAIEmbeddings() 使用的默认模型是 text-embedding-ada-002,它有 1,536 个维度。

    # setup.py
    
    # previous code
    
    # Load documents
    loader = JSONLoader(
        file_path="./movies-lite.json",
        jq_schema=".[] | {id: .id, overview: .overview, title: .title}",
        text_content=False,
    )
    documents = loader.load()
    print("Loaded {} documents".format(len(documents)))
    
    # Store documents in Meilisearch
    embeddings = OpenAIEmbeddings()
    embedders = { 
            "custom": {
                "source": "userProvided",
                "dimensions": 1536
            }
        }
    embedder_name = "custom" 
    vector_store = Meilisearch.from_documents(documents=documents, embedding=embeddings, embedders=embedders, embedder_name=embedder_name)
    
    print("Started importing documents")
    

    您的 Meilisearch 实例现在将包含您的文档。Meilisearch 会异步运行文档导入等任务,因此您可能需要等待一段时间才能使文档可用。有关任务如何工作的更多信息,请参阅 异步操作说明

    您的数据库现在已填充电影数据集中的数据。创建一个新的 search.py 文件以进行语义搜索查询:使用相似性搜索来搜索文档。

    # search.py
    
    import os
    from dotenv import load_dotenv
    from langchain.vectorstores import Meilisearch
    from langchain.embeddings.openai import OpenAIEmbeddings
    import meilisearch
    
    load_dotenv()
    
    # You can use the same code as `setup.py` to check for missing env vars
    
    # Create the vector store
    client = meilisearch.Client(
        url=os.environ.get("MEILI_HTTP_ADDR"),
        api_key=os.environ.get("MEILI_API_KEY"),
    )
    embeddings = OpenAIEmbeddings()
    vector_store = Meilisearch(client=client, embedding=embeddings)
    
    # Make similarity search
    embedder_name = "custom"
    query = "superhero fighting evil in a city at night"
    results = vector_store.similarity_search(
        query=query,
        embedder_name=embedder_name,
        k=3,
    )
    
    # Display results
    for result in results:
        print(result.page_content)
    

    运行 search.py。如果一切正常,您应该会看到如下输出

    {"id": 155, "title": "The Dark Knight", "overview": "Batman raises the stakes in his war on crime. With the help of Lt. Jim Gordon and District Attorney Harvey Dent, Batman sets out to dismantle the remaining criminal organizations that plague the streets. The partnership proves to be effective, but they soon find themselves prey to a reign of chaos unleashed by a rising criminal mastermind known to the terrified citizens of Gotham as the Joker."}
    {"id": 314, "title": "Catwoman", "overview": "Liquidated after discovering a corporate conspiracy, mild-mannered graphic artist Patience Phillips washes up on an island, where she's resurrected and endowed with the prowess of a cat -- and she's eager to use her new skills ... as a vigilante. Before you can say \"cat and mouse,\" handsome gumshoe Tom Lone is on her tail."}
    {"id": 268, "title": "Batman", "overview": "Batman must face his most ruthless nemesis when a deformed madman calling himself \"The Joker\" seizes control of Gotham's criminal underworld."}
    

    恭喜 🎉 您已成功使用 Meilisearch 作为 LangChain 向量存储进行相似性搜索。

    更进一步

    使用 Meilisearch 作为 LangChain 向量存储,您可以加载文档并以不同的方式搜索它们

    有关更多信息,请查阅

    Meilisearch Python SDK 文档

    最后,如果您想在不使用 LangChain 或其混合搜索功能的情况下使用 Meilisearch 的向量搜索功能,请参阅 专用教程