- Iniziato a scrivere la CHATBOT...
This commit is contained in:
@@ -21,14 +21,13 @@ const globalTables = require('../tools/globalTables');
|
||||
|
||||
const { ObjectId } = require('mongodb');
|
||||
|
||||
const OpenAI = require("openai");
|
||||
const OpenAI = require('openai');
|
||||
|
||||
const { PassThrough } = require('stream');
|
||||
|
||||
const { spawn } = require('child_process');
|
||||
|
||||
router.post('/getlist', authenticate_noerror, async function (req, res, next) {
|
||||
|
||||
|
||||
try {
|
||||
let idapp = req.body.idapp;
|
||||
|
||||
@@ -36,26 +35,23 @@ router.post('/getlist', authenticate_noerror, async function (req, res, next) {
|
||||
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_OK,
|
||||
queryAIList
|
||||
queryAIList,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
console.error('/getlist', e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
});
|
||||
|
||||
|
||||
async function getDeepSeekResponse(prompt, options) {
|
||||
try {
|
||||
const deepseek = new OpenAI({
|
||||
baseURL: 'https://api.deepseek.com/v1',
|
||||
apiKey: process.env.DS_API_KEY,
|
||||
defaultHeaders: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (!options.withexplain) {
|
||||
@@ -66,10 +62,10 @@ async function getDeepSeekResponse(prompt, options) {
|
||||
}
|
||||
|
||||
const completionStream = await deepseek.chat.completions.create({
|
||||
model: options.model || "deepseek-chat",
|
||||
model: options.model || 'deepseek-chat',
|
||||
messages: [
|
||||
{ role: "system", content: options?.contestsystem || "" },
|
||||
{ role: "user", content: prompt }
|
||||
{ role: 'system', content: options?.contestsystem || '' },
|
||||
{ role: 'user', content: prompt },
|
||||
],
|
||||
temperature: options?.temp || 0.3,
|
||||
max_tokens: options?.max_tokens || 1000,
|
||||
@@ -101,72 +97,147 @@ async function getDeepSeekResponse(prompt, options) {
|
||||
}
|
||||
|
||||
router.post('/ds', authenticate, async (req, res) => {
|
||||
|
||||
const { prompt, options } = req.body;
|
||||
|
||||
const isstream = (options && options?.stream)
|
||||
const isollama = options.model.startsWith('gemma3');
|
||||
|
||||
if (isstream) {
|
||||
// Se lo streaming è abilitato, restituiamo un flusso di dati
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
if (isollama) {
|
||||
// Endpoint per generare una risposta dal modello Ollama
|
||||
const { prompt } = req.body;
|
||||
// const model = "phi:3.8b-mini-4k"; // Modello predefinito
|
||||
const model = options.model;
|
||||
|
||||
if (!prompt) {
|
||||
return res.status(400).json({ error: 'Il prompt è richiesto.' });
|
||||
}
|
||||
|
||||
try {
|
||||
// Ottieni il flusso di dati da DeepSeek
|
||||
const completionStream = await getDeepSeekResponse(prompt, options);
|
||||
|
||||
for await (const chunk of completionStream) {
|
||||
if (chunk.choices && chunk.choices[0]) {
|
||||
const data = JSON.stringify({ choice: chunk.choices[0] });
|
||||
res.write(`data: ${data}\n\n`);
|
||||
try {
|
||||
const msg = chunk.choices[0].delta.content;
|
||||
if (msg) {
|
||||
console.log(msg);
|
||||
// await tools.sleep(10000)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error: ' + e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Chiamata all'API di Ollama
|
||||
const ollama = spawn('curl', [
|
||||
'-X',
|
||||
'POST',
|
||||
'http://localhost:11434/api/generate',
|
||||
'-H',
|
||||
'Content-Type: application/json',
|
||||
'-d',
|
||||
JSON.stringify({
|
||||
model: model,
|
||||
prompt: prompt,
|
||||
stream: false, // Imposta a true se vuoi una risposta in streaming
|
||||
}),
|
||||
]);
|
||||
|
||||
res.write('data: [DONE]\n\n');
|
||||
res.end();
|
||||
let data = '';
|
||||
let error = '';
|
||||
|
||||
|
||||
} catch (error) {
|
||||
const errorstr = 'DeepSeek API Error:' + (error.response?.data || error.message)
|
||||
console.error(errorstr);
|
||||
|
||||
// In caso di errore durante lo streaming, invia un messaggio di errore
|
||||
const errorData = JSON.stringify({
|
||||
code: server_constants.RIS_CODE_ERR,
|
||||
error: errorstr,
|
||||
ollama.stdout.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.write(`data: ${errorData}\n\n`);
|
||||
res.end();
|
||||
|
||||
ollama.stderr.on('data', (chunk) => {
|
||||
error += chunk;
|
||||
});
|
||||
|
||||
ollama.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
console.error(`Errore Ollama: ${error}`);
|
||||
return res.status(500).json({ error: 'Errore nella generazione del modello.' });
|
||||
}
|
||||
|
||||
try {
|
||||
// Ollama restituisce una risposta JSON
|
||||
const response = JSON.parse(data);
|
||||
const risp = response?.error ? response?.error : response?.response;
|
||||
//res.json({ response: response.response }); // Invia solo la risposta al frontend
|
||||
|
||||
if (response?.error) {
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_ERR,
|
||||
error: risp,
|
||||
});
|
||||
} else {
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_OK,
|
||||
choice: risp,
|
||||
});
|
||||
}
|
||||
} catch (parseError) {
|
||||
console.error('Errore nel parsing della risposta di Ollama:', parseError);
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_ERR,
|
||||
error: 'Errore nella risposta del modello.',
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_ERR,
|
||||
error: 'Errore interno del server.',
|
||||
});
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
// Se lo streaming non è abilitato, restituisci la risposta completa
|
||||
const choice = await getDeepSeekResponse(prompt, options);
|
||||
const isstream = options && options?.stream;
|
||||
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_OK,
|
||||
choice,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorstr = 'DeepSeek API Error:' + (error.response?.data || error.message)
|
||||
console.error(errorstr);
|
||||
if (isstream) {
|
||||
// Se lo streaming è abilitato, restituiamo un flusso di dati
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
|
||||
// In caso di errore senza streaming, restituisci un errore standard
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_ERR,
|
||||
error: errorstr,
|
||||
});
|
||||
try {
|
||||
// Ottieni il flusso di dati da DeepSeek
|
||||
const completionStream = await getDeepSeekResponse(prompt, options);
|
||||
|
||||
for await (const chunk of completionStream) {
|
||||
if (chunk.choices && chunk.choices[0]) {
|
||||
const data = JSON.stringify({ choice: chunk.choices[0] });
|
||||
res.write(`data: ${data}\n\n`);
|
||||
try {
|
||||
const msg = chunk.choices[0].delta.content;
|
||||
if (msg) {
|
||||
console.log(msg);
|
||||
// await tools.sleep(10000)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error: ' + e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.write('data: [DONE]\n\n');
|
||||
res.end();
|
||||
} catch (error) {
|
||||
const errorstr = 'API Error:' + (error.response?.data || error.message);
|
||||
console.error(errorstr);
|
||||
|
||||
// In caso di errore durante lo streaming, invia un messaggio di errore
|
||||
const errorData = JSON.stringify({
|
||||
code: server_constants.RIS_CODE_ERR,
|
||||
error: errorstr,
|
||||
});
|
||||
res.write(`data: ${errorData}\n\n`);
|
||||
res.end();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
// Se lo streaming non è abilitato, restituisci la risposta completa
|
||||
const choice = await getDeepSeekResponse(prompt, options);
|
||||
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_OK,
|
||||
choice,
|
||||
});
|
||||
} catch (error) {
|
||||
const errorstr = 'API Error:' + (error.response?.data || error.message);
|
||||
console.error(errorstr);
|
||||
|
||||
// In caso di errore senza streaming, restituisci un errore standard
|
||||
return res.send({
|
||||
code: server_constants.RIS_CODE_ERR,
|
||||
error: errorstr,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -15,6 +15,8 @@ const Author = require('../models/author');
|
||||
|
||||
const tools = require('../tools/general');
|
||||
|
||||
const axios = require('axios');
|
||||
|
||||
router.post('/test-lungo', authenticate, (req, res) => {
|
||||
const timeout = req.body.timeout;
|
||||
|
||||
@@ -453,4 +455,19 @@ router.post('/search-books', authenticate, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
router.post('/chatbot', authenticate, async (req, res) => {
|
||||
try {
|
||||
const response = await axios.post('http://localhost:5005/webhooks/rest/webhook', {
|
||||
sender: 'user',
|
||||
message: req.body.payload.message,
|
||||
});
|
||||
|
||||
res.json(response.data);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
res.status(500).send('Errore nella comunicazione con Rasa');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -11,6 +11,9 @@ const appTelegramDest = [tools.FREEPLANET, tools.FREEPLANET];
|
||||
|
||||
const appTeleg_BotOnGroup = [tools.IDAPP_BOTONGROUP];
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
//PIPPO
|
||||
|
||||
const printf = require('util').format;
|
||||
@@ -31,8 +34,6 @@ const server_constants = require('../tools/server_constants');
|
||||
// const {ListaIngresso} = require('../models/listaingresso');
|
||||
const { MsgTemplate } = require('../models/msg_template');
|
||||
|
||||
const globalTables = require('../tools/globalTables');
|
||||
|
||||
const i18n = require('i18n');
|
||||
|
||||
let url = process.env.URL || 'https://<PUBLIC-URL>';
|
||||
@@ -1386,6 +1387,8 @@ const MyTelegramBot = {
|
||||
|
||||
sendMsgFromSite: async function (idapp, user, params) {
|
||||
try {
|
||||
const globalTables = require('../tools/globalTables');
|
||||
|
||||
let ris = {
|
||||
numrec: 0,
|
||||
nummsgsent: 0,
|
||||
@@ -3810,34 +3813,69 @@ class Telegram {
|
||||
}
|
||||
}
|
||||
|
||||
// Soluzione 3: Implementazione completa con gestione errori e tentativi multipli
|
||||
async sendImageToTelegram(chatId, imageUrl, opt) {
|
||||
try {
|
||||
// Prima prova: invia direttamente l'URL
|
||||
// Primo tentativo: invia direttamente l'URL
|
||||
try {
|
||||
return await this.bot.sendPhoto(chatId, imageUrl, opt);
|
||||
} catch (error) {
|
||||
console.log('Primo tentativo fallito, provo a convertire...');
|
||||
}
|
||||
|
||||
// Seconda prova: scarica e converti in JPG
|
||||
const response = await axios.get(imageUrl, { responseType: 'arraybuffer' });
|
||||
const imageBuffer = Buffer.from(response.data);
|
||||
|
||||
const jpgBuffer = await sharp(imageBuffer).jpeg({ quality: 90 }).toBuffer();
|
||||
console.log('imageUrl', imageUrl);
|
||||
|
||||
// Secondo tentativo: scarica e converte con sharp
|
||||
try {
|
||||
return await this.bot.sendPhoto(chatId, jpgBuffer, opt);
|
||||
} catch (error) {
|
||||
console.log('Secondo tentativo fallito, provo come documento...');
|
||||
const response = await axios.get(imageUrl, { responseType: 'arraybuffer' });
|
||||
const contentType = response.headers['content-type'];
|
||||
const imageBuffer = Buffer.from(response.data);
|
||||
|
||||
if (!contentType.startsWith('image/')) {
|
||||
console.warn('Non è un formato immagine:', contentType);
|
||||
return await this.bot.sendDocument(chatId, imageBuffer, opt);
|
||||
}
|
||||
|
||||
try {
|
||||
const jpgBuffer = await sharp(imageBuffer).jpeg({ quality: 90 }).toBuffer();
|
||||
return await this.bot.sendPhoto(chatId, jpgBuffer, opt);
|
||||
} catch (err) {
|
||||
console.warn('Sharp conversion failed:', err.message);
|
||||
return await this.bot.sendDocument(chatId, imageBuffer, opt);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("Errore nel download dell'immagine, provo con file locale...");
|
||||
}
|
||||
|
||||
// Ultima prova: invia come documento
|
||||
return await this.bot.sendDocument(chatId, imageBuffer, opt);
|
||||
} catch (error) {
|
||||
console.error('Tutti i tentativi di invio sono falliti:', error);
|
||||
// Terzo tentativo: accedi al file localmente
|
||||
try {
|
||||
if (!imageUrl.includes('/upload/')) {
|
||||
throw new Error('URL non contiene "/upload/", impossibile determinare il path locale.');
|
||||
}
|
||||
|
||||
let dirmain = '';
|
||||
|
||||
if (!tools.sulServer()) {
|
||||
dirmain = server_constants.DIR_PUBLIC_LOCALE;
|
||||
}
|
||||
|
||||
const relativePath = imageUrl.split('/upload/')[1]; // es. "profile/surya1977/mygoods/1_module.jpg"
|
||||
const mydir = tools.getdirByIdApp(opt.idapp) + dirmain + server_constants.DIR_UPLOAD;
|
||||
const localPath = path.join(mydir, relativePath);
|
||||
|
||||
console.log('Cerco il file localmente:', localPath);
|
||||
|
||||
const localBuffer = fs.readFileSync(localPath);
|
||||
return await this.bot.sendDocument(chatId, localBuffer, opt);
|
||||
} catch (err) {
|
||||
console.error('Lettura file locale fallita:', err.message);
|
||||
}
|
||||
|
||||
// Se tutto fallisce
|
||||
console.error('Tutti i tentativi di invio sono falliti');
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error('Errore generale:', error);
|
||||
return false;
|
||||
//throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3919,7 +3957,7 @@ class Telegram {
|
||||
}
|
||||
opt.img = tools.fixUrl(opt.img, opt.idapp);
|
||||
console.log('opt.img', opt.img);
|
||||
risSendPhoto = await this.sendImageToTelegram(id, opt.img, { caption: text, ...form }).catch((e) => {
|
||||
risSendPhoto = await this.sendImageToTelegram(id, opt.img, { caption: text, ...form, ...opt }).catch((e) => {
|
||||
let blocked = false;
|
||||
if (e.message.indexOf('Forbidden') > 0 || e.message.indexOf('chat not found') > 0) {
|
||||
blocked = true;
|
||||
@@ -4362,7 +4400,7 @@ if (true) {
|
||||
|
||||
// RISPOSTE ALLE CALLBACK (Bottoni)
|
||||
|
||||
let testo_notifica_di_risposta = ''
|
||||
let testo_notifica_di_risposta = '';
|
||||
|
||||
try {
|
||||
const myclTelegram = getclTelegBytoken(bot.token);
|
||||
@@ -4612,8 +4650,7 @@ if (true) {
|
||||
}
|
||||
|
||||
// CALLBACK DI RISPOSTA AL BOT
|
||||
bot.answerCallbackQuery(callbackQuery.id, { text: testo_notifica_di_risposta } ) ;
|
||||
|
||||
bot.answerCallbackQuery(callbackQuery.id, { text: testo_notifica_di_risposta });
|
||||
} catch (e) {
|
||||
console.error('Error BOT callback_query', e);
|
||||
}
|
||||
|
||||
@@ -5777,8 +5777,7 @@ module.exports = {
|
||||
|
||||
try {
|
||||
// let dir = this.getdirByIdApp(idapp) + dirmain + '/' + this.getDirUpload();
|
||||
let dir = this.getdirByIdApp(idapp);
|
||||
'/' + this.getDirUpload() + shared_consts.getDirectoryImgByTable(table, username) + dirmain;
|
||||
let dir = this.getdirByIdApp(idapp) + '/' + this.getDirUpload() + shared_consts.getDirectoryImgByTable(table, username) + dirmain;
|
||||
|
||||
img = dir + img;
|
||||
|
||||
@@ -5790,7 +5789,7 @@ module.exports = {
|
||||
|
||||
if (!this.sulServer()) {
|
||||
// Finta Immagine
|
||||
img = 'https://riso.app/upload/profile/SoniaVioletFlame/myskills/1000133092.jpg';
|
||||
// img = 'https://riso.app/upload/profile/SoniaVioletFlame/myskills/1000133092.jpg';
|
||||
}
|
||||
|
||||
return img;
|
||||
@@ -5835,15 +5834,15 @@ module.exports = {
|
||||
},
|
||||
|
||||
fixUrl(myurl, idapp) {
|
||||
if (!myurl.startsWith('http')) {
|
||||
return this.getHostByIdApp(idapp) + myurl;
|
||||
}
|
||||
//if (!myurl.startsWith('http')) {
|
||||
// return this.getHostByIdApp(idapp) + myurl;
|
||||
//}
|
||||
if (myurl.startsWith('http://127.0.0.1')) {
|
||||
//myurl = myurl.replace('http://127.0.0.1:8084/', 'https://riso.app/')
|
||||
|
||||
// Se è in locale allora metti una foto finta...
|
||||
myurl =
|
||||
'https://images.unsplash.com/photo-1464047736614-af63643285bf?q=80&w=2874&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D';
|
||||
// myurl =
|
||||
// 'https://images.unsplash.com/photo-1464047736614-af63643285bf?q=80&w=2874&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D';
|
||||
//myurl = myurl.replace('http://127.0.0.1', 'http://localhost')
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user