资讯详情

资讯详情

INFORMATION DETAIL

技术分享:双模式融合的库内机器学习

2024-12-05 18:30:29

一、技术背景

随着大数据时代的到来,数据分析和机器学习技术在各行各业的应用日益广泛。作为数据存储和管理核心的数据库系统,需要与数据分析和机器学习技术紧密结合,以支持数据驱动的决策。换句话说,现代数据库系统需要将机器学习算法集成到数据库中,实现数据存储、管理和分析的一体化,从而提升数据分析能力,简化机器学习流程。

传统的数据分析流程通常包括数据抽取、转换、加载(ETL)和模型训练等步骤,这些步骤需要在不同系统之间进行数据迁移,效率低下且安全性难以保证。因此,目前数据分析所追求的目标是直接在数据存储位置进行分析,无需数据迁移,从而提高计算效率,增强数据安全性,并简化数据处理流程。

二、库内机器学习动机

机器学习算法集成到数据库内的兴起,主要受两方面因素的驱动:

一方面,提升数据分析能力是一个核心驱动力。在大数据时代背景下,数据的海量增长对分析效率提出了更高要求。传统的数据分析模式往往需要将数据从数据库中导出,再借助外部工具或平台进行分析,这一过程不仅耗时费力,还可能因数据迁移过程中的格式转换、丢失等问题而降低分析准确性。而将机器学习算法直接集成到数据库中,即所谓的“库内机器学习”,则能够彻底改变这一现状。它允许用户直接在数据存储的位置执行分析任务,无需繁琐的数据迁移步骤,从而显著提升了数据分析的效率和实时性。此外,库内机器学习还能利用数据库本身的优化技术和并行处理能力,进一步加速分析过程,使大规模数据集的处理变得更为轻松快捷。

另一方面,简化机器学习流程则是另一个至关重要的动机。机器学习技术虽然强大,但其复杂的模型和算法往往让非专业的数据分析师望而却步。传统的机器学习应用通常需要编写大量的代码,掌握复杂的编程语言和框架,这对于大多数业务分析师来说是一个不小的挑战。而通过SQL实现机器学习算法,则能够极大地降低这一门槛。SQL作为一种广泛使用的数据库查询语言,具有语法简洁、易于学习的特点。将机器学习功能融入SQL中,意味着数据分析师只需掌握基本的SQL语法,就能轻松调用机器学习模型进行预测、分类等任务,无需深入了解复杂的机器学习原理或编程技巧。这不仅简化了机器学习流程,还使得更多非专业的数据分析师能够利用机器学习技术提升工作效率,推动业务创新。

基于以上两方面因素,贝格迈思自主创新研发了分布式智能数据库AiSQL,其内置的BrightML模块无缝融合了机器学习和大模型技术框架,打造了库内高级分析和数据科学AI引擎,为企业提供开箱即用的AI能力,大幅降低了AI技术的应用门槛,方便数据工程师和数据库运维人员使用先进的AI技术。

接下来,我们将深入阐述BrightML中利用双模式融合技术实现的库内机器学习原理及其在实践中的应用。

三、双模式技术原理

双模式融合的库内机器学习技术旨在将机器学习功能集成到数据库中,实现数据分析能力的提升和机器学习流程的简化。该技术通过两种模式结合实现:

  • 模式1引入用户自定义函数(User-Defined Function, UDF);
  • 模式2将机器学习算法转换成SQL语句。

接下来,我们将详细介绍这两种模式。

1. 用户自定义函数模式

1.1 技术实现

用户自定义函数(UDF)是数据库管理系统提供的一种高级功能,它赋予了用户极大的灵活性,允许他们在数据库环境中创建并执行自定义的逻辑代码。这些自定义函数不仅能够执行基本的数学运算、字符串处理和数据转换等操作,还能够作为桥梁,将数据库与外部的高级计算资源和机器学习框架无缝连接起来。

在UDF框架下,用户不再受限于数据库内置的函数库,而是可以根据实际需求,编写并执行复杂的计算逻辑。这一特性使得UDF成为数据处理和分析领域中的一把利器,特别是在需要调用外部机器学习框架进行高级数据分析时,UDF的优势尤为明显。

通过UDF,用户可以轻松地在数据库中集成并调用诸如scikit-learn、Tensorflow、PyTorch、PaddlePaddle和MindSpore等流行的机器学习框架。这些框架各自拥有独特的优势和广泛的应用场景,如scikit-learn擅长于统计建模和数据分析,Tensorflow和PyTorch则以其强大的深度学习能力而著称,PaddlePaddle和MindSpore则分别在中国市场内拥有广泛的用户基础和良好的生态支持。

1.2 集成方式

UDF可以通过编程语言(如Python、R等)与数据库系统建立交互,进而实现对外部机器学习框架如scikit-learn、Tensorflow、PyTorch等的调用。这一机制为数据库与机器学习技术的深度融合提供了可能,使得数据科学家和开发人员能够在数据库环境中直接利用先进的机器学习算法进行数据处理和分析。

