从零打造一个开源的 AI 组件生成平台 😡

660 阅读7分钟

前言

这两年 ai 也是跑的飞快,相信大部分兄弟已经投入 cursor trae 这些编辑器的怀抱了。效率属实提升了太多,即使没有的兄弟,估计也会使用 chatgpt 豆包 这些 ai 辅助自己进行开发。

但当问题比较复杂的时候,生成的代码往往不尽如人意。这时候就要自己来思考处理了。兄弟们有没有想过,为什么我们可以通过自己思考来处理复杂问题?ai 差在哪里?

要想明白这个问题,需要我们简单分析一下自己的行为,假设我们要做一个表单页,其中有定制的 Radio进度条等,我们的思路基本如下:

  1. 实现 Radio 组件,进行测试
  2. 实现进度条组件,进行测试
  3. 使用这些组件组装出完整的页面

是的,我们会将复杂问题,拆分为小块的问题,逐步进行验证和使用

如果按这个思路,让 ai 来处理小块的问题,生成结果会比之前好非常多。这种小块问题,也即基础单元,粒度选为组件太合适了

众所周知,组件可以独立为一个文件进行展示和测试,像积木一样,能很方便的进行组合。

image.png

另外,将其作为上下文注入对话时,也仅需要提供 用途+Props,大模型并不需要知道其内部完整实现,所以能节省很多上下文。

所以本文将聚焦于生成组件这一环,先贴一下我们的目标:

image.png

需要实现的基本功能为:

  1. 能跟 ai 讨论需求
  2. ai 能生成组件代码
  3. 平台需要实时渲染组件代码

这里需要解决的关键问题有:

  1. 如何定制 ai,使其能从对话中分辨出,应该进行需求讨论 or 生成组件
  2. 如何让组件代码能够实时渲染

定制 ai

定制 ai 这一步我选用了 dify,原因有下:

  1. 提供了基本的 ai 能力,支持使用自己的 key
  2. 能够编排模型思路,做出部分逻辑判断
  3. 简单、免费、热门

将花一些篇幅介绍 Dify 的使用,如果想跳过这一步,可以直接拿 DSL 文件,导入 Dify 即可 github.com/imoo666/ai-…

Dify 的基本使用

我们可以新建一个空白的 demo 应用(注意应用类型需要选择 Chatflow),然后简单做个测试

image.png

但是我们需要的是 api,而不是一个聊天的平台,所以看一下怎么用 api 来调用它。

先找 ai 帮我们写个 node 脚本:

const API_KEY = "your-demo-api-key";
const API_URL = "https://api.dify.ai/v1/chat-messages";

async function askDify(prompt) {
  const res = await fetch(API_URL, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      inputs: {},
      query: prompt,
      response_mode: "blocking", // 阻塞式,一次性返回完整结果
      user: "demo-user", // 可选:用于标识请求用户
    }),
  });

  const data = await res.json();
  console.log("🤖 Dify AI Response:", data.answer);
}

// 修改这里的 prompt 内容来测试
askDify("你好,能介绍一下你自己吗?");

dify 的 key 我们可以在这里找到

image.png

接着就可以进行 key 的替换和测试

image.png

不过大家可能在测试的过程中就会发现,openai 的免费额度用的飞快,所以我们需要去整点自己的模型放进 dify 中。

本次流程中,我使用了两个模型:

硅基流动:完全免费的 qwen-8b(在 dify 使用时要选择关闭思考模式),用于简单的对话、判断逻辑,节省成本

google:几乎免费的 gemini2.5 flash,用于生成高质量组件内容

这两个平台的注册和使用都非常简单,直接上官网就行了。

拿到 key 以后,直接上设置中激活对应模型,随之就能在其他地方使用了

image.png

Dify 的逻辑编排

我们增加一个分类器用于对问题的分类

  • 已经整理好了全部需求,可以准备生成组件
  • 还没讨论或是还没讨论完,需要和用户讨论需求

