本文从一个低代码平台真实的多表查询功能出发,完整复盘它从点选式(低代码/无代码)方案演进到大模型自然语言方案的两次架构设计、落地踩坑与关键改造。
所有业务表/字段均已脱敏为通用中性名词(订单、客户、商品、仓库…),聚焦的是方法论、设计权衡与工程经验——这些不依赖任何具体行业,纯中生有、自由适用。
目录
- 一、写在前面:我们到底要解决什么问题
- 二、第一代:用「拆 JOIN」换跨表查询
- 三、半年的冷水:功能「能」做,但没人用
- 四、第二代:AI 复合查询,一句话的事
- 五、关键的架构改造:两段式路由
- 六、与大模型缠斗的过程:十个坑和它们的解法
- 七、效果与价值
- 八、从点选到一句话:低代码/无代码的时代命运
- 九、总结与展望
一、写在前面:我们到底要解决什么问题
我们在超兔一体云平台上,开发低代码交互的查询工具。支撑业务方跨表分析的核心组件,就是我们围绕多表复合查询引擎做的两代开发:从点选式Step by Step 配置,到接入大模型的自然语言查询。作为研发该引擎的技术人员,我们在前一代沉淀了一套成熟的查询底座,又在后一代把这层交互整个交给了大模型。下文便以这项开发为主线,讲讲两次架构设计、落地踩坑与关键改造。业务方在平台上搭表、搭表单、搭流程,最终沉淀出一套几十张相互关联的业务表。随着业务跑起来,一个高频诉求浮出水面:
「把(条件A)的(订单),关联上(条件B)的(客户),看看谁…」
这类查询有几个共同特征:
- 跨表:要同时看订单、客户、商品等多张表的数据;
- 条件不固定:今天是「近 90 天 + 某区域」,明天是「满 2 年没下单 + 有库存」,条件组合千变万化;
- 主从关系可嵌套:订单挂在客户下,明细挂在订单下,还可能经过中间表间接关联。
在关系型数据库里,这种需求最「标准」的答案当然是 JOIN。但在「一套库养几百上千个租户」的 SaaS 架构里,JOIN 并没有想象中美好。这正是我们第一代方案动刀的起点。
而站在更大的时间轴上看,这两代方案恰好把过去几年两条最烫的技术路径——低代码/无代码的「点选式」与大模型的「一句话式」——在同一个功能上完整地各走了一遍。行业里围绕二者的争论有个尖锐的落点:低代码/无代码本就不是给终端用户用的,它帮开发者把「写代码」降级成「点界面」,却把「点界面」这件靠人手工、因硬编码在前端而难以被工具自动复制的事留了下来,因而在大模型时代几乎找不到立足之地。我们这个发生在普通用户身上的小切面,恰恰能在这最贴近业务的一层印证这个判断——这是第八章要展开的核心观点,这里先按下不表。
二、第一代:用「拆 JOIN」换跨表查询
2.1 为什么不敢直接用 JOIN
对单租户自建系统,JOIN 是家常便饭;但对 SaaS 多租户,我们反复权衡后决定避免把多表 JOIN 直接下推到数据库,理由有三个:
| 顾虑 | 说明 |
|---|---|
| 资源占用 | 条件不固定、跨多表 + 大字段(如明细、富文本)JOIN,很容易把库压垮;一个租户的「变态查询」可能拖垮同实例上的其他租户。 |
| 慢查询/死锁 | 高并发写多的系统里,复杂 JOIN 和主从复制之间存在锁竞争风险。 |
| 隔离与公平 | 多租户场景更在意「把负载控制在查询维度、按租户隔离」,而不是让数据库引擎去赌索引和连接策略。 |
一句话概括我们的取舍哲学:用计算时间换数据库负载,把复杂的关联从 SQL 层抬到业务逻辑层。这在多租户下是更「温和」、更可控的做法。
2.2 核心思想:ID 单表查询的逻辑组合
不去 JOIN,却要获得等价的跨表结果,秘诀是用多张表的单表查询 + 内存中的 ID 集合拼接。核心套路三步走:
- 先在主表上用主条件查询出目标记录的主键集合;
- 对每一张需要参与关联的子表/关联表,单独用它的条件单表查询,取出「能和主表对上」的关联字段值(通常是主表的外键 ID)集合;
- 把子表的结果以
关联ID IN (集合)的形式回灌成主表的主键过滤条件,逐级缩小主表结果。
这样每一层查询都是标准单表查询,数据库可以正常走索引、分页、缓存;复杂的关联分析全部发生在应用层,且天然按租户隔离。
我们把它形象地叫做 「IN 管道」:上一级的 ID 集合变成下一级的 IN 条件,一级一级传下去,直到回到主表。
2.3 配套的元数据:表档案
要做到「程序化地点选、无关代码地组合」,光有查询引擎还不够,还需要一份描述「这张表能提供什么」的元数据,我们叫它表档案(Table Profile)。它是一份结构化 JSON,记录了:
- entity:表名、主键、展示名;
- queryable:这张表允许查询的字段清单(含类型、显示名);
- plaintext:可以直接展示的字段;
- 关系描述:主表是谁、通过哪个字段关联。
表档案是整个体系的「唯一事实来源」(Single Source of Truth)。查询引擎本身是通用的、不感知业务;一切「这张表有哪些字段、字段是枚举还是人名」都从档案里读。这意味着加一张新表,只需要新增一份档案,不碰引擎代码。
2.4 一次点选查询的内部时序
用户在界面上的每一次点选,背后都走这样一条链路:

