OA0
OA0 是一个探索 AI 的社区
现在注册
已注册用户请  登录
OA0  ›  代码  ›  MindsDB SQL Agent — 用 SQL 风格接口连接数据与 AI 能力

MindsDB SQL Agent — 用 SQL 风格接口连接数据与 AI 能力

 
  arrange ·  2026-04-25 11:00:24 · 13 次点击  · 0 条评论  

安装

pip install mindsdb_sql

组件

Parser(解析器)
- 接收字符串输入,解析为抽象语法树(AST)

Planner(规划器)
- 接收 AST 输入,将其转换为执行查询所需的一系列步骤

Render(渲染器)
- 接收 AST 输入,将其转换为指定 SQL 方言的字符串

解析器

使用方法


from mindsdb_sql import parse_sql

query = parse_sql('select b from aaa where c=1', dialect='mindsdb')

# 结果是一个抽象语法树 (AST)
query

# AST 的字符串表示形式
query.to_tree()

# 将树结构转换为 SQL 字符串,可能与原始 SQL 不完全一致
query.to_string()

支持的方言

mysql
- MySQL 服务器的 SQL 方言。尚未完全实现,正在持续改进中

sqlite
- 目前尚未完全实现,是 mysql 语法的简化版本

mindsdb
- 扩展的 MySQL 方言,支持 mindsdb SQL 命令和运算符 [https://docs.mindsdb.com/]

架构

解析过程

使用 SLY 库进行解析。

解析分为两个阶段(每个方言有独立模块):
- 在 lexer.py 模块中定义关键字,主要通过正则表达式实现
- 在 parser.py 模块中定义语法规则,通过 BNF 范式 描述规则
- 语法在函数的装饰器中定义,装饰器内可使用关键字本身或解析器中的其他函数
- 函数的输出可作为解析器其他函数的输入
- 解析器的输出列为"顶层语句",必须是抽象语法树(AST)对象

由于 SLY 不支持继承,每个方言需完整独立描述,无法互相扩展。

抽象语法树 (AST)

  • AST 结构在独立模块中定义(位于 parser/ast/ 目录)
  • 支持继承
  • 每个类必须包含以下方法:
  • to_tree - 返回对象的层级表示
  • get_string - 将对象作为 SQL 表达式(或子表达式)返回
  • copy - 将 AST 树复制到新对象

错误处理

为提供更好的用户体验,解析错误会包含问题位置及可能的解决方案。
1. 当以下情况发生时显示错误位置:
- 字符无法被解析(由词法分析器处理)
- 出现意外的标记(由解析器处理)
2. 尝试在错误位置附近建议正确的标记。可能的选项:
- 关键字会原样显示
- '[number]' - 预期为浮点数或整数
- '[string]' - 预期为字符串
- '[identifier]' - 预期为对象名称。例如,以下加粗词汇即为标识符:
- "select x as name from tbl1 where col=1"

建议机制说明:
使用语法规则定义的下一个可能的标记。
如果这是查询的末尾:仅显示这些标记。
否则:
- 尝试用可能的标记列表中的其他标记替换错误标记
- 再次尝试解析查询,如果无错误:
- 将该标记添加到建议列表
- 第二次迭代:在错误标记之前插入可能的标记(而非替换),重复相同操作。

示例:
image

规划器

使用方法

初始化规划器

from mindsdb_sql.planner import query_planner

# 所有参数均为可选
planner = query_planner.QueryPlanner(
    ast_query, # 查询的 AST 树
    integrations=['mysql'], # 可用集成列表
    predictor_namespace='mindsdb', # 查找预测器的命名空间
    default_namespace='mindsdb', # 查询中未指定命名空间时的默认命名空间
    predictor_metadata={ # 预测器信息
        'tp3': { # 预测器名称
           'timeseries': True, # 是否为时间序列预测器
           'order_by_column': 'pickup_hour', # 时间序列列
           'group_by_columns': ['day', 'type'], # 分区列(仅用于时间序列)
           'window': 10 # 窗口大小(仅用于时间序列)
        }
    }
)

时间序列预测器的详细说明:[https://docs.mindsdb.com/sql/create/predictor/]

预编译语句计划

规划器可用于带参数的查询:查询未完整,无法执行,但可以获取查询的列和参数列表。

for step in planner.prepare_steps(ast_query):
    data = do_execute_step(step)
    step.set_result(data)

statement_info = planner.get_statement_info()

# 列列表
print(statement_info['columns'])

# 参数列表
print(statement_info['parameters'])

目前此功能仅在 MySQL 二进制协议的 COM_STMT_PREPARE 命令中使用。

执行计划


# 如果已执行 prepare_steps,则需要传递参数。
# 否则,params=None
for step in planner.execute_steps(params):
    data = do_execute_step(step)
    step.set_result(data)

查询结果数据将在最后一步的输出中。

另一种执行方式

目前执行计划不依赖上一步的结果,但未来可能会改变。

在当前行为下,可以以列表形式获取查询计划:

from mindsdb_sql.planner import plan_query
plan = plan_query(
    ast_query,
    integrations=['mysql'], 
    predictor_namespace='mindsdb', 
    default_namespace='mindsdb', 
    predictor_metadata={
        'tp3': {
           'timeseries': False, 
        }
    }
)
# 步骤列表
print(plan.steps)

架构

规划器分析 AST 查询,并返回执行查询所需的一系列步骤。

步骤定义在 planner/steps.py 中。步骤可引用上一步的将来结果(使用 planner/step_results.py 中的 Result 类)。

查询规划器包含两个不同的规划器:

  1. 预编译语句:query_prepare.py 中的 PreparedStatementPlanner 类

  2. 执行:query_panner.py 中的 QueryPlanner 类
    规划器中最复杂的部分是处理时间序列预测器的连接表查询。逻辑简要说明:
    - 提取集成的查询(不含预测器)
    - 选择所有可能的分组字段值(查询范围内)
    - 对于每个分组字段值
    - 根据过滤条件和窗口大小选择数据部分
    - 将所有数据合并为一个 DataFrame
    - 将其传递到预测器输入
    - 将预测结果与预测前的数据合并

实用函数

  1. planner.utils.query_traversal

可用于分析 AST 树的组成。示例:

query_predictors = []
def find_predictors(node, is_table, **kwargs):
    if is_table and isinstance(node, ast.Identifier):
        if is_predictor(node):
            query_predictors.append(node)

utils.query_traversal(ast_query, find_predictors)

渲染器

渲染器用于将 AST 查询转换为不同 SQL 方言的字符串。

使用方法

from mindsdb_sql.render.sqlalchemy_render import SqlalchemyRender

renderer = SqlalchemyRender('mysql') # 选择方言
sql = renderer.get_string(ast_query, with_failback=True)

如果 with_failback==True:当 sqlalchemy 无法渲染查询时,将返回 AST 树的 SQL 字符串表示形式(使用 to_string 方法)

架构

目前只有一个可用的渲染器:SqlalchemyRender。
- 它将 AST 查询转换为 sqlalchemy 查询。
为此使用了命令式映射
- 然后使用所选方言在 sqlalchemy 内部编译生成的 sqlalchemy 对象

目前支持的方言:mysql, postgresql, sqlite, mssql, oracle

注意:
- 表名最多支持两部分
- 可以是 (integration.table) 或 (schema.table)
- 但不能是 (integration.schema.table)
- 渲染后的 SQL 中的条件有时可能略有变化,例如 'not a=b' 变为 'a!='

如何测试

运行所有组件的测试

env PYTHONPATH=./ pytest
13 次点击  ∙  0 人收藏  
登录后收藏  
0 条回复
关于 ·  帮助 ·  PING ·  隐私 ·  条款   
OA0 - Omni AI 0 一个探索 AI 的社区
沪ICP备2024103595号-2
耗时 15 ms
Developed with Cursor