开源 · Apache-2.0 · 可自托管 · 只读接入你的数据

Trove 数据决策智能体

问数 · 分析 · 决策 · 行动,一条对话链路

把一句自然语言提问,变成可解释的 SQL、图表与结论; 判定规则在同一份语义模型上定时求值——季节噪声带判显著性,触发即带着证据送达; 行动发生在你的流程里(系统对业务数据保持只读),送出之后按同一套噪声带做效果验收。 Trove 把确定性押在语义模型、节点化工作流与确定性安全层上, 只把真正需要模型的那一段交给 LLM。

English summary Trove is a data decision agent: questions, analysis, decisions and action in one conversation. It turns a natural-language question into explainable SQL, a chart and a written conclusion, and evaluates zero-LLM judgment rules on the same semantic model — each trigger arriving with the SQL and rows it was judged on, while the action itself stays in your own processes (Trove keeps read-only access to your data) and is measured back against the same noise band afterwards. It is semantic-first: an OSSIE semantic model defines what is answerable, and a deterministic compiler resolves joins, enums, time buckets and derived metrics — the LLM only handles what genuinely needs a model. This page is the entry point to the docs: quickstart, illustrated user / admin guides, and per-capability source anchors.
一条链路 · 问数 → 分析 → 决策 → 行动 零 LLM 确定性 模型参与 闸门(能拦)
一条链路:问数 → 分析 → 决策 → 行动,终点在外部系统。主行下方四行是每段自己的内部管线:靛蓝描边的节点由模型参与,琥珀描边的是闸门,其余为零 LLM 的确定性步骤;行动的效果验收有一条虚线回环到决策的质量回评

问数管线 28 节点(默认配置) · 8 方言适配器 · 8000+ 条测试(零网络零密钥) · 0 LLM 调用的回归门

全貌 · 01

一句话提问,一份可核对的答案

一个可自托管的问数分析 Agent:接入你自己的库,用自然语言提问,拿到 SQL、图表和一段有依据的结论。 提问与修正会沉淀进该数据源的知识库,准确率随使用增长。

Trove 问答界面(右侧「分析过程」面板展开):提问气泡、结论、结果表、数据截止时间与置信度、洞察、出处条;分析过程共 13 个步骤、总耗时 9.4s——意图路由、表关联、查询计划、生成 SQL、语义、执行 SQL、校验、反思、洞察、图表、结论、最终回答、思考 1 2 3 4
图 1 · 一句话提问,一份可核对的答案:左边是给人读的(结论 → 数据 → 出处),右边是给核查用的「分析过程」——13 个步骤记录这条答案是怎么一步步算出来的,每步带耗时、可展开。
  1. 1结论——一句话给出答案本身。先读这里;数字有疑问再往下核。
  2. 2数据截止时间与置信度——截止时间是这次查询所依据数据的时间边界,无从判断时如实写「无从判断」,不猜一个日期。
  3. 3出处条——数据源、模型与运行 ID,加「KB 命中」与「校验 OK」两枚状态章。答案解剖 →
  4. 4分析过程——这条答案是怎么一步步算出来的:意图路由 → 表关联 → 查询计划 → 生成 SQL → …… → 最终回答,各带耗时,随时展开核对。分析面板 →
# 内置 BIRD 金融演示数据源,装完即可问
uv run trove --datasource demo

# 一次性提问,输出 JSON
echo "哪个地区的平均贷款金额最高?" | uv run trove-cli --datasource demo --print

系统的形状——入口、编排、能力层与数据源各是什么——见 系统架构 · 全貌。

链路 · 02

分析 · 决策 · 行动

问数回答「是多少」。这条链路还有三段——分析回答「为什么变了」,决策回答「该不该警觉」, 行动把触发变成一份等人拍板的提案,并在事后验收效果。三段与问数共用同一套纪律: 数字由确定性引擎算出来,模型只写解读,每个数字都带着可复算的证据。

分析 ——「为什么变了」

问「为什么……」「什么导致……」时,不走生成 SQL,走确定性分解:先按贡献最大的维度把总变化拆开 (贡献分解 / 比率 shift-share),再沿指标表达式下钻成驱动器树。每个数字都由可复算的查询算出来、进证据, LLM 只把结果写成一句人话。「变了多少才算变了」由稳健 z 与历史同粒度块的噪声带回答—— 超出噪声带 / 落在带内 / 判不了,三态如实;判不了绝不冒充「没变化」。

