阅读视图

发现新文章,点击刷新页面。

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

一、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 需求智能化实践|得物技术](# 一、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.生成式召回在得物的落地技术分享与思考

文 /丹克

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

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

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

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

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

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

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

文 /丹克

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

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

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

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

一、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 需求智能化实践|得物技术

一句话理解 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 全栈开发实践|得物技术

一、核心理念: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 应用实战|得物技术

文 /盖伦

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

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

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

通用 AI Agent 驱动网关路由安全审计实践

本项目构建了一个网关路由 AI 安全审计系统,采用"通用 Agent + 业务 Skill"分层设计,增量日检/存量月检。落地 Open 网关路由越权漏洞检测流程,通过 AI 批量筛查 + 人工深度验证的人机协同模式,为大规模 API 安全审计提供了可复用的智能化解决方案。充分发挥通用 Agent 能力,业务逻辑在 Skill 中快速迭代。

一、背景与技术方案

安全审计的核心挑战

随着平台 API 规模持续扩张,安全审计面临新的规模化挑战。

image.png

主要挑战:

  • 覆盖面不足:抽样审计约覆盖 ~20%
  • 时效性压力:新接口需要更快的安全评估
  • 规则一致性:标准化检测规则难以沉淀

技术选型与建设契机

当前,以大型语言模型为基座的 AI Agent 在代码语义理解、逻辑推理与自动化执行等维度的能力已超预期成熟,工程落地准确率与稳定性得到大规模验证。这一技术跃迁使全量自动化安全审计从概念验证走向可靠实践。

传统人工抽样模式在数万条 API、数百个微服务的规模下已难以为继,而基于 AI Agent 的方案可实现 100% 路由覆盖与分钟级检测响应。本文将围绕这一契机,阐述如何构建贯穿全链路调用链的智能审计体系,解决覆盖面、时效性与规则一致性三大核心挑战。

二、技术架构

整体架构设计

架构说明:常规代码负责任务调度与结果存储,所有 AI 分析工作由超级 Agent 完成。具体项目分析告警时采用 AI 批量筛查 + 人工深度验证的人机协同模式。

image.png

具体项目分析告警时采用 AI 批量筛查 + 人工深度验证的人际协同模式:

image.png

场景化应用:

image.png

架构设计原则:通用 Agent + 业务 Skill 分离

设计优势:

image.png

  • 通用 Agent 能力最大化:充分利用 Claude Code/OpenCode 的代码理解、推理分析、上下文管理、会话恢复等标准能力,不重复造轮子
  • 业务逻辑快速迭代:检测规则、分析流程、报告格式等业务逻辑全部沉淀在 Skill 中,可随时调整优化
  • 任务可追溯可复现:通过 --resume 恢复会话现场,任何分析过程都可回溯、可验证

Skill 层核心组成

gateway-route-vuln-analyzer/
├── SKILL.md # 核心:漏洞分析主流程 
│ ├── 检测决策树(Step 1-4)
│ ├── 危害评估规则
│ └── 报告输出模板 
├── references/ 
│ ├── unauthorized_patterns.md # 越权漏洞模式库
│ ├── logic_flaws.md # 逻辑漏洞检测指南
│ ├── data_classification.md # 数据敏感性分级
│ └── report_template.md # 标准化报告模板
└── scripts/ 
└── mcpcli-gateway # CLI入口(Token优化)

MCP 工具集设计

image.png

三、漏洞检测方法论(以越权为例)

越权漏洞精细化分类

基于公开漏洞案例库分析,细分越权漏洞类型:

image.png

检测决策流程

检测分四步,前两步设有短路退出以降低成本:

路由配置检查:检查 auth_config.publicrequired_scopes,配置无异常则跳过后续审计。登录态识别:遍历调用链查找认证节点,标准认证路由直接信任,跳过代码审计 代码审计(三维检测)。:检查权限注解(@PreAuthorize)、用户 ID 来源(登录态 vs 请求参数)、所有权校验(DB 过滤 vs 代码显式校验)。精细化危害评估:区分越权读取(数据敏感性)和越权操作(利益流向),输出风险等级与修复建议。

精细化危害评估机制

越权读取 - 数据敏感性评估

依据《数据安全法》确立的数据分类分级保护制度及《网络安全法》关于网络运营者数据安全管理义务的相关要求,通过 AI Agent 对源代码文本分析(基于变量名、字段类型、接口定义等代码特征进行技术推断),对路由功能返回涉及的数据资产进行分级评估。

image.png

越权操作 - 利益流向评估

image.png

四、技术优化:Token 成本降低 95%+

问题诊断

通过对多个会话日志的深入分析,识别出 Token 消耗的关键问题:

image.png

Token 消耗热点:

image.png

优化策略与效果

MCP → CLI 转换(mcp2cli)⭐核心优化

原理:将 MCP 工具暴露为 CLI 命令,避免每次会话加载 MCP 上下文。

# 优化前:MCP调用(需加载完整MCP上下文)
Claude → MCP Server → 工具执行
# 优化后:CLI调用(直接执行,无额外上下文)
Claude → Bash → mcp2cli → 工具执行

效果:节省 61% Token 消耗。

工具返回值优化 ⭐关键优化

问题:无参数调用返回完整文件(最大 1.47MB ≈ 500K tokens)。解决方案:为 gitlab_file 添加精准参数,实现按需提取。

image.png

效果:v2 vs v1 再节省 88%。

Early-Exit 模式

原理:标准认证路由直接信任,跳过冗余代码审计。

image.png

效果:标准认证场景节省 50-70%。

AI 友好返回格式 YAML

原理:YAML 天然比 JSON 的 Token 量更少,对 AI 阅读更友好,降低模型解析成本。

五、模型选型原则与决策框架

在路由安全审计场景下,模型选型需围绕准确率与召回率两大核心指标建立决策矩阵:

image.png

最终选型:满足 P0/P1/P2 三重约束的最优模型。选型理由:在召回率 100% 的候选模型中,qwen3.5-plus 以更低的单位成本实现可接受的准确率,是批量场景下的最优解。

局限性说明:

测试集局限性:上述结论基于独立手工标注测试集(100+ 样本),与生产告警数据相互隔离,仅可作为基线参考依据。模型迭代风险:大模型迭代更新速度极快,市场中或存在性能更优、成本更低的全新模型,暂未纳入本次评测范围

AI 不是替代人工,而是放大安全工程师的能力:AI 处理重复性筛查,人工聚焦深度分析和复杂判断。

六、方法论沉淀

定制化漏洞分析能力沉淀:针对 API 越权漏洞场景,构建专属漏洞分析技能体系,持续沉淀检测规则与标准化分析流程,保障规则具备落地实战有效性。精细化危害评估体系:严格区分越权读取与越权操作两类风险行为,引入利益流向分析维度,规避一刀切式风险评级,评估更贴合业务实际风险。Token 成本系统化优化:通过 MCP→CLI 格式转换 + 代码精准按需提取 + Early-Exit 提前终止三层优化方案,整体实现 Token 成本降幅 95%+。场景化分层模型选型:批量例行场景采用高性价比模型,核心关键场景启用高精度模型,在检测效果与使用成本之间实现最优平衡

七、误报分析与改进方向

误报根因分析

基于已完成的复核告警深度分析,识别出以下主要误报原因及改进方案:

image.png

针对性改进方案

强化信任边界追踪(解决 35% 误报)

问题:AI 发现中间层没校验就停止,直接认为存在漏洞,未追踪到最终数据操作层。方案:在 Skill 中增加指导规则:发现校验就停止,发现缺失就继续,必须追踪到信任边界,中间层不能下结论。

上下游参数一致性校验(解决 25% 误报)

问题:下游方法参数有越权可能,但上游调用时未传入资源 ID。方案:分析 Controller 层 Request 对象,确认是否包含资源 ID 字段。如果上游 Request 中无资源 ID 字段,判定为"仅操作当前用户数据"。

Dubbo 配置信息补充(解决 10% 误报)

问题:内部网关转 Dubbo 传参信息 AI 无法获取,导致认证判断错误。方案:引入 Open 网关 Dubbo 配置信息(通过内部管理平台获取),新增 MCP 工具 get_dubbo_config,获取路由的 Dubbo 调用配置。

# 新增工具
"get_dubbo_config": {
    "description": "获取路由的Dubbo调用配置和参数映射",
    "inputSchema": {"route_path": "string", "service_name": "string"}
}

响应体价值预判优化(解决 10% 误报)

问题:AI 将无敏感信息的读操作误判为越权。方案:细化响应体敏感性判断规则。不敏感(可忽略):

纯状态码返回
通用配置信息(活动名称、时间、状态)
流程节点信息

后续规划

image.png

八、小结

网关路由 AI 驱动审计是一个面向 API 安全场景的智能化交付范式,将规模化安全审计升级为 AI 自动化检测 + 精细化危害评估 + Token 成本优化的标准化机制。它回答的问题:如何在网关路由规模快速扩张的背景下,实现安全漏洞的全量自动化检测,同时将成本控制在可接受范围。它证明的事:多个高危外网漏洞的实际发现,验证了 AI 在代码审计场景的有效性。单条成本 ¥0.23,某大型业务集群全量扫描一轮不到 1 万元,成本完全可控。人机协同模式有效:AI 批量筛查 + 人工深度验证,既保证效率又确保准确性。它沉淀的方法:MCP→CLI 转换、精准代码提取、Early-Exit 优化,可复用于其他 AI 安全审计场景。

九、附录

标准化告警报告模板

本项目输出标准化的漏洞分析报告,以下是模板结构:

## 漏洞分析报告

### 1. 路由信息
- 路由ID: [必填:从 analyze_route 返回的 route_id]
- 路径: [必填:分析的路由路径]
- 目标服务: [必填:目标服务名称]
- 描述: [必填:路由描述,如无则填"无"]

### 2. 接口功能分析
- 接口用途: [必填:简要说明接口用途]
- 业务场景: [必填:业务场景描述]
- 调用方: [必填:H5前端/APP客户端/小程序/其他服务]
- 数据敏感性评估:
  - 涉及数据类型: [必填:PII/金融数据/订单信息/配置信息等]
  - 敏感等级: [必填:critical/high/medium/low]
  - 影响用户范围: [必填:全平台用户/特定用户群/内部用户等]

### 3. 调用链分析
[必填:调用链树形展示,使用缩进表示层级关系,标记漏洞点]

示例格式:
[网关入口] (总耗时)
  └─ [认证服务]: [认证接口] (耗时) [认证节点]
  └─ [业务服务A]: [业务接口] (耗时) [漏洞点]
     └─ [业务服务B]: [数据库查询] (耗时)

关键中间件操作(只写与漏洞分析直接相关的部分):
- SQL: [可选:列出执行的 SQL 操作类型]
- Redis: [可选:如有 Redis 操作则填写]
- MQ: [可选:如有 MQ 操作则填写]

### 4. 漏洞详情

⚠️ 说明:
- 如果发现漏洞,必须填写此章节
- 如果未发现漏洞,填写"未发现漏洞"并跳过后续小节

#### 漏洞 1: [必填:漏洞标题]
- 严重等级: [必填:critical/high/medium/low]
- 类型: [必填:越权读取/越权操作/逻辑漏洞/竞争条件]
- 漏洞位置:
  - 服务: [必填:漏洞所在服务名称]
  - 方法: [必填:漏洞所在方法名]
  - 文件: [必填:文件路径:行号]
  - 仓库链接: [必填:GitLab 代码链接]
  - Trace ID: [必填:对应的 trace_id]
- 问题描述: [必填:详细描述漏洞原因和利用机制]
- 调用链位置: [必填:标注漏洞在调用链中的位置]
- 问题代码: [必填:漏洞代码片段,包含行号]
- 漏洞危害:
  1. [必填:直接危害]
  2. [必填:间接危害]
  3. 潜在连锁攻击: [必填:可能的连锁攻击场景]
  4. 合规风险: [必填:法律合规风险]
- 修复建议:
  1. [必填:具体修复方案]
  2. [必填:具体修复方案]
  3. [可选:额外加固建议]

### 5. 分析置信度
- 置信度: [必填:高/中/低]
- 依据: [必填:说明置信度的判断依据]

### 6. 局限性
⚠️ 数据获取不全说明:

| 限制类型 | 说明 | 影响范围 | 建议操作 |
|----------|------|----------|----------|
| [限制类型] | [说明] | [影响范围] | [建议操作] |

### 7. 二方包依赖
- 涉及的二方包: [必填:group_id:artifact_id:version - 用途说明,如无则填"无"]
- 源码获取: [必填:已获取/未获取/不需要]

### 8. 涉及的微服务
⚠️ 重要:必须包含 commit_id 和 project_path

- [service_name1] (commit: [commit_id], project: [project_path])
- [service_name2] (commit: [commit_id], project: [project_path])

往期回顾

  1. AI 驱动:从运营行为到自动化用例的智能化实践|得物技术
  2. 生成式召回在得物的落地技术分享与思考
  3. 立正请站好:一个组件复用 Skill 的工程化实践|得物技术
  4. 财务数仓 Claude AI Coding 应用实战|得物技术
  5. 日志诊断 Skill:用 AI + MCP 一键解决 BUG|得物技术

文 / 炁源

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

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

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

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

一、项目背景

随着交易业务的快速增长,对质量保障工作提出了更高标准与全新要求。为提升研发体验和架构升级,大量后台页面经历从 Vue -> React -> 全栈的迁移过程。业务演进过程中,后台能力持续迭代与优化;团队在交付新能力的同时,同步保障存量链路的稳定与可预期行为。为进一步完善测试用例覆盖范围,高效支撑回归测试与重构验证工作,需通过技术手段升级质量保障模式,为业务与架构迭代提供更充分的质量支撑。

E2E 测试: 即端到端测试,是一种从用户视角出发,模拟真实操作验证应用完整业务流程的自动化测试方法。自动化生成用例: 用线上内部运营操作日志自动生成 E2E 测试用例,快速覆盖核心流程,解决用例缺失问题。智能元素定位: 自动识别重构等场景 UI 变化并调整定位策略,实现维护流程的自动化。平台化管理: 通过数据看板管理用例和执行结果,让 E2E 测试可追踪、可优化,提升测试效率。

基于以上分析,我们致力于构建一套自动化 + 智能化的 E2E 测试方案,该方案旨在支撑快速迭代开发模式,有效应对用例覆盖与重构验证等场景,从而在现有资源条件下,持续为业务快速迭代和技术架构升级提供可靠的质量保障。

二、价值收益

提供基于线上真实运营行为的自动化 E2E 测试能力,能够实际发现页面线上/重构等场景的体验问题。在页面重构等迭代任务中,通过优化回归测试流程与资源分配,有效进一步提升测试支持效率。测试的页面代码覆盖率≥X%;无代码覆盖率场景步骤执行成功率≥X%。

页面代码覆盖率:页面用例在测试过程中 运行的代码行数 / 该页面关联的所有代码行数 * 100%步骤执行成功率:页面用例在测试过程中 执行成功的步骤数 / 用例总步骤数 * 100%。

三、方案选型

传统 E2E(DOM)

名词解释 核心差异
传统 E2E 基于 DOM 的测试方案,主要通过操作和验证浏览器中的页面元素,来模拟用户行为的测试方案。 定位方式:依赖 XPath/CSS 选择器。用例生成:手动编写或录制。维护成本:(DOM 变化需手动更新用例)。

AI E2E

名词解释 核心差异
AI E2E 指利用人工智能技术,增强传统 E2E 测试的智能化、自适应性和效率的测试方案。 定位方式:视觉识别、语义化分析(如按钮文本、图标)。用例生成:自动生成(基于用户行为日志或需求描述)。维护成本:(AI 自动适应 UI 变化)。

方案对比

传统 E2E 优势: 贴近真实用户操作:实际触发页面渲染和事件。跨页面流程验证:适合测试多步骤业务场景(如登录→下单)。传统 E2E 劣势: 脆弱性:DOM 结构变化易导致用例失败(需频繁维护定位表达式)。执行速度慢:依赖浏览器渲染和网络请求。

AI E2E 优势: 降低维护成本:减少因 UI 微调导致的用例失败。提升覆盖率:AI 可探索非预期路径(如异常输入)。AI E2E 劣势: 黑盒性:AI 决策过程不透明,调试困难。高成本:需积累足够数据优化模型,复杂视觉处理需要更高性能。

基于上述对比分析,我们选用 AI 驱动的 E2E 测试方案,能够在支持重构场景的同时,显著提升用例生成的自动化水平,从而形成高效可持续的自动化测试解决方案。

四、AI 工具选型

特征
Midscene 原生 JavaScript + WebExtensions API;开源 AI 驱动 UI 自动化工具; 支持 Playwright、Puppeteer 定制行为逻辑;支持 Dom 分析和视觉分析,如 Qwen-vl、Chain-vl。
browser-use Python + 大语言模型(LLM)+ 浏览器驱动;基于 Playwright;同时支持视觉和非视觉模型;同时支持 DOM 分析和视觉分析。

Midscene优点: 基于 JS 技术栈,前端友好,开发成本较低;支持 Playwright、Puppeteer 定制行为逻辑;公开渠道反馈与迭代节奏相对清晰;支持 DOM 与视觉多模态分析。如上优点对工程化落地更友好。Midscene缺点: 调用视觉/大模型时存在 Token 消耗与成本。

browser-use优点: 支持 Playwright 定制行为逻辑;支持 DOM 与视觉分析,能力面较全。browser-use缺点: 同样存在 Token 消耗与成本;基于 Python 技术栈,有开发语言熟悉成本。

综合评估后采用 Midscene,主要考量:与现有技术栈匹配: 以 JavaScript 为主,便于与前端工程、现有工具链协同,降低接入与维护成本。能力与扩展方式符合需求: 支持 DOM 与视觉等多路径信息输入,并可在需要时用 Puppeteer / Playwright 补充确定性、可编排的自动化逻辑,覆盖模型不稳定或不适用的环节。工程化与定制空间: 定制与扩展路径清晰,便于按业务拆解控制流、做兜底与回归,贴合当前团队的交付方式。

五、流程设计

核心流程图:

图片

Midscene 测试过程详情:

图片

核心流程可以概括为:将运营真实操作记录转化为可执行的测试用例,并通过智能化的方式在测试环境中回放验证。具体实现链路分为四个阶段:

图片

阶段一:智能用例生成——从“行为记录”到“可执行脚本”

这是整个流程的源头与起点,目标是实现测试用例的“自动化生产”。

image.png

阶段二:灵活执行触发——从“静态资产”到“动态任务”

本阶段负责调度,将静态的测试用例转化为具体的执行任务。

image.png

阶段三:AI驱动执行——从“指令”到“结果”的转化

img_v3_0210v_543748eb-43ae-4d1d-a3e6-8781967b08dg.png

阶段四:平台化数据运营——从“结果”到“决策”的质量闭环

img_v3_0210v_62103562-ae83-42a0-9e55-33fa6e26a09g.png

通过这四个阶段的闭环,系统实现了从真实运营行为到自动化测试用例的完整转化,并将执行结果转化为可运营的质量数据。

六、技术亮点

基于真实环境中的运营行为生成测试用例

image.png

基于 Midscene+Qwen2.5-VL-72B 执行用例

image.png

AI 驱动的精准 UI 交互测试

image.png

代码覆盖率作为硬指标

image.png

七、平台化效果

我们在页面上实现了以下可运营能力,将 E2E 测试从黑盒脚本转变为可管理、可追踪、可复盘的平台系统。

整体数据看板

页面列表(入口):

图片

展示内容:按业务域 / 系统 / 负责人筛选、页面级 PV/UV、用例数量、步骤执行成功率、代码覆盖率等指标。系统能力:页面维度汇总视图,将访问热度(PV/UV)与自动化质量指标(成功率 / 覆盖率)结合,指导用例优先级(高 PV 页面优先铺用例、优先治理)。

用例详情视图

用例列表(抽屉):

图片

展示内容:每条用例绑定监控系统信息、点击行为数量、执行结果、步骤成功率、打标及备注、执行/删除操作。系统能力:以线上运营行为列表为用例数据,将 可执行性评估/识别执行结果与预期偏差/可信度(打标)统一实现。

执行详情(弹窗):

图片

展示内容:按步骤展示 CLICK 结果、详细错误堆栈/描述、页面截图缩略图、单步覆盖率、页面地址与 监控系统链接。系统能力:将每一步的线上行为与 E2E 执行对照落库,让失败从黑盒变为可复盘的证据链。

点击明细(单页面的用例序列):

图片

展示内容:点击序号、点击描述(如点击某某预览弹窗/眼睛按钮)、点击行为数量等。系统能力:系统会为 Click Scope 生成更可读的描述,便于非开发同学理解与复盘,也是后续策略库/稳定性治理的输入。

八、总结展望

面对交易业务快速增长、技术栈频繁迁移、测试资源紧张的多重挑战,我们成功实现了基于真实运营行为的 AI 驱动E2E 测试方案。通过 Midscene 的视觉 AI 能力结合 Puppeteer 的精准控制,实现了用例自动化生成、智能交互执行和质量数据闭环。

之后我们将持续优化 AI 模型的准确率和稳定性,逐步实现从「用例执行」到「质量预测」的升级。同时推动平台向标准化、智能化方向发展,让质量保障真正成为业务创新的加速器而非瓶颈。

往期回顾

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

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

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

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

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

文 /卓翎

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

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

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

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

一、背景

推荐系统在提升用户体验的同时,也面临着信息茧房、兴趣收敛和内容同质化的挑战。随着用户与系统交互的深入,"推荐→用户反馈→再推荐"的闭环会逐渐强化用户的少数主兴趣,导致推荐结果趋同,降低用户的新鲜感与满意度。

生成式AI技术的快速发展为推荐系统带来了新的机遇。与传统的判别式匹配范式不同,生成式召回通过预测用户下一个可能点击的内容,实现从"匹配已知"到"预测潜在"的范式转变。在得物社区这一潮流生活方式平台上,用户对内容多样性和新颖性的需求尤为突出,这为生成式召回的探索提供了天然的场景。

基于此背景,得物启动了生成式召回方向的一期探索,旨在为下一代智能推荐系统的构建积累经验,探索推荐系统的 scaling-law 规律。

传统召回方法的局限性与生成式召回的动机

传统判别式ANN召回的局限性

  • 时序信息建模不足:难以有效捕捉用户行为序列中的长期兴趣、短期偏好及其动态演变过程。
  • 兴趣多样性受限: 基于历史行为的匹配范式容易收敛到少数高频兴趣点,难以拓展用户的兴趣广度。
  • 匹配范式天花板:判别式兴趣建模受限于已有历史数据,难以预测用户未来的、潜在的兴趣方向。
  • 兴趣融合能力弱:各兴趣点通常独立建模,缺乏对用户多兴趣间协同关系的端到端建模能力。

生成式召回的核心优势

  • Next-Token Prediction 范式:通过预测用户下一个可能点击的内容,实现端到端的用户兴趣融合建模。
  • 引导式召回机制:为生成式模型提供可控的、结构化的召回条件,确保召回内容的相关性与业务目标一致性。
  • 时序依赖建模:基于 Transformer 架构,自然捕捉用户行为序列中的时序依赖关系。
  • 兴趣预测能力:不仅能匹配已知兴趣,还能基于历史行为模式,预测用户的潜在兴趣方向。
  • 端到端优化:从用户行为序列直接生成召回结果,减少中间环节的信息损失。
  • 具有 scaling-law 规律:随着样本与模型规模的提升,能大幅提高模型的表达能力,提高线上的推荐效果。

二、技术方案

得物生成式召回系统采用 Generative Model 与 Rerank Model 联合训练的端到端设计,实现了生成与排序的协同优化。

image.png

Generative Model设计细节

生成式模型基于 Transformer 架构实现 Next-Token 生成任务,主要特征包括:

  • 主序列特征:使用用户图文和视频的有效点击序列,以及对应的一 / 二 / 三级类目序列,截断最近 100 个行为;
  • 首位 User Token 生成策略:联合训练辅助双塔模型产出首位 user_token,通过梯度隔离机制,确保生成任务与双塔任务的独立优化;
  • 模型参数配置:采用当前 DeepRec 框架可承受的最大参数规模,配置为 n_layers=3,n_heads=4,dim=64,并加入 position embedding,增强时序建模能力。

Rerank Model设计细节

重排模型与生成式模型联合训练,通过多任务学习提升召回精度:

  • 联合训练机制:通过召回目标同时训练 rerank 模型的 item 塔与 user 塔,与 Generative Model 共享底层特征表示;
  • 多任务梯度平衡:设计合理的损失权重分配策略,确保生成任务与重排任务的梯度协同优化。

推理过程:从一级类目生成到精准召回

生成式召回在线上推理时遵循"生成→向量化→检索→重排"的四步流程,兼顾了生成式模型的预测能力与向量检索的效率。

一级类目生成

推理过程首先通过生成式模块的 Decoder 生成 Top-K 一级类目。经过离线 recall@100 参数搜索对比,确定 K=4 为最优配置,在召回效果与计算成本间取得平衡。生成的一级类目作为后续步骤的 “硬条件” 向量,为多兴趣建模提供结构化引导。

多兴趣向量构造

基于生成的 K 个一级类目,通过条件双塔的 user_tower 分别得到图文和视频的 K 个用户兴趣向量。这一设计实现了兴趣解耦,每个兴趣向量专注于特定类目下的用户偏好,避免了传统单向量表示中的兴趣混淆问题。

ANN召回与Rerank排序

各兴趣向量分别进行 ANN 向量检索,从候选池中召回相关 item。召回结果再由 Rerank 模型进行精细化打分排序,最终通过蛇形 Merge 策略将多个兴趣通道的结果融合,作为最终召回列表输出。

三、实验效果

为验证生成式召回的实际效果,我们在得物社区进行了严格的AB测试。结果也带来了社区线上指标的显著提升。验证了生成式算法的在得物落地的可行性,并预示着更大的探索潜力。

核心消费指标显著提升

生成式召回在多个核心消费指标上取得显著正向效果:

指标名称 相对提升(%) 显著性
人均推荐有效VV +0.41% 显著
社区DAU均时长(秒) +0.37% 显著
人均推荐总时长(秒) +0.45% 显著
推荐曝光UV人均内容VV +0.39% 显著

多样性指标改善

除了消费深度,生成式召回在兴趣广度拓展上也表现突出:

多样性指标 相对提升(%) 显著性
人均点击一级类目数 +0.18% 显著
人均点击三级类目数 +0.23% 显著
人均曝光三级类目数 +0.19% 显著

未来工程优化方向

基于一期实践经验,后续工程优化将聚焦于:

  • 框架迁移:从 DeepRec 迁移至 DeepSea-Torch 框架,支持更大参数量与稀疏特征;
  • 架构升级:探索 One-Rec 框架落地,统一生成式与判别式召回范式;
  • 推理加速:研究模型压缩、量化等推理优化技术,进一步降低服务延迟;
  • 成本优化:通过训练策略改进和资源调度优化,降低单位效果的成本。

四、总结与展望

得物生成式召回一期实践表明,通过 “生成预测 + 引导召回” 的技术路径,可以在可控成本下,同时实现用户消费深度与兴趣广度的双重提升,为下一代智能推荐系统的构建提供了重要参考。本次实践成功验证了生成式召回在工业级推荐场景的可行性与有效性。通过 Generative Model 与 Rerank Model 的联合训练架构,实现了从判别式匹配到生成式预测的成功范式迁移。技术方案在保持推荐相关性的同时,显著提升了兴趣探索能力,为打破信息茧房提供了新的技术路径。

当前方案以一级类目作为生成目标,这是考虑到类目体系的稳定性和可解释性。下一步将基于社区样本训练 Item Embedding,并将 Item Token 离散化与用户 Next-Token 生成任务联合训练。这一演进将实现从粗粒度到细粒度的兴趣预测,提升召回的精准度。

模型能力升级

通过框架迁移大幅提升模型参数量,支持大规模稀疏特征,探索更强大的生成式模型架构。具体方向包括:

  • 扩展上下文窗口:从当前的 100 行为扩展到更长序列,更好建模用户长期兴趣;
  • 改进注意力机制:研究稀疏注意力、线性注意力等高效注意力变体,平衡效果与效率。

与LLM结合的可能性

借鉴得物在基于大语言模型的新颖性推荐上的经验,生成式召回可与 LLM 知识增强结合。LLM 的世界知识可以帮助识别用户潜在但未明确表达的兴趣,而生成式模型则负责将这些兴趣转化为可执行的召回策略,形成知识增强的生成式召回新范式。

多模态与跨域生成

探索利用多模态信息生成更丰富的用户兴趣表示,并尝试跨业务域的生成式兴趣迁移。在得物的业务生态中,社区内容与电商商品之间存在天然关联,通过跨域生成式召回,可以实现从内容兴趣到商品需求的自然过渡,提升业务协同价值。

往期回顾

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

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

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

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

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

文 /流煜曦

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

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

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

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

一、背景:为什么要做这个 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 AI Coding 应用实战|得物技术

一、引言:财务数仓为什么需要AI?

财务数仓的特殊性

在电商数仓体系中,财务域是复杂度最高、容错率最低的领域。不仅因为财务对于数据准确性的要求高,也因为财务是横向域,与几乎所有的域都有数据交叉,因此对业务 Sense 的要求很高。财务数仓工程师本质上在做三件事:

  • 业务翻译: 将交易、支付、资金、促销补贴、成本等数十个业务系统的数据,翻译成通用的财务语言;
  • 资产架构: 从 ODS 到 DWD、DWS、ADS 层层构建,确保财务 UE、财务管报等公司核心指标算得准、算得快;
  • 质量兜底: GMV 口径是否统一,退款是否扣减,分摊是否跨周期对齐,任何一个字段的偏差都可能导致错误的经营决策。

财务域的独特挑战在于:字段间存在严格的数学公式关系(正向-冲销=冲销之后),业务规则涉及跨周期分摊,对于质量的要求极高。如果单纯依靠人工兜底,要么容易出错,要么需要冗余大量人力做复核。尤其是在交付压力大的时候,质量问题就更容易被忽视。

痛点聚焦

从财务数仓的特殊性出发,我们可以总结财务数仓的痛点,大体可以分为如下几类:

基本上,在需求承接的每个环节,都可能因为"人"的问题,带来隐患。

AI 大模型能带来什么改变

为了有效解决"人"的问题,比如催得太急、看不过来、没看仔细、理解错误等问题,我们引入 AI 来做改变。核心思路是:大模型的介入不是替代数仓开发工程师,而是在「需求理解 → 代码编写 → 质量测试 → 文档沉淀」每个环节注入强推理能力。利用 AI 来代替人做大量的重复性工作,同时减少低级错误概率。

那么为什么 AI 能做到这一点?从技术发展的趋势看,有三个核心能力支撑了这一变革:

  • 超大上下文打破知识孤岛: 200k+ token 的上下文窗口,可以将表结构定义、词根字典、指标计算逻辑一次性注入模型的 “工作记忆”,实现基于全域元数据的推演,让大模型具有记忆;
  • 业务语义的自动抽象与对齐: 大模型能理解 “日活”“留存率”“归因窗口” 等业务术语,并映射为具体 SQL 实现,减少因需求理解偏差导致的返工;Claude 在编码领域显著优于其他模型,是因为它能 “懂” 业务逻辑,而不是简单的机械执行;
  • 突破人类极限的规范执行力: 人工在紧迫工期下规范遵守率通常明显下降,而大模型注入规范后,可稳定维持在高位。只要指令给得明确,大模型 “几乎” 不会出错。

参考:亚马逊 AWS 对于构建一个强大、具备自我纠错能力且能查询多种数据源的 Text-to-SQL 解决方案架构图。

二、应用场景概览:从「单点提效」到「全链路增强」

场景与提效预期

基于上述观点,在财务领域,大模型可以在哪些具体的环节落地呢?以下是根据笔者近期实践经验,列出的可落地场景及提效预期。

人机协作模式:数仓研发的「L3 时刻」

如果借用自动驾驶的分级标准,当前数仓大模型应用正处于从 L2(辅助驾驶)向 L3(有条件自动驾驶)过渡的阶段,即在明确的 Prompt 约束与规范文档支撑下,AI 能接管绝大部分标准化的执行动作。

在财务域的实践中,我们也是按照这套自动驾驶分级的方法,将日常工作拆解成了三级:

这种分工背后的逻辑是:规范执行是人类的短板、AI 的长板;业务判断是 AI 的短板、人类的长板。 人工在紧迫工期下对命名规范、分区约束、注释要求的遵守率通常明显下降,且容易因疲劳产生遗漏;而 AI 一旦"学会"了团队规范,输出的规范遵守度可稳定维持在较高水平。反过来,AI 无法替代的是那些需要理解业务上下文、权衡取舍、处理分歧的工作。

AI 对于数仓全链路研发的提效作用

学习 Andrej Karpathy 关于 ChatGPT 分享的内容时,最大的感受是:AI 最强的能力,是 "泛化"。 因此,如果我们可以把数仓研发的链路拆分清楚,那么 AI 必然能够对其中的每一个环节提效,最终带来研发效率的大幅度提升!

三、核心应用场景深度解析

AI OneData 标准化建模(财务核算数据项目)

背景:财务核算 OneData 为什么难搞?

因为:仅第一轮模型设计,就涉及百张以上的表、多个子域、十余个业务过程、数百个指标。如果考虑到后续的二次/三次迭代,工作量势必大到无法想象。在当前以交付为主的阶段,很难花费如此多的时间做基建。以某次核算项目为例,各层表数量分布如下:

同时,财务域的核心特征是来源多(全公司系统)、指标多(单表字段数众多),但以可累加指标为主。财务严格意义上没有原子指标,全是基于业务指标加工出来的派生指标,且一个财务指标往往有多种口径:业务口径、资金口径、财管报口径。并且,项目涉及多个子域(核算域、技术成本域、促销补贴域、商业化域、分析域),覆盖从「计费 → 核算 → 结算 → 财务分析」的端到端业务过程体系。如果要彻底理解核算 OneData 的构建,不仅要懂数仓,还要懂财务,还要熟悉公司财务系统,这个要求非常难做到!主要难点集中在四个方面:

口径溯源极其复杂: 大量逻辑在工程侧实现,绝大多数表缺失业务文档、技术文档、口径文档,口径逻辑需要基于代码猜测,存在错误可能性,溯源工作量巨大。

规范执行不一致: 财务域涉及表命名规范(DIM/DWD/DWS/ADM 各有格式要求)、时间周期规范(1d/7d/30d/wtd/mtd/ytd 等多种)、生命周期规范、刷新周期规范、标准字段英文命名原则({主体}{业务场景}{币种标识}{度量类型}{时间单位})。规范越细,人工遵守率越低。

跨域依赖复杂: 财务是横向域,与各业务域交叉。核算域依赖大量上游表,技术成本域需要从云服务、算法、产研人力、标注人力等多个来源接入数据。

文档输出繁琐: 每个 ADM 表都必须包含 OnePage 文档(OneData 方案最重要内容),加上口径文档、模型使用说明、下游 mapping 文档,文档间大量重复但需各写一遍。

所以,我们更需要通过 AI 的能力,来做一套新时代的建模方法论,以适应 “低投入、大设计” 的智能建模场景。

建模方法论:规范即 Prompt × 迭代收敛法 × 海量文件阅读

第一个方法论:规范沉淀是前提

AI 的输出质量完全取决于输入的规范文档质量。财务核算项目中,我们沉淀了完整的规范体系作为 Prompt 的核心输入,包括:

  • 模型设计规范:表命名、时间周期、生命周期、刷新周期;
  • 标准字段英文命名原则:{主体 /fin}{业务场景 / 费用类型}{币种标识}{度量类型}{时间单位};
  • 财务业务全链路设计理念:计费层 → 核算层 → 结算层 → 财务分析层;
  • 业务过程总线矩阵:多个业务过程与多个维度的交叉关系;
  • 数据质量监控规范:完整性、准确性、一致性、合规性、业务规则等多个大类。

第二个方法论:迭代是常态

不要期望 AI 一次给出完美结果。验证的关键是选择复杂字段进行抽查 —— 在财务场景中,重点验证涉及条件取值的字段(如分摊逻辑、冲销逻辑、多口径指标),对照 SQL 代码验证溯源路径。每次迭代的产物不只是修正后的输出,更重要的是规范文档的完善。因此,针对每次迭代的结果,快速识别要改动的点并修改,这一点就很重要。也就是说,AI 可以显著提升我们的迭代速度!

第三个方法论:海量文件阅读

因为超大的 Context,所以不仅可以把历史上已有的文档一次性灌入进去,也可以把原有设计链路的表和代码交给大模型理解,省去大量阅读和理解的时间。同时,能够帮我们精准地画出业务架构图,辅助数仓工程师理解业务、构建模型。例如财务数仓架构图,很多子模块的逻辑,都是大模型读取代码后输出思路,再由数仓团队整理形成的。

Prompt 和效果

将以上规范作为学习知识输入给模型,再把原始数据表给到模型,模型即可以产出建模建议。

Prompt 示例:

请读取以下规范文档:

  • 数仓规范资产细则(含词根字典、命名规范);
  • 离线数仓开发规范白皮书;
  • 团队 Cursor Rules;

分析目标表(输入对应的表名)的建表语句,按照数仓建模规范(ODS → DWD/DIM → DWS → ADM)的方式,输出重构后的建模建议。

第一次生成的效果展示了初步建模建议,在经过不断的调优和知识输入后,最终版本要丰富很多,形成了完整的财务核算数据 OneData 方案。

收益

经过一段时间的实施,第一版核算数据结构已经落地,效果如下:

  • 效率提升显著: 百张表的口径溯源、文档输出等标准化工作大幅压缩;
  • 规范遵守率大幅提升: 表命名、字段命名、时间周期等规范严格执行,遵守率较人工有明显改善;
  • 可复用性强: 规范文档、工具脚本、Prompt 模板、工作流程 SOP 均可跨子域复用(已在核算域、技术成本域验证);
  • 数据质量监控体系: 基于口径逻辑自动推荐 DQC 规则(完整性、准确性、一致性、合规性、业务规则等多大类)。

AI SQL Coding 实践(财务 UE 表迭代案例)

实践思路

以财务 UE 表某次迭代为代表的案例,主要成果有:

  • 代码结构优化,可读性大幅提升: 指标分段清晰、逻辑分层明确,维护成本明显降低;
  • 代码开发速度提升: 在规范与口径已对齐的前提下,从需求到可上线代码耗时缩短;
  • 性能优化: 整体基线提前完成,为下游留出更多缓冲时间。

那么,我们是如何实现这种成果的?主要靠两点,一是 PRD 快速阅读与理解,二是代码开发效率提升。

如何理解 SQL Coding 核心能力

PRD 阅读与理解方面,AI 能够帮我们实现:

快速将 PRD 中的目标、指标、维度、过滤条件提炼为结构化要点;对「大促期间」、「小仓卖家」、「冲销」等未精确定义的表述,自动生成待确认问题清单;输出「指标口径」「统计周期」「主键与粒度」等需确认条目。

代码开发效率提升方面,AI 能够帮我们实现:

基于词根、分层、命名规范与建表模板,生成符合数仓规范的 DDL 与 SELECT 语句;多维度聚合、归因逻辑、窗口函数、多层嵌套等复杂逻辑,由模型生成初版 SQL,人工校验微调;对存量长 SQL 进行分段、抽取公共逻辑、统一风格与注释。

实践中大模型显著提升点

财务 UE 表迭代需求使用 AI 开发后,具体效果如下:

指标结构分段、编码规范性、注释清晰度:

  • 新表:按数仓分层与命名规范生成 DDL 与 SQL,指标按业务域/统计口径分段组织,注释完整(字段含义、口径说明、KEY 标记等),既符合规范又便于阅读。
  • 旧表改造:在保留业务逻辑正确性的前提下,对历史「屎山」代码进行结构化改写——统一别名、补全注释、拆分过长子查询、显式写出分区过滤等,使后续维护与排查成本明显下降。
  • 代码展示对比:改动前 vs 改动后,可从「可读性、规范遵守度、注释覆盖」等维度做对比分析。

代码撰写速度大幅度提升:

  • AI Coding 的主要步骤:Step 1:整理需求 → 技术文档 将 BI 需求文档中的字段信息整理进技术文档,明确字段范围。
  • Step 2:大模型分析字段来源 提示大模型读取 DWD 源码,分析哪些字段已存在、哪些需要新增关联。
  • Step 3:大模型编写 ETL 代码 由大模型自动在 DWD → DWS → ADM 三层添加字段代码,输出改动代码集合。
  • Step 4:命名规范校准 引入指标字典和 Cursor Rules,让大模型按规范重命名字段(去掉不规范后缀)。
  • Step 5:测试 SQL 生成与跑数验证 大模型生成自测 SQL,逐步验证各层数据一致性,不通过时追问原因并溯源。

性能优化及自动调参:

  • 自动识别性能瓶颈:结合执行计划、大表扫描、数据倾斜等常见问题,由模型分析 SQL 与表结构,指出潜在慢点。
  • 优化建议生成:在分区裁剪、谓词下推、JOIN 顺序、中间结果物化等方面给出具体改写建议。
  • 参数调优方案:针对 Spark/ODPS 等引擎的资源配置、并行度、倾斜处理参数,给出可落地的调优建议,供运维或开发同学选用。

基线优化提升案例:

  • 原链路:多张表串行/并行产出,整体耗时较长。
  • 新链路:经模型辅助做表合并与逻辑下沉,收敛至更少的表,整体耗时明显缩短。
  • 优化效果:在保证口径一致的前提下,表数量与运行时间双降,基线提前完成,资源占用与调度依赖均得到简化。

AI 数据测试(财务 UE 表邮费迭代案例)

财务数据测试的特殊挑战

在数仓开发工作中,数据测试是保障数据质量的关键环节,但也是最复杂、最耗时的环节之一。特别是在财务类指标开发中,数据测试面临着多重挑战:

测试复杂度高,影响面广:

一个指标的改动往往不是孤立的,它会引发连锁反应,影响其他相关计算指标。在复杂的业务场景中,一个字段的修改可能需要同步验证数十个相关字段的正确性。这种复杂的依赖关系使得人工测试很难做到全面覆盖,容易出现遗漏

业务逻辑复杂,公式验证困难:

财务指标通常有明确的数学公式关系:正向 - 冲销 = 冲销之后:需要验证每个字段的正向值、冲销值、冲销之后值之间的计算关系;子项相加 = 汇总项:需要验证各个子项字段相加是否等于汇总字段;

财务的分摊逻辑涉及跨周期问题,难以验证:某些业务场景下,订单时间与收入确认时间不匹配,需要进行跨周期分摊,测试逻辑极其复杂。这些公式关系看似简单,但在实际测试中,需要考虑各种边界情况、精度问题、空值处理等,验证工作量巨大。

测试用例设计困难:

一个需求往往衍生出大量测试点,单纯凭借个人经验和能力,很难做到全面覆盖,容易出现测试盲区,包括:

  • 字段级别的计算逻辑验证;
  • 汇总关系的验证;
  • 冲销逻辑的验证;
  • 边界场景的验证;
  • 精度问题的验证;
  • 业务规则转化的验证。

业务语言到数据语言的转化困难:

业务人员描述的需求往往是自然语言,而数据测试需要将其转化为精确的数据验证逻辑。例如:"退小仓场景下,卖家邮费出资放在第一笔收入冲销,挂在最后一单";"邮费返利抵减技术服务费";"跨周期分摊,商业化订单时间与交易订单时间不匹配"。

AI 在数据测试中的应用实践

那么,我们如何通过 AI,来解决这些复杂问题呢?以某次财务 UE 表邮费迭代项目为例,我们深度应用 AI 进行数据测试,取得了显著效果。

项目背景:

该项目涉及邮费相关字段的全面重构,包括:

  • 迭代字段:修改多个邮费相关字段的计算逻辑;
  • 新增字段:新增大批量邮费细分字段;
  • 删除字段:废弃部分历史字段;
  • 逻辑变更:邮费返利抵减逻辑调整、冲销逻辑优化等。

AI 应用场景:

  1. 测试用例自动生成:向 AI 提出测试要求后,AI 能够自动生成完整的测试 SQL 和说明文档,包括:
  • 正向-冲销=冲销之后的验证逻辑;
  • 子项相加等于汇总项的验证逻辑;
  • 业务规则转化的验证逻辑;
  • 边界场景的验证逻辑。
  1. 规则理解层面的测试补充:AI 能够从规则理解层面补充测试案例,如抽样验证、精度验证等,减少因理解不一致带来的质量问题。特别是在复杂的跨周期分摊场景中,AI 能够识别出人工容易忽略的测试点。

  2. 复杂逻辑的逐步分析:针对复杂的业务逻辑,AI 能够逐步分析不符合预期的环节,帮助找到潜在的代码 Bug。例如在邮费冲销逻辑中,AI 能够分析退小仓场景下的多种分支情况,识别出逻辑漏洞。

  3. 上下游影响分析:AI 能够分析一个字段的改动对上下游的影响,帮助识别需要同步验证的相关字段,避免遗漏。

  4. 公式验证与精度问题诊断:AI 能够自动生成公式验证 SQL,并识别精度问题。在测试过程中,AI 能够区分真正的逻辑错误和可接受的精度误差,避免误报。

实际效果与收益

经过 AI 加持之后,效果和收益明显,包括:

开发效率提升:

测试 SQL 生成效率明显提升:从提出测试要求到生成完整测试 SQL,时间大幅缩短;测试用例覆盖度提升:AI 能够识别出人工容易忽略的测试点,测试覆盖更全面。

交付质量提升:

一次交付通过率显著提升:从规则理解层面补充测试案例,减少理解不一致带来的质量问题;针对复杂逻辑逐步分析,找到潜在代码 Bug;自动生成全面的测试用例,减少测试盲区。

问题发现能力提升:

AI 在测试过程中能够:发现人工难以发现的逻辑错误,识别精度问题并区分可接受的误差,分析复杂的业务规则转化问题,诊断上下游影响关系。

综合收益较高。通过 AI 辅助数据测试,整体交付质量大幅提升,主要体现在:测试覆盖更全面,减少遗漏,问题发现更及时,减少返工,测试效率更高,缩短测试周期,质量保障更可靠,提升交付信心。

AI 需求文档转换(财务 UE 表邮费复杂逻辑解读)

痛点

理解 PRD 和与业务产品反复核对口径,大约占数仓总体工作时间的较大比例。BI 需求文档往往复杂难懂,第一眼看过去看不懂。

实践案例:邮费 UE 迭代技术文档

以邮费 UE 迭代需求为例,BI 需求文档涉及大量字段口径调整、新增字段、废弃字段、冲销逻辑重写等复杂内容。例如通过飞书 MCP 让 Cursor 直接读取 BI 需求文档,大模型自动总结出两张表(DWS 层和 ADS 层)各自需要改什么。大模型输出的结论结构清晰,按表分类列出:

  • 字段含义/口径调整(哪些字段的逻辑需要改);
  • 数据来源与计算点(应收邮费、实收邮费的新口径);
  • 新增字段清单(应收拆分、冲销相关、实收拆分、成本、UE 等);
  • 废弃字段清单(相关历史字段);
  • 冲销逻辑重点(退小仓规则);
  • 两表关系与实现顺序(先改 DWS 再改 ADS)。

Prompt 实例:读取「邮费逻辑梳理」文档内容,分析其文字描述与财务 UE 表的代码,分析要改动的点,帮我生成对应改动代码和改动原因注释。

通过这个分析结果,能够很快地定位要改动的代码,然后一步步理解业务逻辑和具体如何改动。

效果

经过这个过程快速 get 到 PRD 缺失的内容、快速对齐,总体沟通时间有效缩减。虽然在总时间占比上看似不高,但节省的是工程师最头疼的碎片化沟通时间。

四、总结与展望

核心价值

当前市场上,部分头部大厂由于自身产品策略的原因,限制了内部使用最新的大模型和 IDE 工具,导致一线使用大模型的效率受到制约。而我们则能够更灵活地选择最适合的工具组合,在使用技巧和经验积累上具备优势。例如,我们有如下两个方面的优势:

能力层面:

  • 规范化规则遵守:注入规范后生成结果遵守度稳定维持在高位;
  • 业务抽象能力:快速理解 PRD 中的目标、指标与口径,识别模糊点;
  • 实际落地案例丰富:财务 UE 表迭代等项目已有可量化结果。

组织与场景层面:

  • 模型选择灵活,不绑定单一厂商,按任务类型选用最优模型;
  • 组织精简高效,从确定方向到试点上线路径清晰,试错迭代周期短;
  • 离线数仓分层与规范稳定,模型易学易用、效果可预期;
  • 离线任务可重跑、可回溯,模型产出便于充分校验后再上线。

未来展望

使用大模型的能力不仅仅局限在财务、局限在个人,也要向整个团队推广,包括:优先选择 1-2 个痛点明确、规范相对清晰的场景做试点;将有效的 Prompt 设计、上下文组织方式、测试用例模板等经验在团队内分享,形成可复用知识库;从「人做」为主转向「人定规则与口径、模型执行环节」的协作模式,让大模型成为数仓同学的日常助手。未来已来。

往期回顾

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

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

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

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

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

文 /丹克

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

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

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

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

一、背景

在实际迭代开发中,不同需求的代码规模差异很大,有些需求涉及上千行代码,有些则只有一两行。且对于前端的代码验收,主要侧重在界面功能,通过功能验收,没法确保每一行代码都测试到的,以及功能的代码逻辑是否合理,是否健壮、是否规范等问题,都需要通过人工代码 CR 来进一步兜底验收代码的质量,尽量降低业务线上出错的可能。但当面对上千行的代码变更时,人工 CR 也是心有余而力不足。

传统的代码审查依赖人工,面对大规模代码变更时效率有限,而 AI 代码审查能够实现自动化、标准化的质量检查,有效补充人工审查的不足。

二、前端研发 CR 现状与可优化点

CR 现状

目前前端研发同学主要使用的代码质量保障工具有前端 Apex 插件智能体、Uraya 质量分检测。其中 Apex 插件智能体是通过前端研发自助点击或 git hook 自动触发 CR 智能体执行,智能体内定制了 CR 规则以及与 MCP 的结合,利用 Cursor IDE 的 Agent 能力进行本地 AI CR ,找出代码问题、本地解决问题。Uraya 质量分检测是在创建 MR 后,通过流水线自动触发,Uraya 质量分检测代码变更的质量分浮动,产出具体问题的记录,引导研发优化代码。

可优化点

  1. 本地触发 CR 需要研发同学主动点击触发或者通过 Apex git hook 执行 CR 智能体,当开发的需求多、分支多、提交次数多的时候,时长容易漏触发、忘记点。
  2. 对于 MR 评审人员,如果希望通过 Cursor CR 时,需要在本地通过调用 CR 智能体再执行一遍,获取 CR 结果,在目前 Cursor 按量计费的背景下,重复执行 CR 智能体的成本需要及时关注。
  3. 当前流水线 Diff + 大模型 API 的 AI CR 方式,误报率较高,研发使用意愿较低。

三、AI CR 方案对比分析

基于以上现状分析,我们对不同 AI CR 方案进行了深入对比。

Cursor Agent CR 主要优势

流水线集成 CR 与本地 AI CR 差异

四、技术方案设计

结合目前现状与可优化点,我们期望能像 Uraya 质量分检测一样,在 MR 过程中通过流水线自动触发,中途每次代码提交也能自动触发,对于流水线中的 CR 不满意时,可以结合 Apex CR 智能体进行本地 CR 调整代码。

为此我们考虑结合 Cursor Agent CLI 在流水线中增加一个 AI CR 的任务,自动触发 Cursor Agent 代码 CR,并记录 CR 结论,及时展示给研发或者代码评审的同学,辅助代码质量优化。

整体链路设计如下:

  1. 当研发创建 MR 后,流水线配置了 AI CR 检测流水线后,将会自动触发 Cursor Agent CR 任务。
  2. 接收到检测任务后,将会前置将该仓库准备好,并将 MR 的信息以及制定的 CR 规则,一并交给 Cursor Agent CLI 执行,待执行完成,会得到一份 CR 报告。
  3. 接收到检测任务完成后,目前会通过 MR 评论的方式添加到对应的 MR 中,引导用户查看。
  4. 对于开发者视角,打开审查报告,可以根据审查出的问题,进行修改。
  5. 对于 CR 人员视角,打开审查报告,可以根据审查出的问题,一键添加到评论,引导开发者修改。

五、MR 流水线接入与 AI CR 报告

自动触发

以下图 MR 为例,在 MR 流水线中,添加了仓库流水线 AI 检测的检测任务,当创建 MR 时,会自动触发执行一次,在 MR 未合入的过程中,每次代码变更也会自动触发。

添加审查报告评论

检测完成后会自动添加一条 MR 评论,通知研发已完成检测,可以点击查看 CR 报告。评论概览中有审查摘要,显示聚类问题的数量;还有审查总结,即对所有反馈的总结,概览问题。

AI CR 报告

以下为实际 MR 生成的 CR 报告,可以看到,报告主要包括:MR 的基础信息、问题的分类 Tab、问题的具体描述、问题的操作。

具体问题列表

首先报告列表会对问题进行聚类,分为严重问题、警告、建议三类,切换对应 Tab 可以看到问题列表。具体的问题信息,主要有类型、问题代码、修复后代码、描述、文件路径、行号、操作等列。

添加到评论

点击操作列的添加到评论,将会一键将相关问题的信息,生成格式化描述,添加到 MR 的评论中,提醒开发者关注问题、解决问题。

AI 智能解决

点击操作列的 Cursor 解决,将会一键将相关问题的信息,生成解决问题 Prompt,一键打开本地 Cursor ,创建 Agent 对话去解决问题。打开链接后,Cursor 会先接收 Prompt ,你可以简单浏览下,点击 Create Chat ,即可一键创建 Chat,回车执行修复。

Cursor Prompt 预览

Cursor Prompt 预览 确认填入 Chat 执行

复制 Prompt

点击复制 Prompt,支持一键复制修复问题 Prompt,可以放到期望的 IDE 里使用。如下图,就是复制的 Prompt 示例。

六、推荐研发流程实践

尽早创建 MR

当需求分支第一次提交后,就可以创建到 release 或 test 目标分支的 MR 了,后续每次提交代码都将会自动触发检测,产出 AI CR 报告。

研发自主查看与解决

研发收到 AI CR 报告的通知后,可以及时打开 CR 报告查看,确认反馈的疑问点是否需要调整,如果需要调整可以通过 Cursor 一键解决,将问题解决前置到提测以前,这样所有的改动可以尽可能的被测试同学验证到。

人工 CR

发布前最后的人工 CR 可以通过前置的 AI CR 发现与问题前置解决,大幅提升靠最后人工 CR 的反馈、修改等环节效率。特别是当业务需求代码量较大时,人工 CR 浏览的效率和质量也是无法保证的。

七、内置提示词工程

AI CR 其实就像给 AI 一个详细的检查清单。这个清单分两部分:一部分是基本规则,比如"你要扮演什么样的角色"、"按什么流程检查";另一部分是具体的技术要点,比如"注意空指针问题"、"检查React用法是否正确"等。有了这个清单,AI 就能像有经验的程序员一样,系统地检查代码,发现各种潜在问题,让代码质量得到保障。

具体这个规则体系的结构如下:

.cursor/rules
├── 00-role-and-constraints.mdc          # 角色与约束 - 定义AI代码审查助手的角色和基本约束条件
├── 01-workflow-steps.mdc                # 工作流程步骤 - 描述代码审查的工作流程和步骤
├── 02-detection-standards.mdc           # 检测标准 - 定义代码问题的检测标准和准则
├── 03-output-format.mdc                 # 输出格式 - 规定代码审查结果的输出格式和规范
├── 04-best-practices.mdc                # 最佳实践 - 提供代码审查中的最佳实践建议
├── common                               # 通用规则目录 - 包含各种常见的代码问题检测规则
│   ├── 01-null-pointer-defense.md       # 空指针防御 - 防止空指针异常的最佳实践
│   ├── 02-react-hooks-usage.md          # React Hooks 使用 - React Hooks 的正确使用方式
│   ├── 03-data-merge-state.md           # 数据合并状态 - 处理数据合并时的状态管理问题
│   ├── 04-async-programming.md          # 异步编程 - 异步编程模式和常见陷阱
│   ├── 05-memory-leak-performance.md    # 内存泄漏性能 - 检测和防止内存泄漏问题
│   ├── 06-security-coding.md            # 安全编码 - 安全编程实践和漏洞防范
│   ├── 07-compatibility.md              # 兼容性 - 确保代码兼容性的检查点
│   ├── 08-git-conflict-detection.md     # Git 冲突检测 - 检测并解决 Git 合并冲突
│   ├── 09-code-quality.md               # 代码质量 - 代码质量评估和改进规则
│   ├── 10-resource-handling.md          # 资源处理 - 正确处理系统资源的规则
│   ├── 11-url-params.md                 # URL 参数 - URL 参数处理的安全和有效性检查
│   ├── 12-business-logic-consistency.md # 业务逻辑一致性 - 确保业务逻辑一致性的规则
│   └── 13-monorepo-dependency.md        # 大仓依赖 - Monorepo 架构中的依赖管理规则
└── README.md                            # 说明文档 - 规则系统的介绍和使用说明

八、模型选择

在 AI CR 环节,模型的选择需要考虑模型对于代码理解的复杂性、上下文长度需求以及推理准确性、模型的速度、模型的使用成本等考量。在 Cursor 的模型列表中,我们优先使用 Compose 1.5,当额度不足时,我们也会降级使用 Auto 模型。

以下为 Cursor auto 模型与 Composer 1.5 模型对比,可以看出,两个模型都找出了 4 个问题,但在时间上,Composer 1.5 进行需 44 秒即可完成,而 auto 模型需要 91 秒。

九、总结与规划

通过多个迭代实践与数据统计,Cursor Agent CR 挖掘的有效问题数可以达到 50% 左右,研发使用的意愿也相比原来有不少提升。当前我们也在将 AI CR 报告融合到 Cursor IDE 插件中,进一步融合到研发流程里。

随着 AI 生成代码在开发流程中越来越普遍,AI CR 的重要性将进一步凸显。相比传统的人工审查,AI 审查能够自动发现 AI 生成代码中可能存在的逻辑错误、安全性问题和规范性缺陷,提前在开发过程中消除隐患。同时,AI CR 还能确保 AI 生成的代码符合团队的技术规范和最佳实践,保持代码风格的一致性。为 AI 时代的开发流程提供了可靠的质保机制,让开发流程更加顺畅,是现代软件开发的重要保障。

往期回顾

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

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

3.搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术

4.得物社区搜推公式融合调参框架-加乘树3.0实战

5.深入剖析Spark UI界面:参数与界面详解|得物技术

文 /大圣

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

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

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

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

一、概述

做后端开发,调 BUG 有一个让人头疼的固定流程:打开日志平台,输入 traceId 或关键词,搜日志;从几十上百条日志里,找到关键的那几条;把日志里的类名、方法名复制出来,去 IDE 里找对应代码;结合代码逻辑,判断哪里出了问题;如果一次找不准,回去再搜日志,再翻代码……

这个过程相对固定,但非常耗时间。每次 BUG 定位,光在日志平台和 IDE 之间来回切换,就能消耗掉大半的时间。

最开始在去年 Q3 想到这个问题的时候,脑子里浮现的第一个方案是:用 Cursor + MCP,把日志平台接进来,再挂一个代码知识库,让 AI 帮我查日志。但这个方案有缺陷 —— 日志查询是「动态的」,它依赖环境、应用、时间范围,没办法静态预置。此外,这样处理没有办法做到比较丝滑地读代码、改代码。

后来开始用 Claude Code,接触到了 Skill 的概念:可以在项目里定义一套自定义命令,描述 AI 应该怎么执行这个命令的每个步骤,于是整个思路变得清晰了。

日志平台有 MCP,Claude Code 有 Skill,两者结合,就能让 AI 自动完成「查日志 → 找关键信息 → 扫描代码 → 定位问题」这整个闭环。然后在 PM 的帮助下,才有了 /log-diagnosis 这个 Skill。

二、日志平台 MCP 是什么

MCP 原理

日志平台推出了基于 MCP(Model Context Protocol)协议的日志查询服务,让 Claude 可以直接调用日志平台的能力,无需人工在日志平台上手动查询。

MCP 本质上是一种标准化的「工具调用协议」,Claude Code 通过 SSE(Server-Sent Events)长连接与 MCP Server 通信,实时获取日志数据。

MCP 环境对照

核心 MCP 工具

鉴权流程

secretKey(日志平台后管申请)
    ↓ acquireTokenTool
accessToken(1小时有效,最多同时存在5个)
    ↓ 携带 accessToken
logsQuery / logSqlQuery / countLogTool ...

secretKey 申请地址:进入日志管理后台 → 日志权限 → 我的应用 → 生成密钥。

三、/log-diagnosis Skill 是什么

Skill 工作原理

log-diagnosis 是一个运行在 Claude Code 里的自定义诊断命令。Claude Code 支持通过 .claude/skills/ 目录定义自定义技能(Skill),以 Markdown 文件描述行为规范,Claude 在收到对应命令时会自动加载并执行。你只需要把 traceId 或告警信息告诉它,剩下的全部交给 AI。完整执行链路如下:

用户输入 /log-diagnosis {环境} {代码分支} {诉求}
    ↓
Claude 加载 .claude/skills/log-diagnosis/SKILL.md
    ↓
读取 .diagnosis/config.json 获取当前环境配置
    ↓
检查 accessToken 是否过期,过期则自动刷新
    ↓
从 traceId 计算日志时间范围(取第9-16位16进制时间戳)
    ↓
调用日志平台 MCP 分页拉取全量日志(最多20页,不遗漏)
    ↓
切换到指定代码分支,结合日志关键词检索代码
    ↓
综合分析:上游日志 + 当前服务日志 + 代码逻辑 → 根因
    ↓
生成诊断报告(飞书文档 or 本地 Markdown)
    ↓
恢复原始代码分支

两种诊断入口

核心能力

  • Token 自动管理:accessToken 过期自动刷新,无需手动维护;
  • 分页全量拉取:自动分页拉完所有日志,禁止只查第一页就下结论(最多 20 页);
  • 跨服务分析:自动识别上下游服务,拉取关联服务日志交叉验证;
  • 代码联动:日志里出现的类名/方法名,直接在代码里精确定位。

queryString 语法规则

# 格式
{field} {操作符} "{值}" {连接符} {field} {操作符} "{值}"
# 操作符
=  : 精确匹配
≈  : 模糊匹配(like)
# 连接符
AND / OR / NOT
# 示例
trace_id"a1b2c3d4e5f6789012345678abcdef01"
trace_id"xxx" AND log_level = "ERROR"
endpoint ≈ "/api/your-endpoint" AND log_level"ERROR"
message ≈ "timeout"

注意:时间范围只通过 start/end 参数控制,不要写在 queryString 中。

四、安装与配置

安装日志平台 MCP

Claude Code

在 Claude Code 命令行中执行,按需安装对应环境:

# 测试环境
claude mcp add --transport sse dw-log-mcp-t1 https://{your-t1-aigw-domain}/api/v1/mcp/log-mcp/sse
# 预发环境
claude mcp add --transport sse dw-log-mcp-pre https://{your-pre-aigw-domain}/api/v1/mcp/log-mcp/sse
# 生产环境
claude mcp add --transport sse dw-log-mcp-prd https://{your-prd-aigw-domain}/api/v1/mcp/log-mcp/sse

安装后重启 Claude Code,执行 /mcp 确认连接状态正常。

Cursor

  1. 打开 Cursor Setting;

  2. 点击 Tools & MCP,添加 MCP Server;

  3. 添加 URL,MCP Server 名称任意。

建议按需安装 MCP Server,避免额外消耗 token,示例配置:

{
  "mcpServers": {
    "dw-log-mcp-t1": {
      "url": "https://{your-t1-aigw-domain}/api/v1/mcp/log-mcp/sse"
    },
    "dw-log-mcp-pre": {
      "url": "https://{your-pre-aigw-domain}/api/v1/mcp/log-mcp/sse"
    },
    "dw-log-mcp-prd": {
      "url": "https://{your-prd-aigw-domain}/api/v1/mcp/log-mcp/sse"
    },
    "dw-log-mcp-oversea-prd": {
      "url": "https://{your-oversea-aigw-domain}/api/v1/mcp/log-mcp/sse"
    }
  }
}

4. 返回设置,就可以看到已经连接上。

安装 /log-diagnosis Skill

将 log-diagnosis 目录放到项目的对应目录下:

Claude Code

your-project/
└── .claude/
    └── skills/
        └── log-diagnosis/
            ├── SKILL.md        # 技能行为规范(核心)
            ├── README.md       # 使用说明
            └── reference.md   # 附录:时间脚本、queryString 示例等

Cursor

your-project/
└── .cursor/
    └── skills/
        └── log-diagnosis/
            ├── SKILL.md        # 技能行为规范(核心)
            ├── README.md       # 使用说明
            └── reference.md   # 附录:时间脚本、queryString 示例等

配置 .diagnosis/config.json

首次运行会自动引导创建 (直接调用 /log-diagnosis,Skill 会一步步指示你给出 secret key),也可手动在项目根目录创建 .diagnosis/config.json:

your-project/
└── .cursor/
    └── skills/
        └── log-diagnosis/
            ├── SKILL.md        # 技能行为规范(核心)
            ├── README.md       # 使用说明
            └── reference.md   # 附录:时间脚本、queryString 示例等

字段说明:

secretKey:唯一需要人工填写的字段,在日志平台后管申请;

accessToken:首次使用时由 AI 自动调用 acquireTokenTool 获取,过期自动刷新;

accessTokenExpireAt:从 acquireTokenTool 返回值自动填充;

fields:调用 logFields 工具自动获取。

五、使用方式

命令格式:

/log-diagnosis {环境} {代码分支(可选)} {诉求描述}

参数说明:

  • {环境}:T1 / PRE / PRD(按实际环境标识填写);
  • {代码分支}:可选,留空则使用当前分支;
  • {诉求描述}:包含 traceId 或告警信息的问题描述,用自然语言书写即可。

示例:

# 用 traceId 定位接口异常
/log-diagnosis T1 feature/your-branch trace_id: "your-trace" 为什么最终没有返回数据
# 用告警信息分析错误原因
/log-diagnosis PRD master 告警详情:【接口:YourService/yourMethod】【业务码:10002000】【业务码消息:系统异常,请稍后重试】帮我分析问题可能性

一行命令,AI 全程接管,几分钟内给出根因分析。

六、实战案例:一个隐蔽的 SQL BUG

背景

某搜索接口在测试环境反馈没有返回数据。拿到 traceId,直接执行:

/log-diagnosis T1 feature/your-branch trace_id: "your-trace" 为什么最终没有返回数据

← 就这一句话,接下来全部交给 AI。

AI 自动拉取日志

Skill 触发后,AI 自动完成:

  • 从 traceId 推算出日志时间范围(2026-02-27 全天);
  • 检查 accessToken 已过期,自动刷新;
  • 调用日志平台 MCP,分 2 页拉取完整日志,共 73 条。

请求入参(从日志自动提取):

{
  "assembleByOrg": true,
  "channelType": "MANUAL",
  "orderNo": "your-order-no",
  "status": 1,
  "ticketNo": "your-ticket-no"
}

AI 还原完整调用链路

AI 自动识别出关键节点:resultList is empty,SQL 查询返回了空结果。问题在 DB 层,而不在业务逻辑层。

AI 提取组装后的查询 DTO

从日志中提取到 toSearchDTO 组装结果:

{
  "channelType": "MANUAL",
  "customerTag": 1,
  "deliveryMode": "某配送方式",
  "orderStatus": "8010",
  "orderType": "0",
  "productCategoryIds": [29],
  "status": 1,
  "ticketSource": 67,
  "ticketTypeId": 5802
}

AI 从日志中提取实际执行的 SQL 发现根因

ORM 框架在日志中打印了实际执行的 SQL,AI 直接读取并分析:

SELECT a.id, a.pid, a.name, a.mode, a.status, a.org_id, a.org_ids,
       a.ticket_group_id, a.tenant_id, a.is_del, a.channel_types
FROM your_type_table a
LEFT JOIN your_relation_table b
    ON b.tenant_id = 1 AND a.id = b.type_id AND b.type = 3 AND b.is_del = 0
WHERE a.tenant_id = 1 AND a.mode = 2 AND a.is_del = 0
  AND a.status = 1
  AND (a.channel_types IS NULL OR a.channel_types = '' OR FIND_IN_SET('MANUAL', a.channel_types) > 0)
  AND (b.root_id is null or b.root_id in (29))
  AND (a.order_types IS NULL OR a.order_types = '' OR FIND_IN_SET('0', a.order_types) > 0)
  AND (a.order_statuses IS NULL OR a.order_statuses = '' OR FIND_IN_SET('8010', a.order_statuses) > 0)
  AND (a.delivery_modes IS NULL OR a.delivery_modes = '' OR FIND_IN_SET('某配送方式', a.delivery_modes) > 0)
  AND (a.ticket_sources IS NULL OR a.ticket_sources = '' OR FIND_IN_SET(67, a.ticket_sources) > 0)
  AND (a.customer_tag IS NULL OR a.customer_tag = 1)   ← BUG 在此

AI 发现:其他字段都处理了 IS NULL 和 = ''(空字符串代表 “不限制”)两种情况,唯独 customer_tag 只判断了 IS NULL,遗漏了空字符串 '' 的情况。

SQL 语义对比:

-- 其他字段(正确):IS NULL 和 '' 都处理了
AND (a.order_types IS NULL OR a.order_types'' OR FIND_IN_SET('0', a.order_types) > 0)
AND (a.delivery_modes IS NULL OR a.delivery_modes'' OR FIND_IN_SET('某配送方式', a.delivery_modes) > 0)
AND (a.ticket_sources IS NULL OR a.ticket_sources'' OR FIND_IN_SET(67, a.ticket_sources) > 0)
-- customer_tag(遗漏了 = '' 的判断)← BUG
AND (a.customer_tag IS NULL OR a.customer_tag1)

DB 中现有的数据,customer_tag 字段都存的是空字符串(未配置),按业务语义本应匹配所有请求,却因为这个遗漏被全部过滤掉了。

AI 定位代码,给出修复方案

AI 在代码中直接找到对应的 MyBatis Mapper XML:

<!-- 问题代码 -->
<if test="customerTag != null">
    and (a.customer_tag IS NULL OR a.customer_tag = #{customerTag})
</if>
<!-- 修复后 -->
<if test="customerTag != null">
    and (a.customer_tag IS NULL OR a.customer_tag = '' OR a.customer_tag = #{customerTag})
</if>

效率对比

这个 BUG 的隐蔽性在于:SQL 语法正确,逻辑上也「看起来」没问题——只有对比了其他字段的写法,才能发现 customer_tag 独自遗漏了空字符串的处理。这类细节差异,人工排查很容易忽略,AI 反而很擅长。

七、诊断效率关键点

  • 有 traceId 时优先用 traceId 拉日志,可精准获取单次请求的完整链路,比关键词搜索精确得多;
  • 关注关键日志节点:toSearchDTO finished / search begins / resultList is empty / search finished 等,快速判断数据在哪一层丢失;
  • SQL 打印日志(ORM 框架输出)是黄金线索,直接反映最终执行的查询条件,AI 能从中发现肉眼难以察觉的差异;
  • 分页必须拉完:日志平台一次只返回部分数据,AI 会严格执行分页直到取完,确保不遗漏关键日志。

八、总结

核心思路:用「协议 + 规范」让 AI 接管固定流程:

这篇文章的本质,是一次对重复性工程劳动的自动化尝试。调 BUG 的过程——查日志、提取关键信息、找代码、分析原因——逻辑固定,步骤繁琐,但并不需要太多创造性思维。这类工作恰好是 AI 最擅长接管的。

实现这个闭环,靠的是两个关键组合:

  • MCP:让 AI 能够调用外部系统(日志平台),突破了「AI 只能处理静态上下文」的限制,实现了对动态数据的实时获取。
  • Skill:给 AI 一份行为规范,告诉它每一步该怎么做、先做什么后做什么、遇到什么情况怎么处理,把「一次性对话」变成「可复用的工程化能力」。

两者缺一不可。只有 MCP,AI 能查日志但不知道怎么系统地分析;只有 Skill,AI 有流程但没有数据来源。组合起来,才形成了真正可落地的闭环。

值得借鉴的地方:

识别「固定流程」是自动化的起点:不是所有工作都适合 AI 接管,但凡是「步骤固定、信息来源明确、输出格式可预期」的工作,都值得尝试用 Skill + MCP 的方式来自动化。排查 BUG 是一个典型,类似的还有:代码审查、性能分析报告生成、告警巡检等。

Skill 的本质是「给 AI 写操作手册」:Skill 文件不是在「训练模型」,而是在给 AI 一份清晰的 SOP。写得越细、约束越明确(比如「禁止只查第一页就下结论」「必须分页拉完所有数据」),AI 的执行质量越稳定。这和写给人看的文档本质上是一回事。

AI 擅长发现「横向对比」类的 BUG:本文的案例揭示了一个有意思的规律:AI 在处理「同类字段逻辑不一致」这类问题时,表现往往比人工更好。原因在于 AI 没有「先入为主」的经验偏见,不会因为「这段代码看起来没问题」就跳过,它会对所有字段做同等的审查。

最后说一句:AI 时代,工程师的核心竞争力不只是「能写代码」,更是「能把自己的经验和流程转化成可复用的 AI 能力」。/log-diagnosis 是一次小小的尝试,但背后的思路,值得在更多场景里延伸。

往期回顾

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

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

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

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

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

文 /阿程

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

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

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

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

一、背景介绍

随着业务规模与流量的持续高速增长,自建 Redis 集群面临着更高地性能与稳定性要求,对平台化、自动化运维能力也提出了新的挑战。为进一步提升资源利用效率、保障服务稳定运行,并更好地支撑业务快速发展,我们对 Redis 平台进行了自动化能力的建设与升级,通过系统化的平台能力优化,降低人工运维费力度,提升整体运维效率与服务质量。

Redis 使用现状

Redis 集群目前基于 ECS 进行部署,采用单机多实例、主从混合部署的架构模式,并将 Proxy 组件与数据节点混合部署,以提升 CPU 资源利用率与整体部署密度。当前集群已达到百 TB 级存储规模、数十万数据节点,支撑超大规模业务场景的稳定运行。

面临的挑战和问题

随着业务规模与流量的持续增长,平台在资源效能与运维效率方面面临着新的优化空间:资源池层面机器资源池的整体利用率仍有提升空间,需进一步优化资源调度与负载均衡策略。运维自动化层面告警自动化处理覆盖度有待提升,部分复杂运维场景仍需人工介入,流程效率可进一步优化。

集群架构

自建 Redis 由 ConfigServer、Redis-Proxy、Redis-Server 等核心组件构成。

自建 Redis 2.0(SDK标准版) 整体架构图如下所示:

一主一从,双区部署

ConfigServer

ConfigServer 是自建 Redis 系统中关键组件之一,跨多可用区多节点部署,采用 raft 协议实现 ConfigServer 组件高可用;ConfigServer 主要负责两方面职责:

  • 负责 Proxy 添加与删除、group 创建与删除、Redis-server 实例添加与删除、Redis-server 实例手动主从切换、水平扩容与数据迁移等功能操作。
  • 负责 Redis-server 实例故障检测与自动故障转移(主节点故障后自动主从切换)。

Redis-Proxy

Redis-Proxy 组件是自建 Redis 系统中的代理服务,负责接受客户端连接,然后转发客户端命令到后端相应的 Redis-server 实例,使得后端 Redis-server 集群部署架构对业务透明,Proxy 支持 Redis RESP 协议,业务访问 Proxy 就像访问一个单点 Redis 服务一样,业务可以把一个自建 Redis 集群当作一个容量无限大的单点 Redis 实例即可。

Redis-Server(Redis-Group)

Redis-server 组件为开源 Redis 版本基础上,增加槽 slot 同步迁移与异步迁移等相关功能;支持原生开源 Redis 的所有特性,比如支持 String、Hash、List、Set、ZSet 等常用数据结构,AOF 持久化、主从复制、Lua脚本等等。默认一主一从,可支持多从部署。

二、自动化运维能力

自动化运维

资源池自动化均衡调度

当前 Redis 资源池支持按内存使用率自动化均衡调度、按内存分配率自动化均衡调度、按 CPU 使用率均衡调度、支持指定机器凌晨迁移调度(隐患机器提前维护、凌晨资源池迁移优化下线等)等功能,核心流程为合理选择迁移节点。现在每天定时生成迁移计划,迁移任务默认每天凌晨定时执行。

资源池均衡任务管理

迁移 server 节点选择算法流程图

Redis 潮汐调度算法示意

选择 Server 节点原则

  1. 机器选择:
  2. 获取内存容量使用率超过指定百分比的机器。
  3. 获取分配率超过指定百分比的机器。
  4. 获取需要维护和迁移优化的机器。
  5. 优先节点数量多的实例节点:这样可以在资源均衡的同时,使得同一集群节点也更均衡,同一集群节点尽可能分散到不同的机器上。
  6. 优先实例等级为非 P0 的实例。
  7. 优先从节点:从节点迁移对大部分业务都没有任何影响。
  8. 分配率和内存容量一样,优先节点规格中等规格(1-4G)实例,再选择 1G-5G 规格实例,最后选择其他规格的节点。
  9. 最后汇总迁移任务节点:
  10. 优先处理需要维护和需要迁移优化的节点。
  11. 去掉同一个集群同一个分组的 master 节点,避免对同一 group 分组进行操作。
  12. 对于需要维护和迁移优化的机器上的 proxy:
  13. 获取原来 proxy 版本,资源标签等信息,判断是否是特殊作用 proxy,部署新 proxy。
  14. 调整旧 proxy:对于 sdk proxy 禁用 proxy,对于 slb 下 proxy,调整权重。

选择 server 迁移任务流程图

  • 节点选择后生成迁移任务,前端可展示、确认、取消;
  • 定时任务执行生成的迁移任务;
  • 添加从节点、同步数据;
  • 同步数据完成后如果迁移节点是从则删除节点;
  • 同步数据完成后如果迁移节点是主则进行主从切换;
  • 如果迁移节点是主进行主从切换后检查新主从关系,检查 proxy 拓扑更新等,如果有异常则告警迁移。

迁移 proxy 节点选择算法流程图

proxy 节点选择流程图

选择 Proxy 节点原则

  1. 优先机器 CPU 负载峰值高的机器上 Proxy 节点;均衡调度阈值支持可配置,后续均衡后继续调整。
  2. 需要先采集到 proxy 24 小时 CPU 峰值,排序后优先迁移机器上 CPU 峰值最高的,直到机器 CPU 峰值降到均衡调度阈值。
  3. 每台机器每天只迁移 1 个 proxy。
  4. 判断 proxy CPU 峰值高的个数(如果只有一个就不处理,如果大于等于 3 个 proxy CPU 峰值高则处理一个(超过配置的均衡调度阈值算高 CPU 使用率))。

Proxy 迁移任务流程图:

  • 节点选择后生成迁移任务,前端可展示、确认、取消;
  • 定时任务执行生成的迁移任务;
  • 获取原来 proxy 版本,资源标签等信息,判断是否是特殊作用 proxy,部署新 proxy;
  • 新 proxy 绑定 LB;
  • 调整旧 proxy:对于 sdk proxy 禁用 proxy,对于 slb 下 proxy,调整权重。

收益

  • 提升资源池内存与 CPU 利用率,优化整体资源使用效率。
  • 合理管控资源超卖率,降低自动扩容失败率与告警发生率。
  • 基于机器维护窗口,在凌晨低峰期执行调度与实例迁移,高效支撑隐患机器前置治理、资源池离线优化及节点下线等运维需求。

资源池分级维护和管理

对 ECS 机器资源和 LB 资源进行打标,根据特殊业务需要做不同资源池的隔离调度。

可对资源进行多维度筛选:比如按资源标签、CPU、可用区、是否重保等维度筛选。

可对机器上部署的节点信息进行迁移操作和查看机器详细监控等。

物理资源隔离:自建 Redis 通过对 ECS 机器资源打标,实现重保集群隔离,支持集群物理隔离,减少集群相互影响,支持资源分级维护和灰度测试验证,减少大面积变更影响,使用相对保守的资源水位阈值来减少重保集群的运维频次和任务调度。

Redis 资源池隔离方案示意

不同资源池资源阈值项设置:

资源池分配阈值

集群生命周期自动化管理

集群自动化部署

当前 Redis 支持自动化集群部署,集群交付时间缩短至分钟级。

当业务提交集群申请工单审批通过后,判断是否支持自建,如符合自建则自动化进行集群部署和部署结果校验,校验集群可用性后自动给业务交付集群信息,整个过程高效快速。集群部署成功或者失败都会发送消息通知。

部署结果成功通知

部署结果失败通知

集群垂直扩缩容自动化

当前 Redis 支持 server 垂直扩缩容,ecs-proxy、docker-proxy 扩容等工单自动化操作。

扩容方案

集群 server 垂直扩缩容,ecs-proxy、docker-proxy 扩容等场景在业务提单时给出扩缩容方案和校验,实现工单自动化操作。

集群水平扩缩容自动化

当前 Redis 支持 server 自动扩容分片,以支持更高的请求和负载。

Server 水平扩缩容任务管理

水平扩缩容执行任务详情

集群下线支持回收和重建

当前 Redis下线回收,支持立即销毁和重建恢复。

集群自动下线流程

  • 工单审批通过后立即下线接入层:检测 proxy(ecs-proxy 和 docker-proxy)连接和 qps 请求,都没有则调整权重,下线接入层(ecs-proxy 和 docker-proxy)。
  • 7 天内如有反馈问题,需要继续访问,则重建恢复集群正常访问。
  • 7 天后无反馈下线集群所有资源(包括数据层数据,这里下线后不再支持回收重建)。

集群回收站管理

大 key 删除支持产品化可回滚

支持自建 Redis 和云 Redis 多 db 大 key 删除可回滚。支持控制台大 key 删除任务管理(立即执行删除、定时删除、回滚等)。

进行中的任务

历史删除任务

版本升级自动化

  • 对有需要的集群支持将指定集群在指定时间进行滚动升级到指定版本。
  • 自动化版本升级收敛,通过自动化任务在凌晨低峰期进行同版型系列滚动升级。
  • 支持升级任务管理、修改时间、查看任务详情、升级进度,取消任务等。

版本升级任务

版本升级记录

工单自动化

当前所有运维工单都已完成工单自动化,如 Biz 申请、创建实例、密码申请、权限申请、实例升降配、实例架构升级、Server 版本升级、Server 水平扩容、删除 key、下线实例等均完成工单自动化。业务提单审批通过后自动校验执行,执行完成后自动发送工单执行结果通知。

总结:除了需求描述性(云 Redis 需求)的工单,其他均实现操作工单化标准化,工单自动化。

查询自动化

集群控制台支持命令查询、Key 模糊查询、Key 随机采样等,查询结果也支持 json 格式化、复制等功能。

支持查询历史缓存,查询耗时记录等。

告警自动化处理

告警入库收敛优化

  • 告警触发后收敛至集群维度入库;
  • 判断告警是否沉默中:如内存容量告警,部分特殊集群可以写满按淘汰策略淘汰,不用扩容,这种告警需要沉默;
  • 判断告警是否超频:因为集群分片很多,同一集群同一指标不同分片每次触发阈值都会触发告警;
  • 将告警信息按集群所属发送到对应的业务域:同一集群可能存在多个业务方使用,根据业务域纬度增加业务域大群告警通知,提高告警业务感知能力。

Server 分片内存容量告警自动扩容

自建 Redis 支持业务配置自动扩容,当集群容量超过预警水位线 80% 时,可自动进行垂直扩容,不需要人工介入运维,对业务无感,自动扩容在夜间无人值守的场景下,大大降低了集群容量激增带来的风险。

Redis 自动扩容开关

Server 自动扩容流程图:

Redis 自动扩容流程图

  • 管控周期性任务获取监控平台 Redis 内存使用率超过 80% 的监控信息。
  • 节点告警信息收敛到集群维度处理。
  • 判断集群是否开启自动扩容:集群申请时会让业务填是否开启自动扩容,页面也可配置开启或者关闭自动扩容。
  • 判断节点是否超过集群设置的 80% 扩容阈值。
  • 判断最近一天是否扩容次数大于 3 次:如果 24 小时内扩容多次,说明可能增长异常,需要让告警发出。
  • 判断扩容后容量是否大于设置的最大阈值(8G):这里单个节点最大值为 8G,方便维护。
  • 预检查扩容后分配是否大于机器内存:自动扩容后分配容量不能大于机器容量。如果大于机器容量则记录扩容失败信息,如果小于则可执行扩容操作,扩容操作后再持久化参数到 Redis 配置文件,然后记录节点扩容成功。

宕机场景告警收敛与自动化处理

机器维度的告警收敛,减少告警。

  • 订阅机器宕机事件入库;
  • Redis server 和 proxy Down 告警信息入库;
  • Redis server 和 proxy Down 告警触发后判断所属机器是否有宕机事件;
  • 如果告警所属机器没有机器宕机事件,则直接发送电话告警和飞书告警消息通知;
  • 如果告警所属机器有机器宕机事件,则判断告警时间是否超过 5 分钟,如果 5 分钟后告警还没恢复则当前节点自动拉起失败,发送电话告警和飞书告警消息通知。如果节点自动拉起成功,则不会再触发告警。

宕机节点自动重启流程图:

针对夜间 Redis 实例机器宕机,引入自动化巡检和自动重启机制,减少夜间运维成本,提高夜间故障集群主备完整性恢复效率。

Redis 宕机自动恢复示意图

  • 订阅机器宕机事件入库;
  • 周期性任务查询宕机信息;
  • 机器宕机加入事件队列,判断是否事件重复,重复则不加;
  • 重启宕机上的节点,如果返回失败加入事件队列,支持重试 3 次;
  • 发送重启结果消息通知。

收益

  • 将告警信息按集群所属发送到对应的业务域,降低了告警后不断找人拉群的运维工作量。告警自动实时同步给业务,提高了业务告警实时性和告警感知能力。
  • 通过告警入库收敛优化、宕机场景告警收敛优化和告警自动化处理,降低告警噪音 90% 以上。
  • 通过 Server 分片内存容量告警自动扩容、机器宕机节点自动重启,极大降低运维成本和提高告警恢复效率。

自动化巡检推送

黑名单管理

对集群大 key、集群热 key、集群混用情况、集群成本等进行巡检,针对特殊场景的 key 支持集群维度、key 维度和 key 前缀维度的黑名单配置。

黑名单管理

大 key 巡检日报

每日按业务域维度巡检集群存量大key,推送巡检信息到对应业务域大群,大 key 巡检支持黑名单管理。点击实例 ID 可跳转查看 key 分析详情。

大 key 巡检日报

key 分析详情

热 key 巡检

实时将集群热 key 信息,推送巡检信息到对应业务域大群,热 key 支持黑名单设置。

集群热 key 实时巡检

实时热 key 分析

三、总结

通过持续构建与完善平台自动化运维体系,我们实现了 Redis 集群全生命周期运维的规范化、标准化与自动化,覆盖集群部署、垂直扩缩容、分片水平扩容、版本升级、集群生命周期管理、资源池多维度智能调度、自动化告警处理及常态化巡检等核心场景。整体运维流程实现少人化、无人化执行,大幅降低运维复杂度和人工运维费力度。依托运维工单化、流程自动化的建设思路,平台整体运维效率得到显著提升,为 Redis 服务长期高稳定、高可靠、高性能运行提供了坚实保障。

往期回顾

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

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

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

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

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

文 /陌叶

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

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

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

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

随着以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 项目实战|得物技术

文 /博温

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

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

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

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

一、破局:AI 编码的真正瓶颈不是模型,是上下文管理

在软件开发的历史进程中,每一次效率的飞跃都伴随着抽象层次的提升。从汇编语言到高级语言,从手动内存管理到垃圾回收,开发者始终在寻求降低认知负荷的方法。进入 2026 年,生成式人工智能(GenAI)已成为编程领域不可或缺的力量。 然而,行业正经历从 “模型崇拜” 向 “工程落地” 的深刻转型,单纯依靠增加大语言模型(LLM)的参数规模已无法解决复杂业务逻辑中的幻觉与失控问题。

当前的共识是,AI 编码(AICoding)的真正瓶颈不在于模型的逻辑能力,而在于上下文管理(Context Management)的失效与开发意图(Intent)的模糊。

通过对 Anthropic 推出的 Claude Code(以下简称 CC)与 Fission AI 倡导的 OpenSpec 进行深度解构可以发现,两者正在通过 “代理化执行” 与 “规格化驱动” 双轮驱动,构建一套闭环的 AI 研发体系。这种结合不仅标志着 AI 编程工具从 IDE 插件向终端原生代理(Agentic Tool)的转变,更预示着 “规格驱动开发”(Spec-Driven Development, SDD)将成为企业级 AICoding 落地的核心范式。

在 AICoding 的早期阶段,开发者普遍认为只要模型足够强大,就能解决所有编程难题。然而,随着项目复杂度的增加,这种观点遭到了现实的挑战。研究表明,虽然 AI 编码助手的使用率在提升,但软件交付的稳定性却在下降。例如,Google 的 DORA 2024 报告指出,AI 采用率每增加 25%,交付稳定性反而下降 7.2%。

生产力悖论与认知负荷

AICoding 领域存在一个显著的 “生产力悖论”:开发者在使用 AI 时主观感知速度提升了 20%,但实际完成任务的时间却增加了 19%。这一现象的根源在于 AI 在处理长上下文时的效能衰减。随着任务推移,AI 往往会陷入修正循环(Fix/Test Loops),无法触及深层的业务功能,反而需要更多的人工干预。

模型的逻辑推理能力(Reasoning)在短小上下文中表现卓越,但在大型工程环境中,模型面临的是 “上下文中毒”(Context Poisoning)和 “注意力漂移”(Attention Drift)。当对话历史过长或包含过多无关代码时,模型的性能会呈现非线性下降。例如,GPT-4o 等先进模型在 1K Token 时的准确率为 99.3%,而当上下文扩展到 32K Token 时,准确率会暴跌至 69.7%。这种 “性能断崖” 意味着,单纯依靠扩大上下文窗口(Context Window)并不能解决问题。

上下文工程的兴起

上下文工程(Context Engineering)正在取代提示词工程(Prompt Engineering),成为 AICoding 的核心技术方案。上下文工程的核心不在于 “如何写更好的指令”,而在于 “如何为模型筛选最精准的 Token 集合”。

下表对比了传统缩放路径与上下文工程路径的局限性:

在大型组织中,上下文管理面临更严峻的挑战。很多关键决策并未记录在代码中,而是散落在飞书文档评论、群消息、会议或开发者的认知中。AI 代理在缺乏这些隐性知识(Implicit Knowledge)的情况下,生成的方案虽然符合语法,但却违背了架构初衷或业务约束。

上下文作为一等系统

现代 AI 代理架构开始将上下文视为一种具有自身架构、生命周期和约束的 “一等系统”。在这种视角下,上下文管理不再是临时的字符串拼接,而是一条精密的 “编译器管道”:

  • 存储与呈现分离: 区分持久化的会话状态(Session)与单次模型调用的工作上下文(Working Context)。
  • 显式转换: 通过命名的、有序的处理器(Processors)构建上下文,而非随机堆砌。
  • 默认作用域: 每个子代理仅能看到执行任务所需的最小上下文,通过工具(Tools)按需获取更多信息。

二、Claude Code:把 AI 变成真正懂你项目的编码伙伴

Claude Code (CC) 是 Anthropic 推出的原生代理工具,它直接运行在终端中,具备读取文件、运行命令、执行重构以及自主验证的能力。与传统的 IDE 插件相比,CC 的核心优势在于其“代理循环”(Agentic Loop)和对上下文协议的深度掌控。

代理循环:收集、行动与验证

CC 的工作流程被定义为一个闭环系统,旨在模仿人类工程师的思维过程:

  • Gather Context(收集上下文): CC 不会盲目读取整个目录,而是通过文件搜索、Git 状态检查以及读取特定的 CLAUDE.md 文件来建立认知。
  • Take Action(采取行动): 基于推理,CC 可以跨多个文件执行编辑,或者利用终端工具(如 npm install、git commit)操作环境。
  • Verify Results(验证结果): 这是 CC 最具杀伤力的特性。它能自动运行测试、捕捉错误,并根据反馈调整方案。研究表明,带有验证步骤的 Coding 生成过程,其成功率远高于单次生成。

终端原生的工程哲学

CC 选择了终端而非图形界面作为主场,这体现了其 “代理优先” 的设计哲学。CC 遵循 Unix 哲学,支持管道(Pipe)、脚本化和自动化集成。这种设计使得 CC 能够与现有的 CI/CD 流程完美衔接,例如在 GitHub Actions 中自动执行代码审计。Anthropic 最新推出的 Code Review 功能,就是通过 Claude Code 基于 PR 的方式进行 bug 的追踪。

下表详细对比了 CC 与行业领先的 AI 编辑器 Cursor 的差异:

MCP 与“即时上下文”

CC 深度整合了模型上下文协议(Model Context Protocol, MCP)。MCP 是一个开放标准,允许 AI 代理安全地访问外部数据源。

为了应对大规模工具定义导致的上下文溢出,CC 引入了 “工具搜索” 和 “代码执行” 模式。代理不再一次性加载成千上万个 API 定义,而是通过编写代码按需调用 MCP 服务。例如,在分析大型数据库时,CC 不会加载全量数据,而是编写针对性的查询语句,仅将结果摘要读入上下文。这种 “按需加载” 策略极大地提升了 Token 的效用。

CLAUDE.md 与自动记忆

CC 引入了 CLAUDE.md 文件作为项目的 “操作手册”。这是一个置于根目录的 Markdown 文件,用于存储项目特定的编码标准、架构决策和测试指令。与临时提示词不同,CLAUDE.md 提供了持久的、跨会话的约束。

此外,CC 具备 “自动记忆”(Auto Memory)功能。它会自动在 MEMORY.md 中记录项目的构建命令、调试心得和用户的偏好设置。每当新会话启动时,CC 会加载这些记忆的前 200 行,从而确保 AI 在长期协作中能够 “越用越懂你”。

三、OpenSpec:给 AI 编码加上"规格书",从失控到可沉淀

虽然 Claude Code 提供了强大的执行引擎,但在复杂业务中,AI 仍然可能因为意图不明而跑偏,最终导致交付的代码不符合预期。

OpenSpec 的出现为 AI 编码提供了 “规格说明书”,将 AICoding 从 “凭感觉写代码” 提升到了 “按规格执行任务” 的高度。

规格驱动开发 (SDD) 的兴起

OpenSpec 倡导的是一种 “规格驱动开发”(Spec-Driven Development)范式。其核心理念是:在写任何一行代码之前,先由人类与 AI 共同协商并锁定一份机器可读、人可评审的规格文档。

下表展示了 SDD 的三个演进阶段:

OpenSpec 的工件体系 (Artifacts)

OpenSpec 弃用了笨重的开发文档,转而采用一套轻量级的、面向 AI 优化的 Markdown 工件体系。每个变更(Change)都被组织在独立的文件夹中:

  • proposal.md: 描述变更的初衷(Why)和范围(What)。
  • specs/: 具体的逻辑规格,通常包含 “Scenario(场景)” 描述,通过具体的输入输出消除模糊性。
  • design.md: 技术设计方案,包括本次变更涉及的数据库变更、接口调整等。
  • tasks.md: 原子化的任务清单,作为 AI 的执行路径图。

解决上下文污染:提案、应用与归档

OpenSpec 最具洞察力的设计在于其生命周期管理。AI 在处理新任务时,最忌讳被旧任务的陈旧信息干扰。OpenSpec 的 “归档(Archive)” 机制解决了这一问题:

  • Proposal 阶段: 建立一个独立的变更上下文,让 AI 只关注当前变更。
  • Apply 阶段: AI 严格按照 tasks.md 执行,避免了盲目扫描全库导致的 Token 浪费。
  • Archive 阶段: 任务完成后,临时变更文档被移入归档,核心规格更新至主规格文件。这保证了 AI 始终在一个 “卫生” 的上下文环境下工作,同时也为项目留下了可追溯的决策链路。

四 、实战:CC + OpenSpec 如何落地真实业务

在实际的企业业务场景中,如何整合这两大工具?答案在于将 OpenSpec 的标准化指令集注入到 Claude Code 的会话环境中。

案例实战:复杂业务逻辑的重构

假设一个电商项目需要重构其优惠券结算逻辑。在传统的 AI 辅助下,AI 可能会在修改 CouponService.java 时遗漏分布式锁,或者破坏原有的满减叠加规则。采用 CC + OpenSpec 模式,流程如下:

第一步:提案初始化

执行 /opsx:propose "重构优惠券结算逻辑,引入 Redis 分布式锁并支持多卷叠加"。CC 会在 openspec/changes/refactor-coupon-logic/ 下生成整套骨架。AI 会通过分析现有代码,在 spec.md 中自动列出已知的结算场景。

第二步:规格对齐与边界确认

这时不用急着让 AI 写代码,而是需要先审阅 spec.md。如果发现 AI 没考虑 “优惠券过期临界点” 的并发问题,可以直接要求 AI 修改规格:“在 spec.md 中增加过期校验场景,并要求使用 Lua 脚本保证原子性”。

第三步:受控应用(Apply)

一旦规格通过人工评审,就可以执行 /opsx:apply 了。这时,CC 就变成了完美的执行机器。它不再 “猜” 开发者的意图,而是对照 tasks.md 逐项实施。每一项修改后,它都会运行相关的测试。如果测试失败,CC 会自动分析错误并重新修复,直到该项 Task 标为 “完成”。

第四步、归档与知识固化

任务结束后,执行 /opsx:archive。原本散落在会话记录中的重构逻辑,现在变成了 openspec/specs/coupon-settlement.md 中的标准规格。当下一次另一个 AI 代理(或新入职同事)需要修改此模块时,它只需读取这份规格,即可获得完整的业务语境。

工具链对比:为何选择 OpenSpec

在 SDD 工具链中,OpenSpec 展现出了极高的工程性价比:

OpenSpec 的优势在于它不试图改变开发者的工具偏好。无论是使用 Claude Code、Cursor 还是 Aider,都可以无缝接入 OpenSpec 的规格管理层。

五、沉淀:让 AI 编码能力在团队中持续积累

AICoding 落地的终极目标不是让个体开发者写得更快,而是提升整个团队的知识资产质量。AI 编码能力不应随对话窗口的关闭而消失,而应作为 “团队记忆” 沉淀下来。

从个人技能到组织技能

团队可以通过自定义 Skill 和 MCP Server 来固化组织资产。

  • Skill: 将公司特有的代码风格、安全审计清单,或者特定中间件的使用指南封装为 .claude/skills/。当团队成员使用 CC 时,AI 会自动加载这些技能,仿佛有一位资深架构师在时刻盯着每一行代码。
  • MCP Server: 连接企业内部的向量数据库(如基于 Zilliz 的语义搜索),让 AI 代理能够从数千万行历史代码中找到最佳实践。

建立 AICoding 效能飞轮

AICoding 的成功落地需要建立一套正向循环的 “飞轮”:

  • 规格积累: 每完成一个 PR,都强制更新对应的 OpenSpec 规格文件。
  • 指令进化:发现 AI 反复犯的错,就将其转化为 CLAUDE.md 中的负向约束(Prohibited rules)。
  • 并行执行: 利用 CC 的 Agent Teams 能力,让一个代理负责写规格,另一个代理负责审计代码,第三个代理负责集成测试。

角色转变:从 “码农” 到 “规格定义者”

在 CC + OpenSpec 模式下,软件工程师的角色正在发生质变。如果 AI 能够根据完美的描述生成任何代码,那么 “代码” 本身就变成了编译后的中间产物,而 “规格” 才是核心产品。领域专家(Domain Experts)的重要性显著提升,因为他们能提供最高质量的业务意图描述。这种趋势将迫使开发者从关注 “语法实现” 转向关注 “系统设计” 和 “逻辑严密性”。

六、结语:AICoding 落地的飞轮正在转动

在 2026 年,AICoding 已不再是科幻。Claude Code 提供的强大代理能力,配合 OpenSpec 提供的精密规格框架,为企业提供了一套可复制、可量化的研发新范式。

我们必须承认,AI 编码的瓶颈从来不是模型不够聪明,而是我们与 AI 之间的 “沟通带宽” 太低且 “上下文” 太脏。通过上下文工程化管理(CC)和意图标准化表达(OpenSpec),我们正在构建一套让 AI 能够长期、稳定产出的工程环境。

随着这一模式的普及,软件开发的门槛将进一步降低,而创新的上限将被无限拉高。AICoding 落地的飞轮已经转动,那些能够率先将 AI 编码能力转化为团队组织资产的企业,将在未来的数字化竞争中占据绝对的先机。毕竟,在 AI 时代,掌握了 “意图” 与 “上下文” 的人,才掌握了软件工程的未来。

参考文档:

  1. thenewstack.io/context-is-…
  2. github.blog/ai-and-ml/g…
  3. solguruz.com/blog/spec-d…
  4. medium.com/@eran.swear…
  5. www.anthropic.com/engineering…
  6. code.claude.com/docs/en/how…
  7. www.anthropic.com/engineering…
  8. code.claude.com/docs/en/bes…
  9. dev.to/webdevelope…

往期回顾

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

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

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

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

5.搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术

文 /后羿

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

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

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

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

一、前言

大禹平台是一个离线 Dump 平台。在不同的场景都有自己的 Dump 流程,我们这里的 Dump 特指在搜索、推荐、广告(后续简称 “搜推广”)的场景中,将异构数据源加工处理后给到索引平台做索引的流程。

Dump 流程有如下一些特点:

  • 多源异构的数据:包括 MySQL、ODPS、HBase 和 Kafka 等各种数据源。
  • 多样化的输出:输出支持搜推广引擎构建倒排索引、Summary 服务构建 kv/kkv 索引等。
  • 流批数据结合:一般会有全量和增量,需要保证处理逻辑一致,增量能达到秒级更新。
  • 数据处理能力:例如多表 Join、UDF、Filter 等,以方便业务的开发和接入。

离线 Dump 流程

二、项目背景

现状

当前 dump 开发模式

如上图是当前常见的 Dump 开发模式,采用了流批分离架构:流处理通过 DTS 订阅 binlog,由 Flink 消费主表变更事件并反查关联表构建宽表,实现增量更新;批处理则将 MySQL 数据抽取至 ODPS,通过 Spark 处理多源数据并按业务逻辑拼接,最终输出 ODPS 表。这种架构存在以下问题:

当前 dump 开发的问题

目标

依托社区搜索核心场景,构建流批一体化的新质 Dump 架构,实现以下三大核心能力突破:

  • 工程效率: 基于可视化 DAG 编排工具,提供低代码开发能力,通过拖拽式界面实现复杂任务流程的快速搭建与迭代,显著降低开发门槛。
  • 数据质量: 基于流批一体架构,通过统一逻辑开发范式实现流批数据同源同构,从根本上提升数据准确性与可靠性。
  • 稳定性保障: 通过引入镜像表和状态大宽表,提高了数据的查询效率,系统性降低对源库的反查压力,确保系统长期稳定运行。

二、大禹平台介绍

平台设计

系统架构

平台架构

如上图是大禹平台技术架构,底层依赖公司的 DJob Cron 定时任务、Flink/Spark 流批计算能力以及多种存储系统;上层为平台支持的搜推广多种场景业务。

大禹平台分为管理平台与后台系统两部分。管理平台完成处理逻辑的 DAG 开发和相关 Debug、回归验证、监控大盘等能力;后台系统将管理平台的配置转为执行任务,然后依托流批框架生成 Flink/Spark 执行实例,通过调度引擎完成全流程任务执行。

如下图是新版 Dump 流程,将 Dump 拆分为三个阶段:镜像阶段、宽表阶段、导出阶段,以及流、批两种处理模式。新版流程处理过程有如下优化:

  • MySQL 镜像至 HBase: 平台将任务依赖的 MySQL 数据统一同步至 HBase 构建镜像层,实现与上游 RDS 解耦。有效规避多任务并发反查导致的数据库压力,支持跨任务共享复用 HBase 镜像表,显著提升数据源稳定性与资源利用率。
  • Binlog 订阅平台化: 将 RDS Binlog 订阅流程深度内嵌,自动完成 DTS 订阅创建与 Kafka 资源申请,封装为标准化服务。开发者无需关注底层链路,一键配置即可获取实时变更流,降低接入复杂度,保障流式数据可靠性。
  • 状态大宽表消除反查: 基于 HBase 构建持久化状态大宽表,完整记录字段中间状态。任务处理时直接读取状态数据,彻底规避冗余反查逻辑,简化开发流程。

新版 Dump 流程

调度引擎

大禹平台利用得物 DJob Cron 自建调度系统,通过搭建多个 Cron Job 轮训的方式,完成对任务分阶段的处理。

Cron Job 构建调度系统

一个执行实例的全流程

执行框架

在镜像、宽表、导出三个阶段,分别都有对应 Spark 和 Flink 处理框架。其中,镜像阶段完成 MySQL 数据同步,导出阶段完成状态宽表到引擎数据源的导出流程,宽表阶段是具体的业务逻辑实现。

宽表 Spark 框架逻辑: 任务严格遵循 DAG 拓扑顺序,依次执行各算子节点(数据源→业务逻辑→导出)的数据处理流水线,最终通过 BulkLoad 方式将结果高效写入 HBase。

宽表阶段 Spark 框架逻辑

宽表 Flink 框架逻辑: 消费非维表节点的增量,依据节点依赖关系进行拓扑排序后依次执行各节点计算逻辑,将产出字段更新至状态宽表,并实时同步至下游导出链路。

宽表阶段 Flink 框架逻辑

流批一体保障数据质量

平台采用统一的 DAG 编排引擎,将流处理与批处理任务抽象为相同的计算拓扑,从架构层面保障数据源头的天然一致性,彻底规避因不同环境下开发导致的数据偏差风险。同时,平台内置标准化的 UDF(用户自定义函数)开发模板与运行时框架:开发者只需专注业务逻辑实现,编写的 UDF 代码经一次注册,即可无缝嵌入流式与批量处理流程,真正实现 “一次开发、流批复用”,显著提升开发效率,降低维护成本,保障 Dump 开发从数据源头到处理逻辑各环节的流批一致性。

平台通过定义 AlgoDumpUDF 方法类,完成消息类型封装,用户可以利用 UDF 实现数据过滤和驱动删除等逻辑。

public abstract class AlgoDumpUDF implements UDFFunction, Serializable {
    //消息类型 add/delete/drop 三种
    public AlgoDumpMessageType algoDumpMessageType = 
    AlgoDumpMessageType.MESSAGE_TYPE_ADD;
    @Override
    public AlgoDumpMessageType getStatus() {
        return algoDumpMessageType;
    }


    //调用该方法实现增量驱动删除
    @Override
    public void delete(Object key, String reason) {
        this.algoDumpMessageType = AlgoDumpMessageType.MESSAGE_TYPE_DELETE;
    }
    //调用该方法实现增量过滤
    @Override
    public void drop(Object key, String reason) {
        this.algoDumpMessageType = AlgoDumpMessageType.MESSAGE_TYPE_DROP;
    }
    /**
     * 用户重写该方法完成业务逻辑开发
     */
    public void process() throws Exception {
    }
}

CASE示例:用户通过重写process()方法, 实现自己的业务逻辑,实现时可以利用drop方法把无效数据过滤,利用delete方法实现对下游索引发送删除消息。

public class MyUdf extends AlgoDumpUDF implements Serializable {
    public  Tuple2<String, String> process(String id, String taskname) 
    throws Exception {
        //过滤消息
        if(StringUtils.isBlank(id)) {
            this.drop(id, "drop by id null");
        }


        //驱动增量删除消息
        if(id.equals(0)) {
            this.delete(id, "delete by id = 0");
        }


        //用户写具体业务逻辑
        String a1 = "";
        if (taskname.equals("dddddd")) {
            a1 = "ddd";
        }
        String b1 = "test";
        return new Tuple2<>(a1, b1);
    }
}

小全量模式加速数据Dump

大禹支持任务实例按照大全量和小全量两种模式运行,针对部分频繁更新部分字段需求的任务可实现快速加载。

  • 大全量: 对数据源执行全量同步重建,生成全新的状态大宽表,并同步刷新流批处理链路,实现数据基准的彻底更新与端到端一致性保障。
  • 小全量: 基于现有状态大宽表,仅针对批处理来源字段加载最新数据源快照,经处理后通过 BulkLoad 高效写入 HBase;依托 HBase 多版本特性实现新旧数据平滑切换,确保批处理数据增量更新过程中查询服务零中断、数据时效性与业务连续性兼得。

小全量模式

任务复用支持数据分层管理

大禹平台支持任务产出的双重应用:既可对接计算引擎(如 CEngine),亦可作为公共数据被下游任务高效复用。平台通过标准化的 MirrorOut(导出)与 MirrorIn(接入)算子构建清晰的数据复用链路 —— 上游任务将公共数据配置为 MirrorOut 导出,下游任务通过 MirrorIn 算子一键引用,无需重复开发与数据搬运,实现数据资产的即产即用、任务依赖的显式管理,显著提升开发效率与数据复用性。

任务复用

管理平台

任务开发与运维

管理平台提供一站式任务开发生命周期管理,涵盖任务创建、可视化流程编排、实例调度与资源管控等核心环节;其中,Dump 任务通过可视化编排实现业务配置——用户仅需拖拽算子节点、配置参数,即可直观构建数据处理逻辑,显著提升开发效率与配置准确性。

如下图,通过拖拽算子的方式,可以直观地构建 dump 任务的流程图,实现便捷高效的开发体验。

图画编排式开发任务

执行实例以可视化流程图形式完整呈现任务执行全流程,每个节点清晰展示输入参数与输出结果,并支持对指定节点进行手动重试或终止操作,便于问题定位与流程干预。

执行实例状态

辅助工具

数据回归验证

平台提供流批数据回归验证能力,支持模板化配置与一键复用,高效保障数据质量与业务稳定性。

  • 批量回归: 多版本批数据快速比对,一键校验全量一致性,适用于版本迭代验证;
  • 流式回归: 基于索引表增量变更抽样,对指定时间窗口内实时数据进行跨索引一致性校验,精准定位流式链路异常。

创建批数据回归任务

创建流数据回归任务

数据Debug

大禹平台构建了覆盖全链路的数据运维干预能力,确保数据处理的可靠性与灵活性。

  • 组图配置: 支持对源端组图配置进行主动干预与调整,实现配置策略的快速生效。
  • Dump流程: 支持Dump构建流程的调控,实现对全链路流程的问题快速定位,保障数据产出的稳定性与高效性。
  • 在线索引: 提供线上索引数据的实时干预能力,支持对增量数据进行修正,确保索引内容的及时性与准确性。

四、业务场景实践

社区搜索倒排表链路

如下图所示,社区搜索倒排表 Dump 任务以动态内容为核心实体,融合动态实时内容流、天级统计特征及商品多维特征,通过流批一体处理生成高时效的倒排索引宽表。

社区搜索倒排宽表链路

穿搭精选推荐链路

如下图所示,穿搭精选推荐 Dump 任务以动态-商品关系为核心主表,融合动态维度的多源流批特征数据(如内容特征基础表、内容审核表、天级离线统计特征表等),利用DAG 编排构建动态-商品的大宽表。

穿搭精选推荐链路

五、未来规划

平台能力持续增强

  • 算子体系完善: 基于业务场景持续增强关键算子(如维表动态更新、Service 服务化算子、UDTF 部署优化等)和优化调度流程,强化数据处理灵活性;
  • 性能深度优化: 引入任务剪枝、智能倾斜治理等策略,提升资源利用率与执行效率;
  • 可观测性升级: 构建覆盖全局大盘与任务粒度的监控体系,完善资源消耗追踪、Debug 与全链路 Trace 能力,夯实平台稳定性与运维支撑基础。

深化协同共建,释放平台价值

  • 纵向提效: 聚焦索引构建效率攻坚,与索引平台深度协同重构数据同步链路。以社区搜索大宽表为例,当前同步耗时近3小时,通过消除冗余中间状态、精简处理流程,可以实现索引构建端到端提速,显著压缩数据准备周期。
  • 横向赋能: 平台能力已在社区域多业务场景完成验证,后续可以联动其他业务场景共建;同时平台的子功能也具有通用能力,可将数据回归验证、索引监控大盘等高复用能力模块化开放,赋能各业务线“即插即用”,加速技术资产沉淀与跨域协同创新。

大禹未来规划

往期回顾

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

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

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

4.搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术

5.得物社区搜推公式融合调参框架-加乘树3.0实战

文 /野雨

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

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

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

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

一、背景

事情是这样的,之前对 AI 编程一直是观望态度,但是部门最近在做 AI 辅助编程 POC,有幸成为 POC 用户,用上了自己舍不得买的高级编程模型 (感谢公司)。尽管我自认为是一个在代码上很挑剔的人,但是试了下感觉居然还可以 (Go、React)!只能说还得是谷歌,调整重心略微发力,Gemini 3 表现确实很不错。既然尝到甜头了,觉得自己是时候好好地琢磨琢磨,研究研究,沉淀一套自己的工作流、方法论,解放自己的生产力,顺应潮流努力成为 AI 时代的受益者,而不是被淘汰的人!

新的开发范式需要搭建新的开发环境和匹配自己开发习惯的工作流,这就像刚学编程那会,需要挑一个自己喜欢的 IDE、熟悉 IDE 快捷键和优化 IDE 设置一样。过程中间肯定有阵痛,Java 开发者们回忆一下多年之前从 Eclipse 转 IDEA 那会的阵痛吧,但是磨刀不误砍柴工,阵痛之后一定是生产力提升。借本文分享下我摸索后的方案,供大家参考。

二、工具选型

目前 AI 辅助编程领域热火朝天,各种 GUI 工具、TUI 工具如雨后春笋让人目不暇接,这对于花心的强迫症选手(比如我)来说选型很困难。但是我觉得有两个基础认知可以帮助我们更好地做决定:

(一)AI 辅助编程工具由脑和手两部分组成。脑是外接的大模型 API,手是各个产品调教的提示词和内部工作流。按我理解,【脑】决定了工具的上限,【手】决定了工具的下限。在这个场景里,大模型就像是汽车里的发动机,而且所有型号的汽车支持的【发动机】规格都是通用的、统一的、标准化的。有了这个基础,我们可以随便选一个趁手的工具,然后自行按场景选配【合适】的【发动机】。

(二)AI 辅助编程当前是一个【千帆竞发】的热门领域,而且单纯就【工具】来说,这个领域【没有技术壁垒】。A 产品抛出的杀手级特性,不出半个月一定会有 B 产品跟进。毕竟现在软件迭代的速度借助 AI 提升了很多,A 产品验证过的想法,B 产品可以很快地跟进和实现。Claude Code CLI 的开发者就使用 Claude Code CLI 迭代 Claude Code CLI,有点绕口,大概就是【工具自举】的意思吧。

Claude Code CLI

综上,其实没啥纠结的,我们照着这两点来选型就好:1. 这个工具一定得便捷地支持模型插拔,就是我随时可以根据场景换一个更适合的、更便宜的、表现更好的大模型。而且这种插拔一定要简单。 2. 这个工具一定要有积极的维护者,不断地迭代、优化它的工作流、提示词。最好是一个商业化产品,因为商业化产品出于其商业目标,一定会投入资源积极进行迭代。 

当前满足这两个条件的,我想也就是 Claude Code CLI 了: 1. Claude Code CLI 是一个商业化产品,有专门的技术团队在不停地更新、迭代。 2. Claude Code CLI 可以非常便捷地支持大模型插拔,我可以随时根据成本、效率、体验来切换合适的大模型。因此,这个环节我选 【Claude Code CLI】。

后文以CC代指Claude Code CLI。

快速切换模型

我通过自定义 Shell 函数来实现便捷的模型切换,不同的场景、不同的任务使用不同的模型。基本原理就是,CC 支持环境变量注入 LLM 配置信息,因此我只需要按场景注入【行内临时环境变量】即可。

详见:Bash - 行内环境变量,Bash 是标准的 Shell 实现,其他 Shell 如 Zsh 都兼容其行为。

Shell配置

我到处弄了一堆免费的、收费的模型用,然后给他们取了我记得住的别名:

使用效果

为了兼容,设置了一个 claude 别名:

这样输入claude 时,默认使用智谱 GLM 模型。

脚本源码

Shell 脚本大概这样,可以修改后配置到自己的 ~/.zshrc 中。如果不熟悉 Shell,嫌麻烦也可以试试这个开源工具:farion1231/cc-switch。

# claude 默认
alias claude='zcc'
# Kimi
function kcc(){
    echo Kimi Claude Code...
    local model="kimi-k2.5"
    ANTHROPIC_BASE_URL="https://api.moonshot.cn/anthropic" \
    ANTHROPIC_AUTH_TOKEN="sk-xxxxxxxxx" \
    ANTHROPIC_SMALL_FAST_MODEL="$model" \
    ANTHROPIC_DEFAULT_OPUS_MODEL="$model" \
    ANTHROPIC_DEFAULT_SONNET_MODEL="$model" \
    ANTHROPIC_DEFAULT_HAIKU_MODEL="$model" \
    CLAUDE_CODE_SUBAGENT_MODEL="$model" \
    launch_claude_code $@
}
# 智谱GLM
function zcc(){
    echo GLM Claude Code...
    ANTHROPIC_BASE_URL="https://open.bigmodel.cn/api/anthropic" \
    ANTHROPIC_AUTH_TOKEN="sk-xxxxxxxxx" \
    launch_claude_code $@
}
# 七牛
function qcc(){
    echo QiNiu Claude Code...
    local model="minimax/minimax-m2.1"
    ANTHROPIC_BASE_URL="https://api.qnaigc.com" \
    ANTHROPIC_AUTH_TOKEN="sk-xxxxxxxxx" \
    ANTHROPIC_SMALL_FAST_MODEL="$model" \
    ANTHROPIC_DEFAULT_OPUS_MODEL="$model" \
    ANTHROPIC_DEFAULT_SONNET_MODEL="$model" \
    ANTHROPIC_DEFAULT_HAIKU_MODEL="$model" \
    CLAUDE_CODE_SUBAGENT_MODEL="$model" \
    launch_claude_code $@
}
function launch_claude_code(){
    CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
#    clear
    command claude $@
}

三、开发环境

在当前的气氛下,我想我算是一个【古板】的开发者,我做不到【fire and forget】,或者说完全靠黑盒的自然语言对话来完成代码开发。

我还是只将 AI 当助手,还是想要白盒的掌控 AI 写的代码,还是希望最终交付的代码有我的风格、我的审美、我的品味。毕竟 AI 也只能帮我写代码,并不能帮我背锅。尽管我选择了 TUI 工具 Claude Code CLI,但是我还做不到全程只在终端操作,我还是习惯 JetBrains 特色的双栏 diff。

因此,当前我开发流程的起点还是传统的 IDE,比如我最喜欢的 JetBrains。每天上班第一件事是接水,第二件事就是打开 IDE。所以我需要想办法来将 GUI 工具和 TUI 工具流畅的衔接起来,减少代码开发时的频繁切换产生的割裂感!

多屏协作

如上图,我有 3 个显示器,我的构想是这样的:

  1. MacBook 内置显示器 —— 常驻两个空间:一个用来打开浏览器,还有 VPN、网易云音乐、Finder 软件,用来承接各种临时的操作。一个用来打开飞书,用来沟通、协作。

  1. 中间主屏 —— 常驻两个空间:一个用来打开浏览器,用来做各种【输出】。一个用来打开 IDE,专注于写代码、看代码,用标签页打开多个 Project。

  1. 左边竖屏 —— 常驻两个空间:一个用来打开浏览器,用于看文档、查资料等各种【输入】。一个用来打开 TUI 工具,进行辅助编程!

GUI/TUI衔接

现在问题来了,我希望我的开发工作的【主轴】是 IDE,流程的起点是 IDE。但是我的 IDE 在中间屏幕,终端在左边屏幕,它俩是独立软件,没法协作、自动跟随切换 Project 的工作目录。我希望有个【自动化流程】,当我在 IDE 里切换项目的时候,CC 自动跟随切换!

衔接流程

我期待的流程是这样的:

因为某个原因,我在 IDE 里打开了一个项目 A  准备写代码了,点击 IDE 里的某个【按钮】,左边屏幕自动【新建】一个项目 A 的 CC 会话终端并激活到前台显示   我跟左边的 CC 对话,让他干活  我在中间的 IDE 里评审、调试、诊断  因为某些原因我又要在 IDE 打开一个别的项目 B  我再次点击那个【按钮】,左边屏幕自动【新建】一个项目 B 的 CC 会话终端并激活到前台显示  我在 IDE 里又切回了项目 A,我又点击了那个【按钮】,左边屏幕自动【切换】到 A 的 CC 会话终端并激活到前台显示。

好的想法已经有了,AI 时代就怕你没有想法,有想法就一定有办法实现!

代码实现

  1. macOS 上的原生软件,大部分支持 AppleScript 自动化,也就是说我们可以写脚本驱动软件的行为、模拟人机交互,比如打开软件、新建 tab、点击按钮等。

  2. JetBrains IDE 支持集成外部命令,也就是说:可以在 IDE 里点击一个按钮,自动执行一个 Shell 脚本或者别的可执行文件。

产品需求清晰了,接下来开始让 AI 干活!一顿沟通和调试之后,我们有了一个【自动化】创建 iTerm2 新标签的可执行脚本!

这是给大模型的需求提示词,大家可以按需选用,做个性化的调整:

## 📌 工具功能说明
请帮我创建一个 macOS 上的 iTerm2 自动化工具,主要功能包括:
### 核心需求
1. **智能窗口管理**:自动使用或创建 iTerm2 窗口
2. **项目标签管理**:为每个项目目录维护独立的标签页,支持标签复用
3. **三面板布局**:自动创建固定的三面板布局(上方一个全宽面板,下方两个并排面板)
4. **命令自动执行**:在每个面板中自动切换到项目目录并执行预定义的命令
### 使用场景
```bash
# 基本用法:在当前目录打开
./open-claude-in-iterm.sh
# 指定项目目录
./open-claude-in-iterm.sh /path/to/project
```
---
## 🎯 技术架构要求
### 技术栈
- **Shell 脚本** (open-claude-in-iterm.sh):参数处理、路径规范化、日志管理
- **AppleScript** (open-claude-in-iterm.applescript):iTerm2 自动化核心逻辑
**依赖**:macOS、iTerm2、Bash
---
## 📋 详细功能规格
### 1. Shell 脚本 (open-claude-in-iterm.sh)
#### 参数处理
- **参数1**:项目目录(可选,默认当前目录)
- **自动处理**:相对路径转绝对路径
#### 面板命令配置
```bash
PAN1_CMD="claude"     # 上方面板命令
PAN2_CMD="claude"     # 左下面板命令
PAN3_CMD="claude"     # 右下面板命令
```
### 2. AppleScript (open-claude-in-iterm.applescript)
#### 主要流程
**步骤1:窗口管理**
- 检查 iTerm2 是否运行(未运行则自动启动)
- 使用当前激活的 iTerm2 窗口,如果没有则创建新窗口
**步骤2:标签管理(关键逻辑)**
- 在找到的窗口中,查找 `session.path` 变量等于项目目录的标签
- **复用逻辑**:如果找到现有标签 且 窗口不是新创建的 → 直接切换标签并返回
- **创建逻辑**:如果未找到标签 或 窗口是新创建的 → 创建新标签和布局
**步骤3:三面板布局创建**
```
布局示意图:
┌─────────────────────────┐
│   上方面板 (全宽)         │
│   执行: PAN1_CMD         │
├──────────────┬──────────┤
│  左下面板    │  右下面板 │
│  PAN2_CMD   │  PAN3_CMD │
└──────────────┴──────────┘
```
**分割顺序(重要)**:
1. 初始状态:一个全屏 session(上方面板)
2. 第一次分割:对上方 session 执行**水平分割**,创建下方面板
3. 第二次分割:对下方 session 执行**垂直分割**,创建右下面板
**步骤4:命令执行**
在每个面板中依次执行:
1. 切换到项目目录:`cd "/path/to/project"`
2. 清屏:`clear`
3. 等待 0.3 秒(确保目录切换完成)
4. 执行命令:`PAN_CMD`
5. 等待 0.5 秒(确保命令启动)
## ⚠️ 常见错误
- ❌ 符号链接未处理,导致找不到 AppleScript 文件
- ❌ 分割顺序错误,导致布局不正确
- ❌ 缺少 delay,导致命令执行失败或在错误目录执行
- ❌ 新窗口处理错误,导致多余空白标签
- ❌ 标签复用逻辑错误,导致同一项目创建多个标签
- ❌ 路径未引用,导致包含空格的路径失败

IDE配置

创建外部工具

添加到工具栏

使用效果

点击工具栏按钮后,自动在全屏的 iTerm2 窗口新建或激活项目目录下的 CC 会话,下图里就是 3 个项目。

四、多Agent协作

会的越多,让你干的就越多。既然 AI 那么牛,一个 CC 会话已经满足不了我膨胀的想法和需求了。我希望我可以同时支配多个 AI 开发工程师,而我变成 PM!所以参考酒米的思路,我给每个项目的终端,自动化的划分了 3 个子窗口,每个子窗口都是一个 CC 会话。效果大概这样:

主从架构

每个项目自动打开 3 个常驻的 AI 会话,我设想的工作流是这样的:

【架构师】上面的大屏,用贵的模型!专门用来跟我聊需求、对方案、产出任务列表。

【开发者】下面的两个小屏,用领域特定的模型,专门用来落地大屏架构师产出的方案和任务。比如前端需求用前端效果好的模型,后端需求用后端效果好的模型。

知人善用才是好 PM!这个模式也很匹配现实中的组织架构和成本取舍,现实中每个需求一般也都是由一个架构师和多个中高级开发者来协作完成!感谢热心市民无声雨,给我们小组共享了自己采购的纯血 Claude 模型,所以目前我用 Claude 模型来对方案,用 GLM 或者 MiniMax 来实施方案!

规范驱动开发(SDD)

主从智能体的协作很重要,我跟【架构师】聊了半天确定的方案和设计,需要有一个清晰的、对大模型友好的方案和任务文档作为【开发者】的输入。这就很巧,刚好最近在流行 SDD,规范驱动开发。大致就是模拟现实中的软件开发流程将开发生命周期拆分为 3 个阶段:

  • 【proposal】需求对齐、方案设计、【任务细化】;
  • 【apply】开发任务实施;
  • 【archive】功能验收、文档沉淀

围绕这个流程,开源社区设计和研发了一系列对大模型非常友好的工具和提示词(比如 OpenSpec),【阶段 1】和【阶段 2】中间通过格式设计良好的【设计文档和任务文档】来进行上下文交接。

也就是说,我可以在上述的 3 窗口环境中,按照 SDD 流程来:【proposal】跟【架构师】交互,对齐需求、设计和任务 A  【apply】让【开发者 1】着手完成任务 A  【proposal】继续跟【架构师】交互,对齐需求、设计和任务 B  【apply】让【开发者 2】着手完成任务 B  【proposal】继续跟【架构师】交互,对齐需求、设计和任务 C  【apply】让【开发者 1】着手完成任务 C  ……

五、CC拓展

CC 当然很厉害,但它本质上也就是一个朴素的 ReAct 模式智能体。

ReAct 这么火,大家肯定也都耳熟能详了,我们也就不说太多。当然 CC 团队围绕编程这个课题做了很多细致的提示词调优和内置工作流设计,这个我们黑盒的用就好了,也没必要关注太多。我们最需要关注的,是 CC 提供给我们使用者的【拓展点】,那些允许我们个性化设置的东西。

命令(command)

命令的本质就是预定义的提示词模板。目的是为了省事,不用每次都重复的输入类似的提示词。比如想让 CC 帮我提交代码,每次我们可能都要交代一大堆字,比如:

请调用 git diff --cached 获取当前暂存区的代码变动。
忽略所有的 node_modules 或二进制文件。
基于变动内容,判断这是一个 feat (新功能), fix (修复) 还是 chore (杂务)。
生成一个不超过 50 字符的标题,并在正文详细列出影响的文件。
由我确认后执行 git commit。”

就像写代码的时候将重复代码提取为一个独立方法一样,我们可以把这些可以复用的提示词固定成一个【命令】,后续使用的时候,直接输入命令名字就好。斜杠命令是一段提示词的快捷方式。

技能(skill)

技能和命令最大的差别就是:命令是用户主动提交的提示词,而技能是 Agent 自己决策后自动导入的提示词。当然技能包里除了提示词,一般还会携带一些配套的工具、脚本、命令或者文档。

比如,我安装了一个【html 转 pdf 的技能包】,这只能提示 CC 可以使用这个技能,但是具体用不用、什么时候用、怎么用都是 CC 自己规划、决策的。

子代理(subAgent)

SubAgents 是可以并行处理任务的独立 AI 代理,每个子代理拥有独立的上下文窗口,可以分配不同任务以提高效率。【主代理】的上下文窗口中包含有【子代理】的【简短】描述信息,可以基于这个描述信息规划、决策使用哪个子代理。

{
  "agents":{
    "code-reviewer":{
      "description":"专门负责代码审查的子代理",
      "model":"claude-opus-4-5",
      "instructions":"你是一个专业的代码审查专家,专注于检查代码质量、安全漏洞和性能问题。",
      "tools":["read","search","git"],
      "permissions":{
        "allowWrite":false
      }
    },
    "test-writer":{
      "description":"专门负责编写测试的子代理",
      "model":"claude-sonnet-4-5",
      "instructions":"你是一个测试工程师,专注于编写全面的单元测试和集成测试。",
      "tools":["read","write","bash"]
    },
    "doc-generator":{
      "description":"专门负责生成文档的子代理",
      "model":"claude-sonnet-4-5",
      "instructions":"你是一个技术文档专家,专注于生成清晰、准确的技术文档。",
      "tools":["read","write"]
    }
  }
}

独立上下文窗口的好处是:避免上下文污染和占用。比如我要在代码里找一个接口的所有实现类,这个就很适合子代理来做。主代理只需要交代给子代理接口名,然后就等子代理返回实现类列表。

这样在主代理的上下文窗口里,只会有子代理的输入和输出(几个类文件路径),而子代理在搜索过程中遍历文件、目录、读取文件内容产生的临时 token,不会对主代理产生影响。我目前认为 SubAgent 和 Skill 差不太多。不过我不确认 Skill 是不是在独立的上下文中执行。

MCP

MCP 和技能一样,都是由 CC 自主规划、决策使用的。差别有两个:

  1. MCP 工具的说明信息占用的上下文太多了!不管是否被使用,每次都需要一口气提交所有工具的完整元信息(使用说明 + 出入参 Schema)供大模型规划、决策,占用大量上下文。而【技能】选择了【渐进式披露】,先向大模型提供少量关键信息,只有在大模型选择了使用技能时,才告诉大模型更多关于技能的补充说明信息,让大模型进一步推理、决策。

  2. MCP 工具更多的偏向【远程 RPC】,基于网络来实现原子化的远程能力调用。而【技能】更多的偏向【本地 IPC】,具体能力更多通过【编排】本地脚本、本地命令来实现,有点像 stdio 模式下的 MCP。

钩子(hook)

hook 是在特定事件触发时自动执行的脚本,用于自定义工作流、拦截危险操作、自动格式化代码等。就类似 Linux NetFilter,CC 在很多地方植入了流程执行的劫持点,将流程上下文交给用户开发的脚本或者命令。

插件(plugin)

plugin 就是上述各种拓展打包、分发、安装的一种格式。你可以把它想象成 npm 包、pip 包、apk 包等我们比较熟悉的概念。然后我们可以按流程和格式建设插件市场,类似 pip-index、npm-index 等。

我没有细看流程和格式,但是大概也就是一个特定文件布局的 zip 文件包,里面有插件描述信息和各类拓展,比如可以包含:

  • 5 个 Skills;
  • 10 个斜杠命令;
  • 3 个 MCP 服务器配置;
  • 2 个 SubAgent 定义;
  • 若干 Hooks。

六、CC技巧

飞书MCP

飞书官方提供了 MCP,我主要用它来读写飞书文档,蛮好用的,大家可以试试。比如我每周都要在固定目录下创建固定标题格式的【系统巡检文档】,所以我借助飞书 MCP 整了个自定义 Command 帮我自动创建这些文档去除重复劳动,感觉真香!之前每次都要手动建 3 个文档、选目录、改名字!

@模糊搜索

有时候我们需要精确的告诉 CC,哪个文件需要读或者改,其实不用从 IDE 里复制文件路径,直接在终端里模糊搜索就好了。

WebFetch

CC 默认集成了 WebFetch 命令,就是指定 URL 读取网页内容,这个理论上就是一个本地执行的 curl 命令,没有云端成本,不需要云端协作。但是有个问题:(一)CC 在访问地址之前,会先调用 anthropic.com 的一个风控接口,判断这个网络地址是否有安全风险。(二)政策原因,anthropic.com 会拒绝所有来自中国大陆、香港的请求,风控接口返回 404 或者其他。(三)风控不通过,WebFetch 失败。

在 ~/.claude/settings.json 中添加如下配置,禁用 WebFetch 工具前置的风控检查就好了。

{
  "skipWebFetchPreflight":true,
}

详见:linux.do/t/topic/114…

WebSearch

WebSearch 是需要云端协作的,需要有个搜索引擎服务提供能力。因为我们没有用官方的付费订阅,所以默认的 WebSearch 工具我们用不了,调用 WebSearch 工具得到的结果都是 0。

办法是去找一个免费或者收费的 MCP 服务。免费的我看大家都推荐 Brave<brave.com>,大家也可以找找别的。收费的也有很多,我看智谱的套餐里限量提供了 <联网搜索 MCP - 智谱 AI 开放文档>。也有很多按量付费的,大概几分钱一次,有需要的可以找找。

添加了 MCP 搜索工具后,建议禁用 CC 自带的 WebSearch 工具,不然每次跟大模型交互时,工具信息还会带给大模型,产生额外的 token 开销和推理误判。在 ~/.claude/settings.json 中添加如下配置:

{
  "permissions":{
    "deny":[
      "WebSearch"
    ]
  }
}

iTerm2通知

终端上的任务需要我们输入的时候,可以配置下,让 iTerm2 发出声音和通知。这样我们就不会因为忘记确认操作而阻塞进度。

详见:Optimize your terminal setup - Claude Code Docs

清空上下文

因为我们每个项目都复用一屏内的 3 个子窗口,一般不会重开。为了避免上下文溢出或者之前对话对新任务产生干扰,当我们完成一个任务时,需要及时的执行 /clear 命令,清空上下文,从 0 开始新对话。

如果任务没有完成,但是又不得不 clear,那么可以维护一个自定义命令,在 clear 后提示大模型根据 git status 看到的文件变更快速找回上下文。把 git 状态当作 AI 的 “短期记忆快照”,/clear 只清上下文,不清工作进度。

# Context Catch-up
当前对话已被 `/clear`,请通过 git 状态恢复上下文。
使用方式:
1. 阅读 `git status`(必要时结合 `git diff`2. 仅基于文件变更推断正在进行的任务
3. 延续现有实现思路,不要假设额外背景
4. 在未收到明确指令前,先给出你对当前上下文的判断
目标:
- 快速找回任务状态
- 避免旧对话或错误假设干扰新任务

注意力哨兵

在记忆文件里要求大模型扮演一个特别的角色,如果聊着聊着角色行为丢失了,说明大模型注意力失焦了,已经丢掉了你最开始的要求。这时候就该 clear 一下重开会话了。

拓展市场

为了便于相关个性化拓展物料的分发、便于大家搜索、安装,市面上已经有了相关的分发平台和便捷安装命令了。

  1. skills.sh

  1. www.aitmpl.com

状态行个性化

状态行显示在 Claude Code 会话界面底部,可以自定义显示的内容,比如git分支名、目录名、模型名等。推荐使github开源项目:claude-code-statusline-pro-aicodeditor,效果如下:

详见:github.com/HorizonWing…

七、总结

差生文具多,尽管我暂时还没有使用 CC 产出啥说得上来的东西,但是确实花了很多时间琢磨怎么让它用起来更顺手。一些不成熟的想法,希望可以给到大家启发。

参考:

  1. www.ginonotes.com/posts/how-i…
  2. www.cnblogs.com/knqiufan/p/…

往期回顾

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

2.搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术 

3.得物社区搜推公式融合调参框架-加乘树3.0实战

4.深入剖析Spark UI界面:参数与界面详解|得物技术

5.Sentinel Java客户端限流原理解析|得物技术

文 /羊羽

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

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

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

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

一、前言

10 天,2.5 万行代码,提效 36%。 基于 Claude Code 的 Spec Coding(规格驱动编码) 深度实战。通过 2,754 次工具调用,我们不仅完成了从 0 到 1 的前端项目搭建,更在“约束+示范+视觉”的三层规范体系下,摸清了 AI 编程的真实能力边界。本文将复盘这场实战,拆解如何用结构化工作流消除 AI 的不确定性,重构开发者的核心竞争力。

二、Spec Coding

什么是 Spec Coding 工作流

众所周知,Spec Coding(规格驱动编码)的核心思想是:在写代码之前,先写规格文档。通过 openspec 工具,每个功能变更都经历以下阶段:

Spec 工作流的实际价值

减少返工: 在 proposal 阶段明确为什么以及怎么做,避免实现完才发现方向不对。适合复杂功能: 对于需要跨多个文件多个层次的功能,tasks 分组让 AI 聚焦在当前步骤。可审计: 每个 Change 的完整决策链(proposal→design→specs→tasks)都留有记录,方便回溯。

三、项目是什么

一个标准企业级中后台搭建,包括表格、表单、卡片列表、数据看板等中后台常见核心功能,项目从零搭建到完成以下全部功能,全程使用 Claude Code 辅助开发。

四、数据概览

在这次使用Claude Code 做 Spec Coding的从0到1项目探索中,我们积累了一份完整的原始数据,以下所有数字均来自Claude Code对 109 个 .jsonl 会话文件的整体数据统计:

2,754 次工具调用的分布揭示了 AI 的"工作方式", AI 自主完成的 738 次文件读取、550 次代码编辑、662 次终端命令执行,以及 208 次任务进度标记——几乎覆盖了一个研发日常工作的全部动作类型。

五、开发时间线:10 天的演进过程

阶段一:设计阶段

在动工之前,我们完成了产品方向的确认和 UI 设计稿、产品PRD的输出。过程主要使用 Cursor + 设计规范 Rules,直接从概念沟通到生成高保真 UI 稿(HTML文件),再生成标准的 PRD 需求描述,覆盖系统所有核心页面。这一阶段的产出是一套可直接用于开发对齐的视觉参考,也是后续 AI 生成代码时的重要上下文来源。

阶段二:项目搭建(2个工作日,20 条指令)

此阶段我们以问答式交互为主,聚焦于项目基础设施的搭建和简单需求的尝试。我们向 AI 提出架构问题,由 AI 给出方案,我们决策后执行。在这个过程中,AI 帮助我们熟悉技术栈、搭建项目结构、配置开发环境,并完成了第一个核心列表页面的开发,成功打通了前后端的数据链路。

阶段三:功能开发(4个工作日,89 条指令)

这是整个项目开发强度最高的阶段,我们引入了“规格驱动编码”(Spec Coding)的工作流,约 80% 的功能代码在此阶段完成。我们不再是简单地给 AI 下达指令,而是先与 AI 共同定义清晰的功能规格(Specification),然后 AI 基于这份“蓝图”自主进行编码。通过这种方式,我们高效地完成了包括授权管理、数据分析看板、文档树状结构等多个复杂功能的开发。

阶段四:细节打磨与生产部署(4个工作日,108 条指令)

最后阶段的工作重心转向功能迭代、系统重构和生产环境的部署排障。我们与 AI 一起,对已有功能进行了多轮优化,例如完善了核心业务流程、重构了侧边栏导航、修复了登录跳转逻辑等。同时,我们也对项目首页进行了深度的代码重构,解决了前期快速迭代中积累的技术债。最后,在部署阶段,我们遇到了复杂的构建问题,通过与 AI 的多轮分析和尝试,最终定位并解决了问题,成功将应用部署上线。

六、典型案例

案例一:AI 驱动产品设计

没有产品经理、没有 UI 设计师,一个工程师如何用 AI 独立完成从产品定义到高保真原型、再到研发文档的全流程。

背景:

传统意义上,从 0 到 1 开发一个企业级知识问答平台需要三个角色:产品经理(需求分析 + 用户路径 + PRD)、UI 设计师(交互稿 + 高保真设计稿)、工程师(编码实现)。这个项目设计过程中,通过让 AI 在不同阶段扮演不同角色,覆盖了全部三个职责。

让 AI 扮演产品经理:

在 Rules 中植入「首席产品专家」Persona 提示词,将 AI 从工程师的「急于执行」模式切换为产品经理的「先想清楚」模式,与 AI 聊清楚我们想干什么。

让 AI 扮演 UI 设计师:

在 Rules 中定义设计规范,通过对话式生成逐页产出高保真 HTML 文件,而不是源码:

让 AI 生成研发可读的 PRD:

基于产品经理角色,将 HTML 设计稿作为上下文,最后生成精确到组件行为级别的 PRD:

案例二:SDD 驱动前端功能研发

在已有系统上增量交付一个完整功能模块,SDD 如何保证「增量」功能快速开发,并系统性提升前后端联调效率。比如其中有个SSD需求开发「定时任务管理」完整模块,并且对接 6 个后端接口。这是 SDD 工作流第一次被完整运用于新功能模块开发,也是验证「SDD + MCP」前后端联调提效的关键场景。

页面功能开发: opsx:new 到 archive,人工指令 < 10 条,AI代码占比100%,交付完整任务管理模块(独立路由 + 完整 CRUD + 执行记录 + 检索结果)。

前后端联调: SDD + MCP 的联调路径:接口 URL → MCP直连文档 → 一次性获取字段、枚举、必填项 →  接口文件一次生成 → ****联调一次通过,6 个接口零联调返工。

研发效率: 同日额外交付了两个完整模块,3个独立完整模块,单日全部开发完成,按纯人工开发,当天人效提升3倍。

案例三:SDD 驱动系统重构

重构与新功能的根本差异:

新功能开发是「从无到有」:AI 可以大胆生成,错了删掉重来。重构是「在活体系统上动手术」:这种高风险对 AI 执行提出了截然不同的要求——不仅要知道改什么,更要知道不能改什么,以及按什么顺序改。 SDD 的价值正在于此:在动代码之前,把这三件事全部写清楚。

知识问答首页重构:

架构债务: 大量首页业务组件与公共组件混放、useChat 导出 20+ 方法(4 种无关职责混合)、ChatInterface 接收 17 个 props(参数3 层传递)。

执行TASKS: 9 组 34 个子任务,从「grep 确认组件当前归属」→「按新分层迁移」→「更新所有 import 路径」→「tsc 类型检查」→「冒烟验证」,每一步有明确输入和验收标准。

执行结果: 34个任务全部完成(含 4 个验证任务),AI 全程独立执行,人工干预 < 5 条指令。7个业务组件与公共组件完成解耦,useChat 拆为 3 个单职责 hook,ChatInterface 从 17 个 props 缩减至 6-8 个。

案例四:复杂问题排障

并不是所有编程相关的问题AI都可以解决,哪类工程问题从结构上超出了 AI 的能力边界?这里举一个遇到的场景。

其中有一天遇到一个测试环境构建失败的问题,结果过程约 4 小时,7 个会话、15+ 次方案尝试、59 条指令。整个项目单日指令最多的一天,也是 AI 独立解决能力最受限的一天。

这一天有一个值得注意的特征:AI 每次分析都是正确的——问题不在于 AI 的分析能力不足,而在于问题的结构性特征超出了 AI 的信息范围和反馈机制:

  • 云服务器构建时发生,本地无法复现: 每次验证方案必须提交代码等待 CI(一轮约 10 分钟),AI 分析的是日志截图,无法感知「现在的 CI 环境还有哪些隐性配置」。
  • 多根因互相掩盖,解决一层才暴露下一层: AI 每次分析都正确,但正确分析的只是当前暴露的那一层,问题全貌无法被单次分析覆盖。
  • 隐性行为无文档,根因藏在依赖源码内部: Prisma postinstall 境外下载没有任何显式错误,引导AI 不得不深入阅读 node_modules 源码第 2319 行才能发现根因。这类「运行时行为藏在依赖内部、没有文档描述」的问题,超出了 AI 通过训练数据或当前上下文主动推断的范围。

最后确认的原因:

  • .npmrc 历史副作用: 早期为跳过 @next/swc-darwin-arm64 在 Linux 下载而加入的 omit=optional,无意间也跳过了 @tailwindcss/oxide-linux-x64-gnu(Tailwind v4 的 native binding),postinstall 陷入循环等待
  • Prisma v6 境外下载沉默卡死: AI 需要阅读 node_modules/@prisma/fetch-engine/dist/index.js 第 2319 行才能发现这个行为——postinstall 不报错、不超时,只是无限等待。
  • pnpm 跨平台 lockfile 不一致: macOS arm64 生成的 lockfile 不含 Linux x64 的 native package;切回 npm 则 lockfile 被忽略,安装结果每次不同。

最终解法(4 小时探索后得出):

七、代码规范落地:CLAUDE.md 和 Rules 的实际效果

规范体系设计思想:三层结构

本项目的规范体系是三个层次的协同约束, 每层解决不同的问题:

第一层:约束层(.claude/rules/)      ← 告诉 AI「禁止什么、必须怎样」
第二层:示范层(.claude/code-design/)← 告诉 AI「标准产出长什么样」
第三层:视觉层(.claude/ui-design/)  ← 告诉 AI「页面应该长什么样」

为什么需要三层?

只有「约束层」时,AI 知道规则但缺乏参考实现,容易在复杂场景下产生符合规则但不符合团队风格的代码。加入「示范层」和「视觉层」后,AI 可以直接对齐团队的标准产出,减少「虽然合法但不地道」的代码。

第一层:约束层(.claude/rules/)

7 个规范文件,分别约束不同维度:

.claude/rules/
├── ts.md          # TypeScript 规范(禁止 any、使用可选链等)
├── code-names.md  # 命名规范(kebab-case/camelCase/PascalCase)
├── comment.md     # 注释规范(JSDoc、@ai-context/@ai-rules 文件头)
├── lint.md        # 代码风格(单引号、文件末尾换行)
├── style.md       # 样式规范(Tailwind CSS、less 文件)
├── pages.md       # 页面目录结构规范(constants/services/hooks/components 分层)
└── service.md     # API 接口生成规范(fetch{Name}Api 命名、UniversalResp 泛型)

第二层:示范层(.claude/code-design/)

将项目常见场景预置完整的「标准模板代码」,AI 在生成新页面时可以直接参照,后续可以切换为skills:

.claude/code-design/
├── pro-table/          # 通用列表页模板(含搜索、分页、批量操作、行操作)
├── pro-form/           # 通用表单页模板(含创建/编辑双模式、字段验证)
├── editable-pro-table/ # 可编辑表格模板(含行内编辑、添加/保存/删除)
├── drawer/             # 抽屉组件模板(含标准打开/关闭逻辑)
├── compontent/         # 通用组件模板(含 README、Props 定义、使用示例)
└── utils/              # 工具函数模板

示范代码的作用不只是「看个格式」。以 pro-table 为例,当开发者让 AI「参考 .claude/code-design/pro-table 生成知识治理列表页」时,AI 直接继承了这套模式,一次就能生成符合团队风格的代码,无需多轮调整。

第三层:视觉层(.claude/ui-design/)

注意存放 HTML 设计稿,覆盖主要页面的视觉参考:

.claude/ui-design/
├── knowledge-spaces.html  # 知识空间列表页设计稿
├── search-strategy.html   # 检索配置页设计稿
├── space-detail.html      # 空间详情页设计稿
└── xxx设计稿

这些 HTML 文件可以直接在浏览器中打开预览,AI 也可以读取其中的结构和样式信息。实践中,提供 HTML 设计稿后,AI 生成的 UI 与设计意图的吻合度明显高于纯文字描述,尤其是布局结构、颜色方案、间距配置等细节。

规范约束的实际效果

正面效果(规范被遵循的案例):

  • 接口命名一致性: 所有接口函数均以 fetch{Name}Api 命名,类型以 I{Name}Req/Res 格式,整个项目 205 个文件保持高度一致。
  • 目录分层被遵守: constants/、services/、hooks/、components/ 分层在每个新页面中都被正确创建。
  • 代码模板被继承: CURD页面均参照了 pro-table 模板的 hooks 分离方式,代码结构高度一致。
  • 使用可选链: 几乎所有数据访问都使用了 ?. 和 ??,有效避免运行时报错。

需要人工干预的案例:

  • 2/24,AI 生成知识空间列表后,将所有代码写在单文件中,未按规范分层。通过一条追问后,AI 重构为正确结构。
  • 2/27,AI 错误地使用了 .less 后缀,但项目实际配置使用 SCSS,在收到错误提示后立即修正。
  • 出现 antd v5 废弃 API(destroyOnClose、dropdownStyle),AI 习惯于使用训练数据中更常见的旧 API,需要通过报警信息触发修正。

结论:

规范体系对 AI 的约束是有效的,但规范文件只是「约束」而非「能力」——只有「约束层」时,AI 知道不能做什么,但遇到复杂场景仍可能生成不够地道的代码;加入「示范层」和「视觉层」后,AI 有了对齐的锚点,输出质量和一致性明显提升。

八、MCP 工具:消除信息断层

在 AI 辅助前端开发中,有两类高频信息断层,在此项目中进行了接入:

接口文档断层: 接口文档在 API平台,AI 无法直接访问,只能靠用户手工复制字段,容易遗漏、版本不一致。需求文档断层: PRD、设计文档存在飞书云文档中,每次引用都需要用户打开→复制→粘贴到对话框,打断思路。

MCP 一:接口文档直连

通过该工具,AI 可以根据接口 URL 自动拉取完整接口文档——包括入参字段、出参结构、枚举值定义、必填项标注。累计被调用了 21 次,完成39个接口联调 ,覆盖了几乎所有接口的初次接入和更新迭代场景。服务端接口未生效之前,并且支持同步生成mock数据,减少后端依赖。interface.ts 类型定义质量非常高,字段注释完整,无需人工校对。

MCP 二:飞书云文档直读

通过该MCP工具,AI 可以直接读取飞书云文档的内容(PRD、设计说明、技术文档等),无需用户手工打开→复制→粘贴。

典型应用场景:

九、AI Spec Coding 经验总结

重新理解「AI 辅助编程」是什么

流行的说法是「AI 是你的 Copilot」。这个比喻在日常补全层面成立,但在 Spec Coding 实践之后,我更倾向于另一个模型:AI 是一个极度服从、无限耐心、但没有内部业务知识常识的「顶级执行者 」。

这个比喻捕捉了三个关键特征:

极度服从: AI 会一字不差地执行你写的规范,不会主动质疑「这样做合理吗」。这是优势,也是风险——规范写得越准确,执行越可靠;规范有歧义,AI 会选一个「看起来合理」的解释,而不是停下来问你。

无限耐心: 34 个任务的重构、9 组联调任务、跨会话的上下文恢复——这些在人类身上需要消耗大量意志力的事情,AI 做起来没有摩擦成本。本项目 208 次 TodoWrite 调用背后,是 AI 持续更新进度状态、从不嫌烦的特性。

没有内部业务常识: AI 不知道你们公司的部署环境是什么样的,不知道这个接口上周刚换过版本,不知道「这个交互做成这样用户会抱怨」。它只知道你告诉它的。这也是 3/4 生产构建排障花了大量时间的根本原因。

AI 的能力边界在哪里

从 10 天、2,754 次工具调用中,我们归纳出一个更精确的能力边界框架,而不是简单的「能做/不能做」:

真实项目中的并不是所有的需求都值得写一份 Spec。在真实的项目迭代中,我们需要根据需求颗粒度来选择协作模式。

小颗粒需求:对话框即扫即改

  • 场景:改个文案、修个显隐逻辑、调整 CSS 间距。
  • 策略:直接在 Cursor Chat  中对话。
  • 理由:沟通成本低于编写规范的成本,AI 的即时反馈效率最高。

中颗粒标准化需求:基于Rules 或者 Skills 预设规范生成

  • 场景:增加一个标准的 CRUD 页面、创建一个简单的业务组件。
  • 策略:利用预设的 Cursor Rules 或 Skills(如 pro-table.mdc)。
  • 理由:这类需求有强烈的“模式感”。只要规则定义清晰(如“执行流程:识别场景 -> 读取示例 -> 生成类型 -> 完成 UI”),AI 就能基于标准化模板高质量输出。

中大颗粒复杂功能:OpenSpec 深度协作

  • 场景:重构核心逻辑、新增带有复杂业务逻辑的模块、无参考代码的新功能。
  • 策略:OpenSpec 标准流 (SDD)。
  • 理由:业务逻辑复杂时,AI 极易产生幻觉或需求偏移。通过 Spec 强制进行“先设计后编码”,可以确保 AI 的每一步都在既定轨道上,且 Spec 记录了设计的决策过程,对于后期维护价值巨大。

AI 失效的三种模式

经过本项目的实践,AI Coding 的失效不是随机的,而是可归类的:

模式一:规范真空

任务涉及的领域没有规范约束,AI 自行填充「合理默认值」。

  • 表现:生成的代码功能正确,但风格/结构偏离团队约定。
  • 发生频率:高(尤其在新功能开发初期)。
  • 应对:在 CLAUDE.md 或 code-design 中补充对应规范,一次修复,全局生效。

模式二:信息孤岛

AI 掌握的信息是当前会话的快照,看不到系统外的状态。

  • 表现:本地正常,CI 失败;AI 分析每次都对,但解的都是当前暴露的问题。
  • 发生频率:低,但代价高。
  • 应对:跨平台、跨环境的依赖要在架构设计阶段提前锁定;环境差异要写成规范前置处理。

模式三:任务目标模糊

AI 把「该问人的问题」当成「执行问题」来解决。

  • 表现:用户说「优化一下首页」,AI 悄悄改了组件结构,而不是先澄清目标。
  • 发生频率:中。
  • 应对:Spec 工作流的 proposal 阶段强制要求先描述「Why」,避免 AI 自行填充目标。

开发者角色的重构

AI Coding 不是让开发者「消失」,而是让开发者的工作向上迁移:

这意味着:

规范设计能力成为 AI 时代开发者的核心竞争力——能写出让 AI 可靠执行的规范,价值比能写出同等功能代码更高。

系统性思维变得更重要——生产构建问题的排障经历说明,AI 可以帮你解决每一个局部问题,但无法帮你看到真实业务全局。

质量意识前移——过去 Code Review 在代码写完后进行,现在需要在 方案设计/任务执行 阶段就介入,而不是等 AI 执行完再纠错。

值得期待的方向

基于本项目的数据和经验,后续在以下方向可作深入探索:

规范体系的结构化积累: 每次踩坑后补充到 CLAUDE.md/rules,形成团队共享的「AI 执行约束库」。目前 7 条规范文件是手动维护的,下一步可以建立「踩坑→提炼规范→自动追加」的闭环。

MCP 工具链的纵向延伸: 本项目 MCP 仅覆盖了接口文档、飞书文档。后续针对设计稿、测试用例、发布平台、日志平台接入,可以进一步形成完整的AI Coding链路。

多 Agent 并行开发: 本项目开发过程中,发现大型任务执行等待时间较长,下一步可以尝试多Agen并发生成,同时开发不同功能模块。

一句话总结

AI Coding 的本质不仅仅是用 AI 写代码,而是用结构化的规范和工作流把不确定性消除在执行之前——AI 负责在确定性空间里高速执行,人负责维护和扩展那个确定性空间的边界。

10 天、217 条指令、2,754 次工具调用、25,546 行净增代码——这个数字背后,是一套让 AI 可以「看见」、「理解」、「遵守」团队约定的规范体系。规范是杠杆,AI 是力,Spec 工作流是支点。

本报告由claude code基于claude code 109 个真实历史会话、2,754 次工具调用记录生成,人工补充并校准,数据来源:~/.claude/projects/-Users-admin-Desktop-code-knowledge-qa/。

往期回顾

1.搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术

2.得物社区搜推公式融合调参框架-加乘树3.0实战 

3.深入剖析Spark UI界面:参数与界面详解|得物技术

4.Sentinel Java客户端限流原理解析|得物技术

5.社区推荐重排技术:双阶段框架的实践与演进|得物技术

文 /阳凯

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

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

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

搜索 C++ 引擎回归能力建设:从自测到工程化准出|得物技术

一、为什么要做这件事

在搜索系统中, C++ 引擎长期扮演着底层核心基础设施的角色:性能敏感、逻辑复杂、变更频繁,同时承载着大规模线上流量的稳定运行。随着业务持续发展和技术架构不断演进,我们逐步意识到:在高频迭代背景下,回归能力也需要同步升级。

过去一年,我们围绕搜索 C++ 引擎展开了一次系统性的回归能力工程化建设。本文将介绍这次能力升级的背景思考、核心设计思路以及落地实践。

高频迭代背景下:回归能力需要同步升级

搜索 C++ 引擎的升级主要来自三类需求:业务功能需求、重要技术项目(有 QA 深度参与)、大量技术优化与结构性改造需求。

在实际迭代节奏中,技术优化与结构性改造类需求占比较高,引擎整体呈现出多人并行开发、持续迭代推进的状态。随着规模扩大,我们发现:现有回归环境更适用于单次项目式验证。多需求并行时,资源调度与复用能力仍有提升空间,回归准出标准尚未完全工程化。这意味着,在稳定性要求不断提升的背景下,我们有必要构建更加标准化、流程化的回归体系,让质量保障能力与迭代节奏匹配。

现有测试方式的演进空间

当前搜索引擎主要依赖两类测试手段:DIFF 测试和压测,这些手段在长期实践中发挥了重要作用,但随着业务复杂度提升,我们也逐步看到进一步优化的空间:流量获取依赖下载日志、手工上传,自动化程度仍可提升。DIFF 过程中存在自然噪音。需要更精细化处理(AA DIFF、排序不稳定)。报告与分析信息分散在不同工具中,定位效率有优化空间。多套工具并行使用,缺乏统一平台化沉淀。整体来看,测试能力更多体现为“工具能力集合”,而在流程标准化、资产沉淀与统一治理方面仍有提升空间。

二、我们要解决什么问题

这次建设的目标,并不是简单“再做一个工具”,而是希望系统性解决以下问题:让 DIFF 和压测成为搜索 C++ 引擎的标配回归能力、让回归结果具备可分析、可归因能力、让回归成为发布的硬性准出标准、保证工具本身的稳定性,不成为新风险、整体提升引擎的回归效率和交付质量、通过流程和流水线,降低对“人”的依赖。一句话总结:把回归这件事,从“靠自觉”,变成“靠系统”。

三、整体方案概览

围绕上述目标,我们将建设拆分为五个关键方向:流量录制:一次录制,多处复用。环境建设:稳定、可复用的 DIFF/ 压测环境。DIFF 工具体系:从“能跑”到“好分析”。一键压测能力:降低执行门槛。工具与索引平台集成:让回归真正被用起来。

下面将会按模块展开说明。

流量录制:回归的基础设施

为什么先做流量录制

DIFF 和压测的核心前提只有一个:真实、稳定、可复用的流量。因此我们优先建设了搜索 C++ 引擎的流量录制链路,作为后续所有测试能力的基础。

流量如何触发

  • 索引平台集群详情页直接发起流量录制。
  • 索引平台更新 ARK 配置中心中的录制配置。
  • 搜索 C++ 引擎实时监听配置变化。

录制配置设计

所有配置统一收敛在 dsearch3#test.properties,支持:

  • 全局开关。
  • 指定 app / group。
  • 截止时间。
  • 指定 IP。
  • 采样率(0~100)。

这使得录制行为可控、可回收、可精细化管理。

流量生成与存储

  • 引擎侧根据配置生成 Kafka 消息。
  • 多业务场景复用同一 ARK 集。
  • 多场景流量复用同一个 Kafka Topic。

最终流量落入 ODPS,按天分区,字段包含:

  • 请求体。
  • 流量场景。
  • 实验信息。
  • 环境信息(生产 / 预发)。

这为后续 DIFF、压测、问题复现提供了统一数据源。

流量存储字段说明:

request_type:流量标签(原C++引擎请求类型)
app_name:C++引擎appName
group_name:C++引擎groupName
request_body:录制的C++引擎请求体
env:录制的流量环境:预发/生产
graph_name:图名称
experiments:实验列表(搜索新增)
pt:ODPS分区,按天分

DIFF 测试:从无到“可归因”

DIFF 执行流程:

DIFF 的入口统一在索引平台:查询流量 →选择流量→配置参数→触发 DIFF→查看报告。底层由测试服务 + 脚本完成:流量筛选与改造、请求转发、去噪、报告生成与存储。

DIFF 对比方式:

对照组部署 master 分支,实验组部署预发布分支。指定行或者指定集群方式请求对照组和实验组环境。打开新功能开关进行响应比对,生成预期有DIFF报告。

DIFF 环境设计

支持两种模式:

  • 指定集群:对照组 / 实验组两套完整集群。
  • 指定行 精确绑定 search / rank IP。

通过该设计,保证对比的唯一变量只有代码和配置。

流量筛选与回放改造

支持多维度筛选:

  • 搜索场景(交易 / 社区 / 聚合等)。
  • 流量标签(综合 / 销量 / 新品等)。
  • 实验命中情况。

同时解决了生产流量无法直接在预发回放的问题(表名、图参数、模型等适配)。

DIFF 策略设计

我们不只关注“有没有 DIFF ”,而是关注这个 DIFF 是否符合预期,因此 DIFF 被拆为两类:

响应 DIFF
  • 响应字段对比。
  • 漏斗算子字段对比。
指标 DIFF
  • 相似度分布(忽略/不忽略排序)。
  • 漏斗算子一致率。
  • 字段增删改统计。
  • 定制化指标。

DIFF 去噪

DIFF 不可用,往往不是因为“真问题”,而是噪音太多。我们重点处理了:AA DIFF(排序不稳定、非确定性逻辑)、可忽略字段、数值微小波动、内部超时导致的异常结果,目标只有一个:让开发看到的DIFF,尽可能都是真问题。

DIFF 报告设计

报告展示

DIFF 汇总报告:

  • 应用、集群、请求接口、流量标签、路由信息、对比数量、DIFF 数量、完全一致率、query_tag 平均召回数、score 平均分等。
  • 相似度分布统计报告(不忽略排序/忽略排序)。
  • 漏斗算子一致率统计报告。
  • 字段增删改统计。

DIFF 详情报告:

  • traceId、一致率、增删改字段、请求体等。
  • 漏斗算子 DIFF 明细。
  • 响应 DIFF 明细。
报告通知

通知到群 @个人,添加报告链接。

压测:一键完成性能回归

压测执行流程:

  • 索引平台作为压力测试发起入口,查询流量->选择流量->填写压测参数->压测触发->压测记录查看。
  • 测试服务提供索引平台操作的接口能力,查询流量->流量筛选->压测文件生成->压测任务触发->压测状态更新。
  • 压测平台提供实际压测能力,启动压测任务->生成压测报告。

整个过程无需人工干预。

执行方式:

  • 对照组:master 分支。
  • 实验组:预发布分支。
  • 开启新功能开关。
  • 阶梯式加压,对比性能曲线。

压测环境设计

同 DIFF 环境建设。

压测报告设计

报告展示

压测平台报告。

报告通知

通知到群 @个人,添加报告链接。

发布流水线与准出机制

回归能力建设的最终目标,是进入发布流程。当前已完成:UT / MR 流水线初步建设,后续规划中将:把 DIFF 和压测作为发布硬性卡点、回归不通过,禁止上线、回归过程自动扩缩容,避免长期占用资源、自动生成准出报告。

四、后续规划

回归执行率 100%:解决“忘跑回归”。

准出流水线全自动化。

横向覆盖更多搜索场景(流控、商业化、国际搜索等)。

形成统一的上线 SOP 规范。

五、总结

搜索 C++ 引擎回归能力建设,并不是一次“工具升级”,而是一场工程化治理:把经验变成流程、把自觉变成约束、把风险前移到上线之前,最终目标只有一个:让搜索引擎的每一次升级,都更可控、更可信。

往期回顾

1.得物社区搜推公式融合调参框架-加乘树3.0实战

2.深入剖析Spark UI界面:参数与界面详解|得物技术 

3.Sentinel Java客户端限流原理解析|得物技术

4.社区推荐重排技术:双阶段框架的实践与演进|得物技术

5.Flink ClickHouse Sink:生产级高可用写入方案|得物技术

文 /耿辉

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

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

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

得物社区搜推公式融合调参框架-加乘树3.0实战

一、背景简介

近年来,搜索/推荐/广告系统在粗排(Pre-ranking)与精排(Ranking)阶段的模型训练中,呈现出一个明确的趋势:从单目标优化转向多目标建模 + 多目标融合。模型目标多、融合公式复杂,给工程维护、算法迭代效率都带来了挑战。

为了明文化直白展示公式全景、方便决策调参方向,直接配公式、线上自动算(既支持精排预估目标融合、也支持业务条件boost)。我们设计并落地了加乘树调参框架。从1.0优化至3.0,我们提供了:一个调参框架(Java版、同时引擎基建同学落地了C++版)能支持不同算法环节“公式即配即用”,一个打通AB实验的一站式产品化平台,支持一站式“辅助配置->调试->开实验->变更管控”。

带来收益:无论是粗排还是精排,“训多目标、融公式” 已成为工业界标准范式。在得物社区搜索、推荐的模型迭代实践中,我们也确实走“模型多目标训练 + 融合公式调参”范式,2025在社区推荐、社区搜索落地了几十次LR(社区推荐内外流精排、粗排,社区搜索精排)、近百次加乘树推全。

二、即配即用:算法爆发的催化剂,工程稳定的绊脚石?

在算法领域,“即配即用”的工程框架多次成为推动算法快速迭代甚至“爆发式增长”的关键基础设施。面对粗、精排“多目标建模 + 多目标融合”这一建模范式,社区算法和工程提出了如下基建目标:

即配即用提人效: 实时调整配置、线上就能自动生效数学逻辑,使算法工程师从过去几天才能完成一次调参,转变为一天内可进行多次迭代,从而将精力集中在模型和融合公式本身。

全量配置+增量配置范式: 实验只配要改的几行,降低配错风险。全量配置不动,形成天然降级能力。

DSL可解释性强: 粗、精排的融合公式配置量大,数学变换复杂,容易配错。我们提供的DSL让算法同学直接写数学公式/逻辑表达式。明文公式形成策略全景,方便算法同学决策调参方向。

编译校验与降级体系筑牢稳定性防线: 即配即用+数学公式DSL的需求,给工程稳定性带来极大挑战。我们采用“编译语法校验 + 自动用全量配置降级 + 手动切换编译/解释模式”三位一体保障稳定性。

三、可信赖底座:让复杂公式配置既灵活又可靠

全量配置+增量配置范式

传统的KV、JSON 或 YAML等配置格式在面对上百行数学公式时已显乏力:一方面配置体量大、人工修改易出错且缺乏容错机制;另一方面可读性差,难以维护和审查。

我们采用“全量配置+增量配置”的设计,天然解决了使用门槛&自动降级问题:

  • 只配增量,让使用更轻松、出错更可控: 全量配置锁定为只读,确保基线稳定;算法同学只需声明需要新增或修改的增量配置(upsert)。系统在运行时将增量动态合并到全量配置中,生成最终生效的实验配置——既简化了操作;又避免了误改全局参数的风险。
  • 增量可试,基线兜底: 增量配置有误,自动回退至基线,形成天然降级机制。

给一个社区搜索主搜精排的样例:

DSL接近数学公式/逻辑表达式明文

社区搜索、社区推荐的精排融合公式,服务了“多目标融合+业务boost调权”,语义包含:数学变换、逻辑判断、自定义UDF。当算法写下一串sin(log(max(UDF(x), y))),框架能否接住?框架必须托底,正确校验与执行,杜绝“配错即崩”。

从加乘树1.0到3.0,公式解析统一选用 ANTLR。相比手搓“逆波兰表达式”或“Flex & Bison”,它基于AST校验更可靠,且Java开发门槛低。实际加乘树的配置结构里,公式按KV配置(Key 为结果名,Value 为表达式),支持跨行引用——前序公式的输出可作为后序公式的输入,形成可串联的计算链,直至得出最终结果。

  • 公式链转DAG: 在加乘树3.0中,有相互依赖关系的多行公式,被框架解析成DAG。每个item都通过这套DAG计算融合分,1个item可能有多个融合分、每棵DAG的根结点对应1个融合分。
  • AST驱动逐行校验: 每行公式都依托编译原理,校验&解析为抽象语法树(AST)。结构化的AST可支撑后续可靠计算。
  • 加乘树3.0把DAG和AST直接翻译成代码: 框架将公式链直接翻译成可执行代码,用字节码技术加载到JVM中。每个item直接计算即可。

编译校验与降级体系筑牢稳定性防线

即配即用给算法同学迭代提效带来便利,同时给工程维稳带来挑战。尤其加乘树面临的配置是可自由组合、千变万化的数学公式时,绝对不能出现“配错即崩”的情况。我们做了如下一整套安全设计:

  • 编译原理强校验: 如何应对无限组合的公式配置?加乘树选择了编译原理强校验,用了ANTLR框架,把公式校验&解析成严谨的可访问结构(AST)。
  • DAG强校验公式链: 加乘树3.0初始化阶段自动解析公式链间的依赖关系,一边将公式链解析成DAG、一边强校验。能通过校验、最终编排成DAG的公式,才会进入实际计算;不能通过校验的危险配置(漏配公式、公式配错)都会在初始化阶段就被拦截,不会进入实际计算。
  • 自动降级范式: 加乘树设计了一套自动降级范式,方便“前置拦截错误、事中有效托底、后置发出告警”。一旦有错误的实验开流量,加乘树初始化阶段就会校验出错误,当次请求忽略AB实验配置、直接用全量配置计算,并及时发出“实验配置有误”的告警。
  • 串行重算托底: 如果有“编译原理校验”、“DAG校验”没有校验出的意外怎么办?如果框架仅仅是高峰期计算超时失败了怎么办?加乘树最后一层安全托底是“用全量配置串行重算”。无论如何保证线上效果。

四、核心攻坚:加乘树3.0升级编译执行

加乘树2.0在社区搜索落地后,“每次请求3000个item、线程并发拆的多”的情况,暴露出加乘树耗CPU、耗线程的弱点。C++版加乘树替换了计算引擎,没有采用antlr visitor解释执行数学运算的方式,而是用exprtk框架、收获了更高的性能。

受C++版加乘树的启发,我们计划替换Java版加乘树的计算引擎,降CPU消耗、降执行平响。加乘树3.0变成“直接将配置翻译成代码,字节码加载,直接计算”的编译执行形态。

极致性能:配置直译硬代码,零中间损耗 + 最优 JIT

Antlr翻译&Javassist加载,直接“公式翻译成可执行代码”: 包括多行公式的依赖关系、数学计算&UDF调用,直接拉平成硬代码。硬代码执行效率最高,没有map缓存、递归调用栈等损耗。

多行公式传递中间结果,map换POJO: 每个item维护自己的缓存map,高并发put/resize,造成明显的CPU消耗、youngGC压力。本次会初始化时决策缓存POJO,避免resize、且读写更高效。

核心Javassist管理类借鉴Dubbo写法: Dubbo的ClassGenerator写法,对内存管理考虑比较完善。本次借鉴ClassGenerator,把动态生成代码收入唯一管理单例类。

性能收益

晚高峰模块平响、CPU火焰图消耗和内存分配火焰图消耗均显著降低。

典型踩坑

字节码加载不容忍语法糖:

动态生成的字节码必须严格遵循JVM 范,平时习惯手写的Java法糖是不容忍的。例如,Float a = (float) b; 在源码中合法,但若b是Double类型,该语句涉及拆箱 + 窄化转换 + 装箱,而字节码层面需显式插入doubleValue() → (float) cast → Float.valueOf() 等指令。若直接按表面类型生成字节码,将触发VerifyError。

OOM在多处需要关注:

Javassist使用不当容易OOM:Javassist 在生成和操作字节码时(如通过 CtClass),因为其缓存机制,需要开发者主动管理资源释放。每次parse字节码的CtClass要及时释放,否则高频生成字节码容易触发OOM。这一点上,加乘树参照了Dubbo的ClassGenerator写法,创建、销毁内聚在同一个类里,即用即释放。

动态生成ClassLoader/Class/Instance要能GC:Instance能GC,ClassLoader/Class能GC吗?答案是能,只有从ClassLoader -> Class -> Instance全链路都GC Root不可达了,这一串才能GC。所以用Spring的ClassLoader这类常驻ClassLoader加载动态生成类是不行的,必须用即用即弃的自定义ClassLoader,并注意全链路的强引用问题。

我们实际验证了动态生成的类确实能被GC掉。

多重护航:防止非法Java字节码引发线上问题

ASM + Javassist双重检验: 翻译生成的代码,经Javassist生成字节码后,除Javassist .toClass()的自检验,我们还让字节码过了ASM的字节码静态校验(会运行类似JVM的类型推断验证,确保每条指令执行前后,局部变量表和操作数栈的状态是类型安全的)。

沙箱加载: 我们将加乘树管理平台封装成了一个沙箱,算法同学调试公式点击“校验”,平台会用同一套SDK模拟线上全套加载流程:“AST强校验 -> DAG强校验 -> 真实翻译代码 -> Javassist & ASM 双校验 -> 反射调用构造器创建实例”,一整套无误后才往线上推配置。

线上异步加载,任何问题自动降级: “可执行代码(执行器)初始化”读写分离,新配置上线是异步刷新,刷新错误只会造成线上流量过来找不到执行器,自动降级走全量配置(并发出告警),不影响效果。

可回退解释执行: 加乘树2.0、1.0的解释执行能力十分稳定、只是性能略差,3.0可以一键回退解释执行。

加乘树管理平台:一站式配置、调试与实验平台

面向算法同学: 做了一套一站式“辅助配置->校验->实时调试->开实验->变更管控”的使用体验,告别繁琐配置、体感更丝滑。

面向系统稳定: 加乘树管理平台把自己封装成了一个沙箱,如上一个模块所述,一切风险都拦截在沙箱爆炸。

五、稳扎稳打:从1.0到3.0的演进

加乘树1.0: 支持配公式、框架直接算公式,支持UDF,解释执行。加乘树2.0: 少量性能优化,抽象成SDK。加乘树3.0: 升级为编译执行,外观简化为只需要配公式、框架自动解析DAG。

加乘树1.0和2.0都是用的解释执行,antlr visitor遍历AST做“数学/逻辑/if判断”运算。加乘树3.0升级成了编译执行,多行公式解析DAG、每行公式用antlr解析AST时,直接翻译成Java执行代码,用字节码技术把执行代码加载进JVM直接执行。同时加乘树3.0也支持降级至解释执行。

加乘树1.0

解决:落地即配即用公式,解决手搓硬代码迭代效率低、代码腐化导致生效逻辑不清晰的问题。缺陷:费线程&CPU。

加乘树1.0于2025年1月在社区推荐外流精排落地,配法(使用外观)、降级机制是后续迭代不变的:

  • 配法:1): “全量配置+叠实验改动”的配置机制 2)配置总共分 consts(输入物料)、paramBranch(条件分支替换参数)、formulas(公式)、root(融合结果字段名)。
  • 降级机制:1): 初始化阶段就检测公式配错、漏配公式等,一旦检出就自动降级走全量配置、并发出告警 2)少量运行时才能发现的问题,串行重算、降级算全量配置。

