context.data/ 数据规范

SRHarness 用一个目录保存结构化数据:每个变量或较长的轴对应一个 NPY 文件,manifest.json 描述变量、轴及它们之间的关系。下面明确区分程序强制执行的规则、解释数据含义的约定,以及改善科研工作流的建议。

硬约束 语义约定 建议

硬约束不满足时加载失败;语义约定决定数据如何被人和 Agent 理解,但当前未必能完全自动检查;建议不会触发校验错误。

“描述不应泄露待发现的真实公式”属于建议。加载器只检查 description 是否为字符串,无法可靠判断自然语言是否泄露答案。数据准备 Agent 会收到这项指导,但违反它不会使 manifest 校验失败。

目录结构

context.data/
├── manifest.json
├── x.npy
├── y.npy
├── time.npy       # 较长的轴也可存为 NPY
└── A.npy          # 网络关系也作为变量存储
硬约束

目录中必须存在合法的 manifest.json。每个被引用的 NPY 文件必须位于该目录的顶层;文件名不得包含路径。

硬约束

NPY 必须保存一个 numpy.ndarray,并能以 allow_pickle=False 读取。对象 dtype 不允许使用;字符串请使用 NumPy 的 Unicode 或定长字符串 dtype。

建议

未被 manifest 引用的 *.npy 只产生警告,便于 Agent 在整理数据时保留临时文件;正式运行前建议移除或登记这些文件。

manifest.json 根字段

字段级别含义
variables硬约束非空对象,登记所有变量,包括关系变量。
axes硬约束对象,登记变量引用的所有轴;可以为空。
num_nodes条件必需正整数。只要存在 kind: "relation" 就必须提供;没有关系变量时不得提供。
硬约束

根对象只支持上述字段。未知字段、缺少必需字段或重复的 JSON key 都会使校验失败。

语义约定

目标变量、特征选择、问题描述和 Evaluator 属于一次研究任务的配置,不属于数据本身,因此不写入 manifest。

变量

"variables": {
  "theta": {
    "file": "theta.npy",
    "description": "Oscillator phase in radians.",
    "axes": ["time", "node"]
  }
}
硬约束

每个变量必须包含 file、description 和 axes;只可额外包含 kind 与 structure。

硬约束

变量名必须是非空名称,不得为 .、..,也不得包含路径分隔符或 NUL。文件必须严格命名为 <变量名>.npy。

硬约束

axes 必须是轴名数组。数组维数必须等于轴名数量,且每一维长度必须与对应轴一致。标量变量使用空数组 []。

完整上下文约束

加载进 AgentContext 后,变量名与轴名必须互不重叠;所有轴及变量共同构成 context.data。

轴

轴必须有 description,并且在 values、file、size 中恰好选择一种取值来源。

"axes": {
  "time": {"values": [0.0, 0.1, 0.2], "description": "Time in seconds."},
  "node": {"values": ["node1", "node2", "node3"], "description": "Node label."},
  "sample": {"size": 100, "description": "Zero-based sample position."}
}
硬约束

values 必须是非空的一维 JSON 标量数组;短轴和有意义的标签优先使用这种写法。

硬约束

file 必须是 <轴名>.npy,对应数组必须是一维;size 必须是正整数,并会生成 0 … size-1。

硬约束

所有登记的轴必须至少被一个变量引用,变量也不得引用未登记的轴。

建议

像 ["target", "source"] 或较短年份列表这样的轴直接写入 values;只有较长的轴才单独保存为 NPY。

网络与超图

"num_nodes": 10,
"variables": {
  "A": {
    "file": "A.npy",
    "description": "Directed graph endpoint pairs.",
    "axes": ["edge", "endpoint"],
    "kind": "relation"
  },
  "weight": {
    "file": "weight.npy",
    "description": "Edge weight at each time.",
    "axes": ["time", "edge"],
    "structure": "A"
  }
}
硬约束

关系必须显式写为 kind: "relation",不会根据变量名 A 或 T 猜测。关系数组形状只能是 (E, 2) 或 (H, 3)。

硬约束

关系端点必须使用整数 dtype,所有值必须位于 [0, num_nodes)。显式的 num_nodes 允许图中存在孤立节点。

语义约定

(E, 2) 的列顺序为 (target, source);(H, 3) 的列顺序为 (target, source1, source2)。建议在 endpoint 轴的 values 中明确写出这些标签。当前加载器只校验形状,不推断列的语义。

硬约束

最后一维与某个关系的 E 或 H 对齐的变量,用 structure 指向该关系。被指向的变量必须存在并标记为 relation,且长度必须匹配。

语义约定

普通节点变量不写 structure;关系变量本身也不指向自己。当前一个 manifest 中的关系共享同一个 num_nodes。

描述的边界

硬约束

每个变量和轴都必须提供 description,其值必须是字符串。空白会被剥除;当前校验器允许空字符串。

建议

描述变量的现实含义、单位、测量或生成方式,以及必要的数据质量说明。对字符串类别变量,除非用户明确要求,不要预先转换成 one-hot 编码。

建议

不要泄露待发现的真实公式,也不要用措辞暗示其函数形式。例如避免 “由 y=1+x² 生成的目标” 或 “指数衰减坐标”;可以写成 “响应变量” 或陈述可公开的观测含义。这是实验设计建议,程序不会自动判定。

完整示例

普通表格数据

{
  "variables": {
    "population": {
      "file": "population.npy",
      "description": "Annual population count.",
      "axes": ["year"]
    },
    "gdp": {
      "file": "gdp.npy",
      "description": "Annual gross domestic product in constant currency.",
      "axes": ["year"]
    }
  },
  "axes": {
    "year": {
      "values": [2018, 2019, 2020, 2021, 2022],
      "description": "Calendar year."
    }
  }
}

网络动力学数据

{
  "num_nodes": 10,
  "variables": {
    "theta": {
      "file": "theta.npy",
      "description": "Oscillator phase in radians.",
      "axes": ["time", "node"]
    },
    "A": {
      "file": "A.npy",
      "description": "Directed interaction endpoints.",
      "axes": ["edge", "endpoint"],
      "kind": "relation"
    }
  },
  "axes": {
    "time": {"file": "time.npy", "description": "Time in seconds."},
    "node": {
      "values": ["node1", "node2", "node3", "node4", "node5",
                 "node6", "node7", "node8", "node9", "node10"],
      "description": "Node label."
    },
    "edge": {"size": 32, "description": "Directed edge position."},
    "endpoint": {
      "values": ["target", "source"],
      "description": "Endpoint column order."
    }
  }
}

在 Python 中校验与加载

from sr_harness.core import inspect_context_data, load_context_data

report = inspect_context_data("workspace/context.data")
if report["errors"]:
    print("invalid:", report["errors"])
else:
    loaded = load_context_data("workspace/context.data")
    print(loaded["data"].keys())
    print(loaded["variable_axes"])
    print(loaded["relation_names"], loaded["num_nodes"])

inspect_context_data 返回错误与警告,适合数据准备 Agent 在提交前自检;load_context_data 对无效数据抛出 ContextManifestError,并返回可直接载入 AgentContext 的数组和元数据。