AI 查数据库总是一本正经地胡说?NVIDIA 用“语义本体层”给 Text-to-SQL 加了护栏

0 阅读6分钟

NVIDIA Auto Ontology 项目预览

让 AI 用自然语言查询数据库,看起来已经不是难题:

帮我查上周已发货订单数

模型通常能生成一段 SQL。

但在真实企业数据里,真正困难的不是“能不能生成 SQL”,而是这段 SQL 是否真的符合业务定义。

例如,“收入”到底是订单金额、已支付金额、已开票金额,还是扣除退款后的净收入?“活跃用户”是过去 7 天登录过,还是过去 30 天有订单?

今天 GitHub Trending 上增长很快的项目 NVIDIA Auto Ontology,就是为这个问题设计的。它在数据库和 LLM 之间增加一个可验证的语义层,让 Agent 不只是猜 SQL,而是基于经过认证的业务概念、指标和关联关系生成查询。

为什么普通 Text-to-SQL 不够可靠?

最朴素的 Text-to-SQL 流程是:

flowchart LR
    A[自然语言问题] --> B[LLM]
    B --> C[SQL]
    C --> D[数据库]
    D --> E[答案]

它的问题是,LLM 可能不知道:

  • 业务中的“收入”应该使用哪一列;
  • 两张表之间该如何关联;
  • 指标是否应该排除退款、取消订单或测试数据;
  • 当前数据源是否根本没有用户问到的数据;
  • 同一个指标在不同系统中的定义是否一致。

结果是:SQL 语法正确,返回数字也很自然,但业务上可能完全错误。

这比报错更危险。

Auto Ontology 的核心思路:先理解数据,再回答问题

Auto Ontology 的核心是建立一个企业数据本体(Ontology)。

可以把它理解为一层“AI 能读懂、业务人员能审查”的数据说明书,包含三类信息:

类型作用示例
业务术语定义业务实体和别名客户、订单、发票行、收入
SQL 属性定义经过审核的指标计算毛利、净收入、滚动 30 天销售额
关系定义表之间如何关联订单 → 客户 → 城市 → 省份

整体流程变成:

flowchart LR
    A[业务数据库] --> B[采集 Schema、字段和样本]
    B --> C[生成语义本体]
    C --> D[人工审核与认证]
    D --> E[Agent / MCP / API]
    F[自然语言问题] --> E
    E --> G[检查可回答性]
    G --> H[生成并验证 SQL]
    H --> I[答案 + SQL + 推理步骤]

关键变化是:模型不再直接面对杂乱的表和字段,而是先检索经过定义和认证的业务概念。

它如何减少“幻觉 SQL”?

Auto Ontology 将回答一个问题拆成多个可检查的步骤:

  1. 识别用户问题中的意图和实体;
  2. 通过向量检索找到候选术语、字段和 SQL 属性;
  3. 根据本体中的关系推导需要的 Join;
  4. 生成 SQL;
  5. 校验筛选值和 SQL 是否可执行;
  6. 执行并返回答案、SQL、结果行和推理步骤。

如果本体覆盖不了问题,它不会硬编答案,而是给出“数据无法回答”的结论。

例如,数据库只包含销售数据,没有广告花费数据。用户问:

某个商品上月的广告投入回报率是多少?

系统可以识别出“广告花费”没有对应数据,而不是只用销售额拼出一个看似合理的数字。

技术架构

Auto Ontology 是一套完整的全栈系统:

组件技术栈职责默认端口
Web 前端Next.js、React、TypeScriptChat、数据目录、设置、认证3000
后端FastAPI、Python、LangChainText-to-SQL、目录和本体 API3001
采集服务FastAPI数据摄取、Embedding 与语义编译3002
数据层PostgreSQL + pgvector本体、目录、向量检索5432
MCP ServerFastMCP供 Agent 安全读取本体3003

它支持 PostgreSQL、MySQL、Databricks、Snowflake、ClickHouse、Trino、DuckDB、SQLite 等多种数据源。

快速开始:Docker Compose 本地运行

官方 Quickstart 使用 Microsoft 的 Wide World Importers 示例销售数据库。

1. 获取代码并创建环境变量

git clone https://github.com/NVIDIA/auto-ontology.git
cd auto-ontology
cp .env.example .env