在调用机器学习框架的过程中,UDF首先通过编程语言的接口与数据库系统建立连接。这种连接可以是直接的(如通过数据库提供的API或扩展模块),也可以是间接的(如通过中间件或数据管道)。一旦连接建立,UDF就可以通过编程语言调用数据库中的数据和函数,执行必要的预处理和特征工程操作,为后续的机器学习模型训练或预测做好准备。

框架调用的过程不仅简化了机器学习模型在数据库中的应用流程,还使得模型能够直接作用于数据库中的数据,从而大大提升了数据处理的智能化水平和响应速度。此外,由于UDF支持多种编程语言和机器学习框架,用户可以根据自己的技术背景和项目需求,选择最适合的工具和框架来构建和部署机器学习模型,从而更加高效地实现数据处理和分析任务。

2. 机器学习算法SQL编码模式

2.1 技术实现

将机器学习算法转换成SQL语句,意味着用户可以直接在数据库中执行机器学习任务,无需编写复杂的代码或调用外部工具。这种模式的核心思想是将机器学习算法的数学公式和逻辑转换为数据库查询语言。这需要深入挖掘并利用SQL的强大功能和高度灵活性,对机器学习算法的核心组成部分进行重新构思与实现。

机器学习算法的基本元素包括变量、函数、条件和循环等。在SQL中,这些元素需要被重新定义并适应SQL的查询和数据处理范式。下面将以这些基本元素为例,进行其映射过程介绍。

  • 变量:在SQL中,变量通常通过SELECT语句中的列名或子查询来表示。对于机器学习中的变量,可以将其视为SQL表中的列,每一行代表一个数据点,每一列则代表一个变量(特征)。
  • 函数:SQL提供了丰富的内置函数,如聚合函数(包括SUM、AVG等)、字符串函数(包括CONCAT、SUBSTRING等)以及数学函数(包括ABS、SQRT等),这些都可以用来实现机器学习算法中的数学运算和数据处理。
  • 条件:在SQL中,条件语句主要通过WHERE子句、CASE表达式和IF函数来实现。这些条件语句允许我们根据数据的值来过滤记录、计算新值或执行不同的操作,这是实现机器学习算法中决策逻辑的关键。
  • 循环:虽然SQL是一种声明式语言,并不直接支持循环结构,但我们可以通过递归查询(如使用公共表表达式CTE)和窗口函数(包括ROW_NUMBER、RANK等)来模拟循环的行为。这些技术允许我们在SQL查询中处理复杂的数据迭代和累积操作。

通过将机器学习算法的基本元素映射到SQL的声明式语法中,我们可以利用SQL的强大数据处理能力和优化技术,来高效地实现和运行机器学习模型。这不仅为数据分析师和数据库管理员提供了更强大的工具,也促进了机器学习技术在数据库管理和数据分析领域的广泛应用。

2.2 性能优化

为了显著提升机器学习算法转换成的SQL查询效率,我们需要对SQL代码进行优化,确保其能够充分适应并利用数据库的内部架构特性。尤其是在列式存储和矢量化操作等数据库特性明显的环境中,这些特性对查询执行的效率有着重要的影响。只有精心设计和优化SQL代码,我们才能充分利用这些特性,从而大幅提高数据库的查询速度。下面将以列式存储和矢量化操作为例,介绍其对应的SQL代码优化策略。

2.2.1 列式存储优化

在列式存储中,数据是按照列而不是行来存储的。这意味着,如果查询只涉及数据表的一小部分列,那么数据库可以仅读取和处理这些特定的列,从而大大减少I/O操作和内存使用。为了优化SQL代码以适应列式存储,可以采取以下策略:

  • 精确选择列:在SELECT语句中仅指定所需的列,避免使用SELECT *来选择所有列。这不仅可以减少数据传输量,还可以提高缓存效率和减少不必要的计算。
  • 利用索引:在列式存储数据库中,为经常查询的列创建索引可以显著提高查询速度。索引允许数据库快速定位所需的数据,而无需扫描整个数据集。
  • 分区策略:根据查询模式将数据分区可以进一步优化查询性能。例如,可以按时间范围、地理位置或业务逻辑对数据进行分区,以便在查询时仅扫描相关的分区。
2.2.2 矢量化操作优化

矢量化操作是数据库处理大量数据的一种高效方式。它允许数据库在单个操作中处理多个数据项,而不是逐个处理它们。这通常通过利用现代处理器的单指令多数据(SIMD)指令集来实现。为了优化SQL代码以适应矢量化操作,可以采取以下措施:

  • 批量处理:尽可能使用批量操作而不是逐行操作。例如,使用INSERT INTO ... SELECT语句来批量插入数据,而不是使用循环逐行插入。
  • 避免逐行函数:在SQL查询中避免使用逐行计算的函数,如逐行聚合或逐行条件判断。相反,应使用内置的矢量化函数,这些函数可以在单个操作中处理整个数据集。

四、两种模式实践例子

接下来,我们将分别介绍两种模式的实践例子。

1. 用户自定义函数模式实践

我们将展示如何在数据库中创建UDF,在UDF中调用外部机器学习框架进行模型训练及预测。

1.1 创建UDF

