03LangChain初學者指南:從零開始實現高效資料檢索

onecyl發表於2024-11-13

LangChain初學者指南:從零開始實現高效資料檢索

https://python.langchain.com/v0.2/docs/tutorials/retrievers/

這個文件,我們將熟悉LangChain的向量儲存和抽象檢索器。支援從(向量)資料庫和其他來源檢索資料,並與大模型的工作流整合。這對於需要檢索資料以進行推理的應用程式非常重要,例如檢索增強生成(retrieval-augmented generation)的情況,或者RAG(請參閱我們的RAG教程在這裡)。

概念

這個指南著重於文字資料的檢索。涵蓋以下主要概念:

  • Documents:文字
  • Vector stores:向量儲存
  • Retrievers:檢索

Setup

Jupyter Notebook

這些教程和其他教程可能最方便在Jupyter筆記本中執行。請參閱此處有關安裝方法的說明

Installation

這個教程需要使用 langchainlangchain-chromalangchain-openai包。

  • Pip
pip install langchain langchain-chroma langchain-openai

Installation guide.

LangSmith

設定環境變數

export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="..."

如果在 notebook中,可以這樣設定:

import getpass
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

Documents

LangChain 實現了一個提取的文件,文件包括文字單元和相關後設資料。它具有兩個屬性:

  • page_content :字串格式的內容
  • metadata :包含任意後設資料的字典。

後設資料屬性可以包含關於文件來源、與其他文件的關係以及其他資訊。請注意,單個文件物件通常代表更大文件的一部分。

生成一些 documents 例子:

from langchain_core.documents import Document
documents = [
    Document(
        page_content="Dogs are great companions, known for their loyalty and friendliness.",
        metadata={"source": "mammal-pets-doc"},
),
    Document(
        page_content="Cats are independent pets that often enjoy their own space.",
        metadata={"source": "mammal-pets-doc"},
),
    Document(
        page_content="Goldfish are popular pets for beginners, requiring relatively simple care.",
        metadata={"source": "fish-pets-doc"},
),
    Document(
        page_content="Parrots are intelligent birds capable of mimicking human speech.",
        metadata={"source": "bird-pets-doc"},
),
    Document(
        page_content="Rabbits are social animals that need plenty of space to hop around.",
        metadata={"source": "mammal-pets-doc"},
),
]

API 呼叫:

  • Document

這裡我們生成了五個包含後設資料的文件,其中顯示了三個不同的“來源”。

向量儲存

向量搜尋是一種常見的儲存和搜尋非結構化資料(如非結構化文字)的方法。其思想是儲存與文字相關聯的數值向量。給定一個查詢,我們可以將其嵌入為相同維度的向量,並使用向量相似度度量來識別儲存中相關的資料。

LangChain的VectorStore物件定義了用於將文字和文件物件新增到儲存,和使用各種相似度度量進行查詢的方法。通常使用嵌入模型進行初始化,這些模型確定了文字資料如何被轉化為數字向量。

LangChain包括一套與不同向量儲存技術整合的解決方案。一些向量儲存由提供者(如各種雲服務提供商)託管,並需要特定的憑據才能使用;一些(例如Postgres)在獨立的基礎設施中執行,可以在本地或透過第三方執行;其他一些可以執行在記憶體中,用於輕量級工作負載。在這裡,我們將演示使用Chroma的LangChain向量儲存的用法,是一個基於記憶體的實現。

例項化一個向量儲存的時候,通常需要提供一個嵌入模型來指定文字應該如何轉換為數字向量。在這裡,我們將使用 OpenAI 的嵌入模型

from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
vectorstore = Chroma.from_documents(
    documents,
    embedding=OpenAIEmbeddings(),
)

API 呼叫:

  • OpenAIEmbeddings

呼叫 .from_documents 把文件新增到向量儲存中。VectorStore實現了用於新增文件的方法,這些方法可以在物件例項化之後呼叫。大多數實現都允許您連線到現有的向量儲存,例如,透過提供客戶端、索引名稱或其他資訊。有關特定整合的更多詳細資訊,請參閱文件

一旦我們例項化了一個包含文件的 VectorStore,我們就可以對其進行查詢。VectorStore 包括以下查詢方法:

  • 同步和非同步查詢;
  • 透過字串查詢和透過向量查詢;
  • 帶有和不帶有返回相似度分數的查詢;
  • 透過相似度和最大邊際相關性(在檢索結果中平衡相似度和多樣性的查詢)進行查詢。

這些方法會輸出一個Document物件的列表。

例子

返回與字串查詢相似的文件:

vectorstore.similarity_search("cat")
[Document(page_content='Cats are independent pets that often enjoy their own space.', metadata={'source': 'mammal-pets-doc'}),
 Document(page_content='Dogs are great companions, known for their loyalty and friendliness.', metadata={'source': 'mammal-pets-doc'}),
 Document(page_content='Rabbits are social animals that need plenty of space to hop around.', metadata={'source': 'mammal-pets-doc'}),
 Document(page_content='Parrots are intelligent birds capable of mimicking human speech.', metadata={'source': 'bird-pets-doc'})]

非同步查詢:

