首页
/ LlamaIndex Typesense 向量存储(TypesenseVectorStore)接入指南:从集合创建到混合检索的源码级解析

LlamaIndex Typesense 向量存储(TypesenseVectorStore)接入指南:从集合创建到混合检索的源码级解析

2026-09-09 20:57:25作者:邓越浪Henry

本文围绕 LlamaIndex 的 llama-index-vector-stores-typesense 集成包展开,系统讲解 TypesenseVectorStore 的安装方式、构造参数、数据写入、按文档删除以及基于 Typesense 多搜索接口的向量检索与全文检索流程。读者读完可以掌握如何在 LlamaIndex 中基于 Typesense 构建可持久化的向量索引,并理解其底层实现细节,便于二次定制或排障。

一、集成包概览与安装

TypesenseVectorStore 是 LlamaIndex 官方提供的向量存储集成之一,它将节点的 embedding 向量与文本内容统一存入 Typesense 的 collection(集合)中,查询时借助 Typesense 的 multi_search 接口一次性完成向量近似检索(vector search)或文本全文检索(text search)。

pyproject.toml 中可以看到该包的核心依赖约束:

  • typesense>=0.19.0,<0.20:Typesense 官方 Python 客户端;
  • llama-index-core>=0.13.0,<0.15:依赖 LlamaIndex 核心库(含 BasePydanticVectorStoreVectorStoreQuery 等基础类型)。

安装命令(来自源码 docstring 中的官方示例):

pip install llama-index-vector-stores-typesense

包入口在 init.py,仅导出 TypesenseVectorStore 一个类。

二、快速开始:客户端与向量存储初始化

使用前需要先准备一个 Typesense 客户端。以本地 Typesense 服务为例,源码 base.py 给出的最小初始化示例为:

from llama_index.vector_stores.typesense import TypesenseVectorStore
from typesense import Client

# 在 Typesense 控制台申请或获取 API Key
typesense_client = Client(
    {
        "api_key": "your_api_key_here",
        "nodes": [{"host": "localhost", "port": "8108", "protocol": "http"}],
        "connection_timeout_seconds": 2,
    }
)

# 创建向量存储实例
vector_store = TypesenseVectorStore(typesense_client)

随后即可将 vector_store 作为 VectorStoreIndex.from_vector_store(vector_store=...) 的存储后端接入标准 LlamaIndex 索引流程。

类型校验:构造函数会强制校验 client 必须是 typesense.Client 实例,否则抛出 ValueError(见 base.py)。如果使用 Client 之外的客户端对象(例如模拟对象或错误导入的类),会得到明确的类型错误提示。

三、构造参数详解

TypesenseVectorStore.__init__ 提供以下可调参数(源码 base.py):

