使用外部数据源构建Data-Agent

更新时间:
复制为 MD 格式

PolarDB for AI支持将外部数据源接入Data-Agent。无论您的业务数据存储在外部数据库(如PostgreSQL、Hive、Elasticsearch)中,还是希望在不实际创建表的前提下,Data-Agent均能够帮助您快速实现基于大语言模型的自然语言查询。PolarDB for AI通过预先定义数据结构(Schema),为大模型构建一个知识库,使其能将自然语言问题(例如“查询订单最多的客户”)转换为对应数据源的查询语句(SQL/DSL),从而实现对外部数据的分析与访问。

工作原理

PolarDB for AI将外部数据源的元数据(如表结构、列注释、示例值等)存储在特定表中。然后,通过内置模型将文本元数据转换为向量,并存入一个可供检索的索引表schema_info_index中。

当发起自然语言查询时,自然语言到SQL语言转义(基于大语言模型的NL2SQL)功能执行以下操作:

  1. 将自然语言问题转换为向量。

  2. schema_index表中进行向量相似度搜索,找到与问题相关的表和列。

  3. 结合检索到的元数据信息,生成可执行的SQLDSL查询语句。

适用范围

开始前,请确保已完成以下准备:

  • 引擎:PostgreSQL 16(内核小版本2.0.16.10.11.0及以上)。

  • 节点:增加AI节点,并设置AI节点的连接数据库账号添加与管理AI节点

    说明
    • 若您在购买集群时已添加AI节点,则可以直接为AI节点设置连接数据库的账号。

    • AI节点的连接数据库账号需具有读写权限,以确保能够顺利读取和写入目标数据库。

  • 访问地址:使用集群地址连接PolarDB集群。

准备工作

  1. 使用高权限账号登录集群。

  2. 获取节点Token。

    请前往PolarDB控制台,目标集群详情页中数据库节点区域,找到AI节点,并单击查看记录节点Tokenimage

  3. 创建polar_ai扩展并配置节点Token。

    在数据库中执行以下命令,创建功能扩展并设置访问大模型服务所需的密钥。

    重要

    请确认您已为AI节点设置了连接数据库账号

    -- 创建扩展
    CREATE EXTENSION polar_ai;
    
    -- 设置您的密钥
    SELECT polar_ai._ai_nl2sql_alter_token('sk-xxx');
  4. 创建元数据表schema_info。

    此表用于记录外部数据源的表名、列名、注释、数据类型等信息。

    CREATE TABLE IF NOT EXISTS public.schema_info (
        id SERIAL PRIMARY KEY,
        table_name VARCHAR(255) NOT NULL,
        table_comment TEXT,
        column_name VARCHAR(255) NOT NULL,
        column_comment TEXT,
        data_type VARCHAR(255) NOT NULL,
        sample_values TEXT,
        is_primary BOOLEAN DEFAULT FALSE,
        is_foreign BOOLEAN DEFAULT FALSE,
        ext TEXT,
        db_type VARCHAR(128)
    );
    
    COMMENT ON TABLE schema_info IS '数据库元数据信息表';
    COMMENT ON COLUMN schema_info.id IS '自增主键';
    COMMENT ON COLUMN schema_info.table_name IS '表名';
    COMMENT ON COLUMN schema_info.table_comment IS '表注释,对NL2SQL准确性至关重要';
    COMMENT ON COLUMN schema_info.column_name IS '列名';
    COMMENT ON COLUMN schema_info.column_comment IS '列注释,对NL2SQL准确性至关重要';
    COMMENT ON COLUMN schema_info.data_type IS '列数据类型';
    COMMENT ON COLUMN schema_info.sample_values IS '示例值,用英文逗号分隔';
    COMMENT ON COLUMN schema_info.is_primary IS '是否主键 (true/false)';
    COMMENT ON COLUMN schema_info.is_foreign IS '是否外键 (true/false)';
    COMMENT ON COLUMN schema_info.ext IS '外键关联信息,格式:数据库名.表名.列名';
    COMMENT ON COLUMN schema_info.db_type IS '关系型数据库语言类型(如 MySQL, PostgreSQL, StarRocks, Oracle等)';
  5. 准备并插入元数据

    按照以下格式要求,将元数据插入schema_info表。

    • db_type:指明源数据库的类型,如MySQLPostgreSQL等。同一逻辑库下的所有表,其db_type必须一致。

    • sample_values:提供示例值,多个值之间使用英文逗号(,)分隔。为保证效果,字段总长度不应超过100个字符。

    • is_foreign:是否为外键。值为1时,表示该列为外键。

    • ext:当is_foreign1时,此列需填写外键关联信息。格式为:<database_name>.<table_name>.<column_name>

    示例: 为customersorders两张表插入元数据。

    -- 插入 customers 表的元数据
    INSERT INTO schema_info (table_name, table_comment, column_name, column_comment, data_type, sample_values, is_primary, is_foreign, ext, db_type) VALUES
    ('customers', '客户信息表', 'id', '客户唯一标识', 'INT', '1,2,3', true, false, NULL, 'MySQL'),
    ('customers', '客户信息表', 'name', '客户姓名', 'VARCHAR(100)', '张三,李四,王五', false, false, NULL, 'MySQL'),
    ('customers', '客户信息表', 'email', '客户邮箱', 'VARCHAR(100) UNIQUE', 'zhangsan@example.com,lisi@example.com', false, false, NULL, 'MySQL');
    
    -- 插入 orders 表的元数据
    INSERT INTO schema_info (table_name, table_comment, column_name, column_comment, data_type, sample_values, is_primary, is_foreign, ext, db_type) VALUES
    ('orders', '订单信息表', 'order_id', '订单唯一标识', 'INT', '1001,1005,1003', true, false, NULL, 'MySQL'),
    ('orders', '订单信息表', 'order_date', '订单日期', 'DATE', '2023-01-01,2023-05-06', false, false, NULL, 'MySQL'),
    ('orders', '订单信息表', 'customer_id', '关联客户ID', 'INT', '1,2,3', false, true, 'dbname.customers.id', 'MySQL'),
    ('orders', '订单信息表', 'total_amount', '订单总金额', 'DECIMAL(10,2)', '99.99,101.81,250.00', false, false, NULL, 'MySQL');
  6. 授权业务表权限给AI节点的数据库账号。

    例如,若您为AI节点配置的数据库连接账号为polarai_user,则需将schema_info表的权限授予polarai_user

    说明

    在应用于业务环境时,请确保所设置的AI节点数据库账号具备相关业务表的权限。

    -- 授权
    GRANT ALL PRIVILEGES ON TABLE public."schema_info" TO polarai_user;