首先,我们在数据库中创建一个UDF,该UDF将调用外部机器学习框架进行模型训练。以下是一个简单的Python UDF示例,它提供了一个调用机器学习算法进行模型训练的框架。

create or replace function aisql.train(project_name text, task text, relation_name text, x_column_names text[], y_column_names text[] default NULL, cat_columns integer[] default NULL, algorithm text default NULL, hyperparams text default '{}', search text default NULL, search_params text default '{}', search_args text default '{}', preprocess text default '{}')
returns table(project_id integer, model_name text, algorithm text) as $$
from aisql.ml_utils import table_train
-- 在table_train函数中调用外部机器学习框架,并调用algorithm映射到的机器学习算法建立模型并将模型入库
return table_train(plpy, project_name, task, relation_name, x_column_names, y_column_names, cat_columns, algorithm, hyperparams, search, search_params, search_args, preprocess)
$$ language 'plpython3u';

然后,我们在数据库中创建一个UDF,该UDF将调用外部机器学习框架进行模型预测。以下是一个简单的Python UDF示例,它提供了一个调用机器学习算法进行模型预测的框架。

create or replace function aisql.predict(project_name text, tuple_text text, label_column text default NULL)
returns text as $$
from aisql.ml_utils import table_predict
-- 在table_predict函数中调用外部机器学习框架应用project_name对应的库内模型来预测label_name列的值
-- label_name为None时使用库内模型在训练时使用的首个标签列进行预测
return table_predict(plpy, project_name, tuple_text, label_column)
$$ language 'plpython3u';

1.2 调用UDF

接下来,我们将展示如何调用这些UDF来训练和预测模型。以下是一个简单的SQL语句示例,它使用我们之前创建的UDF来训练和预测模型。

-- 训练模型(不设置algorithm,使用所有预定义好的机器学习算法建模)
-- 训练数据集aisql.iris的标签列值为字符串,需要预处理转成自然数
select aisql.train(project_name=>'iris.classification', task=>'classification', relation_name=>'aisql.iris', x_column_names=>'{a1,a2,a3,a4}'::text[], y_column_names=>'{class}'::text[], preprocess=>'{"class":{"encode":{}}}');
-- 预测模型(调用指定项目中在训练期间5-折交叉验证效果最好的库内模型来进行预测)
select aisql.predict(project_name=>'iris.classification', tuple_text=>'{"a1":5.1,"a2":3.5,"a3":1.4,"a4":0.2}');

2. 机器学习算法SQL编码模式实践

我们将通过举例对比UDF模式,展示如何使用纯SQL语句直接编写机器学习算法的模型训练及预测过程。下面先给出Python实现的感知器分类器算法,再给出UDF模式下调用感知器分类器算法的SQL代码,最后给出纯SQL实现的等价代码。

  • Python代码(perceptron.py)
import numpy as np

def softmax(XW):
    cols = XW.shape[1]
    e_x = np.exp(XW - np.repeat(np.amax(XW, axis=1)[:, np.newaxis], cols, axis=1))
    repeated_row_sums = np.repeat(np.sum(e_x, axis=1)[:, np.newaxis], cols, axis=1)
    return e_x / repeated_row_sums + 2.220446049250313e-16

def gradient(W, X, Y):
    sm = softmax(X.dot(W))
    return -np.dot(X.T, Y - sm) + W

def gradient_descent(X, Y, iterations, alpha):
    W = np.zeros((X.shape[1], Y.shape[1]))
    for i in range(iterations):
        g = gradient(W, X, Y)
        W = W - alpha * g
    return W

def predict(X, W):
    p = softmax(X.dot(W))
    return np.argmax(p, axis=1)
  • UDF模式下的SQL代码(假设aisql.iris表的标签列class已经转成{0,1,2}中的自然数)
-- 创建UDF
create or replace function experience_perceptron() as $$
import numpy as np
from perceptron import *
rows = plpy.execute("SELECT a1, a2, a3, a4, class FROM aisql.iris")
X = np.array([r[:-1] for r in rows])
y = np.array([r[-1] for r in rows], dtype=np.int64)
# add column of ones (for intercept)
X = np.column_stack((X, np.ones(X.shape[0])))
# one-hot encoding for classification
amount_classes = len(np.unique(y))
y_one_hot = np.eye(amount_classes)[y]
Y = y_one_hot
W = gradient_descent(X, Y, iterations=2000, alpha=0.001)
WT = W.T
for i in range(len(WT)):
    plpy.info(f"class weights {i}: {WT[i]}")
preds = predict(X, W)
accuracy = sum(preds == y) / float(len(y))
plpy.info(f"train accuracy: {accuracy}")
$$ language 'plpython3u';
-- 调用UDF
select experience_perceptron();
  • 纯SQL实现的等价代码(假设aisql.iris表的标签列class已经转成{0,1,2}中的自然数)
