在前后端分离与大模型应用日益普及的当下,我搭建了这个集模拟后端、交互前端、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 服务器,方便后端开发时模拟数据接口。
-
bash
pnpm i json - server
bash
pnpm i json - server
-
准备模拟数据:
- 在
backend目录下创建一个名为users.json的文件,并在其中添加一些自定义数据。例如:
- 在
json
{
"users":[
{
"id":1,
"username":"刘",
"hometown":"萍乡"
},
{
"id":2,
"username":"徐",
"hometown":"上饶"
},
{
"id":3,
"username":"薛",
"hometown":"赣州"
},
{
"id":4,
"username":"瞿",
"hometown":"宜春"
}
]
}
这里的数据结构和内容你可以根据实际需求随意调整,它将作为模拟 API 的数据来源。
- 配置启动脚本:
- 打开
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 方法与后端进行数据交互。以下是详细的代码分析:
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>
代码说明:
-
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代码解析:- 引入模块:
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,获取其中的 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 模型生成回答并返回。