news 2026/9/14 13:05:19

Haystack 集成 Oracle AI Vector Search:OracleDocumentStore 与 OracleEmbeddingRetriever 完整实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Haystack 集成 Oracle AI Vector Search:OracleDocumentStore 与 OracleEmbeddingRetriever 完整实战指南

Haystack 集成 Oracle AI Vector Search:OracleDocumentStore 与 OracleEmbeddingRetriever 完整实战指南

【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack

本文基于 Haystack 仓库中 Oracle 集成 API 参考文档(docs-website/reference_versioned_docs/version-2.20/integrations-api/oracle.md)编写,系统讲解如何将 Oracle Database 23ai 的 AI Vector Search 作为 Haystack 的向量文档存储后端,涵盖连接配置(Thin/Thick 模式)、文档写入与去重、HNSW 近似检索索引、向量相似度检索、元数据过滤与统计、删除清理、异步 API 及序列化等全部能力。读完本文,你将能够在自己的 RAG 与语义搜索流水线中,把OracleDocumentStoreOracleEmbeddingRetriever真正跑起来。

集成概览:把 Oracle 23ai 变成 Haystack 的向量后端

OracleDocumentStore是 Haystack 中由 Oracle AI Vector Search 支撑的 Document Store。它把文档连同稠密向量一起存进 Oracle 原生的VECTOR列,并借助自动管理的DBMS_SEARCH索引同时支持向量相似度检索关键字全文检索。该集成要求Oracle Database 23ai 或更高版本,因为 23ai 才提供VECTOR数据类型与IF NOT EXISTSDDL 支持。

集成由两个核心构件组成:

  • OracleDocumentStore(haystack_integrations.document_stores.oracle.document_store):负责建表、建索引、读写文档与元数据操作的后端存储;
  • OracleEmbeddingRetriever(haystack_integrations.components.retrievers.oracle.embedding_retriever):基于向量相似度从OracleDocumentStore中取回相关文档,通常作为 Text Embedder 之后的检索组件。

配套的使用指南可参考仓库内的 OracleEmbeddingRetriever 组件文档 与 OracleDocumentStore 文档。

安装集成包:

pip install oracle-haystack

如果使用 Sentence Transformers 系列的嵌入器,还需要安装:

pip install sentence-transformers-haystack

连接配置:OracleConnectionConfig 的 Thin 与 Thick 两种模式

OracleConnectionConfig是集成的连接参数数据类,支持两种连接模式:

  • Thin 模式(默认):通过直接 TCP 连接 Oracle,无需安装 Oracle Instant Client
  • Thick 模式:当传入wallet_location时自动激活,用于连接 Oracle Autonomous Database(ADB-S),需要钱包(wallet)文件做认证。

基础连接(Thin 模式)

推荐把敏感信息放进环境变量,再用Secret.from_env_var引用:

export ORACLE_USER="haystack" export ORACLE_PASSWORD="secret" export ORACLE_DSN="localhost:1521/freepdb1"
from haystack.utils import Secret from haystack_integrations.document_stores.oracle import ( OracleDocumentStore, OracleConnectionConfig, ) store = OracleDocumentStore( connection_config=OracleConnectionConfig( user=Secret.from_env_var("ORACLE_USER"), password=Secret.from_env_var("ORACLE_PASSWORD"), dsn=Secret.from_env_var("ORACLE_DSN"), ), embedding_dim=1536, )

连接 Oracle Autonomous Database(Thick 模式)

OracleConnectionConfig传入wallet_locationwallet_password,集成会自动切换到 Thick 模式:

document_store = OracleDocumentStore( connection_config=OracleConnectionConfig( user=Secret.from_env_var("ORACLE_USER"), password=Secret.from_env_var("ORACLE_PASSWORD"), dsn=Secret.from_env_var("ORACLE_DSN"), wallet_location="/path/to/wallet", wallet_password=Secret.from_env_var("WALLET_PASSWORD"), ), embedding_dim=1536, )

OracleConnectionConfig同样实现了to_dict()/from_dict()两个方法,用于把连接配置序列化为字典、以及从字典反序列化,方便配合 Haystack 的 YAML 管线持久化机制使用。

本地快速启动 Oracle 23ai

想在本地跑通示例,可以用 Docker 启动 Oracle Free 23ai(参考 OracleEmbeddingRetriever 组件文档):

docker run -d --name oracle23ai \ -p 1521:1521 \ -e ORACLE_PASSWORD=oracle \ -e ORACLE_INIT_PARAMS=vector_memory_size=512M \ gvenzl/oracle-free:23-slim

OracleDocumentStore 初始化参数详解

