TRAE MCP 实践:如何让 LLM 准确生成业务表单代码

204 阅读25分钟

本文作者:张天宇,TRAE 开发者用户

写在前面

随着 AI 技术发展,大语言模型(LLM)已成为提升开发效率的利器,尤其擅长处理代码补全、重复逻辑生成等标准化工作,能显著降低人工成本、加快开发节奏。但 LLM 在需求开发全流程中存在局限:缺乏全局视角,仅聚焦当前生成任务,难以关联已有业务逻辑与架构规范,也无法预判对现有代码的兼容性影响。长期依赖易导致代码仓库混乱、冗余,增加维护成本。

因此,LLM 辅助开发需要人工介入把控:将开发流程拆分为目标明确、边界清晰的小步骤,让 LLM 在限定范围内逐步参与,既发挥其优势,又通过人工把控步骤衔接与代码兼容性,最终平衡效率与代码质量。

探索背景

我所在的商业平台团队负责建设广告投放平台,广告主可通过平台自主创建并投放广告计划以实现营销目标。“创编页面”作为核心载体,是一套承载复杂业务逻辑的表单系统(涵盖广告信息配置、定向筛选、出价设置、素材校验等),其功能与易用性直接影响广告主投放效率。

日常业务迭代中,创编表单相关需求高频出现:既有字段修改(如新增定向维度),也有新场景专属表单创建(如短视频广告表单)。这类需求虽场景相似,却需重复处理字段校验、逻辑关联、UI 适配等工作,既耗费人力,也易因重复劳动产生错误。

基于此,本文结合实践,以创编表单为切入点,探索引入 LLM 生成代码的方式,旨在辅助开发人员提升创编表单开发效率、降低重复开发风险,为业务高效迭代提供实践思路。

整体思路

由人工将 PRD 拆解,梳理为技术文档,将技术文档的片段分步骤输入给 LLM,配合 MCP 让 LLM 逐步生成代码,结合 TRAE 的代码审查能力,完成需求开发。

1. 由研发编写特定格式的技术文档

为什么是特定格式的技术文档?

  • 现有的研发技术文档没有统一规范,书写风格也因人而异,因此无法作为标准输入给到 LLM。因此,需要规范输入的格式,来保证较为理想的输出效果。

  • 开发人员需要对需求进行拆解与编排,保证 LLM 的生成效果。

2. 编写特定功能的 MCP,帮助 LLM 扩展上下文

LLM 的训练数据总是有限的,无法囊括超过过截止日期的的新生数据,也无法囊括一些私域数据。因此,我们需要在模型推理阶段将新的知识输入到模型的上下文中,然后模型通过充分利用其本身的上下文学习能力去完成代码输出。

3. 分步骤生成代码

为什么分步骤生成代码?

  • 单个需求内容过多,LLM 容易产生一步错步步错

  • 分步骤可以让 LLM 每次都有获取足够上下文,避免空中楼阁式代码生成

  • 开发者可以及时干预生成结果

实现细节

让 LLM 了解如何生成表单代码

目前我们使用的创编表单方案是一个基于 Formily 的上层封装方案,可以简单理解为是一个强化表单物料写法的表单方案。

最初的做法是将表单已有的使用文档转化为 Markdown 格式,直接添加到 TRAE 的上下文,让 LLM 了解表单的使用方法。

这种使用方式有很大的弊端,一方面是封装后的表单的文档其实会经常性发生变更,以单一文件存储,不方便维护与共享,二是,单一的文件会造成 LLM 抓不住重点,无法按预期生成代码。

因此,有了第二版的方案,单独创建一个 MCP 仓库来维护表单的使用文档,同时以 MCP Tool 的形式,向 LLM 按需提供表单使用文档及 demo,让 LLM 能够更准确的生成可用的代码。

这个业务表单方案 MCP  目前有提供三个 TOOL:

工具名称描述备注
QuickStart可以获取如下信息:1. 表单的基本介绍、使用引导。3. 表单的主要 API 的介绍。4. 推荐目录结构设计。主要是为 LLM 提供对业务表单的最基础认知的入口文件
BasicUsage获取业务表单方案的主要 API 的使用方法及示例主要是提供单一 API 的详细描述以及示例
Example获取 业务表单方案 的示例代码获取一个文正的示例代码

