Files
AI-webUI-V1/server.js
2026-02-15 23:08:47 +08:00

71 lines
1.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
require("dotenv").config();
const express = require("express");
const helmet = require("helmet");
const rateLimit = require("express-rate-limit");
const app = express();
app.use(helmet());
app.use(express.json({ limit: "1mb" }));
app.use(express.static("public"));
const DEEPSEEK_API_KEY = process.env.DEEPSEEK_API_KEY;
const BASE_URL = process.env.DEEPSEEK_BASE_URL || "https://api.deepseek.com";
if (!DEEPSEEK_API_KEY) {
console.error("Missing env: DEEPSEEK_API_KEY");
process.exit(1);
}
// 只对 API 做限流(防止被刷)
app.use("/api/", rateLimit({
windowMs: 60 * 1000,
max: 60,
standardHeaders: true,
legacyHeaders: false,
}));
app.get("/api/health", (req, res) => {
res.json({ ok: true });
});
// Chat API假设已经由 Nginx Basic Auth 保护了整个站点
app.post("/api/chat", async (req, res) => {
try {
const { model, messages, temperature } = req.body || {};
if (!model || !Array.isArray(messages)) {
return res.status(400).json({ error: "model/messages required" });
}
const r = await fetch(`${BASE_URL}/v1/chat/completions`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${DEEPSEEK_API_KEY}`,
},
body: JSON.stringify({
model, // deepseek-chat / deepseek-reasoner
messages,
temperature: typeof temperature === "number" ? temperature : 0.7,
}),
});
const data = await r.json();
if (!r.ok) {
// 把 DeepSeek 返回透出,方便你排障(不会暴露 API key
return res.status(r.status).json(data);
}
const reply = data?.choices?.[0]?.message?.content ?? "";
return res.json({ reply });
} catch (e) {
return res.status(500).json({ error: String(e) });
}
});
// 只监听本机回环:外网只能走 Nginx更安全
app.listen(3000, "127.0.0.1", () => {
console.log("DS WebUI listening on 127.0.0.1:3000");
});