从零开始的技术探索与实践:用Bolt.new、Prompt工程和vLLM打造你的第一个AI应用

内存泄漏君
2026-07-06 23:06
阅读 640

大家好,我是你们的B站技术UP主。在大厂搬砖3年,业余时间最喜欢做的事就是把自己踩过的坑整理成教程分享给大家。今天这篇文章,是我应很多粉丝的要求写的——关于如何从零开始进行技术探索与实践。我当初学的时候,最头疼的就是找不到一篇既能讲清楚原理,又能手把手带着做项目的教程。所以今天,我就用这篇文章,带你用最简单的方式入门这三个热门技术:Bolt.newPrompt工程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}

请按以下格式回答:

  1. 功能概述:这段代码的整体功能是什么

  2. 逐行解析:关键代码行的作用

  3. 设计思路:为什么这样写

  4. 优化建议:有什么可以改进的地方""" 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}

请按以下步骤回答:

  1. 理解问题:先分析问题的核心是什么
  2. 分解问题:将问题拆解为更小的子问题
  3. 逐步推理:对每个子问题进行推理
  4. 得出结论:综合以上分析给出最终答案

请开始你的分析:""" 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应用:

  1. vLLM:帮我们快速部署了本地大模型,解决了"模型跑不起来"的问题
  2. Prompt工程:帮我们设计了高质量的提示词,解决了"模型回答不好"的问题
  3. Bolt.new:帮我们快速搭建了前端应用,解决了"不会写前端"的问题

我当初学的时候,最大的感悟就是:技术探索最重要的是动手实践。看十遍教程不如自己敲一遍代码。希望这篇教程能帮你迈出AI开发的第一步。

如果这篇文章对你有帮助,欢迎点赞、收藏、转发。有问题可以在评论区留言,我会尽量回复。我们下期见!


作者:大厂3年开发 / B站技术UP主 声明:本文为原创教程,转载请注明出处。 更新:文中代码均已实测,环境为Python 3.10 + vLLM 0.4.x + Node.js 18。

评论 0

最热最新
暂无评论
内存泄漏君Lv.1
0
影响力
0
文章
0
粉丝