mcpField
M
Misata: synthetic data library

Misata: synthetic data library

本地服务
misata.studio开发工具722 天前更新

关于 Misata: synthetic data library

Misata 是面向 Python 数据工程和测试的声明式合成数据生成库。用户描述数据必须满足的约束,系统据此生成多表数据,并用 DuckDB 独立复核、生成可重跑的证明。

主要功能

  1. 01用 YAML 声明数据约束
  2. 02生成关联的多表数据
  3. 03从 SQL DDL 构建数据
  4. 04用 DuckDB 重验不变量
  5. 05生成数据证明与校验脚本
  6. 06支持流式及分区输出

适用场景

  1. 01为数据管道测试构造确定性样本
  2. 02验证 dbt 模型的预期结果
  3. 03生成满足外键和账目约束的夹具
  4. 04为团队分享附带可验证证明的数据

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"rasinmuhammed-misata": {
"command": "uvx",
"args": [
"misata"
]
}
}
}
启动命令uvx misata

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypimisata0.9.8

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Misata

Misata

声明必须满足的条件。生成符合条件的数据。证明结果。

Misata 是一个面向 Python 的声明式合成数据生成器。你只需写下数据集必须满足的事实,从每月收入曲线、平衡账本,到绝不允许悬空的外键;引擎便会构建同时满足所有条件的多表数据。随后,DuckDB 会检查磁盘上的文件,并生成任何人都能重新运行的证明文件。

PyPI Python Tests License Open in Colab smithery badge

文档 · 用例 · 语言 · 限制 · Studio · 更新日志


六十秒上手

pip install "misata[duckdb]"
# misata.yaml
seed: 7
tables:
  customers:
    rows: 2000
    columns:
      customer_id: {type: int, unique: true, min: 1, max: 2000}
      name: {type: text, text_type: name}
      signed_up: {type: date, start: "2024-01-01", end: "2024-12-31"}
  orders:
    rows: 40000
    columns:
      order_id: {type: int, unique: true, min: 1, max: 1000000}
      customer_id: {type: foreign_key}
      channel: {type: categorical, choices: [web, app, store]}
      amount: {type: float, min: 5, max: 900}
      ordered_at: {type: date, start: "2025-01-01", end: "2025-12-31"}
relationships:
  - customers.customer_id -> orders.customer_id
outcome_curves:
  - table: orders
    column: amount
    time_column: ordered_at
    start_date: "2025-01-01"
    curve_points:
      - {month: 1, target_value: 180000}
      - {month: 6, target_value: 240000}
      - {month: 12, target_value: 310000}
group_shares:
  - table: orders
    measure: amount
    group_column: channel
    shares: {web: 0.5, app: 0.3, store: 0.2}
misata generate -c misata.yaml -o data --attest
python data/verify.py
Attestation: data
  result: PASSED
  files pinned: 2
  invariants held: 69 of 69

ok    2 file(s) match their attested sha256
ok    69 of 69 invariant(s) hold

这 69 项在生成任何行之前,就已根据 YAML 推导得出:十二个月的收入总额(一月为 180,000.00,六月为 240,000.00,十二月为 310,000.00,中间月份按直线递增)、每个月内的渠道占比、每月计划行数、没有悬空的 customer_id,以及唯一键。verify.py 只需要标准库和 duckdb,且不与生成器共享任何代码。

快速入门示例按月生成并汇总的数据。十二个堆叠柱分别按 web、app 和 store 渠道划分,从一月的 180,000.00 上升到六月的 240,000.00,再到十二月的 310,000.00。每个柱形的总额都恰好等于声明的月度总额,各渠道占比分别为 50%、30% 和 20%。48 个总额和单元格中,声明值与生成值的最大差额为 0.00。

上方 YAML 按月份和渠道生成并汇总的结果。每个柱形代表一个月的生成收入,按渠道划分;顶端标记为 YAML 声明的总额。该图由 readme_charts.py 根据本 README 中的 YAML 重新运行生成。

只要有一行偏差一分钱,它就会指出来:

FAIL  orders.csv: sha256 301165f9dc4e does not match the attested 670f89195826
FAIL  orders.amount.month:1.outcome_curve_period: expected 180000.00, observed 180000.01
FAIL  orders.amount.outcome_curve_total: expected 2945000.00, observed 2945000.01
FAIL  orders.amount.web.2025-01.group_share_period: expected 90000.00, observed 90000.01
FAIL  orders.amount.web.group_share_total: expected 1472500.00, observed 1472500.01
FAIL  65 of 69 invariant(s) hold