WITH RECURSIVE X(f1, f2, f3, f4, y) AS (
    SELECT a1, a2, a3, a4, class FROM aisql.iris
), iterations (iterations) AS (
    VALUES (CAST(2000 AS INTEGER))
), alpha (alpha) AS (
    VALUES (CAST(0.001 AS DOUBLE PRECISION))
), _X AS (
    SELECT *, ROW_NUMBER() OVER() AS row_id FROM (SELECT DISTINCT * FROM X) AS T
), log_reg_softmax(i, y, w1, w2, w3, w4, intercept) AS (
    VALUES
    (CAST(0 AS INTEGER), CAST(0 AS INTEGER), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION)),
    (CAST(0 AS INTEGER), CAST(1 AS INTEGER), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION)),
    (CAST(0 AS INTEGER), CAST(2 AS INTEGER), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION), CAST(0 AS DOUBLE PRECISION))
    UNION ALL
    SELECT i, y, w1, w2, w3, w4, intercept FROM (
        WITH log_reg_softmax_mock AS (
            SELECT * FROM log_reg_softmax
        ), XW AS (
            SELECT CAST(log_reg_softmax_mock.y = _X.y  AS INTEGER) AS y_class, row_id AS rn, log_reg_softmax_mock.y, (f1 * w1 + f2 * w2 + f3 * w3 + f4 * w4 + intercept) AS val FROM _X, log_reg_softmax_mock
        ), XW_exps AS (
            SELECT y_class, rn, y, EXP(val - MAX(val) OVER(PARTITION BY rn)) AS exps FROM XW
        ), y_minus_sm AS (
            SELECT y_class, rn, y, y_class - exps / (SUM(exps) OVER(PARTITION BY rn)) + 2.220446049250313e-16 AS y_sm FROM XW_exps
        ), X_t_dot_y_minus_sm AS (
            SELECT -SUM(f1 * y_sm) AS w1, -SUM(f2 * y_sm) AS w2, -SUM(f3 * y_sm) AS w3, -SUM(f4 * y_sm) AS w4, -SUM(y_sm) AS intercept, y_minus_sm.y FROM y_minus_sm, _X WHERE row_id=rn GROUP BY y_minus_sm.y ORDER BY y_minus_sm.y
        ), grad AS (
            SELECT a.w1 + b.w1 AS w1, a.w2 + b.w2 AS w2, a.w3 + b.w3 AS w3, a.w4 + b.w4 AS w4, a.intercept + b.intercept AS intercept, b.y FROM log_reg_softmax_mock a, X_t_dot_y_minus_sm b WHERE a.y = b.y
        ), w_new(i, y, w1, w2, w3, w4, intercept) AS (
            SELECT i + 1, a.y, a.w1 - alpha * b.w1, a.w2 - alpha * b.w2, a.w3 - alpha * b.w3, a.w4 - alpha * b.w4, a.intercept - alpha * b.intercept FROM log_reg_softmax_mock a, grad b, alpha WHERE a.y = b.y
        ) SELECT * FROM w_new) tmp, iterations WHERE i <= iterations
), weights AS (
    SELECT y, w1, w2, w3, w4, intercept FROM log_reg_softmax, iterations WHERE i = iterations
), _XX AS (
    SELECT *, ROW_NUMBER() OVER() AS row_id FROM X
), XW AS (
    SELECT CAST(weights.y = _XX.y  AS INTEGER) AS y_class, row_id AS rn, weights.y, (f1 * w1 + f2 * w2 + f3 * w3 + f4 * w4 + intercept) AS val FROM _XX, weights
), XW_exps AS (
    SELECT y_class, rn, y, EXP(val - MAX(val) OVER(PARTITION BY rn)) AS exps FROM XW
), y_sm AS (
    SELECT y_class, rn, y, exps / (SUM(exps) OVER(PARTITION BY rn)) + 2.220446049250313e-16 AS y_sm FROM XW_exps
), accuracy AS (
    SELECT SUM(CAST(class_rank = 1 AS INTEGER)) / CAST(COUNT(class_rank) AS DOUBLE PRECISION) AS accuracy FROM (SELECT y_class, y_sm, RANK() OVER(PARTITION BY rn ORDER BY y_sm DESC) AS class_rank FROM y_sm) AS ranked WHERE y_class = 1
)
SELECT 'class weights ' || CAST(y AS TEXT) || ':' AS stats_and_params, ARRAY_TO_STRING(ARRAY[w1, w2, w3, w4, intercept], ', ') AS "values" FROM weights
UNION ALL
SELECT 'train accuracy:  ', CAST(accuracy AS TEXT) FROM accuracy
ORDER BY stats_and_params;

五、两种模式对比

1. 性能对比

1.1 UDF模式

UDF的执行速度受多重因素影响。它们利用传统的编程语言如Python及其优化的库如NumPy、Pandas、scikit-learn等,能够灵活高效地执行复杂的数学运算。然而,在数据库调用UDF时,由于它可能在数据库服务器的不同进程或远程机器上执行,因此需要承担额外的网络通信和上下文切换的开销。若UDF设计不当或计算复杂,其执行速度会受到影响而降低。此外,当UDF在外部环境中运行时,可能无法充分利用数据库的并行处理能力,这进一步影响了其性能表现。

资源消耗方面,UDF在编写时需要额外编程工作并可能加载外部资源比如如库文件或数据,同时它们可能会消耗大量CPU和内存资源。在处理大规模数据集时资源消耗尤为显著,影响数据库服务器性能,并且若UDF在外部环境中执行,可能因不受数据库资源管理限制而导致资源使用失控。

