> ## Documentation Index
> Fetch the complete documentation index at: https://langchain.idochub.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 使用 LangChain 构建语义搜索引擎

本教程将帮助您熟悉 LangChain 的[文档加载器](/oss/python/langchain/retrieval#document-loaders)、[嵌入模型](/oss/python/langchain/retrieval#embedding-models) 和 [向量存储](/oss/python/langchain/retrieval#vector-store) 抽象层。这些抽象层旨在支持从（向量）数据库及其他来源检索数据，以便与大语言模型（LLM）工作流集成。对于需要在模型推理过程中获取待分析数据的应用（例如检索增强生成 RAG），它们至关重要。

在本教程中，我们将基于一份 PDF 文档构建一个搜索引擎，用于检索与输入查询相似的 PDF 段落。此外，本指南还将在该搜索引擎基础上实现一个最小化的 RAG 应用。

## 核心概念

本指南聚焦于文本数据的检索，涵盖以下核心概念：

* 文档与文档加载器；
* 文本分割器；
* 嵌入模型；
* 向量存储与检索器。

## 环境设置

### 安装依赖

本教程需要安装 `langchain-community` 与 `pypdf` 包：

<CodeGroup>
  ```bash pip theme={null}
  pip install langchain-community pypdf
  ```

  ```bash conda theme={null}
  conda install langchain-community pypdf -c conda-forge
  ```
</CodeGroup>

更多详情请参阅我们的 [安装指南](/oss/python/langchain/install)。

### LangSmith

使用 LangChain 构建的许多应用会包含多个步骤及多次 LLM 调用。随着应用日益复杂，能够检查链或代理内部具体发生了什么变得至关重要。最佳方式是使用 [LangSmith](https://smith.langchain.com)。

注册上述链接后，请设置环境变量以开始记录追踪信息：

```shell theme={null}
export LANGSMITH_TRACING="true"
export LANGSMITH_API_KEY="..."
```

或者，在笔记本环境中可这样设置：

```python theme={null}
import getpass
import os

os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_API_KEY"] = getpass.getpass()
```

## 文档与文档加载器

LangChain 实现了 [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html) 抽象类，用于表示一段文本及其关联元数据，包含三个属性：

* `page_content`：代表内容的字符串；
* `metadata`：包含任意元数据的字典；
* `id`：（可选）文档的字符串标识符。

`metadata` 属性可用于捕获文档来源、与其他文档的关系等信息。注意，单个 `Document` 对象通常代表较大文档的一个片段。

我们可以按需生成示例文档：

```python theme={null}
from langchain_core.documents import Document

documents = [
    Document(
        page_content="狗是极好的伴侣，以其忠诚和友善著称。",
        metadata={"source": "mammal-pets-doc"},
    ),
    Document(
        page_content="猫是独立的宠物，常常喜欢独处。",
        metadata={"source": "mammal-pets-doc"},
    ),
]
```

然而，LangChain 生态系统实现了[文档加载器](/oss/python/langchain/retrieval#document-loaders)，[可对接数百种常见数据源](/oss/python/integrations/document_loaders/)，便于将这些数据源的数据整合到您的 AI 应用中。

### 加载文档

让我们将一份 PDF 加载为一系列 `Document` 对象。LangChain 仓库中有一个示例 PDF [在此处](https://github.com/langchain-ai/langchain/tree/master/docs/docs/example_data) —— 耐克公司 2023 年的 10-K 文件。我们可以查阅 LangChain 文档中的 [可用 PDF 文档加载器](/oss/python/integrations/document_loaders/#pdfs)。

```python theme={null}
from langchain_community.document_loaders import PyPDFLoader

file_path = "../example_data/nke-10k-2023.pdf"
loader = PyPDFLoader(file_path)

docs = loader.load()

print(len(docs))
```

```output theme={null}
107
```

`PyPDFLoader` 为每页 PDF 创建一个 `Document` 对象。每个对象均可轻松访问：

* 页面的字符串内容；
* 包含文件名和页码的元数据。

```python theme={null}
print(f"{docs[0].page_content[:200]}\n")
print(docs[0].metadata)
```

```output theme={null}
目录
美利坚合众国
证券交易委员会
华盛顿特区 20549
表格 10-K
（标记一项）
☑ 根据 1934 年《证券交易法》第 13 或 15(D) 条提交的年度报告
FO

{'source': '../example_data/nke-10k-2023.pdf', 'page': 0}
```

### 文本分割

无论是为了信息检索还是后续问答任务，以整页作为粒度可能过于粗糙。我们的最终目标是检索能回答输入查询的 `Document` 对象，进一步分割 PDF 有助于确保相关段落的含义不会被周围文本“稀释”。

为此，我们可以使用[文本分割器](/oss/python/langchain/retrieval#text_splitters)。这里我们使用一个基于字符的简单文本分割器，将文档分割为 1000 字符的块，并在块间保留 200 字符的重叠部分。重叠有助于避免将语句与其重要上下文分离。我们使用 `RecursiveCharacterTextSplitter`，它会递归地使用常见分隔符（如换行符）分割文档，直到每个块达到合适大小。这是通用文本场景推荐的文本分割器。

我们设置 `add_start_index=True`，以便在初始文档中每个分割文档的起始字符索引作为元数据属性 “start\_index” 保留下来。

```python theme={null}
from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000, chunk_overlap=200, add_start_index=True
)
all_splits = text_splitter.split_documents(docs)

len(all_splits)
```

```output theme={null}
514
```

## 嵌入模型

向量搜索是存储和检索非结构化数据（如非结构化文本）的常用方法。其核心思想是将文本关联的数值向量存储起来。给定一个查询，我们可以将其[嵌入](/oss/python/langchain/retrieval#embedding_models)为相同维度的向量，并使用向量相似度度量（如余弦相似度）识别相关文本。

LangChain 支持来自[数十家提供商](/oss/python/integrations/text_embedding/)的嵌入模型。这些模型规定了如何将文本转换为数值向量。让我们选择一个模型：

<Tabs>
  <Tab title="OpenAI">
    ```shell theme={null}
    pip install -U "langchain-openai"
    ```

    ```python theme={null}
    import getpass
    import os

    if not os.environ.get("OPENAI_API_KEY"):
    os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter API key for OpenAI: ")

    from langchain_openai import OpenAIEmbeddings

    embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
    ```
  </Tab>

  <Tab title="Azure">
    ```shell theme={null}
    pip install -U "langchain-openai"
    ```

    ```python theme={null}
    import getpass
    import os

    if not os.environ.get("AZURE_OPENAI_API_KEY"):
    os.environ["AZURE_OPENAI_API_KEY"] = getpass.getpass("Enter API key for Azure: ")

    from langchain_openai import AzureOpenAIEmbeddings

    embeddings = AzureOpenAIEmbeddings(
        azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
        azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
        openai_api_version=os.environ["AZURE_OPENAI_API_VERSION"],
    )
    ```
  </Tab>

  <Tab title="Google Gemini">
    ```shell theme={null}
    pip install -qU langchain-google-genai
    ```

    ```python theme={null}
    import getpass
    import os

    if not os.environ.get("GOOGLE_API_KEY"):
    os.environ["GOOGLE_API_KEY"] = getpass.getpass("Enter API key for Google Gemini: ")

    from langchain_google_genai import GoogleGenerativeAIEmbeddings

    embeddings = GoogleGenerativeAIEmbeddings(model="models/gemini-embedding-001")
    ```
  </Tab>

  <Tab title="Google Vertex">
    ```shell theme={null}
    pip install -qU langchain-google-vertexai
    ```

    ```python theme={null}
    from langchain_google_vertexai import VertexAIEmbeddings

    embeddings = VertexAIEmbeddings(model="text-embedding-005")
    ```
  </Tab>

  <Tab title="AWS">
    ```shell theme={null}
    pip install -qU langchain-aws
    ```

    ```python theme={null}
    from langchain_aws import BedrockEmbeddings

    embeddings = BedrockEmbeddings(model_id="amazon.titan-embed-text-v2:0")
    ```
  </Tab>

  <Tab title="HuggingFace">
    ```shell theme={null}
    pip install -qU langchain-huggingface
    ```

    ```python theme={null}
    from langchain_huggingface import HuggingFaceEmbeddings

    embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")
    ```
  </Tab>

  <Tab title="Ollama">
    ```shell theme={null}
    pip install -qU langchain-ollama
    ```

    ```python theme={null}
    from langchain_ollama import OllamaEmbeddings

    embeddings = OllamaEmbeddings(model="llama3")
    ```
  </Tab>

  <Tab title="Cohere">
    ```shell theme={null}
    pip install -qU langchain-cohere
    ```

    ```python theme={null}
    import getpass
    import os

    if not os.environ.get("COHERE_API_KEY"):
    os.environ["COHERE_API_KEY"] = getpass.getpass("Enter API key for Cohere: ")

    from langchain_cohere import CohereEmbeddings

    embeddings = CohereEmbeddings(model="embed-english-v3.0")
    ```
  </Tab>

  <Tab title="MistralAI">
    ```shell theme={null}
    pip install -qU langchain-mistralai
    ```

    ```python theme={null}
    import getpass
    import os

    if not os.environ.get("MISTRALAI_API_KEY"):
    os.environ["MISTRALAI_API_KEY"] = getpass.getpass("Enter API key for MistralAI: ")

    from langchain_mistralai import MistralAIEmbeddings

    embeddings = MistralAIEmbeddings(model="mistral-embed")
    ```
  </Tab>

  <Tab title="Nomic">
    ```shell theme={null}
    pip install -qU langchain-nomic
    ```

    ```python theme={null}
    import getpass
    import os

    if not os.environ.get("NOMIC_API_KEY"):
    os.environ["NOMIC_API_KEY"] = getpass.getpass("Enter API key for Nomic: ")

    from langchain_nomic import NomicEmbeddings

    embeddings = NomicEmbeddings(model="nomic-embed-text-v1.5")
    ```
  </Tab>

  <Tab title="NVIDIA">
    ```shell theme={null}
    pip install -qU langchain-nvidia-ai-endpoints
    ```

    ```python theme={null}
    import getpass
    import os

    if not os.environ.get("NVIDIA_API_KEY"):
    os.environ["NVIDIA_API_KEY"] = getpass.getpass("Enter API key for NVIDIA: ")

    from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings

    embeddings = NVIDIAEmbeddings(model="NV-Embed-QA")
    ```
  </Tab>

  <Tab title="Voyage AI">
    ```shell theme={null}
    pip install -qU langchain-voyageai
    ```

    ```python theme={null}
    import getpass
    import os

    if not os.environ.get("VOYAGE_API_KEY"):
    os.environ["VOYAGE_API_KEY"] = getpass.getpass("Enter API key for Voyage AI: ")

    from langchain-voyageai import VoyageAIEmbeddings

    embeddings = VoyageAIEmbeddings(model="voyage-3")
    ```
  </Tab>

  <Tab title="IBM watsonx">
    ```shell theme={null}
    pip install -qU langchain-ibm
    ```

    ```python theme={null}
    import getpass
    import os

    if not os.environ.get("WATSONX_APIKEY"):
    os.environ["WATSONX_APIKEY"] = getpass.getpass("Enter API key for IBM watsonx: ")

    from langchain_ibm import WatsonxEmbeddings

    embeddings = WatsonxEmbeddings(
        model_id="ibm/slate-125m-english-rtrvr",
        url="https://us-south.ml.cloud.ibm.com",
        project_id="<WATSONX PROJECT_ID>",
    )
    ```
  </Tab>

  <Tab title="Fake">
    ```shell theme={null}
    pip install -qU langchain-core
    ```

    ```python theme={null}
    from langchain_core.embeddings import DeterministicFakeEmbedding

    embeddings = DeterministicFakeEmbedding(size=4096)
    ```
  </Tab>
</Tabs>

```python theme={null}
vector_1 = embeddings.embed_query(all_splits[0].page_content)
vector_2 = embeddings.embed_query(all_splits[1].page_content)

assert len(vector_1) == len(vector_2)
print(f"生成的向量长度为 {len(vector_1)}\n")
print(vector_1[:10])
```

```output theme={null}
生成的向量长度为 1536

[-0.008586574345827103, -0.03341241180896759, -0.008936782367527485, -0.0036674530711025, 0.010564599186182022, 0.009598285891115665, -0.028587326407432556, -0.015824200585484505, 0.0030416189692914486, -0.012899317778646946]
```

有了生成文本嵌入的模型后，下一步便是将它们存储在一个支持高效相似度搜索的特殊数据结构中。

## 向量存储

LangChain 的 [VectorStore](https://python.langchain.com/api_reference/core/vectorstores/langchain_core.vectorstores.base.VectorStore.html) 对象包含向存储中添加文本和 `Document` 对象的方法，以及使用各种相似度度量进行查询的方法。它们通常使用[嵌入模型](/oss/python/langchain/retrieval#embedding_models)初始化，这些模型决定了文本数据如何转换为数值向量。

LangChain 提供了一系列与不同向量存储技术的[集成](/oss/python/integrations/vectorstores)。一些向量存储由提供商托管（如各类云服务商），需要特定凭证才能使用；一些（如 [Postgres](/oss/python/integrations/vectorstores/pgvector)）可在本地或通过第三方运行的独立基础设施上运行；还有一些可内存运行以处理轻量级负载。让我们选择一个向量存储：

<Tabs>
  <Tab title="In-memory">
    ```shell theme={null}
    pip install -U "langchain-core"
    ```

    ```python theme={null}
    from langchain_core.vectorstores import InMemoryVectorStore

    vector_store = InMemoryVectorStore(embeddings)
    ```
  </Tab>

  <Tab title="AstraDB">
    ```shell theme={null}
    pip install -U "langchain-astradb"
    ```

    ```python theme={null}
    from langchain_astradb import AstraDBVectorStore

    vector_store = AstraDBVectorStore(
        embedding=embeddings,
        api_endpoint=ASTRA_DB_API_ENDPOINT,
        collection_name="astra_vector_langchain",
        token=ASTRA_DB_APPLICATION_TOKEN,
        namespace=ASTRA_DB_NAMESPACE,
    )
    ```
  </Tab>

  <Tab title="Chroma">
    ```shell theme={null}
    pip install -qU langchain-chroma
    ```

    ```python theme={null}
    from langchain_chroma import Chroma

    vector_store = Chroma(
        collection_name="example_collection",
        embedding_function=embeddings,
        persist_directory="./chroma_langchain_db",  # Where to save data locally, remove if not necessary
    )
    ```
  </Tab>

  <Tab title="FAISS">
    ```shell theme={null}
    pip install -qU langchain-community
    ```

    ```python theme={null}
    import faiss
    from langchain_community.docstore.in_memory import InMemoryDocstore
    from langchain_community.vectorstores import FAISS

    embedding_dim = len(embeddings.embed_query("hello world"))
    index = faiss.IndexFlatL2(embedding_dim)

    vector_store = FAISS(
        embedding_function=embeddings,
        index=index,
        docstore=InMemoryDocstore(),
        index_to_docstore_id={},
    )
    ```
  </Tab>

  <Tab title="Milvus">
    ```shell theme={null}
    pip install -qU langchain-milvus
    ```

    ```python theme={null}
    from langchain_milvus import Milvus

    URI = "./milvus_example.db"

    vector_store = Milvus(
        embedding_function=embeddings,
        connection_args={"uri": URI},
        index_params={"index_type": "FLAT", "metric_type": "L2"},
    )
    ```
  </Tab>

  <Tab title="MongoDB">
    ```shell theme={null}
    pip install -qU langchain-mongodb
    ```

    ```python theme={null}
    from langchain_mongodb import MongoDBAtlasVectorSearch

    vector_store = MongoDBAtlasVectorSearch(
        embedding=embeddings,
        collection=MONGODB_COLLECTION,
        index_name=ATLAS_VECTOR_SEARCH_INDEX_NAME,
        relevance_score_fn="cosine",
    )
    ```
  </Tab>

  <Tab title="PGVector">
    ```shell theme={null}
    pip install -qU langchain-postgres
    ```

    ```python theme={null}
    from langchain_postgres import PGVector

    vector_store = PGVector(
        embeddings=embeddings,
        collection_name="my_docs",
        connection="postgresql+psycopg://...",
    )
    ```
  </Tab>

  <Tab title="PGVectorStore">
    ```shell theme={null}
    pip install -qU langchain-postgres
    ```

    ```python theme={null}
    from langchain_postgres import PGEngine, PGVectorStore

    pg_engine = PGEngine.from_connection_string(
        url="postgresql+psycopg://..."
    )

    vector_store = PGVectorStore.create_sync(
        engine=pg_engine,
        table_name='test_table',
        embedding_service=embedding
    )
    ```
  </Tab>

  <Tab title="Pinecone">
    ```shell theme={null}
    pip install -qU langchain-pinecone
    ```

    ```python theme={null}
    from langchain_pinecone import PineconeVectorStore
    from pinecone import Pinecone

    pc = Pinecone(api_key=...)
    index = pc.Index(index_name)

    vector_store = PineconeVectorStore(embedding=embeddings, index=index)
    ```
  </Tab>

  <Tab title="Qdrant">
    ```shell theme={null}
    pip install -qU langchain-qdrant
    ```

    ```python theme={null}
    from qdrant_client.models import Distance, VectorParams
    from langchain_qdrant import QdrantVectorStore
    from qdrant_client import QdrantClient

    client = QdrantClient(":memory:")

    vector_size = len(embeddings.embed_query("sample text"))

    if not client.collection_exists("test"):
        client.create_collection(
            collection_name="test",
            vectors_config=VectorParams(size=vector_size, distance=Distance.COSINE)
        )
    vector_store = QdrantVectorStore(
        client=client,
        collection_name="test",
        embedding=embeddings,
    )
    ```
  </Tab>
</Tabs>

实例化向量存储后，我们现在可以对文档建立索引。

```python theme={null}
ids = vector_store.add_documents(documents=all_splits)
```

请注意，大多数向量存储实现允许您连接到现有的向量存储——例如，通过提供客户端、索引名称或其他信息。有关更多详细信息，请参阅特定[集成](/oss/python/integrations/vectorstores)的文档。

一旦我们实例化了一个包含文档的 `VectorStore`，就可以对其进行查询。[VectorStore](https://python.langchain.com/api_reference/core/vectorstores/langchain_core.vectorstores.base.VectorStore.html) 包含以下查询方法：

* 同步和异步查询；
* 通过字符串查询和通过向量查询；
* 返回和不返回相似度分数；
* 通过相似度和[最大边际相关性](https://python.langchain.com/api_reference/core/vectorstores/langchain_core.vectorstores.base.VectorStore.html#langchain_core.vectorstores.base.VectorStore.max_marginal_relevance_search)（在检索结果的相关性与多样性之间取得平衡）。

这些方法的输出通常包含一个 [Document](https://python.langchain.com/api_reference/core/documents/langchain_core.documents.base.Document.html#langchain_core.documents.base.Document) 对象列表。

### 使用示例

嵌入模型通常将文本表示为“稠密”向量，使得语义相似的文本在几何空间中彼此接近。这使我们只需传入一个问题即可检索相关信息，而无需了解文档中使用的任何特定关键词。

根据与字符串查询的相似度返回文档：

```python theme={null}
results = vector_store.similarity_search(
    "耐克在美国有多少个配送中心？"
)

print(results[0])
```

```output theme={null}
page_content='直销业务在美国通过以下数量的零售店销售产品：
美国零售店数量
NIKE品牌工厂店 213
NIKE品牌直营店（包括仅限员工的店铺） 74
Converse店铺（包括工厂店） 82
总计 369
在美国，NIKE拥有八个重要的配送中心。详情请参阅第2项“物业”。
2023年10-K表 2' metadata={'page': 4, 'source': '../example_data/nke-10k-2023.pdf', 'start_index': 3125}
```

异步查询：

```python theme={null}
results = await vector_store.asimilarity_search("耐克是何时成立的？")

print(results[0])
```

```output theme={null}
page_content='目录
第一部分
第1项. 业务
概述
NIKE, Inc. 于1967年根据俄勒冈州法律成立。本年度10-K表（“本年报”）中，“我们”、“我们”、“我们的”、“NIKE”和“公司”指NIKE, Inc. 及其前身、子公司和附属公司，除非上下文另有说明。
我们的主要业务活动是设计、开发以及在全球范围内营销和销售运动鞋、服装、设备、配件和服务。NIKE是全球最大的运动鞋和服装销售商。我们通过NIKE直销业务（包括NIKE自有零售店和数字平台销售（也称为“NIKE品牌数字”））、零售账户以及独立分销商、被许可方和销售商的组合销售产品。' metadata={'page': 3, 'source': '../example_data/nke-10k-2023.pdf', 'start_index': 0}
```

返回相似度分数：

```python theme={null}
# 注意，不同提供商实现的分数不同；此处的分数
# 是一个距离度量，与相似度成反比。

results = vector_store.similarity_search_with_score("耐克2023年的收入是多少？")
doc, score = results[0]
print(f"分数: {score}\n")
print(doc)
```

```output theme={null}
分数: 0.23699893057346344

page_content='目录
2023财年NIKE品牌收入亮点
下表按可报告经营分部、分销渠道和主要产品线列出了NIKE品牌收入：
2023财年与2022财年比较
• 2023财年，NIKE, Inc. 收入为512亿美元，较2022财年分别增长10%（按报告数据）和16%（按汇率中性基准）。
增长主要得益于北美、欧洲、中东和非洲（“EMEA”）、APLA和大中华区收入的增长，分别贡献了约7、6、2和1个百分点。
• NIKE品牌收入占NIKE, Inc. 收入的90%以上，分别增长10%（按报告数据）和16%（按汇率中性基准）。这一增长主要得益于男装、Jordan品牌、女装和童装的批发等效基础上分别增长17%、35%、11%和10%。' metadata={'page': 35, 'source': '../example_data/nke-10k-2023.pdf', 'start_index': 0}
```

根据与嵌入查询的相似度返回文档：

```python theme={null}
embedding = embeddings.embed_query("2023年耐克的利润率受到什么影响？")

results = vector_store.similarity_search_by_vector(embedding)
print(results[0])
```

```output theme={null}
page_content='目录
毛利率
2023财年与2022财年比较
2023财年，我们的综合毛利润从2022财年的214.79亿美元增至222.92亿美元，增长4%。毛利率从2022财年的46.0%下降250个基点至2023财年的43.5%，原因如下：
* 批发等效
2023财年毛利率下降的主要原因是：
• NIKE品牌产品成本（按批发等效计算）上升，主要由于投入成本增加、入境运费和物流成本升高以及产品组合变化；
• NIKE直销业务利润率降低，因本期促销活动增加以清理库存，而上期促销活动较少（因可用库存供应较低）；
• 净外汇汇率（包括对冲）的不利变动；
• 折扣店利润率降低（按批发等效计算）。
这部分被以下因素部分抵消：' metadata={'page': 36, 'source': '../example_data/nke-10k-2023.pdf', 'start_index': 0}
```

了解更多：

* [API 参考](https://python.langchain.com/api_reference/core/vectorstores/langchain_core.vectorstores.base.VectorStore.html)
* [特定集成文档](/oss/python/integrations/vectorstores)

## 检索器

LangChain 的 `VectorStore` 对象并非 [Runnable](https://python.langchain.com/api_reference/core/index.html#langchain-core-runnables) 的子类。LangChain 的 [Retrievers](https://python.langchain.com/api_reference/core/index.html#langchain-core-retrievers) 是 Runnable，因此它们实现了一组标准方法（如同步和异步的 `invoke` 和 `batch` 操作）。虽然我们可以从向量存储构造检索器，但检索器也可以与其他非向量存储数据源（如外部 API）交互。

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

```python theme={null}
from typing import List

from langchain_core.documents import Document
from langchain_core.runnables import chain


@chain
def retriever(query: str) -> List[Document]:
    return vector_store.similarity_search(query, k=1)


retriever.batch(
    [
        "耐克在美国有多少个配送中心？",
        "耐克是何时成立的？",
    ],
)
```

```output theme={null}
[[Document(metadata={'page': 4, 'source': '../example_data/nke-10k-2023.pdf', 'start_index': 3125}, page_content='直销业务在美国通过以下数量的零售店销售产品：\n美国零售店数量\nNIKE品牌工厂店 213 \nNIKE品牌直营店（包括仅限员工的店铺） 74 \nConverse店铺（包括工厂店） 82 \n总计 369 \n在美国，NIKE拥有八个重要的配送中心。详情请参阅第2项“物业”。\n2023年10-K表 2')],
 [Document(metadata={'page': 3, 'source': '../example_data/nke-10k-2023.pdf', 'start_index': 0}, page_content='目录\n第一部分\n第1项. 业务\n概述\nNIKE, Inc. 于1967年根据俄勒冈州法律成立。本年度10-K表（“本年报”）中，“我们”、“我们”、“我们的”、“NIKE”和“公司”指NIKE, Inc. 及其前身、子公司和附属公司，除非上下文另有说明。\n我们的主要业务活动是设计、开发以及在全球范围内营销和销售运动鞋、服装、设备、配件和服务。NIKE是全球最大的运动鞋和服装销售商。我们通过NIKE直销业务（包括NIKE自有零售店和数字平台销售（也称为“NIKE品牌数字”））、零售账户以及独立分销商、被许可方和销售商的组合销售产品。')]]
```

向量存储实现了 `as_retriever` 方法，用于生成一个检索器，即 [VectorStoreRetriever](https://python.langchain.com/api_reference/core/vectorstores/langchain_core.vectorstores.base.VectorStoreRetriever.html)。这些检索器包含特定的 `search_type` 和 `search_kwargs` 属性，用于标识调用底层向量存储的哪些方法以及如何参数化它们。例如，我们可以用以下方式复制上述操作：

```python theme={null}
retriever = vector_store.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 1},
)

retriever.batch(
    [
        "耐克在美国有多少个配送中心？",
        "耐克是何时成立的？",
    ],
)
```

```output theme={null}
[[Document(metadata={'page': 4, 'source': '../example_data/nke-10k-2023.pdf', 'start_index': 3125}, page_content='直销业务在美国通过以下数量的零售店销售产品：\n美国零售店数量\nNIKE品牌工厂店 213 \nNIKE品牌直营店（包括仅限员工的店铺） 74 \nConverse店铺（包括工厂店） 82 \n总计 369 \n在美国，NIKE拥有八个重要的配送中心。详情请参阅第2项“物业”。\n2023年10-K表 2')],
 [Document(metadata={'page': 3, 'source': '../example_data/nke-10k-2023.pdf', 'start_index': 0}, page_content='目录\n第一部分\n第1项. 业务\n概述\nNIKE, Inc. 于1967年根据俄勒冈州法律成立。本年度10-K表（“本年报”）中，“我们”、“我们”、“我们的”、“NIKE”和“公司”指NIKE, Inc. 及其前身、子公司和附属公司，除非上下文另有说明。\n我们的主要业务活动是设计、开发以及在全球范围内营销和销售运动鞋、服装、设备、配件和服务。NIKE是全球最大的运动鞋和服装销售商。我们通过NIKE直销业务（包括NIKE自有零售店和数字平台销售（也称为“NIKE品牌数字”））、零售账户以及独立分销商、被许可方和销售商的组合销售产品。')]]
```

`VectorStoreRetriever` 支持的搜索类型包括 `"similarity"`（默认）、`"mmr"`（最大边际相关性，如上所述）和 `"similarity_score_threshold"`。我们可以使用后者通过相似度分数对检索器输出的文档设置阈值。

检索器可以轻松集成到更复杂的应用中，例如[检索增强生成 (RAG)](/oss/python/langchain/retrieval) 应用，将给定问题与检索到的上下文结合形成 LLM 的提示。要了解更多关于构建此类应用的信息，请查看 [RAG 教程](/oss/python/langchain/rag/)。

## 下一步

您现在已经了解了如何基于 PDF 文档构建语义搜索引擎。

关于文档加载器的更多信息：

* [概述](/oss/python/langchain/retrieval#document_loaders)
* [可用集成](/oss/python/integrations/document_loaders/)

关于嵌入模型的更多信息：

* [概述](/oss/python/langchain/retrieval#embedding_models/)
* [可用集成](/oss/python/integrations/text_embedding/)

关于向量存储的更多信息：

* [概述](/oss/python/langchain/retrieval#vectorstores/)
* [可用集成](/oss/python/integrations/vectorstores/)

关于 RAG 的更多信息，请参见：

* [构建检索增强生成 (RAG) 应用](/oss/python/langchain/rag/)
