APEX实战第5篇:利用APEX程序直观体验向量近似检索能力

在圈内朋友看来,Oracle 数据库的 多模能力 已经不是什么新鲜话题。它不仅在关系型数据管理方面独树一帜,还能够在同一个数据库引擎中,支持几乎所有主流的数据模型 ------ 从 JSON、XML、时序、空间,到图数据、区块链,再到如今最火的向量数据与 AI。

利用 Oracle APEX,可以更简单、高效地展示数据库的多模能力。本文将通过一个 简明示例,演示如何使用 APEX 程序 直观地体验向量近似检索(Approximate Nearest Neighbor, ANN) 的能力,从而让多模数据的操作与查询可视化、易上手。

APEX实现功能:文本内容的近似最近邻检索(ANN) 功能。

  • 1.库内Embedding模型准备
  • 2.APEX简明示例
  • 3.其他细节信息参考

1.库内Embedding模型准备

我们知道,Oracle 23ai数据库原生支持向量数据类型的存储,可以支持直接在任意数据库表对象上增加一个或多个vector数据类型的列,专门用于存储向量数据格式。

具体如何存储向量化的数据呢?

  • 首先我们需要一个Embedding模型,可以对指定的内容向量化,然后将向量化后的结果直接存储到vector数据类型的字段中;

如果还没有Embedding模型可用,不必折腾,Oracle本身支持库内加载onnx模型,具体可以参考之前文章《曾经风光无限的 Oracle DBA 已经落伍了吗?》中提到过的方法,唯一需要注意,当时是直接使用了官方文档介绍的all_MiniLM_L12_v2.onnx模型,这里笔者实际测试发现其对中文的匹配效果并不理想,所以换用另一个Embedding模型bge-base-zh-v1.5.onnx,为了方便大家动手操作,这里贴出导入此模型的关键步骤:

SQL 复制代码
--删除模型(可选)
exec DBMS_VECTOR.DROP_ONNX_MODEL(model_name => 'BGE_BASE', force => true);

--加载导入模型:
BEGIN
   DBMS_VECTOR.LOAD_ONNX_MODEL(
        directory => 'DM_DUMP',
                file_name => 'bge-base-zh-v1.5.onnx',
        model_name => 'BGE_BASE',
        metadata => JSON('{"function" : "embedding", "embeddingOutput" : "embedding", "input": {"input": ["DATA"]}}'));
END;
/

--查询导入的EMBEDDING模型:
select model_name, algorithm, mining_function from user_mining_models where model_name='BGE_BASE';

--测试EMBEDDING模型可用,可以正常返回向量化结果
SELECT VECTOR_EMBEDDING(BGE_BASE USING 'Hi, Alfred' as DATA) AS embedding;

2.APEX简明示例

随便找一张表,对其中任意一个想做近似检索的文本列字段,针对该表增加一个向量列。然后使用上一步配置好的库内Embedding模型进行向量化处理。

我这里就以之前的Demo为基础,针对t_history表中 content列的内容进行向量化,结果存储到表中列v中,数据类型是vector。

关键步骤:

SQL 复制代码
--1.向量字段存储向量化后的内容,只是测试下模型可用
UPDATE t_history
SET v = VECTOR_EMBEDDING(BGE_BASE USING content AS DATA)
where username = 'test';

--2.分批处理更新,向量字段存储向量化后的内容,可配置到APEX页面中前台调用
DECLARE
  CURSOR c_history IS
    SELECT rowid AS rid, content
    FROM t_history
    WHERE content is not null 
    and (v IS NULL or v_needs_update=1);  -- 只处理未向量化和需要更新向量化的行
BEGIN
  FOR r IN c_history LOOP
    UPDATE t_history
    SET v = VECTOR_EMBEDDING(BGE_BASE USING r.content AS DATA)
    WHERE rowid = r.rid;
  END LOOP;
  COMMIT;
END;
/

--3.APEX可以通过报表直观展现近似检索功能
SELECT type, week, day, history_date, content
FROM t_history
where username = :APP_USER
ORDER BY VECTOR_DISTANCE(v, VECTOR_EMBEDDING(BGE_BASE USING :P7_SEARCH_TEXT AS DATA))
FETCH APPROX FIRST 5 ROWS ONLY;

APEX近似检索效果:

这里首先我在表中的content列中,初始化了一些测试数据,比如针对爱情、开发等主题,模拟用户日常操作,录入一些与主题相关的内容,不知道该具体输入啥内容的同学,可以直接让LLM帮你生成哈。

然后,我们到APEX页面上进行检索测试。