1.2 SQL编码模式

SQL编码实现能够提升执行速度,因为它能够充分利用数据库的查询优化器和底层存储结构如列式存储和索引来加快数据访问和处理,同时现代数据库管理系统支持的矢量化操作也显著提高了数据处理效率。此外,对于编译型数据库而言,SQL查询在执行前还会被编译成机器代码,减少解释执行的开销。

资源消耗方面,SQL编码实现能够高效利用数据库管理系统的资源管理机制来控制内存消耗和CPU时间。同时,它通过减少数据移动、提高数据局部性来减少I/O操作并提升缓存利用率。此外,SQL编码实现还能利用数据库的并行和分布式执行能力,在多核和多节点环境中实现有效扩展。

1.3 小结

UDF模式和SQL编码模式的性能比较取决于具体的使用场景和系统配置。UDF模式提供了灵活性和访问外部优化库的能力,而SQL编码模式则可以充分利用数据库的优化和资源管理。

2. 适用场景对比

2.1 UDF模式

UDF模式的适用场景广泛。在数据库缺乏内置复杂机器学习算法时,UDF可调用Python、R等高级语言中的机器学习库。UDF可为高度复杂或最新模型提供快速集成方式。结合特定业务逻辑,UDF能够灵活解决各种问题,并在执行复杂计算或逻辑操作时提供多样化的实现手段。用户还可以根据特定需求自行编写UDF,满足个性化的数据处理要求。

然而,UDF也存在多方面的限制。它们可能会在处理大规模数据集时引入额外的性能开销,影响数据库服务器的性能;同时不易于数据库管理系统的资源管理,可能导致资源使用失控。为了保障数据库的安全和数据隐私,UDF还需要额外的权限和安全措施。此外,依赖特定编程语言或库的UDF在不同数据库系统间的移植性较差,且开发和维护成本较高,因为它们需要额外的编程工作,并可能需要加载外部资源,增加了复杂性。

2.2 SQL编码模式

SQL编码模式比较适用于数据量巨大的场景,可以通过就近计算来减少数据传输以提高性能。SQL编码可充分利用数据库的并行处理、优化器、底层存储结构如列式存储和索引等资源来提高机器学习任务的性能,确保所有操作在数据库内部完成以管理和维护数据安全和一致性。通过将机器学习算法转换成SQL语句执行,可标准化操作并简化数据处理流程。此外,SQL编码还能利用数据库的并行和分布式执行能力,在多核和多节点环境中实现有效扩展。

然而,纯SQL实现机器学习算法也存在多方面的限制。例如,算法转换为复杂的SQL语句后,在某些复杂任务上可能达不到专用机器学习库的性能;对特定数据库系统的依赖性限制了算法的可移植性。同时,SQL无法高效表达所有机器学习算法,特别是需要复杂数据结构和控制流的算法。与UDF模式相比,SQL编码模式在灵活性方面可能受限。对于不熟悉SQL的用户来说,也存在较高的学习曲线。在执行复杂计算时,SQL编码还可能遇到性能瓶颈。

2.3 小结

选择UDF模式还是SQL编码模式取决于具体的业务需求、数据规模、性能要求、安全性考虑以及技术栈。在某些情况下,可结合使用这两种模式,以便充分利用各自的优势。例如,可以使用SQL实现数据预处理和线性模型的训练和预测,然后通过UDF调用高级机器学习库进行更复杂模型的训练和预测。

六、实践应用

双模式融合的库内机器学习技术的优势在于灵活运用两种不同的模式以适应不同的应用场景,能够显著减少数据移动,提高计算效率,并增强数据安全性,从而简化数据处理流程。接下来,我们将以贝格迈思自研的分布式智能数据库AiSQL为例,具体展示其通过双模式融合的库内机器学习技术所支持的实践应用。

AiSQL支持以文搜文、以文搜图、以图搜文和以图搜图等四种跨模态数据检索方式。为了提供这些服务,我们需要事先构建文本向量库和图片向量库。文本向量库存储于由(id, raw_text, embedding)三个字段构成的表单中,其中id是integer类型的文本主键,raw_text是text类型的文本内容,embedding是vector类型的文本向量。类似地,图片向量库存储于由(id, base64_image, embedding)三个字段构成的表单中,其中id是integer类型的图片主键,base64_image是text类型的图片内容base64编码,embedding是vector类型的图片向量。为了提高检索效率,文本向量库和图片向量库中的embedding字段一般都配备IVFFlat、HNSW、DiskANN和SPANN等近似最近邻检索索引结构。

此外,基于大模型的问答系统是大模型的重要应用。它实质上是在执行文本生成任务,即输入以文本为主的数据,输出回复文本。AiSQL中的AI特性插件支持四种模式的大模型问答功能,包括传统对话、基于检索增强生成的对话、基于图片和自然语言的视觉问答,以及自然语言到SQL语句的转换。基于这些问答模式,AI特性插件还提供了零样本训练的翻译、摘要和分类能力,用户无需额外的标注数据,只需通过简单的调用接口就能实现这些功能。

1. 以文搜文

