文档

LangChain 实现了一个 文档 抽象,旨在表示一个文本单元及其相关元数据。它有两个属性:

  • page_content:一个表示内容的字符串;
  • metadata:一个包含任意元数据的字典。

metadata 属性可以捕获有关文档来源、与其他文档的关系以及其他信息。请注意,单个 Document 对象通常表示一个较大文档的一部分。

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"},
    ),
]

在这里,我们生成了五个文档,包含指示三个不同“来源”的元数据。

向量存储

LangChain 向量存储 对象包含用于将文本和 文档 对象添加到存储中以及使用各种相似性度量进行查询的方法。它们通常使用 嵌入 模型进行初始化,这决定了文本数据如何转换为数值向量。

LangChain 包含与不同向量存储技术的 集成 套件。一些向量存储由提供商(例如各种云提供商)托管,并需要特定的凭据才能使用;一些(如 Postgres)在可以本地运行或通过第三方运行的独立基础设施中运行;其他可以在内存中运行以处理轻量级工作负载。这里我们将演示使用 Chroma 的 LangChain 向量存储,它包括一个内存实现。

要实例化一个向量存储,我们通常需要提供一个 嵌入 模型,以指定文本应如何转换为数值向量。这里我们将使用 OpenAI 嵌入。

from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings

vectorstore = Chroma.from_documents(
    documents,
    embedding=OpenAIEmbeddings(
        openai_api_base="https://api.siliconflow.cn/v1/",
        openai_api_key=os.environ["siliconFlow"],
        model="Qwen/Qwen3-Embedding-4B")
)

在这里调用 .from_documents 将把文档添加到向量存储中。向量存储 实现了可以在对象实例化后调用的添加文档的方法。

一旦我们实例化了一个包含文档的 向量存储,我们就可以对其进行查询。向量存储 包含用于查询的方法:

  • 同步和异步;
  • 通过字符串查询和通过向量;
  • 有和没有返回相似性分数;
  • 通过相似性和 最大边际相关性(以平衡查询的相似性与检索结果的多样性)。

这些方法的输出通常会包含 文档 对象的列表。

示例

根据与字符串查询的相似性返回文档:

vectorstore.similarity_search("cats")

在这里插入图片描述
异步查询:

await vectorstore.asimilarity_search("cats")

在这里插入图片描述
返回分数:

vectorstore.similarity_search_with_score("cats")

在这里插入图片描述
根据与嵌入查询的相似性返回文档:

embedding = OpenAIEmbeddings(
        openai_api_base="https://api.siliconflow.cn/v1/",
        openai_api_key=os.environ["siliconFlow"],
        model="Qwen/Qwen3-Embedding-4B").embed_query("cat") # 获取"cat"的向量表示
vectorstore.similarity_search_by_vector(embedding)

在这里插入图片描述

检索器

LangChain VectorStore 对象不继承 Runnable,因此无法立即集成到 LangChain 表达式 chains 中。

LangChain 检索器 是 Runnables,因此它们实现了一组标准方法(例如,同步和异步的 invoke 和 batch 操作),并设计为可以纳入 LCEL 链中。

我们可以自己创建一个简单版本,而无需继承 Retriever。如果我们选择希望用于检索文档的方法,我们可以轻松创建一个可运行的对象。下面我们将围绕 similarity_search 方法构建一个:

from langchain_core.runnables import RunnableLambda

retriever = RunnableLambda(vectorstore.similarity_search).bind(k=1)

retriever.batch(["cat", "shark"])
  • RunnableLambda:将普通函数包装成 Runnable 对象
  • vectorstore.similarity_search:向量存储的相似度搜索方法
  • 作用:把 similarity_search 函数转换为可以在 LCEL 链中使用的组件
  • bind():为函数绑定固定参数
  • k=1:设置返回结果的数量为 1 个
  • retriever.batch([“cat”, “shark”]) 的作用是批量处理多个查询,同时对 “cat” 和 “shark” 两个查询词进行相似度搜索。

在这里插入图片描述
向量存储实现了一个 as_retriever 方法,该方法将生成一个检索器,特别是一个 VectorStoreRetriever。这些检索器包括特定的 search_type 和 search_kwargs 属性,用于识别调用底层向量存储的方法,以及如何对其进行参数化。例如,我们可以用以下方式复制上述内容:

retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 1}
)

retriever.batch(["cat", "shark"])

在这里插入图片描述
检索器可以轻松地纳入更复杂的应用程序,例如检索增强生成(RAG)应用程序,这些应用程序将给定问题与检索到的上下文结合成 LLM 的提示。下面我们展示一个最小示例。

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    openai_api_base = "https://api.siliconflow.cn/v1/",
    openai_api_key = os.environ['siliconflow'],
    model_name = "Qwen/Qwen3-8B",  # 模型名称
)

注意: LangChain 自动将包含 Runnable 对象的字典转换为 RunnableParallel 对象。

字典中的每个 Runnable 会并行执行,输入会同时传递给所有组件。

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
response = rag_chain.invoke("tell me about cats")
print(response.content)

在这里插入图片描述
这里用Qwen的4B模型效果很差,建议用8B

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