首页
/ LlamaIndex 集成阿里云 Lindorm 向量存储:LindormVectorStore 实战指南

LlamaIndex 集成阿里云 Lindorm 向量存储:LindormVectorStore 实战指南

2026-09-09 20:12:26作者:滕妙奇

本篇技术指南围绕 LlamaIndex 官方仓库中的 Lindorm 向量存储集成(llama-index-vector-stores-lindorm)展开,系统讲解如何在 LlamaIndex 中使用阿里云 Lindorm 搜索引擎作为向量数据库,涵盖索引自动创建、IVFPQ/HNSW 索引映射参数、数据写入、kNN 检索、元数据过滤、词法检索、混合检索与删除操作。读者完成本文阅读后,将能够独立配置 Lindorm 实例接入 LlamaIndex,并针对不同召回场景正确选择检索模式与索引参数。

一、集成概览:Lindorm 在 LlamaIndex 中的定位

阿里云 Lindorm 是一款多模数据库,其搜索引擎(LindormSearch)提供兼容 OpenSearch/Elasticsearch 协议的能力,并原生支持向量检索。在 LlamaIndex 中,该能力被封装为 LindormVectorStore 向量存储实现,位于集成包 llama-index-vector-stores-lindorm

该集成的核心能力(与官方 README.md 一致)包括:

  • 纯向量检索(kNN 近似检索)
  • 带元数据过滤的向量检索(pre-filter / post-filter)
  • 词法(文本)检索
  • 向量 + 词法混合检索(Hybrid Search)
  • 完整的同步与异步接口(add / async_addquery / aquerydelete / adelete

从代码结构看,集成包由两个核心类组成(base.py):

  • LindormVectorClient:底层客户端,封装"单个启用了向量搜索的 Lindorm 索引"的全部操作,包括建索引、批量写入、构造各类查询;
  • LindormVectorStore:面向 LlamaIndex 的向量存储适配层,继承自 BasePydanticVectorStore,负责把 LlamaIndex 的 BaseNode / VectorStoreQuery 语义翻译给底层客户端。

两者的导出关系见 init.py

二、安装与依赖

根据集成包 pyproject.tomlREADME.md,需要安装三个包:

pip install llama-index
pip install opensearch-py
pip install llama-index-vector-stores-lindorm

依赖约束如下(来自 pyproject.toml):

  • opensearch-py[async]>=2.4.2,<3:Lindorm 客户端基于 OpenSearch Python SDK 实现(因为 LindormSearch 兼容 OpenSearch 协议),且依赖其异步能力;
  • llama-index-core>=0.13.0,<0.15:核心框架依赖。

需要说明的是,底层客户端内部对 opensearchpy 的导入是延迟的——如果环境中缺少该 SDK,初始化时会抛出提示信息:"Could not import OpenSearch Python SDK. Please install it with pip install opensearch-py"(见 base.py)。

三、连接 Lindorm 实例并初始化客户端

3.1 前置信息

使用前需要先获取 Lindorm 搜索引擎实例的连接信息:实例的公网/私网访问地址(host)、端口(port)、账号与密码。官方文档中建议通过以下途径准备环境(此处仅给出操作指引,对应文档位于阿里云官方帮助中心,搜索关键词即可找到):

  • 创建 Lindorm 实例;
  • 查看实例访问地址与端口;
  • 使用 curl 命令验证与 LindormSearch 的连通性。

3.2 初始化 LindormVectorClient

LindormVectorClient 的初始化签名如下(base.py):

LindormVectorClient(
    host, port, username, password, index, dimension,
    text_field="content",
    max_chunk_bytes=1 * 1024 * 1024,
    os_client=None,
    **kwargs,
)

必填参数:

参数 说明
host Lindorm 搜索引擎的兼容 Elasticsearch 主机地址
port Lindorm 实例端口
username / password 实例访问账号与密码
index 索引名称(不存在时会在初始化阶段自动创建)
dimension 向量维度,必须与所选 embedding 模型的输出维度一致

可选参数:

参数 默认值 说明
text_field "content" 文档正文存储的字段名
max_chunk_bytes 1 * 1024 * 1024 批量写入时单个数据块的最大字节数
os_client None 可传入外部构造好的 OpenSearch 异步客户端,缺省时内部自动创建

初始化时的关键行为是自动建索引:客户端会先查询索引是否存在,捕获 NotFoundError 后按内部构造的 mapping 创建索引并执行 refresh(base.py)。因此该索引要么尚未创建,要么是此前由本类创建过的——这是该类文档字符串中明确说明的假设前提。

四、索引映射与算法参数详解

初始化时客户端会自动生成索引 mapping(base.py),核心结构为:

{
  "settings": {"index": {"number_of_shards": 4, "knn": true}},
  "mappings": {
    "_source": {"excludes": ["vector_field"]},
    "properties": {
      "vector_field": {
        "type": "knn_vector",
        "dimension": 1536,
        "data_type": "float",
        "method": {
          "engine": "lvector",
          "name": "ivfpq",
          "space_type": "l2",
          "parameters": {...}
        }
      }
    }
  }
}

其中 vector_field 默认值为 "vector_field",向量以 knn_vector 类型、float 数据存储,并通过 method 指定索引算法。相关参数均通过 kwargs 传入,分为三类。

4.1 通用 mapping 参数

参数 默认值 取值/说明
method_name "ivfpq" 索引算法:ivfpqhnsw;传入其他值会抛出 RuntimeError
engine "lvector" Lindorm 向量引擎标识
space_type "l2" 距离度量:l2cosinesimilinnerproduct
vector_field "vector_field" 向量字段名

4.2 Lindorm 搜索扩展参数

参数 默认值 说明
filter_type "post_filter" 过滤方式:pre_filter(先过滤后检索)或 post_filter(先检索后过滤);传入其他值会抛出 ValueError
nprobe "1" 查询时访问的聚类簇数量,取值范围 1 到 method.parameters.nlist,以字符串形式传入
reorder_factor "10" 重排序因子,用于提升召回精度但会增加性能开销,取值范围 1 到 200,默认 10,字符串形式

4.3 IVFPQ 专用参数

method_name="ivfpq" 时(base.py):

参数 默认值 说明
m 等于 dimension 子空间数量,范围 2 到 32768
nlist 10000 聚类中心数量,范围 2 到 1000000
centroids_use_hnsw True 搜索聚类中心时是否使用 HNSW 算法
centroids_hnsw_m 16 聚类中心 HNSW 图的边数,范围 1 到 100
centroids_hnsw_ef_search 100 k-NN 检索时动态列表大小,值越大检索越准但越慢
centroids_hnsw_ef_construct 100 k-NN 构图时动态列表大小,值越大图越准但建索引越慢

4.4 HNSW 专用参数

method_name="hnsw" 时(base.py):

参数 默认值 说明
m 16 图中每层最大出边数,范围 1 到 100
ef_construction 100 建索引时动态列表长度,范围 1 到 1000

五、典型初始化示例

以下代码来自集成包 README.mdbase.py 中的官方示例:

from llama_index.vector_stores.lindorm import (
    LindormVectorStore,
    LindormVectorClient,
)

# lindorm instance info
host = "ld-bp******jm*******-proxy-search-pub.lindorm.aliyuncs.com"
port = 30070
username = "your_username"
password = "your_password"

# index to demonstrate the VectorStore impl
index_name = "lindorm_test_index"

# extension param of lindorm search,
# number of cluster units to query; between 1 and method.parameters.nlist.
nprobe = "a number(string type)"

# extension param of lindorm search, usually used to improve recall accuracy,
# but it increases performance overhead; between 1 and 200; default: 10.
reorder_factor = "a number(string type)"

# LindormVectorClient encapsulates logic for a single index with vector search enabled
client = LindormVectorClient(
    host=host,
    port=port,
    username=username,
    password=password,
    index=index_name,
    dimension=1536,  # match with your embedding model
    nprobe=nprobe,
    reorder_factor=reorder_factor,
    # filter_type="pre_filter/post_filter(default)"
)

# initialize vector store
vector_store = LindormVectorStore(client)

几点实操提醒:

  • dimension 必须与 embedding 模型输出维度一致(示例使用 1536,对应常见的 OpenAI text-embedding-ada-002 一档模型维度);
  • nprobereorder_factor 在代码中以字符串形式传入(其类型注释为 str);
  • 若需使用 pre_filter 过滤策略,在初始化时显式传入 filter_type="pre_filter"

六、数据写入:add / async_add

LindormVectorStore 通过 add(同步)与 async_add(异步)两个入口写入节点(base.py):

def add(self, nodes: List[BaseNode], **add_kwargs: Any) -> List[str]:
    return asyncio.get_event_loop().run_until_complete(
        self.async_add(nodes, **add_kwargs)
    )

async def async_add(self, nodes: List[BaseNode], **add_kwargs: Any) -> List[str]:
    await self._client.index_results(nodes)
    return [result.node_id for result in nodes]
  • 同步方法是对异步逻辑的封装(run_until_complete),因此要求在可运行事件循环的上下文中调用;
  • 返回值为写入节点的 node_id 列表。

底层 index_results 会把每个节点拆分为四类数据后批量写入(base.py):

  • node_id 作为文档 _id
  • node.get_embedding() 作为向量;
  • node.get_content(metadata_mode=MetadataMode.NONE) 作为正文文本(写入 text_field);
  • node_to_metadata_dict(node, remove_text=True) 作为元数据。

批量写入使用 opensearchpy.helpers.async_bulk,受 max_chunk_bytes 约束,写入完成后立即执行 refresh 以保证可见性(base.py)。

七、检索:三种查询模式与元数据过滤

7.1 查询入口

查询统一走 query / aquery 接口,入参为 LlamaIndex 的 VectorStoreQuery 对象(base.py),实际委托给底层客户端的 aquery

async def aquery(self, query: VectorStoreQuery, **kwargs: Any) -> VectorStoreQueryResult:
    query_embedding = cast(List[float], query.query_embedding)
    return await self._client.aquery(
        query.mode,
        query.query_str,
        query_embedding,
        query.similarity_top_k,
        filters=query.filters,
    )

底层 aquery 根据 query.mode 分发到三种查询构造器(base.py):

查询模式 走通的分支 说明
VectorStoreQueryMode.HYBRID _hybrid_search_query 向量 + 词法混合检索;此时必须提供 query_str,否则抛出 "Please specify the lexical_query for hybrid search."
VectorStoreQueryMode.TEXT_SEARCH _lexical_search_query 纯词法检索,基于 text_field 字段做 match 匹配
其他模式(默认/DEFAULT _knn_search_query 纯向量 kNN 近似检索

7.2 kNN 检索与过滤策略

_knn_search_query 的核心逻辑(base.py):

  • 无元数据过滤时:构造纯近似 kNN 查询,请求体为 query.knn + 扩展的 ext.lvector(携带 nprobereorder_factor);
  • 有元数据过滤时:在 kNN 查询中嵌入过滤条件。过滤条件组合规则为:FilterCondition.ANDbool.mustFilterCondition.ORbool.should;其他条件(如 NOT)当前不受支持,会抛出 ValueError

MetadataFilter 支持的操作符映射(base.py):

FilterOperator 生成的 DSL 说明
GTE / LTE / GT / LT range 查询 数值范围过滤
EQ term 查询 精确匹配
其他 抛出 ValueError("Unsupported filter operator")

同时要注意源码中的明确说明:纯近似 kNN 检索本身不支持元数据过滤,一旦带过滤条件,查询会走带 filter 的精确 kNN 路径。

7.3 词法检索与混合检索

  • 词法检索:构造 bool.must + match 查询作用于 text_field,若存在元数据过滤则追加到 bool.filterbase.py);
  • 混合检索:将词法查询的 bool.must 条件注入 kNN 查询的过滤上下文,两者组合后在单个请求中完成向量 + 文本联合召回(base.py)。

7.4 结果解析

检索结果通过 _to_query_result 转换为 VectorStoreQueryResultbase.py),转换逻辑为:

  • 优先通过 metadata_dict_to_node 重建节点(覆盖正文文本);
  • 若元数据无法解析(旧数据兼容),则退化为直接构造 TextNode,从 node_info 中恢复 start_char_idx / end_char_idx,并从 relationships 恢复关系;
  • 最终返回 nodesidssimilarities(即 _score)三要素。

