普通视图

发现新文章,点击刷新页面。
昨天以前掘金专栏-得物技术

Claude Code Harness 工程:数仓侧落地方案|得物技术

作者 得物技术
2026年5月21日 09:56

一、AI Coding 现状与痛点:为什么需要 Harness

当前使用情况

得物离线数仓各小组已基本完成 AI Coding 工具的覆盖,主力工具为 Claude Code,辅以数据平台的 IDE 插件,应对重复性工作时效率提升明显。

核心痛点

尽管整体提效已显现,但团队在实际使用中暴露出三类结构性痛点。

痛点一:AI 不记得上下文约束,开发过程中反复"失忆"。会话开始时告知了"金额字段单位是千元",对话进行到一半后 AI 忘了,生成的 SQL 把千元当元用,导致数据差了 1000 倍。这不是偶发问题,而是 Claude Code 的 context compact 机制(上下文压缩)的系统性限制:当对话 token 接近上限(约 95%)时,历史内容被自动压缩为摘要,临时口头说的约束全部丢失。

痛点二:规范执行不稳定,靠记忆兜底的部分最容易出问题。OneData 命名规范、注释三段式、INSERT 必须带 PARTITION 子句……这些规范大家都知道。在项目工期紧张时,人工规范遵守率降至 60%~70%,AI 靠 prompt 记忆的规范遵守率也只有 70%~80%。真正需要的是:把规范从"LLM 记忆中的指导性内容"变成"每次执行时强制检查的护栏"。

痛点三:大型需求开发中,context 很快被撑满,越到后期 AI 越不可靠。复杂需求(大型宽表、大量下游血缘)的典型开发过程:

血缘查询结果(500~3000 tokens) 自测 23 条 SQL 执行结果(5000~15000 tokens) SKILL 规范文件内容(~10000 tokens) 数据比对两表样本(大量行)= context 迅速膨胀 → compact 触发 → 关键约束遗忘 → AI 开始犯低级错误

核心矛盾:越是复杂的需求,越依赖 AI;但越复杂的需求,context 越容易撑满,AI 越容易"失忆"。

从"随手问 AI"到"把能力封装起来"

针对上述痛点,我们沿用了一条反复验证的结论:规范执行是人的短板、AI 的长板;业务判断是 AI 的短板、人的长板。Harness 工程的目标,就是把"执行层"的不稳定因素系统性地消掉:把规范写进 hooks,不再靠 AI 记忆,每次写 SQL 文件后自动触发检查;把迭代约束写进持久化文件,compact 后自动重新注入,不再靠临时口头说;把高 token 操作隔离到 subagent,主 context 只接收摘要,不被过程数据撑满。

二、先搞清楚"Harness"是什么

在 Claude Code 的 update-config skill 描述中有一句话:"Automated behaviors require hooks configured in settings.json — the harness executes these, not Claude"。

Harness = Claude Code 的宿主运行框架,即 Claude Code 客户端本身这个"工具链容器"。它:管理 context window 生命周期;在 LLM 推理循环之外确定性地执行 hooks;协调 subagents 的生命周期;不依赖模型判断,直接执行配置的自动化行为。区别总结:

三、核心问题:compact 到底丢掉什么?

每次数仓开发 context 接近满时,auto-compact 触发(默认 95% 时触发),会把整个对话历史替换为一份摘要,token 缩减到原来的约 12%。哪些内容 compact 后丢失:

数仓场景最痛的点:对话中说的"这次用 OVERWRITE 模式"、"先忽略 field_a 字段" → compact 后全忘;SKILL 文件读了一半,compact 后前几个 step 的内容没了 → Claude 重复询问;自测跑出来 50 行结果,加上血缘查询的几十行表结构 → context 很快膨胀到 compact 阈值。

四、五层防御体系(从简单到复杂)

第一层:写死进 CLAUDE.md(立即可用)

机制:项目根目录 .claude/CLAUDE.md 每次 compact 后从磁盘重新注入,是最可靠的持久化位置。将当前迭代的关键信息写入,格式建议:

# 当前迭代状态(每次迭代手动更新)## 正在开发- 表:db_a.dws_table_a
 版本:V1.0
 node_id:1000000001
 状态:ETL开发阶段(Step 3/8)

## 本次迭代约束- 禁止修改:dwd_table_b(已上线,只读)
 分区字段:partition_dt(格式 yyyyMMdd,不是 dt)
 amount 字段单位:千元(不是元)

## 数仓全局规范
 建表:分区字段必须是 partition_dt string
 禁止:SELECT *UPDATE/DELETEWHERE
 金额字段用 DECIMAL(20,4),不用 DOUBLE
 INSERT 必须带 PARTITION 子句

操作规则:进入新迭代时,更新"正在开发"和"本次迭代约束"两节;上线后清空"本次迭代约束";全局规范长期保留,控制在 100 行以内。

第二层:Auto Memory 自动积累(已在运行)

机制:Claude 自动将跨会话发现写入 ~/.claude/projects//memory/MEMORY.md,每次 compact 后重新注入。数仓场景下主动触发 Claude 写记忆的时机:"这张表的 amount 字段单位是千元,请记住";"field_a 在特定场景下会为空,请记住这个踩坑";"本次 V1.0 的关键变更是 field_b 逻辑调整,请记住"。Claude 会自动写入 MEMORY.md,下次会话或 compact 后自动恢复。

第三层:hooks 自动验证(核心防御,解决"忘了检查"的问题)

这是解决"每次写完 SQL 自动检查"的关键机制。

配置文件位置

数仓项目根目录/
└── .claude/
    ├── settings.json          ← hooks 在这里配置
    ├── CLAUDE.md              ← 数仓规范上下文
    └── hooks/
        ├── validate_sql.sh          ← SQL 规范自动检查
        ├── block_dangerous_ddl.sh   ← 危险 DDL 拦截
        └── inject_context.sh        ← compact 后重注入上下文

settings.json 完整配置

{"hooks": {"PostToolUse": [{"matcher": "Write|Edit","hooks": [{"type": "command","command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/validate_sql.sh","timeout": 60,"statusMessage": "检查 SQL 规范..."}]}],"PreToolUse": [{"matcher": "Bash","hooks": [{"type": "command","command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block_dangerous_ddl.sh"}]}],"SessionStart": [{"matcher": "compact","hooks": [{"type": "command","command": "cat \"$CLAUDE_PROJECT_DIR\"/.claude/context/dw_conventions.md","statusMessage": "重注入数仓规范..."}]}],"Stop": [{"hooks": [{"type": "prompt","prompt": "检查用户要求的所有任务是否都已完成。如果还有未完成项,返回提示但不要重新开始。检查 stop_hook_active 是否为 true,如是则直接 exit。","model": "claude-haiku-4-5-20251001"}]}]}}

SQL 规范自动检查脚本

.claude/hooks/validate_sql.sh:

#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo"$INPUT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('tool_input',{}).get('file_path',''))" 2>/dev/null)

# 只处理 .sql 文件
[[ "$FILE_PATH" != *.sql ]] && exit 0
[[ -z "$FILE_PATH" ]] && exit 0

SQL=$(cat "$FILE_PATH" 2>/dev/null)
[[ -z "$SQL" ]] && exit 0

ERRORS=()

# 规范1:禁止 SELECT *echo "$SQL" | grep -iqE 'SELECT\s+\*' && ERRORS+=("CRITICAL: 发现 SELECT *,必须明确列名")

# 规范2:INSERT 必须带 PARTITIONif echo "$SQL" | grep -iqE 'INSERT\s+(INTO|OVERWRITE)'; thenecho "$SQL" | grep -iqE 'PARTITION\s*\(' || ERRORS+=("CRITICAL: INSERT 缺少 PARTITION 子句")
fi# 规范3:DOUBLE 类型金额echo "$SQL" | grep -iqE '\bDOUBLE\b' && ERRORS+=("WARNING: 金额字段建议用 DECIMAL(20,4),不用 DOUBLE")

