首页
/ LlamaIndex × YugabyteDB:使用 YBVectorStore 构建分布式向量检索与混合搜索

LlamaIndex × YugabyteDB:使用 YBVectorStore 构建分布式向量检索与混合搜索

2026-09-09 21:12:43作者:彭桢灵Jeremy

本指南以 LlamaIndex 官方 API 参考文档中公开的 YBVectorStore 类为核心,系统讲解如何在 LlamaIndex 生态中接入 YugabyteDB 作为向量存储后端,覆盖安装配置、参数语义、底层建表与索引机制、密集/稀疏混合检索、元数据过滤以及增删改查全流程。读完本文,你将能够独立完成 YugabyteDB 向量库的初始化、索引构建、混合查询与日常维护,并将其无缝接入 LlamaIndex 的 VectorStoreIndex 检索链路。

一、概述:为什么选择 YugabyteDB 作为向量存储

YBVectorStore 是 LlamaIndex 官方的 YugabyteDB 向量存储集成,位于 llama-index-integrations/vector_stores/llama-index-vector-stores-yugabytedb,包名为 llama-index-vector-stores-yugabytedb。它继承自 LlamaIndex 核心的 BasePydanticVectorStore(参见 test_vector_stores_yugabytedb.py 中的继承关系断言),因此天然兼容 LlamaIndex 统一的 add / query / delete / get_nodes 向量存储接口。

base.py 的依赖关系看,该集成底层由四块技术拼装而成:

  • pgvector:提供 PostgreSQL/YugabyteDB 原生的向量列类型与余弦距离计算;
  • SQLAlchemy:负责动态建模、ORM 映射与连接管理;
  • psycopg2-yugabytedb:YugabyteDB 定制的 psycopg2 驱动,支持集群感知的负载均衡连接;
  • YugabyteDB 自身的 ybhnsw 索引:为海量向量提供近似最近邻(ANN)检索能力。

对应的运行时依赖声明在 pyproject.toml 中:pgvector>=0.3.6,<1.0.0psycopg2-yugabytedb>=2.9.3.5sqlalchemy[asyncio]>=1.4.49,<2.1sqlalchemy-yugabytedb>=1.0.0.1,并要求 Python 版本 >=3.10,<4.0

二、安装与前置条件

pip install llama-index-vector-stores-yugabytedb

安装后还需满足两项运行前置:

  1. 一个可访问的 YugabyteDB 实例。官方测试指引(见 tests/README.md)推荐通过 ./bin/yugabyted start 启动本地节点;
  2. vector 扩展可用YBVectorStore 在初始化时会自动执行 CREATE EXTENSION IF NOT EXISTS vector(见 base.py),若数据库账号权限不足,可通过 initialization_fail_on_error=True 将初始化错误升级为硬失败以便排查。

三、快速上手:最小可用示例

官方 README(README.md)给出了最小示例,from_params 类方法会依据连接参数自动拼接连接串并完成初始化:

from llama_index.vector_stores.yugabytedb import YBVectorStore

vector_store = YBVectorStore.from_params(
    host="localhost",
    user="yugabyte",
    password="yugabyte",
    port=5433,
    load_balance="True",
    database="yugabyte",
    table_name="test_table",
    schema_name="test_schema",
    embed_dim=1536,
)

类文档(base.py)中的示例同样演示了 from_params 用法,并额外展示了 use_halfvec=True 启用半精度向量:

from llama_index.vector_stores.yugabytedb import YBVectorStore

vector_store = YBVectorStore.from_params(
    database="vector_db",
    host="localhost",
    password="password",
    port=5432,
    user="yugabytedb",
    table_name="paul_graham_essay",
    embed_dim=1536,   # openai embedding dimension
    use_halfvec=True, # Enable half precision
)

随后即可与 LlamaIndex 索引无缝拼接:

from llama_index.core import VectorStoreIndex
from llama_index.core.node_parser import SimpleNodeParser

# 假设已有 documents 列表
nodes = SimpleNodeParser().get_nodes_from_documents(documents)
vector_store.add(nodes)

index = VectorStoreIndex.from_vector_store(vector_store)
query_engine = index.as_query_engine()
response = query_engine.query("你的问题")

四、核心参数详解

YBVectorStore 的参数分为两类:from_params 的连接参数,以及底层构造函数 __init__ 的存储行为参数(两者最终汇合于 __init__,见 base.py)。

4.1 连接参数(from_params)

