---
title: "09-工程项目生成"
created: 2025-12-02
tags:
- 项目
aliases:
- 工程项目生成
---
# 工程项目生成
## 本节重点
在前面的章节中,我们已经实现了对话历史功能,让 AI 能够基于历史上下文进行网站的迭代优化。但目前平台只支持生成原生网站,在实际使用中有一定局限性。
本节我们将挑战一个有点儿难度的功能 —— 生成更复杂的前端工程化项目,提高本平台的实用性。
主要内容包括:
- 工程项目生成方案设计
- 工程项目生成(工具调用流式输出)
- 工程项目构建和浏览
- 工程项目部署
- 前端开发
## 一、需求分析
前端工程化项目是指使用现代化工具链、规范化流程和组件化架构来构建的前端应用。相比传统的 HTML、CSS、JavaScript 三件套,它具备模块管理、自动化构建、代码分割、热更新等现代开发特性,能够更轻松地开发复杂网站。
现在很多前端工程化项目都是使用 Vue 或 React 框架,结合 Vite 等打包构建工具,再加上 ESLint 之类的代码规范校验库来实现的。
![[image-c6db36b1.png]]
调研其他平台,美团 NoCode 平台支持 React 工程项目:
![[image-27eb92d8.png]]
我们不妨就以 Vue 作为示例,让平台能够生成完整的 Vue3 + Vite 工程项目,并且跟其他两种生成模式一样,实现流式输出、网站浏览和部署。这样一来,我们的平台也能够生成更符合企业标准的项目。
友情提示,受限于大模型的能力,有时效果可能没有那么理想,但大家重点学习思路和方法。
## 二、方案设计
### 方案选型分析
通过对一些大厂生成平台的调研,我们可以初步想到 3 种复杂工程项目的生成方案。
### 方案 1 - 直接输出 Markdown
这种方案延续之前的思路,直接让 AI 在输出的 Markdown 中包含代码块,然后通过解析的方式保存文件。
```text
这是我生成的项目:
```vue
App.vue ```
``` json
package.json ```
```
优点是实现简单、好理解、实时展示效果好。但缺点也很明显:如果代码量较大,一次对话可能无法完整输出,容易出现代码不全或者解析错误的情况。
### 方案 2 - 工具调用
给 AI 提供保存文件等工具,让 AI 来决定什么时候保存文件、保存哪些文件、要保存什么代码到文件中。
这种方式的基本实现很简单,不需要自己解析 AI 的输出并保存为文件,全都交给 AI 和框架来处理。
![[image-d033c77c.png]]
但如果想实时展示工具调用信息(比如要保存为文件的代码内容),就很复杂了!你需要解析 AI 响应的工具调用信息。由于流式输出的特性,AI 是一点点将 JSON 格式的工具调用信息 “吐” 出来的,你很难实时从中提取出有意义的、需要返回给用户的工具调用参数。
举个例子,完整的工具调用信息:
```json
{
"id": "123",
"name": "writeFile",
"arguments": {
"relativePath": "src/App.vue",
"content": "网页代码"
}
}
```
但实际上,AI 会流式输出上述信息,比如可能是这样输出的:
```text
"
relative
Path
:
"
src
/
App
.vue
"
content
":
```
也就是说,AI 的输出会把保存文件的路径和写入文件的内容拆开。如果想在前端实时展示出这些信息,就需要比较复杂的拼接逻辑,比如拼接好 relativePath 后,立刻展示出保存文件的路径。
假设这是后端实时返回给前端的工具调用信息,你应该如何解析和拼接参数呢?
```java
data:{"d":"{\\"id\\":\\"call_1_06579b58-4206-4b3e-bd7f-2de949e39783\\",\\"name\\":\\"writeFile\\",\\"arguments\\":\\"{\\\\\\"\\",\\"type\\":\\"tool_request\\"}"}
data:{"d":"relative"}
data:{"d":"FilePath"}
data:{"d":"\\":\\""}
data:{"d":"v"}
data:{"d":"ite"}
data:{"d":".config"}
data:{"d":".js"}
data:{"d":"\\",\\""}
data:{"d":"content"}
data:{"d":"\\":\\""}
data:{"d":"import"}
data:{"d":" {"}
data:{"d":" define"}
data:{"d":"Config"}
data:{"d":" }"}
data:{"d":" from"}
```
想想就很复杂。。。而且不同工具的调用参数是不一样的!
此外,由于我们有对话历史模块,需要尽可能确保实时流式输出的内容和保存到数据库中的对话历史一致,这就进一步增加了开发成本。
### 方案 3 - Agent 模式
智能体(Agent)是指能够感知环境、进行推理、制定计划、做出决策并自主采取行动以实现特定目标的 AI 系统。它以大语言模型为核心,集成 **记忆、知识库和工具** 等能力为一体,构造了完整的决策能力、执行能力和记忆能力,就像一个有主观能动性的人类一样。
简单来说,Agent 的特点是 **先规划再执行**。比如先制定网站生成计划、然后分别在每个步骤中生成一个文件并解析。
```text
步骤 1:我要生成网站文件 page1.vue、page2.vue、page3.vue
步骤 2:生成 page1.vue,然后保存
步骤 3:生成 page2.vue,然后保存
步骤 4:生成 page3.vue,然后保存
步骤 5:生成网站成功,退出执行
```
这样做的优点是,每一个步骤都非常清晰,在步骤内我可以通过工具调用来实现文件保存,也可以单独调用 AI 获取到生成的代码,然后再通过程序保存(就像我们之前一样),这样实现流式输出就很简单了。
此外,由于划分了多个步骤,即使某一个步骤出错,也能中断恢复,从而能够处理长逻辑的复杂任务。像鱼皮之前分享过的 [Flowith 智能体](https://www.bilibili.com/video/BV1QFTJzzENP/),我一句话,让它执行了整整一天!
但 Agent 模式的缺点是整体架构更复杂,需要自己设计 Agent 流程;而且由于需要多次调用 AI,输出结果更加不可控,成本也更高。
💡 在 [编程导航的 AI 超级智能体项目](https://www.codefather.cn/course/1915010091721236482) 中,鱼皮带大家分析了 OpenManus 智能体的源码,并且复刻了一个 Java 智能体,感兴趣的同学可以学习。
---
从美团 NoCode 的输出效果来看,很有可能采用了 Agent 模式,每一个步骤都可以做到流式输出,用户能即时看到生成的代码内容和 AI 的操作情况。
![[image-aba66b23.png]]
刷新页面后,你依然能看到上面的内容,跟实时流式输出时用户看到的效果一样。
这是怎么做到的呢?美团是怎么维护对话历史的呢?
通过分析网络请求,我们能获取到后端返回给前端的完整对话信息:
![[image-c849d88d.png]]
原来如此,美团自己约定了一些 **工具标签**,比如 `mc-add-dependency` 安装依赖、`mc-write` 保存文件,这样前端就能识别到展示什么内容了。
```text
"我将为您创建一个复古波普艺术风格的电商网页,包含鲜艳的橙色和粉色撞色背景、漫画风格圆点图案和手绘插图,以及波普画框形式的商品展示区。\\n\\nSTEP 1: 安装必要的依赖\\n\\nframer-motion\\n\\n\\nSTEP 2: 更新首页为复古波普风格电商页面\\n\\nimport { motion } from \\"framer-motion\\";\\nimport { ShoppingBag, Star, Heart } from \\"lucide-react\\";\\n\\nconst Index = () => {\\n const products = [\\n {\\n id: 1,\\n;\\n\\n\\n创建了一个充满活力的复古波普艺术风格电商首页,包含鲜艳的橙色粉色渐变背景、漫画风格圆点图案、波普画框形式的商品展示区以及带有跳跃动画的交互元素。"
```
### 最终方案确定
由于 LangChain4j 本身就支持 AI 多次调用工具,相当于已经实现了基础的 Agent 多步骤执行能力,因此考虑到开发复杂度,我们选择第 2 种方案 - 工具调用。
![[image-bb3226bb.png]]
为了提升用户体验,需要为工具调用支持流式输出能力,但是只流式输出工具调用的基本信息,让用户能看到 AI 调用了哪些工具,避免了复杂的拼接解析逻辑(不利于项目扩展)。
由于不知道要生成多少个文件、以及文件的层级组织关系,需要使用工具调用来写入文件。工具调用中需要特别注意文件路径的处理。如果不使用工具调用,就要输出一大堆的代码块,自己解析,比如下列提示词格式:
```yaml
## 必须遵守下列输出格式
- 你的整个回复必须是一系列 Markdown 代码块
- 每个代码块代表一个完整的文件
- 每个代码块的第一行必须是注释,用 `[FILE_PATH: ...]` 的格式清晰地标明该文件的路径
文件代码块示例:
格式 vue
// [FILE_PATH: src/components/NewComponent.vue]
然后是完整的代码内容
```
### 系统提示词
我们需要定义新的生成模式 Vue 工程模式(vue\_project),这种模式使用 DeepSeek 的推理模型,提供的系统提示词也会更复杂。如下:
```text
你是一位资深的 Vue3 前端架构师,精通现代前端工程化开发、组合式 API、组件化设计和企业级应用架构。
你的任务是根据用户提供的项目描述,创建一个完整的、可运行的 Vue3 工程项目
## 核心技术栈
- Vue 3.x(组合式 API)
- Vite
- Vue Router 4.x
- Node.js 18+ 兼容
## 项目结构
项目根目录/
├── index.html # 入口 HTML 文件
├── package.json # 项目依赖和脚本
├── vite.config.js # Vite 配置文件
├── src/
│ ├── main.js # 应用入口文件
│ ├── App.vue # 根组件
│ ├── router/
│ │ └── index.js # 路由配置
│ ├── components/ # 组件
│ ├── pages/ # 页面
│ ├── utils/ # 工具函数(如果需要)
│ ├── assets/ # 静态资源(如果需要)
│ └── styles/ # 样式文件
└── public/ # 公共静态资源(如果需要)
## 开发约束
1)组件设计:严格遵循单一职责原则,组件具有良好的可复用性和可维护性
2)API 风格:优先使用 Composition API,合理使用 `\\\\n