为什么要声明,而不是生成

每个测试夹具都有预言机问题。要检查 dbt 模型、Spark 作业、 仪表板图块或数据 Agent,你需要输入数据,也需要一个独立于被测代码而得出的已知答案。复制生产数据能提供数据,却没有答案。手写夹具能提供答案,但会逐渐失效。随机生成器能提供数据,但你必须用正在测试的代码来计算答案。

Misata 扭转了这一做法。规范是真值,行数据由规范推导而来。“1 月收入是 180,000”在任何行数据产生之前就已成立,因此你的流水线要么返回 180,000.00,要么就是有缺陷。

flowchart LR
    A["Declare<br/>curves, shares, ledgers,<br/>keys, lifecycles"] --> B{"Can they<br/>all hold?"}
    B -- "no" --> R["Refused, with the<br/>arithmetic and a fix"]
    B -- "yes" --> C["Build rows<br/>closed form where it can,<br/>by construction elsewhere"]
    C --> D["Write<br/>CSV, Parquet, JSONL,<br/>DuckDB, Postgres"]
    D --> E["Attest<br/>DuckDB re-runs every<br/>derived invariant"]
    E --> F["Certificate<br/>in-toto Statement<br/>plus verify.py"]

以下三个特性使它不同于带选项的生成器:

  • 声明会被遵守,或被拒绝,绝不会悄悄替换。 如果声明无法同时成立,生成过程就会停止并报错,指出每项声明、 展示计算过程并建议如何修改。
  • 证书由未参与数据生成的代码进行检查。 Misata 算术中的错误会表现为不变量检查失败,而不是得到一个自洽的错误答案。
  • 相同的规范、种子和版本会在 Linux、macOS 和 Windows 上生成相同的字节,因此夹具可以连同其指纹一起存入 git。

未来方向

Misata 的目标是:不再有人编写 Python 脚本来生成任何类型的数据集。你只需说明需要满足什么条件;引擎会计算出各行数据,拒绝无法成立的要求,并证明它生成的内容符合要求。

目前还未实现这一目标,但正一步步接近。每个版本都会增加可声明而非编程实现的功能。只有通过三项测试,才能添上一块砖:只需几行 YAML 就能声明;与其他声明矛盾时,会在生成前拒绝;生成后,还会由未参与生成的代码对各行数据进行重新检查。

一面由砖块组成的墙,每块砖代表 Misata 目前支持的一项保证,共分三层:键、规则和关系,例如外键、唯一键和 CHECK 规则;精确计数与总和,例如 outcome_curves、rate_curves 和 group_shares;以及状态、结构、时间和特征,例如 lifecycles、dag_edges 和 time_grids。DuckDB 证书会重新检查的砖块以填充样式显示。墙上方还有尚未完成的一层虚线砖块,代表仍需手动编写脚本的部分。

每块砖都代表一项可通过声明而非代码实现的功能。内容取自 misata/registry.py,这是契约测试用来约束代码的清单,确保墙上不会出现引擎尚不支持的砖块。


一个事实,两种实现方式。 要让事实成立,脚本必须完成什么,以及你可以改为如何声明:

事实在生成器脚本中在 Misata 中
1 月收入为 180,000.00抽取金额、求和、重新缩放、四舍五入,再反复调整最后一分钱{month: 1, target_value: 180000}
每个月的收入中,web 占一半在每个月和渠道内重新缩放,然后修复刚刚破坏的月度总额shares: {web: 0.5, app: 0.3, store: 0.2}
每笔订单都有真实客户从父表中抽取 ID,并确保两边保持同步customers.customer_id -> orders.customer_id
一些流失客户此前曾处于活跃状态按状态分支、按顺序写入时间戳、其余置空,再手动计数transitions: [[trialing, active], [active, churned]]
1% 的转账构成洗钱模式,且模式比例固定手动构建每个环路和扇形结构,再证明背景数据自身不存在环路rate: 0.01 和 shares: {cycle: 0.4, fan_in: 0.25, ...}
试算平衡表的余额为零为每笔分录记录借贷两方,并在最后进行核对对日记账分录应用 balanced_ledger 约束

仍需编写代码的部分及其当前状态:

仍需手动编写脚本当前状态
Misata 无法反推的逻辑预期输出:窗口函数、自定义 SQL、业务规则misata solve 会运行你真实的 dbt、SQL 或 Python 流水线,使结果达到声明的数值及指定容差;超出该范围后,预期值需要由你编写
只能通过示例描述的相关性misata.mimic 会从真实数据行中拟合相关性,生成结果并非匿名数据
带有独特语气的自由文本文本由语法生成,并与所在数据行一致;目前还无法声明读起来像人工撰写的文本
版本历史(SCD2)和库存变化轨迹可生成满足平衡要求的数据,但尚不能逐步声明
文档、图像和音频尚未开始

LIMITATIONS.md 列出了完整清单。当某项内容从此表中移除时,意味着取代它的砖块已经通过了全部三项测试。

证据

The Gauntlet,每个部分通过的断言数。Misata 通过 136 项中的 136 项。使用相同列的 Faker 脚本通过 136 项中的 78 项:它在键、值域、菱形联接、算术和分布方面打平,在时间顺序、状态隐含字段、跨表总数、地理位置、生命周期、缺失值、延迟到达和网格方面不及 Misata。

The Gauntlet:13 张表和 136 项 SQL 断言,由 DuckDB 执行。Faker 脚本只要事实涉及单列就能打平;凡是列、行或表之间必须保持一致的地方,它就会落败。源代码,可用 python -m benchmarks.gauntlet 重新运行。


检测 AUC,越低越好;0.5 表示分类器无法区分生成行与真实行。Olist 订单:根据声明式架构生成的 Misata 为 0.63,根据一句描述生成的 Misata 为 0.73,Faker 脚本为 0.78,使用真实数据训练的 SDV 为 0.71,Misata 模仿模式为 0.54。纽约市出租车行程:依次为 0.75、0.80、0.79、0.68 和 0.54。

梯度提升分类器尝试区分生成行与真实行;取五个随机种子的均值。在未查看任何真实行的情况下,声明式架构的表现优于使用真实订单训练的 SDV。在出租车行程数据上,SDV 胜出:盲猜车费的表现不佳。源代码,数字见 summary.json。


声明测量结果重现方式
按构造保证有效在五种 DDL 架构上,键、CHECK、UNIQUE、NOT NULL 和自引用树均无违规。逐列生成的 Faker 脚本:每种架构有 15,014 至 50,416 项违规。使用有效数据训练的 SDV 多表模型:有 3,055 至 5,557 项违规,且拒绝处理五种架构中的两种python -m benchmarks.validity_bench
符合性三个测试套件共包含 294 项 SQL 断言,全部通过:The Gauntlet 136 项、The Warren 110 项、The Ledger 48 项python -m benchmarks.gauntlet
可复现在 Linux、macOS 和 Windows 上生成相同的指纹python -m benchmarks.golden
规模在 Apple M1 上以 0.78 GB 的峰值内存,在 36.3 秒内生成分布于 14 张表的 10,000,000 行数据,之后检查每个外键python benchmarks/bench_r3_volume.py --scale 10 --stream out/

可以声明的内容

每项声明都有可测试的保证、所属列列表、成本和拒绝条件。LANGUAGE.md 是参考文档。所有 25 种声明类型都会在行生成前进行可行性检查,并在生成行后再次检查;标有 ✓ 的类型也包含在 DuckDB 证书中。

声明保证内容证书
outcome_curves每个期间内某项指标的总量,精确到分✓
rate_curves每个期间内标记行所占的比例,精确到行✓
group_shares每个期间内各组在某项指标中的占比✓
balanced_ledger每笔分录的借方等于贷方,且试算平衡为零✓
waterfalls每个组成部分的期初值加变动等于期末值✓
relationships、min_children、partition_by无孤儿记录、父记录至少有一个子记录、键不会跨越租户✓
unique、inequality、col_range、choices、NOT NULL、DDL CHECK没有行违反规则✓
lifecycles状态意味着完整的历史记录:应有的时间戳齐全且顺序正确,其余时间戳为空✓
dag_edges、graph_motifs除预设案例外没有环;每种环、扇形和链的数量都精确✓
汇总、stock_flows、scd2、bitemporal、when_then、lte_parent父项等于子项、库存保持平衡、各版本完整覆盖时间线
outliers、typos、duplicates、missingness、late_arrivals脏数据数量精确,并附有答案
retention、joint_distributions、time_grids、event_logs、processes队列曲线、联合边际分布、声明的时钟,以及与状态一致的日志