参数 默认值 说明
host / port / database / user / password None 经典连接五项;from_params 会拼出形如 yugabytedb+psycopg2://user:password@host:port/database?<query> 的连接串
load_balance False 是否启用 YugabyteDB 驱动层面的负载均衡,对多节点集群连接至关重要
topology None 映射为连接串中的 topology_keys,用于约束流量在指定拓扑(可用区/region)内路由
yb_servers_refresh_interval 300 集群节点列表刷新间隔(秒)
fallback_to_topology_keys_only False 当拓扑键不可达时是否仅回退到拓扑键内节点
failed_host_ttl_seconds 5 失败主机被临时拉黑的最短时间(秒)
connection_string None 直接传入完整连接串或 sqlalchemy.engine.URL,可跳过上述拼接逻辑

这些查询参数由 from_params 通过 urllib.parse.urlencode 拼进连接串(见 base.py),更多驱动级参数可查阅 YugabyteDB psycopg2 驱动文档。

4.2 存储行为参数(init

参数 默认值 说明
table_name "llamaindex" 逻辑表名,会自动小写;实际物理表名为 data_{table_name}
schema_name "public" 表所在 schema,自动小写;只允许字母、数字与下划线
embed_dim 1536 向量维度,须与所用 Embedding 模型输出维度一致(如 OpenAI 默认 1536)
hybrid_search False 是否启用「稠密向量 + 全文检索」混合模式,开启后会额外创建 TSVECTOR 计算列
text_search_config "english" 全文检索的文本搜索配置(如 englishsimple),hybrid 模式下必填,否则抛 ValueError
cache_ok False 自定义 TSVector 类型装饰器是否可安全参与 SQLAlchemy 编译缓存键
perform_setup True 是否在首次使用时自动执行 schema/extension/建表/HNSW 索引等初始化 DDL
debug False 透传给 SQLAlchemy create_engine(echo=...),开启后打印 SQL 日志
use_jsonb False 元数据列使用 JSONB 而非 JSONJSONB 支持 @> 包含操作符过滤
hnsw_kwargs None 提供则创建 HNSW 索引(详见下文);None 表示关闭 ANN 索引
create_engine_kwargs {} 透传给 create_engine 的额外关键字参数
use_halfvec False 向量列使用 HALFVEC(半精度)以节省存储并提升检索吞吐
indexed_metadata_keys None 需要建立 B-tree 索引的元数据键集合,元素为 (key, PGType) 二元组
initialization_fail_on_error False 初始化某一步失败时是否直接抛出异常(默认仅记录 warning 继续)
engine None 复用外部传入的 SQLAlchemy Engine,跳过内部创建

其中 indexed_metadata_keysPGType 必须取自白名单:textintintegernumericfloatdouble precisionbooleandatetimestampuuid(类型映射见 base.py),传入其他类型会直接抛 ValueError

五、底层原理:动态建表与自动初始化

YBVectorStore 最核心的实现技巧是用 SQLAlchemy 动态建模get_data_model 函数(base.py)以 type() 动态生成表模型,表结构为:

类型 说明
id BIGINT 自增主键 行主键
text VARCHAR NOT NULL 节点原文
metadata_ JSONJSONB 节点元数据(去掉文本后的序列化结果)
node_id VARCHAR LlamaIndex 节点 ID
embedding Vector(embed_dim)HALFVEC(embed_dim) 向量列
text_search_tsv TSVECTOR(计算列) 仅 hybrid 模式存在,由 to_tsvector('<config>', text) 持久化计算

每次 add/query 等操作触发 _initialize()base.py)时,会按顺序执行四步幂等初始化:

  1. _create_schema_if_not_exists:校验 schema 名合法性,查询 information_schema.schemata,不存在则 CREATE SCHEMA IF NOT EXISTS
  2. _create_extensionCREATE EXTENSION IF NOT EXISTS vector
  3. _create_tables_if_not_existsmetadata.create_all 建表并创建元数据 B-tree 索引与 ref_doc_id 索引;
  4. 若提供 hnsw_kwargs,则 _create_hnsw_index 创建 HNSW 索引。

由于 DDL 全部是 IF NOT EXISTS 幂等语义,多个 YBVectorStore 实例指向同一表时不会互相破坏——测试 test_hnsw_index_creationtest_yugabytedb.py)专门验证了创建两个实例后 pg_indexes 中 HNSW 索引恰好只有一份。若某一步失败,默认只记录 PG Setup: ... 警告日志;只有 initialization_fail_on_error=True 时才会向上抛出。

六、HNSW 近似最近邻索引