await vectorstore.asimilarity_search("cat")
[Document(page_content='Cats are independent pets that often enjoy their own space.', metadata={'source': 'mammal-pets-doc'}),
 Document(page_content='Dogs are great companions, known for their loyalty and friendliness.', metadata={'source': 'mammal-pets-doc'}),
 Document(page_content='Rabbits are social animals that need plenty of space to hop around.', metadata={'source': 'mammal-pets-doc'}),
 Document(page_content='Parrots are intelligent birds capable of mimicking human speech.', metadata={'source': 'bird-pets-doc'})]

返回分數查詢:

# Note that providers implement different scores; Chroma here
# returns a distance metric that should vary inversely with
# similarity.
vectorstore.similarity_search_with_score("cat")
[(Document(page_content='Cats are independent pets that often enjoy their own space.', metadata={'source': 'mammal-pets-doc'}),
  0.3751849830150604),
 (Document(page_content='Dogs are great companions, known for their loyalty and friendliness.', metadata={'source': 'mammal-pets-doc'}),
  0.48316916823387146),
 (Document(page_content='Rabbits are social animals that need plenty of space to hop around.', metadata={'source': 'mammal-pets-doc'}),
  0.49601367115974426),
 (Document(page_content='Parrots are intelligent birds capable of mimicking human speech.', metadata={'source': 'bird-pets-doc'}),
  0.4972994923591614)]

根據嵌入的查詢返回類似文件的查詢:

embedding = OpenAIEmbeddings().embed_query("cat")
vectorstore.similarity_search_by_vector(embedding)
[Document(page_content='Cats are independent pets that often enjoy their own space.', metadata={'source': 'mammal-pets-doc'}),
 Document(page_content='Dogs are great companions, known for their loyalty and friendliness.', metadata={'source': 'mammal-pets-doc'}),
 Document(page_content='Rabbits are social animals that need plenty of space to hop around.', metadata={'source': 'mammal-pets-doc'}),
 Document(page_content='Parrots are intelligent birds capable of mimicking human speech.', metadata={'source': 'bird-pets-doc'})]

學習更多:

  • API reference
  • How-to guide
  • Integration-specific docs

Retrievers

LangChain VectorStore 物件不繼承 Runnable,因此無法直接整合到 LangChain 表示式語言 chains 中。

Retrievers 繼承了 Runnables,實現了一套標準方法(例如同步和非同步的 invokebatch操作),並且設計為納入LCEL鏈中。

我們可以自己建立一個簡單的可執行物件,而無需繼承 Runnables。下面我們將圍繞相似性搜尋方法構建一個示例:

from typing import List
from langchain_core.documents import Document
from langchain_core.runnables import RunnableLambda
retriever = RunnableLambda(vectorstore.similarity_search).bind(k=1)  # select top result
retriever.batch(["cat", "shark"])

API 呼叫:

  • Document
  • RunnableLambda
[[Document(page_content='Cats are independent pets that often enjoy their own space.', metadata={'source': 'mammal-pets-doc'})],
 [Document(page_content='Goldfish are popular pets for beginners, requiring relatively simple care.', metadata={'source': 'fish-pets-doc'})]]

Vectorstores 實現一個 as_retriever 方法,該方法將生成一個 VectorStoreRetriever。這些 retriever 包括特定的 search_typesearch_kwargs 屬性,用於識別呼叫底層向量儲存的方法以及如何給它們引數化。例如,我們可以使用以下方法複製上述操作:

retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 1},
)
retriever.batch(["cat", "shark"])
[[Document(page_content='Cats are independent pets that often enjoy their own space.', metadata={'source': 'mammal-pets-doc'})],
 [Document(page_content='Goldfish are popular pets for beginners, requiring relatively simple care.', metadata={'source': 'fish-pets-doc'})]]

VectorStoreRetriever 支援相似度(預設)、mmr(最大邊際相關性)和 similarity_score_threshold 可以對輸出的相似文件,設定相似度分數閾值。

Retrievers 可以很容易地整合到更復雜的應用中,比如檢索增強生成(RAG)應用程式,它將給定的問題與檢索到的上下文結合組成 LLM 的提示。下面我們展示一個最簡單的例子。

  • OpenAI
pip install -qU langchain-openai
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-3.5-turbo-0125")
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
message = """
Answer this question using the provided context only.
{question}
Context:
{context}
"""
prompt = ChatPromptTemplate.from_messages([("human", message)])
rag_chain = {"context": retriever, "question": RunnablePassthrough()} | prompt | llm

API 呼叫:

  • ChatPromptTemplate
  • RunnablePassthrough
response = rag_chain.invoke("tell me about cats")
print(response.content)
Cats are independent pets that often enjoy their own space.

總結:

本文件提供了向量儲存和檢索的示例程式碼。介紹了LangChain的向量儲存和抽象檢索器,包括向量儲存和檢索器的概念和使用。向量儲存是儲存和搜尋非結構化資料的一種方法,LangChain的VectorStore物件定義了用於將文字和文件物件新增到儲存,和使用各種相似度度量進行查詢的方法。檢索器繼承了Runnables,實現了一套標準方法,並且可以加入LCEL鏈中。

相關文章