开发者文档:/v1/forecast 与 /v1/clean 已开放,API 密钥在 SequenxAI 平台自助创建。

清洗策略与清洗报告

default 与 strict 预设会在推理前清洗数据:排序、去重、对齐网格、补齐缺失、处理缺失值代码等。每一处改动都作为一条带稳定 id 的「决定」写进清洗报告,不会静默修改数据。你可以按 id 采纳或拒绝决定,也可以用 /v1/clean 免费预演。

1. 清洗预设

用 options.cleaning.preset 选择预设:

预设行为/v1/forecast/v1/clean
default自动应用常规修复;不确定的改动只提议、不执行。支持支持
strict只自动执行结构性修复(排序、去掉完全相同的重复行、对齐网格等)。删除数据、补值、改写数值的决定都降为提议;未采纳时拒绝请求。支持支持
raw不清洗,数据原样交给模型,只做结构校验;不返回清洗报告。支持不支持,返回 CLEANING_OPTION_UNSUPPORTED

raw 的输入要求见 raw 预设。

clean_series: false 表示不允许修复:数据需要任何修复时,请求以 TIMESTAMP_IRREGULAR 或 SERIES_DISCONTINUOUS 拒绝,并附带报告说明原因。

2. 生效策略 effective_policy

每个成功响应都会回显实际生效的策略:

effective-policy.json
"effective_policy": {
"id": "default@2026-13",
"preset": "default",
"version": "2026-13",
"source": "platform"
}
字段说明
id预设@版本,可以记录下来,用于复现同一次清洗。
presetdefault、strict 或 raw。
version规则集版本。同一版本的规则与阈值不变;规则调整会发布新版本。
source策略来自哪里,按优先级:request(请求中的 options.cleaning.preset 或 version)> key(该密钥的默认值)> org(组织默认值)> platform(平台默认,即 default@2026-13)。预设和版本分别解析,source 取设置了其中任一项的最高层级。

密钥或组织的默认值由平台配置,目前没有自助设置入口。请求里显式传 preset 或 version 总是优先。

策略版本

版本状态
2026-13默认(不传 version 时使用)。在 2026-12 基础上,把 10% 缺失占比上限改为按缺失位置判断,并逐项列出健康分扣分;见缺失判断规则。
2026-12已弃用,将在公告后移除。在 2026-11 基础上固定预测起点:末尾至多 3 个空值按未知处理,预测仍从您最后一个时间戳的下一步开始。可通过 options.cleaning.version: "2026-12" 继续使用,响应 warnings[] 会带 cleaning_version_deprecated。
2026-11已弃用,将在公告后移除。仍可通过 options.cleaning.version: "2026-11" 使用,响应 warnings[] 会带 cleaning_version_deprecated。
2026-10已弃用,将在公告后移除。最初的规则集(缺口一律线性填补),用法与提醒同上。

建议不传 version,让请求跟随平台默认。移除日期会提前公告。

2026-11 保留 2026-10 的全部规则,并新增:

  • 逐段补值。 每个缺口单独选方法:短缺口用 PCHIP(保形、不过冲);较长缺口在季节周期被确认时用季节补值(取相邻周期同一相位),否则用线性。imputed 动作的每条 gaps[] 都写明 method、tier 与 reason;series[].seasonality 写明检验的周期以及是否采用。
  • 补值的物理约束。 非负序列的补值截到 0 以上(constraint.nonnegative),截到声明的范围内(constraint.bounds),几乎总为 0 的相位(如夜间光伏出力)补值保持为 0(constraint.structural_zero)。观测值从不修改;违反约束的观测值会被标记(negative_in_nonnegative、out_of_bounds)。每条约束都是可拒绝的决定。
  • 工作日。 没有周末日期的日频数据放到 B 网格上:周末不算缺口,预测时间戳跳过周末(决定 grid.business_days,问题 business_days_pattern)。拒绝该决定即可保留自然日。
  • 更多数据检查。 不是普通数字的 y 文本会被报告(thousands_separator、decimal_comma、ambiguous_separator、number_format_mixed、non_numeric_value),保持缺失而不猜测;常数序列与全零序列给出警告(constant_series、all_zero_series);所有无法解析的时间戳在一次错误中全部列出。

2026-11 的七个参数(impute_method、seasonal_period、nonnegative、bounds、structural_zero、business_days、long_gap)、每个版本逐步执行的规则与阈值,以及报告中每个决定与问题代码的含义,见清洗策略版本参考。

3. 清洗报告 cleaning_report/1

