# 自定义 API 数据源与 LLM 映射系统 — 实施计划 **状态**:规划中 **创建日期**:2026-04-28 **核心原则**:LLM 辅助生成映射配置;生产采集使用确定性转换引擎 ## 已确认决策 | 项目 | 决策 | |-----|------| | 自定义 API 的定位 | 作为内置数据源的补充入口,不直接等同于 Earth 新功能 | | LLM 的职责 | 探索未知 API、分析样本 JSON、生成 mapping 草案 | | 采集时是否调用 LLM | 不调用;采集链路必须确定性、可审计、可复现 | | 自定义数据如何进入 Earth | 必须映射到已支持的目标 schema,或先进入通用数据沉淀 | | 外部凭证放置位置 | Settings / 外部集成统一管理 provider token;DataSources 引用 provider profile | | TimescaleDB | 高频时序数据稳定后再评估迁移 | --- ## 一、背景与问题 当前系统已经有 `datasource_configs`,可以配置自定义数据源的 endpoint、auth、headers、config,也已经有部分 collector 会读取这些配置。但这只能解决“怎么请求数据”,还没有解决以下问题: - API 返回 JSON 后,如何转换成系统已有领域模型。 - 自定义数据源是补充已有能力,还是全新数据沉淀。 - 转换规则由谁生成、谁校验、谁执行。 - 未知数据是否能自动在 Earth 上展示。 - 外部 token 是放在全局配置中心,还是放在每个 datasource 下。 专业做法是把“请求配置”“外部凭证”“目标 schema”“字段映射”“采集执行”拆开: - Settings 管外部集成凭证,例如 AI Provider、BarentsWatch、未来付费 AIS API。 - DataSources 管具体数据源实例,例如 endpoint、调度频率、目标 schema、mapping 版本。 - LLM 只在配置阶段辅助生成 mapping,不进入生产采集链路。 - Earth 只消费明确 schema 的数据,不消费任意未知 JSON。 --- ## 二、目标架构 ### 2.1 自定义 API 数据源生命周期 ```mermaid flowchart LR A[配置 endpoint/auth/request] --> B[抓取 sample JSON] B --> C[选择目标 schema] C --> D[LLM 生成 mapping 草案] D --> E[确定性 mapping engine 预览] E --> F[schema validation] F --> G[保存 mapping version] G --> H[scheduler 执行 mapped collector] H --> I[写入目标表或 generic_records] ``` ### 2.2 目标 schema 分层 | schema | 用途 | Earth 可视化 | |-------|------|-------------| | `vessel_ais` | 船只 AIS 位置、航速、航向、MMSI 等 | 进入船舶图层 | | `geo_points` | 通用点位数据,包含经纬度、名称、类型、时间 | 未来进入通用 geo layer | | `news_events` | 新闻/事件类数据,带时间、地点、摘要、来源 | 复用新闻/事件链路 | | `compute_centers` | 算力中心、机房、数据中心数据 | 复用算力中心图层 | | `generic_records` | 未知结构化数据沉淀 | 不直接展示 | v1 建议优先实现: - `vessel_ais` - `geo_points` - `generic_records` 其他 schema 可先在 registry 中预留名称,但不承诺完整落库与可视化。 ### 2.3 LLM 的边界 LLM 可以做: - 根据 API 文档或 sample JSON 解释字段含义。 - 推荐目标 schema。 - 生成 mapping JSON 草案。 - 给出字段置信度和需要人工确认的字段。 - 帮用户发现分页、数组路径、时间字段、坐标字段。 LLM 不应该做: - 在正式采集时参与每批数据转换。 - 生成并执行 Python/JavaScript 代码。 - 接触 API key、bearer token、basic auth password。 - 自动创建新的 Earth 图层或数据库表。 --- ## 三、后端实施计划 ### Phase 1 — Target Schema Registry 新增代码级 registry,统一描述系统支持的目标数据类型。 每个 target schema 至少包含: - `key`:例如 `vessel_ais`。 - `label`:前端展示名称。 - `description`:适用场景。 - `fields`:字段名、类型、是否必填、说明、示例。 - `validator`:Pydantic 或等价校验器。 - `destination`:写入目标,例如 vessel 表、generic_records、future geo layer。 示例概念: ```json { "key": "vessel_ais", "fields": [ {"name": "mmsi", "type": "integer", "required": true}, {"name": "lat", "type": "float", "required": true}, {"name": "lon", "type": "float", "required": true}, {"name": "sog", "type": "float", "required": false}, {"name": "cog", "type": "float", "required": false}, {"name": "received_at", "type": "datetime", "required": false} ] } ``` ### Phase 2 — Mapping Template Model 新增 mapping 配置持久化表,建议命名为 `datasource_mapping_templates`。 关键字段: - `id` - `datasource_config_id` - `target_schema` - `mapping_json` - `sample_payload_hash` - `validation_status` - `version` - `is_active` - `created_at` - `updated_at` `mapping_json` 是声明式 DSL,不允许任意代码执行。 示例: ```json { "source": { "items_path": "$.data.vessels[*]" }, "fields": { "mmsi": {"path": "$.mmsi", "type": "integer"}, "lat": {"path": "$.latitude", "type": "float"}, "lon": {"path": "$.longitude", "type": "float"}, "sog": {"path": "$.speedOverGround", "type": "float", "default": null}, "received_at": {"path": "$.timestamp", "type": "datetime"} } } ``` ### Phase 3 — Deterministic Mapping Engine 实现独立 mapping engine,输入 sample/raw payload 和 mapping JSON,输出目标 schema 记录。 v1 支持能力: - JSONPath/JMESPath 风格路径提取。 - 数组展开。 - 默认值。 - 基础类型转换:string、integer、float、boolean、datetime。 - 坐标范围校验。 - 简单枚举映射。 - 错误收集:缺字段、类型转换失败、路径不存在。 明确不支持: - 任意表达式执行。 - 用户提交脚本。 - LLM runtime 修复。 ### Phase 4 — LLM Mapping Assistant API 新增配置阶段 API: - `POST /api/v1/datasources/custom/sample` - 按 datasource 请求配置抓取 sample JSON。 - `GET /api/v1/datasources/target-schemas` - 返回可选目标 schema 和字段说明。 - `POST /api/v1/datasources/mappings/propose` - 输入 sample JSON + target schema,调用 AI provider 生成 mapping 草案。 - `POST /api/v1/datasources/mappings/preview` - 使用确定性 mapping engine 预览转换结果。 - `POST /api/v1/datasources/mappings` - 保存 mapping 版本。 - `PUT /api/v1/datasources/mappings/{id}` - 更新 mapping,生成新版本或覆盖草稿。 - `POST /api/v1/datasources/{id}/run-mapped` - 手动触发一次 mapped collector。 安全要求: - `propose` 请求发送给 LLM 前必须脱敏 sample。 - auth headers、token、password 不进入 prompt。 - LLM 返回结果必须再经过 mapping schema 校验。 ### Phase 5 — Generic Mapped HTTP Collector 新增通用 collector: - 读取 `DataSourceConfig` 请求配置。 - 读取 active mapping template。 - 拉取 API 数据。 - 使用 mapping engine 转换。 - 使用 target schema validator 校验。 - 调用 destination handler 写入目标表或 generic storage。 - 将失败记录写入错误日志或 dead-letter 结构。 对于 `generic_records`: - 保存 datasource id。 - 保存 target schema。 - 保存 normalized JSON。 - 保存 raw payload 摘要或 raw reference。 - 保存采集时间、source timestamp、mapping version。 --- ## 四、前端实施计划 ### Phase 1 — Settings 外部集成 Settings 中保留统一外部集成配置: - AI Provider:base URL、model、API key。 - BarentsWatch:client id/client secret 或 bearer token。 - 未来付费接口:AISHub、MarineTraffic、VesselFinder 等 provider profile。 DataSources 不直接管理全局 secret,只引用 provider profile。 ### Phase 2 — Settings 自定义源向导 自定义数据源配置入口应放在 `/settings` 的“采集器设置”或后续专门的自定义采集器设置区。`/datasources` 保持数据源目录和采集触发职责,不再承载编辑入口。 自定义数据源配置改成向导或右侧 drawer: 1. Request - endpoint - method - auth profile - headers - query/body config - schedule 2. Sample - 点击抓取 sample - 展示 JSON tree - 支持选择数组根路径 3. Target Schema - 选择 `vessel_ais`、`geo_points`、`generic_records` - 展示该 schema 必填字段 4. Mapping Proposal - 调用 LLM 生成 mapping 草案 - 显示字段匹配置信度 - 标出需要人工确认的字段 5. Preview - 用确定性 engine 预览前 N 条转换结果 - 展示校验错误 6. Save & Enable - 保存 mapping version - 启用调度或仅保存草稿 ### Phase 3 — 运维视图 为 mapped datasource 展示: - 上次运行时间。 - 成功记录数。 - 失败记录数。 - 当前 mapping version。 - 目标 schema。 - 最近错误。 - 手动运行按钮。 --- ## 五、数据库与存储策略 ### v1:继续使用 PostgreSQL PostgreSQL 可以承载当前规模的采集、关系查询、JSONB 沉淀和基础时序查询。v1 不必因为“时序数据”立刻引入 TimescaleDB。 适合继续用 PostgreSQL 的场景: - 数据量可控。 - 最近状态查询为主。 - 历史保留窗口较短。 - 查询模式还没稳定。 - 需要快速迭代 schema 与 mapping。 ### TimescaleDB 后续评估 以下条件满足后,再评估 TimescaleDB: - AIS、遥测、轨迹类数据达到高频持续写入。 - 需要按时间窗口做聚合、降采样、retention policy。 - 单表时间序列查询明显成为瓶颈。 - 历史轨迹保留从 24h 扩展到数周或数月。 候选迁移对象: - `vessel_position` - future telemetry tables - future generic time-series records 备选方案: - PostgreSQL 原生按天/月分区。 - TimescaleDB hypertable。 - 热数据 PostgreSQL,冷数据对象存储。 --- ## 六、安全与治理 ### Secret 管理 - Settings 中保存 provider credentials。 - API 返回配置时必须 mask secret。 - LLM prompt 只能包含脱敏 sample 和 schema 说明。 - 后续可引入字段级加密或 KMS。 ### Mapping 治理 - 每次 mapping 变更保留版本。 - active mapping 只能有一个。 - 允许保存 draft mapping。 - 运行记录关联 mapping version。 - 校验失败不能自动启用。 ### 错误处理 常见错误类型: - API 401/403:凭证错误或过期。 - API 429:限流,需要调整 schedule。 - JSON path 不存在:上游结构变化。 - 类型转换失败:mapping 规则错误。 - schema validation failed:转换结果不满足目标模型。 每次运行需要记录: - datasource id。 - mapping version。 - started_at / finished_at。 - fetched count。 - mapped count。 - written count。 - failed count。 - error summary。 --- ## 七、测试计划 ### Backend Unit Tests - mapping engine: - path 提取。 - 数组展开。 - 默认值。 - 类型转换。 - datetime parse。 - 枚举映射。 - 缺字段错误。 - target schema registry: - `vessel_ais` 必填字段校验。 - `geo_points` 经纬度范围校验。 - `generic_records` 接受未知结构。 - LLM assistant: - mock provider 返回 mapping。 - 验证 secret 不进入 prompt。 - 验证非法 mapping 被拒绝。 ### Backend Integration Tests - sample JSON -> propose mapping -> preview -> save mapping。 - mapped collector 使用保存的 mapping 写入 `generic_records`。 - `vessel_ais` sample 写入船舶相关目标结构。 - 上游 JSON 结构变化时,运行失败并记录错误。 ### Frontend Tests - 自定义数据源向导完整流程。 - 未配置 AI Provider 时,提示去 Settings 配置,但允许手写 mapping。 - LLM 返回不完整 mapping 时,Preview 阶段显示校验错误。 - 保存 mapping 后展示 active version 和运行状态。 --- ## 八、分期工作量 | 阶段 | 内容 | 估算 | |-----|------|------| | Phase 0 | 完成本规划、确认 schema registry 设计 | 0.5 天 | | Phase 1 | target schema registry + mapping template model | 1–2 天 | | Phase 2 | deterministic mapping engine | 2–3 天 | | Phase 3 | sample/propose/preview/save API | 2–3 天 | | Phase 4 | DataSources 自定义源向导 | 3–5 天 | | Phase 5 | generic mapped collector + run history | 2–4 天 | | Phase 6 | vessel_ais / geo_points destination handler | 2–4 天 | --- ## 九、当前差距与下一步 当前差距: - `datasource_configs` 只描述请求配置,不描述目标 schema 和 mapping。 - 自定义源没有 sample -> schema -> mapping -> preview -> save 的闭环。 - 生产采集还没有通用 mapped collector。 - Settings 与 DataSources 的职责边界需要在 UI 上进一步明确。 - Earth 还没有通用 `geo_points` 图层。 下一步建议: 1. 先实现 target schema registry 和 mapping engine,不急着接 LLM。 2. 用固定 sample JSON 做 `vessel_ais` 和 `generic_records` 的单元测试。 3. 再接 LLM propose API,让 LLM 产出的只是 mapping 草案。 4. 最后做前端向导,把人工确认和 preview 放到启用之前。