并给定两种输出来验证分类的正确性

image.png

分类是正确的,那么我们就可以写后续的逻辑了,对于不同的分类,我们给予不同的提示词

你是一个引导机器人,你有丰富的前端开发经验,你需要一步步引导用户进行 react 组件生成。
- 你只需要和用户详细的讨论需求,不需要进行代码实现
- 如果用户不想考虑的很详细,则用你的经验来为用户选择一个最简单、最合理的需求列表
- 代码实现由另一个 api 来做,它将使用 react + ts,类组件,且只支持一个文件
- 每次和用户讨论需求后,将所有需求要点都重新罗列出来,按 12345... 进行输出,直到用户觉得满意,可以生成组件为止

你是一个前端组件代码生成器,你需要根据用户的需求,将其实现为可运行的 React 函数组件代码(TSX)。
要求:
- 使用函数组件,且只能生成一个文件
- 这个文件需要包含两个部分 1. 导出的组件,注意需要用局部导出 2. 导出的 使用demo,使用默认导出
- 需要使用行内 style 来写样式,组件的 ui 要现代化和美观
- 代码中严禁出现反引号`,代码中严禁出现反引号`
- 只需要返回组件代码,不需要用 markdown 格式输出,不需要其他介绍,只需要代码!

image.png

这样逻辑就编排完毕了,也成功实现了该讨论讨论,该生成生成。

现在我们只需要考虑如何将这一大串组件代码进行实时渲染即可。

React 实时渲染

主流的解决方案有以下三种

image.png

首先由于 react-live 不支持 import,导致很多包用不了,假如我们是基于其他组件来做二次封装会相当麻烦,直接 pass。

Livecode 体验了一下,感觉很重,而且 ui 比较古老,遂放弃。

Sandpack 则是功能最完整,体感最好的,也是 storybook 等工具的同款。

使用起来也非常容易,只需要接入一个组件即可,demo 如下

import { Sandpack } from "@codesandbox/sandpack-react";

const App = () => {
  const files = {}
  
  return (
    <Sandpack
      files={files} 
      theme="light" 
      template="react"
    />
  )  
}

随后左侧的框就可以写入 react 代码,并将其渲染到右侧

image.png

至此,我们掌握的这些就可以串起来了,先用 ai 区别出需求讨论或是组件生成,若是需求讨论,则沟通细节。若是组件生成,则将代码置入我们的 Sandpack 组件中,进行实时预览,若是不满意则再进行调整。

不过在此过程中还有个问题,前端接收到 api 返回后,如何判断此次请求应该渲染为正常对话还是组件预览

如果能直接拿到整条消息,那倒是可以尝试去解析格式之类的,但要注意,对话是流式输出,我们不能在最后才进行判断。

这里我的解法是在 dify 平台返回值时,在最前端增加了一个 @component 的标识,如果 steam 读取到的第一个 token@component,则走生成组件的路径。

这样一来,整体的逻辑就完全打通了。

平台实现

平台的技术栈选用了 nextjs,因为必须要请求 dify 的 api,我们需要一个后端来做转发工作,否则会触发跨域,所以 nextjs 这种全栈框架就非常合适了。

简单跟 v0 配合,平台整体做了个七七八八,这种前端活就不赘述了,有兴趣的同学可以查看源码。

image.png

我用 vercel 搭建了一个站点,给大家体验一下。因为使用了我的 api,额度不多,随时可能会挂

image.png

体验地址:v0-online-component-builder.vercel.app/

源码:github.com/imoo666/ai-…

有用就给个 star 吧~

未完成部分

这个平台目前还只是个 demo,有很多东西没有填充。未完项还有:

  • 网页卡顿的厉害,需要优化,因为是直接让 ai 生成了,没仔细看源码
  • 链接知识库,读取私有组件库的代码,这一块实际上在另一个项目里跑通了,但是还没接入此项目中
  • 完善保存功能

总之起个抛砖引玉的作用,诸君共勉