多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

积木智能体开发Todo应用:动手前先问两个问题,为什么是关键设计

积木智能体开发Todo应用:动手前先问两个问题,为什么是关键设计 一个月前我做了一次报复性的测试平时让AI写代码大多是我说需求、它直接吐答案但我那次偏要反着来——丢给某积木智能体平台一句话让它从零开发一个 Todo 应用而且只给极简描述不给任何技术约束。结果这台“见惯了需求文档”的智能体没有像普通对话AI那样闷头狂写而是在动手前先停下来反问了我两个问题。这两个问题让我对“AI开发”的整个认知重新洗了一遍牌。这篇就把整个过程完整复盘我给了什么、它问了什么、为什么这么问、之后的工作流如何一步步推进以及我在后续测试里踩中的坑和关于“提问分寸感”的一些思考。如果你也在折腾智能体搭建或者对“AI能不能真的顶替开发”这件事既期待又怀疑这篇应该比单纯秀一段生成代码更有参考价值。1. 为什么拿积木智能体造 Todo一场刻意留白的小实验1.1 积木智能体和普通AI问答到底差在哪儿先解释一下我口中的积木智能体是什么。它不是那种“你问一句、它答一段”的聊天机器人而是一套可以把任务拆成多个节点的可视化流程系统。你可以在画布上拖出“接收需求”“识别意图”“调用生成能力”“执行自测”这类积木块把它们像流水线一样串联起来。前一个节点的输出自动喂给后一个节点最终形成一个可重复执行的工作流。拿现实类比会更直观普通AI聊天是让一位全能老师傅直接听完需求就上手做出成品积木智能体则更像一条流水线先由前置工位读图、辨识零件再由后面工位加工装配。好处是每个环节你都能单独观察和介入坏处是流程本身的设计质量会直接影响结果。这次我用了本地搭建的模拟项目X来跑整个过程在可视化界面上看得一清二楚意图识别是一个节点信息补全是另一个节点生成代码又细分出若干子步骤。这让我第一次觉得AI并不是“一键魔法”而是一个可以逐步审计、逐步干预的过程。1.2 Todo是个被低估的“麻雀”项目很多人觉得Todo应用是入门demo没什么含金量。但我一直认为它恰恰是测试智能体开发能力的高质量样本。一个合格的Todo应用必须覆盖软件工程里最核心的几件事数据的增删改查添加任务、删除任务、状态流转待办变已完成、持久化存储刷新不丢、界面渲染、交互反馈。麻雀虽小五脏俱全。正因为它足够小一旦生成失败我能很快定位是智能体的哪一环出了问题。如果第一版就跑不对问题几乎必然出在某个关键假设上而不是需求复杂度本身。更关键的是正因为Todo对智能体来说并不难它如果在“不难”的场景下依然选择先提问那才更能说明“提问”是这套系统刻意设计出来的行为而不是被复杂需求逼出来的应急反应。这也是我接下来要说的核心观察。1.3 我给这次实验定的三条规则为了让实验有参照价值我给自己定了三条规则第一原始需求只给一句话刻意留下多处信息缺口。第二不提前告诉它用什么技术栈、要不要后端看它如何假设和追问。第三它每做出一个关键动作我都截图记录一次方便事后复盘。我把这三条规则写在本子上目的很明确我不想看它如何把一件已经描述得明明白白的事做完我想看它在信息不足时如何应对那些“需要猜”的决策点。结果它确实没有让我失望——它在动手前拦住了我。2. 我交出的需求只有一句话它却反问了这两个问题2.1 需求原文角色、目标、约束、偏好唯独不写架构我当时交给它的需求文本是这样的你是一名全栈开发工程师。请从零开发一个可用的 Todo 应用。 约束不需要花哨设计但要运行稳定。 偏好任务数据不希望丢失。然后把需求拆开看其实我给了四个要素角色、目标、约束、偏好。但涉及技术选型的部分全部省略了——比如单机还是多端、要不要后端、要不要账号体系、用什么框架、数据存在哪里。我当时心态是如果它直接开干大概率会默认生成一个“前后端分离、带登录注册”的Web应用理由很充分——这样最“完整”也是大模型训练语料里最常见的Todo应用形态。但那样恰恰离我的真实需求最远。它停下来之后我问它“你有什么问题”它抛出的两个问题让我有点意外意外不是因为问题刁钻而是因为它问得实在太到位了。2.2 第一个问题单机自用还是多人共享——这是架构分水岭它问的第一件事是这个 Todo 应用的使用场景是你自己单机使用还是需要多人共享协作我愣了两秒。这个问题直接戳中了架构的分水岭。单机自用的Todo数据落在本地前端一把梭就有八九成效果完全不需要服务器多人共享的Todo则是另一套逻辑要考虑身份识别、数据同步、并发冲突处理开发复杂度直接上一个台阶。如果它跳过这个问题直接开干大概率会默认做成前后端带登录的产品形态那和我想要的差了十万八千里。它选择先问说明它清楚“使用形态”这个变量对后续技术方案的影响面最大值得动用一次提问机会去澄清。我在复盘时特别注意到一点它没有问“你喜不喜欢暗色主题”也没有问“要不要支持语音输入”而是把提问机会留给了影响架构的变量这种分配注意力的方式值得点个赞。2.3 第二个问题数据要不要长期保存——这是存储分水岭第二个问题是关于持久化的你希望任务数据长期保存还是说程序重启后保留即可对数据丢失的容忍度如何这个问题同样有讲究。长期保存意味着必须引入某种存储机制至少是本地数据库或文件存储如果连重启后数据都需要保留那就要更进一步确保数据写盘而不是放在内存里。如果对数据丢失无所谓那直接在内存里跑一个数组关掉页面一切归零省去所有存储代码。我给出的回答是“要长期保存”。这个回答直接决定了它后续会选择把数据写入本地持久化存储而不是做一个“刷新即清空”的教学Demo。如果当时我回答“无所谓”生成的Todo就是一个刷新就清空的玩具根本担不起“可用”两个字。一个问题的答案直接决定产品是玩具还是工具这种判断力放在人类开发者身上都算关键经验何况是智能体。2.4 为什么是两个问题而不是一个或十个聊到这里我最想展开的是这个“两个问题”的分寸感。市面上绝大多数AI工具要么不问青红皂白直接用默认值开写要么一上来弹出一张覆盖十几个维度的需求调查问卷把用户活活劝退。它只问两个看起来少却恰好覆盖了影响后续架构最大的两个维度——使用形态决定系统边界数据形态决定存储方案。这种“抓大放小”的能力背后其实是对“需求变更影响面”的量化认知有的信息缺失只影响样式用默认值补上就行有的信息缺失会影响整个技术骨架必须在动手前问清楚。我也问过自己如果让我列“Todo应用最小信息清单”我会选哪两项想来想去大概率也是这两项。有这种默契在我对后面流程的信任感陡然提升了不少。3. “先问再做”不是礼貌而是一条完整的工作流设计3.1 需求澄清、任务规划、分步执行三段式背后的积木逻辑回答完两个问题之后我盯着画布看它接下来的动作逐渐摸清了它内部的运行逻辑。它其实把任务处理分成了三个阶段需求澄清、任务规划、分步执行。提问只是第一阶段对外界的表现真正重要的是它在动手前建立了一套“先对齐再开工”的机制。我在画布上看到需求澄清阶段结束后下一个节点自动激活了任务规划。这个顺序不是随意的少了澄清就规划规划容易建立在错误假设上少了规划就执行执行会变成无头苍蝇。这也解释了为什么它会先稳定输出两个问题而不是想到哪儿问到哪儿。因为“提问”这件事本身也被设计进了流程而不是靠大模型临场发挥。3.2 它怎么判断自己“信息不足”权重化信息缺口检测我起初以为它只是设置了一组固定模板问题看到后面运行日志才发现不是这么回事。它会先把需求文本拆成若干实体和属性再和“生成一个Todo应用”所需的最小信息清单做逐项对比。这个最小信息清单里的每一项都带有一个权重类似于“这个属性缺失会对最终结果造成多大影响”。使用形态权重最高因为它直接决定系统边界数据存储权重次之因为它决定代码结构界面偏好、交互细节这些属于低权重项用默认值先跑做完再在输出面板里提示“这部分我是按默认方案处理的”。这套逻辑本质上和现实中的产品评审非常像先问那些“不问我就会猜错”的问题其余细节靠合理默认值推进把用户的决策精力留给最关键的少数。3.3 多花的三十秒换回了什么用传统AI聊天工具直接生成应用我最常见的体验是第一版出来的东西“能跑但不对”。界面、功能大差不差但总有一个或几个关键假设是错的。典型例子是我想做个本地小工具它默认生成了需要登录的版本我被迫花大量时间在骨架上返工。积木智能体先问两个问题看似每次多花了三十秒实际上把返工成本提前支付了。一个错误的架构假设后续修起来可能是几小时甚至几天的事远比两点确认的时间成本高得多。用经济学的说法提问是一种信息增益操作花小成本消除高方差假设避免后面放大成高代价错误。这个逻辑放在人类团队协作里成立放在智能体工作流里同样成立。3.4 一个被忽略的体验细节它把“决策权”还给了用户使用传统AI工具时我经常有一种“答案像开盲盒”的失控感。它替我做了很多假设然后直接交给我一个既定结果。改起来倒是也能改但你永远不知道它到底在哪些地方替我做了决定又基于什么理由。积木智能体问问题的行为本质上是在关键的决策点上把选择权交还给我。虽然它只问了两项但这两项恰恰是最需要用户拍板的地方。做过项目的人都懂方案好不好的重要标准之一就是你有没有留出干预空间。我回答完这两个问题之后明显感觉到这条工作流已经和我“对齐”了接下来它生成的东西大概率就是我脑子里想的那一种。4. 回答完问题之后从任务清单到跑通首版4.1 两个回答如何框定技术边界我当时的回答是单机自用数据要长期保存。就这两句话直接画出了整个技术方案的边界。没有后端服务意味着可以剔除网络请求、数据库部署、鉴权体系这一大堆复杂度数据要长期保存意味着必须引入本地持久化方案单机自用意味着界面可以做成极简形式不需要适配多用户视角。它没有继续追问用Vue还是React、用原生JS还是框架因为到了这一步低权重信息可以靠默认值补齐。而事实也证明它对技术选型的默认值相当稳妥——选了一条“打开即用、无依赖、跨平台”的最简路径让整个应用保持在一个HTML文件就能承载的复杂度内。4.2 它在画布上拆出的任务步骤回答完问题后它没有直接吐给我一坨代码而是在画布上先铺开了一份任务清单大致是确定技术方案、搭建项目结构、实现任务数据的增删改查、实现完成状态切换、接入本地持久化、补充交互细节、运行自测。这个拆分本身就是很大的价值。因为用AI写代码最大的痛点从来不是“它不会写”而是你无法预判它先写哪部分、后写哪部分。一旦中途要改需求改动影响面如同乱麻。有了任务清单至少我能做中途拦截发现某一步跑偏了直接停下来修正而不必等它全部写完才发现方向错了。这种“过程可见”的能力让我第一次对AI生成的代码建立了可控感。4.3 核心逻辑实现界面层和存储层解耦我还是要放一段生成出来的核心代码虽然不是什么高深算法但非常适合说明“Todo的界面层和存储层为什么必须解耦”。// 任务数据与界面渲染分离的最小结构 let tasks []; function addTask(title) { const text title.trim(); if (!text) return; const task { id: String(Date.now()) String(Math.floor(Math.random() * 10000)), title: text, done: false, createdAt: Date.now() }; tasks.push(task); saveTasks(); render(); } function toggleTask(id) { const target tasks.find(t t.id id); if (target) { target.done !target.done; saveTasks(); render(); } } function removeTask(id) { tasks tasks.filter(t t.id ! id); saveTasks(); render(); } function saveTasks() { localStorage.setItem(todos, JSON.stringify(tasks)); } function loadTasks() { const saved localStorage.getItem(todos); tasks saved ? JSON.parse(saved) : []; render(); } loadTasks();代码结构很朴素但我注意到两个关键点。一是它把所有修改tasks数组的操作都收敛到调用saveTasks()和render()这两个函数上新增、切换、删除共用同一套保存和渲染管道逻辑清爽而且不容易漏掉界面刷新。二是数据结构和界面渲染完全分开后续改需求时只需要动很少一部分代码。其中的id字段我特意展示的是二次修复后的版本在原版生成里id是直接用Date.now()字符串化的。当时我还没意识到这个写法有隐患直到第二轮边界测试翻车才回来改掉。这一点很重要后面细说。4.4 自测阶段暴露的两个小插曲整个流程不是一帆风顺的。生成结束后的自测环节它自己跑了基础用例抓到两个问题。第一个是“清空已完成任务”这个操作数据文件里删掉了记录但界面上的剩余数量没有同步刷新。问题出在一个节点里更新了存储却漏掉了界面渲染的调用属于典型的“改了一个入口漏了一个出口”问题。它没有装死而是在输出面板里标注“已修复”并且让我复测确认。第二个是空标题任务。如果输入框只敲空格就点添加原版逻辑会创建一个没有实际内容的任务卡片。它用了trim()做了拦截同时给出提示文案。这两个问题都不大但让我看清一件事AI生成的代码可以很快但它对边界条件的覆盖能力仍不稳定不是每次都主动。自测环节可以把显性bug抓出来可隐性缺陷往往要等真人上手操作才会暴露。5. 三轮“刁难”测试以及一条关于分寸感的思考5.1 功能测试基本盘很稳还有个加分项第一轮我带它跑的是常规功能测试添加任务、删除任务、勾选完成、刷新页面后数据还在。这些它做得干净利落本地刷新后数据全部恢复没有丢。真正让我加分的是一个行为它在生成结束时的输出面板里列了一张“已知限制清单”明确写了“当前版本未实现任务优先级排序”“未实现截止时间提醒”。这种“不夸大自己”的做法体现的是模型对自身输出边界的感知能力在团队协作场景里非常讨人喜欢。至少它没有像某些工具那样稍微能跑就号称“已完成完整应用”。它是真的知道自己交付到了什么程度。5.2 边界测试空提交过关连续点击却翻车第二轮就精彩了。我干了几件特别“用户行为”的事在输入框里只敲空格粘贴一段两千字的任务文本以及用最快的速度连续点击添加按钮。空字符串拦截它第一版就防住了超长文本也能正常渲染不卡顿轮到连续快速点击时问题终于暴露——出现了一条任务被创建两次的情况。根源就是我前面提到的id生成方式直接用Date.now()作为唯一标识在同一毫秒内连续调用会生成相同的id。数据结构里两个任务共用一个id界面渲染时只画出了一个。这个问题在常规使用中并不常见但一旦发生就是数据层面的脏数据。我后来把id改成了“时间戳加随机数”的组合才彻底解决。这件事给我最大的提醒是AI生成代码可以很快但“review不能省”这条铁律在智能体时代依然适用。它的鲁棒性来自训练数据的覆盖而真实用户的操作习惯远比训练语料古怪得多。5.3 需求变更测试改动范围的收与放第三轮我故意加了新需求在列表里按截止时间排序。我观察它如何处理这次变更——是只动排序逻辑还是会牵连到其他地方。结果它很克制只调整了排序函数和渲染入口没有大动干戈地重写结构。这要归功于它在第一版里就把数据结构和界面渲染解耦写到位了所以改起来不会伤筋动骨。这次经验让我想明白一件事让AI写好代码不只是让它“现在把功能实现”更重要的是让它“为后续改动留下空间”。解耦意识才是产品级代码和玩具级代码的分界线。5.4 两个问题未必永远最优数量与复杂度要匹配全套测试跑完我心里反而升起一个疑问两个问题是不是永远的最优数量如果需求再复杂一些比如做一个团队协作的Todo需要成员、权限、通知两个问题显然不够覆盖。如果需求再简单一些比如只是活动页面上内嵌一个任务清单两个问题又显得冗余。可能的改进方向是让智能体根据需求复杂度动态调整提问数量。低复杂度需求问一个甚至不问高复杂度需求分层问先问架构层再问功能层。判断依据可以是它对需求文本里“不确定性”与“影响权重”的综合评估。这个能力如果成型它才算真正理解了协作的分寸感。最后分享一点我的变化玩完这一轮我自己最大的转变是从“把AI当自动售货机”切换到了“把AI当协作对象”。以前我用AI工具恨不得把需求写到三百字生怕它有歧义。现在我会刻意在需求描述里留几个空位故意不填看看它会不会主动问我。如果它问的问题恰好戳中架构关键点我会觉得这套系统是真的懂需求边界如果它闷头直接开干那梁子就算记下了。这大概就是积木智能体和我以前用的工具最大的区别——它不再是一个“答案生成器”而是一个“有工作节奏的协作对象”。它动手前先问两个问题这个细节我看了之后没有觉得聪明反而觉得踏实。后来我又用同样的方式让它做了一次数据分析类的任务同样收获了一批“原来它关心的是这些变量”的启发。如果你也想试试我建议从最熟悉的场景开始先给一个一句话需求然后什么都不补充看看它敢不敢问、会问什么。这个过程有时候比生成的Todo应用本身有意思多了。
返回列表