目前的业务表单方案 MCP 结构

LLM 使用 业务表单 MCP 效果

可以看到,LLM 可以根据需求按需查看 业务表单方案 的使用方法。

这个环节的核心难点在于,如何消除因自然语言描述文档引发大语言模型(LLM)理解歧义,进而导致生产效果出现显著差异的问题。在实际落地过程中,需要依据代码生成效果,持续迭代调整 MCP 返回的文档内容,这一步骤在人力与时间上均消耗了较多成本。

创建的 MCP 可以手动添加到 TRAE 中:

2. 编写技术文档

技术文档的本质就是需求文档的的结构化描述,帮助研发同学理清需求细节,梳理研发流程。理论上只要格式是有规律的即可,LLM 都可以很好的理解技术文档中的需求点并完成代码生成。但是在使用特定工具或者框架的时候,需要规范描述用语,防止 LLM 理解产生歧义。

本文用来探索的需求是全店推广需求中的创编需求部分,为千川平台全店推广场景开发一套独立的小型创编表单,就是下面这个样子。

本需求的技术文档需要如下准备工作:

1. 梳理表单用到的所有字段

  • 包含字段的所有类型、初始化逻辑、提交逻辑、联动逻辑、校验逻辑等

2. 梳理现有可用的物料

  • UI 组件、枚举、工具函数等

3. 将上述所有内容结合需求点拆解为多个步骤,交给 LLM 去生成代码。

在探索过程中,直接将拆解后的技术文档保存在代码仓库中,方便添加到 TRAE 的对话框中使用。

具体文档内容见下文代码生成章节

为保障 LLM 代码输出效果与准确性,技术文档中引入了 业务表单方案 的特定概念。这虽会带来一定的理解成本,但仍是当前阶段最直接有效的解决方案。

3. 使用 TRAE 分步骤生成代码

步骤拆分的逻辑大致如下:

1. 先分步骤将表单的框架搭建出来,将所需要的字段填充进去

  • 此步骤会先将部分逻辑代码留空或者使用替代逻辑占位

2. 将表单布局进行调整

3. 将已有的物料应用到表单中

代码生成验证

目前采用人工方式确认生成效果。后续可建设自动化流程提升效果效率。

技术文档

 ## 需求
基于业务表单方案实现一个表单。

你需要为个表单搭建最基础的能力,包括表单的提交,字段配置,表单渲染等。

每个字段的所有相关物料都需要收敛在相同的目录下,方便后续的维护。

为表单初始化一个 SubmitFn 函数,用于表单提交。这个函数直接打印出来表单的值即可。

这个表单有如下字段:

### 推广抖音号 awemeInfo
#### Model 物料
类型是 object,数据结构如下

```json
{
    "userId": "1111",
    "nickName": "千川大客版自动化测试账号企业店",
    "avatar": "https://p11.douyinpic.com/img/aweme-avatar/aweme_default_avatar.png~c5_168x168.webp?from=3782654143",
    "showId": "22222",
    "authRole": 1,
    "userTypes": [
        3
    ],
    "hasShopPermission": false,
}
```

#### Initializer 物料
使用一个异步函数模拟,直接返回上述 json

#### Transformer 物料
直接返回字段值本身即可

#### Component 物料
为字段生成一个vue组件,支持支持展示抖音号头像以及昵称

### 推广店铺 shopInfo
#### Model 物料
类型是 object,数据结构如下

```json
{
    "shopName": "资管文具礼品专营店",
    "shopId": "111",
    "shopImg": "https://p3-ecom-qualification-sign.ecombdimg.com/tos-cn-i-6vegkygxbk/fbe26f8d1316487d86b20f72f70e02fe~tplv-6vegkygxbk-s:750.image?lk3s=c08c0450&x-expires=1778687541&x-signature=YsxT9Ywn8QM%2B2HRJuDMzf9UFdVI%3D",
},
```

#### Initializer 物料
使用一个异步函数模拟,直接返回上述 json