八、删除操作

delete / adeleteref_doc_id 为入参,删除该文档对应的全部节点(base.py)。底层通过 delete_by_query 执行(base.py):

search_query = {"query": {"term": {"doc_id.keyword": {"value": doc_id}}}}
await self._os_client.delete_by_query(index=self._index, body=search_query)

即按 doc_id.keyword 字段精确匹配并删除相关节点。

九、测试验证与可复现示例

集成包自带完整测试,可作为理解 API 行为与验证环境的参考:

  • tests/test_vector_stores_lindorm.py:验证 LindormVectorStore 正确继承自 BasePydanticVectorStore
  • tests/test_lindorm_client.py:端到端集成测试,覆盖以下场景:
    • test_add_nodes:批量写入 1000 个节点,断言返回 ID 数量一致;
    • test_simple_query:5 维向量纯 kNN 检索;
    • test_query_with_metadata_filtermark_id 字段 GTE / LTE + AND 组合过滤检索;
    • test_lexical_query:词法检索(注意:查询词的最小检索粒度是一个 token);
    • test_hybrid_query:混合检索;
    • test_delete_node:按 ref_doc_id 删除后,用 relationships.SOURCE.node_id 过滤查询确认节点已不可见。

测试中索引维度为 5、nprobe="2"reorder_factor="10",并针对占位配置(含 < 字符)做了跳过处理——这意味着运行集成测试需要真实的 Lindorm 实例连接信息,无实例时测试会被 pytest.skip 跳过。

