新手友好!50 行代码封装 DeepSeek API,快速搭建 AI 对话网页
新手友好!50 行代码封装 DeepSeek API,快速搭建 AI 对话网页
新手友好!50 行代码封装 DeepSeek API,快速搭建 AI 对话网页
本文适合:刚接触 AI API、想做一个自己的 AI 聊天网页、但又不想一上来就被框架和工程配置劝退的新手。
最近很多同学都想给自己的个人网站、课程作业或者小工具接入 AI 对话功能。其实最小闭环并不复杂:前端输入一句话,后端转发给 DeepSeek API,拿到回复后再返回给前端展示。
我做了一个开源项目 JXL-AI,用原生 Node.js + 原生 HTML/CSS/JS 搭了一个 AI 对话网页,同时保留了图鉴上传、排行榜、小游戏等扩展功能。
项目地址:
https://github.com/Tuoxie423/jxl-ai
在线体验:
https://tuoxie.asia/
如果你觉得项目对新手有帮助,欢迎点一个 Star 支持一下。
一、最终效果
项目里有几个页面:
- 首页:角色展示、小游戏、排行榜、证书生成
- 聊天页:调用 DeepSeek API 和角色对话
- 图鉴页:上传图片并展示
- 开场动画页:角色入场动画
README 里放了截图和 GIF,clone 后可以直接运行:
npm install
npm start
浏览器访问:
http://127.0.0.1:5177
二、为什么不用复杂框架?
很多 AI Web 教程一上来就是:
- Next.js
- LangChain
- 向量数据库
- 登录系统
- 云函数部署
这些当然都很强,但对新手来说有点重。
这篇文章只讲最小闭环:
浏览器输入消息
↓
fetch 请求自己的 Node 后端
↓
Node 后端调用 DeepSeek API
↓
DeepSeek 返回 AI 回复
↓
后端把 reply 返回给浏览器
↓
页面展示回复
只要理解这个流程,你再去学复杂框架就会轻松很多。
三、准备工作
你需要:
- Node.js 22.5+,推荐 Node.js 24+
- 一个 DeepSeek API Key
- 一个普通编辑器
安装依赖:
npm install openai
配置环境变量,不要把 Key 写死到代码里:
export DEEPSEEK_API_KEY="你的 DeepSeek API Key"
Windows PowerShell:
$env:DEEPSEEK_API_KEY="你的 DeepSeek API Key"
四、50 行核心代码:封装 DeepSeek 聊天接口
下面是最小可运行版本,保存为 server.mjs:
import { createServer } from "node:http";
import { readFileSync, existsSync, createReadStream } from "node:fs";
import path from "node:path";
import OpenAI from "openai";
const port = 5177;
const publicDir = path.resolve("public");
const client = new OpenAI({
baseURL: "https://api.deepseek.com",
apiKey: process.env.DEEPSEEK_API_KEY
});
const server = createServer(async (req, res) => {
const url = new URL(req.url, `http://${req.headers.host}`);
if (req.method === "POST" && url.pathname === "/api/chat") {
const body = await readBody(req);
const input = JSON.parse(body || "{}");
const message = String(input.message || "").trim();
if (!message) {
sendJson(res, 400, { error: "message_required" });
return;
}
const completion = await client.chat.completions.create({
model: "deepseek-chat",
messages: [
{ role: "system", content: "你是一个友好的中文 AI 助手。" },
{ role: "user", content: message }
]
});
const reply = completion.choices?.[0]?.message?.content || "我刚刚走神了。";
sendJson(res, 200, { reply });
return;
}
const file = url.pathname === "/" ? "index.html" : url.pathname.slice(1);
const filePath = path.join(publicDir, file);
if (!existsSync(filePath)) {
res.writeHead(404);
res.end("Not found");
return;
}
createReadStream(filePath).pipe(res);
});
server.listen(port, () => {
console.log(`http://127.0.0.1:${port}`);
});
function readBody(req) {
return new Promise(resolve => {
const chunks = [];
req.on("data", chunk => chunks.push(chunk));
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
});
}
function sendJson(res, status, data) {
const body = JSON.stringify(data);
res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" });
res.end(body);
}
上面代码做了三件事:
- 创建一个 Node HTTP 服务
- 暴露
/api/chat接口 - 收到用户消息后调用 DeepSeek API,再把回复返回给前端
五、前端页面:输入消息并展示回复
新建 public/index.html:
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>DeepSeek AI 聊天 Demo</title>
<style>
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: system-ui, "Microsoft YaHei", sans-serif;
background: #f6efe1;
}
main {
width: min(720px, calc(100vw - 32px));
padding: 24px;
border: 2px solid #222;
border-radius: 12px;
background: #fffaf0;
box-shadow: 10px 10px 0 rgba(0,0,0,.12);
}
#messages {
min-height: 320px;
display: grid;
gap: 12px;
align-content: start;
margin-bottom: 16px;
}
.msg {
padding: 12px 14px;
border: 2px solid #222;
border-radius: 10px;
background: white;
}
.user { background: #f3d886; justify-self: end; }
form { display: flex; gap: 10px; }
input { flex: 1; padding: 12px; border: 2px solid #222; border-radius: 8px; }
button { padding: 0 18px; border: 2px solid #222; border-radius: 8px; background: #222; color: white; }
</style>
</head>
<body>
<main>
<h1>DeepSeek AI 聊天 Demo</h1>
<div id="messages"></div>
<form id="form">
<input id="input" placeholder="输入一句话试试">
<button>发送</button>
</form>
</main>
<script>
const form = document.getElementById("form");
const input = document.getElementById("input");
const messages = document.getElementById("messages");
function addMessage(text, type) {
const div = document.createElement("div");
div.className = `msg ${type}`;
div.textContent = text;
messages.appendChild(div);
}
form.addEventListener("submit", async event => {
event.preventDefault();
const text = input.value.trim();
if (!text) return;
addMessage(text, "user");
input.value = "";
addMessage("思考中...", "bot");
const last = messages.lastElementChild;
try {
const res = await fetch("/api/chat", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: text })
});
const data = await res.json();
last.textContent = data.reply || "没有拿到回复";
} catch {
last.textContent = "请求失败,请检查后端服务。";
}
});
</script>
</body>
</html>
运行:
node server.mjs
打开:
http://127.0.0.1:5177
到这里,一个最小 AI 对话网页就跑起来了。
六、调用原理讲清楚
很多新手会卡在“API 到底是怎么调的”。其实可以把它理解成一次普通的 HTTP 请求。
1. 前端不能直接放 API Key
错误做法:
fetch("https://api.deepseek.com/...", {
headers: {
Authorization: "Bearer 你的 Key"
}
});
这样 Key 会暴露在浏览器里,任何人打开开发者工具都能看到。
正确做法:
浏览器 → 你的 Node 后端 → DeepSeek API
API Key 只放在后端环境变量中。
2. messages 是什么?
DeepSeek/OpenAI 兼容接口使用 messages 数组表示对话上下文:
messages: [
{ role: "system", content: "你是一个友好的中文 AI 助手。" },
{ role: "user", content: "你好" }
]
常见 role:
| role | 作用 |
|---|---|
| system | 设定 AI 的身份、语气、规则 |
| user | 用户说的话 |
| assistant | AI 之前回复过的话 |
如果你想让 AI 记住上下文,就把最近几轮 user 和 assistant 一起发给模型。
3. 为什么项目里要保留 history?
单轮对话:
用户:你好
AI:你好呀
多轮对话:
用户:我叫小明
AI:你好小明
用户:我叫什么?
AI:你叫小明
模型本身不会自动记住上一次请求,所以需要前端或后端保存历史,再传给 API。
项目里的聊天页就是把最近几轮 history 发给后端,后端再拼进 messages:
const messages = [
{ role: "system", content: "你是佳小乐,一个温暖、机灵、会鼓励用户的中文互动角色。" },
...history.slice(-10),
{ role: "user", content: userMessage }
];
4. DeepSeek 为什么能用 OpenAI SDK?
DeepSeek 提供了 OpenAI 兼容接口,所以可以这样写:
const client = new OpenAI({
baseURL: "https://api.deepseek.com",
apiKey: process.env.DEEPSEEK_API_KEY
});
关键点是:
- SDK 还是
openai baseURL换成 DeepSeekapiKey换成 DeepSeek 的 Keymodel使用 DeepSeek 支持的模型名
七、开源项目 JXL-AI 做了哪些增强?
上面的 Demo 是最小版,而我的开源项目 JXL-AI 在它基础上做了完整网页:
- AI 角色聊天页
- 聊天失败时本地回复兜底
- 开场动画
- 图片投稿图鉴
- SQLite 排行榜
- 同名用户确认
- 整活证书生成
- Nginx/PM2 部署友好
项目结构:
.
├── server.mjs
├── package.json
├── data/app.db
├── public/
│ ├── index.html
│ ├── chat.html
│ ├── intro.html
│ ├── bestiary.html
│ ├── uploads/
│ └── assets/
└── scripts/check.mjs
八、总结
AI 对话网页的核心并不神秘,本质就是:
前端收集输入
后端保护 API Key
后端请求 DeepSeek
前端展示回复
先跑通这个最小闭环,再去加角色设定、历史上下文、上传、数据库、部署,就会顺很多。
我把完整项目开源了:
https://github.com/Tuoxie423/jxl-ai
如果这篇文章或项目帮你跑通了第一个 AI 网页,欢迎给项目点一个 Star。后续我也会继续更新更多适合新手的 AI Web 实战内容。
更多推荐

所有评论(0)