sequenceDiagram
autonumber
participant U as 用户
participant UI as 点选界面
participant EP as 引擎(多表组合)
participant WG as WHERE生成器
participant DB as 各业务表
U->>UI: 选主表(如 订单)
U->>UI: 选关联子表(如 客户) 与其条件
U->>UI: 选主表自己的过滤条件
UI->>EP: 提交:主表 + 步骤队列 + 条件
EP->>WG: 编译主表 WHERE
WG->>DB: 主表单表查询
DB-->>EP: 主表主键集合
EP->>DB: 查关联表(客户)单表,取关联ID集合
DB-->>EP: 客户ID集合
EP->>WG: 生成 IN(客户ID集合) 回灌主表
EP->>DB: 主表带 IN 条件再查
DB-->>EP: 命中主键/结果
EP-->>UI: 结果集(分批/翻译展示值)
UI-->>U: 表格结果
2.5 它做到了什么,又留下了什么
做到的:一个通用引擎,能覆盖非常多条件不固定的多表组合查询,且每层都是单表查询,负载可控、租户隔离清晰、可加表不改引擎。我们当时对它很满意。
留下的:它把「能力」做到了,却把「门槛」也留下了——这个门槛最终决定了一代产品的命运,见下一章。
三、半年的冷水:功能「能」做,但没人用
功能大概在 3、4 月份上线。到 7、8 月份回看数据,我们得到一个冷静的事实:
这个功能只有一些「深度用户」和「粉丝级用户」在用。
3.1 谁在用,谁不用
用的人:理解表之间关系的老用户,愿意啃界面、一层层配关系。这批人觉得「很香」。
不用的人:占绝大多数的普通用户。不是功能跑不起来,而是他们一眼就看不懂、也不想学。
3.2 门槛到底在哪里
我们复盘出,门槛由三层「认知税」构成:

mindmap
root(点选式查询的用户门槛)
表关系认知
要知道订单挂在客户下
要知道明细挂在订单下
要知道哪些表能间接关联
字段理解
字段的显示名是什么
字段是枚举还是人名还是数字
字段该用哪个条件算符
交互复杂度
主表子表一层层选
关系逐级配置
条件逐条添加保存
更扎心的对比是一句话:普通用户要表达的诉求,一两句话就能说清楚;但用点选界面把它配出来,可能要花 2 分钟左右,还要夹带上面那些认知。价值(能查复杂数据)是真的,但获取价值的成本把绝大多数人挡在了门外。
3.3 大模型交互为什么能破局
回看大模型之所以能快速普及,本质不是它逻辑多强,而在于两点交互特质:
- 自然语言输入:用户用「说话」代替「配置」;
- 复杂逻辑输出:把脑子里那句含混的话,翻译成严谨的结构化逻辑。
即便我们清楚大模型是靠「概率生成」而非「严格推理」,但用户认可的是交互本身——低门槛、说人话、即时反馈。对我们的启示非常直接:
既然查询引擎(第一代)已经成熟可靠,那 AI 方案不需要再造一个引擎,只需要在前面加一个「听得懂人话的大脑」,把自然语言翻译成引擎能吃的结构化查询要求。复用已踩过坑的成熟引擎,用 LLM 替换「点选」这层输入。
四、第二代:AI 复合查询,一句话的事
4.1 总设计:复用引擎,新增大脑
第二代在整个系统里只做了两个大的环节:
flowchart LR
A[用户自然语言提问] --> B[环节一: 意图理解/结构化]
B --> C[查询要求 JSON(主表/条件/关联)]
C --> D[环节二: 原有复合查询引擎执行]
D --> E[(各业务表单表查询)]
E --> F[结果翻译 展示]
F --> G[前端表格呈现]
- 环节一是唯一的新东西:分析用户自然语言描述的多表查询逻辑,结构化为查询要求;
- 环节二是直接复用第一代已经打磨成熟的复合查询引擎。
这避免了「为 AI 重造轮子」,是第二代能快速落地、且一上来就有 80% 命中率的关键。
4.2 端到端链路

