从零搭建:json-server+Bootstrap+OpenAI 全栈 AI 小项目

在前后端分离与大模型应用日益普及的当下,我搭建了这个集模拟后端、交互前端、AI 响应于一体的实战项目。

本笔记将详细记录从项目结构搭建、依赖安装,到接口模拟、页面开发、大模型对接的完整流程,核心技术涵盖 json-server 后端模拟、Bootstrap 前端布局、JavaScript fetch 数据交互及 OpenAI API 集成。

通过这个轻量化项目,可快速掌握前后端通信逻辑与大模型的实际应用,适合作为入门级全栈 + AI 开发的实践参考。

初步准备

在启动项目开发前,需完成基础环境与工具的准备,确保后续开发流程顺畅:

  1. 环境配置 :安装 Node.js(推荐 v16+ 版本)及包管理器 pnpm(可通过 npm install -g pnpm 全局安装),用于项目初始化、依赖安装与脚本执行。
  2. 工具准备:选择代码编辑器(如 VS Code),搭配终端工具(系统自带终端或 VS Code 集成终端),方便执行命令与编写代码。
  3. 资源准备:获取 OpenAI API Key(用于大模型服务调用),可通过 OpenAI 官方平台或合法第三方代理平台申请。
  4. 网络环境:确保网络通畅,能够正常访问 npm 镜像源(用于安装依赖)与大模型 API 服务地址。

后端backand

后端初始化详细步骤

  1. 创建项目目录结构

    • 首先,在你选择的存储位置创建一个名为 project 的文件夹。这将作为整个项目的根目录,用于组织所有相关文件和文件夹。
    • 进入 project 文件夹,在其中分别创建 backendfrontendllm 三个文件夹。backend 文件夹将专门用于存放后端相关代码及配置,frontend 用于前端代码,llm 文件夹可用于存放与大语言模型(Large Language Model)相关的文件或代码。
  2. 初始化后端项目并安装依赖

    • 使用终端(Terminal)进入 backend 目录。这是后续后端开发操作的主要工作目录。

    • 在终端中执行 npm init -y 命令。该命令会快速初始化一个 package.json 文件,它是 Node.js 项目的配置文件, -y 参数表示采用默认配置,无需手动确认各项设置。

    • 接着执行 pnpm i json - server 命令。pnpm 是一个快速高效的 Node.js 包管理器,此命令会安装 json - server 这个工具。json - server 能够根据提供的 JSON 文件快速搭建一个 RESTful API 服务器,方便后端开发时模拟数据接口。

bash 复制代码
pnpm i json - server
bash 复制代码
pnpm i json - server
  1. 准备模拟数据

    • backend 目录下创建一个名为 users.json 的文件,并在其中添加一些自定义数据。例如:
json 复制代码
{
    "users":[
        {
            "id":1,
            "username":"刘",
            "hometown":"萍乡"
        },
        {
            "id":2,
            "username":"徐",
            "hometown":"上饶"
        },
        {
            "id":3,
            "username":"薛",
            "hometown":"赣州"
        },
        {
            "id":4,
            "username":"瞿",
            "hometown":"宜春"
        }
    ]
}

这里的数据结构和内容你可以根据实际需求随意调整,它将作为模拟 API 的数据来源。

  1. 配置启动脚本
  • 打开 backend 目录下的 package.json 文件,找到 "scripts" 字段。在其中添加一个新的脚本配置 "dev":"json - server --watch users.json --port 3001"。此脚本定义了通过 json - server 启动模拟服务器的方式,--watch 参数表示监听 users.json 文件的变化,一旦文件内容更新,服务器会自动重新加载数据;--port 3001 则指定服务器运行在端口 3001 上。

完成以上步骤后,你就初步完成了后端的初始化设置,一个基于 json - server 的简单后端模拟服务器已准备就绪,可以为前端开发提供数据接口模拟服务。

前端代码实现解析