OracleDocumentStore.__init__的完整签名如下(见 API 参考):

__init__( *, connection_config: OracleConnectionConfig, table_name: str = "haystack_documents", embedding_dim: int, distance_metric: Literal["COSINE", "EUCLIDEAN", "DOT"] = "COSINE", create_table_if_not_exists: bool = True, create_index: bool = False, hnsw_neighbors: int = 32, hnsw_ef_construction: int = 200, hnsw_accuracy: int = 95, hnsw_parallel: int = 4 ) -> None

各参数含义与默认值:

参数默认值说明
connection_config(必填)Oracle 连接配置(user、password、DSN、可选 wallet)。
table_name"haystack_documents"存放文档的 Oracle 表名。必须是合法的 Oracle 标识符:仅含字母、数字、_$#,最长 128 字符,且不能以数字开头。
embedding_dim(必填)向量维度,必须与生成向量的模型一致。例如all-MiniLM-L6-v2是 384/768 维,OpenAI 的 text-embedding-3 系列常用 1536 维。
distance_metric"COSINE"相似度搜索使用的向量距离函数,可选"COSINE""EUCLIDEAN""DOT"
create_table_if_not_existsTrueTrue(默认)时,首次使用时自动创建表以及DBMS_SEARCH关键字索引;连接已存在的表时请设为False
create_indexFalseTrue时在初始化阶段创建 HNSW 向量索引,等价于手动调用create_hnsw_index()
hnsw_neighbors32HNSW 图中的邻居数。值越大召回率越高,但索引体积与构建时间也越大。
hnsw_ef_construction200HNSW 索引构建期间动态候选列表的大小。值越大召回率越高,构建时间越长。
hnsw_accuracy95HNSW 索引的目标召回率百分比(0-100)。
hnsw_parallel4构建 HNSW 索引时的并行度。

初始化时若table_name不是合法的 Oracle 标识符,或embedding_dim不是正整数,会抛出ValueError

关于向量检索模式与 HNSW 索引

默认情况下,存储执行的是精确向量搜索。当数据集较大时,可创建 HNSW 索引启用近似最近邻(ANN)搜索以换取更快的查询速度:

