privet/lib/alem.js

121 lines
4.5 KiB
JavaScript
Raw 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.

"use strict";
const ALEM_TIMEOUT_MS = 600000;
function fetchWithTimeout(url, options, timeoutMs) {
const controller = new AbortController();
const timer = setTimeout(function () { controller.abort(); }, timeoutMs);
return fetch(url, Object.assign({ signal: controller.signal }, options)).finally(function () {
clearTimeout(timer);
});
}
function createAlemSession() {
const url = process.env.ALEM_BASE_URL + "/api/v1/open-api/conversation";
return fetchWithTimeout(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + process.env.ALEM_API_KEY
},
body: JSON.stringify({
template_id: process.env.ALEM_TEMPLATE_ID,
title: "KFU-agent-call",
user_id: "kfu_app"
})
}).then(function (resp) {
if (!resp.ok) throw new Error("Alem create " + resp.status + ": " + resp.statusText);
return resp.json().then(function (body) {
const sid = body && body.data && body.data.session_id;
if (!sid) throw new Error("Alem no session_id: " + JSON.stringify(body).slice(0, 200));
return sid;
});
});
}
function extractSseText(raw) {
var answer = null;
var lines = String(raw).split(String.fromCharCode(10));
for (var i = 0; i < lines.length; i++) {
var s = lines[i].trim();
if (!s.startsWith(String.fromCharCode(100,97,116,97,58))) continue;
var payload = s.slice(5).trim();
if (!payload || payload === String.fromCharCode(91,68,79,78,69,93)) continue;
try {
var ev = JSON.parse(payload);
if (ev && ev.detail && typeof ev.detail.full_content === String.fromCharCode(115,116,114,105,110,103) && ev.detail.full_content) {
answer = ev.detail.full_content;
}
} catch (e) { }
}
return answer || String.fromCharCode(78,101,116,32,101,116,32,111,116,118,101,116);
}
function askAlem(sessionId, message) {
var url = process.env.ALEM_BASE_URL + sendPath(sessionId);
return fetchWithTimeout(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + process.env.ALEM_API_KEY
},
body: JSON.stringify({ content: message, user_id: 'kfu_app', model_api_key: process.env.ALEM_API_KEY })
}, ALEM_TIMEOUT_MS).then(function (resp) {
if (!resp.ok) throw new Error('Alem send ' + resp.status + ': ' + resp.statusText);
return resp.text().then(function (raw) {
return extractSseText(raw);
});
});
}
function sendPath(id) {
return '/api/v1/open-api/conversation/' + id + '/send';
}
function extractJsonFromText(text) {
var s = String(text || '');
var fenceStart = s.indexOf('```');
if (fenceStart !== -1) {
var inner = s.slice(fenceStart + 3);
var langEnd = inner.indexOf('```');
if (langEnd !== -1) inner = inner.slice(langEnd + 3);
var jsonStart = inner.indexOf('{');
var jsonEnd = inner.lastIndexOf('}');
if (jsonStart !== -1 && jsonEnd > jsonStart) {
try { return JSON.parse(inner.slice(jsonStart, jsonEnd + 1)); } catch (e) { }
}
}
var first = s.indexOf('{');
var last = s.lastIndexOf('}');
if (first !== -1 && last > first) {
try { return JSON.parse(s.slice(first, last + 1)); } catch (e) { }
}
return null;
}
function callKfuAgent(company, period, fileText) {
var prompt = [
'Расчёт коэффициентов финансовой устойчивости (КФУ).',
'Компания: ' + company,
'Отчётный период: ' + period,
'Данные отчёта:',
fileText,
'',
'Верни ТОЛЬКО один JSON-объект без пояснений со строгими полями:',
'{company, period, units, debt, ebitda_ltm, interest_ltm, equity, k1, k2, k3, zone_k1, zone_k2, zone_k3, zone_company, flags, sources, comment}.',
'Числа — числом (без слов и валютного знака), zone_* — одно из: зелёная, жёлтая, красная, без оценки.',
'flags — массив строк (пустой, если замечаний нет), sources — объект-источник цифр, comment — краткое замечание (или пустая строка).'
].join("\n");
return createAlemSession().then(function (sid) {
return askAlem(sid, prompt).then(function (text) {
var data = extractJsonFromText(text);
if (!data) throw new Error('Alem не вернул JSON. Ответ: ' + String(text).slice(0, 300));
return data;
});
});
}
module.exports = { callKfuAgent, extractSseText, extractJsonFromText };