前端代码构建了一个具有用户数据展示和问题提交功能的页面,利用了 Bootstrap 框架进行页面布局,并通过 JavaScriptfetch 方法与后端进行数据交互。以下是详细的代码分析:

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF - 8">
    <!-- 设置视口,确保页面在不同设备上正确显示 -->
    <meta name="viewport" content="width=device - width, initial - scale = 1.0">
    <title>Users Chatbot</title>
    <!-- 引入Bootstrap CSS文件,为页面提供预定义的样式和布局类 -->
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter - bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>
    <!-- Bootstrap的.container类创建一个响应式的固定宽度容器,用于包裹页面主要内容 -->
    <div class="container">
        <!-- 创建一个.row类的行容器,用于水平排列其子元素 -->
        <div class="row">
            <!--.col - md - 6表示在中等及以上屏幕宽度时占6列宽度,.col - md - offset - 3表示偏移3列,使表格在页面中居中 -->
            <div class="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>
                        <!-- 表格主体部分,后续将通过JavaScript动态填充用户数据 -->
                    </tbody>
                </table>
            </div>
        </div>
        <div class="row">
            <!-- 定义一个表单,用户可在其中输入问题并提交 -->
            <form name="aiForm">
                <div class="form - group">
                    <label for="questionInput">请输入问题:</label>
                    <!-- 文本输入框,用于用户输入问题,required属性确保输入框不能为空 -->
                    <input type="text" class="form - control" id="questionInput" name="question" required
                        placeholder="请输入问题">
                </div>
                <div class="form - group">
                    <!-- 提交按钮,样式为Bootstrap的primary风格 -->
                    <button type="submit" class="btn btn - primary">提交</button>
                </div>
            </form>
        </div>
        <!-- 用于显示后端返回回答消息的区域 -->
        <div class="row" id="message"></div>
    </div>
    <script>
        // 获取名为aiForm的表单元素,用于监听提交事件
        const oForm = document.forms["aiForm"];
        // 获取id为user_table的表格中的tbody元素,用于动态添加用户数据行
        const oBody = document.querySelector('#user_table tbody');
        // 获取页面中的按钮元素,用于在提交过程中禁用和启用
        const oBtn = document.querySelector(".btn");
        // 声明一个变量users,用于存储从后端获取的用户数据
        let users;

        // 为表单的提交事件添加监听器
        oForm.addEventListener("submit", (event) => {
            // 阻止表单的默认提交行为,防止页面刷新
            event.preventDefault();
            // 获取用户在表单中输入的问题
            const question = oForm["question"].value;

            // 检查用户是否输入了问题,如果没有则提示并终止后续操作
            if (!question) {
                alert("请输入问题");
                return;
            }

            // 禁用提交按钮,避免用户重复提交
            oBtn.disabled = true;

            // 构造请求URL,包含用户输入的问题以及从后端获取的用户数据(若有)
            const requestUrl = `http://localhost:1314/?question=${question}&data=${JSON.stringify(users)}`;
            // 在控制台打印请求URL,方便调试
            console.log(requestUrl);

            // 使用fetch API发送GET请求到指定的后端URL
            fetch(requestUrl)
               .then(res => res.json())
               .then(data => {
                    // 在控制台打印后端返回的数据,方便调试
                    console.log(data);
                    // 启用提交按钮,允许用户再次提交
                    oBtn.disabled = false;
                    // 将后端返回数据中的result字段内容显示在页面的message区域
                    document.getElementById('message').innerHTML = data.result;
                });
        });

        // 使用fetch API发送GET请求到后端获取用户数据
        fetch('http://localhost:3001/users')
           .then(res => res.json())
           .then(data => {
                // 将从后端获取的用户数据存储在users变量中
                users = data;
                // 使用map方法遍历用户数据数组,为每个用户生成一行HTML表格行
                const tableRows = data.map(user => `
                    <tr>
                        <td>${user.id}</td>
                        <td>${user.username}</td>
                        <td>${user.hometown}</td>
                    </tr>
                `).join("");
                // 将生成的表格行添加到表格的tbody元素中,实现用户数据的动态展示
                oBody.innerHTML = tableRows;
            });
    </script>
</body>

</html>

代码说明:

  1. HTML 部分

    • 头部 :设置了页面的字符编码、视口以及引入了 Bootstrap 的 CSS 文件,为页面提供基本样式和布局支持。

    • 主体 : 使用 Bootstrapcontainerrowcol - md - * 类创建了一个响应式布局。表格用于展示用户数据,表单用于用户输入问题并提交,message 区域用于显示后端返回的回答。

  2. JavaScript 部分

    • 变量声明 :获取表单、表格主体和按钮元素,并声明一个变量 users 用于存储从后端获取的用户数据。

    • 表单提交事件

      • 阻止表单默认提交行为,获取用户输入的问题。若问题为空,提示用户并终止操作。
      • 禁用提交按钮,构造请求 URL 并发送 fetch 请求。接收到后端响应后,将数据解析为 JSON 格式,启用按钮,并将后端返回的结果显示在页面上。
    • 获取用户数据 :发送 fetch 请求到后端获取用户数据,将数据解析为 JSON 格式后存储在 users 变量中,并动态生成表格行添加到表格主体,实现用户数据的展示。

通过上述前端代码,实现了页面的布局、用户交互以及与后端的数据通信功能。

大模型项目llm

