LangChain 向量库常见方法详解

前言

LangChain 提供了统一的向量存储(Vector Store)接口,支持多种向量数据库,如 Chroma、FAISS、Milvus 等。无论是使用内存向量存储(InMemoryVectorStore)还是持久化向量存储(如 Chroma),它们都遵循相同的 API 接口,这使得在不同向量存储之间切换变得非常简单。

本文将详细介绍 LangChain 向量库中最常用的方法,帮助开发者快速掌握向量存储的使用。

核心方法概览

LangChain 向量存储提供了以下核心方法:

  1. 数据添加方法

    • add_documents() - 添加 Document 对象列表
    • add_texts() - 添加字符串列表
  2. 数据检索方法

    • similarity_search() - 相似性搜索
    • similarity_search_with_score() - 带分数的相似性搜索
  3. 数据管理方法

    • delete() - 删除文档
  4. 检索器转换方法

    • as_retriever() - 转换为检索器对象

一、数据添加方法

1.1 add_documents() - 添加文档对象

add_documents() 方法用于将 Document 对象列表添加到向量存储中。每个 Document 对象包含 page_content(文本内容)和 metadata(元数据)。

方法签名:

add_documents(
    documents: List[Document],
    ids: Optional[List[str]] = None,
    **kwargs
) -> List[str]

参数说明:

  • documents: Document 对象列表,每个 Document 包含 page_contentmetadata
  • ids: 可选,文档 ID 列表,如果不提供会自动生成
  • **kwargs: 其他可选参数

返回值:

  • 返回文档 ID 列表

使用示例:

from langchain_core.documents import Document
from langchain_chroma import Chroma
from langchain_community.embeddings import DashScopeEmbeddings

# 初始化嵌入模型和向量存储
embedding = DashScopeEmbeddings()
vector_store = Chroma(
    collection_name="example_collection",
    embedding_function=embedding,
    persist_directory="./chroma_db"
)

# 创建文档对象
documents = [
    Document(
        page_content="Python 是一种高级编程语言,由 Guido van Rossum 创建。",
        metadata={"source": "python_intro", "topic": "programming"}
    ),
    Document(
        page_content="机器学习是人工智能的一个分支,通过算法让计算机从数据中学习。",
        metadata={"source": "ml_intro", "topic": "ai"}
    )
]

# 添加文档到向量存储
doc_ids = vector_store.add_documents(documents=documents, ids=["doc1", "doc2"])
print(f"成功添加文档,ID: {doc_ids}")

适用场景:

  • 需要为每个文档设置详细的元数据信息
  • 文档已经以 Document 对象形式存在
  • 需要精确控制文档的 ID

1.2 add_texts() - 添加文本字符串

add_texts() 方法用于直接将字符串列表添加到向量存储中,比 add_documents() 更简洁。

方法签名:

add_texts(
    texts: List[str],
    metadatas: Optional[List[dict]] = None,
    ids: Optional[List[str]] = None,
    **kwargs
) -> List[str]

参数说明:

  • texts: 字符串列表,要添加的文本内容
  • metadatas: 可选,元数据字典列表,与 texts 一一对应
  • ids: 可选,文档 ID 列表
  • **kwargs: 其他可选参数

返回值:

  • 返回文档 ID 列表

使用示例:

from langchain_chroma import Chroma
from langchain_community.embeddings import DashScopeEmbeddings

# 初始化向量存储
embedding = DashScopeEmbeddings()
vector_store = Chroma(
    collection_name="example_collection",
    embedding_function=embedding,
    persist_directory="./chroma_db"
)

# 准备文本列表
knowledge_texts = [
    "减肥就是要少吃多练。",
    "在减脂期间吃东西很重要,清淡少油控制卡路里摄入并运动起来。",
    "跑步是很好的运动哦。"
]

# 构建元数据(可选)
metadata = {
    "source": "health_guide",
    "create_time": "2024-01-01 10:00:00",
    "operator": "小曹"
}

# 添加文本到向量存储
vector_store.add_texts(
    texts=knowledge_texts,
    metadatas=[metadata for _ in knowledge_texts]  # 为每个文本分配相同的元数据
)

适用场景:

  • 已有字符串列表,不需要先转换为 Document 对象
  • 需要快速批量添加文本
  • 元数据相对简单或统一

add_texts 与 add_documents 的区别:

特性 add_texts add_documents
输入类型 List[str] List[Document]
元数据设置 通过 metadatas 参数 在 Document 对象中设置
使用便捷性 更简洁,适合字符串列表 需要先创建 Document 对象
灵活性 适合批量添加相同元数据 适合为每个文档设置不同元数据

二、数据检索方法

2.1 similarity_search() - 相似性搜索

similarity_search() 是向量存储最核心的检索方法,根据查询文本找到最相似的文档。

方法签名:

similarity_search(
    query: str,
    k: int = 4,
    filter: Optional[dict] = None,
    **kwargs
) -> List[Document]

