LangChain 向量数据库实战:Redis 与 Pinecone 的知识点总结

在 RAG(检索增强生成)应用中,向量数据库用于保存文档切分后的文本向量,并在用户提问时快速召回语义最相关的内容。本文以 Redis 和 Pinecone 两种向量数据库为例,梳理从文档加载、文本切分、向量入库到相似度检索与元数据过滤的完整流程。

一、RAG 离线与在线流程

整个流程可分为两部分:

  1. 离线数据处理:加载原始文档,将文档切分为较小的文本块,调用 Embedding 模型生成向量,再存入向量数据库。

  2. 在线检索问答:将用户问题转为向量,在向量库中检索相关文本块,把检索结果连同提示词交给大模型生成最终回答。

    Markdown / PDF / 数据库

    文档加载(Loader)

    文本切分(Splitter)

    Embedding 向量化

    向量数据库(Redis / Pinecone)

    相似度检索 + 元数据过滤

    Prompt + LLM

    最终回答

二、Embedding 模型:文本与向量之间的桥梁

OpenAIEmbeddings 负责调用兼容 OpenAI 协议的 Embedding 服务,将文本转换为高维浮点向量。

复制代码
from langchain_openai import OpenAIEmbeddings
import os

embeddings = OpenAIEmbeddings(
    model="qwen3.7-text-embedding",
    api_key=os.environ["DASHSCOPE_API_KEY"],
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    check_embedding_ctx_length=False,
)

核心参数说明:

  • model:指定向量模型。向量维度必须与向量数据库索引配置一致。

  • api_key:服务访问密钥,推荐从环境变量中读取。

  • base_url:兼容 OpenAI API 的服务地址。注意这里应为普通字符串,不能写成 Markdown 链接。

  • check_embedding_ctx_length=False:可避免部分兼容服务在分词或上下文长度检查上的兼容性问题;是否关闭应结合实际服务测试。

Embedding 的本质是让语义相近的文本在向量空间中距离更近。因此,"项目介绍"和"系统简介"即使字面不同,也可能被检索为相近内容。

三、文档加载与文本切分

Markdown 文档可通过 UnstructuredMarkdownLoader 加载:

复制代码
from langchain_community.document_loaders import UnstructuredMarkdownLoader

loader = UnstructuredMarkdownLoader(
    "../Docs/MarkDown/脚手架级微服务租房平台Q&A.md"
)
data = loader.load()

加载后得到的是 Document 对象列表,每个对象通常包含:

  • page_content:文本正文;

  • metadata:来源文件、页码、自定义标签等元数据。

随后使用 CharacterTextSplitter 对文档切分:

复制代码
from langchain_text_splitters import CharacterTextSplitter

text_splitter = CharacterTextSplitter(
    chunk_size=200,
    chunk_overlap=50,
)

docs = text_splitter.split_documents(data)

参数含义:

  • chunk_size=200:每个文本块的最大字符数。

  • chunk_overlap=50:相邻文本块保留 50 个字符重叠区域,降低切分边界导致的上下文丢失。

文本不宜过长,否则一个向量会混入多个主题;也不宜过短,否则缺少足够语义。实际项目中可根据文档类型、模型上下文窗口和检索效果调整切分大小。

四、元数据:让向量检索更可控

除了文本向量,还可以给每个文档块写入元数据:

复制代码
for i, doc in enumerate(docs, start=1):
    doc.metadata["category"] = "qa"
    doc.metadata["num"] = i

这里:

  • category:文档类别,例如 qaproductfaq

  • num:文本块序号,便于演示数值范围过滤。

元数据不参与文本语义计算,但可以在检索时缩小范围。例如,只在"问答"分类中检索,或只检索序号大于 6 的文档块。

五、Redis Vector Store:适合自建与精细过滤

Redis 在安装 Redis Stack 或 RedisSearch 模块后,可以支持向量检索。LangChain 通过 RedisVectorStore 将文档、向量和元数据写入 Redis。

复制代码
from langchain_redis import RedisVectorStore, RedisConfig

config_redis = RedisConfig(
    redis_url="redis://<host>:6379",
    index_name="qa",
    metadata_schema=[
        {"name": "category", "type": "tag"},
        {"name": "num", "type": "numeric"},
    ],
)

vectorstore = RedisVectorStore(
    config=config_redis,
    embeddings=embeddings,
)

1. Redis 索引与 Redis Key 的关系

Redis 向量检索并不是把所有数据直接放到一个"表"中,而是:

  • 每一个文档块保存为一个 Redis Key;

  • 文档内容、向量和元数据保存在对应 Key 的字段中;

  • RedisSearch 创建 Index,为这些字段建立检索索引;

  • 查询时先通过 Index 找到匹配的 Key,再返回对应文档。

常见元数据字段类型包括:

  • TAG:精确匹配的分类或标签,例如 category=qa

  • NUMERIC:整数或浮点数,可用于范围过滤;

  • TEXT:全文文本检索;

  • GEO:地理位置坐标检索。

因此,metadata_schema 不是可有可无的配置:只有声明后的元数据字段,才能被 RedisSearch 正确用于过滤。

