Text2SQL 破局便捷的技术解析之三:NLQ 词典与准确性
在本系列的前两篇文章(Text2SQL 破局技术解析之一:规范文本与灵活性 和 Text2SQL 破局技术解析之二:MQL 达成与复杂性)中剖析了 Text2SQL 领域面临的 "灵活性、准确性与查询复杂性" 三难困境,并提出了润乾 NLQ 的破局架构:引入 LLM 处理自然语言的多样性来保障灵活性;通过人类可读的规范文本来消除 LLM 的幻觉问题,确保准确性;再用 MQL、DQL、SPL 的分工协作来支撑查询复杂性。
这一架构的优势在于实施可行性。引入规范文本和词典机制,不需要投入高昂成本进行 Fine-tuning 或构建 RAG 知识库,更无需组建专业的 AI 工艺团队,降低了实施 Text2SQL 的技术门槛。
那么,架构中的 NLQ 规则引擎,是如何能像“理解了一门语言”一样,将仍有相当自由程度的规范文本准确地转换为语法严格的 MQL?就像前篇所言,这个 NLQ 已经相当于实现了一个小语言模型(SLM)。这就是本篇将要解析的NLQ 词典,它是 NLQ 引擎的“大脑”与“规则手册”,支撑整个架构完成准确性。
NLQ 词典:语义的映射基础
一个结构化的业务 - 数据映射知识库,定义了业务语言中每个“词”在资料世界中身份、行为逻辑和关联关系。就是NLQ 词典
基本概念:构筑查询语义的积木
NLQ 词典的构建围绕以下几个概念展开,它们共同构成了从自然语言到 MQL 的转换路径:
表与实体:表对应数据库中的物理表。实体是表的业务化视图,本质上是表的子集,同一个物理表可以对应多个不同的实体。例如,“订单”是一个表,除了订单实体外,还可以有“新订单”(本年订单)实体,附带了 Year(签单日期)=Year(Now()) 的过滤逻辑。每个实体可以设置不同的字段组合和过滤条件,满足不同的业务查询需求。
宏字段:是查询的最小语义单元,可以映射到物理表的字段(如“订单金额”),并有更多的扩展性:
计算字段:通过已有字段计算得出,如通过“身高”和“体重”计算“BMI 指数”:EMPLOYEE.WEIGHT*10000.0/EMPLOYEE.HEIGHT/EMPLOYEE.HEIGHT。
外键字段:依据订单表中的“客户 ID”关联到客户表,从而引入“客户名称”、“客户城市”等字段,这里许可借助 DQL 的外键属性化思路,实现了跨表信息查询。
指标:通过表达式定义的聚合度量。有些复杂的计算指标会采用 SPL 语法实现 SQL 不擅长的计算。比如月活,留存率,股票连涨天数等。指标为困难业务场景提供了强大的计算能力。
字段簇与簇词:这是 NLQ 词典的特色,用于处理业务中常见的组合信息与语义歧义。
字段簇是一组在业务上紧密相关的宏字段的集合。例如,为订单表定义“发货”簇,包含“发货城市”、“发货日期”、“发货省份”;同时定义“收货”簇,包含“收货城市”、“收货日期”、“收货省份”。
簇词是字段簇的业务别名,如“发货”、“收货”。当用户在规范文本中使用簇词时,如“发货 城市 日期”,NLQ 引擎会优先在该簇词对应的字段簇内寻找“城市”和“日期”字段。这一机制避免了全局搜索可能带来的歧义,例如,能区分用户要的是“发货日期”而非“签单日期”。
举例:查询“订单编码,发货 城市 日期,收货 城市 日期”,引擎能准确识别出四个不同的字段,结果列标题也会清晰显示为“发货城市”、“发货日期”、“收货城市”、“收货日期”。
维、维词与常数词:用于描述数据的分析视角和构建过滤条件,实现智能过滤。
维定义了分析视角,如“城市”、“省份”、“年月”、“性别”。
维词是维的业务名称。
常数词与维绑定,将业务语言中的值映射到底层数据存储。例如,将“北京”、“上海”与“城市”维绑定,其“真实值”对应数据库中的城市编码(如 30101)。用户输入“籍贯 北京 的雇员”时,引擎能理解为 HOMECITY=30101,而用户无需知晓底层编码。
举例:查询“男雇员”或“直辖市 客户”,尽管没有指定字段,引擎也能经过常数词“男”、“直辖市”自动关联到“性别”、“城市类型”等维,并找到表中与之匹配的字段进行过滤。
特色词型:应对灵活表达的武器库
为了覆盖多样化的自然语言表达,NLQ 词典配备了多种特色词型:
无效词:用于过滤掉查询中的口语化虚词和语气词,如“请帮我查一下”、“有哪些”、“记录”等,使引擎能聚焦于有效信息。
宏词:用于处理口语化的业务概念,将其转换为规范的查询逻辑。例如,可以将“已售罄”定义为宏词,其背后对应的逻辑是“库存量 <= 0”。当用户查询“已售罄的商品”时,NLQ 引擎会将其转换为规范的过滤条件。
动词:用于建立更繁琐的过滤逻辑,特别是涉及多个字段簇时。例如,定义动词“发往”,可以将其左侧条件关联到“发货”簇,右侧条件关联到“收货”簇。这使得“北京 发往 青岛 的订单”能被准确解析为“发货城市 = 北京 且 收货城市 = 青岛”。动词“入职 超过 10 年”则能将“超过 10 年”映射到“雇用年数”这个计算字段。
量词:用于处理带有单位的数值,自动进行单位换算。例如,定义量词 "万元",其换算系数为 10000。当用户查询 "金额大于 20 万元" 时,引擎会自动将 "20 万元" 转换为 200000 进行数值比较。用户在表达数值时可以使用更符合业务习惯的单位,而无需关心底层数据的存储形式。
比较词与连词:大于、小于、等于等比较词定义了过滤关系;且、或等连词则明确了多个过滤条件间的逻辑关系,从而支持“年龄大于 40 且 性别 男”这样的复杂筛选。
实例解析:从文本到 MQL 的转换
下面用几个示例,理解词典如何驱动 MQL 生成。
例 1:基础过滤查询
文本:姓名为李芳的职务、出生日期和年龄
NLQ 引擎解析:
分词:姓名,李芳,职务,出生日期,年龄。
识别:“姓名”、“职务”、“出生日期”、“年龄”被识别为字段词,确定它们来自员工实体。
“李芳”被识别为常数,由于前一个词是字段词“姓名”,引擎将其构建为过滤条件姓名 ='李芳'。
生成 MQL:SELECT 姓名, 职务, 出生日期, 年龄 FROM EMPLOYEE WHERE 姓名 ='李芳'
例 2:字段簇与动词消除歧义
文本:查询北京发往青岛的订单
NLQ 引擎解析:
分词:北京,发往,青岛,订单。
识别:“订单”被识别为实体。
“发往”被识别为动词簇词。查询动词定义,知其关联“发货”和“收货”两个字段簇。
“北京”在动词左侧,被分配给“发货”簇中的“城市”字段。
“青岛”在动词右侧,被分配给“收货”簇中的“城市”字段。
生成 MQL:SELECT ... FROM ORDERS WHERE (发货城市 =30101) AND (收货城市 =20201)(其中代码由常数词映射而来)
例 3:复杂聚合与子查询
文本:订单金额总和大于 20 万元的女员工
NLQ 引擎解析:
SELECT 性别 ,…,ORDERS.sum(订单金额) AS 订单金额总和
FROM EMPLOYEE
WHERE (性别 ='女')
JOIN ORDERS
HAVING 订单金额总和 >20*10000识别主体“员工”为实体。
“女”为常数词,与“性别”维匹配,过滤员工表。
“订单金额总和大于 20 万元”是一个聚合条件。识别出“订单金额”来自订单表,“总和”是聚合词,“大于 20 万元”是比较条件。由于订单表与员工表通过“销售”字段关联,引擎识别出这是一个基于子表聚合结果的过滤。
"大于 20 万元" 这个比较条件,NLQ 引擎会识别 "万元" 为量词,并根据词典中定义的换算系数(1 万元 =10000)自动进行单位转换。"20 万元" 在生成 MQL 时将被转换为 20*10000,而不是直接使用数值 200000,体现了量词保持业务表达的自然性。
生成 MQL:此 MQL 会表达为:从员工表中查询,其条件为子表(订单表)中对应销售员的订单金额总和大于 200000
例 4:多表汇总与复杂指标计算
文本:各省的员工数、产品数和大订单数
NLQ 引擎解析:
SELECT EMPLOYEE.count(雇员编码) AS 员工数,
PRODUCT.count(产品编码) AS 产品数,
ORDERS. 大订单数 () AS 大订单数
ON 省份
FROM EMPLOYEE BY 省份
JOIN PRODUCT BY 省份
JOIN ORDERS BY 省份识别 "各省" 为维词,作为统一的分组维度。
"员工数"、"产品数" 被识别为基于 EMPLOYEE 表和 PRODUCT 表的计数聚合。
"大订单数" 是一复杂指标,该指标采用 SPL 语法定义,用于计算订单金额超过最大订单金额 50% 的订单数量。
引擎识别出这是一个多表同维汇总与复杂指标结合的查询,需要按照 "省份" 维度分别从员工表、产品表和订单表进行聚合计算,其中订单表需要调用 SPL 指标函数进行繁琐计算。
生成 MQL:此 MQL 会表达为按省份维度,分别统计员工数量、产品数量,并调用大订单数指标进行计算。
指标定义:
大订单数指标采用 SPL 语法定义,实现 SQL 难以直接表达的复杂计算: 大订单数 = (x=?1.max( 订单金额)/2, ?1.count(订单金额 >=x))
该例子展示了 NLQ 如何同时处理多表关联(员工表、产品表、订单表按省份关联)、基础聚合(计数统计)和繁琐指标计算(基于相对阈值的大订单判定)。
解析过程是基于词典规则的、确定性的通过,不用“再训练”,每一步可追溯、可解释、可调试。当出现解析错误或无法解析的查询时,能够在规则框架下快速定位问题,是缺少词条、字段簇配置不当,还是维度映射不完整,当然也有可能是引擎的 BUG。这种可解释性将获得持续优化的能力,通过补充词典配置等操作即可修复问题。相反, LLM 过于复杂而失去可解释性,用它直接生成 SQL 或 MQL 也就缺乏可控性:生成失败时难以诊断根源,即使投入大量成本进行再训练,也难以预测和保证改进效果。
词典的构建、管理与工程实践
词典构建是实现准确性的核心,润乾 NLQ 提供了可视化的设计器来拥护这一过程。
元数据导入:从 DQL 语义层自动获取表、字段、维度和关联关系等基础信息,为词典奠定内容基础。
业务化封装:
定义字段词:将“SALARY”改为“薪水”,将“PRODUCT_NAME”改为“产品名称”。
创建字段簇:根据业务逻辑,将字段分组,如创建“发货信息”、“收货信息”、“客户信息”等簇。
设置实体:为同一张表创建不同业务视图,如“员工基础信息”、“员工财务信息”等,并部署不同的字段簇。
配置词汇表:维护维词、常数词、比较词、动词等。
持续测试与优化:借助设计器的“搜索实验”功能,使用真实例句进行测试,查看解析过程与结果,发现并修复词典配置的边界案例,迭代优化,逐步提升解析准确率。
这个过程由懂业务的开发人员实施,工艺门槛远低于 AI 模型的训练与调优,确保了 NLQ 方案的普适性和可落地性。
将 LLM 的泛化能力限定在 "文本转写" 范畴,并将企业特有的知识固化为可管理、可优化的词典规则,构建一条通往实用可靠的自然语言素材查询的工程路径。这种基于词典的规则引擎方案,使 Text2SQL 具备了可实施、可维护、可信任的企业级应用特性。
至此,润乾 NLQ 技术解析系列三部曲已完结。大家从“规范文本”破局,用“MQL”构建复杂性,继而用“NLQ 词典”保证准确性。三者环环相扣,共同构成了一个同时满足灵活性、准确性、复杂性的 Text2SQL 架构。