#### Transformer 物料
这个字段不参与表单提交,不需要 Transformer 物料

#### Component 物料
为字段生成一个vue组件,支持展示店铺图片以及店铺名称

### 排除商品 blockProductList
#### Model 物料
类型是 Array<string>

#### Initializer 物料
这个字段不需要单独的初始化物料,直接使用静态默认值即可,默认值是个空数组

#### Transformer 物料
直接返回字段值本身即可

#### Component 物料
为字段生成一个vue组件,只需要展示如下文案:
系统将为您自动投放店铺的可投潜力商品,默认开启智选素材。您可以选择排除无需投放的商品:

生成过程

生成结果

需求点完成情况:

1. 表单基础框架、目录生成 ✅

2. awemeInfo 字段:

  • Model 物料  ✅
  • Component 物料,用于展示抖音号头像和昵称  ✅
  • Initializer 物料 ✅
  • Transformer 物料 ✅

3. shopInfo 字段:

  • Model 物料  ✅
  • Initializer 物料  ✅
  • Component 物料,用于展示店铺图片和名称 ✅
  • 不参与提交,无 Transformer 物料 ✅

4. blockProductList 字段:

  • Model 物料  ✅
  • 无 Initializer 物料,直接使用静态默认值  ✅
  • Transformer 物料 ✅
  • Component 物料,用于展示屏蔽商品列表说明 ✅

5. 表单提交:创建了表单级别的 SubmitFn,用于提交表单数据,并应用到所有 Transformer,点击提交可正常打印 ✅

6. 表单渲染:创建了 useCreationForm hook 和 SubmitBtn 组件,在 index.vue 中渲染完整表单并且交互不报错  ✅

备注

会出现不参考 MCP 自由发挥的情况,一般会在调用刚开始时候。可以通过观察一下 MCP 调用情况,发现没有调用详细文档直接重试即可。

当 LLM 正确调用了 MCP 的前提下,基本有一半的测试情况可以无需任何代码修改直接跑通。

后续研究一下如何强制其严格按照 MCP 生成代码

技术文档

 ## 需求
在已有的业务表单中,追加如下字段

### 投放方式 smartBidType
#### Model 物料
类型是 SmartBidType 枚举类型,已存在仓库中,可以直接通过如下代码导入使用
`import { SmartBidType } from '@legacy-pmc/shared'`
通过上述语句导入的枚举类型如下
```ts
// 投放方式
export enum SmartBidType {
  CUSTOM = 0, // 控成本投放
  NO_BID = 7, // 放量投放
}
```

#### Initializer 物料
这个字段的默认值通过 `window.whiteList.XXX1` 的值来判断,
如果 `window.whiteList.XXX2`true,那么这个字段的默认值是 `SmartBidType.NO_BID`,否则是 `SmartBidType.CUSTOM`

#### Transformer 物料
直接返回字段及其值即可

#### Component 物料
为字段生成一个vue组件,支持枚举的中文文案展示,并且支持点击切换枚举值,点击后,将新的值设置到表单中

#### Reaction 物料
为字段增加一个 reaction 用来控制显隐:
字段 smartBidType 会根据 `window.whiteList?.XXX1` 的值来判断是否展示。
如果 `window.whiteList?.XXX2``true` 那么这个字段展示,并且参与表单提交及其他联动逻辑,否则这个字段不展示,但是字段仍保留在表单中,参与表单提交及其他联动逻辑。

注意:
- 无需为 whiteList 添加全局类型定义

生成过程

生成结果

需求点完成情况:

1. smartBidType 字段:

  • Model 物料,正确导入并引用仓库内已有的枚举  ✅
  • Initializer 物料,根据 window.whiteList.hitProductNobidAllowList 的值判断,为 true 时默认值为 NO_BID ,否则为 CUSTOM  ✅
  • Transformer 物料 ✅
  • Reaction 物料,正常调用 setDisplay API 控制字段显示/隐藏,但始终参与表单提交 ✅
  • Component 物料,正确支持中文文案展示和点击切换功能 ✅ 