当时是从手搓硬代码做公式融合,无DIFF迁移过来,解决了如下2个迭代痛点:

  • 迭代效率: 除调参是可配,调公式形态、调生效条件等都需要开发&上线。
  • 逻辑黑盒: boost、融合公式迭代复杂之后,生效逻辑变得黑盒,不容易分析调参方向。

加乘树1.0的实现要点

纯item维度(请求维度的公式也会每个item重复计算)。consts->paramBranch->formulas串行计算。antlr解析单行公式成AST,框架递归解析树依赖,antlr visitor解释执行。

为什么用antlr

DSL语法校验: 我们需要一种配置设计,能尽可能简洁地表征模型融合公式(支持逻辑判断/复杂数学变换/UDF)——接近Java语法&数学公式的DSL(当时有对标字节的配置外观)。我们需要准确校验DSL配置正确、并正确解析DSL配置——在antlr、手搓逆波兰表达式、flex&bison里,选了用antlr校验、解析DSL(用AST校验原理可靠,Java上手难度低)。

antlr visitor解释执行: 依靠AST解析计算是一种可靠的计算逻辑。我们需要稳定靠谱的计算引擎,因为算法同学大规模使用后、会出现大量千变万化的公式组合——依靠AST解析计算是一种可靠的计算逻辑。

