从零搭建: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 模型生成回答并返回。
相关推荐
温宇飞2 小时前
CCState:为大型 Web 应用设计的状态管理库
前端
r0ad2 小时前
读诗的时候我却使用了自己研发的Chrome元素截图插件
前端·javascript·chrome
汤姆yu3 小时前
基于springboot的民间救援队救助系统
java·spring boot·后端·救援队
IT_陈寒3 小时前
React性能优化实战:这5个Hooks技巧让我的应用快了40%
前端·人工智能·后端
江天澄3 小时前
HTML5 中常用的语义化标签及其简要说明
前端·html·html5
知识分享小能手3 小时前
jQuery 入门学习教程,从入门到精通, jQuery在HTML5中的应用(16)
前端·javascript·学习·ui·jquery·html5·1024程序员节
美摄科技3 小时前
H5短视频SDK,赋能Web端视频创作革命
前端·音视频
韩立学长3 小时前
基于Springboot的智慧管网灌溉系统i1agupa7(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
一 乐3 小时前
高校教务|教务管理|基于springboot+vue的高校教务管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·教务管理