归因分析卡:卡片头的已声明度量章与「归因 · 分解」标记,总变化与主维度,分类瀑布图、维度贡献表(基期 / 当前 / Δ / 贡献)与证据入口 1 2 3 4
图 2 · 归因分析卡:总变化被拆到主维度的每个分类上,瀑布、贡献表与证据里的 SQL 同源同数——分解是确定性的,只有解读是模型写的。读法见 用户指南 · 归因分析卡。
  1. 1已声明度量——归因沿语义模型声明过的指标解析(这里是 max_loan_amount);「归因」标卡片类型,「本期」标基线口径。
  2. 2总变化与主维度——一句话说清变化多大、沿哪个维度分解(这里是 loan.status)。
  3. 3分类瀑布与贡献表——每个分类的增减推演与贡献占比;度量可分解时,贡献表下面还会多一段沿表达式逐层拆的驱动器树。
  4. 4证据(查询 N)——这次归因实跑过的查询清单,当期与基期各一条,每个数字都能复算;哪一步没做成以 degraded 如实记在这里。

决策 ——「该不该警觉」

阈值规则直接用语义模型自己的词汇声明:指标、维度、过滤、时间窗——声明一次,每次求值都按它执行, 判定过程零 LLM;「变了多少才算警觉」同样交给季节噪声带:超出才触发、在带内不打扰、判不了如实报。 每条判定都留着它当时判的 SQL 与原始结果行;规则文件每次改动都是一次 git 提交,判定史按规则版本分桶回评。

判定历史抽屉(loan-high):每条判定带级别与一句话消息,展开的一条显示证据 SQL、原始结果行与判定行(当期 / 基期 / Δ / Δ% / 结论);相邻判定用芯片标出关系——与上次相同 / 规则已修改 / 无前次可比;左侧是判定质量卡,按规则版本分桶 1 2 3 4 5
图 3 · 判定历史:一次触发留下了什么——当时跑的 SQL、原始结果行、判定行,以及它与上一次的关系(与上次相同 / 规则已修改 / 无前次可比)。判定不可编辑,这是它被判定时的数字原样。读法见 判定规则 · 判定历史。
  1. 1一条判定——时间、级别(alert / ok / error)与一句话结论;下面的芯片是相邻 diff 的一句话。
  2. 2证据 · SQL 与原始结果行——判定当时真正执行的那条查询,与它判到的数字原样。
  3. 3判定行——分组、当期、基期、Δ、Δ% 与结论逐项列出;维度不足时照实呈现,不补造。
  4. 4更早的判定——逐条同样带芯片;「无前次可比」也是一枚芯片,而不是一个消失的区块。
  5. 5判定质量——判定史按规则版本分桶回评:触发率、行动有效 / 无变化 / 测不了的条数;样本不足不报比率。

行动 ——「接下来做什么」

判定触发不会只发一条通知了事:它冻结成一份行动提案——载荷在创建那一刻定死,之后谁批准, 外送的就是那一份;批准之前,任何东西都不会离开系统。批准后外送走 webhook / IM,回执逐条落库; 行动之后还会用与判定同一套噪声带复测「数字动了没有」——超出 / 无变化 / 判不了,三态如实。 系统自身没有写回业务库的通道,这是构造上的保证,不是配置开关。

管理台「行动」页的提案页签:页头写明「行动只提议、不触碰业务库」,一条待批准提案(loan-high → loan-baseline-alert,风险中)与行尾的批准 / 拒绝 / 详情 1 2 3
图 4 · 行动:判定命中后生成的提案在这里等人拍板——模板先过确认门,提案经批准才外送,回执逐条落库,验收用与判定同一套噪声带。读法见 行动与审批 · 提案生命周期。
  1. 1只提议,不触碰业务库——页面自己写明的姿态:批准之前,任何东西都不会离开系统。
  2. 2载荷创建时冻结——批准外送的就是抽屉里看到的那一份。
  3. 3一条提案与行尾动作——规则、模板、风险、数据源与创建时间;批准之后才会出现「外送」等后续动作,回执与效果验收都记在这一条的详情里。