document_store = OracleDocumentStore( connection_config=OracleConnectionConfig( user=Secret.from_env_var("ORACLE_USER"), password=Secret.from_env_var("ORACLE_PASSWORD"), dsn=Secret.from_env_var("ORACLE_DSN"), ), embedding_dim=768, distance_metric="COSINE", create_index=True, # 启动时创建 HNSW 索引 hnsw_neighbors=32, hnsw_ef_construction=200, hnsw_accuracy=95, )

除了初始化参数,文档存储还暴露了三个索引管理方法:

  • create_keyword_index():在该表上创建DBMS_SEARCH关键字索引,用于关键字检索。可安全地重复调用——索引已存在时会静默跳过。当create_table_if_not_exists=True时会被自动调用;但连接已存在的表时,必须显式调用。
  • create_hnsw_index():在 embedding 列上创建 HNSW 向量索引,使用IF NOT EXISTS,可安全重复调用。
  • create_hnsw_index_async():异步版create_hnsw_index(),同样使用IF NOT EXISTS

写入文档与去重策略 DuplicatePolicy

write_documents/write_documents_async负责把文档写入存储:

write_documents( documents: list[Document], policy: DuplicatePolicy = DuplicatePolicy.NONE ) -> int
  • documents:待写入的文档列表;
  • policy:写入时的去重策略,返回值为实际写入的文档数量。

去重策略DuplicatePolicy定义在核心仓库的 haystack/document_stores/types/policy.py,共四个取值:

枚举值含义
DuplicatePolicy.NONE默认值,不主动检查去重,遇到重名 id 时可能直接失败(见下方异常说明)。
DuplicatePolicy.SKIP跳过已存在的文档。
DuplicatePolicy.OVERWRITE用新内容覆盖已存在的文档。
DuplicatePolicy.FAIL遇到已存在的文档直接抛错。

当 id 相同的文档已存在、且策略为DuplicatePolicy.FAILDuplicatePolicy.NONE时,会抛出DuplicateDocumentError

向量检索:OracleEmbeddingRetriever

OracleEmbeddingRetriever是兼容OracleDocumentStore的 embedding 检索器,它借助 Oracle AI Vector Search 比较查询向量与文档向量,返回最相关的文档。在管线中的典型位置是 Text Embedder 之后:

pipeline.add_component("embedder", SentenceTransformersTextEmbedder()) pipeline.add_component("retriever", OracleEmbeddingRetriever( document_store=store, top_k=5 )) pipeline.connect("embedder.embedding", "retriever.query_embedding")

run / run_async 方法

run( query_embedding: list[float], filters: dict[str, Any] | None = None, top_k: int | None = None, ) -> dict[str, list[Document]]
  • query_embedding:来自嵌入器组件的稠密浮点向量(必填);
  • filters:运行时过滤器,按照filter_policy与构造时传入的过滤器合并;
  • top_k:覆盖构造时top_k的本次调用参数;
  • 返回值:{"documents": [Document, ...]}

run_asyncrun的异步变体,签名与返回结构完全一致。

过滤器合并规则(filter_policy)

filters的合并遵循 Haystack 核心库定义的FilterPolicy(实现见 haystack/document_stores/types/filter_policy.py):

  • FilterPolicy.REPLACE(默认):运行时过滤器直接替换初始化时设置的过滤器,适合为不同查询动态切换过滤条件;
  • FilterPolicy.MERGE:把运行时过滤器与初始化过滤器合并(运行时值优先覆盖同名字段),用于逐步收窄搜索空间。

过滤器本身的语法(比较过滤器{"field", "operator", "value"}、逻辑过滤器{"operator", "conditions"})可参考仓库文档 docs-website/docs/concepts/metadata-filtering.mdx。

独立使用与完整管线示例

单独调用(示例来自 OracleEmbeddingRetriever 组件文档):

from haystack.utils import Secret from haystack_integrations.document_stores.oracle import ( OracleDocumentStore, OracleConnectionConfig, ) from haystack_integrations.components.retrievers.oracle import OracleEmbeddingRetriever document_store = OracleDocumentStore( connection_config=OracleConnectionConfig( user=Secret.from_env_var("ORACLE_USER"), password=Secret.from_env_var("ORACLE_PASSWORD"), dsn=Secret.from_env_var("ORACLE_DSN"), ), embedding_dim=768, ) retriever = OracleEmbeddingRetriever(document_store=document_store) # 使用假向量保持示例简单 retriever.run(query_embedding=[0.1] * 768)

在 Pipeline 中完成"索引 + 查询"的完整流程:

from haystack import Document, Pipeline from haystack.document_stores.types import DuplicatePolicy from haystack_integrations.components.embedders.sentence_transformers import ( SentenceTransformersDocumentEmbedder, SentenceTransformersTextEmbedder, ) from haystack.utils import Secret from haystack_integrations.document_stores.oracle import ( OracleDocumentStore, OracleConnectionConfig, ) from haystack_integrations.components.retrievers.oracle import OracleEmbeddingRetriever document_store = OracleDocumentStore( connection_config=OracleConnectionConfig( user=Secret.from_env_var("ORACLE_USER"), password=Secret.from_env_var("ORACLE_PASSWORD"), dsn=Secret.from_env_var("ORACLE_DSN"), ), embedding_dim=768, ) documents = [ Document(content="There are over 7,000 languages spoken around the world today."), Document( content="Elephants have been observed to behave in a way that indicates a high level of self-awareness, such as recognizing themselves in mirrors.", ), Document( content="In certain parts of the world, like the Maldives, Puerto Rico, and San Diego, you can witness the phenomenon of bioluminescent waves.", ), ] document_embedder = SentenceTransformersDocumentEmbedder( model="sentence-transformers/all-MiniLM-L6-v2", ) documents_with_embeddings = document_embedder.run(documents) document_store.write_documents( documents_with_embeddings["documents"], policy=DuplicatePolicy.OVERWRITE, ) query_pipeline = Pipeline() query_pipeline.add_component( "text_embedder", SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"), ) query_pipeline.add_component( "retriever", OracleEmbeddingRetriever(document_store=document_store), ) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") query = "How many languages are there?" result = query_pipeline.run({"text_embedder": {"text": query}}) print(result["retriever"]["documents"][0])

注意:使用OracleEmbeddingRetriever时,必须保证文档(索引期)与查询(查询期)都有 embedding——索引管线用 Document Embedder,查询管线用 Text Embedder。距离度量(COSINE / EUCLIDEAN / DOT)是在OracleDocumentStore上配置的。

文档过滤、统计与元数据操作

OracleDocumentStore提供了一整套与元数据打交道的方法,支撑构建复杂的过滤、统计与运维场景(完整签名见 API 参考)。

过滤与计数

  • filter_documents(filters=None)/filter_documents_async:返回匹配过滤条件的文档列表。过滤器的详细规范见 docs-website/docs/concepts/metadata-filtering.mdx。
  • count_documents()/count_documents_async:返回存储中的文档总数。
  • count_documents_by_filter(filters)/count_documents_by_filter_async:返回匹配过滤条件的文档数量,空字典匹配全部文档。
  • delete_by_filter(filters)/delete_by_filter_async:删除所有匹配过滤条件的文档并返回删除数量。空字典视为 no-op,返回0且不触碰表

更新元数据(JSON_MERGEPATCH)

update_by_filter(filters: dict[str, Any], meta: dict[str, Any]) -> int

meta合并进所有匹配文档的元数据中。底层使用 Oracle 的JSON_MERGEPATCH语义:已存在的键被更新、新键被添加、meta中值为null的键被删除meta必须是非空字典,否则抛出ValueError

元数据字段统计

  • count_unique_metadata_by_filter(filters, metadata_fields):统计匹配文档中各元数据字段的去重值数量。字段名可以带"meta."前缀(如"meta.lang""lang");metadata_fields必须非空,字段名只能包含[A-Za-z0-9_.],否则抛ValueError
  • get_metadata_fields_info():返回元数据字段名到其检测类型的映射。底层使用 Oracle 的JSON_DATAGUIDE聚合函数对存储的 metadata 列做类型探查,结果形如{"field_name": {"type": "<type>"}, ...}<type>"text""number""boolean";表为空时返回空字典。
  • get_metadata_field_min_max(metadata_field):返回某个元数据字段在全库的最小值与最大值。实现上优先尝试用TO_NUMBER做数值比较,因此MAX(1, 5, 10)会返回10而不是按字典序取胜的"5";当字段包含非数值时回退到纯字符串比较。数值字符串在结果中会自动转成intfloat。返回{"min": <value>, "max": <value>},表为空或字段不存在时两个值均为None
  • get_metadata_field_unique_values(metadata_field, search_term=None, from_=0, size=10, filters=None):返回某个元数据字段去重值的分页列表及总数,返回(values, total)元组。支持:
    • search_term:对该字段自身值做不区分大小写的子串过滤;
    • from_/size:零基偏移与页大小(size=None时返回从from_起的所有值);
    • filters:限制参与统计的文档范围。
    • 值得注意的语义:不同类型的 JSON 值不合并——字符串"1"与数字1是两个不同的去重值。唯一的例外是metadata列为 Oracle 原生JSON类型,会规范化数值存储,因此整数值的浮点1.0与整数1会合并为同一值;带小数的浮点(如1.5)不受影响。

以上每个统计方法都有对应的_async异步版本,签名与返回一致。

删除与清理操作

存储层提供从细粒度到全量的一整套删除能力,且对不可逆操作给出了明确警告:

  • delete_documents(document_ids)/delete_documents_async:按 id 列表删除文档。
  • delete_all_documents()/delete_all_documents_async:使用TRUNCATE清空表中所有文档。TRUNCATE不可恢复——不能回滚,且绕过行级触发器;表结构与索引会被保留。
  • delete_table()/delete_table_async永久删除文档表及其关联的DBMS_SEARCH关键字索引。底层使用DROP TABLE ... PURGE绕过 Oracle 回收站,操作不可逆;关键字索引在表之后删除,两步中任一步失败都会抛出DocumentStoreError

异步 API 一览

该集成对核心方法全面提供了异步版本,适合在高并发、IO 密集的 async 场景下使用。同步与异步方法一一对应:

同步方法异步方法
run(Retriever)run_async
create_hnsw_indexcreate_hnsw_index_async
write_documentswrite_documents_async
filter_documentsfilter_documents_async
delete_documentsdelete_documents_async
count_documentscount_documents_async
delete_tabledelete_table_async
delete_all_documentsdelete_all_documents_async
count_documents_by_filtercount_documents_by_filter_async
delete_by_filterdelete_by_filter_async
update_by_filterupdate_by_filter_async
count_unique_metadata_by_filtercount_unique_metadata_by_filter_async
get_metadata_fields_infoget_metadata_fields_info_async
get_metadata_field_min_maxget_metadata_field_min_max_async
get_metadata_field_unique_valuesget_metadata_field_unique_values_async

此外,OracleEmbeddingRetrieverOracleDocumentStore都实现了close()方法,用于释放底层 Document Store 持有的同步资源。

序列化与反序列化

两个核心类都实现了标准的 Haystack 序列化协议:

  • to_dict() -> dict[str, Any]:把组件序列化为字典;
  • from_dict(data) -> OracleEmbeddingRetriever/from_dict(data) -> OracleDocumentStore:从字典反序列化还原组件。

这使 Oracle 集成的文档存储与检索器可以被纳入 Haystack 的 YAML 管线定义,实现配置化、可版本化的部署。

端到端示例:基于 Oracle 的 RAG 管线

把上面的能力组合起来,就是一个完整的 RAG 应用(示例来自 OracleDocumentStore 文档):

from haystack import Document, Pipeline from haystack.document_stores.types import DuplicatePolicy from haystack_integrations.components.embedders.sentence_transformers import ( SentenceTransformersDocumentEmbedder, SentenceTransformersTextEmbedder, ) from haystack.components.builders import ChatPromptBuilder from haystack.components.generators.chat import OpenAIChatGenerator from haystack.dataclasses import ChatMessage from haystack.utils import Secret from haystack_integrations.document_stores.oracle import ( OracleDocumentStore, OracleConnectionConfig, ) from haystack_integrations.components.retrievers.oracle import OracleEmbeddingRetriever document_store = OracleDocumentStore( connection_config=OracleConnectionConfig( user=Secret.from_env_var("ORACLE_USER"), password=Secret.from_env_var("ORACLE_PASSWORD"), dsn=Secret.from_env_var("ORACLE_DSN"), ), embedding_dim=384, ) # 1. 索引文档 documents = [ Document(content="There are over 7,000 languages spoken around the world today."), Document(content="Elephants have been observed to behave in a way that indicates a high level of self-awareness."), Document(content="In certain places, you can witness the phenomenon of bioluminescent waves."), ] doc_embedder = SentenceTransformersDocumentEmbedder( model="sentence-transformers/all-MiniLM-L6-v2", ) embedded_docs = doc_embedder.run(documents)["documents"] document_store.write_documents(embedded_docs, policy=DuplicatePolicy.OVERWRITE) # 2. 构建 RAG 管线 template = [ ChatMessage.from_user( """ Given the following context, answer the question. Context: {% for doc in documents %}{{ doc.content }}{% endfor %} Question: {{ query }} """, ), ] pipeline = Pipeline() pipeline.add_component( "embedder", SentenceTransformersTextEmbedder(model="sentence-transformers/all-MiniLM-L6-v2"), ) pipeline.add_component( "retriever", OracleEmbeddingRetriever(document_store=document_store, top_k=3), ) pipeline.add_component("prompt_builder", ChatPromptBuilder(template=template)) pipeline.add_component( "llm", OpenAIChatGenerator(api_key=Secret.from_env_var("OPENAI_API_KEY")), ) pipeline.connect("embedder.embedding", "retriever.query_embedding") pipeline.connect("retriever.documents", "prompt_builder.documents") pipeline.connect("prompt_builder.prompt", "llm.messages") result = pipeline.run( { "embedder": {"text": "How many languages are there?"}, "prompt_builder": {"query": "How many languages are there?"}, }, ) print(result["llm"]["replies"][0].text)

小结

Oracle AI Vector Search 集成让 Haystack 用户可以把企业级 Oracle Database 23ai 直接用作 RAG / 语义搜索的向量后端:OracleConnectionConfig兼顾 Thin/Thick 两种连接方式,OracleDocumentStore提供完整的文档生命周期管理(写入、过滤、统计、更新、删除)与精确/近似(HNSW)两种检索路径,OracleEmbeddingRetriever则无缝接入 Haystack 管线。若需进一步深入,可在仓库内继续阅读 OracleDocumentStore 使用文档、OracleEmbeddingRetriever 使用文档 以及过滤器语法规范 docs-website/docs/concepts/metadata-filtering.mdx。

【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 13:01:05

阿基米德优化算法在路径规划中的应用与原理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 12:57:47

外观模式:简化复杂系统的设计艺术

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 12:52:56

MuJoCo MJX Shadow Hand 模型详解:E3M5 灵巧手如何适配 GPU 批量仿真

MuJoCo MJX Shadow Hand 模型详解&#xff1a;E3M5 灵巧手如何适配 GPU 批量仿真 【免费下载链接】mujoco Multi-Joint dynamics with Contact. A general purpose physics simulator. 项目地址: https://gitcode.com/GitHub_Trending/mu/mujoco 本文围绕 MuJoCo 仓库中…

作者头像 李华
网站建设 2026/9/14 12:51:45

Django+MySQL+Redis构建稳定聊天系统架构

简介&#xff1a;这是一套基于Python全栈技术实现的轻量级多人实时聊天系统&#xff0c;面向Web开发初学者与Django进阶学习者&#xff0c;解决在线通信场景下的用户管理、状态同步与消息实时推送等核心问题。资源包共80个文件&#xff0c;包含21个Python源码&#xff08;涵盖D…

作者头像 李华
网站建设 2026/9/14 12:48:09

多机器人协同编队控制:领航-追随法原理与Matlab实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华