无论声明什么,外键都会通过构造方式解析(先构建父记录,再构建子记录);文本与所在行相符,金额呈偏态,时间戳具有每日节律,且少数客户会下大多数订单,因此即使不做任何声明,数据看起来也像真实业务数据。输入一句话即可选择 18 种故事领域之一,从 SaaS 和金融科技到医疗保健、物流和流媒体;每种领域都有自己的表、键和校准分布。


选择入口

你有调用方式备注
一句话misata.generate("A SaaS company with 1,000 customers", seed=42)最快上手;打印表,或运行 misata explain 查看生成内容
YAML 或字典misata.generate_from_schema(schema)所有声明都必须成立,否则会拒绝
SQL DDLmisata.from_ddl(ddl) 或 misata generate -c schema.sql支持 NOT NULL、UNIQUE、复合键、CHECK 范围和枚举、自引用
正在运行的数据库misata seed postgresql://...会检查数据库结构并在一个事务中插入数据;除非传入 --truncate,否则绝不清空表
dbt 项目misata dbt-unit-test --select my_model从键相符的 manifest.json 生成测试数据
Prisma 或 Djangomisata prisma-seed、misata.from_django(app_labels=[...])
超出内存容量的行数misata.generate_stream(schema)生成 (table, batch);按分区输出 Parquet,每个分区一个文件
输出必须达到指定数值的流水线misata solve -c solve.yaml将输入送入真实的 dbt 或 Python 流水线,达到声明的结果并满足指定容差
要分享的数据集misata publish data --hf you/name重新验证后,连同数据规范、证书和验证器一起上传
可供模仿的真实行misata.mimic(df)基于真实行拟合;并非匿名数据

每次都传入种子。同一种子会生成相同的数据。


十二个配方

每个配方都是一个文件夹,包含模式、命令,以及证明声明成立的检查。每次发布前,tools/stranger.py --clean 都会在全新的虚拟环境中,从刚构建的 wheel 运行每个页面上的所有命令,因此页面上的数字就是你实际会看到的结果。

配方适用对象验证结果
为开发数据库填充种子数据应用开发者、编码 Agent根据三个 CREATE TABLE 语句生成 22 条不变量
dbt 的已知答案测试分析工程师能捕捉月末最后一天错误的 dbt 测试
用户到来前准备好数据仓库创始人、数据负责人291,000 行分区 Parquet 数据,80 条不变量
演示租户销售工程师、产品经理已流失和健康的账户,以及少数巨鲸账户;逼真度 0.96
评测数据库AI 实验室、评测团队在三个轮换使用的数据库上验证文本转 SQL 的答案
Agent 沙箱Agent 构建者沙箱与评分器逐行一致
负载测试平台工程师热点键和每日曲线;重放前检查键
欺诈与 AML风险与 ML 团队无环背景数据,且每个关系环都符合声明的数量
可对账的分类账财务工程、审计两个财年、52 条不变量,试算平衡为零
带回家的练习招聘团队、课程作者每位候选人都有不同的答案密钥,且均经过验证
不含 PII 的环境受监管团队根据生产 DDL 生成暂存数据,绝不使用生产行
文档示例数据DX、API 和 SDK 团队嵌套 JSONL,ID 可跨文件解析

状态蕴含其历史

只需声明一次状态机,每一行的时间戳都会根据其状态生成。摘自演示租户:

stateDiagram-v2
    direction LR
    [*] --> trialing
    trialing --> active
    trialing --> churned
    active --> past_due
    active --> churned
    past_due --> churned
lifecycles:
  - name: subscription
    table: subscriptions
    state_column: status
    start_column: started_at
    initial: trialing
    states:
      - {name: trialing}
      - {name: active, timestamp: activated_at}
      - {name: past_due, timestamp: past_due_at}
      - {name: churned, timestamp: churned_at, terminal: true}
    transitions:
      - [trialing, active]
      - [trialing, churned]
      - [active, past_due]
      - [active, churned]
      - [past_due, churned]
    weights: {trialing: 0.07, active: 0.6, past_due: 0.07, churned: 0.26}

