376 lines
13 KiB
Markdown
376 lines
13 KiB
Markdown
# Scene Skill Compiler Design
|
||
|
||
> **Status:** Draft
|
||
> **Date:** 2026-04-17
|
||
> **Author:** Codex
|
||
|
||
## Problem Statement
|
||
|
||
当前 `sg_scene_generate` 已经具备基础的场景识别、LLM 抽取和模板渲染能力,但整体上仍然更接近“场景元数据提取器 + 模板填充器”,还不是一个真正可复用的通用 skill 转化器。
|
||
|
||
这在两个对照样本上表现得很明显:
|
||
|
||
| 样本 | 转化方式 | 结果 |
|
||
|------|----------|------|
|
||
| `tq-lineloss-report` | 基于 Claude 的语义重建 | 生成结果接近可运行 skill,显式表达了月/周模式、请求体、列定义、响应路径 |
|
||
| `marketing-zero-consumer-report` | 基于当前项目自动转化 | 生成结果偏“骨架 skill”,无法正确表达分页、逐户补数、过滤、导出等复合工作流 |
|
||
|
||
### 根因
|
||
|
||
1. 当前生成流程主要抽取“字段”,没有稳定抽取“工作流”。
|
||
2. 生成器默认假设报表场景接近“单次请求 -> 表格归一化 -> 输出 artifact”。
|
||
3. `scene.toml`、bootstrap、参数合同和 browser script 之间仍存在较强硬编码。
|
||
4. LLM 输入存在截断,且缺少对关键逻辑片段的优先抽取。
|
||
5. 运行时 resolver 能力较弱,无法稳定承接更复杂的自动生成结果。
|
||
|
||
### 典型失败模式
|
||
|
||
以 `marketing-zero-consumer-report` 为例,原始场景实际是:
|
||
|
||
1. 获取组织或用户列表。
|
||
2. 按页拉取用户数据。
|
||
3. 对每个用户发起二次请求补充电费信息。
|
||
4. 根据 `charge !== 0` 做业务过滤。
|
||
5. 组装导出数据并通过本地服务导出。
|
||
|
||
但当前自动生成结果把它错误归类成了“单请求报表”,导致:
|
||
|
||
- bootstrap 域名和目标页面来源不稳定。
|
||
- browser script 只使用第一个 API 端点。
|
||
- 数据归一化直接对原始列表生效,没有分页循环和二次请求。
|
||
- 生成出的参数合同与真实业务流程不匹配。
|
||
|
||
## Goal
|
||
|
||
将当前场景生成器升级为一个面向常见内网场景的“迷你版 skill-creator / scene skill compiler”,使其具备以下能力:
|
||
|
||
1. 先理解场景工作流,再选择模板并生成 skill。
|
||
2. 覆盖常见报表类内网场景,而不是只覆盖单请求表格场景。
|
||
3. 在生成前给出可运行性评估,减少“生成成功但内网跑不通”的情况。
|
||
4. 让同类场景可以复用同一套转化机制,而不是逐个手工重写。
|
||
|
||
## Non-Goals
|
||
|
||
1. 不追求一次性支持所有历史场景和所有前端技术栈。
|
||
2. 不在第一阶段解决登录、鉴权、跨域和浏览器宿主差异的全部问题。
|
||
3. 不要求 LLM 单独完成完整语义恢复,必须允许规则提取参与。
|
||
4. 不要求生成结果 100% 无需人工审阅。
|
||
|
||
## Design Principles
|
||
|
||
### 1. 先建模,再生成
|
||
|
||
必须先把原始场景建模为统一的 `Scene IR`,再由编译器按 archetype 渲染 skill。
|
||
|
||
### 2. 抽取“工作流证据”优先于抽取“字段清单”
|
||
|
||
对通用 skill 转化器而言,分页、模式切换、二次请求、导出动作、过滤条件,比单纯的 URL 和列定义更重要。
|
||
|
||
### 3. 确定性优先,LLM 补全
|
||
|
||
URL、请求方法、分页变量、入口函数、列头、导出调用等确定性信息优先由规则提取;LLM 负责做语义归并、命名和补全。
|
||
|
||
### 4. 模板按 archetype 拆分
|
||
|
||
不能继续用一个通用模板覆盖所有报表场景。不同工作流 archetype 必须有独立编译路径。
|
||
|
||
### 5. 运行时合同必须与生成能力对齐
|
||
|
||
生成器输出什么参数合同,运行时 resolver 就必须能承接;否则生成器必须降级或提示人工补齐。
|
||
|
||
## Architecture
|
||
|
||
### Target Architecture
|
||
|
||
```text
|
||
原始场景目录
|
||
-> 场景扫描器
|
||
-> 确定性规则提取
|
||
-> LLM 语义补全
|
||
-> Scene IR 合并
|
||
-> archetype 分类
|
||
-> archetype 编译器
|
||
-> skill 包
|
||
-> 静态验收 / 可运行性评级
|
||
```
|
||
|
||
### Core Pipeline
|
||
|
||
1. 扫描 `index.html`、`scripts/*.js`、目录结构和可见依赖关系。
|
||
2. 规则提取器抓取确定性证据。
|
||
3. LLM 基于分块后的关键上下文提取高层语义。
|
||
4. 合并为统一 `Scene IR`。
|
||
5. 根据 `workflowArchetype` 路由到对应编译器。
|
||
6. 生成 `scene.toml`、`SKILL.toml`、browser script 和说明文档。
|
||
7. 执行静态门禁和 readiness 评级。
|
||
|
||
## Scene IR
|
||
|
||
### Top-Level Fields
|
||
|
||
```json
|
||
{
|
||
"sceneId": "marketing-zero-consumer-report",
|
||
"sceneName": "营销2.0零度户报表数据生成",
|
||
"sceneKind": "report_collection",
|
||
"workflowArchetype": "paginated_enrichment",
|
||
"bootstrap": {
|
||
"expectedDomain": "yx.gs.sgcc.com.cn",
|
||
"targetUrl": "http://yx.gs.sgcc.com.cn"
|
||
},
|
||
"params": [
|
||
{
|
||
"name": "org_code",
|
||
"resolver": "org_tree",
|
||
"required": true
|
||
}
|
||
],
|
||
"modes": [],
|
||
"workflowSteps": [
|
||
{ "type": "paginate", "entry": "getUserList" },
|
||
{ "type": "foreach", "source": "userList" },
|
||
{ "type": "secondary_request", "entry": "getUserCharges" },
|
||
{ "type": "filter", "expr": "charge !== 0" },
|
||
{ "type": "export", "entry": "exportExcel" }
|
||
],
|
||
"requestTemplate": {},
|
||
"responsePath": "data.rows",
|
||
"normalizeRules": {
|
||
"type": "field_map"
|
||
},
|
||
"artifactContract": {
|
||
"type": "report-artifact"
|
||
},
|
||
"validationHints": {
|
||
"requiresTargetPage": true
|
||
},
|
||
"evidence": []
|
||
}
|
||
```
|
||
|
||
### Required IR Blocks
|
||
|
||
| Block | Purpose |
|
||
|------|---------|
|
||
| `workflowArchetype` | 决定编译器路由 |
|
||
| `bootstrap` | 决定目标域名、目标页面和 helper page 行为 |
|
||
| `params` | 决定 `scene.toml` 参数合同 |
|
||
| `modes` | 表达月/周、日/月、报表类型切换等多模式逻辑 |
|
||
| `workflowSteps` | 表达分页、循环、二次请求、过滤、导出等复合流程 |
|
||
| `requestTemplate` | 表达固定请求体和参数映射 |
|
||
| `responsePath` | 指定响应数据抽取路径 |
|
||
| `normalizeRules` | 指定字段映射、空行过滤和关键字段校验 |
|
||
| `artifactContract` | 指定输出 artifact 结构和状态语义 |
|
||
| `evidence` | 保留抽取证据,便于 UI 预览和人工复核 |
|
||
|
||
## Workflow Archetypes
|
||
|
||
第一阶段建议先稳定支持以下 archetype:
|
||
|
||
| Archetype | 场景特征 | 典型样本 |
|
||
|-----------|----------|----------|
|
||
| `single_request_table` | 单次请求,直接返回表格或列表 | 简单报表场景 |
|
||
| `multi_mode_request` | 同一场景存在月/周等多模式,请求体和列定义随模式切换 | `tq-lineloss-report` |
|
||
| `paginated_enrichment` | 先分页拉主列表,再逐条或逐批补数,再过滤或导出 | `marketing-zero-consumer-report` |
|
||
| `page_state_eval` | 更偏状态检查、页面判定、轻量采集 | 监测类或状态判定类场景 |
|
||
|
||
### Routing Rules
|
||
|
||
1. 有显式模式切换条件,优先判定为 `multi_mode_request`。
|
||
2. 有分页调用且伴随逐条二次请求,优先判定为 `paginated_enrichment`。
|
||
3. 无明确请求链、以页面状态判定为主,归到 `page_state_eval`。
|
||
4. 其余默认归到 `single_request_table`,但标记为低置信度。
|
||
|
||
## Extraction Architecture
|
||
|
||
### Stage 1: Deterministic Extraction
|
||
|
||
规则提取器负责抽取高确定性信息:
|
||
|
||
1. URL、请求方法、`contentType`、请求体拼装方式。
|
||
2. 分页参数,例如 `page`、`rows`、`pageSize`、`sidx`、`sord`。
|
||
3. 入口函数、导出函数、列表函数、详情函数。
|
||
4. `if/switch` 模式分支。
|
||
5. 表头、列定义、字段映射。
|
||
6. 明确的过滤条件,例如 `charge !== 0`。
|
||
|
||
### Stage 2: LLM Semantic Completion
|
||
|
||
LLM 负责以下内容:
|
||
|
||
1. 对规则提取结果做归并和命名。
|
||
2. 补全 `workflowSteps` 的高层描述。
|
||
3. 判断 archetype。
|
||
4. 推断 `requestTemplate`、`responsePath`、`normalizeRules`。
|
||
5. 输出不确定项和置信度。
|
||
|
||
### Input Strategy
|
||
|
||
当前“截前 15000/3000 字符”的做法需要替换为:
|
||
|
||
1. 目录结构摘要。
|
||
2. `index.html` 分块。
|
||
3. 命中关键模式的函数片段优先注入。
|
||
4. URL 和请求构建语句优先注入。
|
||
5. 同一场景允许分阶段提问,而不是一次性塞完整上下文。
|
||
|
||
## Compiler Architecture
|
||
|
||
### Compiler Split
|
||
|
||
建议把当前单一生成器改成 archetype 路由后的多编译器:
|
||
|
||
| Compiler | Responsibility |
|
||
|----------|----------------|
|
||
| `single_request_table` compiler | 生成简单表格采集 skill |
|
||
| `multi_mode_request` compiler | 生成多模式切换 skill |
|
||
| `paginated_enrichment` compiler | 生成分页 + 补数 + 过滤类 skill |
|
||
| `page_state_eval` compiler | 生成状态判定或轻量监测类 skill |
|
||
|
||
### Compiler Outputs
|
||
|
||
每个编译器都负责:
|
||
|
||
1. 生成 `scene.toml`。
|
||
2. 生成 `SKILL.toml`。
|
||
3. 生成 browser script。
|
||
4. 生成引用说明文档,例如 `collection-flow.md`。
|
||
5. 输出 readiness 评级和风险说明。
|
||
|
||
### Marketing Case
|
||
|
||
`marketing-zero-consumer-report` 必须走 `paginated_enrichment` 编译器,至少生成这些逻辑骨架:
|
||
|
||
1. 主列表分页采集。
|
||
2. 对每个用户执行二次请求。
|
||
3. 聚合字段。
|
||
4. 业务过滤。
|
||
5. 导出或 report artifact 输出。
|
||
|
||
### TQ Case
|
||
|
||
`tq-lineloss-report` 必须走 `multi_mode_request` 编译器,至少生成这些逻辑骨架:
|
||
|
||
1. 模式识别。
|
||
2. 模式专属请求体构建。
|
||
3. 模式专属列定义。
|
||
4. 固定响应路径抽取。
|
||
5. 统一 artifact 输出。
|
||
|
||
## Runtime Contract Alignment
|
||
|
||
当前运行时参数解析器主要集中在 [src/compat/scene_platform/resolvers.rs],能力仍偏基础。编译器设计必须显式处理这层约束。
|
||
|
||
### Short-Term Strategy
|
||
|
||
短期有两种可选策略:
|
||
|
||
1. 扩展 resolver 集合,支持更多参数合同。
|
||
2. 在生成阶段限制输出,只允许生成当前运行时能消化的参数模型。
|
||
|
||
### Recommended Resolver Additions
|
||
|
||
第一阶段建议补齐以下解析能力:
|
||
|
||
- `mode_enum`
|
||
- `date_range`
|
||
- `org_tree`
|
||
- `page_size`
|
||
- `hidden_static`
|
||
- `derived_param`
|
||
|
||
如果 resolver 暂时不扩,则生成器必须在 UI 和生成报告中明确标出“不兼容运行时合同”的风险。
|
||
|
||
## Verification And Readiness Gates
|
||
|
||
### Static Gates
|
||
|
||
生成完成后必须先过静态门禁:
|
||
|
||
1. 是否识别到业务入口。
|
||
2. 是否识别到核心请求链。
|
||
3. 是否识别到正确 bootstrap。
|
||
4. 参数合同是否与 archetype 匹配。
|
||
5. 编译器是否覆盖全部关键步骤。
|
||
|
||
### Readiness Levels
|
||
|
||
建议为每个生成结果打分级标签:
|
||
|
||
| Level | Meaning |
|
||
|-------|---------|
|
||
| `A` | 可以直接进入内网试跑 |
|
||
| `B` | 结构正确,但建议人工校验后试跑 |
|
||
| `C` | 只适合作为草稿,需要人工补逻辑 |
|
||
|
||
### Minimum Acceptance For Reference Scenes
|
||
|
||
`marketing-zero-consumer-report`:
|
||
|
||
1. 被识别为 `paginated_enrichment`。
|
||
2. 识别出主列表请求和二次补数请求。
|
||
3. 识别出 `charge !== 0` 过滤逻辑。
|
||
4. 生成结果不再退化为单请求表格模板。
|
||
|
||
`tq-lineloss-report`:
|
||
|
||
1. 被识别为 `multi_mode_request`。
|
||
2. 识别出月/周双模式。
|
||
3. 模式切换字段、请求体和列定义被区分。
|
||
4. 生成结果与手工 skill 在结构上同构。
|
||
|
||
## File Impact
|
||
|
||
### New Or Modified Areas
|
||
|
||
| File | Responsibility |
|
||
|------|----------------|
|
||
| `frontend/scene-generator/llm-client.js` | 深度抽取 schema、分块上下文、置信度输出 |
|
||
| `frontend/scene-generator/generator-runner.js` | 文件读取、关键片段抽取、目录摘要 |
|
||
| `frontend/scene-generator/server.js` | 分析接口、IR 透传、生成报告 |
|
||
| `frontend/scene-generator/sg_scene_generator.html` | 抽取预览、风险展示、readiness 展示 |
|
||
| `src/bin/sg_scene_generate.rs` | 接收 `Scene IR` 或 IR JSON 参数 |
|
||
| `src/generated_scene/analyzer.rs` | 确定性提取、archetype 辅助识别 |
|
||
| `src/generated_scene/generator.rs` | archetype 路由和多编译器编排 |
|
||
| `src/generated_scene/ir.rs` | 定义统一 `Scene IR` |
|
||
| `src/compat/scene_platform/resolvers.rs` | 参数合同对齐与扩展 |
|
||
|
||
## Migration Strategy
|
||
|
||
### Phase 1
|
||
|
||
先修当前明显错误:
|
||
|
||
1. bootstrap 来源修正。
|
||
2. 移除通用报表默认硬编码。
|
||
3. 替换截断式 LLM 输入。
|
||
4. 生成前展示抽取预览。
|
||
|
||
### Phase 2
|
||
|
||
引入 `Scene IR`,完成“先建模、再生成”的主干改造。
|
||
|
||
### Phase 3
|
||
|
||
接入 archetype 分类器和多编译器。
|
||
|
||
### Phase 4
|
||
|
||
补运行时 resolver,加入 readiness 门禁。
|
||
|
||
## Open Questions
|
||
|
||
1. `Scene IR` 是否作为单独 JSON 文件落地到输出目录,便于后续复用和回放。
|
||
2. `page_state_eval` 是否继续共用当前 `report-artifact`,还是定义独立 artifact 类型。
|
||
3. 是否允许用户在 Web UI 中手工修正 archetype、bootstrap 和参数合同后再生成。
|
||
|
||
## Acceptance Criteria
|
||
|
||
满足以下条件时,可以认为本设计达到预期:
|
||
|
||
1. 同一套生成流程能够同时覆盖 `tq-lineloss-report` 和 `marketing-zero-consumer-report` 两类差异明显的场景。
|
||
2. `marketing` 不再因错误 archetype 导致内网必然跑不通。
|
||
3. `scene.toml` 不再默认带入错误的组织、周期和标题关键字。
|
||
4. 生成结果具备明确的 readiness 分级,用户能在生成前识别风险。
|
||
5. 生成器在定位上从“模板填充器”升级为“通用场景 skill 编译器”。
|