1. 从“能聊”到“能干”:TDSQL NEXA 要解决的真问题
企业数据这个领域,过去十年最大的矛盾是什么?是数据量涨得比人快,而人理解数据的速度几乎没变。业务方提一个取数需求,数据团队要翻三张表、写五段 SQL、跑两轮校验,最后发现口径对不上,再拉个会。这个循环我经历过太多次,每次都觉得时间不是花在分析上,而是花在“找路”上。
TDSQL NEXA 这个项目标题里有两个关键词:AGENT和企业数据。把这两个词放在一起,指向的其实是一个很具体的诉求——让 AI Agent 不只是“会聊天”,而是能真正连上企业的数据库,理解表结构、理解业务语义、理解权限边界,然后自主完成查询、分析、甚至运维动作。说白了,就是让 Agent 从“嘴替”变成“手替”。
这件事为什么难?因为企业数据环境有三个天然屏障。第一是结构复杂,一张核心业务表可能有上百个字段,字段名还是拼音缩写加下划线的组合,人看着都头疼,模型更懵。第二是语义断层,数据库里存的是order_amt,业务方嘴里说的是“成交金额”,中间隔着一层只有老员工才知道的映射关系。第三是安全红线,Agent 不能随便看、随便改,权限必须卡死,操作必须留痕。
TDSQL NEXA 的定位,就是在这三层屏障上各开一扇门。它不是一个单纯的 NL2SQL 工具,而是一套让 Agent 具备“数据库素养”的基础设施。适合谁来关注?如果你是数据平台工程师、AI 应用开发者、或者正在把大模型往业务系统里塞的技术负责人,这个方向值得花时间研究。哪怕你暂时不落地,理解它的设计思路,对判断未来两三年数据栈的演进也有参考价值。
我下面会从整体设计、核心细节、实操落地、问题排查四个层面展开,尽量把“为什么这么设计”和“具体怎么干”都说清楚。有些地方我会给出基于常见实践的合理推演,因为官方文档不可能覆盖所有踩坑场景,而这些恰恰是一线最需要的。
2. 整体设计思路:Agent 驾驭企业数据的四层架构
2.1 为什么不能直接让大模型裸连数据库
很多人第一反应是:不就是让 GPT 写 SQL 吗?我试过,直接给模型一张表的 DDL,让它根据自然语言生成查询,简单场景确实能跑。但一旦表数量超过二十张,字段超过五百个,准确率断崖式下跌。原因不复杂——上下文窗口塞不下完整的 schema,模型只能靠猜。更致命的是,企业数据库里大量字段名是f_1、f_2、ext_col_03这种,模型没有任何先验知识可以依赖。
所以 TDSQL NEXA 的第一层设计,一定是元数据治理层。它要做的事情是把物理 schema 翻译成模型能理解的语义层。具体来说,包括给表打业务标签、给字段写自然语言描述、标注主外键关系、标注枚举值的含义。这一步听起来像“脏活累活”,但它是整个 Agent 能不能用起来的地基。我见过太多团队跳过这一步直接上模型,最后效果不行就怪模型能力不够,其实是元数据没喂饱。
第二层是检索与路由层。企业库里可能有几千张表,但一次查询真正相关的往往只有三到五张。NEXA 需要根据用户问题,先从元数据索引里召回候选表,再让模型在缩小后的范围内做推理。这个思路和 RAG 很像,只不过检索的对象不是文档,而是表结构和字段语义。检索质量直接决定后续 SQL 生成的准确率,所以索引怎么建、召回怎么排序,是核心工程问题。
第三层是执行与校验层。模型生成的 SQL 不能直接怼到生产库上跑,中间必须有沙箱校验、语法检查、权限过滤、代价预估。我个人的经验是,至少要做三层拦截:语法层拦截明显错误的 SQL,权限层拦截越权访问,代价层拦截全表扫描这种可能拖垮库的操作。NEXA 作为数据库原厂出的方案,在这一层有天然优势,因为它能直接调用数据库内核的能力做校验,而不是在外面套一层薄薄的代理。
第四层是记忆与反馈层。Agent 每次执行的结果、用户的修正、失败的案例,都应该沉淀下来。下次遇到类似问题,可以直接复用之前的正确 SQL 模板,或者避开之前踩过的坑。这一层是让 Agent 越用越聪明的关键,也是区分“玩具”和“工具”的分水岭。
2.2 四层架构的协作逻辑
把这四层串起来看,一次完整的交互是这样的:用户用自然语言提问,检索层从元数据索引里找到相关表和字段,语义层把这些信息翻译成模型友好的格式,模型生成 SQL 候选,校验层做多重检查,执行层在受控环境下运行,结果返回给用户,同时反馈层记录这次交互的成败。
每一层都有独立的优化空间,但层与层之间的接口设计同样关键。比如检索层召回的表如果太多,模型上下文又不够用了;召回太少,可能漏掉关键表。这个平衡点需要根据实际数据规模反复调。我的建议是,初期召回数量控制在 10 到 15 张表,随着元数据质量提升再逐步收紧。
还有一个容易被忽略的点:Agent 的“理解”不只是理解 schema,还要理解业务语境。比如“上个月”在不同部门可能指自然月、财务月、或者滚动 30 天。NEXA 需要在语义层里把这些口径固化下来,否则同一个问题不同人问,Agent 给出的答案不一致,信任就崩了。
3. 核心细节解析:让 Agent 真正“看懂”数据库
3.1 元数据语义化:从字段名到业务含义
这一步是整个项目里最耗人力、但回报最高的环节。我拿一个真实场景举例。假设有一张订单表,字段包括ord_id、uid、pay_tm、ord_st、amt。对人来说,看一眼大概能猜出意思,但对模型来说,ord_st到底是“订单状态”还是“订单站点”,它分不清。
NEXA 的做法应该是提供一套语义标注规范,让数据管理员给每个字段补充:中文名称、业务定义、数据类型、枚举值映射、是否敏感、关联字段。比如ord_st标注为“订单状态”,枚举值 1 对应“待支付”、2 对应“已支付”、3 对应“已取消”。这些信息会作为元数据索引的一部分,在检索和生成时注入给模型。
注意:枚举值映射一定要和代码里的定义保持一致。我踩过的坑是,数据库里存的是 1/2/3,但代码里定义的是 10/20/30,标注时抄错了,导致 Agent 生成的 SQL 条件永远查不到数据。这种错误排查起来非常费劲,因为 SQL 语法没问题,就是结果为空。
标注的粒度也有讲究。核心表的核心字段必须人工标注,边缘表的非关键字段可以半自动生成。我通常的做法是,先用脚本从字段名和注释里提取候选描述,再让业务方确认。这样能把人力集中在真正影响查询准确率的字段上。
3.2 检索策略:怎么从几千张表里找到对的那几张
检索层的核心是元数据索引的构建。索引里存的不是原始数据,而是表名、字段名、字段描述、业务标签的向量表示。用户提问后,先把问题向量化,然后在索引里做相似度检索,召回 top-K 张表。
这里有几个实操细节值得说。第一,表名和字段名的分词要特殊处理。比如order_detail要拆成order和detail,ord_amt要能映射到“订单金额”。第二,业务标签的权重应该高于字段名。因为用户提问用的是业务语言,不是数据库语言。第三,要支持多路召回。除了向量检索,还可以用关键词匹配、同义词扩展做补充,最后合并去重。
我实测下来,纯向量检索在字段名规范的情况下效果不错,但遇到拼音缩写就拉胯。所以混合检索是更稳的方案。另外,召回结果最好带上置信度分数,低于阈值的直接丢弃,避免把噪声喂给模型。
3.3 SQL 生成与校验:把错误拦在执行之前
模型生成 SQL 这一步,prompt 的设计至关重要。我的经验是,prompt 里必须包含四样东西:相关表的完整 DDL、字段的业务描述、数据库方言说明、以及几条正确的 SQL 示例。少一样,准确率都会明显下降。
方言说明经常被忽略。TDSQL 兼容 MySQL 语法,但有一些自己的扩展和限制。如果 prompt 里不说明,模型可能生成 PostgreSQL 风格的 SQL,执行时直接报错。示例 SQL 的作用是给模型“定调”,让它知道这个环境里常用的写法是什么样。
校验层我建议至少做这几件事:
| 校验类型 | 检查内容 | 失败处理 |
|---|---|---|
| 语法校验 | SQL 是否符合方言规范 | 返回模型重新生成 |
| 权限校验 | 是否访问了未授权表或字段 | 直接拒绝并告警 |
| 代价校验 | 是否全表扫描、是否缺少索引条件 | 提示优化或拒绝执行 |
| 敏感校验 | 是否触碰敏感字段 | 脱敏或拒绝 |
代价校验这一层,很多团队初期会省略,觉得“先跑通再说”。但生产环境里一条全表扫描的 SQL 可能直接把库拖慢,影响面远超预期。NEXA 作为数据库原厂方案,应该能直接调用优化器的代价估算能力,这是它相比外部工具的核心优势。
3.4 记忆机制:让 Agent 越用越顺手
记忆层分短期和长期。短期记忆是当前会话的上下文,比如用户前面问了什么、Agent 生成了什么 SQL、执行结果如何。长期记忆是跨会话的知识沉淀,包括成功的 SQL 模板、常见的查询模式、用户偏好。
我特别想强调失败记忆的价值。Agent 生成了一条 SQL,执行报错,这个错误信息应该被记录下来。下次遇到类似问题,Agent 可以主动避开这个坑。比如某张表的某个字段实际是字符串类型,但模型总以为是数字,失败几次后就应该在记忆里标注这个字段的类型陷阱。
记忆的存储形式可以是向量库加结构化表的组合。向量库存 SQL 模板和问题描述的嵌入,结构化表存执行结果、错误码、时间戳。检索时先查结构化表看有没有精确匹配,没有再走向量检索找相似案例。
4. 实操落地:从零搭一个 Agent 数据助手的完整流程
4.1 环境准备与元数据采集
假设你已经在腾讯云上有一套 TDSQL 实例,现在想接一个 Agent 上去。第一步不是写代码,而是盘清楚数据资产。我通常会让团队先跑一个脚本,把库里所有表的 DDL、字段注释、索引信息、数据量统计拉出来,形成一份资产清单。
-- 采集表基本信息 SELECT TABLE_NAME, TABLE_COMMENT, TABLE_ROWS, CREATE_TIME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'your_database' ORDER BY TABLE_ROWS DESC; -- 采集字段信息 SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, COLUMN_COMMENT, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'your_database' ORDER BY TABLE_NAME, ORDINAL_POSITION;拿到清单后,按数据量和使用频率排序,优先标注 Top 50 的核心表。这些表通常覆盖了 80% 的查询需求。标注工作可以用表格工具协作,一列填字段名,一列填业务描述,一列填枚举映射,一列填敏感标记。
提示:标注时一定要拉上业务方一起过一遍。技术人员以为的“订单金额”和业务方说的“成交金额”可能不是一回事,这种偏差在标注阶段发现成本最低。
4.2 元数据索引构建
标注完成后,把结构化标注转成向量索引。我一般用 embedding 模型把“表名 + 字段名 + 字段描述 + 业务标签”拼成一段文本,然后向量化存入向量库。同时保留一份结构化映射,方便后续精确查询。
# 伪代码示意:构建元数据索引 import embedding_model import vector_store def build_index(table_metadata): for table in table_metadata: for column in table['columns']: text = f"{table['name']} {table['comment']} {column['name']} {column['comment']} {column['business_tag']}" vector = embedding_model.encode(text) vector_store.insert( id=f"{table['name']}.{column['name']}", vector=vector, payload={ 'table': table['name'], 'column': column['name'], 'type': column['type'], 'sensitive': column['sensitive'] } )索引建好后,用一批真实的历史查询做召回测试。召回率低于 90% 的话,回去补标注。这个迭代过程可能要重复两三轮,但值得投入。
4.3 Agent 主流程编排
主流程我建议用状态机的方式组织,每个状态做一件事,失败可以回退。核心状态包括:问题理解、表召回、SQL 生成、校验、执行、结果格式化。
# 伪代码示意:Agent 主流程 def agent_query(user_question): # 1. 问题理解与改写 rewritten = rewrite_question(user_question) # 2. 召回相关表 candidate_tables = retrieve_tables(rewritten, top_k=12) # 3. 构建 prompt prompt = build_prompt( question=rewritten, tables=candidate_tables, dialect='tdsql_mysql', examples=get_few_shot_examples(rewritten) ) # 4. 生成 SQL sql = llm_generate(prompt) # 5. 校验 if not validate_syntax(sql): sql = llm_regenerate(prompt, error='syntax') if not validate_permission(sql): return '权限不足,无法执行' if not validate_cost(sql): sql = llm_optimize(sql) # 6. 执行 result = execute_in_sandbox(sql) # 7. 记录记忆 save_memory(user_question, sql, result) return format_result(result)这个流程里,每一步都要有超时和重试控制。模型生成可能慢,执行可能卡,没有超时机制的话,用户体验会很差。我的经验是,单次查询总耗时控制在 10 秒以内比较合理,超过 15 秒用户就开始不耐烦了。
4.4 权限与安全配置
权限这块不能马虎。我的做法是双层控制:第一层在 Agent 层面,根据用户身份过滤可访问的表和字段;第二层在数据库层面,用独立的只读账号执行查询,账号权限严格限制在必要的库表上。
敏感字段的处理要特别小心。比如手机号、身份证号、金额字段,Agent 生成的 SQL 里如果包含这些字段,要么脱敏返回,要么直接拒绝。我倾向于默认脱敏,需要明文时走审批流程。这样即使 Agent 出错,也不会造成数据泄露。
注意:不要用超级管理员账号跑 Agent 查询。我见过一个案例,Agent 生成的 SQL 里带了
DELETE语句(虽然概率极低,但确实发生过),幸好用的是只读账号,否则后果不堪设想。
5. 常见问题与排查技巧实录
5.1 Agent 生成的 SQL 查不到数据怎么办
这是最高频的问题。排查顺序我一般是这样:
- 先看 SQL 本身有没有语法问题。把 SQL 复制到客户端里手动跑一遍,如果报错,说明校验层没拦住,需要加强语法检查。
- 再看字段映射对不对。Agent 可能把“成交金额”映射到了
order_amt,但实际应该用pay_amt。这时候要回去检查元数据标注。 - 再看枚举值。状态字段的条件值是不是和数据库里存的一致,这个前面提过,是重灾区。
- 最后看时间范围。“上个月”的起止时间是不是符合业务口径。
我整理了一个速查表:
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
| SQL 报语法错误 | 方言不匹配或模型幻觉 | 检查 prompt 里的方言说明 |
| 结果为空但 SQL 能跑 | 字段映射错误 | 核对元数据标注 |
| 结果为空且条件涉及枚举 | 枚举值不一致 | 查数据库实际值分布 |
| 结果明显偏少 | 时间范围口径错误 | 确认业务时间定义 |
| 结果明显偏多 | 缺少过滤条件 | 检查是否漏了状态或类型过滤 |
5.2 召回表不准确怎么调
召回不准通常有两个方向:要么该召回的没召回,要么召回了太多无关的。前者要补充同义词和业务别名,比如“客户”和“用户”要能互相映射。后者要提高相似度阈值,或者引入重排序模型做二次筛选。
我自己的经验是,召回阶段宁多勿少,精排阶段再收紧。因为漏掉关键表的代价远大于多召回几张表。多召回的表可以在 prompt 里标注“可能相关”,让模型自己判断用不用。
5.3 模型生成不稳定怎么破
同一个问题,今天生成的 SQL 对,明天就错了,这种不稳定最让人头疼。原因通常是prompt 里的示例不够或者温度参数太高。我的做法是:
- 把 temperature 调到 0 或接近 0,减少随机性
- 针对高频查询场景,准备固定的 few-shot 示例
- 对生成结果做缓存,相同问题直接复用之前的正确 SQL
还有一个技巧是让模型生成多个候选 SQL,然后投票选最优。虽然会增加成本,但对关键场景值得。投票的维度可以包括:语法正确性、代价估算、历史成功率。
5.4 性能瓶颈在哪里
Agent 查询的延迟主要花在三块:模型推理、向量检索、SQL 执行。模型推理通常是大头,尤其是用大参数模型的时候。优化方向包括:用小模型做召回和改写,大模型只做最终的 SQL 生成;对常见问题做结果缓存;把向量检索的索引放到内存里。
SQL 执行这块,如果发现某类查询总是很慢,可以考虑在数据库侧建物化视图或者预计算表。Agent 查询的特点是模式相对固定,适合做预聚合。NEXA 如果能结合数据库的物化视图能力,性能会有明显提升。
5.5 怎么评估 Agent 的效果
没有度量就没有优化。我建议至少跟踪这几个指标:
- SQL 准确率:生成的 SQL 能正确回答问题的比例
- 召回率:相关表被召回的比例
- 平均响应时间:从提问到返回结果的耗时
- 用户采纳率:用户直接使用 Agent 结果的比例
- 失败原因分布:各类错误的比例,指导优化方向
评估集要覆盖典型场景和边缘场景。我通常从历史查询日志里采样 200 到 500 条,人工标注正确答案,然后定期跑评估。准确率低于 70% 的话,先别急着上线,回去补元数据和示例。
6. 我对这个方向的一些判断
TDSQL NEXA 这类产品的出现,标志着 Agent 在企业数据领域的落地进入了一个新阶段。之前的 Agent 更多是在“外围”打转,做做客服、写写文案,现在开始往核心系统里走了。这个趋势不可逆,因为企业数据的价值太大了,不可能一直靠人肉去挖。
但我也要泼一盆冷水:Agent 驾驭企业数据,瓶颈不在模型,在元数据。模型能力每年都在涨,但企业里的元数据治理是个慢功夫,需要业务方、数据方、开发方一起投入。谁先把元数据这关过了,谁的 Agent 就能先跑起来。技术选型上,我倾向于选数据库原厂出的方案,因为它们在权限、执行、优化器这些层面有天然优势,外部工具很难绕过去。
最后分享一个我自己的小技巧:上线初期,让 Agent 只做“生成 SQL 并展示”,不直接执行。用户看到 SQL 后,自己复制去跑,跑完反馈对不对。这样既能积累评估数据,又能避免 Agent 出错带来的业务风险。等准确率稳定在 85% 以上,再逐步开放自动执行。这个过渡期大概需要一到两个月,急不得。