2. 表单集成

  • 未将字段追加到表单末尾,在表单中随意插入字段 ❓

备注

本次需求的复杂点在于正确生成

Reaction 物料中对于字段显隐逻辑的控制。

在 Gemin-2.5-pro 模型中,此处基本上没有生成错误

在 Kimi-k2 模型中,此出有一定概率生成错误。

正确示例:

api.setDisplay('visible')

api.setDisplay('hidden')

错误示例:

api.setDisplay('visible')

api.setDisplay('none')

另外,对于追加字段的要求, Gemin-2.5-pro 每次都是在表单末尾追加,无需额外说明,但是 Kimi-k2 会经常出现随机插入的情况。

此处应该优化技术方案中的描述,明确字段插入位置

技术文档

 ## 需求
在已有的 业务表单 表单中,追加如下字段

### 日预算 budget
#### Model 物料
number 类型
有三个额外的字段依赖:smartBidType、blockProductList、awemeInfo

#### Initializer 物料
这个字段不需要单独的初始化物料

#### Transformer 物料
直接返回字段及其值即可

#### Component 物料
为字段生成一个vue组件,支持展示字段的中文名,以及字段值,并展示输入框,最后展示字段值的单位 "元"

#### Reaction 物料
增加一个 reaction 用来更新字段的值以及更新UI组件依赖的字段值:
当表单中 smartBidType、blockProductList、awemeInfo 三个字段值变化时,需要做如下操作:
1. 获取 budget 字段的最新的建议值并回填到表单中,获取值的过程可以直接使用一个异步函数来模拟,值为随机数。
2. 将这三个字段的值更新到 budget 字段的 Model 中,以便 budget 字段的UI组件可以访问到这三个字段的最新值,从而更新UI组件的展示。

#### Validator 物料
当字段的未输入时,需要返回一个错误文案,文案内容为 "请输入日预算",并展示在 UI 组件下方

生成过程

生成结果

需求点完成情况:

1. budget 字段:

  • Model 物料,正确注册依赖 ✅
  • 无 Initializer 物料
  • Transformer 物料 ✅
  • Reaction 物料,可监听依赖变化做出正确操作 ✅
  • Component 物料,交互正常,展示正常,文件引用路径有误,校验错误信息展示异常 ❓

2. 表单集成

  • 未将字段追加到表单末尾,但是加载了上一个字段的后面 ❓

备注

本次需求的复杂点在于正确生成联动逻辑。

Kimi-k2 出现了不按照文档自由发挥的情况。

Gemin-2.5-pro 出现了文件路径引用错误的低级问题。

校验错误信息展示异常的问题在于 MCP 提供的文档没有提供完整的例子导致

此处应该完善 MCP 文档,补充 Validator 相关事例

技术文档

 ## 需求
在已有的业务表单中,追加如下字段

### 整体支付ROI目标 ecpRoi2Goal
#### Model 物料
类型是 number 类型

#### Initializer 物料
这个字段不需要单独的初始化物料

#### Transformer 物料
直接返回字段及其值即可

#### Component 物料
为字段生成一个vue组件,支持展示字段的中文名,以及字段值,并展示输入框

#### Reaction 物料
1. 增加一个 reaction 用来控制显隐:
字段 ecpRoi2Goal 会根据字段 smartBidType 的值来决定是否展示。如果 smartBidType 的值是 `SmartBidType.NO_BID`,那么 ecpRoi2Goal 字段就不展示。否则,ecpRoi2Goal 字段就展示。当 ecpRoi2Goal 字段不展示时,字段值会被清空,不参与表单提交及其他联动逻辑

1. 增加一个 reaction 用来更新字段的值并更新UI组件依赖:
当字段 smartBidType、blockProductList、awemeInfo 三个字段的值准备好或变化时,需要做如下操作:
  1. 获取 ecpRoi2Goal 字段的最新的建议值并回填到表单中,获取值的过程可以直接使用一个异步函数来模拟,值为随机数。
  2. 将这三个字段的值更新到 ecpRoi2Goal 字段的 Model 中,以便 ecpRoi2Goal 字段的UI组件可以访问到这三个字段的最新值,从而更新UI组件的展示。

