用 Node.js + OpenAI + Bootstrap 打造一个 AI 全栈应用

129 阅读4分钟

用 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 全栈应用的核心思想:

  1. 前后端分离:前端专注交互,后端专注逻辑;
  2. 数据驱动:AI 的输入来源于真实业务数据;
  3. 低耦合架构:AI 服务作为独立中间层,可复用于多个前端;
  4. 快速原型验证:借助 json-server 和 Bootstrap,10 分钟即可跑通 MVP。

可优化方向:

  • 使用 Express 替代原生 http 模块,增强路由和错误处理;
  • 前端改用 Vue/React 提升交互体验;
  • 添加请求缓存,避免重复调用 LLM;
  • 部署到 Vercel + Render 实现线上演示。

掘金提示:本文适合初级~中级开发者阅读,代码已简化便于理解。实际生产中请务必处理安全性(如 CORS、输入校验、API Key 保密等)。

欢迎点赞、收藏、评论交流!你也可以基于此模板,打造自己的 AI 助手应用 🚀