从零开始的技术探索与实践:用Bolt.new、Prompt工程和vLLM打造你的第一个AI应用
大家好,我是你们的B站技术UP主。在大厂搬砖3年,业余时间最喜欢做的事就是把自己踩过的坑整理成教程分享给大家。今天这篇文章,是我应很多粉丝的要求写的——关于如何从零开始进行技术探索与实践。我当初学的时候,最头疼的就是找不到一篇既能讲清楚原理,又能手把手带着做项目的教程。所以今天,我就用这篇文章,带你用最简单的方式入门这三个热门技术:Bolt.new、Prompt工程和vLLM。
一、开篇:我们要学什么?为什么要学?
在开始之前,我们先来搞清楚这三个关键词分别是什么:
| 技术 | 一句话解释 | 核心用途 |
|---|---|---|
| Bolt.new | 一个AI驱动的全栈开发平台 | 通过自然语言描述,快速生成完整的前后端项目 |
| Prompt工程 | 设计优化AI输入提示词的技术 | 让大模型输出更准确、更符合预期的结果 |
| vLLM | 一个高性能的大模型推理引擎 | 快速部署和运行开源大语言模型 |
为什么要把这三个放在一起讲?
因为它们恰好构成了一个完整的AI应用开发链路:
第一步:用 vLLM 部署你自己的大模型(基础设施层)
↓
第二步:用 Prompt工程 让模型输出你想要的结果(交互层)
↓
第三步:用 Bolt.new 快速搭建一个完整的应用(应用层)
我当初学的时候,最大的痛点就是这三块知识是割裂的,网上教程要么只讲Prompt,要么只讲部署,很少有人把它们串起来。所以今天这篇教程,我会带你从零开始,一步步走完整个链路。
二、环境准备:工欲善其事,必先利其器
在开始实战之前,我们需要准备好开发环境。别担心,我会把每一步都写得很详细。
2.1 基础环境清单
| 工具 | 版本要求 | 用途 | 安装方式 |
|---|---|---|---|
| Python | 3.10+ | vLLM运行环境 | 官网下载或conda |
| Node.js | 18+ | Bolt.new本地开发 | 官网下载 |
| Git | 最新版 | 代码版本管理 | 官网下载 |
| CUDA | 12.1+ | GPU加速(可选) | NVIDIA官网 |
| 显卡 | 显存≥16GB | 运行开源模型 | 硬件要求 |
2.2 Python环境搭建
# 第一步:创建虚拟环境
conda create -n ai-practice python=3.10 -y
# 第二步:激活环境
conda activate ai-practice
# 第三步:验证Python版本
python --version
# 期望输出:Python 3.10.x
2.3 vLLM安装
# 安装vLLM(推荐使用pip)
pip install vllm
# 验证安装是否成功
python -c "import vllm; print(vllm.__version__)"
# 期望输出:类似 0.4.x 的版本号
避坑指南:如果你没有NVIDIA GPU,也不用慌。vLLM也支持CPU推理,只是速度会慢很多。后面我会给出CPU版本的配置方法。
2.4 Bolt.new环境
Bolt.new有两种使用方式:
- 在线版:直接访问
https://bolt.new,无需安装,适合快速体验 - 本地版:需要克隆仓库并运行,适合深度定制
# 本地版安装步骤
git clone https://github.com/stackblitz-labs/bolt.new.git
cd bolt.new
npm install
npm run dev
三、核心概念:用最简单的话讲清楚
3.1 什么是vLLM?
官方说法:vLLM是一个快速且易于使用的大语言模型推理和服务库,具有高吞吐量和高效的注意力机制(PagedAttention)。
我的大白话:你可以把vLLM想象成一个"模型翻译官"。你有一个很聪明的大脑(大模型),但它说话很慢。vLLM的作用就是给这个大脑装上一个"加速器",让它能同时处理多个人的问题,而且回答速度飞快。
vLLM的核心优势:
| 特性 | 传统推理 | vLLM |
|---|---|---|
| 内存管理 | 预分配固定内存 | PagedAttention动态管理 |
| 并发处理 | 串行处理请求 | 支持continuous batching |
| 吞吐量 | 较低 | 提升2-4倍 |
| 显存利用率 | 约50% | 可达90%以上 |
3.2 什么是Prompt工程?
官方说法:Prompt工程是设计和优化输入提示(Prompt)以引导语言模型产生期望输出的过程。
我的大白话:Prompt工程就是"跟AI说话的艺术"。就像你问一个聪明但有点轴的朋友问题,你问的方式不同,得到的答案质量天差地别。Prompt工程就是研究怎么问,才能让AI给你最好的回答。
Prompt的基本结构:
一个完整的Prompt通常包含以下要素:
┌─────────────────────────────────┐
│ 1. 角色设定(你是谁) │
│ 2. 任务描述(你要做什么) │
│ 3. 上下文信息(背景资料) │
│ 4. 输出格式(你要怎么回答) │
│ 5. 约束条件(什么不能做) │
└─────────────────────────────────┘
3.3 什么是Bolt.new?
官方说法:Bolt.new是一个AI驱动的全栈Web开发工具,可以通过自然语言描述生成完整的应用程序。
我的大白话:Bolt.new就像是一个"AI程序员"。你只要用大白话告诉它"我想做一个XXX网站",它就能自动帮你把前端、后端、数据库全部搞定,而且代码质量还不错。对于想快速验证想法的开发者来说,简直是神器。
四、实战项目:从零搭建一个AI智能问答应用
好了,概念讲完了,咱们来点真格的。接下来我会带你一步步完成一个实战项目:搭建一个基于本地大模型的智能问答Web应用。
4.1 第一步:用vLLM部署本地大模型
我们先来部署一个开源大模型。这里我选择 Qwen2-7B-Instruct,因为它对中文支持好,而且7B参数量在16GB显存的显卡上就能跑。
创建模型服务脚本 model_server.py:
"""
使用vLLM部署本地大模型服务
"""
from vllm import LLM, SamplingParams
import json
from http.server import HTTPServer, BaseHTTPRequestHandler
# 第一步:初始化模型
print("正在加载模型,请稍候...")
llm = LLM(
model="Qwen/Qwen2-7B-Instruct", # 模型名称,首次运行会自动下载
tensor_parallel_size=1, # GPU数量,单卡设为1
max_model_len=4096, # 最大上下文长度
gpu_memory_utilization=0.9, # GPU显存使用率
trust_remote_code=True, # 信任远程代码
)
print("模型加载完成!")
# 第二步:定义采样参数
sampling_params = SamplingParams(
temperature=0.7, # 温度,控制输出随机性
top_p=0.9, # 核采样概率
max_tokens=1024, # 最大生成token数
repetition_penalty=1.1 # 重复惩罚
)
# 第三步:创建HTTP服务
class ModelHandler(BaseHTTPRequestHandler):
def do_POST(self):
# 获取请求内容
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
request = json.loads(post_data)
# 提取用户输入
user_input = request.get("prompt", "")
# 构造对话格式(ChatML格式)
messages = [
{"role": "system", "content": "你是一个有帮助的AI助手。"},
{"role": "user", "content": user_input}
]
# 使用模型的chat_template
prompt = llm.get_tokenizer().apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
# 生成回答
outputs = llm.generate([prompt], sampling_params)
response_text = outputs[0].outputs[0].text
# 返回结果
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
response = {
"status": "success",
"response": response_text,
"model": "Qwen2-7B-Instruct"
}
self.wfile.write(json.dumps(response, ensure_ascii=False).encode('utf-8'))
def do_OPTIONS(self):
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
self.end_headers()
# 第四步:启动服务
if __name__ == "__main__":
server = HTTPServer(('localhost', 8000), ModelHandler)
print("模型服务已启动,监听端口:8000")
print("测试命令:curl -X POST http://localhost:8000 -H 'Content-Type: application/json' -d '{\"prompt\": \"你好\"}'")
server.serve_forever()
启动模型服务:
# 运行模型服务
python model_server.py
# 另开一个终端,测试服务是否正常
curl -X POST http://localhost:8000 \
-H "Content-Type: application/json" \
-d '{"prompt": "请用一句话介绍你自己"}'
新手常见问题:
- Q:模型下载太慢怎么办? A:可以设置HuggingFace镜像:
export HF_ENDPOINT=https://hf-mirror.com- Q:显存不够怎么办? A:可以换用更小的模型,比如
Qwen2-1.5B-Instruct,或者设置gpu_memory_utilization=0.95
4.2 第二步:设计Prompt模板
模型部署好了,接下来我们来设计Prompt。一个好的Prompt能让模型的回答质量提升一个档次。
创建Prompt模板文件 prompt_templates.py:
"""
Prompt工程:设计高质量的提示词模板
"""
class PromptEngineer:
"""Prompt工程师类,封装常用的Prompt模板"""
@staticmethod
def general_qa(question: str) -> str:
"""通用问答模板"""
template = f"""你是一个知识渊博、逻辑清晰的AI助手。请根据以下要求回答问题:
## 要求:
1. 回答要准确、简洁、有条理
2. 如果涉及多个方面,请使用编号列表
3. 如果不确定答案,请诚实说明
4. 使用通俗易懂的语言
## 用户问题:
{question}
## 你的回答:"""
return template
@staticmethod
def code_explanation(code: str, language: str = "Python") -> str:
"""代码解释模板"""
template = f"""你是一位资深{language}开发工程师。请对以下代码进行详细解释:
## 代码:
```{language.lower()}
{code}
请按以下格式回答:
功能概述:这段代码的整体功能是什么
逐行解析:关键代码行的作用
设计思路:为什么这样写
优化建议:有什么可以改进的地方""" return template
@staticmethod def few_shot_learning(task: str, examples: list, new_input: str) -> str: """少样本学习模板(Few-shot Prompting)""" template = f"""请根据以下示例,完成相同的任务。
任务说明:
{task}
示例:
""" for i, example in enumerate(examples, 1): template += f"\n示例{i}:\n输入:{example['input']}\n输出:{example['output']}\n"
template += f"\n## 现在请处理:\n输入:{new_input}\n输出:"
return template
@staticmethod
def chain_of_thought(question: str) -> str:
"""思维链(Chain of Thought)模板"""
template = f"""请一步步思考以下问题,展示你的推理过程。
问题:
{question}
请按以下步骤回答:
- 理解问题:先分析问题的核心是什么
- 分解问题:将问题拆解为更小的子问题
- 逐步推理:对每个子问题进行推理
- 得出结论:综合以上分析给出最终答案
请开始你的分析:""" return template
测试不同的Prompt模板
if name == "main": pe = PromptEngineer()
# 测试1:通用问答
print("=" * 50)
print("【通用问答模板】")
print(pe.general_qa("什么是大语言模型?"))
# 测试2:代码解释
print("\n" + "=" * 50)
print("【代码解释模板】")
sample_code = """
def fibonacci(n): if n <= 1: return n return fibonacci(n-1) + fibonacci(n-2) """ print(pe.code_explanation(sample_code))
# 测试3:少样本学习
print("\n" + "=" * 50)
print("【少样本学习模板】")
examples = [
{"input": "今天天气真好", "output": "积极"},
{"input": "这个产品太烂了", "output": "消极"},
{"input": "一般般吧", "output": "中性"},
]
print(pe.few_shot_learning("判断以下文本的情感倾向", examples, "这个功能太棒了!"))
# 测试4:思维链
print("\n" + "=" * 50)
print("【思维链模板】")
print(pe.chain_of_thought("一个水池有进水管和出水管,进水管每小时注水3吨,出水管每小时排水2吨,水池容量为30吨,从空池开始,多久能注满?"))
**调用模型并测试Prompt效果**:
```python
"""
测试不同Prompt模板的效果
"""
import requests
from prompt_templates import PromptEngineer
def call_model(prompt: str) -> str:
"""调用本地模型服务"""
response = requests.post(
"http://localhost:8000",
json={"prompt": prompt},
headers={"Content-Type": "application/json"}
)
if response.status_code == 200:
return response.json()["response"]
else:
return f"请求失败:{response.status_code}"
# 测试思维链Prompt
pe = PromptEngineer()
cot_prompt = pe.chain_of_thought(
"小明有10个苹果,给了小红3个,又买了5个,现在有几个?"
)
print("Prompt:")
print(cot_prompt)
print("\n" + "=" * 50)
print("模型回答:")
print(call_model(cot_prompt))
4.3 第三步:用Bolt.new搭建前端应用
现在后端模型和Prompt都准备好了,最后一步是用Bolt.new快速搭建一个Web前端。
在Bolt.new中输入以下Prompt:
请帮我创建一个AI智能问答的Web应用,具体要求如下:
## 技术栈:
- 前端:React + TypeScript + Tailwind CSS
- 后端API:调用 http://localhost:8000 的POST接口
## 功能需求:
1. 一个聊天界面,类似ChatGPT的对话样式
2. 用户可以输入问题,点击发送按钮或按Enter发送
3. 显示AI的回答,支持Markdown渲染
4. 有加载状态提示(发送中...)
5. 支持清空对话历史
6. 左侧有对话历史列表,可以新建对话
## UI要求:
- 整体风格简洁现代
- 深色主题
- 响应式布局,支持手机端
- 消息气泡样式,用户消息靠右,AI消息靠左
## API接口说明:
- URL: POST http://localhost:8000
- 请求体: {"prompt": "用户输入的问题"}
- 响应体: {"status": "success", "response": "AI的回答"}
Bolt.new会生成的核心代码结构:
src/
├── components/
│ ├── ChatMessage.tsx # 单条消息组件
│ ├── ChatInput.tsx # 输入框组件
│ ├── Sidebar.tsx # 侧边栏组件
│ └── MarkdownRenderer.tsx # Markdown渲染组件
├── hooks/
│ └── useChat.ts # 聊天逻辑Hook
├── types/
│ └── index.ts # 类型定义
├── App.tsx # 主应用组件
└── main.tsx # 入口文件
关键的API调用代码(Bolt.new生成):
// src/hooks/useChat.ts
import { useState, useCallback } from 'react';
interface Message {
id: string;
role: 'user' | 'assistant';
content: string;
timestamp: number;
}
interface Conversation {
id: string;
title: string;
messages: Message[];
createdAt: number;
}
export function useChat() {
const [conversations, setConversations] = useState<Conversation[]>([]);
const [currentConvId, setCurrentConvId] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(false);
// 发送消息到AI模型
const sendMessage = useCallback(async (content: string) => {
setIsLoading(true);
try {
// 调用本地模型API
const response = await fetch('http://localhost:8000', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: content }),
});
const data = await response.json();
if (data.status === 'success') {
return data.response;
} else {
throw new Error('模型返回错误');
}
} catch (error) {
console.error('调用模型失败:', error);
throw error;
} finally {
setIsLoading(false);
}
}, []);
// 添加用户消息并获取AI回复
const handleSend = useCallback(async (content: string) => {
const userMessage: Message = {
id: Date.now().toString(),
role: 'user',
content,
timestamp: Date.now(),
};
// 如果没有当前对话,创建新对话
let convId = currentConvId;
if (!convId) {
convId = Date.now().toString();
const newConv: Conversation = {
id: convId,
title: content.slice(0, 20),
messages: [userMessage],
createdAt: Date.now(),
};
setConversations(prev => [newConv, ...prev]);
setCurrentConvId(convId);
} else {
setConversations(prev =>
prev.map(conv =>
conv.id === convId
? { ...conv, messages: [...conv.messages, userMessage] }
: conv
)
);
}
// 获取AI回复
try {
const aiResponse = await sendMessage(content);
const assistantMessage: Message = {
id: (Date.now() + 1).toString(),
role: 'assistant',
content: aiResponse,
timestamp: Date.now(),
};
setConversations(prev =>
prev.map(conv =>
conv.id === convId
? { ...conv, messages: [...conv.messages, assistantMessage] }
: conv
)
);
} catch {
const errorMessage: Message = {
id: (Date.now() + 1).toString(),
role: 'assistant',
content: '抱歉,服务暂时不可用,请稍后重试。',
timestamp: Date.now(),
};
setConversations(prev =>
prev.map(conv =>
conv.id === convId
? { ...conv, messages: [...conv.messages, errorMessage] }
: conv
)
);
}
}, [currentConvId, sendMessage]);
return {
conversations,
currentConvId,
setCurrentConvId,
handleSend,
isLoading,
};
}
主应用组件:
// src/App.tsx
import React from 'react';
import { useChat } from './hooks/useChat';
import { Sidebar } from './components/Sidebar';
import { ChatMessage } from './components/ChatMessage';
import { ChatInput } from './components/ChatInput';
function App() {
const {
conversations,
currentConvId,
setCurrentConvId,
handleSend,
isLoading,
} = useChat();
const currentConv = conversations.find(c => c.id === currentConvId);
return (
<div className="flex h-screen bg-gray-900 text-white">
{/* 侧边栏 */}
<Sidebar
conversations={conversations}
currentConvId={currentConvId}
onSelectConv={setCurrentConvId}
onNewConv={() => setCurrentConvId(null)}
/>
{/* 主聊天区域 */}
<div className="flex-1 flex flex-col">
{/* 消息列表 */}
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{currentConv?.messages.map(msg => (
<ChatMessage key={msg.id} message={msg} />
))}
{isLoading && (
<div className="flex items-center space-x-2 text-gray-400">
<div className="animate-pulse">AI正在思考中...</div>
</div>
)}
</div>
{/* 输入区域 */}
<ChatInput onSend={handleSend} disabled={isLoading} />
</div>
</div>
);
}
export default App;
4.4 完整项目运行流程
步骤1:启动模型服务
┌──────────────────────────────────────┐
│ 终端1:python model_server.py │
│ 输出:模型服务已启动,监听端口:8000 │
└──────────────────────────────────────┘
↓
步骤2:启动前端应用
┌──────────────────────────────────────┐
│ 终端2:cd bolt-new-project && │
│ npm run dev │
│ 输出:Local: http://localhost:5173 │
└──────────────────────────────────────┘
↓
步骤3:打开浏览器访问
┌──────────────────────────────────────┐
│ 浏览器:http://localhost:5173 │
│ 开始和你的AI助手对话吧! │
└──────────────────────────────────────┘
五、常见问题:新手踩坑指南
根据我在B站评论区收集的问题,这里整理了新手最容易遇到的坑:
5.1 环境相关问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
CUDA out of memory |
显存不足 | 换用小模型或降低max_model_len |
ModuleNotFoundError: vllm |
未安装或环境问题 | 确认在正确的conda环境中 |
| 模型下载卡住 | 网络问题 | 设置HF镜像或手动下载模型 |
| CORS跨域错误 | 前后端端口不同 | 后端添加CORS头(代码中已包含) |
5.2 Prompt相关问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 模型回答跑题 | Prompt不够明确 | 增加约束条件和输出格式要求 |
| 回答太长或太短 | 未限制输出长度 | 调整max_tokens参数 |
| 回答重复 | 采样参数问题 | 增加repetition_penalty |
| 代码解释不准确 | 缺少上下文 | 在Prompt中补充更多背景信息 |
5.3 Bolt.new相关问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 生成的代码有Bug | AI生成不完美 | 手动调试修改,这是正常的 |
| 样式不符合预期 | Prompt描述不够详细 | 补充更具体的UI要求 |
| API调用失败 | 后端服务未启动 | 确认模型服务正在运行 |
| 页面白屏 | 前端报错 | 打开浏览器开发者工具查看错误 |
六、学习建议:下一步怎么走?
恭喜你完成了第一个AI应用!但这只是开始,下面是我给你的进阶学习路径:
6.1 短期目标(1-2周)
第1周:
├── 深入理解vLLM的PagedAttention原理
├── 尝试部署不同的开源模型(Llama3、ChatGLM等)
└── 练习编写更多Prompt模板
第2周:
├── 给应用添加流式输出(Streaming)
├── 实现对话历史的本地存储
└── 尝试RAG(检索增强生成)
6.2 中期目标(1-2月)
- 学习模型微调(Fine-tuning),让模型更懂你的业务
- 研究多模态模型(支持图片、音频输入)
- 学习模型量化技术(GGUF、GPTQ),在更低配置上运行
- 搭建完整的AI应用架构(鉴权、限流、监控)
6.3 长期目标(3-6月)
- 深入理解Transformer架构
- 学习分布式推理和训练
- 研究Agent(智能体)技术
- 关注前沿论文,跟进最新技术进展
6.4 推荐学习资源
| 资源类型 | 推荐内容 | 适合阶段 |
|---|---|---|
| 官方文档 | vLLM官方文档 | 入门到进阶 |
| 视频课程 | B站搜索"大模型部署" | 入门 |
| 开源项目 | LangChain、LlamaIndex | 进阶 |
| 论文 | Attention Is All You Need | 深入理解 |
| 社区 | HuggingFace论坛 | 全程 |
七、总结
回顾一下今天的内容,我们用三个技术完成了一个完整的AI应用:
- vLLM:帮我们快速部署了本地大模型,解决了"模型跑不起来"的问题
- Prompt工程:帮我们设计了高质量的提示词,解决了"模型回答不好"的问题
- Bolt.new:帮我们快速搭建了前端应用,解决了"不会写前端"的问题
我当初学的时候,最大的感悟就是:技术探索最重要的是动手实践。看十遍教程不如自己敲一遍代码。希望这篇教程能帮你迈出AI开发的第一步。
如果这篇文章对你有帮助,欢迎点赞、收藏、转发。有问题可以在评论区留言,我会尽量回复。我们下期见!
作者:大厂3年开发 / B站技术UP主 声明:本文为原创教程,转载请注明出处。 更新:文中代码均已实测,环境为Python 3.10 + vLLM 0.4.x + Node.js 18。


评论 0