在前后端分离与大模型应用日益普及的当下,我搭建了这个集模拟后端、交互前端、AI 响应于一体的实战项目。
本笔记将详细记录从项目结构搭建、依赖安装,到接口模拟、页面开发、大模型对接的完整流程,核心技术涵盖 json-server 后端模拟、Bootstrap 前端布局、JavaScript fetch 数据交互及 OpenAI API 集成。
通过这个轻量化项目,可快速掌握前后端通信逻辑与大模型的实际应用,适合作为入门级全栈 + AI 开发的实践参考。
初步准备
在启动项目开发前,需完成基础环境与工具的准备,确保后续开发流程顺畅:
- 环境配置:安装 Node.js(推荐 v16+ 版本)及包管理器 pnpm(可通过
npm install -g pnpm全局安装),用于项目初始化、依赖安装与脚本执行。 - 工具准备:选择代码编辑器(如 VS Code),搭配终端工具(系统自带终端或 VS Code 集成终端),方便执行命令与编写代码。
- 资源准备:获取 OpenAI API Key(用于大模型服务调用),可通过 OpenAI 官方平台或合法第三方代理平台申请。
- 网络环境:确保网络通畅,能够正常访问 npm 镜像源(用于安装依赖)与大模型 API 服务地址。
后端backand
后端初始化详细步骤
- 创建项目目录结构:
- 首先,在你选择的存储位置创建一个名为
project的文件夹。这将作为整个项目的根目录,用于组织所有相关文件和文件夹。 - 进入
project文件夹,在其中分别创建backend、frontend和llm三个文件夹。backend文件夹将专门用于存放后端相关代码及配置,frontend用于前端代码,llm文件夹可用于存放与大语言模型(Large Language Model)相关的文件或代码。
- 首先,在你选择的存储位置创建一个名为
- 初始化后端项目并安装依赖:
- 使用终端(Terminal)进入
backend目录。这是后续后端开发操作的主要工作目录。 - 在终端中执行
npm init -y命令。该命令会快速初始化一个package.json文件,它是 Node.js 项目的配置文件,-y参数表示采用默认配置,无需手动确认各项设置。 - 接着执行
pnpm i json - server命令。pnpm是一个快速高效的 Node.js 包管理器,此命令会安装json - server这个工具。json - server能够根据提供的 JSON 文件快速搭建一个 RESTful API 服务器,方便后端开发时模拟数据接口。
- 使用终端(Terminal)进入
1pnpm i json - server 2
1pnpm i json - server 2
- 准备模拟数据:
- 在
backend目录下创建一个名为users.json的文件,并在其中添加一些自定义数据。例如:
- 在
1{ 2 "users":[ 3 { 4 "id":1, 5 "username":"刘", 6 "hometown":"萍乡" 7 }, 8 { 9 "id":2, 10 "username":"徐", 11 "hometown":"上饶" 12 }, 13 { 14 "id":3, 15 "username":"薛", 16 "hometown":"赣州" 17 }, 18 { 19 "id":4, 20 "username":"瞿", 21 "hometown":"宜春" 22 } 23 ] 24} 25
这里的数据结构和内容你可以根据实际需求随意调整,它将作为模拟 API 的数据来源。
4. 配置启动脚本:
- 打开
backend目录下的package.json文件,找到"scripts"字段。在其中添加一个新的脚本配置"dev":"json - server --watch users.json --port 3001"。此脚本定义了通过json - server启动模拟服务器的方式,--watch参数表示监听users.json文件的变化,一旦文件内容更新,服务器会自动重新加载数据;--port 3001则指定服务器运行在端口3001上。
完成以上步骤后,你就初步完成了后端的初始化设置,一个基于
json - server 的简单后端模拟服务器已准备就绪,可以为前端开发提供数据接口模拟服务。
前端代码实现解析
前端代码构建了一个具有用户数据展示和问题提交功能的页面,利用了 Bootstrap 框架进行页面布局,并通过 JavaScript 的 fetch 方法与后端进行数据交互。以下是详细的代码分析:
1<!DOCTYPE html> 2<html lang="en"> 3 4<head> 5 <meta charset="UTF - 8"> 6 <!-- 设置视口,确保页面在不同设备上正确显示 --> 7 <meta name="viewport" content="width=device - width, initial - scale = 1.0"> 8 <title>Users Chatbot</title> 9 <!-- 引入Bootstrap CSS文件,为页面提供预定义的样式和布局类 --> 10 <link href="https://cdn.bootcdn.net/ajax/libs/twitter - bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> 11</head> 12 13<body> 14 <!-- Bootstrap的.container类创建一个响应式的固定宽度容器,用于包裹页面主要内容 --> 15 <div class="container"> 16 <!-- 创建一个.row类的行容器,用于水平排列其子元素 --> 17 <div class="row"> 18 <!--.col - md - 6表示在中等及以上屏幕宽度时占6列宽度,.col - md - offset - 3表示偏移3列,使表格在页面中居中 --> 19 <div class="col - md - 6 col - md - offset - 3"> 20 <table class="table table - striped" id="user_table"> 21 <!-- 表格头部,定义了表格各列的标题 --> 22 <thead> 23 <tr> 24 <th>ID</th> 25 <th>姓名</th> 26 <th>家乡</th> 27 </tr> 28 </thead> 29 <tbody> 30 <!-- 表格主体部分,后续将通过JavaScript动态填充用户数据 --> 31 </tbody> 32 </table> 33 </div> 34 </div> 35 <div class="row"> 36 <!-- 定义一个表单,用户可在其中输入问题并提交 --> 37 <form name="aiForm"> 38 <div class="form - group"> 39 <label for="questionInput">请输入问题:</label> 40 <!-- 文本输入框,用于用户输入问题,required属性确保输入框不能为空 --> 41 <input type="text" class="form - control" id="questionInput" name="question" required 42 placeholder="请输入问题"> 43 </div> 44 <div class="form - group"> 45 <!-- 提交按钮,样式为Bootstrap的primary风格 --> 46 <button type="submit" class="btn btn - primary">提交</button> 47 </div> 48 </form> 49 </div> 50 <!-- 用于显示后端返回回答消息的区域 --> 51 <div class="row" id="message"></div> 52 </div> 53 <script> 54 // 获取名为aiForm的表单元素,用于监听提交事件 55 const oForm = document.forms["aiForm"]; 56 // 获取id为user_table的表格中的tbody元素,用于动态添加用户数据行 57 const oBody = document.querySelector('#user_table tbody'); 58 // 获取页面中的按钮元素,用于在提交过程中禁用和启用 59 const oBtn = document.querySelector(".btn"); 60 // 声明一个变量users,用于存储从后端获取的用户数据 61 let users; 62 63 // 为表单的提交事件添加监听器 64 oForm.addEventListener("submit", (event) => { 65 // 阻止表单的默认提交行为,防止页面刷新 66 event.preventDefault(); 67 // 获取用户在表单中输入的问题 68 const question = oForm["question"].value; 69 70 // 检查用户是否输入了问题,如果没有则提示并终止后续操作 71 if (!question) { 72 alert("请输入问题"); 73 return; 74 } 75 76 // 禁用提交按钮,避免用户重复提交 77 oBtn.disabled = true; 78 79 // 构造请求URL,包含用户输入的问题以及从后端获取的用户数据(若有) 80 const requestUrl = [`http://localhost:1314/?question=${question}&data=${JSON.stringify(users)}`](http://localhost:1314/?question=${question}&data=${JSON.stringify(users)}); 81 // 在控制台打印请求URL,方便调试 82 console.log(requestUrl); 83 84 // 使用fetch API发送GET请求到指定的后端URL 85 fetch(requestUrl) 86 .then(res => res.json()) 87 .then(data => { 88 // 在控制台打印后端返回的数据,方便调试 89 console.log(data); 90 // 启用提交按钮,允许用户再次提交 91 oBtn.disabled = false; 92 // 将后端返回数据中的result字段内容显示在页面的message区域 93 document.getElementById('message').innerHTML = data.result; 94 }); 95 }); 96 97 // 使用fetch API发送GET请求到后端获取用户数据 98 fetch('http://localhost:3001/users') 99 .then(res => res.json()) 100 .then(data => { 101 // 将从后端获取的用户数据存储在users变量中 102 users = data; 103 // 使用map方法遍历用户数据数组,为每个用户生成一行HTML表格行 104 const tableRows = data.map(user => ` 105 <tr> 106 <td>${user.id}</td> 107 <td>${user.username}</td> 108 <td>${user.hometown}</td> 109 </tr> 110 `).join(""); 111 // 将生成的表格行添加到表格的tbody元素中,实现用户数据的动态展示 112 oBody.innerHTML = tableRows; 113 }); 114 </script> 115</body> 116 117</html> 118
代码说明:
- HTML 部分:
- 头部:设置了页面的字符编码、视口以及引入了
Bootstrap的 CSS 文件,为页面提供基本样式和布局支持。 - 主体: 使用
Bootstrap的container、row和col - md - *类创建了一个响应式布局。表格用于展示用户数据,表单用于用户输入问题并提交,message区域用于显示后端返回的回答。
- 头部:设置了页面的字符编码、视口以及引入了
- JavaScript 部分:
- 变量声明:获取表单、表格主体和按钮元素,并声明一个变量
users用于存储从后端获取的用户数据。 - 表单提交事件:
* 阻止表单默认提交行为,获取用户输入的问题。若问题为空,提示用户并终止操作。
* 禁用提交按钮,构造请求 URL 并发送fetch请求。接收到后端响应后,将数据解析为 JSON 格式,启用按钮,并将后端返回的结果显示在页面上。 - 获取用户数据:发送
fetch请求到后端获取用户数据,将数据解析为 JSON 格式后存储在users变量中,并动态生成表格行添加到表格主体,实现用户数据的展示。
- 变量声明:获取表单、表格主体和按钮元素,并声明一个变量
通过上述前端代码,实现了页面的布局、用户交互以及与后端的数据通信功能。
大模型项目llm
本项目结合了 HTTP 服务与 OpenAI 的大语言模型(LLM)服务,通过设置环境变量来配置 API Key 和基础 URL,并利用 http 模块创建一个简单的 HTTP 服务器,以接收前端发送的请求并返回基于大模型生成的响应。
- 项目初始化与依赖安装:
- 首先,通过
pnpm安装所需的依赖包:openai用于与 OpenAI 的 API 进行交互,dotenv用于加载环境变量。 - 命令:
pnpm i openai dotenv
- 首先,通过
- 环境变量配置:
- 创建一个
.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。
- 创建一个
index.mjs代码解析:- 引入模块:
1import http from 'http'; 2import OpenAI from 'openai'; 3import url from 'url'; 4import { config } from 'dotenv'; 5
这里引入了 http 模块用于创建 HTTP 服务器,OpenAI 模块来自 openai 包用于与 OpenAI 服务交互,url 模块用于解析 URL,config 函数来自 dotenv 包用于加载环境变量。
- 加载环境变量:
1config({ 2 path: '.env' 3}); 4console.log(process.env.OPENAI_API_KEY, '////'); 5
config 函数加载 .env 文件中的环境变量。console.log 用于调试,打印出加载的 OPENAI_API_KEY,确保环境变量正确加载。
- 初始化 OpenAI 客户端:
1const client = new OpenAI({ 2 apiKey: process.env.OPENAI_API_KEY, 3 baseURL: 'https://api.agicto.cn/v1' 4}); 5
创建一个 OpenAI 客户端实例,传入从环境变量中获取的 API Key 和自定义的 baseURL。
- 定义获取模型响应的函数:
1// aigc 2const getCompletion = async (prompt, model = 'gpt - 3.5 - turbo') => { 3 const messages = [{ 4 role: 'user', 5 content: prompt 6 }]; 7 const result = await client.chat.completions.create({ 8 model, 9 messages, 10 temperature: 0.1 11 }); 12 return result.choices[0].message.content; 13}; 14
getCompletion 函数是一个异步函数,它接受一个 prompt(提示信息)和一个可选的 model(模型名称,默认为 gpt - 3.5 - turbo)。函数构建一个包含用户角色和提示内容的消息数组,然后使用 client.chat.completions.create 方法向 OpenAI 发送请求,获取模型的回复。temperature 参数控制生成文本的随机性,值越低越确定。
- 创建 HTTP 服务器:
1http.createServer(async (req, res) => { 2 res.setHeader('Access - Control - Allow - Origin', '*'); 3 // req, question data 4 const parsedUrl = url.parse(req.url, true); 5 // console.log(parsedUrl); 6 const prompt = ` 7 ${parsedUrl.query.data} 8 请根据上面的 JSON 数据, 回答${parsedUrl.query.question} 这个问题。 9 `; 10 const result = await getCompletion(prompt); 11 let info = { 12 result 13 }; 14 res.status = 200; 15 res.setHeader('Content - Type', 'application/json'); 16 res.end(JSON.stringify(info)); 17}).listen(1314); 18
创建一个 HTTP 服务器,监听在端口 1314。对于每个请求,设置响应头允许跨域访问(Access - Control - Allow - Origin: *)。通过 url.parse 解析请求的 URL,获取其中的 data 和 question 参数。构建一个提示信息,将 data 和 question 包含在内,然后调用 getCompletion 函数获取模型的回答。将回答包装在一个对象中,设置响应状态码为 200,响应头 Content - Type 为 application/json,最后将响应数据以 JSON 字符串的形式发送回客户端。
- 开发过程中的辅助工具安装与启动:
- 安装
nodemon:nodemon是一个工具,它可以在文件更改时自动重启 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安装openai和dotenv,.env配置 API 密钥等。index.mjs创建 HTTP 服务器,接收前端请求,调用 OpenAI 模型生成回答并返回。