类SIMD设计使性能可接受: antlr解析AST非常耗时,必须一次parse多次复用,不能在item维度重复parse。一般用antlr visitor做线上实时计算,性能是不可接受的。我们采用了一种类SIMD的代码写法,使落地性能可接受——类SIMD的设计,一次antlr visitor算一批item。最终落地的性能、没有因为antlr visitor拖过多后腿,性能比旧版硬代码融合公式还要好。

antlr语法定义文件

antlr visitor如何通过访问AST计算1行公式

加乘树2.0

解决:抽象成SDK;执行计划自动识别请求维度公式、便于序融合等逻辑写UDF。缺陷:受限于解释执行,仍然比较耗线程。

加乘树2.0于2025年9月在社区搜索落地。优化点如下:

  • 使用体验: 配置json结构简化,只需要配递归的一组公式即可(砍掉了consts、paramBranch)。if()的配法简化:旧版编译器设计的简单,将 “logic表达式”与“math表达式”分别放在2个编译器里,使用者不允许if里嵌套函数,加乘树2.0合并了编译器,if()里可以嵌套函数。支持“隐式item正排”。

  • 性能: 框架自动识别Req维度的公式,全局只计算1次。执行计划加缓存,砍掉“每次请求都重新build执行计划”,平响降低。
  • 横向扩展: Java版加乘树抽象为SDK,方便扩场景直接引用。

