主要技术:FastAPI、SQLModel、PostgreSQL、pgvector
项目目录
项目简介
SQLBot 是一套基于 Python、FastAPI 和 Vue 的自然语言数据分析平台。它连接业务数据库,结合表字段说明、业务术语和查询示例生成 SQL,展示查询数据、图表与分析结果。
用户先选择已接入的数据源,再提出统计问题,查看生成语句和结果,并在同一会话中继续追问。管理端可维护表字段说明、表关系、术语和问题—SQL 示例,让模型在实际数据库结构和业务含义的共同上下文中生成查询。
项目亮点
- 表结构向量与名称匹配: 以表结构为召回单位,融合向量相似度和表名、字段名、注释等关键词信号,并保留问题明确点名的表。字段随入选表进入上下文,不另建独立字段召回链。
- 一跳关联与业务知识补充: 根据人工维护的
table_relation补入相邻表及连接字段;术语和问题—SQL示例另行匹配、分段注入,分别补充业务口径和参考查询。 - 结构同步与知识分层维护: 元数据同步更新字段类型和原始注释,保留人工说明,再异步更新结构向量。表关系、术语和示例独立维护,便于定位结构变化与业务知识变化。
- 实际语句检查与跨轮错误反馈: 从生成的
SQL提取真实表名核对本次候选范围,执行前检查读取操作;数据库执行错误保存后带入下一轮,供模型继续修正,而不是在同轮无界重试。
技术架构
Vue 页面发起对话,FastAPI 后端由 LLMService 组织关键词、候选表、结构与业务知识,再调用模型生成查询。数据库适配层执行 SQL,结果用于表格、图表和分析展示,流式事件向页面反馈当前进度。
平台配置、会话和知识数据通过 SQLModel 持久化,PostgreSQL/pgvector 支撑平台存储与向量匹配;被查询的业务数据库由各数据源连接器接入,不要求都迁移到平台数据库。
| 代码位置 | 主要职责 |
|---|---|
backend/apps/datasource/ |
管理数据源与表字段元数据,构建表向量并组装关联结构 |
backend/apps/terminology/、backend/apps/data_training/ |
匹配业务术语和问题—查询示例 |
backend/apps/chat/task/llm.py |
组织问数上下文、模型调用、语句检查与错误反馈 |
backend/apps/db/db.py、frontend/src/views/ |
适配数据库执行,并展示对话、数据与图表 |
如何写进简历
仓库问数台 · 仓配库存问数助手 | 物流仓储场景示例
项目描述:面向仓配运营人员的库存问数助手,围绕仓库、商品和批次查询指定时点的实物或可用库存及收发存变化,支持从汇总差异回查原始单据。
技术栈:Python、FastAPI、SQLModel、PostgreSQL、pgvector
主要工作:
- 混合召回与跨表关联补全:基于表结构
Embedding与关键词得分召回库存、商品和流水候选,保留显式表名,再按table_relation补充一跳关联与连接字段,为跨表库存查询组织完整上下文。 - 库存时点重建与聚合粒度:以带流水水位的快照加增量重建指定时点库存,迟到过账和冲销按原单修正;库存与有效占用先按仓库、商品和批次聚合,再关联查询视图,避免重复累计及一对多连接放大结果。
- 分层 SQL 上下文与执行反馈:将库存时点、实物或可用口径作为术语及问题—
SQL示例,与Schema分层注入模型;解析实际表名核对候选范围,执行前检查读取操作,并将数据库错误带入下一轮修正。
酒店有数 · 酒店经营问数助手 | 酒店住宿场景示例
项目描述:面向酒店经营人员的问数助手,按酒店、渠道和营业日查询预订、实际入住房晚及取消变化,展示统计口径、数据和图表。
技术栈:Python、FastAPI、SQLModel、PostgreSQL、pgvector
主要工作:
- 房晚与经营金额的粒度建模:按营业日展开实际入住房晚,退房日不计入住,停用房从可售分母剔除;房晚、费用与退款分别聚合后再关联,房晚级金额按明确规则分摊并核对总额,避免多房晚重复累计。
- 表结构检索与经营语义增强:结合表向量、表字段名称及注释关键词收敛预订、房态和渠道候选,将房晚与取消口径通过术语、问题—
SQL示例补入上下文;结构同步保留人工说明并异步更新向量,支撑业务表调整后的问数。 - 多轮问数与日期语义重建:结合近期问答保存酒店、预订日或入住日、期间与指标的查询计划,追问改期间时重建日期条件;把确认口径与本轮
Schema共同交给模型生成查询,减少历史条件与新问题错配。
面试题与回答
3 题如何检索召回数据库的表和字段?
展开收起
核心回答
SQLBot的这条召回链以表级结构为单位:先在当前数据源已选用的表字段范围内,用表结构向量和关键词规则给表排序,保留用户明确点名的表,再补入已配置关系中与候选表直接相连的表,最后把表名、字段类型、说明和连接关系交给模型生成SQL。它的
Python后端负责结构读取与上下文组装,Embedding模型提供语义相似度,关键词规则补充精确名称和业务描述。字段参与表的匹配,并随入选表进入结构上下文;这条实现并没有为每个字段建立独立向量召回分支。选中了业务表,还要确认连接路径及需要的字段是否完整。先准备结构,再做表匹配
构建表向量时,程序把表名、字段名、字段类型及自定义说明组织为结构文本,计算并保存向量。查询阶段先读取已勾选的表和字段,对字段应用列权限过滤;若调用方提供
table_list,还会进一步限制候选表。随后组装各表的
schema_table:表说明优先采用自定义说明,否则使用原表注释;字段结构包含字段名、类型及已配置的自定义说明。关键词评分还能使用字段原注释。由此,向量所依据的结构、关键词信号和最终送给模型的字段列表需要分别核对,修改说明后也要关注表向量是否同步更新。普通内置数据源路径会先抽取问题关键词,再用术语同义词扩展,供表匹配使用。向量分数衡量关键词与表结构的语义接近程度;关键词规则则匹配表名、表说明、字段名和字段说明,并结合匹配质量与覆盖率评分。启用融合时,分数为
α × 向量分数 + (1−α) × 关键词分数,默认α=0.4。它是规则分数与向量分数的线性融合,未使用RRF或独立重排模型。见关键词与向量融合实现。明确点名的表怎样保留,失败时怎样回退
仅按融合分取前几名,可能漏掉问题中明确要求使用的表。
_select_tables()因此会用原始问题匹配完整表名或完整表说明,把这些表保留在前面,再按已有排名填充剩余名额。匹配处理标识符边界、引号包裹名称和重叠名称,减少把短表名误当成长表名中一部分的情况。TABLE_EMBEDDING_COUNT默认是 10,但显式命中的表全部保留,数量可能超过这个值。这一规则只作用于调用方已经筛选过的候选,不会把范围外的表重新引入。见显式表保留规则。当前表匹配按排名和数量选择,没有额外的最低相似度阈值。因此,低相关问题也可能得到若干候选表。关键词为空、关键词功能关闭或融合计算异常时,会改用原问题做纯向量排序;纯向量计算也异常时,则保留全部已过滤候选并把显式命中项置前。这种回退减少了计算失败造成的漏表,但会增加结构上下文,不能把“有候选”当作已经找到正确表。
一跳关联补表能补什么
表匹配后,程序读取数据源维护的
table_relation,找出至少一个端点属于当前候选表的关系边,补入这些边另一端缺失的表结构,再追加相应字段等式。关系来自配置,虽然输出栏目名是Foreign keys,并不表示已经从数据库自动发现并验证全部外键约束。补表也只从此前允许的候选范围中取结构。这个过程只扩展一跳。例如已选
A,关系为A→B→C,能补入与A直接相连的B,但不会再以新补的B为起点递归查找C。它可以补回某些未直接命中的桥表,却没有实现任意多跳路径搜索;长链查询仍可能缺表或缺边。具体流程见结构拼接与一跳关系补全。最终结构上下文包括数据库标识、入选和补入的表结构,以及相关字段连接式;可选的样本数据另行读取。业务术语、示例
SQL和额外提示分别注入生成消息,不由表向量替代。若要进一步支持复杂桥接,应在允许范围内增加路径选择与连接粒度校验,而不是无差别扩展整张关系图。验证时,可以对照纯向量、融合、显式保留和一跳补表,分别检查目标表是否出现、关键字段是否保留、连接路径是否完整,以及最终结果是否符合口径。这样才能区分是选表漏了、关系配置缺了,还是结构已经齐全但生成的连接或聚合有误。
参考资料
- 国内:飞致云:SQLBot 最佳实践:采用表字段说明、手工关系配置、术语与示例分别提供上下文的做法,解释表匹配之后为何仍需连接和业务知识。
- 国外:Wang 等:RAT-SQL:依据问题名称、字段及关系共同对齐的分析,解释显式名称信号与表结构关系各自解决的歧义;项目机制以固定版本源码为准。
Text-to-SQL 如何区分表结构与业务规则知识,并适应表结构变更?
展开收起
核心回答
SQLBot将表字段元数据、人工维护的表关系、业务术语和SQL示例分开管理,生成时再组合成上下文。表字段说明有哪些可用对象、类型和注释,表关系提供连接依据;术语解释业务含义与同义表达,示例则提供“问题—查询写法”的参考。字段类型本身不能说明库存余额采用哪个快照时点、滞销天数按哪类出库计算,这类口径需要补进业务说明或示例。适应结构变化时,先同步真实表字段,再检查人工关系、业务说明和示例是否仍引用正确对象。该版本的结构同步会更新元数据并触发表与数据源的向量更新,但这条同步链没有自动迁移业务术语、改写示例
SQL或清理全部生成依赖的过程。不同知识怎样进入 SQL 上下文
以平台管理的普通数据源问数为例,
get_table_schema()从启用的表与字段构造结构信息,列权限过滤也在构造前处理。选表后,表名、字段名、类型与注释被组织成Schema文本;已有人工配置的table_relation会补充相关表及连接字段。这里的表关系来自维护的关系图,不等于系统自动读取并验证了数据库中的外键约束。表字段范围、结构与表关系组装。业务语义走独立匹配:
filter_terminology_template()根据未扩展的关键词或原问题匹配术语,带上当前数据源等适用范围,返回主词、同义词与解释;filter_training_template()按问题匹配该数据源范围内的SQL示例。开启向量匹配时可补充语义候选,结果随后被格式化为上下文,并非修改数据库结构或训练模型。术语匹配入口、示例匹配入口、术语模板、示例模板。sql_sys_question()分别构造结构、术语和示例模板,init_messages()将这些内容逐项加入生成SQL的消息。结构信息与业务解释因此可以同时约束查询,但前提是对应内容确实被匹配并加入;只维护一条术语,并不代表每次生成都会使用它。模板构造、消息注入。结构同步更新了什么
同步逻辑按表名、字段名匹配记录:已有表更新数据库注释,已有字段更新类型、原始注释和顺序,新表新字段创建记录。已有的
custom_comment不会因此被数据库注释覆盖,所以人工维护的业务说明可以保留,也需要在含义变化时另行检查。表与字段同步。同步结束会提交表和数据源的向量更新任务,这些任务在线程池中运行。触发更新与更新完成需要区分;重新生成时应检查实际选表结果及注入的结构,确认使用的是更新后的内容。单表字段更新、后台向量更新。
字段重命名也不会自动识别为同一业务字段的迁移。旧名称可能仍出现在术语解释、示例查询和人工关系配置中,相关内容需要单独确认和修改。若要实现“字段变化后自动定位并停用受影响的规则、示例与缓存”,还需要额外维护依赖关系与失效机制,不能仅靠同步表结构完成。
怎样验证一次变更
例如业务库把库存数量字段从
stock_qty改成on_hand_qty,且业务含义不变:先同步字段,检查注入结构是否已使用新名称;再检查相关术语、示例及连接配置中是否残留旧引用。用同一批问数问题重新生成查询,对照参考SQL检查库存快照、出入库和日期口径,并核对查询结果与可访问范围。这能分别确认结构刷新、知识匹配与业务结果。查询成功执行只说明表字段和语法可用,不能证明新字段承接了原来的业务含义,也不能证明示例中的统计口径仍然正确。
Text-to-SQL 在 Agent 中如何应用?存在哪些风险和限制?
展开收起
核心回答
SQLBot把自然语言问数拆成相关表选择、结构与业务知识组装、SQL 生成、执行和结果展示。表备注、人工表关系、术语与 SQL 示例帮助模型理解该查什么、怎样关联;生成后仍需由程序检查实际 SQL,并依据数据库返回的数据回答。这里要区分三件事:模型按格式返回了 SQL、SQL 通过现有执行检查、查询结果符合业务口径。前两项成立,也不能证明日期条件、连接粒度和统计公式都正确。
生成结果怎样进入执行?
check_sql()从模型返回中提取 JSON,读取success、sql等字段,并检查 SQL 非空。它负责响应格式和生成结果解析,不是完整的语法、安全或成本审核。随后程序用
sqlglot从 SQL 本身提取真实表名,与本次允许的table_name_list比较,不直接信任模型附带的tables字段。没有成功提取表或出现白名单外表时拒绝继续。这个检查使用裸表名,不能据此推导已经完成任意数据库、Schema、列和行级权限校验。响应解析、真实表提取与白名单。exec_sql()执行前还会调用check_sql_read()。该函数检查允许的首关键字、危险模式、解析出的语句类型和危险函数;默认允许SELECT/WITH,元数据命令另受配置控制。它形成了一层读取操作检查,但现有写类型判断主要针对每条语句的顶层节点,不能直接称为已经证明所有嵌套表达式都安全的完整 AST 沙箱。执行前检查、读取操作检查。查询失败后会自动反复修正吗?
这条对话链路没有同一轮自动重试循环。数据库执行异常会被包装、保存并作为错误返回,本轮随后结束;下一轮初始化时,程序查询同一会话的最新记录,如果它属于
exec-sql-err,才把错误放入<error-msg>供模型参考。连接失败、格式错误等情况不能统一当成这条执行错误反馈。错误保存与结束、下一轮错误上下文。若要增加自动纠错,应限制次数,区分可纠正的语法、结构错误与权限拒绝,并让修正后的 SQL 重新通过执行检查。这是进一步完善方案,不能写成该版本已经具备的行为。
实际落地还要验证什么?
首先核对业务结果。例如一对多连接可能让库存数量重复累加,SQL 却能顺利执行;要用明确的样例数据和参考查询检查粒度、时间及过滤条件。术语和示例是生成依据,不是正确性证明。
其次按数据源核对运行限制。不同连接器的连接、驱动和执行超时配置并不相同,不能统一称为查询的硬截止时间;提示词中的结果行数要求也不等于所有分支都有后端强制上限。生产接入还应配置适当的数据库账号与权限、结果上限和查询资源约束,再验证越权、慢查询与错误反馈。这里的源码审查不替代这些部署测试。