# RAGFlow 搭建数据查询 AI 应用

# 简介

在大数据飞速发展的时代,现在企业基本都会向 AI 靠近,传统的系统和用户交互都是让用户在系统上自己操作,要查询什么内容通过对话的方式就能获取到结果,而不需要点这个菜单又去点哪个菜单,还要选条件在点查询,本篇文章就实现,怎么将自然语言转成 SQl 在去查询实际的数据。之前有介绍使用 dify 来实现,但是 dify 的知识库检索并不理想,所以我们用 RAGFlow

# 开始

首先我们需要 RAGFlow 环境,这里安装就不再赘述了。

我们需要准备一个专门用于生成 Text2SQL 提示词的知识库,该知识库包含各类自然语言到 SQL 的样例数据。当用户向 RAGFlow 发起一个 Text2SQL 提问时,先到该知识库中进行搜索,找到相似结果后拼接成生成 SQL 的提示词,再把该提示词发给大模型,让大模型生成最终的 SQL。该 SQL 可以直接用来查询数据库,如果返回结果出现错误,证明产生的 SQL 不对,那么需要继续调用大模型让它产生一个正确的 SQL 直到错误次数超过上限。

RAGFlow 提供了对应的 agent 例子, 下面开始具体步骤

# 知识库

需要将我们的业务 表结构详细的字段说明 还有一些 sql的示例 上传到知识库,当用户提问提就会检索出来,让大模型理解在给出进行生成 sql 语句,如图创建 三个 知识库:

三资 Description:

解析的时候,分段标识符为 "#"

### 地区表(dist)
地区表用于存储地区的信息。以下是该表中每个字段的含义:
- `id`: 这是一个整数类型的自增字段。
- `distno`: 字符串类型,用于存储地区的编号。地区编号,1位长度表示省级,2位长度表示市级,4位长度表示区县级,6位长度表示镇街级,9位长度表示村级。
- `distname`: 字符串类型,用于存储地区的名称。
- `parentDistNo`: 字符串类型,用于存储上级地区编号。可以和本身关联,关联上一级的地区。
- `parentDistName`: 字符串类型,用于存储上级地区名称。
### 资产表(ht_land)
资产表用于存储土地资产的信息。以下是该表中每个字段的含义:
- `id`: 这是一个整数类型的自增字段。
- `title`: 字符串类型,用于存储资产的标题。
- `distNo`: 字符串类型,用于存储地区编号,这个字段可以和地区表关联,以实现是哪个地区的资产。
- `distName`: 字符串类型,用于存储地区的名称。
- `landNo`: 字符串类型,用于存储资产的编号。
- `landName`: 字符串类型,用于存储资产的名称。
- `area`: 小数类型,用于存储资产所占面积。
- `unit`: 字符串类型,用于存储资产的面积单位,可能的值有:亩、平方米等。
这些表的设计是相互关联的,例如,资产表中的`distNo`字段将与地区关联起来,说明是哪个地区的资产。

三资 DDL

解析的时候,分段标识符为 ";"

CREATE TABLE `dist` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `distno` VARCHAR(32) NOT NULL,
  `distname` VARCHAR(255) NOT NULL,
  `parentDistNo` VARCHAR(32),
  `parentDistName` VARCHAR(255)
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_distno` (`distno`)
);
CREATE TABLE `ht_land` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(32),
  `distNo` VARCHAR(32) NOT NULL,
  `distName` VARCHAR(32),
  `landNo` VARCHAR(255) NOT NULL,
  `landName` VARCHAR(255),
  `area` decimal(18,4),
  `unit` VARCHAR(255)
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_landNo` (`landNo`),
  FOREIGN KEY (`distno`) REFERENCES `dist` (`distno`)
);

sql 示列:

解析方式选 Q&A

我有一个大表格,包含两个键(id,date),我希望每天的账户id都从1开始重新计数。\tSELECT dense_rank() OVER (PARTITION BY date\n                          ORDER BY id) as new_id,\n       date\nFROM   your_table;

测试检索效果如图:

# 工作流

我们可以直接在添加的时候选择对应的模板 Text To SQL

大致流程:开始 -> 知识检索 -> 大模型解析返回 sql -> 回复用户

流程图如下:

这里生成 SQL 的提示词是:



##用户提供一个问题,您提供SQL。您将仅以SQL代码回应,不做任何解释。



##硬性要求

1.严格使用检索到的表字段

2.确保SQLSERVER语法兼容

3.仅输出最终结果sql语句的txt文本,不要加任何信息

4.禁止中间过程输出

5.返回纯SQL文本内容, 不要代码块

6.表名称要去掉特殊符号





##关键步骤:

1、对用户输入的内容进行识别和判断,如果内容涉及政治、时事、社会问题以及违背道德和法律法规的情形,一律输出:”您提出的问题超出我应当回答的范围,请询问与公司业务相关的问题,否则我无法作出回答“

2、去除SQL语句中多余的注释、换行符等无用信息,输出一个纯净的、可直接执行的SQL语句

3、用户提到的“村集体”就是地区,如果没有说哪个村集体,那么就是所有地区



##编写SQL时的注意事项:

1.务必根据上下文提供的数据表结构描述来编写SQL语句,确保仅使用数据表结构描述中提到的表名和字段名,并参考对字段的解

2.确保SQL兼容SQL Server 2014

3.只用简体中文

4.只输出一个完整SQL语句,无注释,确保可直接执行并获得预期的结果

5.对于字符串和长文本类型的字段,除非用户有特别说明,否则都用LKE操作,而不是等于操作,例如:WHERE distno LIKEN'%关键词%',而不是WHERE distno='关键词'

6.除法处理:参考以下模板以避免错误:

CASE WHEN 「除数] = 0 THEN 0

ELSE CAST([被除数] AS FLOAT)/[除数]

END AS[结果列名]




##您可以使用以下DDL语句作为可能可用表的参考。使用对过去问题的回答来指导您:{Retrieval:TrueCornersJam}。

##您可以使用以下文档作为可能可用表的参考。使用对过去问题的回答来指导您:{Retrieval:LazyChefsWatch}。

##您可以使用以下SQL语句作为可能可用表的参考。使用对过去问题的回答来指导您:{Retrieval:EasyDryersShop}。

# dify 引入 RAGFlow 外部知识库

由于 RAGFlow 的工作流不是很好用,所以我们可以使用 dify 来外部调用 RagFlow 的知识库,具体操作如下:

  1. 首先开启 RAGFlow 的 api

  2. dify 中知识库中添加外部知识库

    API Key 填写第一步申请到的

  3. 添加到 dify 中

    ragflow-1-7