一、场景背景与架构设计
-
场景需求:
企业内部存储了大量 PDF/Word 文档(产品手册、制度文件、培训资料),员工需通过自然语言提问,快速找到语义相似的文档内容,替代传统的关键词检索(精准度低、无法理解语义)。 -
架构设计:
采用 Oracle 23ai 原生向量引擎作为核心,整体流程简单清晰:
文档预处理:将 PDF/Word 文档拆分为文本块(解决长文本语义割裂问题);
向量生成:在 Oracle 数据库内调用VECTOR_EMBEDDING函数,生成文本块的嵌入向量;
索引创建:为向量列创建 HNSW 索引(适配文本检索的高召回率需求);
语义检索:用户输入自然语言问题,生成向量后,在数据库内执行相似检索;
结果展示:将检索到的文本块与原文档关联,返回给用户查看。二、实战步骤:从 0 到 1 搭建语义检索系统
-
步骤 1:环境准备与权限配置
确保 Oracle 23ai 数据库已安装并启用原生向量引擎(23ai 默认开启,无需额外配置);
创建专用 schema 与用户,授予必要权限:-- 创建用户 CREATE USER vector_user IDENTIFIED BY Vector@123456; -- 授予连接、创建表、索引权限 GRANT CONNECT, RESOURCE, CREATE TABLE, CREATE INDEX TO vector_user; -- 授予向量操作相关权限 GRANT EXECUTE ON SYS.vector_embedding TO vector_user; GRANT EXECUTE ON SYS.vector_chunks TO vector_user; -
步骤 2:创建数据表,存储文档与向量数据
我们需要三张表:文档基础信息表(存储原文档元数据)、文本块表(存储拆分后的文本片段)、向量映射表(存储文本块对应的嵌入向量),也可合并为一张表,这里拆分是为了提升查询效率。-- 1. 文档基础信息表 CREATE TABLE doc_archives ( doc_id NUMBER PRIMARY KEY, doc_name VARCHAR2(200) NOT NULL, doc_type VARCHAR2(50) NOT NULL, -- PDF/WORD/MD upload_time DATE DEFAULT SYSDATE );-- 2. 文本块表 CREATE TABLE doc_chunks ( chunk_id NUMBER PRIMARY KEY, doc_id NUMBER REFERENCES doc_archives(doc_id), chunk_content CLOB NOT NULL, -- 文本片段内容 chunk_index NUMBER NOT NULL, -- 文本块在原文档中的序号 -- 1536维文本嵌入向量(适配主流开源/商用文本嵌入模型) chunk_emb VECTOR(1536) FLOAT32 );-- 创建文档与文本块的关联索引 CREATE INDEX idx_chunks_doc_id ON doc_chunks(doc_id); -
步骤 3:文档预处理与向量生成(核心:数据库内生成向量)
传统做法是在应用层拆分文档、调用外部 API 生成向量,再导入数据库。而 Oracle 23ai 原生向量引擎提供了 VECTOR_CHUNKS(文本分块)与VECTOR_EMBEDDING(向量生成) 两大函数,直接在数据库内完成全流程,无需外部依赖。3.1 文本分块:用VECTOR_CHUNKS拆分长文本
VECTOR_CHUNKS函数可将长文本按指定长度、重叠度拆分,避免单文本块语义不完整。
-- 示例:将ID为1的PDF文档拆分为500字/块,重叠50字 DECLARE v_doc_content CLOB; BEGIN -- 模拟从原文档获取内容(实际可从文件存储读取,存入CLOB字段) v_doc_content := '企业数字化转型是指企业利用云计算、大数据、人工智能等新一代信息技术,对业务流程、组织架构、商业模式进行全面重构……'; -- 长文档内容 -- 调用VECTOR_CHUNKS拆分文本,插入文本块表 INSERT INTO doc_chunks (doc_id, chunk_content, chunk_index) SELECT 1 AS doc_id, chunk_content, chunk_index FROM TABLE(VECTOR_CHUNKS(v_doc_content, 500, 50)); -- 500字/块,重叠50字 COMMIT; END; /3.2 向量生成:用VECTOR_EMBEDDING生成文本嵌入向量
VECTOR_EMBEDDING支持调用内置 AI 模型或 外部 AI 服务(如 Ollama、OpenAI API) 生成向量,这里以调用开源文本嵌入模型all-MiniLM-L6-v2(本地部署)为例。
-- 为已拆分的文本块生成嵌入向量 DECLARE CURSOR c_chunks IS SELECT chunk_id, chunk_content FROM doc_chunks WHERE doc_id = 1; BEGIN FOR r IN c_chunks LOOP -- 调用VECTOR_EMBEDDING生成1536维向量,存入chunk_emb列 UPDATE doc_chunks SET chunk_emb = VECTOR_EMBEDDING( 'all-MiniLM-L6-v2', -- 嵌入模型名称 r.chunk_content, -- 文本块内容 VECTOR_OUTPUT => 'FLOAT32' -- 输出精度 ) WHERE chunk_id = r.chunk_id; END LOOP; COMMIT; END; /步骤 4:创建 HNSW 索引,提升检索性能
文本语义检索对召回率要求高,因此选择 HNSW 索引:
-- 为文本块向量列创建HNSW索引,使用余弦距离(文本嵌入的标准相似度计算方式) CREATE INDEX idx_chunks_emb_hnsw ON doc_chunks USING VECTOR HNSW (chunk_emb VECTOR_COSINE_DISTANCE) WITH ( DIMENSIONS=1536, M=16, -- 每个节点的最大边数 EF_CONSTRUCTION=200 -- 索引构建候选集大小 );步骤 5:语义检索:自然语言转向量,执行相似查询
这是整个系统的核心环节:用户输入自然语言问题,先将问题生成向量,再与数据库中的文本块向量执行相似检索,返回 Top-N 个最相似的结果。
-- 示例:用户提问“企业数字化转型的核心步骤是什么?” DECLARE v_question VARCHAR2(1000) := '