参数说明:

  • query: 查询文本
  • k: 返回最相似的文档数量,默认为 4
  • filter: 可选,元数据过滤条件(字典格式)
  • **kwargs: 其他可选参数

返回值:

  • 返回 Document 对象列表,按相似度从高到低排序

使用示例:

基础搜索:

# 不带过滤条件的搜索
query = "什么是机器学习?"
results = vector_store.similarity_search(query, k=3)

for i, doc in enumerate(results, 1):
    print(f"【结果 {i}】")
    print(f"内容:{doc.page_content}")
    print(f"元数据:{doc.metadata}\n")

带元数据过滤的搜索:

# 只搜索特定主题的文档
query = "人工智能相关的内容"
results = vector_store.similarity_search(
    query=query,
    k=3,
    filter={"topic": "ai"}  # 只返回 topic 为 "ai" 的文档
)

# 只搜索特定来源的文档
results = vector_store.similarity_search(
    query=query,
    k=3,
    filter={"source": "ml_intro"}  # 只返回 source 为 "ml_intro" 的文档
)

适用场景:

  • 标准的相似性搜索需求
  • 需要根据元数据过滤结果
  • RAG 应用中的文档检索

2.2 similarity_search_with_score() - 带分数的相似性搜索

similarity_search_with_score()similarity_search() 类似,但会返回每个文档的相似度分数。

方法签名:

similarity_search_with_score(
    query: str,
    k: int = 4,
    filter: Optional[dict] = None,
    **kwargs
) -> List[Tuple[Document, float]]

参数说明:

  • similarity_search() 相同

返回值:

  • 返回 (Document, score) 元组列表
  • 分数越小表示越相似(距离越小)

使用示例:

query = "什么是深度学习?"
results = vector_store.similarity_search_with_score(query, k=3)

print("搜索结果(带相似度分数):")
for i, (doc, score) in enumerate(results, 1):
    print(f"【结果 {i}】相似度分数:{score:.4f}")
    print(f"内容:{doc.page_content}")
    print(f"元数据:{doc.metadata}\n")

适用场景:

  • 需要评估搜索结果的相关性
  • 需要根据分数阈值过滤结果
  • 调试和优化检索效果

注意事项:

  • 分数是距离值,越小越相似
  • 不同向量存储的分数范围可能不同
  • 可以通过分数判断检索质量

三、数据管理方法

3.1 delete() - 删除文档

delete() 方法用于从向量存储中删除指定的文档。

方法签名:

delete(
    ids: Optional[List[str]] = None,
    **kwargs
) -> Optional[bool]

参数说明:

  • ids: 要删除的文档 ID 列表
  • **kwargs: 其他可选参数

返回值:

  • 返回布尔值表示是否成功(某些实现可能返回 None)

使用示例:

# 删除指定的文档
delete_ids = ["doc_1", "doc_2"]
vector_store.delete(ids=delete_ids)
print("文档删除成功")

# 验证删除效果
query = "什么是机器学习?"
results_after = vector_store.similarity_search(query, k=3)
print(f"删除后搜索结果数量:{len(results_after)}")

适用场景:

  • 需要更新或删除过时的文档
  • 数据清理和维护
  • 动态管理知识库内容

四、检索器转换方法

4.1 as_retriever() - 转换为检索器

as_retriever() 方法将向量存储转换为检索器(Retriever)对象,可以无缝集成到 LangChain 的链(Chain)中。

方法签名:

as_retriever(
    search_type: str = "similarity",
    search_kwargs: Optional[dict] = None,
    **kwargs
) -> VectorStoreRetriever

参数说明:

  • search_type: 搜索类型,默认为 “similarity”
  • search_kwargs: 搜索参数字典,如 {"k": 2} 设置返回数量
  • **kwargs: 其他可选参数

返回值:

  • 返回 VectorStoreRetriever 对象

使用示例:

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

# 将向量存储转换为检索器
retriever = vector_store.as_retriever(search_kwargs={"k": 2})

# 在 RAG 链中使用检索器
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个有用的助手。请根据以下上下文回答问题:\n{context}"),
    ("human", "{question}")
])

# 构建 RAG 链
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
)

# 调用链
result = rag_chain.invoke("什么是机器学习?")
print(result)

适用场景:

  • 构建 RAG 应用
  • 将检索集成到 LangChain 链中
  • 需要自动化的检索-生成流程

五、完整使用示例

下面是一个完整的使用示例,展示所有核心方法的组合使用:

from langchain_core.documents import Document
from langchain_chroma import Chroma
from langchain_community.embeddings import DashScopeEmbeddings
from datetime import datetime

# 1. 初始化向量存储
embedding = DashScopeEmbeddings()
vector_store = Chroma(
    collection_name="knowledge_base",
    embedding_function=embedding,
    persist_directory="./chroma_db"
)

