使用 OpenAI API 构建网页版 AI 聊天助手
本文介绍如何使用 Node.js 和 OpenAI API 构建一个网页版 AI 聊天助手。项目包含前后端交互,前端提供简洁的聊天界面,后端处理 API 请求并维护对话历史。通过 Express 搭建服务器,结合原生 JavaScript 实现消息发送与渲染,支持 Markdown 解析。文章涵盖环境配置、代码实现及运行步骤,重点讲解了环境变量管理、跨域处理及安全部署建议,适合希望快速集成 AI 能力的开发者参考。

本文介绍如何使用 Node.js 和 OpenAI API 构建一个网页版 AI 聊天助手。项目包含前后端交互,前端提供简洁的聊天界面,后端处理 API 请求并维护对话历史。通过 Express 搭建服务器,结合原生 JavaScript 实现消息发送与渲染,支持 Markdown 解析。文章涵盖环境配置、代码实现及运行步骤,重点讲解了环境变量管理、跨域处理及安全部署建议,适合希望快速集成 AI 能力的开发者参考。

随着大语言模型技术的普及,将 AI 能力集成到 Web 应用中已成为开发者的常见需求。本文将详细介绍如何基于 Node.js 和 OpenAI API,从零开始构建一个具备前后端交互能力的网页版 AI 聊天助手。项目涵盖环境搭建、后端服务配置、前端界面实现以及安全部署建议,适合希望快速掌握 AI 应用开发的开发者参考。
在开始之前,请确保您的开发环境满足以下要求:
建议采用以下目录结构组织项目文件:
project-root/
├── .env # 环境变量配置文件
├── ai.js # 后端入口文件
├── package.json # 项目依赖配置
├── public/ # 静态资源目录
│ ├── index.html # 前端页面
│ ├── style.css # 样式表
│ └── script.js # 前端逻辑
└── README.md # 项目说明
在项目根目录下打开终端,执行以下命令初始化项目并安装必要依赖:
npm init -y
npm install express body-parser openai dotenv cors marked
express: Web 应用框架。body-parser: 解析请求体。openai: OpenAI SDK。dotenv: 加载环境变量。cors: 处理跨域资源共享。marked: Markdown 解析库(可选,用于前端渲染)。创建 .env 文件,存储敏感信息,避免硬编码:
PORT=3000
OPENAI_KEY=your_api_key_here
BASE_URL=https://api.302.ai/v1
注意:请勿将
.env文件上传至公共代码仓库(如 GitHub),以免泄露密钥。
在 ai.js 中引入所需模块并配置 OpenAI 客户端:
const express = require("express");
const bodyParser = require("body-parser");
const OpenAI = require("openai");
const dotenv = require("dotenv");
const cors = require("cors");
dotenv.config();
const openai = new OpenAI({
apiKey: process.env.OPENAI_KEY,
baseURL: process.env.BASE_URL || "https://api.openai.com/v1",
});
const app = express();
const port = process.env.PORT || 3000;
启用 JSON 解析和 CORS 支持,允许前端跨域调用:
app.use(bodyParser.json());
app.use(cors());
app.use(express.static("public")); // 托管静态文件
为了保持对话上下文,需维护一个聊天历史数组。注意:在生产环境中,建议使用数据库或 Redis 持久化历史记录,而非仅保存在内存中。
let chatHistory = [{ role: "system", content: "You are a helpful assistant." }];
定义 /chat POST 路由,处理用户消息并返回 AI 回复:
app.post("/chat", async (req, res) => {
const userMessage = req.body.message;
if (!userMessage) {
return res.status(400).json({ error: "Message is required" });
}
// 添加用户消息到历史
chatHistory.push({ role: "user", content: userMessage });
try {
const completion = await openai.chat.completions.create({
messages: chatHistory,
model: "gpt-3.5-turbo",
});
const aiMessage = completion.choices[0].message.content;
// 添加 AI 回复到历史
chatHistory.push({ role: "assistant", content: aiMessage });
res.json({ aiMessage, chatHistory });
} catch (error) {
console.error("API Error:", error);
res.status(500).json({ error: "Failed to process request" });
}
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
在 public/index.html 中构建聊天界面骨架:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI 助手</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<button id="openAiButton" class="button--openai">🤖</button>
<div id="aiWindow" class="ai-window hidden">
<button id="closeButton" class="button--close-window">×</button>
<div id="chatBox" =>
发送
在 public/style.css 中设计简洁美观的界面:
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: sans-serif; background: #f0f2f5; }
.container { position: relative; height: 100vh; }
.button--openai {
position: absolute; bottom: 20px; right: 20px;
width: 50px; height: 50px; border-radius: 50%;
background: #007bff; color: white; border: none; cursor: pointer;
}
.ai-window {
position: absolute; bottom: 80px; right: 20px;
width: 400px; height: 500px; background: white;
border-radius: 10px; box-shadow: 0 5px 15px rgba(0,0,0,0.2);
display: flex; flex-direction: column; : hidden;
}
{ : none ; }
{ : ; : ; : auto; }
{ : ; : solid ; : flex; : ; }
{ : ; : ; : solid ; : ; : none; }
{ : ; : ; : white; : none; : ; : pointer; }
{ : ; : ; : ; : ; }
{ : ; : flex-end; : auto; }
{ : ; : flex-start; }
在 public/script.js 中实现交互逻辑:
document.addEventListener("DOMContentLoaded", function () {
const sendButton = document.getElementById("sendButton");
const closeButton = document.getElementById("closeButton");
const openAiButton = document.getElementById("openAiButton");
const chatBox = document.getElementById("chatBox");
const userInput = document.getElementById("userInput");
const aiWindow = document.getElementById("aiWindow");
// 显示/隐藏窗口
openAiButton.addEventListener("click", () => aiWindow.classList.remove("hidden"));
closeButton.addEventListener("click", () => aiWindow.classList.add("hidden"));
// 调整文本框高度
userInput.addEventListener("input", function() {
this.style.height = "auto";
this.. = .(., ) + ;
});
() {
message = userInput..();
(!message) ;
(message, );
userInput. = ;
userInput.. = ;
sendButton. = ;
{
response = (, {
: ,
: { : },
: .({ message }),
});
(!response.) ();
data = response.();
(data., );
} (error) {
(, );
} {
sendButton. = ;
}
}
() {
div = .();
div. = ;
div. = marked.(text);
chatBox.(div);
chatBox. = chatBox.;
}
sendButton.(, sendMessage);
userInput.(, {
(e. === && !e.) {
e.();
();
}
});
});
.env 文件中已填入正确的 OPENAI_KEY。node ai.js
http://localhost:3000。切勿在前端代码中暴露 API Key。所有涉及密钥的操作必须在后端完成。生产环境中建议使用环境变量注入或密钥管理服务(如 AWS Secrets Manager)。
为防止滥用,建议在 Express 中集成限流中间件(如 express-rate-limit)。同时,可考虑增加简单的身份验证机制,确保只有授权用户能调用接口。
推荐使用 Docker 进行部署,确保环境一致性。示例 Dockerfile:
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["node", "ai.js"]
当前示例仅捕获了网络错误。实际项目中应记录详细日志(如使用 Winston 或 Morgan),以便排查问题。对于敏感信息,确保不打印到控制台。
本文完整演示了如何利用 OpenAI API 构建一个功能完备的网页版 AI 聊天助手。通过 Node.js 后端处理业务逻辑,结合原生 JavaScript 实现流畅的前端交互,并提供了安全部署的最佳实践。开发者可根据实际需求扩展功能,如接入多模态模型、支持语音输入或集成知识库等。希望本教程能为您的 AI 应用开发提供有价值的参考。
注:本文代码示例仅供参考,生产环境请务必加强安全性与稳定性测试。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online