Clone
49
Home
Jun Zhang edited this page 2024-06-19 14:51:08 +08:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

总体思路

通过自然语言界面Natural Language Interface访问数据是数据库上古大神们就开始畅想的情境在学术界也一直是专门的研究方向。对我们影响比较大的两篇论文是IBM在2016年发表的ATHENA和谷歌在2017年发表的Analyza但它是纯基于规则的工程实现。2017年之后随着大规模数据集Seq2SQLSpider发布基于AI模型的解决方案如雨后春笋般涌现从seq2seq到slot filling从schema linking到intermediate representation各种奇淫技巧不一而足。直到ChatGPT横空出世基于prompting来实现Text-to-SQL几乎成了大家的共识。

在项目初期我们也曾尝试通过prompt engineering让ChatGPT直接生成SQL但经过多轮迭代在稳定性和可靠性方面始终无法达到生产可用的期望总的来说有如下问题

语义复杂

  • 如果涉及多表关联、运算公式、时间转换等复杂语义情况SQL生成难度变高LLM输出可靠性会显著降低。
  • 涉及指标计算的场景,如果依赖用户问询来描述,无法保证口径的一致性与确定性。

输出幻觉

  • 为了让LLM理解schema需要将所有字段的名称和描述作为context输入如果schema字段数量多可能会超过context window限制。因此基数过大的字段取值一般不会全部放入context使得LLM无法识别到专有领域的术语。即便将schema全部输入且告知LLM不要随意猜测仍然有一定几率会预测出错误的字段甚至可能幻觉出不存在的字段。
  • 相同的语义,不同的语言表达,可能会导致大相径庭的输出结果,无法保证一致性。

推理效率

  • 当前LLM推理速度还处在10秒+量级,再加上底层数据查询的耗时,同时还无法像纯文本那样的流式输出,非常考验用户的耐心。
  • 当前LLM主流是按token计费如果所有查询都需要走LLMMaaS成本会随着查询量线性增长。

我们逐渐意识到LLM只是看作是意图识别和文本生成的引擎它还需要其他的组件来配套才构成一个完整的系统解决方案。可与此类比的是传统OLAP引擎需要有transformation层的清洗、关联、聚合等建模步骤来配套才能形成高效稳定的数据服务。

因此在SuperSonic项目中我们围绕LLM引入与之配套的工程化组件来增强语义解析和SQL生成的可靠性。架构图里黄色背景块就是引入的配套组件下面的篇幅将展开介绍设计思考。

supersonic_components

系统设计

Semantic Layer

当AI领域的LLM满级输出吸走大部份聚光灯的时候BI领域也有一位召唤师在猥琐发育——它就是Semantic Layer也有称为是Headless BI或者Metric Store。所以它的核心价值是什么我们可以用两个拟人化的角色来类比

  • 翻译官:将技术名词(表/字段)翻译成业务术语(维度/指标/标签),便于业务用户理解。
  • 大管家:将技术口径(关联关系/运算公式)统一化、精细化地管理起来,便于查帐比对,消除口径混乱。

两类角色的存在都可以提升数据服务质量增强业务对数据的理解和信任。而随着企业内数据规模和使用场景的不断扩展对于数据的组织能力和传播能力越来越成为数据驱动落地的关键因素这似乎跟企业本身的发展是一个道理所以semantic layer得到越来越多的关注与认可。

接下来的问题semantic layer和LLM又有什么联系我们还是从它的两类角色上来分析

  • 翻译官将技术名词翻译成更有意义的业务术语便于业务用户理解的同时同样能增强LLM对数据的语义理解。
  • 大管家将技术口径封装起来LLM不需要考虑关联关系和运算公式生成复杂度极大地被简化。

因此既然semantic layer可以帮助人更好地把数据用起来为什么不顺便帮一下LLM举手之劳而已。

Schema Mapper