当传入 hnsw_kwargs 时,YBVectorStore 会使用 YugabyteDB 原生的 ybhnsw 索引加速向量检索:

vector_store = YBVectorStore.from_params(
    host="localhost",
    user="yugabyte",
    password="yugabyte",
    port=5433,
    load_balance="True",
    database="yugabyte",
    table_name="hnsw_table",
    schema_name="public",
    embed_dim=1536,
    hnsw_kwargs={
        "hnsw_m": 16,                 # 每层最大连接数
        "hnsw_ef_construction": 64,   # 建图时的动态候选列表大小
        "hnsw_ef_search": 40,         # 检索时的候选列表大小(可选)
        "hnsw_dist_method": "vector_cosine_ops",  # 可选,默认自动推断
    },
)

base.py 的实现可以看到三个关键行为:

  • hnsw_ef_constructionhnsw_m 必填,缺失直接抛 ValueError
  • 距离算子默认自动推断:use_halfvec=True 时用 halfvec_l2_ops,否则用 vector_cosine_ops,也可显式指定 hnsw_dist_method 覆盖;
  • 生成的索引名为 {物理表名}_embedding_idx,例如 data_test_table_embedding_idx,对应 SQL:
    CREATE INDEX IF NOT EXISTS data_xxx_embedding_idx
    ON schema.data_xxx USING ybhnsw (embedding vector_cosine_ops)
    WITH (m = 16, ef_construction = 64);
    

七、半精度向量:use_halfvec

use_halfvec=True 时,embedding 列改用 pgvector 的 HALFVEC 类型(base.py),以 16 位浮点存储向量,从而将向量存储占用减半。官方测试对普通向量与半精度向量并行验证了同一套能力矩阵:写入查询、元数据过滤、IN/CONTAINS/IS_EMPTY 操作符、删除、清空等场景均以参数化方式覆盖(见 test_yugabytedb.py),说明半精度模式功能上与全精度等价,只是精度/性能取舍不同。

八、混合搜索:稠密向量 + 全文检索

开启 hybrid_search=True 后,YBVectorStore 在稠密余弦检索之外,还会基于 text_search_tsv 计算列执行 PostgreSQL 全文检索。查询通过 VectorStoreQueryMode 区分三种模式(base.py):

from llama_index.core.vector_stores.types import VectorStoreQuery, VectorStoreQueryMode

# 模式一:纯稠密(默认)
q_dense = VectorStoreQuery(query_embedding=[0.1, 0.2, ...], similarity_top_k=5)

# 模式二:纯稀疏全文检索
q_sparse = VectorStoreQuery(
    query_str="who is the fox?",
    sparse_top_k=5,
    mode=VectorStoreQueryMode.SPARSE,
)

# 模式三:混合(dense + sparse 结果合并去重)
q_hybrid = VectorStoreQuery(
    query_embedding=[0.1, 0.2, ...],
    query_str="fox",
    similarity_top_k=5,
    mode=VectorStoreQueryMode.HYBRID,
)

混合查询的内部流程(_hybrid_querybase.py)值得注意:

  • sparse_top_k 未指定时回退到 similarity_top_k
  • 稠密与稀疏结果按 node_id 去重后简单拼接,不支持 alpha 加权参数(传入会打印 warning 后忽略);
  • 稀疏分支使用 plainto_tsquery 生成查询,并将 & 替换为 | 以执行 OR 语义、提高召回率(见 _build_sparse_query);
  • 稀疏排序基于 ts_rank

测试覆盖了混合查询的多种情形(test_yugabytedb.py):带 sparse_top_k、缺省 sparse_top_k、句子级查询、叠加元数据过滤等;同时验证了混合模式下必须提供 query_str,否则抛出 "query_str must be specified for a sparse vector query."

九、元数据过滤

9.1 操作符映射

_to_postgres_operatorbase.py)将 LlamaIndex 的 FilterOperator 映射为 SQL 操作符:

