用 Node.js + OpenAI + Bootstrap 打造一个 AI 全栈应用
在大模型(LLM)技术日益成熟的今天,越来越多开发者开始探索如何将 AI 能力集成到自己的 Web 应用中。本文将带你从零搭建一个简单的 AI 全栈应用:前端展示用户列表,用户输入自然语言问题,后端调用 LLM 接口进行智能问答。
整个项目包含三个核心模块:
- 前端页面:使用 Bootstrap 构建简洁 UI;
- 模拟数据服务:通过
json-server快速提供 RESTful API; - AI 服务中间层:基于 Node.js 搭建 HTTP 服务,对接 OpenAI 兼容接口。
🧱 技术栈概览
| 模块 | 技术 |
|---|---|
| 前端 | HTML + Bootstrap 3 + Fetch API |
| 后端数据服务 | json-server |
| AI 中间层 | Node.js + OpenAI SDK |
| 部署方式 | 本地开发环境 |
🗂️ 项目结构设计
ai-fullstack-app/
├── frontend/ # 前端页面
│ └── index.html
├── backend/ # 数据接口服务
│ ├── users.json
│ └── package.json
├── llm/ # AI 服务中间层
│ ├── server.js
│ └── .env
└── README.md
📦 第一步:准备模拟数据服务(backend)
我们使用 json-server 快速启动一个 REST API。
1. 初始化项目
mkdir backend && cd backend
pnpm init -y
pnpm add json-server@1.0.0-beta.3
2. 创建 users.json
{
"users": [
{ "id": 1, "username": "张山", "hometown": "北京" },
{ "id": 2, "username": "王二", "hometown": "上海" },
{ "id": 3, "username": "李四", "hometown": "广州" },
{ "id": 4, "username": "赵五", "hometown": "深圳" }
]
}
3. 配置启动脚本
{
"scripts": {
"dev": "json-server --watch users.json --port 3001"
}
}
运行 pnpm run dev,即可在 http://localhost:3001/users 访问用户数据。
🤖 第二步:搭建 AI 服务中间层(llm)
该服务接收前端传来的自然语言问题和用户数据,调用 LLM 返回答案。
1. 初始化并安装依赖
mkdir llm && cd llm
pnpm init -y
pnpm add openai dotenv
2. 配置 .env
OpenAI_API_Key=your_api_key_here
⚠️ 注意:请替换为你的实际 API Key,并确保该接口支持
chat/completions(如 Moonshot、DeepSeek、或兼容 OpenAI 的代理服务)。
3. 编写 server.js
import http from 'http';
import OpenAI from 'openai';
import url from 'url';
import { config } from 'dotenv';
config({ path: '.env' });
const client = new OpenAI({
apiKey: process.env.OpenAI_API_Key,
baseURL: 'https://api.agicto.cn/v1', // 替换为你的 LLM 代理地址
});
const getCompletion = async (prompt, model = 'gpt-3.5-turbo') => {
const messages = [{ role: 'user', content: prompt }];
const result = await client.chat.completions.create({
model,
messages,
temperature: 0.1
});
return result.choices[0].message.content;
};
http.createServer(async (req, res) => {
res.setHeader('Access-Control-Allow-Origin', '*');
const parsedUrl = url.parse(req.url, true);
const { question, data } = parsedUrl.query;
if (!question || !data) {
res.statusCode = 400;
return res.end(JSON.stringify({ error: '缺少必要参数' }));
}
const prompt = `${data}\n请根据上面的JSON数据,回答“${question}”这个问题。`;
const result = await getCompletion(prompt);
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ result }));
}).listen(1314, () => {
console.log('AI 服务已启动:http://localhost:1314');
});
运行 node server.js 启动服务。
💻 第三步:构建前端页面(frontend)
使用 Bootstrap 3 快速搭建响应式界面。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>AI 用户助手</title>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="row col-md-6 col-md-offset-3">
<table class="table table-striped" id="user_table">
<thead>
<tr><th>ID</th><th>姓名</th><th>家乡</th></tr>
</thead>
<tbody></tbody>
</table>
</div>
<div class="row">
<form name="aiForm">
<div class="form-group">
<label for="questionInput">请输入问题:</label>
<input type="text" class="form-control" id="questionInput" name="question" required placeholder="例如:谁来自北京?">
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
</div>
<div class="row" id="message" style="margin-top: 20px; padding: 15px; background: #f9f9f9;"></div>
</div>
<script>
const oForm = document.forms["aiForm"];
const oBody = document.querySelector('#user_table tbody');
const oBtn = document.querySelector(".btn");
let users;
// 加载用户数据
fetch('http://localhost:3001/users')
.then(res => res.json())
.then(data => {
users = data;
oBody.innerHTML = data.map(user => `
<tr>
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.hometown}</td>
</tr>
`).join("");
});
// 提交问题
oForm.addEventListener("submit", async (e) => {
e.preventDefault();
const question = oForm.question.value.trim();
if (!question) return alert("请输入问题");
oBtn.disabled = true;
try {
const res = await fetch(
`http://localhost:1314/?question=${encodeURIComponent(question)}&data=${encodeURIComponent(JSON.stringify(users))}`
);
const { result } = await res.json();
document.getElementById("message").innerText = result;
} catch (err) {
console.error(err);
document.getElementById("message").innerText = "请求失败,请检查服务是否启动。";
} finally {
oBtn.disabled = false;
}
});
</script>
</body>
</html>
✅ 关键点说明:
- 使用
encodeURIComponent对 URL 参数编码,避免 JSON 中特殊字符导致解析错误;- 添加 loading 状态防止重复提交;
- 响应区域使用
<div>展示 AI 回答。
▶️ 启动与测试
依次启动三个服务:
# 终端 1:数据服务
cd backend && pnpm run dev
# 终端 2:AI 服务
cd llm && node server.js
# 终端 3:前端页面(可用 VS Code Live Server 或直接双击打开)
# 或使用简易服务器:
npx serve frontend
访问前端页面,你会看到用户表格。尝试提问:
- “谁来自北京?”
- “列出所有用户的名字”
- “张山的 ID 是多少?”
AI 将基于提供的 JSON 数据给出准确回答!
🌟 总结与延伸
这个小项目虽简单,却完整体现了 AI 全栈应用的核心思想:
- 前后端分离:前端专注交互,后端专注逻辑;
- 数据驱动:AI 的输入来源于真实业务数据;
- 低耦合架构:AI 服务作为独立中间层,可复用于多个前端;
- 快速原型验证:借助
json-server和 Bootstrap,10 分钟即可跑通 MVP。
可优化方向:
- 使用 Express 替代原生
http模块,增强路由和错误处理; - 前端改用 Vue/React 提升交互体验;
- 添加请求缓存,避免重复调用 LLM;
- 部署到 Vercel + Render 实现线上演示。
掘金提示:本文适合初级~中级开发者阅读,代码已简化便于理解。实际生产中请务必处理安全性(如 CORS、输入校验、API Key 保密等)。
欢迎点赞、收藏、评论交流!你也可以基于此模板,打造自己的 AI 助手应用 🚀