flowchart TD
A[用户: “近90天有订单、且库存>0的商品”] --> B[意图服务 intent-service]
B --> C{两段式路由}
C -->|第一段| D[表路由 table-router<br/>召回相关表]
D --> E["路径闭包<br/>(自动补中间表)"]
E --> F[第二段: 计划生成<br/>只注入选中表档案 + 日期锚点]
F --> G[查询计划 JSON 校验/修复/重试]
G --> H[查询执行器 query-executor<br/>复用IN管道]
H --> I[结果翻译 translateRows<br/>K→V]
I --> J[前端表格]
4.3 环节一:自然语言 → 结构化查询要求
这是整个 AI 方案的「翻译官」,也是和大模型博弈最激烈的地方。它要产出类似这样的结构化查询要求(已脱敏):
{
"mainTable": "商品",
"conditions": [
{
"field": "库存", "op": "gt", "value": 0 }
],
"steps": [
{
"relationTable": "订单",
"via": "商品ID",
"condition": {
"field": "下单日期",
"op": "within",
"value": "近90天"
}
}
]
}
翻译官不是一次就能做好的。它和大模型的每一次握手都可能失败,于是我们在其后挂了 修复 + 校验 + 重试 三层保险(详见第六章)。关键词:不要把大模型的「一次输出」当成可靠输入,而要把它当成一个需要持续对齐、校验、纠偏的子系统。
4.4 环节二:结构化查询要求 → 引擎执行
有了结构化查询要求,剩下就是第一代引擎的主场:
- WHERE 编译:把 JSON 里的条件翻译成各类字段真正的存储值 SQL;
- IN 管道执行:按主表 + 关联条件逐表取 ID 集合并回灌;
- 结果翻译:把存储值/外键翻译回用户看得懂的展示值(枚举中文、人员姓名、关联业务名)。
这一点特别重要:LLM 只是把话说清楚,它一次 SELECT 都不会执行;真正干活、兜底正确性的,仍是那套验证过的查询引擎。
五、关键的架构改造:两段式路由
这是在我们认为第二代「已经完成 80%」时,被迫做、也做得最值的一次改造。
5.1 触发改造的导火索:提示词超限
第二代初期,做法相对朴素:把所有表的档案一股脑塞进提示词,让大模型自己去挑。当表数量到 25 张左右时,提示词超过了大模型的上下文限制(超限)。超限带来两个问题:
- 反馈漂移:提示词越长,大模型越容易注意力涣散,输出开始不稳定、前后不一致;
- 扩展性被锁死:如果就这样下去,往后扩到 40、50 张表根本走不通——这直接堵死了产品的增长预期。
我们意识到:「把所有表都喂给模型」这条路,是条死路。
5.2 两段式的本质:从「喂全部」到「喂相关的」
改造后的核心动作,是把一次问答拆成两段:
sequenceDiagram
autonumber
participant U as 用户
participant I as 意图服务
participant R as 表路由(第一段)
participant P as 计划生成(第二段)
participant E as 查询引擎
participant D as 业务表
U->>I: “近90天有订单、库存>0的商品”
I->>R: 只带表名索引 + 关系图 (相对短的提示词)
R->>I: 候选表集合 [商品, 订单, ...]
I->>P: 只注入选中表档案 + 日期锚点
P->>P: 生成查询计划 JSON
P->>E: 计划JSON
E->>D: 单表查询组合(N管道)
E-->>U: 结果
- 第一段(表路由):只给大模型一张「表名 + 一句话说明」的轻量索引 + 表关系图,让它召回相关表。这里我们刻意采用「宁多勿少(recall more than necessary)」策略——多召回不致命,漏召才是致命的。
- 第二段(计划生成):只把第一段选中的那几张表的完整档案注入提示词,生成精确的查询计划。
这段逻辑把「表的数据」和「大模型的分析结构」彻底解耦了。 无论未来是 27 张、40 张还是 100 张表,第一段都只看一层轻量索引,提示词长度基本恒定;第二段则永远只关心「和本次问题相关的那几张」。扩表从此不再受提示词长度约束,反而因为提示词变短而减少了漂移。
5.3 路径闭包:自动补齐中间表
两段式有个隐患:LLM 按直觉选表,但表之间可能不是直接关联,需要中间表搭桥。例如用户问「近 90 天下单的客户」,模型第一段可能只召回「客户」和「订单」,但两者实际要通过「订单明细」甚至「订单商品」间接关联。
于是我们在表路由后加了一个 闭合(closure) 步骤:拿到召回表集合后,基于预生成的「表关系图」,用 BFS / 最短路径 自动把缺失的中间表补进集合,保证路由结果在关系上「自洽」。