#### Validator 物料
当字段的值为空时,需要返回一个错误文案,文案内容为 "请输入整体支付ROI目标",并展示在 UI 组件下方

生成过程

生成结果

需求点完成情况:

1. ecpRoi2Goal 字段:

  • Model 物料,正确注册依赖 ✅
  • 无 Initializer 物料
  • Transformer 物料,出现 API 使用错误 ❌
  • Reaction 物料,可监听依赖变化做出正确操作,可以正确控制显隐 ✅
  • Component 物料,交互正常,展示正常,校验错误信息展示异常 ❓

2. 表单集成

  • 未将字段追加到表单末尾,但是加载了上一个字段的后面 ❓

备注

本次需求的复杂点在于正确生成联动逻辑。

Kimi-k2  和 Gemin-2.5-pro 均出现出现了一些 API 使用类的低级错误

技术文档

 ## 需求
在已有的业务表单中,追加如下字段

### 推广即享 safeguardAndEstimate

#### Model 物料
这个字段类型如下
```ts
interface SafeguardAndEstimate {
  isShowEstimate: boolean,
  minEstimateConvert: string,
  maxEstimateConvert: string,
  estimateConvert: string,
  minEstimateRoi: number,
  maxEstimateRoi: number,
  estimateRoi: number,
}
```

#### Initializer 物料
不需要

#### Transformer 物料
直接返回字段及其值即可

#### Reaction 物料
为这个字段增加 reaction 用来感知依赖变化:
1. 增加一个 reaction 用来更新字段值
当字段 smartBidType、blockProductList、awemeInfo 的值变化时,需要做如下操作:
  1. 获取 safeguardAndEstimate 字段的最新的建议值并回填到表单中,获取值的过程可以直接使用一个异步函数来模拟,返回如下结构的数据

  ```json
  {
    "isShowEstimate": true,
    "transDay": "7",
    "transBaseMoney": "210",
    "minEstimateConvert": "24",
    "maxEstimateConvert": "35",
    "minEstimateRoi": 0.22,
    "maxEstimateRoi": 0.34,
    "estimateRoi": 0.28,
    "estimateConvert": "29",
    "isUpdate": false,
    "lastUpdateTime": "0",
    "isZero": false,
  }
  ```

2. 增加一个 reaction 用来感知依赖变化:
当字段 smartBidType 的值准备好或变化时,需要做如下操作:
  1. 将 smartBidType 字段的最新值更新到 safeguardAndEstimate 字段的 Model 中,以便 safeguardAndEstimate 字段的UI组件可以访问到这三个字段的最新值,从而更新UI组件的展示。

#### Component 物料
为字段生成一个vue组件,展示字段中文名,组件展示的内容会根据字段 smartBidType 的值来决定。
如果 smartBidType 的值是 `SmartBidType.NO_BID`,那么组件展示格式为:
  根据保障规则享保障福利,计划按oCPM展示付费
  整体支付ROI:{{minEstimateRoi}} ~ {{maxEstimateRoi}}
  订单量:{{minEstimateConvert}} 单 ~ {{maxEstimateConvert}} 单
否则,组件展示为一个文案:
  默认启用智能优惠券,享平台额外补贴。根据保障规则享福利,计划按oCPM展示付费

#### Validator 物料
不需要

生成过程

生成结果

需求点完成情况:

1. safeguardAndEstimate 字段:

  • Model 物料,注册依赖有冗余 ❓
  • 无 Initializer 物料
  • Transformer 物料 ✅
  • Reaction 物料,可监听依赖变化做出正确操作,生成的代码有冗余 ❓
  • Component 物料,没有正常引用枚举 ❓

2. 表单集成

  • 字段追加到表单末尾 ✅ 

备注

本次实现出现了多次代码冗余,虽然不影响实际功能,但是会造成代码冗余,需要手动删除。

此处应该优化技术方案中的描述,明确需求,避免生成多余代码

同时在组件的生成时出现了枚举依赖未引入,这个和技术方案中的描述有比较大关系,需要后续优化。

此处应该优化技术方案中的描述,明确枚举引用等描述