清洗报告出现在三个地方:

  • /v1/forecast 的成功响应(raw 预设除外);
  • /v1/clean 的响应;
  • 数据被清洗阶段拒绝时,错误响应的 error.details.cleaning_report。

顶层结构:

字段说明
schema_version固定为 cleaning_report/1。
policy本次使用的清洗参数,包括 id、clean_series、重复处理方式、补值上限、异常值阈值、默认时区,以及你传入的 accept / decline。
overall汇总:series_count、input_points、output_points、health_score(0 至 100)、health_tier、forecastable。
series[]每个实体一项:freq(推断结果、实际使用值、来源与置信度)、timezone、issues[](发现的问题)、actions[](执行的操作及位置)、health、input / output 点数。
warnings[]不阻断请求、但值得注意的情况,例如 duplicate_conflict、off_grid_dropped、segment_split_skipped。
blocking[]导致请求被拒的原因,每项带 code 与 unique_id。成功时为空。
decisions[]所有改动数据的决定,见下一节。

默认的 2026-13 下,health_tier 按缺失判断规则分级:被该规则拒绝的实体为 Critical,请求以 SERIES_DISCONTINUOUS 拒绝;带 missing_pattern 提醒被接受的实体为 Warning;health.factors 列出各项扣分。已弃用的版本仍按缺失占比(缺口加空值)分级:低于 1% 为 Healthy,1% 至 10% 为 Warning,达到 10% 为 Critical。异常值只在 issues[] 中标记,不会被修改。

4. 决定 decisions[]

每条决定的字段:

字段说明
id稳定标识,格式为 规则:unique_id[:选择器],例如 gap.impute:meter-001、value.sentinel:meter-001:-9999。同样的数据与策略每次得到同样的 id。
rule规则名,见下表。
classstructural(只调整结构,不增删观测值)、drop(删除数据)、fabricate(生成或置空数值)、semantic(按含义改写数值)。
statusapplied(已执行)、proposed(只提议,未执行)、declined(被你拒绝)。
action具体操作,例如 keep_last、linear。
before / after执行前后的计数或取值。
reversible是否可以通过 decline 撤销。
evidence做出该决定的依据,因规则而异。

规则一览:

规则类别操作什么时候出现
time.duplicatesstructural / dropkeep_last同一时间戳出现多行,保留最后一行。值都相同为 structural,值不同为 drop。
time.reorderstructuralstable_sort行没有按时间排序。
grid.snapstructuralnearest_slot时间戳略偏离网格(例如多出几秒),对齐到最近的格点。
grid.off_griddropdrop时间戳落在两个格点之间,删除该行。超过 10% 的行偏离网格时改为拒绝请求。
gap.edge_trimdropdrop序列首尾的空值,直接删除(从 2026-12 起,末尾空值见 gap.masked_tail)。
gap.masked_tailfabricatemask_for_model2026-12:至多 3 个末尾空值保留在网格上、不作为数据使用,预测仍从你的最后一个时间戳之后开始;更长的末尾空值以 SERIES_DISCONTINUOUS(trailing_gap_too_long)拒绝。
window.contextdropkeep_latest保留规则:API 对长于模型最大上下文的序列直接拒绝(SERIES_TOO_LONG),不会只保留最近的部分,因此 API 响应里不会出现这条决定。
gap.splitdropkeep_latest_segment序列中有很长的缺口,只保留缺口之后的最新一段。
grid.regridstructuralinsert_empty_slots网格上缺少时间戳,插入空的格点。
gap.imputefabricatelinear / pchip / seasonal / mixed补齐缺失值:2026-10 一律线性插值,2026-11 起逐段选择方法。
value.sentinelfabricatenull数值是常见的缺失值代码(例如 -9999、65535),置为空值后再补齐。
value.tokenssemanticnull文本单元格中的缺失标记(例如 N/A),置为空值。
value.dash_tokensemanticzero文本单元格中的单独破折号,提议按 0 处理。

value.tokens 与 value.dash_token 只针对文本形式的单元格(例如上传的 CSV);JSON 请求里 y 是数字或 null,通常不会出现这两条。

下面是各规则的前后对比。示例均为逐小时数据,实体为 meter-001;决定内容来自清洗服务在策略版本 2026-12、default 预设下的实际输出。

time.duplicates

time.duplicates.json
// 输入:10:00 出现两次,值不同
{"ds": "2026-09-01T10:00:00Z", "y": 145.7}
{"ds": "2026-09-01T10:00:00Z", "y": 999.0}
// 结果:只保留最后一行 999.0,并附带 duplicate_conflict 警告;
// 999.0 远离其他值,另有一条 outlier_flagged_not_modified 警告(数值不修改)
{"id": "time.duplicates:meter-001", "rule": "time.duplicates", "class": "drop",
"status": "applied", "action": "keep_last",
"before": {"duplicate_rows": 1, "conflicting": 1}, "after": {"duplicate_rows": 0}}