逐条展开:判定规则、因果升级与 what-if 见 判定规则; 提案、审批与效果验收见 行动与审批;分解数学与统计器械见 分解数学与驱动器树 与 统计与噪声带。

入口 · 03

从这里开始

第一次来,按「快速上手」走一遍;想先建立心智模型,看「产品概念」;要对着界面操作,走图文指南。

方法 · 04

为什么语义优先

大多数问数系统的准确率上限押在模型和检索上。Trove 换了一个问题: 这个数据源到底能回答什么——把这件事用一份可读的语义模型写清楚, 先划定边界,再谈生成。语义模型是生成的主视角,也是可答边界; 但它不是一道全有全无的闸门——编译结果是分级的,能答多少答多少,答不了的说清楚为什么:

命中 HIT
编译器直接产出 SQL。join 路径解析、枚举词归一、时间分桶、派生指标与比率指标递归内联, 全部在确定性代码里完成,不走模型。
软 MISS
产出骨架,按计划补齐。词表、枚举值、未声明口径这类缺口会留下 PartialCompile:能解析的部分(join、过滤、分组)先权威化, 剩余组件交给生成节点按计划文本补齐,回答照常交付。
硬 MISS
拒绝,并反问怎么把模型扩起来。结构性缺口——fan-out、join 二义、未覆盖的表、坏掉的派生定义—— 拒绝硬猜,改为向用户澄清口径,并把这次澄清沉淀成语义模型的扩展建议。

而这份语义模型不只是「指标 + 维度」的清单:数据集可以声明成对象(业务名、自然键、别名), 表间连接可以声明成关系(业务名),维度链可以声明成层级(粗 → 细)—— 声明一次,答案表头、拒绝出口、分析取哪一级、判定与行动通知都改说业务的词。 它没有自己的存储,就是 semantics.yml 里的三段声明: 见 本体。

边界 · 05

安全与可核对

问数系统要落地,安全边界不能是提示词里的一句请求。以下八条都在链路上生效—— 它们全部是代码,不是模型行为。

机制做什么位置
只读语句防火墙 对 SQL 做 AST 解析后判定,非只读语句在执行前被拒——不靠关键字黑名单。 services/sql/guard.py:50 check_readonly
执行代价护栏 执行前估算扫描行数(EXPLAIN 档,拿不到则退到元数据画像档),三路径判定:放行 / 降级加 LIMIT 执行 / 拒绝。估算不出来时走降级,而不是放行——没有下层兜底,所以这一轨 fail-closed。 services/sql/budget.py:136 BudgetService · :236 decide
执行前授权门 执行前判定,三道依次是 A1 主体存在 → A2 数据源在 grants 内 → A3 SQL 引用的表在语义层声明内。三道默认全拒:A1/A2 恒拒无开关;A3 默认 enforce(2026-10 切换,依据是全量快径示例 SQL 静态核验违规 0 条)。存量部署可显式写 authz.table_enforcement: warn 回退到观察档。 services/authz/enforcer.py:84 Authorizer · core/config.py:81 AuthzConfig
组织守卫(guard 档) 管理员把 SQL 断言写成声明式条件(select_star、join_count、has_time_predicate 等九变量闭集),在授权门之后、执行之前零 LLM 判定:明确违反即拦、回滚到生成侧收窄;判不了绝不拦——缺失基线或类型不匹配记为「判不了」,不会把否定式断言翻成假阳性。 services/skills/guards.py:55 GUARD_VARIABLES · workflow/nodes/execute_sql.py:62 ORG_GUARD_TAG
字段级脱敏 结果集在进模型上下文之前按语义层声明改写(partial / hash / null);声明了 hash 却取不到 salt 即拒绝执行,不降级为明文。 services/authz/masking.py:327 Masker
不可信内容隔离 值进入模型上下文只有两条通道,两条都过同一个隔离核:命中注入短语即把整个值作废成中性标记,而不是剪掉命中的那一段(模型不能以为自己拿到的是不完整但可用的数据)。截断排在隔离之后,否则长文本里的注入串会被从中间切断、正则漏判。 llm/untrusted.py:86 isolate_tree · prompts/loader.py:71 _isolate_vars
人在环与审计 SQL 执行前可交人过目,载荷无法识别时默认拒绝——这道门只在能读懂输入时才开。拒绝、字段改写、凭 scope 读原文三类各记一条审计(只记字段名与模式,从不记值)。 workflow/nodes/hitl.py:65 make_hitl · agent/session.py:1903 _audit_authz
语义模型单一写入口 草稿确认、自动门放行、变更合入都收敛到同一个写盘函数,且合入前先判:基准快照与主线现文件不符、载荷应用失败或有阻断级 lint,都在第一个字节落盘之前拒绝(主线零改动)。「自动批准」标记没有 HTTP 入口——客户端可控的参数会让审计标记可伪造。有一条 AST 守卫逐个文件钉住这条边界。 services/semantic_layer/changes.py:367 _write_merge · api/routers/semantic.py:614 merge_semantic_change