技术文档

 ## 需求
在已有的业务表单中,追加如下逻辑。

### 表单字段排版
1. 增加一个排版容器组件,所有的表单字段排版都用这一个组件实现,组件的需求如下:
   - 容器组件支持插槽,用于传入若干个元素,元素可以是表单字段,也可以是排版容器组件
   - 容器宽度默认是 100%,支持外部传入参数自定义宽度
   - 布局方式默认是横向排列(可以配置为纵向排列),参考 flex 的布局方式
   - 支持额外传入一个 style 对象,用来设置容器组件的其他样式
2. 表单字段的排版规则如下:
   - 第一个区块分为两行
     - 第一行是横向排版的 awemeInfo 字段、 shopInfo 字段
     - 第二行是 blockProductList 字段
   - 第二个区块只有一行
     - 在这一行里是横向排版的两个子区块
       - 第一个子区块是横向排版的 smartBidType 字段、budget 字段、ecpRoi2Goal 字段
       - 第二个子区块是 safeguardAndEstimate 字段
3. 所有区块均使用白色背景,区块间距 20px

生成过程

生成结果

需求点完成情况:

  • 布局组件 ✅

  • 按需求调整字段布局 ✅

  • 正确展示复杂嵌套布局  ✅

备注

一个测试 LLM 进行字段排版的需求,因为没有 D2C 能力,所以看起来比较潦草,需要人工补充 CSS。

如果未来可以有比较靠谱的 D2C 能力,生成效果就会好很多。

技术文档

 ## 需求
在已有的业务表单中,追加如下逻辑。

目前有如下表单物料列表:
```json
{
  getUniPromSuggestBudgetV2: {
    type: 'AsyncFunction',
    desc: '获取建议预算',
    importStatement: "import { getUniPromSuggestBudgetV2 } from '@legacy-pmc/request'",
    params: {
      awemeId: {
        desc: '抖音号id',
        required: true,
      },
      smartBidType: {
        desc: '投放方式',
        required: true,
      },
      marGoal: {
        desc: '营销目标',
        defaultValue: 1,
        required: false,
      },
      isUniPromShop: {
        desc: '是否是全店推广',
        defaultValue: true,
        required: false,
      },
      externalAction: {
        desc: '转化目标',
        defaultValue: 96,
        required: false,
      },
    },
    returnValue: {
      budget: {
        desc: '建议预算',
      },
    }
  },
  getUniPromotionROISuggestionV2: {
    type: 'AsyncFunction',
    desc: '获取建议ROI',
    importStatement: "import { getUniPromotionROISuggestionV2 } from '@legacy-pmc/request'",
    params: {
      authorId: {
        desc: '抖音号id',
        required: true,
      },
      marGoal: {
        desc: '营销目标',
        defaultValue: 1,
        required: false,
      },
      isUniPromShop: {
        desc: '是否是全店推广',
        defaultValue: true,
        required: false,
      },
      blockProductList: {
        desc: '排除商品',
        defaultValue: [],
        required: false,
      },
    },
    returnValue: {
      ecpRoi2Goal: {
        desc: '建议ROI',
      },
    }
  },
  getUniPromSuggestEstimateV2: {
    type: 'AsyncFunction',
    desc: '获取预估数据',
    importStatement: "import { getUniPromSuggestEstimateV2 } from '@legacy-pmc/request'",
    params: {
      awemeId: {
        desc: '抖音号id',
        required: true,
      },
      smartBidType: {
        desc: '投放方式',
        required: true,
      },
      marGoal: {
        desc: '营销目标',
        defaultValue: 1,
        required: false,
      },
      isUniPromShop: {
        desc: '是否是全店推广',
        defaultValue: true,
        required: false,
      },
      blockProductList: {
        desc: '排除商品',
        defaultValue: [],
        required: false,
      },
      budget: {
        desc: '预算',
        required: true,
      },
    },
    returnValue: {
      desc: '预估值',
    },
  }

}

```

### 使用已有的表单物料

#### 替换建议预算
 budget 字段联动关系中已存在的模拟异步获取建议预算的函数,替换上述物料列表中的真实函数。