# 规范4:UPDATE/DELETE 必须有 WHEREif echo "$SQL" | grep -iqE '\b(UPDATE|DELETE)\b'; thenecho "$SQL" | grep -iqE '\bWHERE\b' || ERRORS+=("CRITICAL: UPDATE/DELETE 缺少 WHERE 条件")
fiif [ ${#ERRORS[@]} -gt 0 ]; thenecho "=== SQL 规范检查失败:$FILE_PATH ===" >&2
  for err in"${ERRORS[@]}"; doecho "  $err" >&2
  doneexit 2
fiecho "SQL 规范检查通过: $(basename $FILE_PATH)" >&2
exit 0

危险 DDL 拦截脚本

.claude/hooks/block_dangerous_ddl.sh:

#!/bin/bash
INPUT=$(cat)
CMD=$(echo"$INPUT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('tool_input',{}).get('command',''))" 2>/dev/null)

# 拦截生产表 DROP/TRUNCATE(放行 _dev/_test/_stg 后缀)if echo "$CMD" | grep -iqE '\b(DROP\s+TABLE|TRUNCATE\s+TABLE)\b'; thenif ! echo "$CMD" | grep -qiE '(_dev|_test|_stg)\b'; thenecho "BLOCKED: 检测到生产表 DROP/TRUNCATE 操作,请确认表名是否正确" >&2
    exit 2
  fifiexit 0

hook 通信协议关键规则

图片

关键陷阱:阻断必须用 exit 2,用 exit 1 不会阻止 Claude 继续执行。

第四层:subagents 做上下文隔离(防 context 膨胀)

核心原则:把"高 token 消耗但结果只需要摘要"的操作放到 subagent 的独立 context 中执行。

数仓场景适合下放 subagent 的操作

图片

创建 subagent 文件

.claude/agents/sql-validator.md(SQL 语法验证):

---
name: sql-validator
description: ODPS/MaxCompute SQL 语法验证与规范检查专用 agent。当用户生成或修改 SQL 文件后需要验证时调用。在独立 context 运行,防止大量验证日志污染主对话。
tools: Read, Bash, Grep, Glob
model: haiku
permissionMode: dontAsk
---

你是数仓 SQL 规范专家,只做验证,不修改文件。

验证项(按优先级):
1. SELECT * 禁止
2. INSERT 必须带 PARTITION
3. 字段用 snake_case 命名
4. 金额字段用 DECIMAL 不用 DOUBLE
5. 多表 JOIN 必须有 ON 条件
6. 笛卡尔积风险检测

输出格式:
- 状态:PASS / FAIL
- 问题列表(CRITICAL / WARNING / INFO)
- 修改建议(具体到行号)

不超过 50 行,只返回结构化报告。

.claude/agents/dw-explorer.md(防止血缘查询撑爆主 context):


---
name: dw-explorer
description: 数仓结构探索 agent。当需要大量读取表结构、DDL、字段信息、血缘关系时自动调用,避免大量文件内容污染主 context。只读,不修改任何文件。
tools: Read, Glob, Grep, Bash
model: haiku
permissionMode: dontAsk
---

你是数仓探索专家,只读操作。

当被调用时:
1. 读取指定表的 DDL、字段信息、分区策略
2. 分析上下游血缘(一层)
3. 识别关键字段口径(金额、日期、状态类字段)

输出:不超过 80 行的结构化摘要,包含:
- 表基本信息(层级、粒度、分区策略)
- 核心字段定义(含口径说明)
- 上下游血缘(只列表名,不展开内容)
- 发现的特殊口径或踩坑点

使用方式

在主对话中自然触发:

用 dw-explorer 分析 db_a.dwd_table_a 的结构

对刚生成的 insert_dws_table_a.sql 用 sql-validator 验证

或强制指定(避免 Claude 自行判断):

@"sql-validator (agent)" 验证 path/to/insert.sql

第五层:SKILL 文件改造(减少 context 消耗)

当前的问题:每次调用 SKILL 文件(01~08.md),内容全部加载进主 context,加速 compact 触发。改造方向:把 SKILL 文件的"执行步骤"提炼成 subagent 指令,subagent 内部读完整 SKILL 文件,主 context 只接收结果摘要;用 path-scoped rules 替代 SKILL 文件中的规范章节,按需加载:

---
# .claude/rules/etl-rules.md
paths:
  - "**/*insert*.sql"
  - "**/*_di.sql"
  - "**/*_df.sql"
---

# ETL 开发规范(按文件路径自动加载)
- 必须有 partition_dt 分区
- INSERT OVERWRITE 前检查分区是否已存在
- 不允许跨库 JOIN

SKILL 文件保持现状,但改变调用方式:不要在主对话中直接触发,而是启动一个 subagent 来读 SKILL 文件执行 ETL,主对话只接收最终产出的 SQL 文件路径。

五、可行落地方案:数仓 Harness 架构

先让我们看一下整体的架构设计(整体架构图):

图片

这张架构图的核心逻辑是职责分层:不同类型的工作交给最合适的机制去做,而不是全部压在 Claude 的推理循环里。

持久化层解决的是"失忆"问题,任何临时口头说的约束,compact 后都会消失;但写进 .claude/CLAUDE.md 的内容,每次会话启动和 compact 后都会从磁盘重新注入——这是整套方案里最简单也最可靠的一层。

Harness 层(Hooks) 解决的是"规范靠记忆"的问题,PostToolUse hook 在每次写 .sql 文件后确定性触发,不依赖 Claude 有没有记住规范要求;违规时 exit 2 强制阻断,Claude 必须修正后才能继续,规范遵守率从 70%80% 提升到 95%+。

Subagent 层解决的是"context 被撑满"的问题,血缘查询、23 项自测、数据比对这类操作会产生大量 token,放到独立 context 的 subagent 里执行,主会话只接收一份摘要,compact 触发频率预计降低 50%70%。

三层机制分工明确,互不干扰:Hooks 处理"写动作触发的规范检查",subagent 处理"读操作的 context 隔离",CLAUDE.md 处理"跨会话状态持久化"。为了配合这套架构落地,数仓的研发流程可以拆解为 8 个大的步骤,流程图如下:

图片

从 Harness 架构的视角来看,8 个步骤可以按"对 context 的影响"分成两类:一类是直接在主会话处理(内容量有限,context 压力低):需求分析(读 PRD)、技术设计(写规范说明)、SR 导入(生成配置)、SLA/DQC(生成规则)。另一类必须通过 Harness 机制处理(否则会加速 compact 或规范失控):ETL 开发每次写 .sql 文件,PostToolUse hook 自动触发规范检查,不依赖人工提醒;自测时 23 条 SQL 的执行结果体量大,交给 data-quality-checker subagent 隔离,主会话只收 PASS/FAIL 摘要;数据比对时两表样本数据量大,交给 data-comparator subagent 隔离;性能优化时血缘 + 多层 DDL 每次 500~3000 tokens,交给 dw-explorer subagent 隔离。这种分工不是把步骤拆开独立执行,而是在同一个工作流里,让每个步骤以最合适的方式运行——context 压力小的步骤留在主会话保持流畅,context 压力大的步骤通过 subagent 隔离保持干净,规范检查通过 hook 自动执行不需要人工干预。

六、基于 SKILL 规范的数仓工作流设计

数仓 8 步 SKILL 规范(需求分析→技术设计→ETL→自测→数据比对→SR 导入→性能优化→SLA/DQC)天然对应 Harness 的三层机制。核心思路是:SKILL 文件不变,改变调用方式——主对话只读规范结论,实际执行由 subagent 或 hook 完成。

图片

各步骤推荐提示词与工作流

Step 1:需求分析

推荐提示词:

用 dw-explorer subagent 先读取上游表结构(只返回摘要),
然后按需求分析规范生成:
1. 需求摘要(≤5行)
2. 表字段口径草稿
3. 待确认问题清单(按优先级排序)
需求文档 URL:[粘贴PRD链接]

Hook 配合:SessionStart 注入当前迭代约束(版本号/表名/禁止修改的表)。

Step 2:技术设计

推荐提示词:

基于上一步确认的需求,按 OneData 规范完成技术设计:
 表名:[按 层级_域_主题_粒度_周期 格式命名]
 粒度:[描述]
 分区:partition_dt string(格式 yyyyMMdd)
 禁止:任何与上游不一致的字段命名
输出 OneData 建模说明,不超过 60

CLAUDE.md 写入(设计完成后手动更新):

## 当前迭代技术设计决策- 表名:db_a.dws_table_a
- 主键:order_no + partition_dt
- 特殊约束:amount 字段继承上游千元单位,不做转换

Step 3:ETL 开发

这是 Harness 工程价值最高的步骤,PostToolUse hook 在每次 SQL 文件保存时自动触发。

推荐提示词:

按 ETL 开发规范生成建表 DDL + Insert SQL- 建表文件:ddl_[表名].sql
- 插入文件:insert_[表名].sql
- 要求:INSERT 用 OVERWRITE 模式,PARTITION 子句必须包含 partition_dt
- 金额字段:DECIMAL(20,4),单位继承上游(千元)
生成完毕后,用 sql-validator subagent 验证两个文件

Hook 自动执行(无需手动触发):每次写入 .sql 文件 → PostToolUse hook 自动运行规范检查。若发现 SELECT * 或缺少 PARTITION → 返回 exit 2,Claude 收到错误自动修正。

Step 4:自测

推荐提示词(防止自测结果撑爆主 context):

用 data-quality-checker subagent 对 [表名] 执行 23 项标准自测,
bizdate = [日期]
补充口径约束:[如"is_perform=1 只取履约订单"]
只返回:PASS/FAIL 汇总 + FAIL 项详情(≤50行),不返回原始 SQL 执行结果

效果:23 条 SQL 的执行结果全在 subagent context 里,主对话只收到一份摘要报告。

Step 5:数据比对

推荐提示词:

用 data-comparator subagent 对比:
 新表:[新表名] partition_dt = [日期]
 参考表:[旧表名/线上表]
 比对字段:[核心金额字段列表]
 容差:≤ 0.01%(金额类)
只返回:差异超过容差的字段列表 + 差值,不返回全量对比数据

Step 6:SR数据库导入

推荐提示词(自动生成最优数据库建表参数):

用 dw-sr SKILL生成建表任务, 先查以下表的 DDL 和一层上下游血缘(只返回摘要):
- 源表:[ODPS表名]
- 目标表:[SR表名]

然后基于 DDL 摘要,分析当前 SR 同步任务的配置风险:
1. 字段类型是否有精度丢失风险(DECIMAL/DOUBLE → DECIMAL(38,18))
2. Key 字段选择是否合理(重复率是否过高导致 DUPLICATE KEY 膨胀)
3. 分区数量是否合理(partition_live_number 与下游查询窗口是否匹配)
4. DISTRIBUTED BY HASH 的 bucket 数与数据量是否匹配
5. 是否有 DATETIME 字段在 SR 侧用了 VARCHAR 存储(会导致时间过滤走全表扫描)

输出同步任务配置建议(按风险高低排序),不超过 20 行。
每条格式:[风险等级 高/中/低] 问题描述 → 建议修改方式

Step 7:性能优化

推荐提示词(防止血缘查询撑爆主 context):

用 dw-explorer subagent 先查 [表名] 的一层上下游血缘和 DDL(只返回摘要),
然后分析当前 Insert SQL 的性能瓶颈:
1. 是否有全表扫描
2. 是否有笛卡尔积风险
3. 是否可以用 MAP JOIN 替代 HASH JOIN
输出优化建议(按收益排序),不超过 30

Step 8:SLA/DQC

推荐提示词:

按 SLA/DQC 规范为 [表名] 生成 9 类 DQC 规则:
 完整性:主键非空、分区数据量
 准确性:核心金额字段与上游比对(容差 0.01%)
 一致性:is_perform 与 perform_flag 联动逻辑
 时效性:产出时间 SLA ≤ 次日 8:00
输出 DQC 配置 JSON,可直接使用

SKILL 调用方式改造(减少主 context 消耗)

当前问题:触发 SKILL 时,SKILL 文件全文(约 10KB)加载进主 context,加速 compact。改造方向:

图片

核心原则:主对话只接收决策级信息(PASS/FAIL、差异字段、优化方案),不接收过程数据(SQL 执行结果、原始血缘列表、完整 DDL 内容)。

精准对话流设计:控制AI思考的艺术

文章中多次提到 /dw-etl、/dw-自测 等命令,这是数仓研发全流程 SKILL 套件的核心触发词,每个命令对应一个封装了规范、产出格式和工具调用的标准化执行单元。核心理念:把每次都要重复讲的要求写进 SKILL,把每次都怕忘的检查点写进 SKILL,把每次都需要的结构化输出也写进 SKILL——这样谁来做需求都行,底座是一致的。

8 个 SKILL 命令一览

图片

以 /dw-etl 为例:一条命令封装了什么?ETL 开发(Step 3)是 Harness 工程价值最高的步骤,SKILL 文件内封装了:① 规范内容(写死,不靠记忆):建表规范:分区字段必须是 partition_dt STRING(格式 YYYYMMDD);金额字段:DECIMAL(26,4),不用 DOUBLE;INSERT 模式:必须使用 INSERT OVERWRITE,必须带 PARTITION 子句;禁止:SELECT *、跨库 JOIN(非血缘关系)。② 产出格式(结构化,不走样):

输出文件:
├── ddl_[表名].sql      ← ODPS 建表语句(含注释三段式、生命周期配置)
├── insert_[表名].sql   ← ODPS Insert SQL(含分区裁剪、JOIN 规范)
└── ddl_sr_[表名].sql   ← SR 建表语句(Key 列顺序、DECIMAL 精度)

③ 自动护栏(Hook 配合):每次 .sql 文件写入后,PostToolUse hook 自动执行 validate_sql.sh;发现 SELECT * 或缺少 PARTITION → exit 2 阻断,Claude 强制修正。④ subagent 卸载(防 context 膨胀):"生成完毕后,用 sql-validator subagent 验证两个文件";验证结果全在 subagent context 里,主对话只收到"PASS/FAIL + 问题列表"。综合效益数据:

图片

七、落地步骤

步骤一:项目级上下文持久化。在数仓项目目录下创建 .claude/CLAUDE.md,写入当前迭代状态。每次新迭代开始时更新"正在开发"和"本次迭代约束"两节,上线后清空约束节。全局规范永久保留,控制在 100 行以内。

步骤二:配置 hooks 自动验证。创建 .claude/settings.json + hooks/ 目录,配置 PostToolUse hook(每次写 .sql 后自动规范检查)和 PreToolUse hook(拦截危险 DDL)。效果:不需要每次手动说"帮我检查 SQL 规范",hook 在 Harness 层自动触发,不占用 Claude 推理资源。

步骤三:创建 subagents 隔离高 token 操作。创建三个核心 subagent 文件:sql-validator.md、dw-explorer.md、data-quality-checker.md。将 Step 4/5/7 的执行全部下放,预计主 context compact 频率降低 50%~70%。

八、Harness 工程能解决的核心问题

这一节是整个方案的出发点,也是对"为什么要这么做"的直接回答。

数仓 AI 开发当前的本质瓶颈:语义理解

在实际数仓 AI 开发中,技术能力不是瓶颈,语义理解才是。需求理解偏差占总返工的 40%~60%,大约 40%~50% 的工作时间花在理解需求和与业务核对口径上。精准血缘探查:准确率提升显著,远超传统方式。这两个观察揭示了同一个问题:AI 在数仓场景的不准确,根本原因不是"不会写 SQL",而是"不理解业务语义"——不知道这张表的 amount 单位是千元还是元,不知道 is_perform=1 在这个版本里意味着什么,不知道某字段在特定场景下会为空。

语义 × 数据 = 准确率

数仓 AI 开发的准确率,可以用一个公式来理解:

准确率 = 语义理解深度 × 数据规范覆盖度

图片

结论:Harness 工程的本质,是把"语义"和"规范"从不可靠的 LLM 记忆中,迁移到确定性的 hooks + 持久化文件里,从而让 语义 × 规范 = 准确率 这个等式两边的变量都变得稳定。

具体能解决的四类问题

问题一:字段口径遗忘导致的计算错误

现状:对话开始时告知了"amount 字段单位是千元",compact 后 Claude 忘了,生成的 SQL 把千元当元用,导致数据差 1000 倍。Harness 解法:字段口径写进 .claude/CLAUDE.md(compact 后重新注入);踩坑经验写进 Auto Memory(跨会话持久化);结果:这类错误从"时常发生"降到"基本不出现"。

问题二:需求理解偏差导致的返工

现状:需求文档描述的是"用户视角的 GMV",但 AI 生成了"交易视角的 GMV",两者口径不同,数据对不上,需要返工。Harness 解法:需求分析的产出(口径草稿 + 待确认问题清单)写进 CLAUDE.md 的迭代约束节;Stop hook 检查任务完整性,确认待确认问题清单已全部明确后才放行;结果:需求一次交付通过率从约 50% 提升到 90%。

问题三:SQL 规范执行不一致

现状:规范文档写了"INSERT 必须带 PARTITION",但 Claude 有时会忘,或在 compact 后规范内容被清除后生成不合规的 SQL。Harness 解法:PostToolUse hook 在每次写 .sql 文件后自动执行规范检查,不依赖 Claude 记忆;违规时 exit 2 返回错误,Claude 强制修正后才能继续;结果:规范执行率从"依赖 LLM 记忆的 70%~80%"提升到"hook 强制的 95%+"。

问题四:大型需求开发中的 context 耗尽

现状:复杂需求(大型宽表、大量下游血缘)开发过程中,血缘查询 + 自测结果 + SKILL 文件内容堆满 context,compact 触发后丢失关键约束,Claude 开始犯低级错误。Harness 解法:血缘查询 → dw-explorer subagent(独立 context,只返回摘要);23 项自测 → data-quality-checker subagent(独立 context,只返回 PASS/FAIL 报告);SKILL 文件内容 → subagent 内部读取,主 context 只接收产出的 SQL 文件路径;结果:主 context compact 频率预计降低 50%~70%。

与传统数仓 AI 开发方式的对比

图片

从"AI 帮我写代码"到"AI 嵌入研发流水线"

Harness 工程的最终目标,不是让 Claude 更聪明,而是让整个研发流水线更可靠。Claude(LLM)负责:理解需求、设计方案、生成代码——这些需要语义理解的事;Harness(hooks)负责:规范检查、危险拦截、任务完整性验证——这些需要确定性执行的事;Subagents 负责:大量文件读取、血缘查询、自测执行——这些会消耗大量 context 的事;CLAUDE.md + Memory 负责:字段口径、迭代约束、踩坑经验——这些需要跨会话持久化的事。这四层分工,让数仓 AI 开发从"对话驱动的一次性辅助"升级为"规则嵌入的流水线自动化"。

往期回顾

1.BP Claw 破解 AI 编码输入难题 ——FlinkSpec 需求智能化实践|得物技术

2.基于 Harness + SDD + 多仓管理模式的 AI 全栈开发实践|得物技术

3.通用 AI Agent 驱动网关路由安全审计实践|得物技术

4.AI驱动:从运营行为到自动化用例的智能化实践|得物技术

5.生成式召回在得物的落地技术分享与思考

文 /丹克

关注得物技术,每周三更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

未经得物技术许可严禁转载,否则依法追究法律责任。

BP Claw 破解 AI 编码输入难题 ——FlinkSpec 需求智能化实践|得物技术

作者 得物技术
2026年5月14日 13:30

一句话理解 BP Claw:它是 FlinkSpec 上游的 “AI 数据 BP”,把产品经理的非标 PRD 自动转化为 AI Coding 可消费的高质量需求文档。在深入阅读之前,先用一张表告诉你 BP Claw 能带来什么。

image.png

如果你的团队也在被以下问题困扰,这篇文章值得读完:AI Coding 效果不稳定,同样的框架、不同的需求,结果天差地别;需求沟通来回反复,一个指标口径要确认三四轮;PRD 质量参差不齐,开发阶段频繁踩雷、返工延期。BP Claw 的答案是:问题的根源在输入,解法在源头。

一、FlinkSpec:实时数仓的 AI 工程化底座

在深入 BP Claw 之前,我们先来看一个更大的图景 ——FlinkSpec。FlinkSpec 是实时数仓团队打造的 AI 工程化开发框架,它以 “需求驱动、制品为锚” 的理念,将一条实时数据链路的生命周期拆解为四个阶段,每个阶段都有严格的门控评估,确保交付质量。

FlinkSpec 全景架构

image.png

BP Claw 在 FlinkSpec 中的定位

在 FlinkSpec 的四个阶段中,需求澄清阶段是一切的起点。而需求澄清阶段的质量,取决于一个关键输入 ——PRD 文档。如果 PRD 质量不达标,后续的一切都是空中楼阁:需求定义模糊 → Intake 门控反复打回 → Define 阶段耗时翻倍;技术口径缺失 → Flink-SQL Agent 无法编码 → 频繁触发阻塞协议(BLOCK-N);验收标准不清 → Review 阶段发现问题 → 回退到 Define 重来。

image.png

BP Claw 解决实际问题案例

问题定义

商业化广告投放链路中,一次广告曝光往往由多个商家共同参与竞价。这种一对多的流量-主体映射关系,在指标聚合时会产生一个结构性的歧义:以"商家"为维度下钻时,同一次流量事件会被多个商家各自计入,导致商家侧明细加总后,与平台侧总量不等。这不是数据质量问题,而是两套在各自语义下都正确的口径共存在同一张宽表里,却没有被显式区分:impression_cnt(平台侧)去重到流量维度,一次曝光 = 1;impression_cnt(商家侧)展开到主体维度,N 个商家参与 = N。当下游消费方使用同一个字段名、却按不同语义聚合时,CTR、CVR、ROI 等衍生指标就会系统性失真。

为什么难以在开发阶段发现

实时数仓的指标开发通常以 FlinkSQL 为载体,开发侧看到的输入是 Kafka 事件流和维度表,字段语义的边界在建模时已经隐式确定。问题在于: FlinkSQL 层面的 GROUP BY 逻辑无法自动感知上游指标应该以哪个粒度聚合。如果流量事件里同时携带了 advertiser_id 列表,不同的展开方式对应完全不同的业务语义,而这一选择在代码里只是一行 UNNEST 或一个 JOIN 的差异。常规的 Code Review 能发现 SQL 逻辑错误,却很难发现"SQL 逻辑正确、但口径选择与业务预期不符"这类问题——因为两种写法都能跑通,数据差异在没有对比基准的情况下也不会报错。

BP Claw 的介入点

BP Claw 作为需求到编码之间的中间层,其核心能力是在指标定义阶段做口径显式化,而不是在开发完成后做数据校验。

具体做法是结合 OpenViking 知识库(团队历史建模文档、字段定义、历史踩坑记录)做语义召回,识别当前需求涉及的指标是否存在多粒度歧义,并在进入 FlinkSpec 之前,将以下约束显式写入需求文档:

image.png

这套约束作为 FlinkSpec 的输入,让 AI Coding 在生成 DDL 和 INSERT 逻辑时,直接基于已经对齐的语义边界,而不是从模糊描述中自行推断。

与通用 AI Coding 的差异

通用 AI Coding 工具在给定输入后,会选择一种"看起来合理"的实现——对于多商家指标,它会倾向于展开商家维度(因为需求里写了"按商家查看"),但不会主动判断这是否会导致平台侧口径膨胀。

BP Claw 的差异在于知识来源:它使用的不是通用语言模型对业务逻辑的推断,而是团队在同类建模问题上积累的历史决策和约束条件。对于"多商家指标是否需要分口径建模"这个问题,OpenViking 里已经有过明确结论,BP Claw 将其召回并作为强约束注入当前需求,而不是重新推断一次。

BP Claw 正是为了解决这个"源头问题"而生。它站在 FlinkSpec 的上游,确保进入 Define 阶段的 PRD 文档质量足够支撑后续的 AI 自动化编码。

二、产品设计:从痛点出发的解决方案

面向谁?解决什么?

image.png

设计哲学:贴合工作流,而非改造工作流

BP Claw 的设计遵循三条核心原则,原则一:嵌入现有场景——用户不需要打开新页面、学习新工具,直接在飞书群聊中 @ 机器人即可触发,和日常"拉群评审"的行为完全一致;原则二:产品经理零感知提效——产品经理只需要提交原始 PRD 文档,BP Claw 自动完成规范化转换,产品经理无需关心格式,产品经理收到的是结构化、高质量的评审群,而非一堆格式要求;原则三:不硬卡点,做参照系——PRD 评分是"参照",不是"阻塞",帮助团队建立质量意识,而非制造流程摩擦,逐步提升 PRD 质量基线,而非一刀切。

三、核心能力层

对实时数仓而言,一份好的 PRD 应该是什么样的?

在深入技术实现之前,我们先回答一个根本性问题:实时数仓对 PRD 文档的要求是什么?一份好的实时数仓 PRD,需要覆盖七大模块:

image.png

然而,产品经理提交的文档往往只覆盖了其中的 2-3 个模块,而且格式五花八门。这正是 BP Claw 要解决的核心问题 —— 需求转化。

能力一:智能需求转化(核心能力)

这是 BP Claw 最核心、最有技术含量的能力。它做的事情,本质上是 模拟一个经验丰富的数据 BP 的工作过程。

转化过程详解

image.png

转化的技术难点

如何处理常见的业务需求类型?我们总结了实时数仓中最常见的几类需求模式:

image.png

转化的核心原则:忠实于原文

原文有的信息进行结构化提取,按模板填充;原文没有的信息标记为待补充,绝不凭空捏造;原文有歧义的信息保留原始表述,同时标注歧义点;原文划删除线的标注为"本期不纳入,暂缓"。

能力二:PRD 质量评分(参照能力)

在完成需求转化后,BP Claw 会对标准化文档进行多维度质量评估,生成诊断报告。

五大评分维度

image.png

三条核心评分规则

规则一:技术口径一票否决——如果技术口径得分 < 15 分(满分 25),即使总分 ≥ 90,也标注为不可执行。原因:没有技术口径,FlinkSpec 的 Flink-SQL Agent 完全无法启动编码。规则二:验收标准缺失扣分——验收标准完全缺失,总分直接扣除 20 分;严重不足(≤5 分),扣除 10 分。原因:没有验收标准的需求,上线即翻车。规则三:溢出得分机制——某维度特别优秀可超出该维度满分,但总分上限仍为 100 分。原因:鼓励在关键维度上做到极致。

image.png

需要强调的是:PRD 评分不是硬卡点,不是流程阻塞。它是一面镜子,帮助团队看到当前 PRD 的质量水位,逐步建立质量意识。

能力三:自动拉群(工作流融合能力)

自动拉群看似简单,但它承载着一个重要的产品设计意图——降低落地阻碍。为什么做自动拉群?如果 BP Claw 只能生成文档,用户还需要手动拉群、手动 @ 人、手动转发文档,那使用体验就是割裂的。自动拉群让整个流程变成了"一步触发、全程自动":用户只需要在飞书群里 @ 机器人、@ 评审人,附上文档链接。BP Claw 自动完成:读取文档 → 生成标准化文档 → 质量评估 → 创建评审群 → 邀请成员 → 发送文档和诊断报告。评审人在新群里直接看到结构化的文档和质量报告,开始评审。这就是"贴合现有工作流"的具体体现——用户的行为没有变,但背后的效率翻了20倍。

四、技术难点与解决方案

省 Token 的技巧

在 AI 应用中,Token 消耗直接关系到成本和响应速度。BP Claw 在这方面做了多项优化。

技巧一:分段生成策略

对于包含 10 个以上指标的大文档,我们不会一次性生成完整文档(这会导致上下文溢出),而是采用分段生成:先创建文档骨架(业务背景 + 角色-页面-指标矩阵),逐个追加指标定义模块,每追加 5 个指标发送一次进度反馈,最后追加验收标准和用数链路。本质是把"一次大事务"拆成"多次小提交",即使中途失败也保留了已写入内容,不需要从头来。同时每段写入后向群聊发送进度消息(已生成 5/12 个指标),让用户有等待感知,不会误以为机器人卡死。收益:避免单次 API 调用超时,同时减少重复上下文传递的 Token 消耗。

技巧二:分层调用架构

BP Claw 采用编排者(动态调度,按需组合 Skill,职责清晰)模式,将核心逻辑拆分到三个独立 Skill 中:

image.png

每个 Skill 独立运行、独立管理上下文,避免了将所有逻辑放在同一个上下文中导致的 Token 膨胀。

技巧三:模板化 Prompt 设计

标准化文档的七大模块,每个模块都有严格定义的模板结构。通过模板约束 AI 的输出格式,避免了冗余输出:明确指定输出字段,不多不少;使用 Markdown 表格约束结构;通过 Few-Shot 示例引导输出风格。

稳定性保障:如何避免幻觉?

这是 BP Claw 最重要的技术挑战。AI 生成的文档如果出现"幻觉"(编造不存在的业务口径),后果比不生成还严重。

策略一:严格的忠实性约束

在 Skill 的核心 Prompt 中,我们设置了多层约束:

核心规则:忠实于源材料原文有的 → 结构化提取原文没有的 → 标记 ⚠️ 待补充绝不凭空发明业务定义绝不猜测技术口径

策略二:标记机制取代猜测

当 AI 遇到无法确定的信息时,不允许"猜测后继续",而是必须:明确标记为待补充;说明缺失的具体内容;给出建议补充的方向。这样做的好处是:用户看到的文档中,每一条确定的信息都是可信的。

策略三:质量评分的交叉验证

prd-quality-scorer 作为独立的评分 Skill,会对生成的文档进行"第二遍"审查。如果文档中存在明显的逻辑矛盾或不合理之处,评分报告中会直接指出。

策略四:参数校验与重试机制

• 调用飞书 API 前,强制校验所有必填参数• 文档生成失败 → 最多重试 3 次(间隔 2s → 5s → 10s 指数退避)• 3 次均失败 → 终止流程,发送明确的错误消息• 绝不降级生成"简化版"文档(不完整不如不生成)

打磨 Skill 的技巧与难点

难点一:如何让 AI 理解"实时数仓"的领域语义?普通的 LLM 并不理解"去重视图""Lookup Join""sink.properties.columns"这些领域概念。我们通过以下方式解决:领域知识注入(在 Skill 定义中嵌入实时数仓的核心概念解释);模板驱动(通过模板结构限定输出范围,减少 AI 的"自由发挥空间");Few-Shot 示例(提供真实的标准化 PRD 样例作为参考)。

难点二:如何处理超长文档?有些 PRD 文档超过 10000 字符、包含 15+ 指标,直接处理会导致 API 超时(默认 60 秒不够用)、Token 超限、输出截断。解决方案:显式设置 timeoutSeconds=1200(20 分钟);采用分段生成策略,每次只处理 3-5 个指标;实时进度反馈,让用户知道系统仍在工作。

难点三:如何协调多个 Skill 的执行顺序?BP Claw 作为"指挥家/编排者",需要严格控制 4 个步骤的执行顺序和依赖关系:

规则:严格串行,前序成功才执行后续STEP 1 成功 → STEP 2STEP 2 成功 → STEP 3STEP 3 成功或失败 → STEP 4(评分失败不阻塞)STEP 4 成功 → 完成任一关键步骤失败 → 立即终止,通知用户

为什么 STEP 3 失败不阻塞?因为质量评分是"参照"而非"卡点"。即使评分失败,标准化文档和评审群依然有价值。

五、与 FlinkSpec 的联动:全链路赋能

BP Claw → FlinkSpec 的价值传递

image.png

体验效果:PRD 质量提升对 AI Coding 的赋能

场景一:技术口径完整的 PRD——BP Claw 评分 ≥ 90 分,FlinkSpec Define 阶段一次通过,无 BLOCK,Flink-SQL Agent 直接编码无需人工干预,整体交付周期为天级 ⏱️。场景二:技术口径缺失的 PRD——BP Claw 评分 < 60 分,触发技术口径一票否决,FlinkSpec Define 阶段频繁触发阻塞协议,Flink-SQL Agent 无法编码需反复沟通,整体交付周期为周级。结论: BP Claw 每提升 10 分的 PRD 质量,FlinkSpec 的编码阶段效率约提升 30%。

六、落地运营:产品 + 运营 = 真正的落地

一个好的产品工具,如果没有运营手段的配合,是无法真正落地的。BP Claw 在落地过程中,我们采用了产品能力 + 运营能力双轮驱动的策略。

运营手段一:成熟度评分体系

我们建立了 域级 PRD 成熟度评分 机制,通过持续追踪各业务域的 PRD 质量水位,推动整体提升:

image.png

运营手段二:质量趋势追踪

通过持续收集每次 PRD 评分数据,建立质量趋势看板:按业务域维度追踪质量变化;识别高频缺失项,定向改进;月度质量复盘,表彰优秀案例。

运营手段三:最佳实践沉淀

将高分 PRD 案例沉淀为模板,形成可复用的知识资产:优秀案例库(≥ 90 分的 PRD 自动入库);改进指南(针对常见扣分项提供标准化的补充模板);新人培训(通过 BP Claw 评分报告快速上手 PRD 编写规范)。

七、快速上手

使用方法

只需一步:在飞书群聊中发送一条消息:

@商业化MOSS @评审人1 @评审人2 @评审人N.... 需求拉群 飞书PRD文档链接

image.png

然后等待 1-5 分钟,你将在新的评审群中看到:标准化 PRD 文档、质量诊断报告、改进建议清单。

注意事项

image.png

八、展望后续

本文为 FlinkSpec 系列之开篇,亦是这场工程化变革的序章。BP Claw 所立之处,不过链路之源。FlinkSpec 所图,乃以 AI 之力,将实时数仓从需求落地至验收上线的全程工序,熔铸为一套精密自洽、生生不息的智能工程体系。宏图未竟,后续系列将逐章揭幕,敬请期待!

往期回顾

1.基于 Harness + SDD + 多仓管理模式的 AI 全栈开发实践|得物技术

2.通用 AI Agent 驱动网关路由安全审计实践|得物技术

3.AI驱动:从运营行为到自动化用例的智能化实践|得物技术

4.生成式召回在得物的落地技术分享与思考

5.立正请站好:一个组件复用 Skill 的工程化实践|得物技术

文 /子宸

关注得物技术,每周更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

未经得物技术许可严禁转载,否则依法追究法律责任。

基于 Harness + SDD + 多仓管理模式的 AI 全栈开发实践|得物技术

作者 得物技术
2026年5月7日 11:12

一、核心理念:Harness 思维 — 让 AI 模仿,而不是凭空创造

全栈 AI 开发最容易踩的坑

全栈 SDD 开发中,最常见也最致命的错误是:让 AI 从零开始写代码。AI 模型具备"通识能力",给它一个需求描述,它确实能生成可运行的代码。但问题在于,这些代码往往是"外星代码":风格不一致(命名规范、目录结构、分层方式与项目现有代码不同)、复用率低(没有利用项目已有的公共组件、工具函数、请求封装)、采纳率低(Code Review 时后端同学看到"外来风格"的代码,会产生大量修改意见)。结果就是:AI 生成了代码,但 Review 成本和返工成本反而更高了。

Harness 思维的核心:给 AI 一个"模仿对象"

Harness(约束)思维的本质是:给 AI 一个已有的实现作为参照,让它照着复刻一份,而不是凭空创造。就像给一个新入职的工程师说"你照着这个模块的风格,写一个类似的",而不是"你自由发挥"——前者往往能更快产出符合团队规范的代码。

image.png

在提示词中体现 Harness

不推荐(凭空创造):

请实现一个结束语管理的 CRUD 接口

推荐(Harness 约束):

请参照现有"场景欢迎语"功能(后端接口 /api/v1/feature/list,前端入口 FeatureTable/index.tsx:53-58)实现"结束语"功能。数据结构、分层方式、命名风格都保持一致。新增场景 code:categoryCode = "SCENARIO_CLOSING"

两者的差距不在于 AI 是否"聪明",而在于你给了 AI 多少约束和上下文。约束越精准,生成代码的可用性越高。

二、全栈工作区搭建与 Codebase Indexing

为什么要搭多仓工作区?

前后端代码通常分布在两个独立仓库。如果分开打开,AI 生成后端接口时看不到前端的调用方式,生成前端代码时看不到后端的返回结构,接口字段对不上是家常便饭。将前后端代码放在同一个工作区下,有三个核心价值,Codebase Indexing:Cursor 对工作区内所有代码进行向量化嵌入,建立语义索引。AI 能跨仓库理解代码关系,生成质量大幅提升。上下文完整:AI 同时能看到前后端代码,接口字段、命名风格自然对齐。SDD 文档集中管理:前后端 SDD 文档在同一工作区,便于接口契约对齐。

Codebase Indexing 的价值

Cursor 的 Codebase Indexing 会对工作区内的代码进行向量化嵌入,建立语义索引。这意味着:当你问 AI "场景欢迎语是怎么实现的",它不需要你手动指定文件,能通过语义检索自动找到相关的 Controller、Service、前端组件。当你让 AI "照着欢迎语写结束语",它会检索到欢迎语的前后端完整实现链路,而不只是单个文件。

前后端放在同一个工作区,Codebase Indexing 覆盖两侧代码。AI 生成后端接口时能参考前端的调用方式,生成前端代码时能参考后端的返回结构。

Tips:Cursor 打开工作区后,首次索引可能需要几分钟。可以在 Cursor 设置查看索引进度。确保索引完成后再开始让 AI 生成代码,效果会明显更好。

Cursor vs Claude Code:选哪个?

在全栈 AI 开发场景下,两款工具各有侧重,下表是实测对比:

image.png

全栈工作区搭建&SDD初始化--内部全栈研发插件

以上述需求为例,工作区结构如下,.claude 和 .cursor 中已对 SDD 能力进行初始化。

三、SDD 驱动的全栈代码生成流程

全栈 SDD 的特殊之处

与纯前端/纯后端 SDD 不同,全栈 SDD 需要:生成两份 SDD 文档(前端一份、后端一份);接口契约对齐,前端 SDD 中的接口调用与后端 SDD 中的接口定义必须严格对应;字段映射一致,前端 VO 中的字段名与后端返回的 JSON 字段名一一对应。

相关概念术语

提示词编写范式

以下是经过实践验证的全栈 SDD 生成提示词模板:

这是一个前后端全栈开发工作区,需要你设计技术接口方案,同时开发前后端项目;首先你需要 cd 到对应前后端应用目录中,创建 sdd 文件;所以你需要生成两份 sdd 文档,之后我会启动两个 agent 分别实现;在生成之前,如果你需要确认某些细节,你应当先确认后生成 sdd 文档。前端应用:service-frontend/sdd-propose  feature/your-feature-name前端修改入口参考:@FeatureTable/index.tsx:53-58 @columns/index.tsx后端应用:service-backend/sdd-propose  feature/your-feature-name后端修改入口参考接口:/api/v1/feature/list需求内容:(附上需求文档或描述,并提供前后端需求点清单)

关键要素解读:

image.png

前后端需求点清单分工示例

前端需求功能点

主要是新增一个后台管理页面的 tab,涉及到搜索、展示、配置新增、删除等;利用内部 SDD 文档工具(如下图)从 PRD 描述和文档图片中提炼出需求点。

内部 SDD 文档工具

左侧导航新增"结束语" Tab。 右侧新增结束语列表页。 字段有:结束语内容、结束语描述、优先级、更新人、更新时间、操作列。

新增 / 编辑弹窗字段:结束语描述、生效日期、生效时段、生效时段、结束语话术(类型和规则这里不一一罗列)。

拖拽排序功能: 点击"排序"按钮进入排序状态,拖拽调整顺序后点击"保存"生效。

后端功能点(含接口清单)

后端功能由 AI 根据前端需求描述自主设计数据表和接口。以下是 AI 在生成 SDD 前需要明确的关键设计问题(这些问题应在提示词中列出,让 AI 先回答再生成)。

接口清单: 列表接口(支持分页,回显数据直接嵌入列表响应,无需单独回显接口)、新增接口、编辑接口(复用新增逻辑,根据 id 更新)、删除接口(逻辑删除,修改删除状态字段)、排序接口(批量更新,需考虑高效实现方案)。

字段设计: 结束语话术内容(数组类型)、结束语描述(文本)、优先级 / 序号(小整型)、更新人(字符串)、更新时间(时间戳)。

需要 AI 在 SDD 中明确回答的设计问题:

  • 主键设计:如何设计主键字段?前端发起编辑、删除时需要传递该字段。
  • 优先级自增逻辑:优先级应基于当前数据条数自增,无需前端传递,由后端自动处理。
  • 排序如何高效更新:批量排序时如何设计接口,避免 N 次单条更新?
  • 嵌套对象如何建表:参考已有的"场景欢迎语"接口,入参中存在嵌套子对象(如下方参考结构)。此类子对象应拆分到多张表,还是序列化为 JSON 字段存单张表?
  • isNextDay 字段含义:次日逻辑的具体含义是什么?前端时段选择器中"次日"勾选状态如何映射到该字段?
  • 列表回显设计:列表接口需要返回完整的回显数据(供编辑弹窗回填),无需单独提供详情接口。

为什么要把这份清单放进提示词?

这份清单做了两件重要的事:前端侧给 AI 完整的 UI 细节,让 AI 知道组件状态、字段约束、交互逻辑,避免它做"最简实现"。后端侧把模糊的设计问题提前暴露,让 AI 在写 SDD 之前先回答这些问题——这正是 Harness 思维的体现:让 AI 参照已有实现(如"欢迎语")来解决"结束语",而不是凭空设计。

SDD 文档产出

一次完整的全栈 SDD 生成,会产出以下文档:

前端 SDD:

  • proposal.md — 需求提案,描述前端要做什么。
  • spec.md — 技术规格,组件设计、接口调用、状态管理。
  • tasks.md — 任务拆分,每个 task 对应一个可执行的代码变更。

后端 SDD:

  • proposal.md — 需求提案,描述后端要做什么。
  • spec.md — 技术规格,接口设计、数据库设计、分层架构。
  • design.md — 详细设计,类图、字段映射、SQL。
  • tasks.md — 任务拆分。

SDD 指令使用说明

典型工作流示例

入门引导:

  1. openspec-onboard(首次,不熟悉才走,引导完整步骤);
  2. openspec-continue-change(提示你下一步要干嘛);
  3. openspec-ff-change(快进)。

场景 A:初次开发

  1. openspec-explore(调研,脑暴);
  2. openspec-propose "..."(生成设计);
  3. openspec-apply-change(写代码);
  4. openspec-verify-change(自测,校验代码与 SDD 文档是否对应);
  5. openspec-archive-change(收尾,归档)。

场景 B:二次开发,修改迭代已有功能

  1. openspec-explore(定位旧代码/旧 spec);
  2. openspec-propose "修改..."(生成变更 Spec);
  3. openspec-apply-change(应用修改);
  4. openspec-verify-change(验证回归);
  5. openspec-archive-change(归档)。

场景 C:二次修改,需求变更

  1. openspec-explore(调研,脑暴);
  2. openspec-propose "..."(生成设计);
  3. openspec-apply-change(写代码);
  4. 发现有问题就用 openspec-explore 修改提案;
  5. openspec-explore "需求变更:xxx"(二次脑暴);
  6. openspec-propose "根据探索结果修改提案";
  7. openspec-apply-change(执行提案中变更内容);
  8. 【可选】openspec-verify-change(验证是否有未完成任务);
  9. openspec-archive-change(归档)。

场景 D:季度大清理

  1. openspec-bulk-archive-change --before 2023-12-31(批量归档)。

总的来说,上述相对来说还是比较繁琐,保持最简使用:想(openspec-propose)、做(openspec-apply-change)、收(openspec-archive-change) 即可。

四、多 Agent 协作:前后端并行开发

为什么需要多 Agent

SDD 文档生成完毕后,前后端的代码生成工作是相互独立的——前端根据前端 SDD 生成组件和页面,后端根据后端 SDD 生成 Controller/Service/Repository。这天然适合并行执行。

Cursor 中的多 Agent 协作

Cursor 支持多个 AI 编程模式并行工作,这是其核心优势之一。全栈开发场景下Tab 1 负责前端代码生成,Tab 2 负责后端代码生成,两个 Agent 同时运行、互不阻塞。

Claude Code 中的 Subagent 能力

Claude Code 内置了 Subagent(子代理)机制,适合命令行场景下的多任务并行。

Subagent 模式

Claude Code 提供了两种多 Agent 协作模式。(下个迭代再实践一下 Team 模式和普通 Subagent 的差别)

image.png

Subagent 配置与使用

Subagent 的核心配置项:

{  "description": "前端代码生成专家",  "tools": ["Read", "Edit", "Write", "Bash", "Grep"],  "permissionMode": "bypass",  "model": "sonnet",  "skills": ["前端编码规范"]}

全栈开发场景中的应用:

 Agent(你在对话的 Claude Code)  ├── Subagent 1:读取前端 SDD,生成前端代码       ├── model: sonnet       ├── tools: Read, Edit, Write, Bash       └── 任务:按照 tasks.md 生成前端组件    ├── Subagent 2:读取后端 SDD,生成后端代码       ├── model: sonnet       ├── tools: Read, Edit, Write, Bash       └── 任务:按照 tasks.md 生成后端接口    └── Subagent 3:(可选)生成接口 Mock 数据        ├── model: haiku        └── 任务:根据后端 SDD spec.md 生成 Mock

多 Agent 实践建议

image.png

五、前后端联调:Mock 数据与分阶段验证

三阶段验证策略

直接联调往往是效率最低的验证方式,推荐采用三阶段分离验证:

阶段 1:前端 Mock 验证  前端代码 + Mock 数据 → 本地跑通页面交互,验证 UI 逻辑阶段 2:后端独立验证  后端代码 → mvn clean compile → 构建通过 → 部署到测试环境阶段 3:前后端联调  前端连接测试后端接口 → 端到端验证

这样做的好处是:前后两端的问题可以提前发现、分别修复;避免在联调阶段才暴露;节省大量排查时间。

Mock 数据编写要点

Mock 数据质量直接决定前端自测的有效性,有三个关键要求:字段名和字段类型必须与后端 SDD 中定义的完全一致;参考已有接口的真实返回数据作为模板,而不是随意构造;覆盖边界场景(空列表、单条数据、多条数据、各字段极值如空字符串、超长字符串、null 值等)。

后端独立构建验证

后端代码不需要在本地完整启动整个 Java 服务,只需编译通过即可验证大部分代码问题。

# 切换到 Java 8 环境(根据项目实际 JDK 版本调整)sdk use java 8# 进入后端项目目录cd service-backend# 编译验证(无需本地启动整个服务)mvn clean compile

编译通过意味着:语法正确、依赖关系正确、类型兼容,是部署前最快速的验证手段。

前后端联调步骤

后端代码提交并部署到测试环境;前端本地开发服务通过代理配置,将 API 请求指向测试后端地址;前端请求携带功能路由标识,确保请求路由到对应的测试环境(而不是其他人的环境);逐接口验证,重点关注字段映射、状态处理、错误场景。

六、警惕 SDD 陷阱:测试如何介入全栈研发

SDD 不等于需求文档

这是 AI 全栈开发中最容易被忽视的问题。SDD 描述的是 "技术上怎么实现" ,而不是 "业务上所有的行为" 。AI 在模仿参考代码生成新代码时,会自动复刻很多隐性功能——这些功能在参考代码中存在,AI 认为是"理所当然"的,所以没有写进 SDD 文档,但实际上已经悄悄实现了。

隐性功能示例

示例 1:变量/表单清除(前端)

// AI 模仿欢迎语弹窗生成结束语弹窗时,自动复刻了"关闭弹窗时清空表单"的逻辑const handleClose = () => {  form.resetFields();   // ← 隐性功能:关闭时清空表单字段  setContentList([]);   // ← 隐性功能:清空内容列表状态  setVisible(false);};

示例 2:数据格式转换(后端)

// AI 模仿已有接口,自动添加了业务逻辑判断if (extendInfo.getIsPermanent()) {    extendInfo.setEffectiveDate(null);   // ← 隐性:永久有效时自动清除开始日期    extendInfo.setExpirationDate(null);  // ← 隐性:永久有效时自动清除结束日期}

示例 3:默认值补齐(后端)

// AI 自动实现了"优先级自增"逻辑,SDD 文档中未提及if (Objects.isNull(req.getSequence())) {    req.setSequence(getMaxSequence() + 1);  // ← 隐性:新增时优先级自动递增}

这些隐性功能可能正是需要的,也可能完全不符合当前需求。问题在于你不知道它们的存在。

测试介入建议

image.png

给测试同学的实操建议:把 SDD 文档当作起点,而不是终点。重点 Review AI 生成的代码,问自己一个问题:"参考功能有哪些隐性行为?这些行为在新功能中是否合适?"

七、综合效益与总结

实践效益

通过本文介绍的"Harness + SDD + 多 Agent"全栈开发方法论,在实际项目中验证的效益如下:采纳率提升,相比传统前后端分离开发,工作区模式可以很好地把项目需求上下文放到一起,更便于 AI 理解需求,设计编码;尤其通过Cursor的索引能力,进一步提高采纳率以及功能实现的完整性。耗时降低,SDD 模式下,AI 分析需求后产生两套 SDD 文档,使得前后端开发完全可以并行;以本需求为例,原本前后端2+4人日需求,在这种模式下,算上环境准备、踩坑时间、联调自测时间,压缩至3人日,提效50%+。调试环节不依赖阻塞,前端功能在全栈开发的视野下,已知数据结构可mock数据自测;后端功能通过远程调试的方式,支持本地打点调试;最终一并上测试环境验证,能够明确知道问题来自于前端还是后端;AI 全栈学习成本骤降,只需掌握入门级别前后端知识,即可介入简单全栈需求开发;提高业务域需求吞吐率。

方法论总结

本文介绍的全栈 AI 开发方法论,核心可以用一张图概括:

本文基于实际全栈开发项目经验整理,所有代码示例已脱敏处理,使用通用命名替代业务专有名词,如有问题欢迎交流探讨。

往期回顾

1.通用 AI Agent 驱动网关路由安全审计实践|得物技术

2.AI驱动:从运营行为到自动化用例的智能化实践|得物技术 

3.生成式召回在得物的落地技术分享与思考

4.立正请站好:一个组件复用 Skill 的工程化实践|得物技术

5.财务数仓 Claude AI Coding 应用实战|得物技术

文 /盖伦

关注得物技术,每周更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

未经得物技术许可严禁转载,否则依法追究法律责任。

立正请站好:一个组件复用 Skill 的工程化实践|得物技术

作者 得物技术
2026年4月14日 09:53

一、背景:为什么要做这个 Skill

做这个 Skill 的初衷很直接,也很现实:功能开发时容易"顺手新建一个",而不是先复用已有组件,造成组件库越来越臃肿。这件事对团队的伤害其实是复利型的:

  • 重复组件越来越多;
  • 维护成本越来越高;
  • UI/交互一致性越来越差;
  • AI 生成代码时也更容易继续复制混乱。

所以做这个 Skill 的目标不是"帮 AI 搜索一下",而是:把"复用优先"的思考过程流程化,让 AI 在写代码前先走一遍"查索引 → 判断是否复用 → 命不中再新建"的路径。

二、想解决的不是搜索问题,而是“思考顺序”问题

一开始很容易把问题理解成:"做个组件搜索工具给 AI 用就好了"。但实际落地后发现,真正的问题不是工具有没有,而是:

  • AI 会不会主动用;
  • AI 什么时候用;
  • AI 用完之后是否还能回到项目上下文;
  • AI 能不能稳定走同一条流程。

这和 Vercel 在他们的 agent 评测里观察到的现象很像:skills 本身不是没用,而是 agent 往往不会稳定触发;而把基础知识放进 AGENTS.md 这种"被动上下文"后,稳定性反而更高。Vercel 的实验里,默认 skill 触发并没有提升通过率,加入显式指令后才明显改善,而 AGENTS.md 文档索引方案表现更稳定。这给了我一个很关键的设计方向:先解决 AI 的"决策点"问题,再解决 AI 的"能力"问题。

三、核心设计思路:AGENTS.md + Hook + Skill(三层结构)

最终采用的是三层结构:

AGENTS.md:放基础上下文(常驻)

把"组件复用优先"的规则、组件索引入口、扫描后需要做的事情,放进 AGENTS.md(或同类常驻上下文机制)里。目的不是塞满文档,而是让 AI 每轮都知道:

  • 这个仓库有组件复用机制;
  • 默认应该先查可复用组件;
  • 查不到再考虑新建;
  • 扫描后还有描述补全流程需要继续执行。

这层解决的是:AI 根本不知道你有这套机制。不写进去,AI 主动使用 skill 的概率确实会很低(这点我踩过坑)。

Hook:做路由增强(提高触发概率)

如果运行环境支持 hooks(例如 Claude Code 的 UserPromptSubmit 支持在用户 prompt 处理前注入额外上下文),就可以做一层"意图路由增强":在用户提到"组件复用 / 是否有现成组件 / 封装组件 / 查组件"等语义时,给 AI 注入提示,让它优先走组件复用流程。Claude 的文档明确写了 UserPromptSubmit 会在处理前触发,并且可通过 additionalContext 注入上下文。这层解决的是:AI 知道有 skill,但不一定想起来用。

Skill:提供流程和工具(真正执行)

Skill 不是只写说明文档,而是要提供:

  • 明确的调用入口;
  • 稳定的输出格式;
  • 可执行脚本;
  • 失败时的兜底逻辑。

OpenAI 的 Codex Skills 文档里提到 skills 是"渐进披露"机制:运行时先看到 skill 的元信息(尤其是 description),只有决定使用时才加载完整 SKILL.md;而且隐式触发高度依赖 description。这也是为什么 skill 的触发边界和描述要写得非常清楚。这层解决的是:AI 想用了,但执行过程不稳定。

四、这套 Skill 在源码里是怎么落地的(我的实现)

下面是我这次组件复用 Skill 的几个关键实现点:

先把"入口"收敛成一个:find-component.js

我在 SKILL.md 里明确规定:Agent 必须调用统一入口find-component.js。这样做的原因很简单:

  • 避免 AI 在多个脚本之间犹豫(scan-components、match-component、resolve-scope……);
  • 避免 AI 漏掉前置步骤(比如索引不存在时先扫描);
  • 避免 AI 调用路径不一致导致结果不稳定。

统一入口做了几件事(都在 find-component.js 里):接收查询词(query)、仓库根路径(repoRoot)、当前聚焦路径(startDir)。

  • 如果 components.csv 缺失,内部自动触发run-scan.js;
  • 调用 resolve-scope 计算当前应用和允许搜索范围;
  • 调用 match-component 做匹配排序;
  • 命中时记录使用(用于后续加权);
  • 按固定 JSON 协议返回结果(成功/失败/无匹配/是否触发扫描等)。

这一步本质上是把分散逻辑聚合成"一个业务动作":"查一下有没有可复用组件",而不是"先算 scope,再查 CSV,再排序,再补扫,再记 usage"。这对 AI 很关键。

不是"全仓库乱搜",而是"当前应用 + 根级共享"优先

在 monorepo 场景里,组件复用很容易踩两个坑:

  • 只搜当前 app,漏掉根级共享组件;
  • 全仓乱搜,结果太多太噪音。

所以我在 resolve-scope.js 里做了一个比较工程化的范围解析策略:

  • 读取 pnpm-workspace.yaml 解析 workspace 包;
  • 根据当前聚焦文件/目录反推 currentAppRoot;
  • 再结合 root_scope_patterns(例如 apps/_share/、packages/ 等)构建允许范围;
  • 最终形成一个搜索集合:当前应用 + 根作用域共享包。

如果没有聚焦子项目(比如 startDir 就是 repo root),则切换为全量 scope。这个设计很像人类工程师的查找策略:先看"我这个业务应用里有没有",再看"全局共享有没有",而不是直接在整个 monorepo 海里捞针。

匹配不是纯关键字:我做了"多因素加权"

组件匹配如果只做字符串包含,很快就会变成垃圾召回器。我在 match-component.js + fuzzy-match.js 里做了一个组合评分,核心包括:

  • 名称精确/包含匹配;
  • 模糊匹配(编辑距离);
  • Token 重叠;
  • 首字母缩写匹配(例如 dlp 匹配 DateLinkPicker);
  • 当前应用加权(当前 app 的组件优先);
  • 使用频率加权(常用组件更靠前);
  • 来源质量加权(README 推断质量高于纯 inferred);
  • 存在性校验(文件不存在则降权/过滤);
  • 记录类型权重(组件优先于依赖)。

这一步的目标不是追求"算法先进",而是让排序更符合团队真实使用习惯:"更可能被复用的组件排在前面"。此外我还加了一个低分阈值(NO_MATCH_SCORE_THRESHOLD):

  • 如果最高分太低,就认为是噪音命中;
  • 可以触发一次扫描后再查;
  • 还是低分则按"无匹配"返回,不把噪音结果塞给 AI。

这个点很重要,因为 AI 一旦拿到一些低质量候选,很容易"将错就错"。

把"索引构建"做成可复用流水线,而不是一次性脚本

很多类似方案停在“扫一遍生成 CSV”,然后就过时了。我这次把扫描做成了 run-scan.js -> index-manager -> enrich 的流水线,核心考虑是持续维护:

run-scan.js 负责编排流程

  • resolve-scope;
  • updateIndex;
  • 自动触发 autoEnrich(可配置)。

index-manager.js 负责索引更新策略

  • 保留历史记录并合并;
  • 根据 source_hash 跳过未变化组件;
  • 记录 last-scan-changed-ids.json;
  • 支持并行扫描(包数量较多时启用);
  • 对缺失文件支持标记 exists=0(在查找阶段也会回写)。

扫描后进入 Agent 富化(enrich)流程

  • 读取 agent-enrich-prompts.json;
  • 找出 summary 占位符项;
  • 按 id 回到 components.csv;
  • 读取源码/README;
  • 生成 summary + keywords;
  • 再通过 update-component-summary.js 写回。

更关键的是在配置里启用了:

  • agent_mode_no_fallback = true。

也就是说,在 Agent 模式下不走规则引擎降级,而是要求 Agent 必须完成这一步。这其实就是"流程化思考"的精髓:不是建议,而是纳入主流程。

让 Skill 不只是"搜索器",还是"反馈回路"

一个很容易被忽视的点是:查找命中后,我还记录了使用行为(usage-tracker)。这意味着系统不是静态的,它会逐步学习团队偏好:

  • 哪些组件经常被复用;
  • 哪些组件在某个 app 里更常出现;
  • 哪些结果应该在排序中更靠前。

这是一种很轻量但非常实用的反馈机制——不需要搞复杂训练,也能提升 AI 下一次推荐质量。

五、这次实现里,总结出"让 AI 流程化"的 3 条原则

这也是我最想分享的部分:

原则 1:把基础上下文放进 AGENTS.md(或用 Hook 注入)

如果不这样做,AI 主动使用 skill 的概率很低。原因不是 AI 笨,而是 agent 的执行是有"决策成本"的:

  • 它要先意识到有 skill;
  • 再判断该不该用;
  • 再决定什么时候用。

而把基础上下文放进 AGENTS.md 或通过 hook 提前注入,本质上是在减少决策点。Vercel 的评测结果说明了这种"被动上下文"在某些场景下会更稳定。

原则 2:Skill 需要直接提供工具函数给 AI 调

只写一堆说明文档不够。AI 在工程任务里最需要的是:

  • 一个可以直接执行的入口;
  • 明确的参数;
  • 稳定的返回结构。

所以我把 find-component.js 做成统一入口,并定义了固定 JSON 输出(ok / matches / noMatch / scanTriggered / hint / error 等),这会明显提升 AI 的执行稳定性。

原则 3:显式告诉 AI 调哪些函数,并把分散逻辑聚合到一个入口

这是最容易被忽略、也是最影响稳定性的一点。如果给 AI 暴露一堆脚本:

  • resolve-scope.js;
  • match-component.js;
  • run-scan.js;
  • scan-components.js;
  • index-manager.js。

它理论上能拼起来,但实践里很容易漏步骤、顺序错、参数错。所以我在 Skill 里显式规定:

  • 查找时用 find-component.js;
  • 构建时用 run-scan.js;
  • 更新描述时用 update-component-summary.js。

把复杂系统收敛成几个明确入口,AI 才容易稳定执行。

六、这次实践里一个很重要的认知转变

我原来以为"写 skill"是在给 AI 增加能力。现在更像是在做:给 AI 增加"默认工作方式"。换句话说,skill 不只是能力包(capability bundle),也是流程控制器(workflow controller)。

  • AGENTS.md 负责"告诉 AI 世界观";
  • Hook 负责"提醒 AI 现在该用哪套流程";
  • Skill 负责"把动作做完,并且做得稳定";
  • 日志/CSV/usage 负责"让系统可观测、可迭代"。

这套思路不只适用于组件复用,后面也可以迁移到:

  • 任务优化闭环;
  • 日志分析标准化;
  • 策略诊断流程;
  • 代码规范治理。

七、这套方案当前的价值

  • AI 开发前先查可复用组件,而不是直接新建;
  • monorepo 下按"当前应用 + 共享组件"范围检索;
  • 索引缺失自动扫描;
  • 组件描述富化进入主流程;
  • 匹配质量有加权与反馈回路;
  • 整体流程有明确入口和输出协议。

八、结语:让 AI 少一点"即兴发挥",多一点"工程纪律"

这次组件复用 Skill 的开发过程,对我最大的启发不是"AI 能帮我写多少代码",而是:AI 其实非常适合被放进一套清晰流程里工作。只要把下面三件事做好:

  • 基础上下文(AGENTS.md / hooks);
  • 可执行入口(工具函数);
  • 明确流程边界(统一入口 + 输出协议)。

AI 就不会只是"一个会说话的代码补全器",而会更像一个遵守团队规范的工程协作者。而这,才是我做这个 Skill 真正想要的结果。

引用文档: vercel.com/blog/agents…

往期回顾

1.财务数仓 Claude AI Coding 应用实战|得物技术

2.日志诊断 Skill:用 AI + MCP 一键解决BUG|得物技术

3.Redis 自动化运维最佳实践|得物技术

4.Claude在得物App数仓的深度集成与效能演进

5.Claude Code + OpenSpec 正在加速 AICoding 落地:从模型博弈到工程化的范式转移|得物技术

文 /魏无涯

关注得物技术,每周更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

未经得物技术许可严禁转载,否则依法追究法律责任。

Claude在得物App数仓的深度集成与效能演进

作者 得物技术
2026年3月26日 10:11

随着以Claude Code为代表的代码大语言模型(Code Large Language Model,以下简称Code LLM)在软件工程领域的普及,其在企业级数据仓库(以下简称数仓)建设中的应用逐渐从单一的代码补全向全链路辅助演进。本文旨在探讨Code LLM在电商数仓环境下的深度集成逻辑与工程实践。文章首先界定了数据确权中的人机边界,分析了内部数据工具向Agentic工作流演进的趋势,并提出了“认知运行时与执行运行时解耦”的架构范式。

本文认为,大模型在企业级数据仓库中的落地核心,主要体现在两大维度:一是数据确权(Data Rights Confirmation) ,二是规范化输入输出(Standardized I/O) 。以此为框架,结合得物App真实数仓建设与研发实践,系统阐述了基于Galaxy MCP的基础设施集成方案,并对智能视觉埋点、AI OneData建模、智能周报生成、策略孵化中心等典型场景的架构设计与运行逻辑进行深入分析。最后,针对大模型应用中存在的幻觉问题与合规风险,本文提出一套系统性的治理与管控机制。

image.png

一、核心逻辑界定:数仓开发中的人机边界与架构演进

Code LLM引入数仓的建设流程,并非简单的工具替换,而是对现有研发范式、职责边界及工具链架构的系统性升级。在讨论具体的提效场景前,必须首先厘清底层的逻辑支柱;若未能厘清权责边界与架构定位,大模型的引入极易演变为不可控的技术债务与运维风险。

数据确权边界:管理审批与技术实现的分离

数仓建设的工程起点是原始数据(ODS 层)的接入,该环节涉及数据来源的合法性、数据所有权的界定、个人可识别信息(Personally Identifiable Information,PII)的合规审查,以及数据质量的责任归属。这些属性决定了数据接入不仅是技术动作,更是企业内部的核心数据确权过程。在引入 AI 辅助能力时,必须严格区分**「管理审批」「技术实现」**的权责边界:

管理审批(人类主导): 数据的权限审批、合规性定责、业务口径的最终确认,属于具备法律与管理效力的行为。当前法律框架下,AI 不具备独立的民事主体资格,无法独立承担法律与管理责任,因此在确权决策环节,必须由明确的数据治理委员会或业务负责人完成人工审批与权责确认。

技术实现(AI 辅助): 在完成人工确权与审批后,涉及的 DDL 脚本编写、同步任务模板配置、基础数据质量校验(Data Quality Check,DQC)规则生成等技术执行工作,可由 Code LLM 基于已确权的元数据自动化生成,并经人工复核确认后上线执行。

明确这一边界,既保障了企业数据资产的安全与合规,也为后续工程环节的 AI 深度介入提供了合规前提。

内部工具演进:从被动式 SaaS 到 Agentic 工作流

传统的数仓研发平台(如得物 App 内部数据研发平台 Galaxy)、BI 系统及指标字典,在形态上多属于被动式内部 SaaS 工具:即工具仅提供标准化的功能模块与图形化界面(GUI),无法主动理解并完成用户的业务意图,需依赖工程师的专业技能手动操作,属于典型的「人找功能」的被动响应模式,工具的价值上限取决于功能丰富度与用户的专业熟练度。

Code LLM 的引入,促使内部数据工具向 Agentic(智能体化)工作流演进。在这一模式下,核心交互方式由 GUI 转向意图驱动的自然语言交互界面(Language User Interface,LUI);系统不再仅仅提供「编写 SQL 的环境」,而是能够接收业务意图(如「按特定维度统计退款归因」),在预设的权限与规则边界内,通过调用底层 API 自主完成元数据检索、逻辑组装,并输出最终的数据洞察或代码草案。这种演进重构了数据工具的核心价值逻辑:从「为专业人员提供功能组件」,转向「为业务用户交付可落地的任务结果」。

架构范式升级:认知运行时与执行运行时的解耦

在探讨 AI 与现有数仓架构的融合时,需先明确大模型在系统中的核心定位:大模型无法替代 Spark、Flink、ClickHouse 等传统大数据计算与存储引擎的核心算力能力,其核心价值是促成了计算架构中「认知决策」与「执行落地」的解耦分离,我们将其拆解为两个核心模块:认知运行时(Cognitive Runtime)执行运行时(Execution Runtime)

认知运行时: 由 LLM 充当核心载体,负责处理非结构化需求解析、业务逻辑到 SQL 的语义映射、代码规范校验及调优策略生成,核心处理语义与逻辑的推演工作。该模块不直接触碰物理数据,仅在数据权限管控体系的约束下,操作已确权授权的元数据(Metadata)与抽象语法树(Abstract Syntax Tree,AST)。

执行运行时: 由传统大数据计算引擎充当核心载体,负责海量数据的物理扫描、分布式计算与存储落地,核心处理确定性的算力调度与执行任务。

这种解耦架构,使得数仓系统既能保有传统引擎的高吞吐、高可靠特性,又能具备大模型的语义理解与逻辑泛化能力,同时与前文的权责边界、合规要求形成了架构层面的呼应。

本质洞察:规范化的输入与输出(Standardized I/O)

当我们试图用 AI 优化数仓系统时,若仅仅停留在「单点提效」的表层,最终往往会陷入「为了用 AI 而用 AI」的陷阱。大语言模型基于概率分布生成文本,存在固有的幻觉风险;在对数据准确性、口径一致性要求极高的数仓场景中,无约束的自然语言对话式开发(业内俗称 Vibe Coding,即无明确规范、凭感觉自由编码的模式),会导致代码风格发散、业务口径不一致、数据失真等严重问题,甚至引发合规风险。

剥离掉「AI 写代码」的表层形式,触碰数仓与 AI 融合的本质,其核心在于构建规范化的输入与输出(Standardized I/O)契约。无论是埋点设计、OneData 建模,还是周报生成与策略孵化,其底层逻辑高度一致:将模糊的业务需求,通过结构化模板、CSV、JSON 或 API 接口(规范化输入)喂给模型,并强制模型按照预设的 Markdown 模板、DDL 规范或报告框架(规范化输出)进行交付。这种基于规范的驱动开发模式(Spec-Driven Development,SDD),将大模型不可控的自由文本生成,转化为基于规范契约的受限定向编译,从根源上压缩了幻觉的产生空间,构成了 AI 在数仓中规模化应用的安全底座。

综上,明确的数据确权边界,与标准化的输入输出契约,共同构成了 Code LLM 在企业级数仓中安全、合规、规模化落地的两大核心支柱。

二、基础设施底座:Galaxy MCP 的标准化集成

要实现上述的“规范化输入与输出”,大模型必须具备感知和操作企业真实数据环境的能力。在实践中,研发团队基于模型上下文协议(Model Context Protocol, MCP),为内部数据研发平台(Galaxy)构建了标准化的集成底座。

image.png

MCP 协议:大模型与数仓环境的通信契约

Galaxy MCP 充当了 Code LLM与企业内部数据资产之间的桥梁。传统模式下,工程师需要手动复制表结构、日志信息喂给大模型;而在 MCP 架构下,大模型被赋予了“手和眼”。

通过提供统一的 HTTP Streamable 接口与 Bearer Token 鉴权机制,MCP 使得大模型能够在安全受控的前提下,直接调用底层数据平台的 API。这种集成的本质,是为大模型提供了标准化的环境感知输入

核心工具集暴露与场景映射

Galaxy MCP 向大模型暴露了一系列高度结构化的工具(Tools),这些工具构成了 Agent 执行复杂任务的基础原子。核心 API 及其对应的数仓场景映射如下:

  • 分析数据结构: 模型在编写 SQL 前,自动获取目标表的建表语句,确保字段名与数据类型绝对准确,消除幻觉。
  • 追溯数据来源: 在 OneData 建模或排查数据异常时,模型自动查询上游血缘表,梳理复杂的依赖链路。
  • 逻辑审查: 模型直接读取线上调度任务的真实 SQL 逻辑,用于代码重构或口径比对。
  • 排查任务失败: 查找特定时间段内失败的运行实例。
  • 根因分析: 模型获取完整的执行日志(如 Spark 报错堆栈),结合上下文自动分析报错原因并给出修复建议。

IDE 深度集成:鉴权链路

在工程落地中,Galaxy MCP 实现了与主流 AI IDE 的无缝集成。通过上述配置,开发者在 IDE 中只需输入自然语言指令(如:“读这个表试试:xxx.table_name”),底层大模型即可自动路由至 Galaxy MCP,完成鉴权、API 调用与结果解析的闭环。这标志着数仓开发正式迈入 Agentic 时代。

三、工程实践落地:基于规范化 I/O 的效能演进

本章将结合得物App数仓研发实证,以实际应用阐述上述底层逻辑在实际业务线中的落地场景。下面的每一个场景,均是在内部经过多轮POC验证,是“规范化输入与输出”理念的具体投射。

智能视觉埋点:多模态输入到结构化 JSON 的映射

业务背景: 埋点设计是数仓数据采集的前置环节。传统流程长期存在三大痛点:

  • 成本高: PRD 交互复杂,且开发过程中变更频繁,人工对齐耗时。
  • 业务参数发散: 历史迭代频繁、经手人多,同类交互动作命名混乱(如 like_clickclick_like_btn 混用),极大增加下游清洗成本。
  • 质量不可控: 埋点规范弱且参数点状上报,不同业务规范不一致,无法准确判断上线/修改埋点会导致下游哪些核心指标发生异常。

image.png

规范化 I/O 逻辑:

  • 需求解析与确认(前置收敛): 构建规范化的 PRD 理解 Prompt,结合原生多模态模型(如 Gemini 1.5 Pro,保留 UI 设计稿的颜色、层级、空间位置等视觉特征),输出标准化的“埋点提需文档”。经业务多轮确认无误后,再进入实质埋点设计环节。
  • 智能埋点设计(上下文注入): 整合三类核心资产作为模型输入:① 当前页面历史权威埋点字典;② 人工沉淀的埋点规范与经验;③ 离线大模型梳理的“埋点-指标”血缘关系。模型基于此契约输出设计方案。
  • 规范化输出(Schema 强校验): 强制模型输出符合企业 Schema 校验的 JSON 格式,核心实现三点:埋点格式化: event_id 必须严格符合 [event]_[page]_[block] 的格式,且事件与参数定义强绑定业务规范字典,杜绝开发随意造词。参数收敛: 基于历史权威字典,自动映射并收敛同义参数,消除发散。参数完备性: 结合业务场景自动补全必填上下文参数,避免漏埋。

实测效能: 在某社区线双周迭代抽样中,埋点设计人力投入从平均10人日缩减至5人日。更核心的收益在于:

  • 一致性提升至 95%: 通过模型前置校验,有效遏制了存量埋点的无序扩张。
  • 质量提升与规则沉淀: 全面盘点并固化了现有埋点规则,将数据质量卡点前置到设计阶段,降低埋点设计引发数仓下游指标计算的事故率。

AI OneData 建模:血缘 CSV 到标准 DDL 的编译

业务背景: OneData 方法论要求严格的数据分层与指标口径统一。但在人工执行时,面对复杂的表血缘关系,规范的遵守率往往存在波动,且梳理历史口径耗时巨大。一个典型的 OneData 项目,纯人工梳理口径溯源、编写白皮书往往需要耗费数月。

image.png

规范化 I/O 逻辑:

  • 规范化输入: 研发团队摒弃了让模型直接阅读杂乱 SQL 的做法,而是通过脚本预先提取底层表的血缘关系与字段清单,将其转化为高度结构化的 CSV 文件(如 某域onedata_表血缘.csv、某域onedata_字段清单.csv)。这些 CSV 文件连同格式严苛的 Markdown 规范文档(规定了字段分隔符 ##、溯源必须到 ODS 层等)一起作为 Prompt 注入模型。
  • 规范化输出: 模型解析多层嵌套的子查询,严格按照契约输出标准化的口径溯源文档与 Mermaid 架构图(如 引力onedata_表血缘_mermaid.md),以及符合分层规范的 DDL 语句。

实测效能: 在某业务线包含 34 张表、涉及 6 个粒度的 OneData 重构项目中,对比历史同等规模项目的纯人工评估耗时(约 60 人日),采用 AI 辅助与人工复核结合的模式,整体交付周期缩短至 16 人日(提效约 74%)。由于机器执行规范的绝对一致性,文档的格式统一度达到 100%。

智能周报生成:SQL 结果集到业务洞察的转化

业务背景: 传统 BI 报表只能展示数据,无法解释数据。业务方需要的是“为什么跌了”,而不是“跌了多少”。但如果直接让 LLM 读取原始 CSV 数据生成周报,极易出现“幻觉”(如 1+1=3 的计算错误),因为 LLM 本质上是概率模型,不擅长精确的数学运算。

image.png

规范化 I/O 逻辑: 系统设计上存在两条并行路径,而其底层逻辑的起点是同一份 Prompt 规范文档。

该规范文档充当单一可信源(Single Source of Truth):在研发阶段,LLM 读取规范文档中精确定义的字段口径、聚合顺序与格式规则,将其编译为 Python 确定性计算模块(Spec-to-Code);在运行时,同一份规范又作为约束契约传入 LLM,驱动语义叙事输出。这意味着规范的变更(如修改 WoW 计算口径)只需更新一处,两条路径同步收敛。

路径一(Python 计算层): 由 LLM 依据规范编译生成的 Python 模块负责所有确定性运算——WoW/YoY 计算、渠道贡献度排序、量级格式化(万/亿分档)——输出已预渲染的 Markdown 文本片段,不再含任何原始数值。

路径二(LLM 叙事层): 模型接收的是无需再做任何数学运算的结构化文本,其唯一任务是完成跨模块的趋势判断与业务归因叙述(如"供给下降叠加搜索量上升 → 供需错配")。

核心价值: 这一架构的核心价值在于:将 LLM 的不确定性严格限制在语义层,将数值精度的责任锁定在代码层,两者各自处于自身最可控的能力边界内,从根本上规避了"让模型直接计算 CSV 原始数据"所带来的计算幻觉与格式漂移风险。

策略孵化中心:从单点提效到端到端业务策略流

业务背景: 区别于纯粹的 Coding 提效,业务冷启动阶段(如违规作者探查)涉及完整的策略工作流:定义目标 -> 数据收集 -> 特征筛选 -> 模型训练 -> 效果回收。该过程涉及业务方、分析师、数据科学家等多个角色,存在巨大的信息损耗与特征选择的“效率孤岛”。特征选择的质量高度依赖于个人的隐性能力。

image.png

规范化 I/O 逻辑:

策略孵化中心将这一复杂的非线性探索过程,重构为基于 AI Agent 的标准化流水线,包含四大核心模块:

  • 策略工作流模块(输入端): 业务人员输入自然语言描述的业务目标(如“异常作者识别”)。
  • 样本分析与特征泛化模块: Agent 自动调用 MCP 接口检索资产,推荐相关特征(探索已有的未知),并利用 LLM 的常识推理补充行业通用特征(探索未有的未知)。输出标准化的样本拼接表。
  • 模型训练模块: Agent 根据特征类型,自动推荐并调用底层机器学习组件(如逻辑回归 LR、随机森林 RF),标准化输入输出矩阵。
  • 可视化分析模块(输出端): 最终生成包含特征重要性可视化、沙盘推演结果的标准化策略报告。

项目演进里程碑:

  • 第一期(MVP 验证): 完成样本分析模块与模型工厂的基础功能,支持逻辑回归和随机森林,并在“违规作者探查”项目中取得显著的业务增量收益。
  • 第二期(Agent 交互): 开发特征交互式 Agent 的核心对话与 PRD 生成能力,完善特征管理。
  • 第三期(高级分析): 深化可视化模块,完成保序性、显著性等高级统计学分析功能。

实测效能: 策略生成到落地的整体周期由 10 人日缩短至 1-2 人日,提效 3-5 倍。AI 的介入不仅加快了策略迭代的频率(策略新鲜度),更通过标准化流程降低了对个人隐性经验的依赖,使得策略的专业度与准确率显著提升。

智能测试与质量保障:不确定性输出的校验机制

业务背景: 财务级数据指标(如实收、补贴、平台服务费等)具有严格的勾稽关系。针对此类指标编写覆盖全面的边界测试用例耗时极长,且业务语言(如“邮费返利抵减技术服务费”)转化为测试 SQL 极其困难。

image.png

规范化 I/O 逻辑:

  • 规范驱动开发(SDD): 将测试环节前置,定义标准化的测试契约(Schema)。
  • 规范化输入: 将 DDL、业务口径文档及上游数据分布特征作为上下文输入给模型。
  • 智能用例生成: LLM 自动生成覆盖主键唯一性、非空校验、枚举值分布、业务逻辑边界。
  • 闭环诊断: 执行测试 SQL 后,若出现报错或精度异常,LLM 通过 MCP 接口自动读取执行日志进行根因诊断,精准区分“底层逻辑错误”与“浮点数计算带来的可接受精度误差”,并输出修复建议。

实测效能: 构建了“质量守夜人”机制,测试覆盖率大幅提升。在某财务项目中,模型自动生成了 20 余个复杂的校验 SQL,将数据质量卡点前置到开发阶段,显著降低了上线后的数据事故率,实现了从“人工抽测”到“机器全量自动化校验”的范式跃迁。

Spark UI Skill:数仓任务排查与智能调优

业务背景: 数仓日常运维中,Spark 任务的排查与调优(如数据倾斜、OOM、执行计划不合理)高度依赖工程师的个人经验。排查过程需要频繁查看 Spark UI,分析 DAG 图、Stage 耗时、Shuffle 数据量等,耗时且门槛高。

image.png

规范化 I/O 逻辑:

  • 规范化输入: 通过 MCP 接口或监控脚本,自动抓取 Spark UI 的核心指标(如 Stage 耗时、Task 倾斜度、GC 时间、内存使用率)及 SQL 执行计划(Explain 树),将其转化为结构化的 JSON 或文本日志作为 Prompt 注入。
  • 智能诊断推演: LLM 充当“认知运行时”,基于输入的结构化日志,结合历史调优专家经验库(如“Shuffle 阶段数据量剧增且单 Task 耗时极长 → 数据倾斜”),进行逻辑推演。
  • 规范化输出: 强制模型输出标准化的诊断报告,包含:① 根因定位(如 Join 键倾斜);② 具体调优建议(如增加 spark.sql.shuffle.partitions,或改写 SQL 引入 Broadcast Join);③ 优化后的 SQL 代码草案或参数配置。

实测效能: 将单次复杂任务排查时间从数小时缩减至分钟级。不仅大幅提升了运维效率,更将资深专家的调优经验固化为标准化的 Agent 技能(Skill),显著降低了团队的整体技术门槛。

四、提示词工程的系统架构化设计

在上述所有工程实践中,提示词(Prompt)不再是简单的自然语言对话,而是演变为了系统架构的一部分。高质量的提示词工程是实现规范化 I/O 的核心载体。

提示词作为系统配置的演进

在传统的开发模式中,系统配置通常是 YAML、JSON 或 XML 文件,用于指定数据库连接、调度频率等确定性参数。而在 AI Native 的数仓架构中,提示词承载了业务规则、编码规范与逻辑约束,成为了认知运行时的“配置文件”。这些提示词被纳入版本控制系统(如 Git),与底层代码同等对待,接受严格的 Code Review。

结构化提示词的模块化拆解

以智能周报生成场景为例,其核心的 周报数据prompt 采用了高度结构化的模块设计:

# 角色设定 (Role Definition)
你是一位资深的电商数据分析师,擅长从复杂的数据指标中提取业务洞察。
# 核心任务 (Core Task)
请基于提供的 [SQL 结果集 JSON],撰写本周的业务周报。
# 规范约束 (Constraints)
1. 必须使用 Markdown 格式,包含二级标题与无序列表。
2. 严禁捏造数据,所有数值必须来源于输入的数据集。
3. 环比计算公式为:(本期值 - 上期值) / 上期值,保留两位小数。
# 结构模板 (Output Template)
## 一、 核心指标概览
- GMV:[数值] (环比 [百分比])
- 转化率:[数值] (环比 [百分比])
## 二、 异动归因分析
[基于数据波动的具体分析]

这种模块化的提示词设计,将角色设定、任务描述、约束条件与输出模板严格分离,最大程度地降低了模型的幻觉概率,确保了输出结果的工程级可用性。

五、风险管控与治理机制

在电商数仓中引入 Code LLM,必须建立系统性的风险管控体系,以应对大模型固有的技术缺陷及企业合规要求。

幻觉风险的系统性抑制

大模型在处理复杂表关联时,可能捏造不存在的字段或错误理解业务逻辑。管控方案包括:

  • 上下文增强 (RAG) 与 MCP 强绑定: 严禁模型在无上下文的情况下“裸写” SQL。必须通过 Galaxy MCP 实时获取真实的表结构与分区信息,确保模型引用的表名、字段名均真实存在。
  • 强类型校验: 模型生成的 SQL 必须经过数仓平台的语法解析器(Parser)进行静态检查,阻断基础语法错误。

数据安全与合规保障

数据仓库包含大量商业机密与用户隐私,使用 LLM(特别是调用外部公有云 API 时)存在数据泄露风险。管控方案包括:

  • 数据脱敏拦截: 在 Prompt 提交至模型前,必须经过网关层的正则表达式与 NLP 实体识别扫描,自动屏蔽或替换真实的手机号、身份证号及真实交易金额等敏感数据。
  • 元数据隔离: 仅允许模型读取表结构(Schema)与脱敏后的样例数据(Mock Data),严禁模型直接访问生产环境的物理数据。
  • 审计追溯: 所有由 AI 辅助生成的代码变更,在版本控制系统(如 Git)中必须带有特定的 AI 标签,并记录对应的 Prompt 与生成日志,确保事故发生时可进行完整的责任追溯。

六、结论

Code LLM 对电商数据仓库的介入,绝非停留在代码补全的表层提效,而是推动了数仓研发范式的底层演进。通过界定数据确权的管理边界,研发团队能够安全地将技术实现环节交由 AI 辅助;通过引入规范驱动开发(SDD)与 Agentic 工作流,并以“规范化的输入与输出”为核心,有效抑制了大模型的不确定性。

从 Galaxy MCP 的底层基础设施打通,到智能埋点、OneData 建模、周报自动化,再到端到端的策略孵化中心,大模型正在重塑数据流转的每一个节点。在这一演进过程中,数据工程师的核心职责正在发生转移:从繁重的 SQL 编码与基础排错,转向业务逻辑的抽象、规范契约的制定以及系统架构的最终决策。未来,基于 LLM 的认知运行时将与大数据执行运行时更加深度地融合,持续推动数据仓库向智能化、自动化的方向演进。

往期回顾

1.Claude Code + OpenSpec 正在加速 AICoding 落地:从模型博弈到工程化的范式转移|得物技术

2.大禹平台:流批一体离线Dump平台的设计与应用|得物技术

3.基于 Cursor Agent 的流水线 AI CR 实践|得物技术

4.从IDE到Terminal:适合后端宝宝体质的Claude Code工作流|得物技术

5.AI编程能力边界探索:基于 Claude Code 的 Spec Coding 项目实战|得物技术

文 /博温

关注得物技术,每周更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

未经得物技术许可严禁转载,否则依法追究法律责任。

❌
❌