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 引擎解析:
识别主体“员工”为实体。
“女”为常数词,与“性别”维匹配,过滤员工表。
“订单金额总和大于 20 万元”是一个聚合条件。识别出“订单金额”来自订单表,“总和”是聚合词,“大于 20 万元”是比较条件。由于订单表与员工表通过“销售”字段关联,引擎识别出这是一个基于子表聚合结果的过滤。
"大于 20 万元" 这个比较条件,NLQ 引擎会识别 "万元" 为量词,并根据词典中定义的换算系数(1 万元 =10000)自动进行单位转换。"20 万元" 在生成 MQL 时将被转换为 20*10000,而不是直接使用数值 200000,体现了量词保持业务表达的自然性。
生成 MQL:此 MQL 会表达为:从员工表中查询,其条件为子表(订单表)中对应销售员的订单金额总和大于 200000
SELECT 性别 ,…,ORDERS.sum(订单金额) AS 订单金额总和
FROM EMPLOYEE
WHERE (性别 ='女')
JOIN ORDERS
HAVING 订单金额总和 >20*10000
例 4:多表汇总与复杂指标计算
文本:各省的员工数、产品数和大订单数
NLQ 引擎解析:
识别 "各省" 为维词,作为统一的分组维度。
"员工数"、"产品数" 被识别为基于 EMPLOYEE 表和 PRODUCT 表的计数聚合。
"大订单数" 是一复杂指标,该指标采用 SPL 语法定义,用于计算订单金额超过最大订单金额 50% 的订单数量。
引擎识别出这是一个多表同维汇总与复杂指标结合的查询,需要按照 "省份" 维度分别从员工表、产品表和订单表进行聚合计算,其中订单表需要调用 SPL 指标函数进行复杂计算。
生成 MQL:此 MQL 会表达为按省份维度,分别统计员工数量、产品数量,并调用大订单数指标进行计算。
SELECT EMPLOYEE.count(雇员编码) AS 员工数,
PRODUCT.count(产品编码) AS 产品数,
ORDERS. 大订单数 () AS 大订单数
ON 省份
FROM EMPLOYEE BY 省份
JOIN PRODUCT BY 省份
JOIN ORDERS BY 省份
指标定义:
大订单数指标采用 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 架构。