awemeId 可以使用抖音号的 userId

#### 替换建议ROI
 ecpRoi2Goal 字段联动关系中已存在的模拟异步获取建议ROI的函数,替换上述物料列表中的真实函数。
authorId 可以使用抖音号的 userId

#### 替换预估数据
 safeguardAndEstimate 字段联动关系中已存在的模拟异步获取预估数据的函数,替换上述物料列表中的真实函数。
awemeId 可以使用抖音号的 userId

生成过程

生成结果

需求点完成情况:

1. 替换 budget 字段联动关系中的模拟请求为真实请求 ✅

2. 替换 ecpRoi2Goal 字段联动关系中的模拟请求为真实请求 ✅

3. 替换 safeguardAndEstimate 字段联动关系中的模拟请求为真实请求 ✅

  • 根据接口入参自动补充 budget 入参 ✅

备注

一个测试将已有物料进行应用的需求,使用一个简易的 JSON 数据来模拟数据源,让 LLM 自己匹配使用。

这是一个为领域化最铺垫的需求。当领域化物料库建设到足够丰富的时候,让 LLM 搭建新的表单就会像拼乐高一样。

技术文档

 ## 需求
在已有的业务表单中,追加如下逻辑。

目前有如下表单物料列表:
```json
{
  UniPromShopBudgetPopover: {
    type: 'component',
    desc: '预算修改',
    importStatement: "import UniPromShopBudgetPopover from '@/pages/uni/components/uni-prom-shop/creation-wrapper/creation-form/budget/uni-prom-shop-budget-popover.vue'
",
    params: {
      value: {
        desc: '预算值',
        type: 'string | number',
        required: true,
      },
      smartBidType: {
        desc: '投放方式',
        type: 'SmartBidType',
        typeEnumImportStatement: "import { SmartBidType } from '@legacy-pmc/shared'",
        required: true,
      },
      entry: {
        desc: '入口',
        defaultValue: 'list',
        required: false,
      },
      scene: {
        desc: '场景',
        defaultValue: 'uniPromShopCreation',
        required: false,
      },
      isUniPromShop: {
        desc: '是否是全店推广',
        defaultValue: true,
        required: false,
      },
      awemeId: {
        desc: '抖音号id',
        required: true,
      },
      blockProductList: {
        desc: '排除商品',
        defaultValue: [],
        required: false,
      },
    },
    events: {
      change: {
        desc: '值改变',
        type: "(event: 'change', val: string | number): void;",
      },
    }
  },
  UniPromShopEcpRoi2GoalPopover: {
    type: 'component',
    desc: '支付ROI目标修改',
    importStatement: "import UniPromShopEcpRoi2GoalPopover from '@/pages/uni/components/uni-prom-shop/creation-wrapper/creation-form/ecpRoi2Goal/uni-prom-shop-ecp-roi2-goal-popover.vue'
",
    params: {
      value: {
        desc: '支付ROI目标值',
        type: 'string | number',
        required: true,
      },
      scene: {
        desc: '场景',
        defaultValue: 'uniPromShopCreation',
        required: false,
      },
      isUniPromShop: {
        desc: '是否是全店推广',
        defaultValue: true,
        required: false,
      },
      awemeId: {
        desc: '抖音号id',
        required: true,
      },
      blockProductList: {
        desc: '排除商品',
        defaultValue: [],
        required: false,
      },
    },
    events: {
      change: {
        desc: '值改变',
        type: "(event: 'change', val: string | number): void;",
      },
    }
  },
}

```

### 使用已有的表单物料

#### 替换建议预算
 budget 字段的 UI 组件中,字段值的展示及修改逻辑替换为 UniPromShopBudgetPopover 组件。
注意:
1. 保留组件中错误信息展示的逻辑
2. awemeId 可以使用抖音号的 userId
3. budget 字段的相关代码在 apps/uni-pmc/src/pages/uni/components/uni-prom-shop/creation-wrapper/creation-form-v2/budget 目录下

#### 替换建议支付ROI目标
 ecpRoi2Goal 字段的 UI 组件中,字段值的展示及修改逻辑替换为 UniPromShopEcpRoi2GoalPopover 组件。
