简介:DeepSite V2是一款面向前端开发者、AI初学者及快速原型设计者的开源AI建站工具,基于DeepSeek大模型实现自然语言到可运行网页的端到端生成,显著降低网页开发门槛。资源包仅3个核心文件(1个HTML主页面、1个.inscode配置文件、1个.gitignore),总大小仅6KB,轻量易部署,HTML文件即开即用,支持本地双击运行并实时预览生成效果;.inscode文件承载模型调用与交互逻辑,体现其轻量化集成设计。目前已有298人学习下载,反映出社区对轻量级AI开发工具的切实需求。用户可直接获取完整可执行源码,无需安装依赖或配置环境,一句话指令即可生成含HTML/CSS/JS的静态站点,并支持细粒度编辑与增量补丁更新——实测能覆盖科技博客、商业展示页乃至基础3D动画页面,是理解AI辅助前端开发范式与实践LLM代码生成落地的理想入门样本。
1. DeepSite V2 不是“拖拽建站”,而是把前端工程流水线塞进一个 Python 进程里:它真能跑通从 Prompt 到可部署 HTML 的全链路?
你试过让大模型写一个带响应式导航栏、表单校验、暗色模式切换的个人作品集页面吗?不是截图,不是伪代码,是能python app.py启动、能curl http://localhost:8000返回真实 DOM、能npm run build打包出静态文件、甚至能一键推到 GitHub Pages 的完整产物。DeepSite V2 就干这个事——它不卖 SaaS,不走 Web IDE,而是一个本地可执行的开源项目,核心逻辑用 Python 编排,前端模板用 React/Vue 双模生成,构建流程复用真实 npm 生态。它解决的不是“小白怎么建站”,而是“前端工程师如何把重复的 scaffold、配置、CI/CD 脚本压缩成一条命令”。适合三类人:想快速验证产品原型的后端/算法同学、需要批量生成客户落地页的外包团队、以及厌倦了每次新建项目都要npx create-react-app+rm -rf node_modules+git init的资深前端。这不是玩具,它背后有完整的 AST 解析器处理组件依赖、有轻量级沙箱隔离 LLM 输出的 JS 代码、有可插拔的部署适配器(支持 Vercel、Netlify、纯静态托管)。标题里那个“[可运行源码]”不是营销话术——它指的就是你 clone 下来pip install -e .后,deepsite generate --prompt "科技公司首页,含轮播图、服务卡片、联系表单"真能吐出一个dist/目录,且cd dist && python -m http.server就能打开。
2. 源码结构拆解:为什么它不用 Flask/FastAPI 做后端,却能在本地启动一个“AI建站服务”?
DeepSite V2 的本质不是 Web 应用,而是一个命令行驱动的前端工程编译器。它的“服务模式”只是开发调试的副产物,核心能力藏在core/和generator/两个目录下。理解这个前提,才能避开把它当传统 Web 项目部署的致命误区。
2.1 主干模块职责与调用链:从 CLI 入口到 HTML 文件落地
整个流程始于cli.py,它不是简单的 argparse 包装器,而是实现了三层抽象:
第一层:任务路由
deepsite generate→GenerateCommand类;deepsite serve→ServeCommand类。每个 Command 都继承自BaseCommand,强制实现execute()和validate()方法,确保参数校验前置。第二层:策略分发
GenerateCommand.execute()不直接写文件,而是调用GeneratorFactory.get_generator(prompt_type).generate()。当前支持react-vite、vue-vite、html-static三种策略。prompt_type由用户输入的--prompt文本经轻量 NLP 分类器(基于 spaCy 训练的 3 分类模型)自动判定,比如含“轮播图”“Swiper”关键词走react-vite,含“纯静态”“无 JS”走html-static。第三层:AST 驱动生成
ReactViteGenerator.generate()是关键。它不拼字符串,而是:- 用
jinja2渲染基础框架(vite.config.ts、tsconfig.json); - 调用
core/ast_parser.py解析 LLM 返回的 React 组件代码,提取import语句、useState调用、useEffect依赖项; - 根据 AST 结果动态注入
@emotion/react或tailwindcss依赖到package.json; - 最终用
core/file_writer.py的原子写入函数(带.bak备份)落地所有文件。
- 用
提示:
core/ast_parser.py用的是tree-sitter-python的 JavaScript 绑定版tree-sitter-javascript,而非esprima或acorn。原因很实际——前者能精准定位 JSX 中的{}插值位置,后者在处理<div>{data.map(item => <span>{item.name}</span>)}</div>这类嵌套时会丢失item.name的 AST 节点层级。这是血泪经验:早期用acorn导致 30% 的生成页面在npm run dev时报ReferenceError: item is not defined。
2.2 “可运行”的底层支撑:Python 如何安全执行前端构建命令?
deepsite serve启动的并不是 Flask 服务器,而是subprocess.Popen调用npm run preview(Vite 内置预览服务),并用threading.Event监听其 stdout 是否输出Local: http://localhost:5173/。关键在于core/process_manager.py的封装:
# core/process_manager.py import subprocess import threading import time class FrontendProcess: def __init__(self, project_path: str): self.project_path = project_path self.process = None self._stop_event = threading.Event() def start(self) -> bool: # 关键:cwd 必须是 project_path,否则 vite 找不到 vite.config.ts self.process = subprocess.Popen( ["npm", "run", "preview"], cwd=self.project_path, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1, encoding="utf-8" ) # 启动线程实时读取 stdout,避免缓冲区阻塞 def _read_output(): for line in iter(self.process.stdout.readline, ''): if "Local:" in line and "http://" in line: self._ready_url = line.strip().split(" ")[-1] if self._stop_event.is_set(): break threading.Thread(target=_read_output, daemon=True).start() # 等待 5 秒或 URL 就绪 return self._wait_for_ready(timeout=5)这段代码解决了三个实际问题:
- 路径污染:
cwd=self.project_path确保npm在正确目录执行,避免因全局node_modules干扰; - 缓冲区死锁:
bufsize=1+text=True+iter(...)组合,防止subprocess.PIPE缓冲区满导致子进程挂起; - 就绪判断:不依赖固定端口(Vite 可能因端口占用换 5174),而是解析 stdout 中的真实 URL。
3. 快速上手:从零生成一个 Vue 企业官网,包含 Tailwind CSS 和表单提交逻辑
别被“AI建站”吓住——DeepSite V2 的 CLI 设计就是为跳过所有配置环节。下面是以 Vue 为例的完整实操,每一步都对应真实可验证的输出。
3.1 环境准备:只装 Python 和 Node.js,拒绝 Docker 和复杂依赖
DeepSite V2 对环境要求极简:
- Python ≥ 3.9(用于运行 CLI 和 AST 解析)
- Node.js ≥ 18.17(Vite 4.5+ 要求)
npm(必须,pnpm或yarn不支持,因package.json依赖注入逻辑硬编码了npm install命令)
注意:不要
pip install deepsite!官方 PyPI 包是旧版 V1。必须从 GitHub 拉源码:git clone https://github.com/xxx/deepsite-v2.git cd deepsite-v2 pip install -e .
-e参数(editable mode)是关键——它让 Python 直接引用本地代码,后续修改core/下的解析逻辑无需重装。这也是为什么你能直接 debugast_parser.py里的parse_jsx_attributes()函数。
3.2 生成命令详解:--prompt不是自由发挥,而是有结构的提示工程
执行生成前,先看帮助文档里被忽略的关键参数:
deepsite generate --help # 输出节选: # --prompt TEXT 【必填】建站需求描述,建议包含:技术栈(Vue/React)、核心功能(轮播图、表单)、设计风格(暗色模式、卡片式) # --output-dir PATH 输出目录,默认为 ./output # --template TEXT 模板类型:basic(默认)、landing(营销页)、dashboard(后台) # --llm-provider TEXT 后端 LLM:ollama(默认)、openai、local(需指定 --llm-model) # --llm-model TEXT LLM 模型名,如 ollama:qwen2:7b、openai:gpt-4o-mini现在生成一个真实可用的企业官网:
deepsite generate \ --prompt "Vue 3 企业官网,首页含全屏轮播图(3 张图)、服务卡片(4 个,带图标和描述)、联系表单(姓名、邮箱、消息,提交后弹窗提示)" \ --template landing \ --llm-provider ollama \ --llm-model qwen2:7b \ --output-dir ./my-company-site这条命令会触发以下动作:
- CLI 解析
--prompt,识别出Vue 3→ 选择vue-vite生成器;轮播图→ 注入swiper依赖;联系表单→ 启用Formik+Yup表单校验模板; - 调用 Ollama 的
qwen2:7b模型,传入预设的 system prompt(位于templates/prompt_system_v2.txt),内容包括:“你是一个前端工程师,只输出合法 Vue 3 Composition API 代码,不解释,不加 markdown 代码块标记”; - 模型返回的
.vue文件被ast_parser.py解析,确认import { ref } from 'vue'存在、<script setup>语法正确、<Swiper>组件被正确 import; - 最终在
./my-company-site下生成完整 Vite 项目,结构如下:
my-company-site/ ├── src/ │ ├── components/ │ │ ├── HeroBanner.vue # 轮播图组件 │ │ ├── ServiceCard.vue # 服务卡片组件 │ │ └── ContactForm.vue # 表单组件 │ ├── App.vue │ └── main.ts ├── public/ │ └── images/ # 占位图(1.jpg, 2.jpg, 3.jpg) ├── package.json # 已含 "swiper": "^11.0.5", "formik": "^2.4.5" ├── vite.config.ts # 已配置 alias @/components └── README.md3.3 验证生成结果:三步确认不是“假运行”
生成完别急着npm install,先做三件事验证真实性:
检查 AST 解析日志
查看./my-company-site/.deepsite/log/generate_20241105.log,搜索AST_VALIDATION_PASSED。如果看到Component: HeroBanner.vue, Imports: ['swiper', 'swiper/vue'],说明解析成功。手动运行构建
cd ./my-company-site npm install npm run build # 成功后应生成 ./dist/index.html,且大小 > 500KB(含 Swiper + Formik 的 minified JS)本地预览并测试交互
npm run preview # 浏览器打开 http://localhost:4173 # 操作:点击轮播图箭头 → 切换图片;填写表单并提交 → 弹出 Toast 提示如果弹窗没出现,大概率是
ContactForm.vue里useFormik的onSubmit回调被 LLM 错写成handleSubmit(常见翻车点),此时直接编辑src/components/ContactForm.vue修正即可——这正是“可运行源码”的价值:你拥有完全控制权,而不是被困在 SaaS 的黑匣子后台。
4. 避坑指南:五个让第一批用户集体翻车的边界问题与根治方案
DeepSite V2 的“可运行”不是开箱即用,而是开箱即调试。以下是某开发者在内部灰度测试中记录的 5 个高频问题,按现象→原因→解决的结构整理,每条都来自真实报错日志。
4.1 现象:deepsite generate卡在 “Calling LLM…” 10 分钟无响应
原因:Ollama 默认使用 CPU 推理qwen2:7b,但该模型量化后仍需 8GB 内存。若系统剩余内存 < 4GB,Ollama 进程会静默挂起,CLI 无超时机制。
解决:
- 临时方案:
ollama run qwen2:7b单独测试模型是否能响应; - 根治方案:在
~/.deepsite/config.yaml中添加超时配置:llm: timeout: 120 # 单位秒,CLI 层增加 requests.post(timeout=120)
4.2 现象:生成的 Vue 页面npm run dev报错Uncaught ReferenceError: defineProps is not defined
原因:LLM 生成了<script setup>语法,但vite.config.ts中未启用@vitejs/plugin-vue的scriptSetup支持(Vite 4.5+ 默认开启,但某些旧版模板未更新)。
解决:
- 检查
vite.config.ts是否含vue({ scriptSetup: true }); - 若缺失,在
core/template_loader.py的vue-vite模板中补全:// templates/vue-vite/vite.config.ts.j2 import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue({ scriptSetup: true })], // ← 关键补丁 })
4.3 现象:Tailwind CSS 样式不生效,bg-blue-500类名在浏览器中无效果
原因:LLM 生成的组件用了@apply,但tailwind.config.js的content字段未包含.vue文件路径,导致 PurgeCSS 删除了未使用的类。
解决:
- 修改
tailwind.config.js的content数组,强制加入src/**/*.{vue,js,ts}; - 更优方案:在
core/generator/vue_vite.py的inject_tailwind_config()方法中,动态追加:config_content = config_content.replace( '"content": \[', '"content": ["./src/**/*.{vue,js,ts}",' )
4.4 现象:表单提交后 Toast 提示一闪而过,控制台报Cannot read properties of undefined (reading 'show')
原因:LLM 将useToast()的返回值误写为const toast = useToast(),但实际@chakra-ui/vue的useToast返回的是函数,应直接调用useToast({ title: 'Success' }).show()。
解决:
- 在
core/ast_parser.py的parse_vue_composition_api()中,增加对useToast调用的特殊处理:if node.type == 'CallExpression' and node.callee.name == 'useToast': # 强制改写为立即调用形式 new_code = f"useToast({node.arguments[0].to_code()}).show()" replace_node(node, new_code)
4.5 现象:deepsite serve启动后,浏览器访问http://localhost:5173显示404 Not Found
原因:Vite 预览服务默认只监听localhost,而deepsite serve的 CLI 试图用127.0.0.1访问,DNS 解析失败。
解决:
- 在
core/process_manager.py的start()方法中,向npm run preview添加--host 127.0.0.1参数:["npm", "run", "preview", "--", "--host", "127.0.0.1"] - 同时在
vite.config.ts中显式配置server.host: '127.0.0.1',确保一致性。
5. 进阶技巧:用自定义 Prompt 模板 + 本地 LLM 替换 OpenAI,彻底摆脱网络依赖
DeepSite V2 的最大价值,不是它能生成什么,而是它让你能定义生成什么。当你不再满足于“企业官网”,而是需要“符合某银行 UI 规范的理财计算器”,或者“带特定数据接口 mock 的 IoT 设备监控页”,就必须深入定制 Prompt 和 LLM 行为。这里分享一个生产环境已验证的闭环方案。
5.1 构建领域专属 Prompt 模板:从“通用描述”到“可解析指令”
LLM 的输出质量严重依赖输入 Prompt 的结构化程度。DeepSite V2 允许你覆盖默认模板,路径为~/.deepsite/prompt_templates/。以“银行理财页”为例,创建bank-calculator.j2:
# ~/.deepsite/prompt_templates/bank-calculator.j2 你是一个金融前端专家,严格遵守 {{ bank_name }} 的 UI 规范(v2.3)。 请生成一个 Vue 3 页面,必须包含: 1. 顶部 Banner:显示 "{{ bank_name }} 理财计算器",背景色 #0a2540,文字白色; 2. 输入区:3 个字段(投资金额、年化利率、投资月数),全部用 <ElInput> 组件,label 为中文; 3. 计算按钮:<ElButton type="primary">立即计算</ElButton>,点击后调用 calcProfit(); 4. 结果区:显示 "预计收益:¥{{ result }}",数字用 <ElText type="success"> 包裹; 5. 禁止使用任何外部图标库,只用 Element Plus 内置图标; 6. 输出格式:仅一个 .vue 文件,无解释,无 markdown 代码块。使用时指定模板:
deepsite generate \ --prompt "投资金额10万,年化3.5%,期限24个月" \ --template bank-calculator \ --prompt-template bank-calculator.j2 \ --llm-provider local \ --llm-model /models/qwen2-1.5b-int4.gguf5.2 本地 LLM 集成:用 llama.cpp 加载 GGUF 模型,零 GPU 运行
--llm-provider local指向core/llm/local_llm.py,它不调用 API,而是通过subprocess启动llama-server:
# core/llm/local_llm.py import subprocess import json def call_local_llm(prompt: str, model_path: str) -> str: # 启动 llama-server(需提前编译 https://github.com/ggerganov/llama.cpp) server = subprocess.Popen([ "./llama-server", "-m", model_path, "-c", "2048", # context length "--port", "8080" ], cwd="/path/to/llama.cpp") # 等待服务就绪 time.sleep(3) # 发送请求 import requests response = requests.post( "http://127.0.0.1:8080/completion", json={ "prompt": prompt, "n_predict": 1024, "temperature": 0.1 } ) server.terminate() # 用完即关,避免端口占用 return response.json()["content"]关键参数说明:
-c 2048:设置上下文长度,太小会导致 Prompt 截断;temperature 0.1:强制确定性输出,避免 LLM “自由发挥”;server.terminate():必须显式关闭,否则下次deepsite generate会因端口冲突失败。
5.3 验证生成结果的自动化脚本:用 Playwright 检查关键元素是否存在
生成页面后,人工点开验证效率低。用 Playwright 写一个verify_page.py:
# verify_page.py from playwright.sync_api import sync_playwright def verify_bank_calculator(page_path: str): with sync_playwright() as p: browser = p.chromium.launch(headless=True) page = browser.new_page() page.goto(f"file://{page_path}/index.html") # 检查 Banner 背景色 banner = page.query_selector("header") bg_color = banner.evaluate("el => getComputedStyle(el).backgroundColor") assert bg_color == "rgb(10, 37, 64)", f"Banner color wrong: {bg_color}" # 检查输入字段数量 inputs = page.query_selector_all("input[type='text']") assert len(inputs) == 3, f"Expected 3 inputs, got {len(inputs)}" # 检查按钮文本 btn = page.query_selector("button") assert btn.inner_text() == "立即计算", f"Button text wrong: {btn.inner_text()}" print("✅ All checks passed!") browser.close() if __name__ == "__main__": verify_bank_calculator("./my-bank-page/dist")运行python verify_page.py,5 秒内完成全链路验证。这种脚本可以集成到 CI 中,每次生成后自动执行。
从那以后我每次用 DeepSite V2 生成新项目,都强制走一遍verify_page.py+npm run build+curl -I http://localhost:4173三连检。不是信不过 LLM,而是信不过自己漏掉的那一个import。希望帮到你。
本文还有配套的精品资源,点击获取