编辑 .env,至少配置:

DEFAULT_MODELS_API_KEY=nvapi-...
AUTH_SECRET=请替换为足够长的随机字符串
APP_URL=http://localhost:3000
POSTGRES_PASSWORD=请设置新密码
AUTO_ONTOLOGY_ADMIN_PASSWORD=请设置新密码

默认推理使用 NVIDIA NIM;需要在 NVIDIA API Catalog 获取 API Key。

2. 启动 Postgres

docker compose up -d --wait postgres

3. 启动完整服务

docker compose up -d --build

打开:

http://localhost:3000

首次进入后,在 Settings → Semantic Compilation 中开启语义编译。系统会从接入的数据源中读取 Schema、字段、样本值和关联关系,生成初始本体草稿。

试着问一个问题

例如:

2015 年 6 月,宾夕法尼亚州“USB food flash drive - sushi roll”的收入是多少?

系统会做的不是简单关键词匹配,而是:

  1. 将“收入”解析为认证过的业务指标;
  2. 将产品和州名映射到相关业务实体;
  3. 找到发票行、发票、客户、城市、州之间的关系;
  4. 生成并验证 SQL;
  5. 返回答案与完整 SQL。

这样,数据分析人员可以审查“为什么得到这个答案”,而不是只能相信模型的一句话。

通过 API 调用

登录后,在用户菜单中创建 API Token,然后调用聊天接口:

curl -N http://localhost:3000/api/chat/completions \
  -H "x-api-key: $AUTO_ONTOLOGY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"question": "How many orders shipped last week?"}'

服务会以 Server-Sent Events 流式返回结果,其中包括回答和生成的 SQL。

Python 示例:

import os
import requests

response = requests.post(
    "http://localhost:3000/api/chat/completions",
    headers={"x-api-key": os.environ["AUTO_ONTOLOGY_API_TOKEN"]},
    json={"question": "上周已发货订单有多少?"},
    stream=True,
    timeout=900,
)

response.raise_for_status()

for line in response.iter_lines(decode_unicode=True):
    if line and line.startswith("data:"):
        print(line)

给 Claude Code、Cursor 等 Agent 接入 MCP

Auto Ontology 提供 MCP Server,使 Agent 可以先检查“这个问题是否可回答”,再查询数据。

它提供的工具包括:

  • check_readiness:检查部署是否已可回答问题;
  • search_terms:搜索业务术语;
  • get_term:查看术语定义;
  • check_answerable:判断本体是否覆盖当前问题;
  • ask_question:返回答案、SQL 和结果行。

例如可以独立启动 MCP 客户端:

AUTO_ONTOLOGY_API_URL=http://localhost:3000 \
uvx --from "git+https://github.com/NVIDIA/auto-ontology.git#subdirectory=mcp" auto-ontology-mcp

它的意义在于:Agent 在分析数据前,先获得可信的业务上下文,而不是把数据库 Schema 原样塞进提示词。

适合哪些场景?

  • 企业内部自然语言查数;
  • 财务、销售、运营指标问答;
  • 多数据源中的口径统一;
  • 给数据分析 Agent 提供可追溯上下文;
  • 需要审查 SQL、数据血缘和业务定义的场景;
  • 已经有指标体系,但缺少 Agent 可使用语义层的团队。

使用前要注意什么?

1. 自动生成的本体仍需人工认证

系统可以从 Schema 和样本中生成初稿,但“收入”“客户”“活跃用户”等业务口径不能只交给模型决定。真正可靠的做法是让数据和业务负责人审核并认证术语、关系和 SQL 属性。

2. 不要将内部数据库直接暴露给 Agent

官方架构中,后端和采集服务应放在私有网络。外部客户端应通过带认证的 Web/API 层访问,数据库密码与连接串也应使用安全的密钥管理方式保存。

3. Embedding 模型要保持一致

用于采集与查询的 Embedding 模型必须一致。否则已经建立的向量索引与查询向量不在同一语义空间,检索质量会明显下降。

4. 先从只读数据源开始

第一阶段建议接入只读分析库或脱敏副本,并为数据库账号设置最小权限。自然语言查询工具最适合先做“读取、验证、解释”,不要一开始就开放写入能力。

相关链接