FilterOperator SQL 说明
EQ / GT / LT / NE / GTE / LTE = > < != >= <= 标量比较;数值类型会自动 ::float 强转
IN / NIN IN / NOT IN 元数据为单值、过滤值为列表
CONTAINS @> 元数据为列表、过滤值为单值(依赖 JSONB @>
TEXT_MATCH / TEXT_MATCH_INSENSITIVE LIKE / ILIKE 自动包裹 %...% 模糊匹配
IS_EMPTY IS NULL 判断键不存在

过滤条件支持 MetadataFiltersand/or 组合,并可嵌套(_recursively_apply_filters)。典型用法:

from llama_index.core.vector_stores.types import (
    MetadataFilters, MetadataFilter, FilterOperator,
)

filters = MetadataFilters(
    filters=[
        MetadataFilter(key="category", value="news", operator=FilterOperator.EQ),
        MetadataFilter(
            key="tags",
            value=["ai", "llm"],
            operator=FilterOperator.IN,
        ),
    ],
    condition="and",
)
q = VectorStoreQuery(query_embedding=embedding, similarity_top_k=10, filters=filters)

9.2 元数据键预索引

对于高频过滤字段,可通过 indexed_metadata_keys 提前建立 B-tree 索引,避免每次查询全表扫描:

vector_store = YBVectorStore.from_params(
    ...,
    indexed_metadata_keys={("category", "text"), ("year", "int")},
)

get_data_model 可见,每个键会生成形如 {indexname}_{key}_{type} 的 btree 索引,例如 test_table_idx_category_text,其底层利用 metadata_->>keycast 表达式实现。

十、增删改查与生命周期管理

YBVectorStore 实现了 LlamaIndex 向量存储的标准接口:

方法 签名要点 行为
add(nodes) 接收 List[BaseNode] 逐条写入,返回写入的 node_id 列表
query(query) 接收 VectorStoreQuery mode 分发稠密/稀疏/混合查询,返回 VectorStoreQueryResult(nodes、similarities、ids)
delete(ref_doc_id) 按文档 ID 删除 依据 metadata_->>'doc_id' 匹配删除整篇文档的节点
delete_nodes(node_ids, filters) 按节点 ID 与/或元数据过滤删除 node_idsfilters 同时为空时直接返回;组合条件按 AND 语义
get_nodes(node_ids, filters) 按 ID 或过滤条件取回节点 二者至少提供一个;返回完整 BaseNode(含 embedding)
clear() 无参 清空整张表
close() 异步方法 释放 SQLAlchemy Engine 连接池

节点写入时(_node_to_table_row),textMetadataMode.NONE 下的纯文本,metadata_node_to_metadata_dict(remove_text=True, flat_metadata=...) 序列化结果;查询回读时优先通过 metadata_dict_to_node 还原节点,若元数据格式异常则回退到 Legacy TextNode 逻辑以保证向后兼容(见 _db_rows_to_query_result)。

连接管理上,client 属性在初始化前返回 None、初始化后返回 SQLAlchemy Engine;也支持外部传入 engine 复用既有连接(测试 test_custom_engines 验证了该路径)。

十一、测试与验证

仓库为 YBVectorStore 提供了两层测试:

  • 集成测试 test_yugabytedb.py:需要本地 YugabyteDB(连接参数 host=localhost, user=yugabyte, password=yugabyte, port=5433),未连接时自动 skipif。覆盖实例创建、写入查询、HNSW/半精度/混合搜索全组合、各类元数据操作符、delete_nodes 的多种组合语义、get_nodes 参数化用例、clear 等;
  • 结构测试 test_vector_stores_yugabytedb.py:断言类继承自 BasePydanticVectorStore,保证接口契约合规。

运行方式(见 tests/README.md):先 ./bin/yugabyted start 启动节点,再执行 uv run -- pytest

十二、注意事项与限制

  1. hybrid_searchtext_search_config:启用混合搜索必须显式指定 text_search_config,否则构造时抛 ValueError
  2. 混合搜索不支持 alpha:稠密与稀疏结果是等权拼接去重,无法调节二者权重;
  3. hnsw_kwargs 的必填项hnsw_ef_constructionhnsw_m 缺一不可;
  4. schema 名严格受限:仅允许 ^[A-Za-z_][A-Za-z0-9_]*$ 模式,防止 SQL 注入;
  5. 表名会被小写化并加 data_ 前缀:物理表名与逻辑 table_name 不一致,排查问题时需注意;
  6. 连接参数可走 connection_string:生产环境建议直接传入完整连接串(含负载均衡等查询参数),避免逐项拼参;
  7. perform_setup=False 的场景:当表结构已由外部 DBA 预先创建、应用只有只读/写入权限时,可关闭自动 DDL 以避免权限报错。

综上,YBVectorStore 是 LlamaIndex 官方向量存储生态中面向分布式数据库场景的成熟选择,既保留 pgvector 的简单建模方式,又借助 YugabyteDB 的 ybhnsw 与全文检索能力,让 RAG 应用在水平扩展的 SQL 集群上同时获得向量检索与关键词检索能力。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395