更多机制——工具权限裁剪、模型预算护栏、以用户身份重放——见 安全边界与 Agent 能力总览的逐条展开。

答案依据抽屉:来源档位、生成的 SQL、执行与计划要点、结果集预览、校验与反思记录、反馈入口、运行轨迹
图 5 · 每条答案都能展开「查看依据」:执行的 SQL、执行与计划要点、校验与反思记录——数字可疑时先读这里。读法见 用户指南 · 依据抽屉。
界面 · 06

界面:用户端与管理台

用户端只做三件事——提问、读答案、核对依据(上文图 1、图 5 即是); 管理台负责接入、建模与治理。逐屏读法见 界面导览 与 管理指南。

管理台总览:健康横幅、六项 KPI、数据源健康表、待办队列与接入向导
图 6 · 管理台总览:健康横幅、KPI、数据源健康表与待办队列——一屏回答「今天平台健康吗」。读法见 管理台总览。
语义模型工作台:摘要行、五项 KPI、问题面板(校验问题与漂移)、指标/数据集/字段/待审批四个 tab 与资产表
图 7 · 语义模型工作台:摘要、校验问题与漂移、指标 / 数据集 / 字段 / 待审批四个 tab——可答边界在这里维护。读法见 语义层治理。
本体页:对象 8 / 链接 8 / 层级 1、声明覆盖率 100%;对象图节点用业务显示名、连线带业务名与基数;右侧是选中「银行账户」的声明(自然键 account_id、别名 账户 / 账号、业务度量、出入链接);底部为地区层级 A3 → A2
图 8 · 本体页:语义模型的只读投影——对象(显示名 · 自然键 · 别名)、链接(业务名)与层级(粗 → 细)同屏,声明覆盖率即「模型替业务说了多少话」。读法见 本体。
验证 · 07

怎么验证,而不是信谁的数字

这个页面不给准确率数字。问数系统的准确率高度依赖数据集、方言、语义模型完备度, 不同口径的数字放在一起没有意义——而且换个数据源就作废。所以这里给的是复现路径。

# 1. 换成你的题目集跑评测,代价敏感,按需手动跑
uv run python scripts/eval_bird.py --kb-dir <你的 KB 目录>

# 2. 拿到 baseline 后,之后每次改动都过一遍零成本回归门
uv run python scripts/eval_gate.py --baseline <旧结果> --current <新结果>

# 3. 扩展资产装上之前,先试跑再回放——同样零 LLM,--json 直喂同一道门
uv run trove validate --run --datasource <你的数据源>           # 装 / 不装 双态消融
uv run trove validate --impact <包或目录> --datasource <你的数据源>  # 影响面四桶差分

第 2 步是这套评测设计的关键:判定落盘之后,回归检查不调用任何模型、不碰网络, 所以它可以进 CI,也可以在你提交前顺手跑一次。同一道门也吃第 3 步的输出: 新技能、判定规则、预设装上之前,先用本机语料装前试跑与影响面回放—— 和评测共用一份语料、报告直喂 eval_gate.py。完整方法见 评测与回归门。

定位 · 08

这套设计押在哪

把确定性押在可编排的节点化工作流、多库多模型抽象与确定性安全策略层上,而不是押在模型与检索的单点强度上——所以跨厂商、跨方言下行为更可预期。

Design bet: put determinism in an orchestratable node graph, a multi-database / multi-model abstraction, and a deterministic safety layer — rather than in the strength of one model or one retriever.