2. 写入文档

复制代码
for i in range(0, len(docs), 20):
    vectorstore.add_documents(docs[i:i + 20])

批量写入可以减少网络调用次数。示例中每批 20 条,实际批次大小需要结合服务限制、文本长度和网络情况调整。

3. 元数据过滤检索

复制代码
from redisvl.query.filter import Tag, Num

filter_config = (
    (Tag("category") == "qa") &
    (Num("num") >= 6)
)

search_docs = vectorstore.similarity_search_with_score(
    "项目介绍",
    k=2,
    filter=filter_config,
    fetch_k=10,
)

这里的逻辑是:

  1. 先将"项目介绍"转换成查询向量;

  2. 限定 category 必须为 qa

  3. 限定 num 必须大于等于 6;

  4. 从候选结果中返回最相近的 2 条。

k 表示最终返回数量,fetch_k 表示先召回的候选数量。过滤条件较多时,适当提高 fetch_k 通常有助于提高召回稳定性。

六、Pinecone Vector Store:适合托管式云向量检索

Pinecone 是托管式向量数据库,无需自行维护 Redis 服务或索引模块,更适合快速构建云端 RAG 应用。

复制代码
from pinecone import Pinecone, ServerlessSpec

pc = Pinecone()
index_name = "qa"

if not pc.has_index(index_name):
    pc.create_index(
        name=index_name,
        dimension=1024,
        metric="cosine",
        spec=ServerlessSpec(
            cloud="aws",
            region="us-east-1",
        ),
    )

index = pc.Index(index_name)

创建索引时需要重点关注:

  • dimension=1024:向量维度,必须与 Embedding 模型的实际输出维度完全一致。

  • metric="cosine":采用余弦相似度衡量文本语义接近程度。

  • cloudregion:指定 Pinecone 的部署云平台与区域,应尽量选择接近应用服务的区域以降低延迟。

通过 LangChain 封装索引:

复制代码
from langchain_pinecone import PineconeVectorStore

vectorstore = PineconeVectorStore(
    embedding=embeddings,
    index=index,
)

写入与检索方式与其他 LangChain 向量库基本一致:

复制代码
ids = vectorstore.add_documents(docs)

result = vectorstore.similarity_search(
    query="项目介绍",
    k=5,
)

七、Redis 与 Pinecone 的主要区别

对比项 Redis Vector Store Pinecone Vector Store
部署方式 自建或使用托管 Redis 云端托管服务
运维成本 需要维护 Redis、模块、索引和容量 平台负责底层运维
元数据过滤 RedisSearch 的 TAG、NUMERIC 等字段类型清晰 支持元数据过滤,按 Pinecone 过滤语法使用
适用场景 已有 Redis 基础设施、低延迟内网检索、缓存与向量一体化 快速上线、云端 RAG、大规模向量检索
索引维度 通常由封装或索引配置处理 创建索引时必须显式指定
数据管理 可直接操作 Redis Key 与索引 通过 Pinecone Index API 管理

简单来说:已有 Redis 环境、希望细粒度控制数据和过滤规则时,可以选择 Redis;希望减少运维、快速使用云向量检索能力时,可以选择 Pinecone。

八、常见问题与注意事项

1. 向量维度不一致

Pinecone 的 dimension 必须等于 Embedding 模型输出维度。若不一致,写入向量时会失败。

  • similarity_search:只返回相关文档;

  • similarity_search_with_score:返回文档及其相似度分数,便于调试召回效果和设置阈值。

九、总结

LangChain 将不同向量数据库的使用方式统一为相似接口:加载文档、切分文本、生成向量、写入向量库、执行相似度检索。真正需要重点关注的是:

  • Embedding 模型与索引维度是否匹配;

  • 文本切分策略是否适合业务文档;

  • 元数据设计是否支持后续过滤需求;

  • 应根据部署成本、运维能力和检索规模选择 Redis 或 Pinecone。

相关推荐
API快乐传递者1 小时前
1688 跨境电商 API 接口实战指南:从寻源到代采的全链路技术方案
java·前端·数据库
LabVIEW开发1 小时前
LabVIEW按段拆分TDMS文件的格式边界与重构
开发语言·数据库·重构·labview·labview知识·labview功能·labview程序
程序员-Benothing2 小时前
什么是数据全量同步和增量同步?它们各有什么优缺点?
数据库
秋名山码民2 小时前
拙见AI——AI操作系统
数据库·人工智能
李可以量化2 小时前
Redis Client 从了解到精通(二)上:redis-py 高级用法与核心命令实战
前端·数据库·redis·python·缓存·ptrade
南棱笑笑生2 小时前
20260826在Ubuntu22.04系统下编译眺望Pi-RK3572工业派开发板的Ubuntu系统
数据库
仍然.2 小时前
Redis---String
数据库·redis·缓存
tg_xianheyun2 小时前
2026BytePlus CDN加速应用场景全面解析
服务器·数据库·阿里云·云计算·cdn·全球访问优化·云直播
JavaPub-rodert2 小时前
Redis 和 MySQL 如何保证数据一致性?从缓存更新到延迟双删完整讲解
redis·mysql·缓存