
SuperSonic Chat BI 与 Headless BI 技术全景一、项目定位与效果展示为什么不是给数据库套一层聊天框1.1 Chat BI 与 Headless BI 解决的是两类问题1.2 固定提交中的能力矩阵二、系统架构与主调用链一次问题如何走到数据库2.1 模块边界与技术栈2.2 /api/chat/query/ 的真实调用顺序2.3 翻译、权限和执行并不是一个动作三、语义层与 S2SQL把业务口径放在模型前面3.1 知识库和 Schema Mapper 先缩小搜索空间3.2 S2SQL 是语义查询不是直接绑定物理表的最终 SQL3.3 规则与 LLM 是协作关系四、Chat 编排、记忆与权限从“能回答”到“可治理”4.1 多轮改写、动态样例和 Memory4.2 Plugin 扩展非结构化问答4.3 三级权限如何进入查询五、安装、构建与第一个可复现闭环5.1 最快体验与版本固定5.2 不要直接带着示例密码上线5.3 建立一个能定位问题的验收用例六、可靠性、安全与许可边界6.1 生成式查询需要多层防线6.2 性能瓶颈不只在大模型6.3 许可证不是标准 Apache 2.0 的简单复述七、适用场景与总结参考资料很多“对话式 BI”演示只完成了自然语言转 SQL却没有解决指标口径、模型关系、数据权限、查询执行和结果解释。SuperSonic 的核心价值正是把这些工程问题放进同一条链路用户面对的是问答界面系统内部依赖的却是一层可管理、可复用的语义模型。uperSonic 将 Chat BI 与 Headless BI 语义层结合用指标、维度、实体和数据集承接业务口径再通过 Schema Mapping、规则/LLM 解析、可配置的 S2SQL 修正、物理 SQL 翻译和权限注入完成自然语言问数。本文基于固定提交拆解真实调用链、插件与记忆机制、部署方法、安全边界和适用场景。GitHub仓库https://github.com/cmyk-labs/supersonic.git(如果这个仓库对你有帮助欢迎在 GitHub 上点一个 Star ⭐ 支持一下。)官方GitHub仓库https://github.com/tencentmusic/supersonic官方Wikihttps://github.com/tencentmusic/supersonic/wiki一、项目定位与效果展示为什么不是给数据库套一层聊天框1.1 Chat BI 与 Headless BI 解决的是两类问题SuperSonic 把产品分成两个相互依赖的视角Chat BI面向最终用户负责自然语言问题、候选解析、多轮对话、结果表格/图表、解释和推荐Headless BI面向数据开发和平台集成负责数据源、模型、指标、维度、实体、标签、数据集、SQL 翻译和权限语义层是两者之间的契约让“销售额”“活跃用户”“本月”这类业务概念先映射到统一口径再生成底层数据库能执行的 SQL。官方 README 强调“不需要复制或修改原始数据”。从固定提交的实现看这里的准确含义是SuperSonic 保存语义元数据和系统配置查询时通过 JDBC/适配器访问已有数据源它不是把企业明细数据重新导入自己的分析仓库。不过查询结果、问答轨迹、缓存和 Text2SQL 记忆仍会进入系统自己的运行边界不能把“不复制原表”误解为“系统不处理业务数据”。下图展示项目理念、组件和交互形态。语义映射、解析、修正与翻译组件从自然语言提问到查询结果的演示1.2 固定提交中的能力矩阵下面只列出可以在当前源码或配置中定位到实现入口的能力。它比 README 功能清单更适合作为选型边界。能力当前实现证据结论自然语言问数NL2SQLParser、HeadlessChatWorkflowEngine、规则与 LLM Parser源码已确认实际准确率依赖语义模型、样例和所选模型语义层查询指标/维度模型、S2SQL、DefaultSemanticTranslator、数据库适配器源码已确认是项目核心而非附属功能规则优先解析STRICT、MODERATE、LOOSE 等 Mapping 模式规则解析失败后再扩大范围源码已确认可减少所有问题都直接交给 LLM 的成本多轮对话基于上一次成功查询、映射结果和历史 SQL 改写问题源码已确认但当前多轮改写应用默认enable(false)需配置启用Chat Plugin自然语言匹配插件插件执行器与管理接口源码已确认插件安全性取决于具体配置和第三方服务Chat Memory成功的 LLM SQL 查询生成待审记忆动态召回 Few-shot 示例源码已确认记忆质量需要审核治理数据权限模型可见性、高敏字段权限、行过滤条件注入源码已确认固定源码的 standalone 配置已启用认证但生产仍须确认最终生效配置与授权多数据源MySQL、PostgreSQL、ClickHouse、StarRocks、Presto、Trino、Kyuubi 等适配器源码存在适配器各版本兼容性需要连接实测结果后处理文本格式化、指标/维度推荐、比率计算、LLM 数据解读源码已确认生成式解释仍需防止误读这张表也说明 SuperSonic 更接近“语义查询平台 Chat BI 应用”不是通用数据仓库、ETL 工具或无语义约束的 Text2SQL Demo。二、系统架构与主调用链一次问题如何走到数据库2.1 模块边界与技术栈固定提交是一个 Maven 多模块项目根pom.xml声明了common、auth、chat、launchers和headless五个模块。当前源码要求 Java 21父工程使用 Spring Boot 3.3.9这与网上仍能搜到的 Java 11、Spring Boot 2.7.x 旧教程不同构建时应以固定提交的 POM 为准。supersonic/ ├── webapp/ # Chat BI 与 Headless BI 管理前端 ├── chat/ │ ├── api/ # Chat 请求、响应和公共模型 │ └── server/ # Parser、Executor、Processor、Plugin、Memory ├── headless/ │ ├── api/ # 语义层查询协议与 Schema 对象 │ ├── chat/ # Mapper、Parser、Corrector、SemanticQuery │ ├── core/ # 语义翻译、优化器、数据库适配器 │ └── server/ # 语义层服务、权限切面、查询执行和 REST API ├── auth/ # 认证、授权资源与用户体系 ├── common/ # SQL、配置、LLM、Embedding 等公共能力 ├── launchers/standalone/ # Spring Boot 单体启动器与数据库初始化 ├── assembly/ # 后端、前端和发行包构建脚本 └── docker/ # Dockerfile 与 PostgreSQL Composechat负责“怎么理解和呈现问题”headless负责“怎么把语义查询安全地翻译并执行”auth负责“谁能看什么”。三个模块没有被揉成一个大 Service后续扩展 Parser、Corrector、Executor 或数据库适配器时可以沿接口边界替换。2.2/api/chat/query/的真实调用顺序前端既可以分别调用parse和execute也可以调用组合查询入口。固定提交的ChatQueryController会先从请求中解析用户再调用ChatQueryServiceHTTP 问题 → UserHolder 解析用户 → ChatQueryServiceImpl.parse → 创建/复用 queryId → ChatQueryParser.accept parse → ParseResultProcessor → 保存候选解析与耗时 → 选择第一个 selectedParse → ChatQueryServiceImpl.execute → ChatQueryExecutor.accept execute → ExecuteResultProcessor → 保存查询结果ChatQueryServiceImpl通过组件工厂取得 Parser、Executor 和结果处理器列表逐个调用accept决定是否参与。当前 Parser 包括普通文本、NL2SQL 和 NL2PluginExecutor 包括插件、纯文本和 SQL执行后还会进行数据解释、指标推荐、维度推荐与比率计算。进入 Headless 层后ChatWorkflowEngine用状态机组织核心步骤MAPPING → PARSING → S2SQL_CORRECTING → TRANSLATING → PHYSICAL_SQL_CORRECTING → FINISHED映射不到任何语义实体会直接失败解析不出候选查询也会结束。只有候选语义查询需要 SQL 时系统才继续经过 S2SQL 修正阶段、翻译物理 SQL并遍历包括LLMPhysicalSqlCorrector在内的 Corrector。不过固定配置中规则 Corrector 和两个 LLM Corrector 默认均关闭基类仍会在correctedS2SQL为空时复制parsedS2SQL所以状态机经过“修正”节点不代表 SQL 默认发生了实际改写。是否启用规则或模型修正取决于系统参数和 ChatApp 配置。这种显式状态比“一次 Prompt 直接吐最终 SQL”更容易记录中间结果、定位问题和插入治理逻辑。2.3 翻译、权限和执行并不是一个动作解析阶段生成的不是立即执行的裸 SQL。performTranslating先构造SemanticQueryReq调用语义层translateS2SemanticLayerService再把请求组装为QueryStatement。真正查询时顺序为SemanticQueryReq → S2DataPermission 权限切面 → 结果缓存查询 → SemanticTranslator若尚未翻译 → 指标下钻合法性检查 → 匹配 QueryExecutor → 填充结果列 → 写入查询缓存与统计信息所以“生成了正确 SQL”只是中间条件。用户身份、语义 Schema、敏感字段、行过滤、执行器、缓存和结果列都可能改变最终行为。Headless BI 也不是只能被 Chat BI 间接调用。固定源码直接暴露POST /api/semantic/query/metric、POST /api/semantic/query/sql和POST /api/semantic/query/chat前两者分别把指标请求转成QueryStructReq、把 S2SQL 送入 Corrector然后统一经过用户解析、权限、Translator 和 JDBC 执行实现可见MetricQueryApiController与SqlQueryApiController。自然语言直查入口的ChatQueryApiController会把解析结果交给带用户参数的queryByReq做最终权限检查但它没有像同控制器的search、map、parse方法那样先把用户写回QueryNLReq解析阶段是否依赖这部分用户上下文应在真实认证配置下补做运行验证。三、语义层与 S2SQL把业务口径放在模型前面3.1 知识库和 Schema Mapper 先缩小搜索空间语义模型把物理表字段提升为业务可以理解的指标、维度、实体和标签再由数据集组合对外查询范围。知识库定期把这些 Schema 信息构建为词典和索引Schema Mapper 根据问题召回候选数据集及元素使后续 Parser 不必把整个数据库结构都塞进 Prompt。当前 Chat 入口的NL2SQLParser对候选数据集先尝试STRICT和MODERATE映射只有当前解析为空、且此前还没有产生任何全局候选时才对当前数据集退到LOOSE。一旦前面的数据集已有候选后续未命中的数据集不会继续触发这个回退。每个数据集保留排序后的最佳解析再从所有候选中取配置允许的数量。这个策略的工程意义有三点先用低成本、可解释的规则找到指标、维度和值按数据集隔离候选避免不同主题域的同名字段相互污染只有需要 LLM 且无需用户反馈时才进入 LLM/规则联合解析。当联合解析失败系统可以把映射模式放宽到ALL把更多语义字段交给模型再试一次。它提高了召回但也会增加 Token、延迟和错误匹配风险因此不是默认第一步。3.2 S2SQL 是语义查询不是直接绑定物理表的最终 SQLParser 产生的parsedS2SQL会经过 Semantic Corrector 阶段得到correctedS2SQL。固定配置中的规则 Corrector 和两个 LLM Corrector 默认均关闭因此默认情况下后者可能只是前者的副本而不是已经完成 Schema 或 Grammar 改写的结果。S2SQL 面向的是数据集中的业务字段Translator 再结合模型关系、指标表达式、数据库方言和权限条件生成querySQL。三者应分别观察用户问题统计各部门本月总访问次数 parsedS2SQL # Parser 的初始语义 SQL correctedS2SQL # Corrector 阶段的输出默认可能只是 parsedS2SQL 的副本 querySQL # Translator 生成、物理 SQL Corrector 可能再次修正的 SQLDefaultSemanticTranslator会依次运行可接受当前语句的QueryParser构造OntologyQuery再把语义层内部 SQL 与外层查询合并。数据库支持WITH时它生成 CTE不支持时则以内联子查询替换语义表最后再交给 Optimizer 重写。这层设计让指标定义与物理 SQL 解耦。例如“收入”可以在模型中统一定义Chat BI、报表和外部 SDK 共享同一个口径底层从 MySQL 迁移到 Trino 时业务问题和指标名称不必跟着全部改写。3.3 规则与 LLM 是协作关系固定源码中的策略不是“规则版”和“LLM 版”二选一没启用 LLM 时Text2SQLType使用ONLY_RULE仍可完成受支持的语义问法启用 LLM 时第一轮可先完成映射和候选选择再将选中 Schema、动态样例和问题交给 LLM物理 SQL 生成后还可能调用 LLM Corrector但最终仍要通过语义层执行器规则解析适合确定性高的指标、维度、时间和过滤条件LLM 适合复杂表达、改写和歧义补全。因此评估准确率时至少要分别记录映射是否命中、S2SQL 是否正确、翻译 SQL 是否正确、权限条件是否正确、数据库执行是否正确。只看最后一张图表很难判断问题究竟发生在哪一层。四、Chat 编排、记忆与权限从“能回答”到“可治理”4.1 多轮改写、动态样例和 Memory多轮场景中当前问题可能只有“那华东呢”。NL2SQLParser的多轮改写会取得最近一次成功查询组合历史问题、历史映射、历史 S2SQL 和当前映射让 LLM 重写出完整问题。源码注册的REWRITE_MULTI_TURN应用默认关闭说明这是可配置能力不应在未检查 Agent 配置时假设已经生效。动态 Few-shot 则来自 Chat Memory。SQL 执行器在 LLM 查询成功后将问题、Side Info、数据库 Schema 和 S2SQL 保存为PENDING记忆后续解析可从 Agent 对应的向量集合召回样例。其正向循环是真实问题 → 成功生成并执行 S2SQL → 形成待审核 Memory → 人工/模型审核与治理 → 进入可召回样例集合 → 相似问题获得更贴近本域的 Few-shot如果把错误 SQL、临时口径或含敏感值的样例直接积累进去记忆会放大错误。固定版本的 LLM 自动 Review 默认关闭成功查询只会先形成PENDINGMemory不会自动成为可召回样例需要人工启用或显式开启复核任务后才写入 Agent 对应的向量集合。因此 Memory 的价值来自“可审查的反馈闭环”不是无条件保存全部聊天记录。4.2 Plugin 扩展非结构化问答NL2Plugin Parser 可以根据插件名称、描述和示例问题选择第三方工具Plugin Executor 再执行插件。固定spring.factories当前只注册EmbeddingRecallRecognizer先从 Agent 允许的插件中按示例问题做向量召回再结合数据集和语义参数确认最后分流到 Web Page 或 Web Service。旧 Wiki 中的 LLM/function fallback 不能直接当作该提交的当前装配。插件适合知识库、内部服务或无法用语义 SQL 表达的能力。插件与 NL2SQL 共用 Chat 编排意味着一个 Agent 可以同时回答数据问题和工具问题但也带来新的安全面插件地址、鉴权和请求参数需要单独做白名单与审计LLM 选择插件不代表调用一定安全服务端仍需校验用户和参数第三方返回文本可能包含 Prompt Injection 或不可信内容插件失败不能静默伪装成正常数据结果。更具体地说Web Service 插件会由后端向配置 URL 发起请求调用点没有可见的 URL AllowlistWeb Page 在前端 iframe 中展示固定 UI 没有sandbox消息监听也没有校验event.origin。并且PluginServiceImpl.authCheck仍是 TODO 并原样返回。生产应只允许可信管理员配置插件限制服务端出口并在网关或定制层补足插件管理授权。4.3 三级权限如何进入查询S2DataPermissionAspect包围语义翻译和查询服务实际顺序如下校验请求与用户若显式needAuthfalse才跳过从语义 Schema 和请求解析涉及的模型模型管理员直接放行否则检查目标模型的 Viewer 可见性查询当前用户已授权的资源对查询中涉及的高敏指标与维度做列权限检查将授权资源中的维度过滤表达式加入 SQL 或结构化查询对结果附加“已按行权限过滤”的提示。权限层代码行为防止的问题模型可见性非管理员必须拥有目标模型 Viewer 权限看见或查询不属于自己的主题域列权限对高敏指标、维度逐项比对授权资源查询手机号、成本、薪资等敏感字段行权限将部门、区域等过滤表达式加入 WHERE/Filter同一指标下越权查看其他组织数据这一实现提升了语义层的一致性但仍应采用最小权限数据库账号、网络隔离、SQL 审计和查询资源限制。应用层权限存在配置错误或绕过风险不能把底层数据库直接暴露给公共网络。认证默认值需要区分“配置类回退值”和“standalone 实际配置”。固定AuthenticationConfig在属性缺失时回退为false但 standalone 的application.yaml会导入s2-config.yaml后者明确设置s2.authentication.enable: true。因此按该固定源码构建的标准 standalone 并非默认匿名管理员模式。只有自定义启动遗漏或覆盖该属性、使最终生效值变为false时FakeUserStrategy才会把请求映射为默认admin。生产仍应确认最终生效值、替换示例 Key/Secret、使用 TLS并逐一复核 Agent、插件和管理接口的授权。五、安装、构建与第一个可复现闭环5.1 最快体验与版本固定官方 README 提供 Docker Compose 方式。先切到固定提交以固定 Compose 文件和初始化配置gitclone https://github.com/cmyk-labs/supersonic.gitcdsupersonicgitcheckout af08d869c4609bf8d48d64e78c61427fe93f7489dockercompose-fdocker/docker-compose.yml up-d启动后访问http://localhost:9080。固定提交的数据库初始化数据包含admin用户SQL 注释给出的默认密码是123456。它只适合本地首次体验暴露服务前必须修改账号密码。还要注意固定docker-compose.yml默认拉取supersonicbi/supersonic:${SUPERSONIC_VERSION:-latest}。也就是说Compose 文件固定了但默认镜像并没有固定直接拉取latest时不能仅凭本文提交中的s2-config.yaml推断容器最终认证状态应同时记录镜像摘要并检查实际生效配置。需要严格复现本文源码时应从固定提交构建自己的镜像# 需要 Java 21、Maven、Node.js、npm/pnpm、Docker 和常见 Unix 工具# 构建参数必须与 pom.xml / 发行包版本一致不能直接换成任意提交标签shdocker/docker-build.sh1.0.0-SNAPSHOTSUPERSONIC_VERSION1.0.0-SNAPSHOT\dockercompose-fdocker/docker-compose.yml up-ddocker-build.sh会调用assembly/bin/supersonic-build.sh先以 Maven 打包 Java 服务再构建 Web 前端最终组装supersonic-standalone-1.0.0-SNAPSHOT.zip和同版本 Docker 镜像。如果还需要便于识别的提交标签应在成功构建后另行执行docker tag不能把任意标签直接作为该脚本参数。构建脚本会执行 Mavenclean、清理发行中间目录前端脚本缺少 pnpm 时还会全局安装它因此应先审阅固定脚本并在干净或隔离的 checkout 中构建。Windows 原生环境可以使用 WSL 或 Git Bash本文环境缺少 Maven因此未把全量构建标记为已通过。5.2 不要直接带着示例密码上线Compose 中 PostgreSQL 用户、密码和应用连接密码都是可读的示例值容器还启用了privileged: true并将数据库端口15432映射到宿主机。生产化至少需要将数据库密码放入受控 Secret不提交到仓库删除不必要的privileged限制容器权限与网络不向公网开放 PostgreSQL 端口只允许应用网段访问修改默认管理员密码接入企业认证并审计管理员操作确认最终生效的s2.authentication.enable为true防止环境变量或自定义配置覆盖并替换示例 App Key/Secret给查询账号设置只读、Schema 和行级最小权限为慢查询、并发、返回行数、LLM 调用和插件调用设置限额关闭不需要的 Swagger/OpenAPI 暴露或放在认证和内网之后。5.3 建立一个能定位问题的验收用例不要一上来接几十张表。建议先选择一张事实表和一张维表定义一个原子指标、一个派生指标、两个维度和一条行权限完成以下闭环1. 创建数据库连接并测试只读账号 2. 建模并确认表关系 3. 定义指标“访问次数”和维度“部门” 4. 组装数据集并发布 5. 给普通用户只授权部分部门 6. 提问“本月各部门访问次数” 7. 对照 parsedS2SQL、correctedS2SQL、querySQL 8. 对照数据库结果和权限过滤提示 9. 再测试追问、错误字段、无权限字段和超大时间范围验收记录应保存问题、映射元素、候选解析、最终 SQL、执行耗时、缓存命中、返回行数和用户权限。这样才能区分语义模型错误、LLM 错误、SQL 方言错误和数据本身错误。六、可靠性、安全与许可边界6.1 生成式查询需要多层防线SuperSonic 已经通过语义层和权限切面减少直接 Text2SQL 的风险但以下边界仍然存在LLM 可能选择错误指标、时间范围、连接关系或插件Physical SQL Corrector 的输出仍是模型生成结果应限制为只读查询行权限表达式来自授权配置配置错误会产生过度授权或错误过滤查询缓存和 Chat Memory 可能包含业务问题、字段和结果上下文打开 DEBUG 日志时Prompt、SQL、Schema 或模型响应可能进入日志第三方 LLM、Embedding、插件和数据库连接会形成新的数据流向。高敏业务应对最终 SQL 做 AST 级只读校验限制函数、数据源和扫描范围为租户隔离缓存与向量集合对 Prompt、日志和结果做脱敏重大指标保留人工确认和传统报表作为对照。6.2 性能瓶颈不只在大模型一次问答可能包含 Schema 召回、Embedding、LLM、SQL 翻译、数据库扫描、结果格式化和二次解释。常见优化顺序是缩小 Agent 可见的数据集和 Schema降低映射与 Prompt 规模优化模型关系、指标表达式和底层表避免生成昂贵 Join使用规则 Parser 处理稳定高频问法将 LLM 留给复杂问题治理 Memory 和样例减少无关 Few-shot对相同语义查询使用结果缓存同时正确隔离用户权限限制返回行数并让数据库承担聚合而不是把大量明细交给 LLM 总结。数据库适配器“存在”不等于企业当前版本已经通过压力测试。正式接入 ClickHouse、Trino、Kyuubi 等引擎前仍需验证方言、时区、NULL、窗口函数、连接池和取消查询行为。6.3 许可证不是标准 Apache 2.0 的简单复述固定提交的LICENSE写明以 Apache License 2.0 为基础但附加了商业条件不修改源码和 Logo 时可作为前后端服务进行商业使用如果基于 SuperSonic 开发并分发衍生作品需要向作者取得商业许可。贡献条款也允许项目方调整协议并将贡献用于商业用途。因此不能仅凭 README 徽章写成“Apache 2.0可任意二次开发分发”。企业部署、白标、修改后交付客户或嵌入商业产品前应让法务按实际使用和分发方式审查完整协议本文不构成法律意见。七、适用场景与总结SuperSonic 适合已有数据库和指标体系、希望统一自然语言问数与语义 API 的团队尤其适用于内部经营分析、自助取数、数据门户和嵌入式 Chat BI。它的优势不是“LLM 一次生成 SQL”而是把 Schema Mapping、规则/LLM Parser、S2SQL、Translator、权限、Memory、Plugin 和结果处理组成一条可观察链路。它不适合替代数据仓库治理也不适合在没有指标口径、模型关系和权限责任人的情况下直接向全公司开放。若数据质量和业务定义尚未统一Chat BI 只会更快地暴露矛盾。选型时可以抓住四个判断点是否愿意持续建设指标、维度、数据集和样例而不只是配置模型 API是否需要 Headless 语义层供多个应用复用是否能够把数据库、LLM、插件、缓存和日志纳入统一安全治理是否接受当前许可证的附加商业条件。满足这些条件后SuperSonic 才能从“看起来会聊天的 BI”变成真正可运营的语义查询平台。参考资料用户提供的 GitHub 仓库https://github.com/cmyk-labs/supersonic.gitSuperSonic 官方 GitHub 仓库https://github.com/tencentmusic/supersonicSuperSonic 官方 Wikihttps://github.com/tencentmusic/supersonic/wikiSuperSonic 官方文档源码归档https://github.com/supersonicbi/supersonic-website