1,200 个订阅中,恰有 720 个处于活跃状态、312 个已流失、84 个逾期,另有 84 个仍在试用期:权重表示数量,按最大余数法分配,而非概率。每一条逾期记录都有激活日期和逾期日期,顺序如此,且都晚于开始日期;活跃记录没有流失日期。证书会逐行检查这两点。一个状态若有多条可达路径,其记录会分布到每条路径上:312 个已流失订阅中,156 个在试用期间离开,78 个在活跃后离开,78 个在逾期后离开。

演示租户中的每条订阅记录,按其携带的时间戳分组。84 条试用中记录只有 started_at。720 条活跃记录还包含 activated_at。84 条逾期记录还包含 past_due_at。156 条记录从试用期直接流失,包含 started_at 和 churned_at;78 条记录在活跃后流失,78 条记录在逾期后流失,每条记录都包含其路径上的所有时间戳。不匹配任何已声明路径的记录:0。

演示租户的 1,200 条订阅,按已设置的时间戳分组。六条路径,没有一条记录不符合路径。由 readme_charts.py 根据配方自身的 YAML 绘制。


当它拒绝时

$ misata explain bad.yaml
Generation would refuse: 1 conflict(s).
1 declaration cannot be satisfied together:
  1. [orders.channel] group_shares on amount
      declared shares sum to 1.500 (web=0.6, app=0.6, store=0.3); a share of a whole cannot exceed 1.0
      → Suggestion: scale the shares so they sum to 1.0, or drop a group. Misata will not renormalise them for you, because the result would be a specification you did not write
Nothing was generated. Change the declarations each conflict names; its remedy says how.

misata explain 会打印计划生成的行、每项声明将写入的内容、证书将包含多少条不变量,以及所有冲突,且不会生成任何内容。每条命令都支持 --json,并打印一个封装对象;退出代码 3 表示这些声明无法同时成立,且没有写入任何内容。


与编码 Agent 协作

Agent 设计架构,Misata 负责计算,DuckDB 负责检查。Agent 无法为自己的输出认证;这种方式能让它得到一个并非由它自己编写的答案。

在 Cursor 中安装

claude mcp add misata -- uvx --from "misata[mcp]" misata-mcp   # Claude Code
misata mcp install --client all                                  # Cursor, Windsurf, Claude Desktop

共有 15 个工具:generate_from_schema、generate_dataset、explain_schema、validate_yaml、inspect_schema、preview_story、list_domains、validate_domain、seed_database、create_sandbox、query_sandbox、solve_outcome、attest_dataset、audit_dataset 和 check_realism。 AGENTS.md 会告诉 Agent 哪个入口适合哪项任务,以及证据支持哪些说法。


它不是什么

除非你提出要求,否则 Misata 不会模仿任何内容。它不会从你的数据中学习联合分布。如果你需要特定私有表的统计孪生数据,请使用明确声明 epsilon 值的差分隐私合成器。mimic 会拟合真实行,因此并非匿名。

对于可声明的内容(总和、比率、占比、汇总、分类账、键、生命周期),它是精确的;对于任意 SQL,则并非如此。即使模型依赖窗口函数或 Misata 无法反演的业务逻辑,生成的数据仍然连贯且键有效,而预期输出由你编写。misata solve 通过将输入送入你的真实流水线,驱动其达到声明结果,并满足指定容差,从而弥补部分差距;证书会说明该容差。

先验设定以英语为主,金额偏向美国惯例,且比率会四舍五入到整数行数。LIMITATIONS.md 列出了完整限制;若与其他文档有争议,以此为准。

命令式推断式声明式
你提供生成值的代码用于拟合的真实数据必须成立的事实
保证事后不作保证大致相似事实精确成立,否则拒绝
外键由你负责单表内没问题,跨表则不可靠构造时保证
需要真实数据否是否
示例Faker、Mockaroo、LLM 种子脚本SDV、学习型合成器Misata

引用

如果 Misata 对你的工作有所帮助,请引用该软件。GitHub 的 引用此仓库按钮会读取 CITATION.cff 中的相同元数据。

@software{rasin_misata,
  title  = {Misata: declarative synthetic data},
  author = {Rasin, Muhammed},
  url    = {https://github.com/rasinmuhammed/misata}
}

参与贡献

git clone https://github.com/rasinmuhammed/misata && cd misata
uv sync --all-extras && uv run pytest -q
python tools/stranger.py --clean    # every documented command, from the built wheel

只有能够声明并验证的功能才值得纳入。benchmarks/ 中的一致性测试套件就是约定:先编写断言,看着它失败,然后让它通过。采用 MIT 许可证。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。