67 lines
3.9 KiB
JavaScript
67 lines
3.9 KiB
JavaScript
const http = require("http");
|
||
const fs = require("fs");
|
||
const path = require("path");
|
||
|
||
const PORT = process.env.PORT || 3000;
|
||
|
||
function body(req) {
|
||
return new Promise((resolve) => {
|
||
let s = "";
|
||
req.on("data", (c) => (s += c));
|
||
req.on("end", () => {
|
||
try { resolve(JSON.parse(s || "{}")); } catch (_) { resolve({}); }
|
||
});
|
||
});
|
||
}
|
||
|
||
async function ai(prompt) {
|
||
const r = await fetch(process.env.AI_BASE_URL + "/chat/completions", {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json", Authorization: "Bearer " + process.env.AI_API_KEY },
|
||
body: JSON.stringify({
|
||
model: process.env.AI_MODEL,
|
||
temperature: 0.4,
|
||
messages: [
|
||
{ role: "system", content: "Сен — артрит, артроз және анкилозды спондилит (Бехтерев ауруы) бар адамдарға арналған көмекші-кеңесші. Қазақ тілінде, жай сөзбен, қысқа әрі нақты жауап бер. Жауабыңда мыналар болсын: 1) шағымды қалай бағалауға болады; 2) қазір не істеу керек (жеңіл қозғалыс, жылу/суық, тыныштық) — жаттығуды тек ауырсынбай ғана орындау керектігін ескерт; 3) дәрі-дәрмекті тек дәрігер тағайындайтынын еске сал, дәрі атын ұсынба; 4) қандай белгілер кезінде дәрігерге шұғыл қаралу керектігін анық жаз (қатты күшейген ауырсыну, қатты ісіну, қызба, аяқ-қолды қозғалта алмау, сезімталдық жоғалуы). Шағымға байланысты пайдалы болса, осы бөлімдерге сілтеме ата: жаттығуларға — «Сайттағы Жаттығу бөлімінде дайын кешен бар» деп, дәрі/мазь/уколға — «Дәрілер және Аптека бөлімдерін қара» деп. Ақырында: «Бұл ақпарат дәрігер кеңесінің орнын баспайды» деп қос. Сен медициналық маман емессің." },
|
||
{ role: "user", content: prompt }
|
||
]
|
||
})
|
||
});
|
||
if (!r.ok) throw new Error("ИИ недоступен, код " + r.status);
|
||
const j = await r.json();
|
||
const out = j.choices?.[0]?.message?.content;
|
||
if (!out) throw new Error("ИИ вернул пустой ответ");
|
||
return out.trim();
|
||
}
|
||
|
||
http.createServer(async (req, res) => {
|
||
const url = req.url.split("?")[0];
|
||
|
||
if (req.method === "POST" && url === "/api/advice") {
|
||
const data = await body(req);
|
||
const text = (data.text || "").trim();
|
||
if (!text) {
|
||
res.writeHead(400, { "Content-Type": "application/json; charset=utf-8" });
|
||
return res.end(JSON.stringify({ ok: false, error: "Хабарлама бос" }));
|
||
}
|
||
try {
|
||
const answer = await ai(text);
|
||
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
|
||
return res.end(JSON.stringify({ ok: true, answer }));
|
||
} catch (e) {
|
||
res.writeHead(502, { "Content-Type": "application/json; charset=utf-8" });
|
||
return res.end(JSON.stringify({ ok: false, error: "ИИ временно недоступен, попробуйте ещё раз" }));
|
||
}
|
||
}
|
||
|
||
let file = url === "/" ? "/index.html" : url;
|
||
const full = path.join(__dirname, file);
|
||
if (full.startsWith(__dirname) && fs.existsSync(full) && fs.statSync(full).isFile()) {
|
||
const ext = path.extname(full);
|
||
const type = ext === ".css" ? "text/css" : ext === ".js" ? "application/javascript" : "text/html";
|
||
res.writeHead(200, { "Content-Type": type + "; charset=utf-8" });
|
||
return res.end(fs.readFileSync(full));
|
||
}
|
||
res.writeHead(404); res.end("Not found");
|
||
}).listen(PORT, () => console.log("Сервер на порту " + PORT));
|