两行值完全相同时,class 为 structural,conflicting 为 0,不产生警告。

time.reorder

time.reorder.json
// 输入:11:00 排在 10:00 之前
{"ds": "2026-09-01T11:00:00Z", "y": 146.9}
{"ds": "2026-09-01T10:00:00Z", "y": 145.7}
// 结果:按时间稳定排序
{"id": "time.reorder:meter-001", "rule": "time.reorder", "class": "structural",
"status": "applied", "action": "stable_sort",
"before": {"out_of_order": 1}, "after": {"out_of_order": 0}}

grid.snap

grid.snap.json
// 输入:10:00:20,比格点晚 20 秒
{"ds": "2026-09-01T10:00:20Z", "y": 145.7}
// 结果:对齐到 10:00:00
{"id": "grid.snap:meter-001", "rule": "grid.snap", "class": "structural",
"status": "applied", "action": "nearest_slot",
"before": {"off_slot": 1}, "after": {"off_slot": 0}}

grid.off_grid

grid.off_grid.json
// 输入:逐小时数据中夹着一行 10:30
{"ds": "2026-09-01T10:00:00Z", "y": 145.7}
{"ds": "2026-09-01T10:30:00Z", "y": 141.0}
{"ds": "2026-09-01T11:00:00Z", "y": 146.9}
// 结果:删除 10:30 这一行,并附带 off_grid_dropped 警告
{"id": "grid.off_grid:meter-001", "rule": "grid.off_grid", "class": "drop",
"status": "applied", "action": "drop",
"before": {"rows": 1}, "after": {"rows": 0}, "evidence": {"ratio": 0.020408}}

evidence.ratio 是偏离网格的行占比;超过 10% 时请求以 FREQ_INFERENCE_FAILED 拒绝。

gap.edge_trim

gap.edge_trim.json
// 输入:前两行为空值
{"ds": "2026-09-01T00:00:00Z", "y": null}
{"ds": "2026-09-01T01:00:00Z", "y": null}
{"ds": "2026-09-01T02:00:00Z", "y": 146.9}
// 结果:删除首尾的空值,序列从 02:00 开始
{"id": "gap.edge_trim:meter-001", "rule": "gap.edge_trim", "class": "drop",
"status": "applied", "action": "drop",
"before": {"empty_edge_slots": 2}, "after": {"empty_edge_slots": 0}}

window.context

window.context.json
// 输入:24 个点,模型最多使用 16 个
// 结果:只保留最近 16 个点
{"id": "window.context:meter-001", "rule": "window.context", "class": "drop",
"status": "applied", "action": "keep_latest",
"before": {"points": 24}, "after": {"points": 16}, "evidence": {"max_context": 16}}

API 不会产生这条决定:长于模型最大上下文的序列直接返回 422 SERIES_TOO_LONG,由你决定发送哪些点。模型的最大上下文见模型与能力上限。

gap.split

gap.split.json
// 输入:128 个观测值,第 40 至 51 小时整段缺失,options.gap_split_min_steps = 8
// 结果:丢弃缺口之前的 40 个点,保留之后的 88 个点,并附带 segment_split 警告
{"id": "gap.split:meter-001", "rule": "gap.split", "class": "drop",
"status": "applied", "action": "keep_latest_segment",
"before": {"points": 128}, "after": {"points": 88}, "reversible": true,
"evidence": {"min_steps": 8, "threshold_source": "option",
            "dropped_observed": 40, "observed": 128}}
  • 缺口长度达到 evidence.min_steps 才会拆分。未传 options.gap_split_min_steps 时自动取阈值(threshold_source: "auto"),取以下三者中最大的:补值上限加一、三个季节周期、序列跨度的 5%。
  • 只有丢弃的观测值不超过一半时才会自动执行;否则只提议(proposed),改为补齐缺口,并附带 segment_split_skipped 警告。
  • 可以用 accept 强制拆分,或用 decline 撤销拆分。

grid.regrid 与 gap.impute

缺少时间戳时,这两条决定成对出现:先插入空格点,再插值补齐。

