使用 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 的向量搜索功能,请参阅 专门指南