输入爱情,点击搜索,就可以从该用户历史记录过的所有内容中,检索到它认为向量近似的前5个结果列出来,可以看到结果都与爱情相关,但未必都包含爱情关键字,比如第5条结果描述的单恋场景:

同样,如果输入开发,点击搜索,结果就是这样,很多结果并没有开发关键字,但表述其实都跟软件开发这个主题密不可分:

这也是向量近似检索的魅力所在,历史传统数据库无论是进行精确或模糊搜索,都只能基于关键字匹配,但如今,向量的近似检索使其可以直接依据语义进行搜索。

3.其他细节信息参考

前面已经展示了实际效果,达成了目标,本节主要补充一些信息,方便读者更好地理解实现细节。

我这里在对t_history表处理的过程中,针对向量列的判断里,有写到 (v IS NULL or v_needs_update=1); -- 只处理未向量化和需要更新向量化的行,还特别注释说明了下,这是因为最初我只处理了未向量化的内容,但是我实际在录入文本内容时,存在更新原内容的需求。而原内容因为已经做过向量化,向量部分不会更新,所以搜索会遇到问题,因此需要fix这个更新场景的bug,增加一列,并加入到对应的逻辑判断中:

SQL 复制代码
--fix更新bug
ALTER TABLE t_history ADD v_needs_update NUMBER(1) DEFAULT 0;

这样,当发现有录入或更新内容,都可以做到能提示最终用户,需要处理新内容。

比如用户想近似检索人工智能相关的内容,下面红色数字就表示,表中数据存在更新内容,但还未向量化的情况,检索结果可能存在不准确的情况,这个例子就是如此,除了第一条记录,其他和人工智能其实关系并不大:

此时,用户可以手工点击向量化,将最新更新的一些内容向量化,再次检索,发现除了第一条结果,其他已经不一样了,说明新的内容(这里可以通过History Date列快速识别)确实存在一些比历史数据更匹配人工智能主题的结果:

也许看到这里,有读者会有疑问,为何不直接设计,在更新内容时直接就向量化呢?

嗯,其实也不是不可以,看应用要求,只是我这里这样设计更符合演示要求而已。同时也为了能让大家直观看到,近似检索,实际上检索结果就是distance的排名,如果要求展示的记录数,本身数据集中就没有足够数量匹配的,也会检索出来一些不太相干的内容。

此外,如果数据量较大,基于性能考量,建议创建HNSW(Hierarchical Navigable Small World)类型的向量索引,同时注意Top-K两种写法差异:

SQL 复制代码
--4.创建HNSW索引
create vector index t_history_hnsw_idx on t_history(v)
organization inmemory neighbor graph
distance COSINE
with target accuracy 95;

--精确 Top-K
SELECT type, week, day, history_date, content
FROM t_history
ORDER BY VECTOR_DISTANCE(v, VECTOR_EMBEDDING(BGE_BASE USING '爱情' AS DATA))
FETCH FIRST 5 ROWS ONLY;

--近似 Top-K,增加了APPROX关键字:
SELECT type, week, day, history_date, content
FROM t_history
ORDER BY VECTOR_DISTANCE(v, VECTOR_EMBEDDING(BGE_BASE USING '爱情' AS DATA))
FETCH APPROX FIRST 5 ROWS ONLY;

至此,我们就利用APEX程序直观体验了向量近似检索能力。

相关推荐
一枝小雨23 天前
【C++】Vector完全指南:动态数组高效使用
开发语言·c++·笔记·vector·学习笔记·std库
深度混淆2 个月前
C#,List<T> 与 Vector<T>
开发语言·c#·vector·list·simd
AlfredZhao4 个月前
曾经风光无限的 Oracle DBA 已经落伍了吗?
ai·vector·embedding·onnx·hnsw·ivf
景天科技苑5 个月前
【Rust通用集合类型】Rust向量Vector、String、HashMap原理解析与应用实战
开发语言·后端·rust·vector·hashmap·string·rust通用集合类型
无心水5 个月前
【Java面试笔记:基础】8.对比Vector、ArrayList、LinkedList有何区别?
java·笔记·面试·vector·arraylist·linkedlist
AlfredZhao6 个月前
利用 APEX 打造 Oracle 23ai 智能开发平台
apex·23ai·vectory·vectorizer
愚润求学6 个月前
【C++】vector常用方法总结
开发语言·c++·vector
AredRabbit6 个月前
vector<int> 的用法
c++·算法·vector
Y1nhl6 个月前
搜广推校招面经六十一
人工智能·pytorch·python·机器学习·推荐算法·ann·搜索算法