grid.regrid-gap.impute.json
// 输入:05:00 之后直接是 07:00,缺少 06:00
{"ds": "2026-09-01T05:00:00Z", "y": 138.8}
{"ds": "2026-09-01T07:00:00Z", "y": 138.2}
// 结果:插入 06:00,并用 PCHIP 补齐(短缺口,见策略版本参考)
{"id": "grid.regrid:meter-001", "rule": "grid.regrid", "class": "structural",
"status": "applied", "action": "insert_empty_slots",
"before": {"slots": 11}, "after": {"slots": 12}}
{"id": "gap.impute:meter-001", "rule": "gap.impute", "class": "fabricate",
"status": "applied", "action": "pchip",
"before": {"missing": 1}, "after": {"filled": 1},
"evidence": {"methods": {"pchip": 1}, "gaps": 1, "seasonal_period": 24,
            "seasonality_accepted": false}}

y 为 null 的行只产生 gap.impute。补齐的具体位置记录在 series[].actions[] 中。缺口长于补值上限(3 步)时仍会补齐,但附带 long_gap_filled 警告。

value.sentinel

value.sentinel.json
// 输入:48 个点里有一个 -9999,其他值都在 132 至 148 之间
{"ds": "2026-09-02T06:00:00Z", "y": -9999}
// 结果:-9999 置为空值,再由 gap.impute 补齐
{"id": "value.sentinel:meter-001:-9999", "rule": "value.sentinel", "class": "fabricate",
"status": "applied", "action": "null",
"before": {"value": -9999.0, "count": 1}, "after": {"value": null, "count": 1},
"reversible": true,
"evidence": {"source": "builtin", "detached": true, "nearest_other": 132.0,
            "spread": 16.0, "share": 0.020833}}
  • 内置的候选值为 9999、-9999、99999、-99999、-999、999999、65535、-32768。
  • 只有当该值远离其他数据(detached)且占比不超过 5%(share)时才自动执行;否则只提议,数值保持不变。
  • 选择器是数值本身,所以同一实体的不同代码各有一个 id。
  • 如果 -9999 是真实数值,用 decline 保留它;报告会给出 outlier_flagged_not_modified 警告。

value.tokens 与 value.dash_token

value.tokens.json
// 输入(文本单元格):两个 "N/A",一个 "-"
// value.tokens:缺失标记置为空值,再补齐
{"id": "value.tokens:meter-001", "rule": "value.tokens", "class": "semantic",
"status": "applied", "action": "null",
"before": {"cells": 2}, "after": {"missing": 2}}
// value.dash_token:默认只提议按 0 处理
{"id": "value.dash_token:meter-001", "rule": "value.dash_token", "class": "semantic",
"status": "proposed", "action": "zero",
"before": {"cells": 1, "token": "-"}, "after": {"value": 0.0, "count": 1}}

破折号可能表示 0,也可能表示缺失。未采纳时按缺失值处理;把 value.dash_token:meter-001 放进 accept 后按 0 处理。

5. 采纳与拒绝

在请求中按 id 列出要采纳或拒绝的决定:

accept-decline.json
"options": {
"cleaning": {
  "preset": "strict",
  "accept": ["gap.impute:meter-001"],
  "decline": ["value.sentinel:meter-001:-9999"]
}
}
  • accept 让提议的决定执行:value.sentinel、value.dash_token、gap.split,以及 strict 预设下被降为提议的任何决定。
  • decline 撤销可撤销的决定(reversible: true):value.sentinel 与 gap.split,2026-11 起还有 grid.business_days 与 constraint.*。撤回 gap.masked_tail(2026-12)则会以 trailing_gap_too_long 拒绝请求。
  • 同一个 id 不要同时出现在两个列表中。
  • 列出的 id 在本次数据中不存在时,报告附带 decision_not_applicable 警告,请求照常处理。
  • raw 预设不能与 accept / decline 同时使用。

strict 预设示例

下面的数据缺少一个时间戳,还有一个 -9999。default 预设会直接补齐;strict 预设把 gap.impute 与 value.sentinel 都降为提议,并拒绝请求:

strict-blocked.json
// 422 SERIES_DISCONTINUOUS,error.details.cleaning_report 中:
"decisions": [
{"id": "value.sentinel:meter-001:-9999", "status": "proposed", ...},
{"id": "grid.regrid:meter-001", "status": "applied", ...},
{"id": "gap.impute:meter-001", "status": "proposed", ...}
],
"blocking": [
{"code": "cleaning_required", "unique_id": "meter-001", "reason": "series_discontinuous"}
]

只采纳 gap.impute:meter-001 仍会被拒,因为 value.sentinel 还是提议状态。两个 id 都放进 accept 后请求通过,三条决定都为 applied。先用 /v1/clean 拿到 id,再在预测请求里采纳,是使用 strict 的推荐流程。