本项目结合了 HTTP 服务与 OpenAI 的大语言模型(LLM)服务,通过设置环境变量来配置 API Key 和基础 URL,并利用 http 模块创建一个简单的 HTTP 服务器,以接收前端发送的请求并返回基于大模型生成的响应。

  1. 项目初始化与依赖安装

    • 首先,通过 pnpm 安装所需的依赖包:openai 用于与 OpenAI 的 API 进行交互,dotenv 用于加载环境变量。
    • 命令:pnpm i openai dotenv
  2. 环境变量配置

    • 创建一个 .env 文件,用于存储敏感信息,如 OpenAI 的 API Key。
    • .env 文件中添加 OPENAI_API_KEY = your_api_key_here,将 your_api_key_here 替换为你实际的 OpenAI API Key。同时,也可以配置 baseURL,如在代码中设置为 https://api.agicto.cn/v1
  3. index.mjs 代码解析

    • 引入模块
mjs 复制代码
import http from 'http';
import OpenAI from 'openai';
import url from 'url';
import { config } from 'dotenv';

这里引入了 http 模块用于创建 HTTP 服务器,OpenAI 模块来自 openai 包用于与 OpenAI 服务交互,url 模块用于解析 URL,config 函数来自 dotenv 包用于加载环境变量。

  • 加载环境变量
mjs 复制代码
config({
  path: '.env'
});
console.log(process.env.OPENAI_API_KEY, '////');

config 函数加载 .env 文件中的环境变量。console.log 用于调试,打印出加载的 OPENAI_API_KEY,确保环境变量正确加载。

  • 初始化 OpenAI 客户端
mjs 复制代码
const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: 'https://api.agicto.cn/v1'
});

创建一个 OpenAI 客户端实例,传入从环境变量中获取的 API Key 和自定义的 baseURL

  • 定义获取模型响应的函数
mjs 复制代码
// aigc
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;
};

getCompletion 函数是一个异步函数,它接受一个 prompt(提示信息)和一个可选的 model(模型名称,默认为 gpt - 3.5 - turbo)。函数构建一个包含用户角色和提示内容的消息数组,然后使用 client.chat.completions.create 方法向 OpenAI 发送请求,获取模型的回复。temperature 参数控制生成文本的随机性,值越低越确定。

  • 创建 HTTP 服务器
mjs 复制代码
http.createServer(async (req, res) => {
  res.setHeader('Access - Control - Allow - Origin', '*');
  // req, question  data
  const parsedUrl = url.parse(req.url, true);
  // console.log(parsedUrl);
  const prompt = `
  ${parsedUrl.query.data}
  请根据上面的 JSON 数据, 回答${parsedUrl.query.question} 这个问题。
  `;
  const result = await getCompletion(prompt);
  let info = {
    result
  };
  res.status = 200;
  res.setHeader('Content - Type', 'application/json');
  res.end(JSON.stringify(info));
}).listen(1314);

创建一个 HTTP 服务器,监听在端口 1314。对于每个请求,设置响应头允许跨域访问(Access - Control - Allow - Origin: *)。通过 url.parse 解析请求的 URL,获取其中的 dataquestion 参数。构建一个提示信息,将 dataquestion 包含在内,然后调用 getCompletion 函数获取模型的回答。将回答包装在一个对象中,设置响应状态码为 200,响应头 Content - Typeapplication/json,最后将响应数据以 JSON 字符串的形式发送回客户端。

  1. 开发过程中的辅助工具安装与启动

    • 安装 nodemonnodemon 是一个工具,它可以在文件更改时自动重启 Node.js 应用程序,方便开发调试。
    • 命令:npm i -g nodemon-g 表示全局安装)
    • 启动项目 :安装完成后,使用 nodemon index.mjs 命令启动项目。nodemon 会监控 index.mjs 文件及相关依赖文件的变化,一旦有更改,自动重启服务器,无需手动停止和启动。

总结

本项目由后端、前端和大模型三部分构成:

  • 后端 :在 project 下的 backend 目录,用 npm init -y 初始化,pnpm i json - server 安装依赖,创建 users.json 模拟数据,在 package.json 配置脚本启动 JSON 服务器。
  • 前端 :基于 Bootstrap 布局,通过 fetch 获取后端 users 数据展示表格。表单提交问题,fetch 向大模型服务请求并展示回答。
  • 大模型(LLM) :在 llm 目录,pnpm 安装 openaidotenv.env 配置 API 密钥等。index.mjs 创建 HTTP 服务器,接收前端请求,调用 OpenAI 模型生成回答并返回。
相关推荐
牛奔7 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
想用offer打牌12 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
崔庆才丨静觅12 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606113 小时前
完成前端时间处理的另一块版图
前端·github·web components
KYGALYX13 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了13 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅13 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅14 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法14 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
崔庆才丨静觅14 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端