dst
Officialdata serve tool (dst)
dst 把你的数据仓库服务给 AI,并为这件事的整个生命周期带来工程最佳实践。 AI 用自然语言提问;dst 根据你的团队写下的定义来回答,并附上产出答案的 SQL、一个置信度评级,以及一张收据。
问题
把 AI 指向一个数据仓库,它就什么都会回答。它从不拒绝回答,而这正是失败模式:一个错误的答案比没有答案更糟。
它去猜测“revenue”是什么意思,然后返回一个数字,看上去和正确答案别无二致。
仅靠上下文无法解决这个问题的。AI 是不确定的,而其他团队、另一个模型,或另一个季度下有效的做法,在你这里未必有效。
唯一知道答案的方法是:在你的数据上,持续地测试它。
解决方案
声明:以版本控制中的文件形式声明你的数据如何被服务。
测试:验证那些对你真正有效的做法。每一个被批准的答案都是一条回归测试,而管线中的每一个开关都可以翻转并重新测量。
部署:只部署通过的内容,经过会大声失败的闸门。
审计:审计所有已经被服务过的内容:谁问了、跑了什么、花了多少。每一个错误都会作为一个新测试自动回流。
由实践者构建,为实践者服务:文件、pull requests、CI 和退出码,而不是一套新工作流。
测试:引擎
生成过程的核心总是不确定的,因此 dst 把测试当成产品本身,而不是后补的环节。
每一条被批准的答案,都是一条回归测试。 一条已认证的答案,就是一个被人担保的问题→SQL 配对。
dst test通过真实生成管线重新提出这个问题,然后把存储的 SQL 和生成的 SQL 都放到你的数据仓库中执行,并对结果。行为也被固定了。
evals/cases.yaml里的用例断言响应的 形态:expect: clarify | refuse | answer。如果一个 lens 开始拒绝明明可回答的问题,或者干脆用猜测代替澄清,它的套件就会失败。每个结果都会被记录。 测试运行都会落入数据库,所以准确率是一个你能看着它在变化的数字,并且每个发布都以它作为门闸:任何比上次发布分数还低的变更,都被拒绝。
管线可以按 lens 调整(答案严格度、自我修复、逐条判断、门控硬度),而每次翻转都可测量:改一处,跑一次 dst test,结果立刻可知。而如果你想知道在你自己的问题集上,哪些部分真正值得保留,内置的试验场会把你的问题集整套跑过管线,每次只剥离掉一个 feature:
python -m services.benchmark --data -./data --strip <feature>。完整的可调面见配置参考。
Related MCP server: RunContext
部署:经过关卡
一个 lens 就是文件。改变一个答案的 diffuse;这就是一次部署,而不是一次编辑:
edit files → dst plan (dry run) → dst apply (gated, atomic)dst plan 会显示一次变更会造成什么,如果 apply 会拒绝它,就以退出码 1 退出:plan 预测 apply 的结局。dst apply 就是一个单一事务:连接会被探测,每个过期的已认证答案都会重新对 live generation 运行,任何失败都意味着 什么都不用发布;之前的那个版本继续对外服务。
版本:每次发布都会为一个 lens 版本做快照;
dst lens log会显示谁在什么时候改了什么(human:ana@corp/token:ci)。回滚就是git revert+dst apply。环境是用来出错的。 每种环境都是一套独立的 dst:你的笔记本、共享查沙盒、生产。让沙盒指向不同的模型、不同的 temperature、不同的数据表,或一套重新撰写定义的解释,跑
dst rotate test,然后比较得分——沙盒只需要在你已有的服务器上dst bootstrap一次。上线就是往生产里应用同一个 git commit;环境之间不会复制任何东西,文件中也没有需要逐环境同步的条款。CI 只用你自己用的那组命令。 exit code 就是接口:PR 任务跑
dst plan;merge 脚本跑dst apply --require-gates;定时任务跑dst test --all和dst drift。一份可直接使用的 GitHub Actions 示例在 环境与 CI 指南。
审计:每条答案都有价格和签名
回执。 每条数据答案都携带一份可移植、HMAC 签名的回执:请求 id、lens、certification、确切 SQL 的哈希。可在之后通过这些 API 在
verify_receiptMCP 工具中验证。拒绝里不带回执:因为拒绝声明明确不做任何数据主张。台账。
dst observe的回答是“谁一直在用它,用它干什么”:每一个调用的题目、SQL、结果、在云计算的两种计价表(AI 和数据仓库)上的成本。已答复、已拒绝、出错分开计数;一次受管控的拒绝是一种结果,把一个错误。访问是被拒绝的。 每一个 allow * 和每一个 deny 都会落入 append-only 审计日志,包含调用者、lens 和原因。
数据仓库的每个角落都在被监视。
dst drift把现在的实况 schema 和已提交的基线做对比,而且把每次变更与读取被改表的全部定义、全体实体相互关联。之后是 exit code:0干净、2无变化,1变更破坏已声明、4还没有基线。的怀疑是一等输入。 Anyone 可以发一个问题来 review;低置信度的答案可以自己用
auto_review标记。AI 法官会先做 triage 三角分类,人再裁判;repair 修复就变成一个文件加一个新测试,把整个闭环完成:
---
config:
theme: base
themeVariables:
fontFamily: "ui-monospace, Menlo, monospace"
fontSize: "14px"
primaryColor: "#faf6ee"
primaryBorderColor: "#b45309"
primaryTextColor: "#292524"
lineColor: "#b45309"
edgeLabelBackground: "#faf6ee"
---
flowchart TD
serve(["an answer is served,<br/>with its receipt"])
doubt["someone doubts it"]
test["it becomes a test:<br/>an approved answer + its check"]
gate["it gates every deploy"]
serve -- "flagged by the asker,<br/>or by dst itself" --> doubt
doubt -- "AI drafts the fix,<br/>a person approves it" --> test
test -- "commit + dst apply" --> gate
gate -- "the corrected answer serves<br/>from then on, and the AI learns from it" --> serve一次被修正的错误,就永远被修正,而且你能证明这一点:被纠正的问题从那个时刻起就被已被认证的 SQL 提供,并且它的测试在 release 每次都会被重跑。注意重点任务请看修正环。
模型
Lens——服务的最小单位。一个使用场景(如流失、销售提成、董事会指标模式)会被描述成你共享的语义资产上的 selects,以及访问规则和自己的时钟。一个 agent 用 natural language 向一个 lens 提问,然后得到一份 grounded 且可引用的答复。
语义文件——实体 and 定义,是一次性写的文件,,每个选择它的 lens 共享。一个指标,一个定义;agent 使用的词是可以变化的,而含义从来不非遗。
在丰富上下文——“在上下文中”被 review 过的回答句就会被每个 lens 传播。entry 条目是刻意的、可追溯的,并且随 lens 一起版本化。
认证的回答——经 review 的 question-to-SQL 对,在匹配时逐句地原样,再由 dst test 当作回归测试重跑,并在每次 dst apply 中重跑。一次被修正确的错误就会成为到这样一个词,这样它就一直是 fixed 的。
治理——访问控制完全用你选择的方式:逐 lens 的 person/group 白名单、逐 caller 的 API key(dst_…)、rate limit、以及在数据库层面强制执行的 tenant 隔离(PostgreSQL RLS)。存储的 warehouse 凭据在 rest 时会被加密。
观测——每次调用都会自上而下被 trace。那个 lens,那个 caller,那个 question,那个 SQL,AI 一致性 + 直接的 warehouse 还分,并又被answered / declined / errored 分开数。答案还能被送去 review:AI 法官审查 reasoning trace,并在需要时快速汇报给人类。
Agents 才是 interface
没有 query UI。真正用你喂的是“agent”:把你的任意 MCP client(Claude
Desktop、Claude Code、Cursor,或者你自己产品里面内置的 agent)连到指向 /mcp 的 guard 上的 /mcp,只需要一个 URL 和一个作用域受限的 dst_… key(见services/mcp/README.md)。每个问题都走同一条受治理的管线,所以无论哪个 agent 问,它得到答案都一样:
agent (Claude Desktop · Claude Code · Cursor · your product's agent)
│ MCP — one scoped dst_… key per person
▼
dst ── lens: semantic model + context + access
│ ground → SQL guard → execute → compose (cited)
▼
your warehouse (BigQuery · Snowflake · Postgres · MySQL · DuckDB)
│
trace + cost + review → Observe人类留在站守,而不是 query 处理路径里:dashboard 才是治理和观察那些 file 所“服务”的驾驶座:review queue,drift 审计、访问、成本。Lens 就是 files 写出来的(dst init → 编辑 → plan/apply),绝不会在 UI 里写。(如果想接 rest API 到 dst 里,也有 REST 门:API reference。)
项目长什么样
项目是这样一组文件:版本化、在 PR 里 review,像 infrastructure 一样地 apply。以下内容是从 dst init 真正生成的 scaffold 里精简略的(scaffold 会把演示语义资源放到 examples/ 下面,所以你可以整体删掉、整那个文件夹也别担忧;那个演示的 lens 本身在 lenses/customer_value/):
name: orders
description: One row per order.
source:
connection: jaffle
table: orders
default_time_field: order_date
primary_key: [order_id]
fields:
- {name: order_id, type: integer}
- {name: customer_id, type: integer}
- {name: order_date, type: date}
- {name: status, type: string}
- {name: amount, type: number, description: Order total (USD).}
metrics:
- {name: revenue, agg: sum, expr: orders.amount, format: currency}
- {name: order_count, agg: count, expr: orders.order_id}
- name: average_order_value
type: ratio
numerator: revenue
denominator: order_count
format: currency
joins:
- {right: customers, on: customers.customer_id = orders.customer_id,
type: left, relationship: many_to_one}一次定义把业务术语绑定给 SQL:
---
metric: repeat_customer
sql: customers.number_of_orders > 1
---
A repeat customer has number_of_orders > 1.而一个 模糊 的定义则会让 dst 去澄清,而不是猜测:
---
metric: value
status: ambiguous
possible_mappings:
- lifetime value — customers.customer_lifetime_value
- order amount — orders.amount
---一下这些 mapping 就足够了:dst 在生成任何东西之前,会在代码里把它们直接长出的澄清,不需要更多配置。
name: customer_value
description: Customer lifetime value and order activity.
connections: [jaffle]
select:
entities:
- name: customers
- name: orders
definitions: [lifetime_value, repeat_customer, value]
model:
temperature: 0.0
answer_mode: balanced
instructions: Select explicit columns.
access:
allow:
- caller: alex # deny-by-default; or `- group: everyone`
eval_gate: block # a failing eval suite blocks the apply
auto_review: unverified # low-confidence answers open review tickets# Served VERBATIM on a match — and each one is a regression test:
# `dst test` re-asks the question and compares against this SQL's result.
- question: How many customers are repeat customers?
sql: SELECT count(*) AS n FROM customers WHERE number_of_orders > 1
- question: What was total revenue?
sql: SELECT sum(amount) AS revenue FROM ordersname: analytics
providers:
anthropic:
type: anthropic
api_key_env: DST_API_KEY_ANTHROPIC
# any openai-compatible endpoint works: deepseek, ollama, vllm, groq …
connections:
jaffle:
type: duckdb
config: {path: fixtures/jaffle_shop.duckdb}
wh:
type: bigquery # or snowflake, postgres, mysql
config: {project: my-gcp-project}
secret_env: DST_API_KEY_WH # an inline key is a parse error$ dst query customer_value "How many customers are repeat customers?"
19 of the 100 customers are repeat customers.
sql: SELECT count(*) AS n FROM customers WHERE number_of_orders > 1
basis: A repeat customer has number_of_orders > 1.
confidence: verified · definition: repeat_customer
$ dst query customer_value "What is the average value of a customer?"
clarify: 'value' is ambiguous in this dataset — lifetime value (total
historical revenue per customer) or order amount (a single order's total)?
- lifetime value — customers.customer_lifetime_value
- order amount — orders.amount拒绝和澄清都算是一种 result 而非 error:dst 更多是要发问,而不是猜。
快速开始
安装包。先决条件:Python 3.12+、Docker(dst 用它自己的 PostgreSQL 运行),以及至少一个 model provider 的 API key:Anthropic 或任何支持 openai 兼容端点的供应商(DeepSeek、Ollama、vLLM、Groq,以及大部分网关)。
pip install dst-core # the CLI is `dst`
dst init analytics --warehouse demo --yes
cd analytics # put your provider key in the generated .env
dst dev # Postgres up + migrate + serve, one command
# in a second terminal, same directory
dst bootstrap --org me --email you@example.com
dst apply
dst query customer_value "How many customers are repeat customers?"dst init 会在一个捆绑的 jaffle DuckDB warehouse 上搭建一整个项目,并且同时保留( apply 和 query 都可以在你连接真实仓库之前就能工作。这个 release wheel 已经带着 migrations 和 dashboard,所以你可以自己 run dst dev,两个都不动,都挂着后端 http://localhost:8000。quickstart 是主路线,并会把这同一套路线引申到您自己的 warehouse。
从源码运行
贡献者的路径:一份源码检出(checkout)、仓库自带的 Makefile,以及由 Vite 构建(而非打包)的仪表盘。前提条件:以上内容,外加 uv、Node 22+ 和 pnpm。
# 1. Backend deps
make install # uv sync
# 2. Configure — create .env in the repo root (see "Configuration" below)
echo 'DST_PROVIDERS={"anthropic": {"type": "anthropic", "api_key": "sk-ant-..."}}' > .env
# openai-compatible works the same:
# {"ollama": {"type": "openai-compatible", "base_url": "http://localhost:11434/v1", "api_key": "unused"}}
# 3. Start Postgres (pgvector), run migrations, seed an org + admin token
make up
make migrate
make seed # prints a dstadm_… admin token — copy it
# 4. Run the API (http://localhost:8000)
make dev然后是仪表盘:
cd apps/web
pnpm install
pnpm dev # http://localhost:5173打开仪表盘,将右上角的 dstadm_… 管理员令牌粘贴进去,即可治理该组织:审核队列、漂移审计、调用方、成本。Lens 本身以文件形式编写:uv run dst init 会在随附的 jaffle DuckDB 数据仓库上生成一个 Lens,因此在连接真实数据仓库之前,uv run dst apply 和 uv run dst query 就能正常工作。源码检出不会把 dst 放到你的 PATH 上——每条命令都以 uv run dst … 的形式运行,Makefile 目标正是这样实现的。
如果要让某个 agent 查询某个 Lens:在 Settings 中签发一个 caller key,把它加入 lens.yaml 中该 Lens 的 allow-list,然后运行 uv run dst apply,最后通过 MCP 连接该 agent。
配置
设置从 .env 加载(见 services/config.py)。常用键:
变量 | 是否必填 | 用途 |
| 是,至少一个条目 | 模型提供方,按名称组织 JSON(BYOK;不要使用以厂商命名的键变量)。类型: |
embedding provider | 上下文功能需要 |
|
| 可选 |
|
| 需要存储凭据时 | 用于加密已存储的数据仓库/上下文凭据的 |
| 本地默认即可 | 应用(强制 RLS、非超级用户)和管理(迁移/种子)连接。 |
| 可选 | 托管仪表盘的身份认证;没有它也不影响本地登录和管理员令牌。 |
数据仓库和检索源凭据不是环境变量:请在 dst.yaml 中用 secret_env 引用声明连接(见 quickstart)。.env.example 由 services/config.py 生成:它是一份完整、永不过时的配置表面。
项目布局
services/ FastAPI app (services.app:app)
api/ control plane (/mgmt/*) + data plane (/v1/*)
contracts/ lens config, semantic model, protocols
connectors/ warehouse connectors
context/ embedding providers + the serving error surface
runtime/ the query pipeline (ground → guard → execute → compose)
reviews/ AI-judge + human review queue
governance/ access policy, credentials, rate limits, audit
mcp/ remote + stdio MCP server (see its README)
apps/web/ React + Vite dashboard
migrations/ Alembic migrations
fixtures/ built-in jaffle DuckDB warehouse开发
命令 | 作用 |
| 启动 / 停止本地 Postgres(pgvector) |
| 应用数据库迁移( |
| 填充一个开发组织和管理员令牌 |
| 在 :8000 上热重载运行 API |
|
|
| 自动格式化 + 修复 |
| 后端测试( |
| 在 :5173 上运行仪表盘 |
架构:FastAPI 后端(lens 配置、context 向量存储、请求 trace、审核)架构基于 Postgres + pgvector,并从你的数据仓库读取数据;结果集本身不会被持久化。trace 保留的是问题、SQL、组合后的答案及其引用;只有 lens 通过 logging.log_samples 开启时,才会保存前几行结果。数据仓库 profiling 同样会存储每列的统计信息和低值列表;exclude_columns 中提到的列只读取其结构,值不会被收集。dst 不会自动分类或脱敏个人数据:不要暴露你不希望值离开你网络的列。仪表盘是一个同源或拆分的 React SPA。
用户文档位于 docs/(quickstart、概念、指南、参考),并发布在 https://www.dataservetool.com;贡献者子系统地图请见 ARCHITECTURE.md。
许可证
Apache-2.0。贡献:CONTRIBUTING.md · 安全漏洞:SECURITY.md · 问题与反馈:github.com/get-dst/dst/issues。
This server cannot be deployed
Maintenance
Related MCP Connectors
The grounded data layer for any LLM: governed SQL, metrics, lineage and catalog over your data.
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceEnables natural language querying of Microsoft Fabric Data Warehouses with intelligent SQL generation, metadata exploration, and business-friendly result summarization. Features two-layer architecture with MCP-compliant server and agentic AI reasoning for production-ready enterprise data access.-
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to understand and query your database safely by providing a semantic layer of metadata, with tools to search, explain, validate, and generate safe SQL.2MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to search, explore data lineage, understand business context, and generate SQL queries across an organization's data ecosystem.Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnforces safety and governance for SQL queries executed by AI agents, providing read-only enforcement, cost estimation, and audit trails.Apache 2.0