以文搜文的SQL语句如下:

select * from aisql.similar_texts_by_text(query_text text, topk integer, dimension integer default 512, relation_name text default 'aisql.muge_texts');

其中,参数说明如下:

  • query_text: 查询文本。
  • topk: 需要返回的最相似文本个数上限。
  • dimension: 文本向量维度,必须与待查找的文本向量库中的向量维度一致。
  • relation_name: 充当文本向量库的表单名。

该SQL语句返回一个数据视图,由(相似文本, 查询文本与相似文本之间的相似度)两个字段的记录构成,每个记录对应文本向量库中的一个文本记录。

以文搜文示例:

-- 从默认文本向量库中检索出与查询文本最相似的5个文本
select * from aisql.similar_texts_by_text('多功能橱柜', 5);

2. 以图搜文

以文搜文的SQL语句如下:

select * from aisql.similar_texts_by_image(image_path text, topk integer, dimension integer default 512, relation_name text default 'aisql.muge_texts');

其中,参数说明如下:

  • image_path: 查询图片的文件路径。
  • topk: 需要返回的最相似文本个数上限。
  • dimension: 文本向量维度,必须与待查找的文本向量库中的向量维度一致。
  • relation_name: 充当文本向量库的表单名。

该SQL语句返回一个数据视图,由(相似文本, 查询图片与相似文本之间的相似度)两个字段的记录构成,每个记录对应文本向量库中的一个文本记录。

以图搜文示例:

-- 从默认文本向量库中检索出与查询图片最相似的5个文本
select * from aisql.similar_texts_by_image('/path/to/image.jpg', 5);

3. 以文搜图

以文搜图的SQL语句如下:

select * from aisql.similar_images_by_text(query_text text, topk integer, dimension integer default 512, relation_name text default 'aisql.muge_images');

其中,参数说明如下:

  • query_text: 查询文本。
  • topk: 需要返回的最相似图片个数上限。
  • dimension: 图片向量维度,必须与待查找的图片向量库中的向量维度一致。
  • relation_name: 充当图片向量库的表单名。

该SQL语句返回一个数据视图,由(相似图片的base64编码, 查询文本与相似图片之间的相似度)两个字段的记录构成,每个记录对应图片向量库中的一个图片记录。

以文搜图示例:

-- 从默认图片向量库中检索出与查询文本最相似的5张图片
select * from aisql.similar_images_by_text('多功能橱柜', 5);

4. 以图搜图

以图搜图的SQL语句如下:

select * from aisql.similar_images_by_image(image_path text, topk integer, dimension integer default 512, relation_name text default 'aisql.muge_images');

其中,参数说明如下:

  • image_path: 查询图片的文件路径。
  • topk: 需要返回的最相似图片个数上限。
  • dimension: 图片向量维度,必须与待查找的图片向量库中的向量维度一致。
  • relation_name: 充当图片向量库的表单名。

该SQL语句返回一个数据视图,由(相似图片的base64编码, 查询图片与相似图片之间的相似度)两个字段的记录构成,每个记录对应图片向量库中的一个图片记录。

以图搜图示例:

-- 从默认图片向量库中检索出与查询图片最相似的5张图片
select * from aisql.similar_images_by_image('/path/to/image.jpg', 5);

5. 传统对话

AI特性插件支持单个或多个回复文本的传统对话。

单个回复文本的传统对话的SQL语句如下:

select aisql.chat(model_name text, version text, api_key text, prompt text);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • prompt: 输入的用户问题。

该SQL语句返回一个回复文本。

单个回复文本的传统对话示例:

select aisql.chat('glm-4-9b-chat', 'v1', 'anykey', '请写一首七言绝句。');

多个回复文本的传统对话的SQL语句如下:

select aisql.chat(model_name text, version text, api_key text, prompt text, nresults integer);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • prompt: 输入的用户问题。
  • nresults: 需要返回的最大回复文本个数。

该SQL语句返回一个回复文本数组,数组中元素个数不超过nresults。

多个回复文本的传统对话示例:

select aisql.chat('glm-4-9b-chat', 'v1', 'anykey', '请写一首七言绝句。', 3);

6. 基于检索增强生成的对话

检索增强生成(Retrieval-augmented Generation, RAG)是缓解大模型幻觉问题的一种有效手段。它通过从知识库中检索与输入相关的文档,并将文档内容作为输入的一部分,从而生成更准确、更丰富的回复文本。AiSQL的AI特性插件实现了一种从历史对话文档和知识文档中检索相关文本的RAG机制。该机制约定历史对话文档保存于一个由(input, output, input_vec)三个字段构成的数据表单中,其中input是text类型的问题文本,output是text类型的回复文本,input_vec是input的向量表示。此外,该机制约定知识文档保存于一个由(id, paragraph, para_vec)三个字段构成的数据表单中,其中id是integer类型的段落序号主键,paragraph是text类型的段落内容,para_vec是paragraph的向量表示。input_vec字段和para_vec字段一般都需要具备IVFFlat、HNSW、DiskANN和SPANN等近似最近邻检索索引,以提供高效的向量检索服务。