参数 类型 默认值 作用
client Any(实为 typesense.Client 必填 Typesense 客户端,用于所有底层操作
tokenizer Optional[Callable[[str], List]] None(使用 get_tokenizer() 分词函数,影响文本相关处理
text_key str DEFAULT_TEXT_KEY(来自 llama_index.core.vector_stores.utils,即 "text" 文档正文在 Typesense 文档中对应的字段名,同时作为全文检索的 query_by 字段
collection_name str "default_collection" Typesense 集合名,对应 collections["default_collection"]
batch_size int 100 批量导入文档时的批次大小
metadata_key str "metadata" 元数据在 Typesense 文档中对应的字段名

其中模块级常量定义在 base.py

  • DEFAULT_COLLECTION_NAME = "default_collection"
  • DEFAULT_BATCH_SIZE = 100
  • DEFAULT_METADATA_KEY = "metadata"

text_keymetadata_key 直接决定了写入 Typesense 的 JSON 文档结构,如果与已有 collection 的 schema 冲突(例如 collection 中已存在同名但类型不同的字段),导入时会按 Typesense 的 schema 校验规则报错。

此外,类还声明了三个 Pydantic 字段(base.py):

  • stores_text: bool = True:声明该存储保留原始文本,检索结果可直接还原出文本节点;
  • is_embedding_query: bool = False:默认不要求查询时传入 embedding(全文检索模式可用);
  • flat_metadata: bool = False:控制元数据是否以扁平结构写入,传入 add 时透传给 node_to_metadata_dict

四、集合(Collection)的自动创建

TypesenseVectorStore 不会在构造时强制要求 collection 已存在。首次写入时,如果 collection 尚未创建,底层会捕获 Typesense 的 ObjectNotFound 异常并自动建集合,逻辑如下(源码 base.py):

fields = [
    {"name": "vec", "type": "float[]", "num_dim": num_dim},
    {"name": f"{self._text_key}", "type": "string"},
    {"name": ".*", "type": "auto"},
]
self._client.collections.create(
    {"name": self._collection_name, "fields": fields}
)

关键点:

  • vec 字段类型为 float[]num_dim 由首批节点的 embedding 维度决定(len(nodes[0].get_embedding())),因此同一 collection 的向量维度需保持一致;
  • 文本字段的类型为 string
  • 通配字段 .* 类型为 auto,意味着除 vec 与文本字段外的其他字段(含 metadataref_doc_id)由 Typesense 自动推断类型,这为写入异构元数据提供了灵活性。

五、写入节点:upsert 导入

add(nodes) 方法将节点批量写入 collection(源码 base.py):

  1. 调用 _create_upsert_docs(nodes) 将每个节点转换为字典(base.py):
    • idnode.node_id,作为 Typesense 文档主键;
    • vecnode.get_embedding() 向量;
    • {text_key}node.get_content(metadata_mode=MetadataMode.NONE),即纯文本正文;
    • ref_doc_idnode.ref_doc_id,用于按文档删除;
    • {metadata_key}node_to_metadata_dict(node, remove_text=True, flat_metadata=self.flat_metadata) 序列化后的元数据字典。
  2. 调用 collection.documents.import_(docs, {"action": "upsert"}, batch_size=self._batch_size) 执行批量 upsert——action: "upsert" 意味着相同 id 的文档会被覆盖更新,适合增量写入场景。
  3. 若 collection 不存在(抛出 ObjectNotFound),先自动建集合,再重试导入。
  4. 返回所有写入节点的 node_id 列表。

六、删除节点

delete(ref_doc_id) 按引用文档 ID 删除集合中所有关联节点(源码 base.py):

collection.documents.delete({"filter_by": f"ref_doc_id:={ref_doc_id}"})

Typesense 的删除接口使用过滤表达式 ref_doc_id:={ref_doc_id}:= 是精确匹配操作符,因此一个 ref_doc_id 下被切分出的多个节点会被一次性清空,这与 LlamaIndex 中"按文档级删除"的语义一致。

七、查询:向量检索与全文检索

query(query: VectorStoreQuery) 统一处理两类检索模式,底层复用 Typesense 的 multi_search.perform 接口(源码 base.py)。

7.1 过滤器转换

查询前先将 LlamaIndex 标准的 MetadataFilters 转换为 Typesense 过滤表达式(base.py):遍历 standard_filters.legacy_filters(),若存在 key == "filter_by" 的过滤器,则直接将其 value 作为 Typesense 的 filter_by 字符串返回;否则返回空串。也就是说,使用该存储时可在查询中通过 MetadataFilters 携带原生 Typesense 过滤语法(如 ref_doc_id:=xxxmetadata.department:=Engineering 等)。

7.2 向量相似检索(默认模式)

query.mode 不是 VectorStoreQueryMode.TEXT_SEARCH 时:

embedded_query = [str(x) for x in query.query_embedding]
search_requests = {
    "searches": [
        {
            "collection": self._collection_name,
            "q": "*",
            "vector_query": f"vec:([{','.join(embedded_query)}],k:{query.similarity_top_k})",
            "filter_by": typesense_filter,
        }
    ]
}
  • 必须提供 query.query_embedding,否则抛出 ValueError("Vector search requires a query embedding")
  • vector_query 使用 vec:([...], k:N) 语法,kquery.similarity_top_k,即返回最相似的 Top-K 个节点;
  • 文本查询词固定为 "*"(匹配所有文档,由向量距离排序)。

7.3 全文检索模式

query.mode is VectorStoreQueryMode.TEXT_SEARCH 时,改为基于关键词的全文检索:

search_requests = {
    "searches": [
        {
            "collection": self._collection_name,
            "q": query.query_str,
            "query_by": self._text_key,
            "filter_by": typesense_filter,
        }
    ]
}
  • 必须提供 query.query_str,否则抛出 ValueError("Text search requires a query string")
  • query_by 指向 text_key 字段,即使用正文文本做全文匹配,该模式不需要 embedding,这也是类属性 is_embedding_query = False 的由来。

7.4 结果组装

multi_search 响应中遍历 response["results"][0]["hits"]

  • 向量模式下,相似度分数取自 hit["vector_distance"]。源码注释明确指出:Typesense 的向量距离范围是 0 到 2,0 表示最相似,2 表示最不相似(见 base.py)。因此该模式下返回的 similarities 是"距离"而非"相似度分数",数值越小越相关,消费端排序时需注意方向;
  • 节点还原优先使用 metadata_dict_to_node 从元数据重建节点并回填文本;若元数据格式为旧版结构(解析失败),则回退到 legacy_metadata_dict_to_node 并手动构造 TextNode,保证向前兼容旧数据;
  • 最终返回 VectorStoreQueryResult(nodes=top_k_nodes, similarities=top_k_scores, ids=top_k_ids),其中全文检索模式下的 similaritiesNone

八、设计要点与源码指引

  1. 继承体系TypesenseVectorStore 继承自 BasePydanticVectorStore(见 base.py),该继承关系由测试 test_vector_stores_typesense.py 通过 __mro__ 显式断言,确保其符合 LlamaIndex 向量存储抽象接口的约定。
  2. 客户端与集合访问clientcollection 均以只读属性暴露,方便外部在调试或运维时直接访问底层对象(base.py)。
  3. 扩展路径typesense 客户端(typesense>=0.19.0)是唯一强依赖外部服务,相关约束见 pyproject.toml

九、适用场景与注意事项

  • 适合已在生产环境使用 Typesense、希望复用其集群与运维能力的团队,将 LlamaIndex 的向量索引直接落在 Typesense collection 上;
  • 向量维度由首个写入批次决定,混合使用不同 embedding 模型时需分别建集合或保持维度一致;
  • 检索分数语义为"距离"(0 最相似、2 最不相似),若沿用 LlamaIndex 中"分数越高越相关"的习惯需要自行反转;
  • add 为 upsert 语义、deleteref_doc_id 级联,写入与删除均通过 Typesense 原生接口完成,具体过滤语法可在 MetadataFilters 中以 filter_by 键透传。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
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