# 2. 添加文档(使用 add_documents)
documents = [
    Document(
        page_content="Python 是一种高级编程语言。",
        metadata={"source": "python_intro", "topic": "programming", "date": "2024-01-01"}
    ),
    Document(
        page_content="机器学习是人工智能的一个分支。",
        metadata={"source": "ml_intro", "topic": "ai", "date": "2024-01-02"}
    )
]
doc_ids = vector_store.add_documents(documents=documents, ids=["doc1", "doc2"])
print(f"✓ 添加文档成功,ID: {doc_ids}")

# 3. 添加文本(使用 add_texts)
texts = ["深度学习使用神经网络。", "自然语言处理研究计算机理解人类语言。"]
metadata = {"source": "ai_guide", "create_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
vector_store.add_texts(
    texts=texts,
    metadatas=[metadata for _ in texts]
)
print("✓ 添加文本成功")

# 4. 相似性搜索
query = "人工智能相关的内容"
results = vector_store.similarity_search(query, k=2)
print(f"\n搜索结果(共 {len(results)} 个):")
for i, doc in enumerate(results, 1):
    print(f"【结果 {i}】")
    print(f"  内容:{doc.page_content}")
    print(f"  元数据:{doc.metadata}")

# 5. 带分数的搜索
results_with_score = vector_store.similarity_search_with_score(query, k=2)
print(f"\n搜索结果(带分数):")
for i, (doc, score) in enumerate(results_with_score, 1):
    print(f"【结果 {i}】分数:{score:.4f}")
    print(f"  内容:{doc.page_content}")

# 6. 带过滤的搜索
filtered_results = vector_store.similarity_search(
    query=query,
    k=2,
    filter={"topic": "ai"}
)
print(f"\n过滤后搜索结果(topic='ai'):{len(filtered_results)} 个")

# 7. 转换为检索器
retriever = vector_store.as_retriever(search_kwargs={"k": 2})
print(f"\n✓ 检索器创建成功")

# 8. 删除文档
vector_store.delete(ids=["doc1"])
print("✓ 文档删除成功")

六、方法选择指南

何时使用 add_texts?

  • ✅ 已有字符串列表
  • ✅ 需要快速批量添加
  • ✅ 元数据相对简单或统一
  • ✅ 代码简洁性优先

何时使用 add_documents?

  • ✅ 需要为每个文档设置不同的详细元数据
  • ✅ 文档已经以 Document 对象形式存在
  • ✅ 需要精确控制文档结构

何时使用 similarity_search?

  • ✅ 标准的相似性搜索需求
  • ✅ 不需要查看相似度分数
  • ✅ 大多数 RAG 应用场景

何时使用 similarity_search_with_score?

  • ✅ 需要评估搜索结果的相关性
  • ✅ 需要根据分数阈值过滤
  • ✅ 调试和优化检索效果

何时使用 as_retriever?

  • ✅ 构建 RAG 应用
  • ✅ 需要将检索集成到 LangChain 链中
  • ✅ 需要自动化的检索-生成流程

七、最佳实践

  1. 合理设置 k 值

    • k 值过小可能遗漏相关文档
    • k 值过大可能引入噪声
    • 建议根据应用场景调整,通常 3-5 较为合适
  2. 善用元数据过滤

    • 为文档添加有意义的元数据
    • 使用过滤条件提高检索精度
    • 元数据应该包含来源、时间、主题等信息
  3. 管理文档 ID

    • 使用有意义的 ID 便于管理
    • 保存 ID 以便后续删除或更新
    • 避免 ID 冲突
  4. 持久化存储

    • 生产环境使用持久化向量存储(如 Chroma)
    • 定期备份向量数据库
    • 注意存储空间管理
  5. 性能优化

    • 批量添加文档而非逐个添加
    • 合理设置 chunk_size 和 chunk_overlap
    • 根据数据规模选择合适的向量存储

八、常见向量存储类型

LangChain 支持多种向量存储,它们都遵循相同的 API:

  • InMemoryVectorStore: 内存向量存储,适合小规模数据和开发测试
  • Chroma: 开源向量数据库,支持持久化,适合中小规模应用
  • FAISS: Facebook 开源,高性能,适合大规模数据
  • Milvus: 企业级向量数据库,支持分布式部署
  • Pinecone: 云服务向量数据库,无需自建基础设施
  • Weaviate: 开源向量数据库,支持 GraphQL

总结

LangChain 向量存储提供了统一且强大的 API,核心方法包括:

  • 数据添加: add_documents(), add_texts()
  • 数据检索: similarity_search(), similarity_search_with_score()
  • 数据管理: delete()
  • 检索器转换: as_retriever()

掌握这些方法,你就能轻松构建强大的 RAG 应用。记住,不同的方法适用于不同的场景,选择合适的方法能让你的代码更简洁、更高效。

参考资源

Logo

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

更多推荐