AI特性插件支持单个或多个回复文本的RAG对话。回答用户的问题时,AiSQL首先从历史对话文档中检索出与用户问题最相似的input问题文本及其对应的output回复文本,即input-output问答对,作为历史对话;然后,从知识文档中检索出与用户问题最相关的段落,作为对话上下文;最后,将历史对话、对话上下文和用户问题作为输入,调用大模型生成回复文本;若历史对话文档不存在,则仅将对话上下文和用户问题作为输入,调用大模型生成回复文本。

单个回复的RAG对话的SQL语句如下:

select aisql.retrieval_augmented_chat(model_name text, version text, api_key text, question text, dimension integer, pr_relation_name text, qa_relation_name text default NULL);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • question: 输入的用户问题。
  • dimension: 向量表示的维度。该维度必须与知识文档和历史对话文档中向量表示的维度一致。
  • pr_relation_name: 充当知识文档的数据表单名,该数据表单由(id, paragraph, para_vec)三个字段构成,其中id是integer类型的段落序号主键,paragraph是text类型的段落内容,para_vec是paragraph的向量表示。
  • qa_relation_name: 充当历史对话文档的数据表单名,该数据表单由(input, output, input_vec)三个字段构成,其中input是text类型的问题文本,output是text类型的回复文本,input_vec是input的向量表示。

该SQL语句返回一个回复文本。

多个回复的RAG对话的SQL语句如下:

select aisql.retrieval_augmented_chat(model_name text, version text, api_key text, question text, nresults integer, dimension integer, pr_relation_name text, qa_relation_name text default NULL);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • question: 输入的问题文本。
  • nresults: 需要返回的最大回复文本个数。
  • dimension: 向量表示的维度。该维度必须与知识文档和历史对话文档中向量表示的维度一致。
  • pr_relation_name: 充当知识文档的数据表单名,该数据表单由(id, paragraph, para_vec)三个字段构成,其中id是integer类型的段落序号主键,paragraph是text类型的段落内容,para_vec是paragraph的向量表示。
  • qa_relation_name: 充当历史对话文档的数据表单名,该数据表单由(input, output, input_vec)三个字段构成,其中input是text类型的问题文本,output是text类型的回复文本,input_vec是input的向量表示。

该SQL语句返回一个回复文本数组,数组中元素个数不超过nresults。

7. 基于图片和自然语言的视觉问答

视觉问答(Visual Question answer, VQA)是一种典型的多模态信息处理问题,给机器一张图片和一个开放式的的自然语言问题,要求机器输出自然语言答案。

视觉问答的SQL语句如下:

select aisql.vqa(model_name text, version text, api_key text, image_path text, prompt text);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • image_path: 用于回答用户问题的图片文件路径。
  • prompt: 输入的用户问题。

该SQL语句返回一个回复文本。

视觉问答示例:

select aisql.vqa('glm-4v-9b', 'v1', 'anykey', '/path/to/image.jpg', '详细描述这张图表达的内容');

8. 自然语言到SQL语句的转换

自然语言到SQL语句的转换(Text-to-SQL)是一种前沿的人机交互技术,通过将针对数据库的自然语言查询转换成数据库管理系统能理解的SQL查询,可以降低数据库运维的学习成本,改善用户使用数据库的体验。AiSQL提供了一种针对数据库内指定命名空间schema的Text-to-SQL服务,利用该命名空间内的所有数据表单将用户针对数据库的自然语言查询转换成SQL查询。

这种Text-to-SQL服务的SQL语句如下:

select aisql.convert_nl_query(model_name text, version text, api_key text, schema_name text, query text, nresults integer default 1);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • shema_name: 需要查询的库内命名空间名,该命名空间内的数据表单用于合成目标SQL查询。
  • query: 用户针对数据库的自然语言查询。
  • nresults: 转换得到的候选SQL查询个数上限。

该SQL语句返回一个候选SQL查询数组,数组中SQL查询个数不超过nresults。

Text-to-SQL示例:

-- 产生至多3个候选SQL查询,每个候选SQL查询单行显示
select unnest(aisql.convert_nl_query('Qwen1.5-7B-NSQL', 'v1', 'anykey', 'concert_singer', '按年龄降序,每个歌手的名字、国家、年龄是什么?', 3));

9. 机器翻译

AiSQL提供了一种基于大模型的机器翻译服务,支持将一种自然语言翻译成另一种自然语言。

这种机器翻译服务的SQL语句如下:

select aisql.translate(model_name text, version text, api_key text, source_language text, target_language text, source_text text);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • source_language: 源语言。
  • target_language: 目标语言。
  • source_text: 源语言文本。

该SQL语句返回一个目标语言文本。

机器翻译示例:

-- 将英文翻译成中文
select aisql.translate('glm-4-9b-chat', 'v1', 'anykey', 'en', 'zh', 'Hello, world!');

10. 文本摘要

文本摘要是指对一段长文本进行精简,提取出关键信息,生成一段简短的摘要。AiSQL提供了一种基于大模型的文本摘要服务,支持将一段长文本转换成指定长度的摘要。

这种文本摘要服务的SQL语句如下:

select aisql.summarize(model_name text, version text, api_key text, source_text text, max_length integer default 100);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • source_text: 需要生成摘要的文本。
  • max_length: 摘要的最大长度。

该SQL语句返回一个摘要文本。

文本摘要示例:

-- 生成至多100个字符的摘要
select aisql.summarize('glm-4-9b-chat', 'v1', 'anykey', '文本摘要是指通过各种技术,对文本或者是文本的集合,抽取、总结或是精炼其中的要点信息,用以概括和展示原始文本的主要内容或大意。作为文本生成任务的主要方向之一,从本质上而言,这是一种信息压缩技术。文本摘要技术是信息爆炸时代,提升人们获取有效信息效率的关键技术之一,如何从冗余、非结构化的长文本中提炼出关键信息,构成精简通顺的摘要,是文本摘要的核心问题。按照实现技术方案的不同,文本摘要可以分为抽取式文本摘要和生成式文本摘要。抽取式的文本摘要直接从原文中摘取完整的句子作为文章的摘要,所以通常在语法层面的正确性以及对原文概括的准确性上比较占优势,如同按部就班的老实人,令人心安;生成式的文本摘要可以产生原文中没有的单词和短语,容易产生事实性错误,好比一位逍遥的江湖侠客,蛟龙终非池中物,目前,我们这位侠客虽然艳惊四座,但却容易野马脱缰,返回不符合事实的结果。', 100);

11. 单标签分类

单标签分类是指对文本进行分类,每个文本只属于一个类别。AiSQL提供了一种基于大模型的单标签分类服务,支持将一段文本分类到指定类别。

这种单标签分类服务的SQL语句如下:

select aisql.classify(model_name text, version text, api_key text, source_text text, labels text[]);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • source_text: 需要分类的文本。
  • labels: 需要分类的标签列表。

该SQL语句返回一个标签列表。

单标签分类示例:

-- 将文本分类到指定类别
select aisql.classify('glm-4-9b-chat', 'v1', 'anykey', '文本分类是指将文本按照一定的规则和标准进行分类,以便于管理和检索。文本分类是自然语言处理领域的一个重要研究方向,广泛应用于信息检索、文本挖掘、机器翻译等领域。', array['news', 'technology']);

12. 多标签分类

多标签分类是指对文本进行分类,每个文本可以属于多个类别。AiSQL提供了一种基于大模型的多标签分类服务,支持将一段文本分类到多个类别。

这种多标签分类服务的SQL语句如下:

select aisql.multilabel_classify(model_name text, version text, api_key text, source_text text, labels text[]);

其中,参数说明如下:

  • model_name: OpenAI服务接口约定的大模型名称。
  • version: 大模型的字符型版本号。
  • api_key: OpenAI服务接口的API密钥,用于验证请求的合法性。
  • source_text: 需要分类的文本。
  • labels: 需要分类的标签列表。

该SQL语句返回一个标签列表。

多标签分类示例:

-- 将文本分类到多个类别,每个类别单行显式
select unnest(aisql.multilabel_classify('glm-4-9b-chat', 'v1', 'anykey', '文本分类是指将文本按照一定的规则和标准进行分类,以便于管理和检索。文本分类是自然语言处理领域的一个重要研究方向,广泛应用于信息检索、文本挖掘、机器翻译等领域。', array['news', 'technology', 'science']));

七、总结

未来,随着自然语言处理技术的进步和机器学习的持续发展,以及数据库管理系统对机器学习能力的增强支持,将机器学习算法自动化翻译成SQL代码的可能性显著提升。这一领域已有实际进展,诸如将自然语言输入转换为SQL查询,并有望扩展到算法描述的转换;同时,基于大型语言模型的机器学习应用能够理解复杂查询需求并生成相应SQL代码,而代码生成算法结合数据库元数据也能生成逻辑SQL。此外,开源工具如SQL Translator、AI驱动的自然语言处理工具LangChain以及BrightML的机器学习扩展等,均展示了自然语言到SQL转换的可行性,并为机器学习算法的自动化翻译奠定了基础。这些技术进步和项目实践预示了将机器学习算法自动化翻译为SQL代码的可能性正不断增大。

将机器学习算法集成到数据库中蕴含着巨大的潜力,它不仅能够通过数据库管理系统提供的数据预处理、存储、分布式计算功能实现数据的高效转换、存储和并行计算,还能通过机器学习模型训练和优化功能提升模型性能。此外,实时分析和智能化集成技术的应用进一步提高了业务响应速度和决策效率。然而,这一过程也伴随着数据安全性和隐私性保护、数据质量提升、技术复杂性管理、计算开销控制以及模型一致性保障等多重挑战。特别是训练数据稀缺、训练时间长、泛化能力受限和适应性不足等问题,在机器学习算法与数据库技术结合的过程中尤为突出。尽管如此,随着技术的不断进步,我们有理由相信这些挑战将逐渐被克服,机器学习与数据库的集成应用将会更加成熟和广泛。

产品与服务

解决方案

资源中心

关于我们

联系方式

深圳市南山区粤海街道高新南七道国家工程实验室大楼A1402

0755 - 8670 1822

贝格迈思微信公众号

仅在办公网络环境可见