十、使用注意事项小结

  1. 协议与依赖:Lindorm 搜索引擎兼容 OpenSearch 协议,因此必须安装 opensearch-py,且本集成使用的是其异步 API;
  2. 索引自动创建LindormVectorClient 初始化时若索引不存在会自动创建,默认 number_of_shards=4knn=true
  3. 参数范围约束nprobe 上限为 nlistreorder_factor 上限为 200,filter_type 仅支持 pre_filter / post_filter,非法取值会在初始化阶段报错;
  4. 过滤能力边界:纯近似 kNN 不带过滤;带过滤时条件组合仅支持 AND / OR,FilterCondition.NOT 尚未实现(源码中以 TODO 标注);
  5. 混合检索前置条件HYBRID 模式必须提供 query_str,否则直接抛错;
  6. 同步方法依赖事件循环addquerydelete 均为异步逻辑的同步包装,需要在可运行 asyncio 事件循环的环境中调用;
  7. 维度一致性dimension 必须与 embedding 模型输出严格一致,建索引后不可随意变更。

通过本文的配置与调用示例,读者可以将阿里云 Lindorm 无缝接入 LlamaIndex 的索引构建与检索链路,并在纯向量、带过滤、词法、混合四种召回策略之间按需切换。

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
900
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
927
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
603
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
397
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
525