构建检索索引

基于schema_info表中的元数据,创建一个可供NL2SQL检索的索引。

语法说明

text ai_BuildSchemaIndex(text name, jsonb text2vecOption default '{"mode": "async", "resource": "schema"}');
  • name:您为索引指定的名称,后续查询时会用到。

  • text2vecOption:一个 JSON 字符串,包含以下参数:

    • mode:数据写入模式。默认为async,表示异步执行。

    • resource:资源类型,对何种信息进行向量化。此处固定为schema_info

    • to_sample:是否对列值进行采样。在列数较少(如小于15)的表中,采样有助于提高生成SQL的质量,但会增加索引构建时间。0(默认):不采样。1:进行采样。

示例

  • 执行以下命令,为schema_info表创建一个名为schema_info_index的表结构索引。此操作会采集表的结构、注释等信息并进行向量化,为大模型提供上下文。

    SELECT polar_ai.ai_BuildSchemaIndex('schema_info_index', '{"mode":"async", "resource":"schema_info", "to_sample":1}');
  • 该命令会返回一个任务ID(如bce632ea-97e9-11ee-bdd2-492f4dfe0918)。您可以通过以下命令查询任务状态,显示为finish时,表示索引构建完成。

    SELECT polar_ai.ai_ShowTask('<your_task_id>');

使用Data-Agent进行查询

索引构建完成后,即可通过自然语言到SQL语言转义(基于大语言模型的NL2SQL)功能,使用自然语言进行数据查询。

-- 查询拥有最多订单的前10位客户
SELECT polar_ai.ai_nl2sql('最多订单的10位客户', 'schema_info_index');

函数将返回一个由AI生成的、符合您问题意图的SQL语句。对于以上示例,预期返回类似如下的SQL:

SELECT customer_id, COUNT(*) AS order_count FROM orders GROUP BY customer_id ORDER BY order_count DESC LIMIT 10;

常见问题

验证任务状态(ai_ShowTask)结果显示fail应如何处理?

任务失败通常由元数据格式错误或权限问题导致。检查以下项目:

  1. ext字段的JSON格式是否正确,以及db_type是否一致?

  2. 检查执行ai_BuildSchemaIndex的用户是否具有源表schema_info的读取权限目标表schema_info_index的写入权限。

NL2SQL的转换结果不准确,如何优化?

结果的准确性依赖元数据质量。可尝试以下优化方法:

  1. 提供有效注释:在table_commentcolumn_comment中描述表和列的业务含义、枚举值说明等。

  2. 提供示例值:在sample_values中提供有代表性的数据,帮助模型理解列内容的格式和范围。

  3. 明确外键关系:在schema_info模式中正确设置is_foreignext字段,此操作对多表关联查询至关重要。