flowchart LR
A[第一段召回: 客户, 订单] --> B[查关系图]
B --> C{客户<->订单直接关联?}
C -->|否| D[经中间表: 订单明细]
D --> E[补入: 订单明细]
C -->|是| F[无需补表]
E --> G[最终表集合: 客户,订单,订单明细]
F --> G
5.4 两段式完整时序
完整的「用户提问 → 结构化 → 执行」时序如下(标注了每一步的兜底/重试):

sequenceDiagram
autonumber
participant U as 用户
participant I as 意图服务
participant L1 as LLM 第一段(路由)
participant C as 路由闭合
participant L2 as LLM 第二段(计划)
participant V as 校验/修复/重试
participant E as 查询引擎
U->>I: 自然语言提问
I->>L1: 表名索引 + 关系图(含日期锚点)
L1-->>I: {"tables":["商品","订单"]}
I->>C: 对召回集合做路径闭包
C-->>I: 补中间表后的最终表集合
I->>L2: 注入选中表档案(精简提示词)
L2-->>I: 查询计划 JSON
I->>V: 解析JSON / 校验字段与表是否合法
V-->>I: 失败→修复JSON→带错误现场重试
I-->>E: 通过校验的查询计划
E-->>U: 结果
六、与大模型缠斗的过程:十个坑和它们的解法
如果说第一代的技术主旋律是「架构权衡」,那第二代的主题就是「和概率生成做纠错」。这一章集中复盘我们踩过的坑和对应的工程化解法。
6.1 JSON 不稳定:全角符号与尾逗号
坑:大模型输出的 JSON 时常携带全角标点(: , {)、或结构末尾多一个逗号,导致 JSON.parse 直接崩。
解法:在解析前增加一个 _repairJson:把全角标点转半角、去掉字符串外的尾逗号。这能静默修复掉很多小毛病,把「偶发失败」挡在解析的最前面。
// 示意:先用宽松手段修复,不行再进入重试路径
function repairJson(raw) {
return raw
.replace(/[\uFF0C\uFF1B\uFF1A]/g, (c) => ({
'\uFF0C': ',', '\uFF1B': ';', '\uFF1A': ':',
}[c]))
.replace(/,\s*([}\]])/g, '$1'); // 去尾逗号
}
6.2 修不好就重试:带上错误现场
坑:修复后仍然解析失败,或者字段非法。
解法:不再盲目整体重试,而是把错误位置 + 前后 40 字上下文回传给大模型,让它「看着现场改」。带现场的重试比无脑重说一遍的命中率高得多。
6.3 相对时间漂移:日期锚点 + 白名单
坑:用户说「近 90 天」,模型可能把它解析成错误的起始日期,或干脆编造一个不存在的时间 token(如 last_30_days),导致查错范围。
解法(两招并用):
- 日期锚点:调用大模型前,在用户消息前注入
[当前系统日期:YYYY-MM-DD],让模型能正确地算相对日期; - token 白名单:所有相对时间 token 必须先过白名单校验;验证到「编造出来的 token」就刻意抛错,反馈给模型要求改用绝对日期,而不是悄悄默认成「今天」——悄悄默认才是真正的隐患。
6.4 KV 双向转换:WHERE 侧与结果侧两面镜像
坑:枚举/人员/选择类字段库里存的是数字 K(如 上海≈25),但用户说的是中文 V(上海),且查询(WHERE)和结果展示(结果侧)两个方向都要转,方向正好相反。
解法:做成双向转换,并且规则完全对称:
| 方向 | 目的 | 手段 |
|---|---|---|
| WHERE 侧 V→K | 把用户/计划里的中文筛选项转成库里的存储值再打库 | 走字典/名称接口取到 {key, value},把 V 映射成 K |
| 结果侧 K→V | 把库里返回的数字/ID 翻译成用户看得懂的展示值 | 主表取数后用字典翻译枚举/人员/选择ID,多选按逗号拆分、用「、」重新拼接 |
这个转换是查询正确性和展示可读性最后的护城河,做了以后,细节瑕疵(如个别值没映射)就地保留原值并打日志,不阻塞整条查询。
6.5 主表取数要「原始值」再翻译
坑:如果直接取翻译后的展示值回来做过滤,会把 K→V 和 V→K 搞乱。
解法:主表取数要求带原始存储值(接口 flag=1),返回后才能统一在结果侧做 K→V 翻译。取数用原值,展示才做二次翻译,方向清晰不打架。
6.6 「id」字段:能聚合、不能筛选
坑:为了让模型能做「计数」类统计,把所有表都注入了 id 字段,但模型可能误把它当普通筛选条件用,造成错误查询。
解法:在档案里对 id 明确标注 「仅用于聚合 count,不可作为筛选条件」,并把这条规则也写进人设,从源头约束。
6.7 单占位符约束:一次档案双注入的教训
坑:提示词模板里曾出现两个替换占位符指向同一份表档案,结果档案被双份注入,token 直接翻倍(曾观察到 2.7 万+ token 的超大提示词),既浪费又加重漂移。
解法:收敛模板,全篇只保留文末一个档案占位符,从根上杜绝双份注入。token 用量显著回落。
6.8 把人设和档案掰开:一致性优先
坑:如果档案内联在人设里,每次加表都要重排人设,且不同入口容易不一致。
解法:人设常量、档案动态注入。Bot 人设只写固定的行为规则与输出约束,表档案作为每次请求的变量注入;加表只改档案、不改人设,天然保持一致。
6.9 别让超时变成谜语
坑:深层思考模型单次出计划可能要几十秒甚至更久,普通用户等得不耐烦;且超时/网络错误如果不处理,就是一段看不懂的报错。
解法:给请求设置较长且可调的超时时间(思考模型需要在 60~120 秒量级),并把超时、网络错误统一包装成中文、清晰、常驻(不随操作消失)的提示,告诉用户「正在等模型,或已超时」,而不是甩一段 stack。
6.10 区分两类失败:语法错误 vs 档案校验失败
坑:初版把所有失败都叫「解析失败」,用户和模型都分不清问题到底出在「JSON 格式」还是「表/字段本身不存在」,纠偏没有方向。
解法:把错误明确分成两类——「JSON 语法错误」 与 「表档案校验失败」,分别走不同的提示词反馈给模型,纠错更有靶心。
七、效果与价值
把两代做下来,简单算一笔账:
- 第一代把「复杂多表查询」从「要写 SQL」降级成「点选配置」,能力到了,但对多数人门槛仍在;
- 第二代把「点选配置」再降级成「说一句话」。实测下来,至少 80% 的多表复合查询,通过自然语言描述就能直接跑通。
而这 80% 还只是「存量用户」口径下的统计。如果把 LLM 交互带来的获客增量算进去,这个功能的潜在普惠用户可能提升 5~10 倍——因为门槛被拉平,普通用户第一次敢用了;而且随着口碑扩散,数据会呈现扩散式增长。
从项目价值的角度,我们认为第二代是一次成功且很有意义的升级探索:它没有推翻第一代的引擎,而是在一个已验证的底座上,用 LLM 替换了「门槛最高、价值最薄」的交互层,把一项「高手专属」能力变成了「人人可用」能力——这正是「以降门槛换取普惠」的典型样本。
八、从点选到一句话:低代码/无代码的时代命运
如果只把这两代方案放在「一个查询功能」的尺度里看,它只是一次成功的升级。但把「点选配置」和「一句话查询」这两类交互方式放到更大的时间轴上,它恰好构成了过去几年低代码/无代码浪潮与今天AI 浪潮的一个缩影。
8.1 两种交互,两个时代
先把术语对齐:
- 点选配置,就是低代码/无代码的交互方式:通过表单、画布、拖拽、点选,把「能力」一块块搭出来;
- 一句话查询,就是经典的大模型/AI 交互方式:用自然语言表达「我要什么」,由模型翻译成可执行的结构化逻辑。
前者强调「配置」,后者强调「表达」。表面看只是操作方式不同,本质上是把人的心智负担,从「理解机器逻辑」转移回了「用人的语言说话」。
8.2 为什么开发者判定低代码/无代码没有未来
最近很多开发者唱衰低代码/无代码,理由并不是「能力不够」,而恰恰是它的交互方式注定的。归纳下来有三点:
| 症结 | 说明 |
|---|---|
| 受众错位 | 低代码/无代码严格说不是给终端用户用的,它是帮开发者/搭建者快速实现能力的工具。一旦交给「不懂表结构的普通用户」,仍然要求对方理解领域模型,门槛并没有消失。 |
| 不可自动复制 | 点选操作本质是「人手工点击界面」,而很多界面级逻辑都硬编码在前端,很难像普通 API 那样被 Ctrl/Cmd 或 MCP 这类标准工具抽象、接管、批量复制。 |
| 重度依赖人工 | 哪怕你脑子里想得再快再清晰,也必须一步不落地点一遍。这种「人肉点按」无法随需求扩张而自动化,也扛不住规模化复制。 |
一句话:低代码/无代码把「写代码」降级成了「点界面」,但「点界面」这件事本身,恰恰是 AI 最难以高效复制的那种劳动。
mindmap
root(为什么点选式难以被 AI 复制)
受众错位
不是给终端用户
仍要懂领域模型
不可自动复制
界面逻辑硬编码在前端
难以被 MCP/Ctrl 抽象
重度依赖人工点击
脑快也需一步不落
无法规模化复制
8.3 在 AI 编程的时代,它退守到哪
当 AI 编程(Vibe Coding)可以用自然语言直接生成、修改、调用代码时,低代码/无代码「降低编码门槛」的价值几乎被覆盖。绝大多数过去非用低代码/无代码不可的场景,现在都能被 AI 编程彻底颠覆。
它真正残留的空间,大概率只有很小范围、做配置升级/配置优化的局部——而且即便如此,也更可能以「被 AI 驱动」的方式存在,而不是以「人手工点选」的方式存在。
8.4 我们的案例恰恰补上了最关键的证据
有意思的地方在于:行业里这场争论大多围绕开发者展开——低代码/无代码对开发者失去了吸引力。而我们的案例发生在终端用户层:
即便不是开发者、只是普通业务用户,「点选配置」和「一句话查询」之间的差距依然大到天壤之别。
第一代把 SQL 降级成点选,对「非开发者」门槛依然高;第二代用一句话平掉门槛,才真正普惠了终端用户。这补上了两件关键证据:
- 低代码/无代码在最贴近业务的一层——终端用户这里,同样无力,而不只是对开发者无力;
- 大模型的「一句话交互」不是一个领域的小改良,而是一种覆盖范围更广、更强的交互范式换代。
所以,如果给这两代方案找一个时代注脚,它可以浓缩成一句话:
低代码/无代码改变了「开发者怎么搭」,而大模型改变了「每个人怎么用」——前者是工具升级,后者是交互范式的换代,也就是技术的时代进步。
九、总结与展望
把第 8 章放回工程语境,回看这六个字:「拆替代、换偏门、再加脑」。
- 第一代(点选式) 回答了「多表查询怎么在 SaaS 多租户下体面地做」——用 IN 管道拆掉 JOIN,用表档案做唯一事实来源。
- 第二代(AI 式) 回答了「怎么让它人人可用」——复用成熟引擎,用自然语言做输入,用两段式路由解决扩展性与漂移。
- 贯穿始终 的是一条工程态度:永远不要把 LLM 的一次输出当可靠输入,系统要在其周围建起 校验、修复、重试、闭环 的护栏。
展望上,我们下一步会往三个方向走:支持更多表的更广业务域、沉淀高频查询为「常用查询」注入、探索让 LLM 不只是翻译查询、还能辅助解释结果。而这些,都已站在两代方案共同打下的地基上。
如果你也在做低代码平台的查询、或正想把 LLM 接入某个成熟功能,希望本文的「两个阶段、两次架构决策、十个工程坑」能给你一个可复制的心智模型:
先问自己:要新增的是「引擎」还是「入口」?如果想降的是门槛,那大概率是后者——复用你的成熟底座,只把交互层交给大模型。
文中涉及的内部表名、字段号、部署细节均已脱敏处理;所有业务均为通用中性命名。