注意:
1. 保留组件中错误信息展示的逻辑
2. awemeId 可以使用抖音号的 userId
3. ecpRoi2Goal 字段的相关代码在 apps/uni-pmc/src/pages/uni/components/uni-prom-shop/creation-wrapper/creation-form-v2/ecpRoi2Goal 目录下

生成过程

生成结果

需求点完成情况:

1. 引入并替换 budget 字段组件 ✅

  • 正确传入组件参数 ✅

2. 引入并替换 ecpRoi2Goal 字段组件 ✅

  • 正确传入组件参数 ✅

3. 替换原有逻辑 ✅

备注

本次测试内容是组件物料的应用,LLM 可以很好的按照使用文档使用组件,并自动传入组件所需的参数

阶段总结

最开始

步骤 1

步骤 2

步骤 3

步骤 4

步骤 5

步骤 6

步骤 7

步骤 8

最终形态

可以看到分步骤实现的效果,每一步都在更接近最终效果。

  1. 在引入 业务表单 MCP 后,LLM 对 业务表单方案的应用处于一个比较好的水准。

  2. 结合特定格式的技术文档后,需求点完成程度处于一个比较高的水准。

  3. 在引入一些物料列表后,LLM 可以比较好的应用已有物料。

后续的一些想法

业务表单 MCP 持续优化

结合 业务表单方 文档及代码库,产出更加 AI Friendly 的文档以及更自动化的 业务表单 MCP 更新流程

同时考虑将 业务表单方案 文档 RAG 化,尝试进一步提升 LLM 代码生成准确率

持续规范完善技术文档标准及规范

目前探索过程中所产生的技术文档,并未形成体系明确的标准以及规范。

考虑在需求功能点描述中引入 Ghkerin (cucumber.io/docs/gherki…

更高效的评测体系

1. 结合 业务表单方案 单元测试,产出自动化的评测体系。也可以考虑 UI 自动化测试等能力,辅助验证生成效果。

2. 建立打分体系,用于量化生成质量

3. 评测大致可以为几个维度:

  • 模型的思考过程

  • 代码产物:是否有语法不规范、API 使用错误、代码报错等

  • 最终效果:需求是否有完整实现

还有哪些可抽象的重复性开发任务?

1. 领域化物料的生成。

  • 以本文为例,围绕 业务表单方案 的各种物料(Reaction、Validator、Transformer、Initializer 等)都可以生成

2. 接口请求类代码生成

  • 结合 BAM 平台提供的能力,生成 BFF、FE 接口请求代码

3. 框架升级改造

  • 比如将 vue2 项目升级为 vue3 项目

写在最后

除了精确的为 LLM 提供上下文信息外,如何准确的描述需求也是一个值得探索的命题。在上述探索过程中,常因自然语言的歧义性,导致 LLM 生成的代码效果差异显著。

编程语言的设计初衷,正是通过高度抽象的语法规则,消除自然语言因灵活性带来的歧义,确保指令能被机器精准执行。这一特性也决定了:自然语言撰写的 PRD 中,一句看似简洁的需求描述,往往需要拆解为大量逻辑严谨的代码才能落地 —— 本质是将 “模糊的自然语言意图” 转化为 “无歧义的机器可执行逻辑”。

而 LLM 在理解自然语言时,同样会受限于这种歧义性:自然语言的多义性、语境依赖性,可能导致 LLM 误读需求核心,进而生成不符合预期的代码。因此,若想让 LLM 更精准地生成代码,就需要主动放弃一部分自然语言的随意性(而非单纯 “灵活性”),通过更结构化的约束降低理解成本。

简言之,我们需要探索一种介于编程语言(强语法、无歧义)与自然语言(易理解、高灵活)之间的 “中间层语法格式”,用它来规范需求描述、知识库内容等输入 —— 既保留自然语言的可读性,又通过适度约束消除歧义,为 LLM 提供更精准的 “生成依据”。

另外,除了本文提到的表单方案外,理论上所有技术方案的实践都可以按本文思路去探索实现。