前文有提到LLM的token限制问题主要是因为想要暴力求解将全部字段的名称和取值一股脑都丢给LLM。直观分析可以在前置环节增加映射机制只保留能在输入文本中映射上的字段可以极大地减少token使用即便不超过限制也能节省推理成本。这就是Schema Mapper组件的由来。

当前的设计方案是定期从semantic model中抽取名称、别名、取值来构建词典形成内部的knowledge base。查询解析阶段先对输入文本分词再采用n-gram词典探测的机制。经过前期调研中文NLP框架HanLP相对成熟,可以满足需要。

Schema mapper会将所有达到匹配阈值要求的schema项及其相似度得分一并保存到info对象传递给后续semantic parsing环节引用最终会由parser挑选输入给LLM。

与此同时schema mapper可以定制扩展并通过Java SPI配置的方式替换或补充SuperSonic的默认实现。

Semantic Corrector

针对前文提到的推测错误和幻觉问题一个方向是对prompt不断试验打磨但现阶段仍然是玄学成分居多。另一个方向是在LLM输出的后置环节增加修正机制将明显错误的表达予以修复。这就是Semantic Corrector组件的由来。

当前的设计方案是从LLM生成的SQL中解析出表、字段、取值等名词逐个检查合法性将不合法名词通过类似schema mapping的方式去knowledge base尝试找到正确的匹配。比如LLM可能将取值映射到了错误的字段通过corrector尝试找到正确的字段映射并改写SQL。

与此同时semantic corrector可以定制扩展并通过Java SPI配置的方式替换或补充SuperSonic的默认实现。

Rule-based Parser

针对前文提到的效率问题除了做时间的朋友等待LLM进化突破之外还可以想办法在应用层规避。比如对于一些简单的问题输入可以尝试基于规则来做语义解析这也是从Google Analyza论文里带来的启发。这就是Rule-based Parser的由来。

当前的设计方案是,通过经验整理一份表单,如下表所示,明确列举每类语义对象(指标/维度/取值/时间/算子的组合会映射到哪一种查询意图。Rule-based parser再根据schema mapping的结果从表单中查到对应的查询意图这个有点类似slot filling的思路。

rule-based parser slot-filling

引入Semantic Parser的抽象分别有rule-based和LLM-based的实现。输入问题首先经过rule-based parser如果有查询意图命中则根据启发性算法来决定是否可以跳过LLM-based parser。当前启发性算法会根据schema mapping命中的词汇总长度除以问题总长度来判断超过配置的阈值则认为规则可以满足需要决定跳过LLM如果跳过那么提升效率的目的就达到了。

与此同时semantic parser可以定制扩展并通过Java SPI配置的方式替换或补充SuperSonic的默认实现也可以选择完全去掉rule-based parser配置。

Chat Plugin

SuperSonic的主链路主要涉及两个步骤1、LLM解析语义生成逻辑SQL提交semantic layer2、semantic layer生成物理SQL提交底层OLAP引擎执行。但是既然已经有了统一的ChatBI界面是否能兼容其他的场景比如文档知识库、数据看板它们的执行过程不同于SuperSonic主链路。这就是Chat Plugin组件的由来。

当前的设计方案是三方插件可以通过WebPage将直接IFrame嵌入展现或者WebServiceHTTP调用获取返回两种方式来注册后续会当作是一种工具来使用。当用户输入问题时如何选择出合适的插件工具经典的方式有以下两种

  • 向量召回插件在注册时可以设定一些示例问题提前通过LLM向量化存储到向量数据库。解析输入问题时将输入文本同样经过LLM向量化后从向量数据库根据相似度来召回通过最匹配的示例问题找到相对应的插件
  • 函数调用插件在注册时可以配置函数名称和描述利用LLM的function call能力来直接根据输入问题选择函数并找到对应的插件。

两种方式可以结合使用,优先走向量召回流程,如果相似度没有达到配置的阈值,则继续用函数调用来选择。