Oracle AI:使用SQL来实现融合检索和整个RAG流程

RAG 都不用写程序了吗?

是的,Oracle 总是习惯把简单留给用户,目前已支持通过一条 SQL 就能实现基础的 RAG 需求。

本文就来深入剖析下这样的一条SQL,并展现下输出效果。

01|实现逻辑

这里先引用最近 AI 大会上的一张图,非常清晰地展现了实现逻辑:

从图片中可以看到,真的是就用这么一条SQL完成了RAG的整个流程。

02|技术拆解

虽然对于暴露给用户只有这么一条SQL,但实际上这条SQL里面调用了很多库内的函数,用户自然可以不关注,但作为技术从业者还是需要理解一下的。

① 用户问题向量化

将用户输入的问题向量化,这里直接调用 vector_embedding() 函数。

Embedding模型可以直接使用已经导入Oracle库内的onnx格式模型,比如我这里使用的是 BGE_BASE,SQL 就类似这样:

SQL 复制代码
select vector_embedding(BGE_BASE USING :question_text AS DATA)

② 执行向量搜索

vector_distance() 函数

查询对应的库内文本信息,依据库内文本信息的向量 和 用户问题的向量 比较结果,选TOP N的记录出来。

实践动手时就会发现,图中有个细节是不对的,估计是工作人员的笔误。

具体在 vector_distance() 函数里面多写了 SELECT,实际应该去掉,正确SQL类似如下:

SQL 复制代码
select content from t_history
    order by vector_distance(v, vector_embedding(BGE_BASE USING :question_text AS DATA))
    FETCH APPROX FIRST 5 ROWS ONLY

注:

  • 笔者这里是Oracle 23.7的测试环境,以笔者这个版本的实际测试的结果为准
  • 本文所有测试都改成笔者实际测试使用的一张表t_history

③ 组合LLM提示词

将自定义的提示词 + 用户的问题 + TOP N的记录作为上下文 组合成整体的LLM提示词。

SQL 复制代码
WITH TOP5 AS (select content from t_history where type = 'English'
    order by vector_distance(v, vector_embedding(BGE_BASE USING :question_text AS DATA))
    FETCH APPROX FIRST 5 ROWS ONLY),
LLM_PROMPT AS (
    SELECT (
        'Answer this question using the following context,' || CHR(10) || CHR(10) ||
        'QUESTION: ' || :question_text || CHR(10) || CHR(10) ||
        'CONTEXT: ' || CHR(10) || CHR(10) ||
        LISTAGG(content, CHR(10))
    ) AS prompt_text
    FROM TOP5
)

注:

  • 这里使用 || 巧妙的拼接了所有需要的内容
  • 使用 LISTAGG(content, CHR(10)) 函数将多行 content 数据合并成单个字符串
  • 谓词条件 type = 'English' 代表只关注 t_history 表中这个类型相关的内容

④ 获得LLM回复结果

最终调用 dbms_vector_chain.utl_to_generate_text() 获取LLM的最终回答。

理想情况下,只需要在上一步的SQL基础上,再加一段:

SQL 复制代码
select dbms_vector_chain.utl_to_generate_text(prompt_text, json(:LLM_paras)) as answer
from LLM_PROMPT;

不过研究发现,这里的 dbms_vector_chain 是一个包,utl_to_generate_text 是包中的一个函数,遗憾的是目前还不能支持国内模型API直接调用。

03|照猫画虎

理解了上面的技术,我们只需要解决一个国内模型API的调用问题,就可以解决很多国内的RAG需求了。

所以这里先尝试自定义一个函数来实现:CHAT_LLM(),功能很简单就是实现调用deepseek官方的api来交互。

下面我们就模拟一个用户需求:

首先,用户已经通过系统记录了日常工作、学习内容;

现在要求实现以下需求:

  • 支持用户输入自然语言描述问题
  • 我们根据问题向量检索到最相关的前5条记录内容,并支持过滤指定分类
  • 程序自动构造组合的提示词
  • 用最终的提示词请求LLM获取最终结果

本质还是直接模仿开头的那张片子来具体实现,只需要:

最终SQL如下:

SQL 复制代码
WITH TOP5 AS (select content from t_history where type = 'English'
    order by vector_distance(v, vector_embedding(BGE_BASE USING :question_text AS DATA))
    FETCH APPROX FIRST 5 ROWS ONLY),
LLM_PROMPT AS (
    SELECT (
        'Answer this question using the following context,' || CHR(10) || CHR(10) ||
        'QUESTION: ' || :question_text || CHR(10) || CHR(10) ||
        'CONTEXT: ' || CHR(10) || CHR(10) ||
        LISTAGG(content, CHR(10))
    ) AS prompt_text
    FROM TOP5
)
select CHAT_LLM(prompt_text) as Answer from LLM_PROMPT;

可以先在SQL命令行下测试效果:

sql 复制代码
-- 首先定义变量
VARIABLE question_text VARCHAR2(100);

-- 给变量赋值
BEGIN
  :question_text := '总结有关日常对话的英文对话';
END;
/

-- 完整的显示配置(新增SET ESCAPE OFF)
SET ESCAPE OFF
SET LINESIZE 32767
SET PAGESIZE 0

04|最终效果

因为TOP5格式还有点显示问题在调试ing,所以这里先用TOP1的内容输出效果展示下:

实话讲思路虽然很简单,但是自定义的函数对模型返回的格式处理还是相当头疼,即便有AI辅助也是被折腾的焦头烂额。

关于自定义的CHAT_LLM函数内容本文就先不贴了,因为调试过程中发现功能实现简单,但是细节处理还是需要太多考量的,建议等官方函数支持国内LLM,或者未来测试相对稳定了笔者再跟大家分享后续吧。

相关推荐
奇牙coding1233 小时前
gpt-5.6-luna 频繁 429 但 gpt-5.5 正常怎么办?不是配额问题,是 luna 独立的并发 session 限速桶
gpt·ai
安逸sgr3 小时前
AI 应用怎么评测?离线评测、人工评估和线上反馈如何结合?
人工智能·ai·大模型·agent·智能体
DS随心转插件4 小时前
Grok生成的html怎么导出——AI导出鸭:大模型结构化输出的“最后一公里”工程化解构
前端·人工智能·ai·html·豆包·deepseek·ai导出鸭
GHL2842710904 小时前
Skill学习
学习·ai
TechEdu2026065 小时前
[人工智能]Claude、GPT、Gemini、Copilot与Llama:概念、架构、应用与评估
人工智能·ai·llm
长谷深风1115 小时前
为什么你的 Tool 总被模型选错?
java·大数据·ai·llm·ai agent·工具设计·agent设计
Patrick在香港5 小时前
Claude Agent 进阶:4 种工具调用编排模式,让 0820 那 13 个 endpoint 并行起来
python·ai·ai编程
MicrosoftReactor6 小时前
技术速递|GitHub Copilot App 入门指南:管理你的工作
ai·github·copilot·agent
码士集团小青6 小时前
细拆DeepSeek Harness设计思路以及未来定位
ai
深念Y6 小时前
为什么选 MiniClaude:一个精简开源替代方案的选型过程
ai·开源·开源软件·agent·claude·workflow·claudecode