一、背景
二、思考
三、具象思考
四、对低代码的“吐槽”
五、主要方案设计
1. 简化组件配置
2. 高效初始化页面
2.1 通过页面模版初始化
2.2 通过接口元数据生成页面
2.3 根据 PRD 描述快速生成页面
3. 智能答疑
六、大模型训练和应用
七、我对大模型应用研发提效的看法
八、功能架构图
九、问题和规划
十、参考
电商供应链的系统建设一般偏向于数据管理类型,但此类系统建设有一个很明显的问题就是前后端开发的沟通成本较高(相对研发成本而言),特别是一些简单加减字段的诉求沟通成本甚至达到 50% 以上,如何将这部分沟通成本降低下来,并保证高质量的交付成为目前亟待解决的问题。
经过对需求和系统页面进行分析,我们得出如下数据:
请注意这里讲沟通成本大是相对于简单需求的开发成本而言,单独看绝对投入其实还好,但是需求数量大,也会造成很大的资源浪费,我们希望探索出更高效的需求交付方式。
对于解决沟通问题其实有很多解决思路,其中有一个比较有效的方式就是目前得物技术正在推进的 Mooncake,它的好处是已经和发布系统打通,代码部署后所有接口和出入参等描述信息都会上传到 Mooncake,做到了统一以文档方式满足接口出入参说明诉求,执行后确实有不错的收益,但还存在两个主要问题:- 即所谓的契约精神问题,什么时间交付接口描述,并且描述清晰?在现实环境中,这是一个比较难达成的事情。服务端什么时候能够上传接口说明,这个时间不确定,即使确定了,也会出现因为各种因素不符合预期,因为很多情况下一个接口和属性的描述他认为描述清楚了,并不代表你能理解,这个就是信息差,但是真要做到你能够理解服务端一定会付出更多成本,有些人会认为没必要。
- 服务端会修改出入参格式而忘记沟通,可能到了比较滞后的联调甚至测试阶段才发现,而且屡禁不止。
在当前背景下,解决这个沟通问题的思路最简单的做法,就是让服务端一个角色全栈搞定前后端开发,为什么是服务端全栈而不是前端全栈,因为中后台系统的服务端的工作相对复杂,通过需求数据分析发现,服务端投入工时是远高于前端的,另外一个原因就是需求前端部分相对简单很多。谈到全栈,肯定不是直接把前端的工作直接交给服务端去做,得物研发目前的工作压力还是不小的,所以需要一种低成本的全栈方案,让服务端快速上手。低成本的前提就是把复杂的前端开发变得简单,初期我们考虑了三条路进行简化:通过低代码配置化代替源码开发,可以再很大程度上降低学习成本。
具象在比较标准化的 CQUD 页面类型,减少发散,用更低的成本覆盖最多的页面类型。
有没有可能借助于目前比较火的大模型 AIGC 方向降低全栈学习成本。
低代码代替源码开发的好处是可以让服务端在配置一两个页面后快速掌握配置技能,它的认知成本会降低,学习周期也会缩短,下面这张图更方便大家理解。源码和低码学习成本趋势图
另外,在知乎看到一张非常有趣的图,虽然有点夸张成分,但是感觉可以帮助大家理解低代码的学习成本。低代码和几种跨界工具的学习成本对比
各个大厂其实在低代码领域已经做的非常成熟,给大家列举两个做的比较好的,大家可以去深度了解:- 阿里低代码引擎:https://lowcode-engine.cn/index 强调可视化配置生成页面;
- 百度 Amis:https://aisuda.bce.baidu.com/amis/zh-CN/docs/index 强调 JSON 配置生成页面。
我们选择 Amis 作为基础的渲染引擎,主要原因如下:- Amis JSON 配置能力更加强大,相对于 Lowcode Engine 需要写很多脚本来满足稍微复杂的场景,JSON 配置的学习成本更低,更适合服务端同学快速上手;
- Amis 的文档功能更加强大,可以直接编辑 JSON 查看修改后的结果,这一步可以极大的方便开发学习 API。
另外关于和 AIGC 的结合,其实重点要看低代码在服务端全栈的场景下,可以帮助解决哪些问题?比如脚本编辑、UI布局等,这些一定会成为痛点,下面我们将随着问题的展开逐渐应用起来。谈及我们的方案之前,我首先要“吐槽”下低代码/零代码,很多人说不好用,甚至有人说低代码是“行业毒瘤”,我翻看了很多这方面的总结性文章,以及自己的经验,理性总结如下:- 没有认清使用人群:B 端低代码产品的绝大部分用户是前端,专业人士用低代码多少有点抵触情绪的,给别人用之前一定要想清楚,他为什么会用?或者说他因为什么才会用?个人认为给前端提供低代码工具做 B 端系统,大概率是行不通的,也许会有效率提升,但是相对专业降级及蹩脚研发体验可能不值一提。
- 灵活性不足:当遇到某种逻辑的时候,用起来就会很蹩脚或者根本没法做下去,正所谓 “一行代码难倒英雄汉”,只能源码开发一遍,这种不断尝试后的返工确实会让体验大大降低,这种一般受组件不支持或者低代码引擎不支持影响。
- 功能不完备:其实做好一个页面,要考虑多方面问题:联调、页面管理、发布/回滚、菜单、权限等,这些是不是都考虑在内了,那种体验割裂,流程分散在各个平台的方式一定会被吐槽的。
- 缺乏设计理念:比如常用组件的一种配置有多种属性命名方式,还有就是功能实现不符合大众认知等等,导致 API 的理解和学习成本巨大。
- 认知成本高:比如我们目前服务端全栈的场景,他们甚至不知道组件的概念,也不知道所谓的数据驱动,拿到的 PRD 对于页面的描述很有可能只是一大段文字描述,连个像样的线框图都没有,对于一个新手如何做才能还原成和标准交互一样的页面,其实是一个很大的考验,这些细节都是我们需要考虑并解决的。
该篇文章我不会过多介绍低代码配置实现的原理,想了解的可以 Google 下。我们整个全栈方案有一个统一的名字叫 Wizard,包括渲染引擎、组件、在线配置、发布流程、AI 答疑、AI Proto 等一系列工具,接下来会捡重点介绍。特殊说明:我们初期全栈覆盖的页面类型主要聚焦在 CQUD,并没有扩散,核心原因就是目前此类页面占比较高(72%),并且交互形式足够收敛,页面类型收敛可以将全栈的成本降低很多,后期可以根据必要性选择性覆盖更多的页面类型。
另外对于上面提到的前 4 个槽点,没什么好的方法,大家只能认清事实,持续的去做,针对第 5 点,我们确实有一些方向,分享出来给大家参考,总结来讲主要是三步:简化组件配置、高效初始化页面、智能答疑。
得物的基础组件建设得益于 Antd 和 ProComponents,好的东西当然直接复用,我们的主要工作是还原得物的设计标准以及业务组件的沉淀,组件注册到 Wizard 中最重要的是要将复杂属性转换成 JSON 配置可实现,比如接口请求、表单联动、数据格式化等,如果这一步做不好,会导致部分功能被阉割,所以这部分我们花费了比较大的精力去设计实现,以表单联动举例,效果参考如下动图:选择显示姓名,姓名展示,选择禁用密码,姓名隐藏,密码禁用
源码实现:https://stackblitz.com/edit/react-vegy7y?file=demo.tsximport React, { useState } from 'react';
import { Radio, Form, Input } from 'antd';
type FieldType = {
username?: string;
password?: string;
type?: number;
};
const App: React.FC = () => {
const [form] = Form.useForm();
const [hiddenName, setHiddenName] = useState(false);
const [diablePassword, setDiablePassword] = useState(false);
const onValuesChangeHandler = (values: FieldType) => {
setHiddenName(values.type !== 1);
setDiablePassword(values.type === 2);
};
return (
<Form
form={form}
name="basic"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
style={{ maxWidth: 600 }}
onValuesChange={onValuesChangeHandler}
autoComplete="off"
>
<Form.Item<FieldType> name="type" wrapperCol={{ offset: 8, span: 16 }}>
<Radio.Group>
<Radio value={1}>显示姓名</Radio>
<Radio value={2}>禁用密码</Radio>
</Radio.Group>
</Form.Item>
{!hiddenName && (
<Form.Item<FieldType> label="姓名" name="username">
<Input />
</Form.Item>
)}
<Form.Item<FieldType> label="密码" name="password">
<Input.Password disabled={diablePassword} />
</Form.Item>
</Form>
);
};
export default App;
{"type": "form","body": [{"type": "radio","name": "type","label": "类型","options": [{"label": "显示姓名","value": 1},{"label": "禁用密码","value": 2}]},{"type": "text","name": "username","label": "姓名","visibleOn": "${type == 1}"},{"type": "password","name": "password","label": "密码","disabledOn": "${type == 2}"}] }
上面右侧 Wizard 代码示例中,type 代表组件类型,同级的其他属性代表组件API,body 属于通用属性用于子元素设置,认真看会发现,Wizard 针对禁用和显隐设置增加了 disabledOn 和 visibleOn 两个属性,并且支持写简单的表达式,类似这种标准属性的实现,是所有的组件统一去实现的(所有的组件都会支持 visibleOn ,所有的表单类组件都支持 disabledOn ),表达式是引擎统一实现的能力,为了更好的支持配置化,Wizard 引擎还支持数据域、数据链、模版、数据映射、表达式、函数、行为等。另外一种比较复杂的情况,是组件自带的数据请求能力,比如 ProTable、Select、Form 等,而且一般都需要解决数据处理问题,比如数据查询前需要对入参进行格式调整,拿到数据之后需要对出参进行格式校准等,是非常常见的操作,我们统一设计了 api 配置,除了满足基本的 url、method、data 设置外,还支持请求前后的 adaptor 设置,当然这里就是我们说的需要写脚本的地方,而且目前是整个 Wizard 唯一需要写脚本的地方,这部分还是有点复杂的,但是我们这里借助于 AI 的能力实现了只需要配置当前数据格式和你需要转换的数据格式,就可以生成转换脚本,并且支持对函数进行快速测试,如果没问题即可回填到配置中,以更低的成本实现脚本输出。下面这个示例,相信大家一看左右结构就能明白研发同学的数据转换意图,此处不再啰嗦。其实这种功能在有了大模型之后,实现变得很简单,我们只需要设计一个合理的 prompts 即可,虽然输出的脚本有时候有点啰嗦,但是准确率和稳定性还是比较高的。//adaptor 脚本生成 prompts你扮演一个纯函数代码生成器,你负责生成数据格式转换代码,你负责接收函数出入参的文本指令,根据要求生成javascript 代码,取变量值和给变量赋值的时候请做好容错处理,处理容错时不要提前返回undefined或null帮我生成一个 js 函数: function formatData(payload, response, api) {},要求最终返回处理好的数据response参数: ${before},返回数据为: ${target}, 只输出函数代码,不要输出其他无关的东西,函数代码中的注释保持中文输出,其他无关信息不要输出输出代码缩进2个空格
俗话说“万事开头难”,页面 0 到 1 的成本如何降到尽可能的低是我们一直比较追求的,因为这样可以有效降低全栈门槛,我们主要通过以下三个手段:针对 CQUD 的场景,我们沉淀了比较多的示例,基本能够涵盖系统需要的常见交互和功能诉求,这是最基础的做法,全栈同学选择模版创建后,修改下配置即可满足页面诉求。上面提到得物的 Mooncake 平台,沉淀了得物所有接口的出入参信息,Wizard 可以做到选择接口和页面类型生成页面描述,根据接口类型,可以选择生成列表、表单、详情,可以复制到页面中成为页面主体或者一部分。这个是为了解决上面“吐槽”中提到的第5点,很多 PRD 对于中后台需求描述过于简单,没有草图说明,即使有草图,对于全栈同学也不一定知道怎么还原 UI,Wizard 训练了自有的大模型(关于模型训练,后面章节会介绍),做到对 Wizard 足够了解,可以结合 PRD 描述快速生成页面效果(插件 Wizard Proto),我们只需要提供标准的描述页面功能的文本格式,产品同学按照格式填空书写页面结构即可,具体实现细节参考:大模型在产品原型生成中的应用实践,这里放一个视频用于说明使用方式:通过 Proto 生成的页面既可以帮助产品用最低的成本还原页面原型,又可以帮助研发同学快速还原 UI。同时我们看到视频中给予产品一定的 UI 配置能力,但是这远远不足,长远的规划上看,大模型在此步的应用只是为了快速生成,而后还是需要提供更加完备的可视化配置能力完成页面 UI 和交互配置(或者换句话说,大模型的应用是为了让产品和技术快速上手),并且这部分配置是可以沿用到全栈开发,我们希望能够做到 CQUD 的 UI 工作在 PRD 阶段搞定,全栈同学的主要工作是做接口配置和功能校准即可,当然这个是很理想的状态,但是我们希望全栈研发同学的单页面输出成本降低到 0.5 人日以下,同时不增加产品的成本。前面提到的 Wizard 自有大模型,还承担着另外一个比较重要的角色,就是辅助全栈同学答疑,比如:同时我们也会支持针对回答的内容进行正向和负向反馈,这些反馈也会用于丰富我们的训练池,让大模型准确率越来越高。这部分能力目前使用率还不够高,根本问题还是准确率问题,关于下一步的规划,下面章节会提到。Wizard 应用的基础大模型是更擅长做代码生成的 DeepSeek Coder,我们使用的版本参数个数是 6.7b,但其实模型准确率如何,核心是训练的数据源怎么搞定,Wizard 不像 Antd 或者 React 一样属于应用广泛的开源产品,社区有大量的代码、文章等让 ChatAIGC 进行训练,Wizard 的训练数据需要我们自己整理,思路如下:- 根据文档中的组件示例、组件 API 描述、概念描述、示例、存储的 QA 问题等快速生成种子问题。
- Proto 和智能答疑的正负向反馈都会被作为训练数据放入种子问题中。
- 种子问题数量有限(1000 以内),所以会进过一轮人工的验证,比如你如果发现 SearchPage 组件相关的问答不够准确,可以搜索处理对种子问题进行矫正,如下是一个简单的种子问题校准工具。
- 针对种子问题通过成熟大模型进行扩展生成多条问题,这一步可以实现数据集的成倍增长,也是为了兼容对一个问题不同的表达,提升模型对问题的兼容度,主要扩展思路如下:
其实这里怎么去生成要看场景,主要思路是把大模型当做一个记忆力和理解能力超强的人去看待,你用哪些信息能够让它快速理解怎么使用一个组件,而后决定怎么去准备你的组件 QA 池。
- 对训练模型准确度进行综合评估,因为上面提到的智能答疑和 Proto 都会有正负反馈,也能部分说明模型准确性,更精细的准确度评估我们目前还没有做,如果要做的话可以参考 Ragas 评估(https://zhuanlan.zhihu.com/p/675777378),针对整理的数据集可以留一部分 QA 不参与训练,而是用于做准确度评估即可。
综合流程整理如上
目前大模型在 Wizard 核心的应用有如下几种场景。有用,但适可而止:以上五种应用场景中的三种都起到了一定的作用,并且我们还在考虑通过大模型实现数据 Mock 能力,因为他足够聪明,只要我们把上下文数据和 type Interface 全部给他,可以用比较低的成本实现CQUD 的接口,但每一种应用在我们的方案设计里面,都不是必经路径,核心是因为在研发这条路上,模型的准确率没有想象那么高,很多情况下需要人为纠正,这个也是我们实践下来的一个最明显的认知,不要想着把大模型训练的特别牛,准确率特别高,ROI 不一定合理,从辅助研发的角度,我认为能达到 70% 以上已经是非常了不起了(Wizard 大模型目前准确率 60%),除非你们成立了一个专业团队,长时间投入。
增强针对性:很多情况下太泛的应用会影响大模型的准确度,我们在实际场景中可以结合严谨的 prompts 和 TypeChat 这种工具,缩小大模型回答的范围,因为你指向越明确,大模型回答的越精确,像上面提到的用于数据格式转换的脚本生成,一般很少会出问题,除非站在人的角度没法理解你要转换的意图,那就是你的输入有问题了。
不要逃避:个人认为 AIGC 一定是未来趋势,各行各业可能都会发生变革,包括研发,一味地按照固有思维去解决问题或者不愿去了解,未来大概率会吃亏的,你不一定要自己学会怎么训练大模型,但最起码要掌握两点:大模型的成长性新闻以及应用场景。个人认为,未来简单页面的开发工作可能真的会被生成式 AI 替代,如果你现在的工作就是在做类似简单 CQUD 的事情,那一定要焦虑一下了,快去多翻翻社区。一个很现实的例子:“十年梦碎,苹果放弃造车转 AI”,不造车可以理解成对新能源不看好或者认为已经很饱和,但是转生成式AI,这个一定是对未来的深刻信心和期许。
功能架构图
1. Wizard 提供 3 种新建页面的方式,根本目的是为了尽可能降低页面 0 到 1 的成本,研发可以选择合适的方式或者组合使用。 c. Proto 工具实现根据 PRD 智能生成页面。2. Mock 能力使得 Proto 生成的页面效果更加逼真,包括动态枚举,列表数据,表单提交等,既方便了产品丰富页面原型,又降低研发复用创建页面的成本。3. Migrate 用于结合 AIGC 对于 ProTable、ProForm 等常用组件的配置转换成 Wizard 配置,用于进一步降低就页面迁移到 Wizard 页面的成本,提升全栈占比。4. 基于天网和统一配置中心,完善了调试、发布、回滚、下线、菜单和权限管理等能力。5. Wizard 根据文档和日常答疑并结合 AI 输出大量 QA 训练自有大模型,在整个全栈过程提供比较大的帮助。 a. 帮助产品画原型图,生成的页面可用于进一步配置; c. 分析源码转换成 Wizard 页面,降低页面迁移成本; d. 后期还会考虑通过需求描述做页面功能修改,进一步降低认知成本; e. 通过训练大模型解决复杂的表达式生成问题,进一步降低联动配置成本。- Proto 和 智能答疑的应用占比不高,组件 API 查看率 70%,这个评估下来和准确度还是有比较大关系,针对这个问题我们做的是从 JSON 配置往可视化配置进行转换,尽量减少大家的认知成本。
- 通过智能答疑和 Proto 的正负向反馈,不断训练模型,提升其准确度,最起码要做到 70%。
- 增强 Proto 的配置能力,提升产品同学使用 Proto 输出页面的比例,争取做到 PRD 阶段输出 UI,进一步提升页面输出效率。
- 提供产品能够理解的可视化配置版本,实现在业务系统上可以直接进入配置界面创建需求,从原来的截图说明需求,变成直接配置生成草稿和变更说明,并和得物的需求创建流转流程关联起来,进一步降低一个需求从需求到上线各个角色参与的成本,缩短需求交付周期。
需求提出流程
需求评估和交付流程
https://www.zhihu.com/question/457292482
https://mp.weixin.qq.com/s/Bqca6JrBlAoGlAXhey18HQhttps://mp.weixin.qq.com/s/udeE32EKlHPMjcirl6i-mQhttps://mp.weixin.qq.com/s/IxsLmaxHmR63tR2sehxwbghttps://blog.shizhuang-inc.com/article/MTQ0MTQhttps://zhuanlan.zhihu.com/p/675777378https://arxiv.org/abs/2310.13671https://arxiv.org/abs/2212.10560https://arxiv.org/abs/2305.19915https://arxiv.org/abs/2310.17876https://arxiv.org/abs/2311.15653