加乘树3.0

解决:升级为编译执行,性能大幅提升。

加乘树3.0于2026年1月在社区搜索落地。之前“核心攻坚”模块有提到,高并发&计算量大的情况下,暴露出加乘树耗CPU、耗线程的弱点(类SIMD设计虽然能让性能可接受,但毕竟antlr visitor计算方式需要升级)。

加乘树3.0替换了执行引擎。我们观察火焰图发现“按公式逻辑直接裸写的java代码”性能最高效,但是迭代效率最低。加乘树为了即配即用公式,性能却打了折扣。为了平衡“即配即用”的迭代效率问题和“性能”,我们“将配置公式直接翻译成可执行代码,用字节码技术加载到JVM中直接计算”,这让加乘树从解释执行升级为编译执行。

六、还能更好

多语言 & 模块化: 加乘树有Java版,同时有C++版,是引擎同学创新实现的另一个高性能版本。支持多种业务场景及模块(如粗排、精排),可灵活接入 Java 业务引擎或 C++ 高性能引擎。欢迎其他场景和模块接入。

稳定性 & 产品化: 重点打磨“加乘树管理平台沙箱拦截 -> 线上容错降级 -> 失败监控告警发现 -> 解释执行托底” 的有效性,定期演练降级、验证算法效果。增强“加乘树管理平台”DIFF能力,扩展展示“调试DAG”、“可DIFF动态生成的代码”,打通实时debug平台,可以“DAG展开看计算的中间结果”。

多层公式组成DAG(打磨中)

配置生成的可执行代码做DIFF(建设中)

打通模型调用自动化: 在加乘树这里打通精排模型调用,对精排模型的调用也高度抽象,一配即用、一配即可加入公式融合。

往期回顾

1.深入剖析Spark UI界面:参数与界面详解|得物技术

2.Sentinel Java客户端限流原理解析|得物技术

3.社区推荐重排技术:双阶段框架的实践与演进|得物技术

4.Flink ClickHouse Sink:生产级高可用写入方案|得物技术

5.服务拆分之旅:测试过程全揭秘|得物技术

文 /啊俊 风林 益嘉

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

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

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

❌