add ai_initiatives
This commit is contained in:
@@ -0,0 +1,57 @@
|
|||||||
|
import { Agent } from 'node:https';
|
||||||
|
import { GigaChat } from "langchain-gigachat";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
const httpsAgent = new Agent({
|
||||||
|
rejectUnauthorized: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const llm = new GigaChat({
|
||||||
|
credentials: process.env.GIGA_AUTH,
|
||||||
|
temperature: 0.2,
|
||||||
|
model: 'GigaChat-2',
|
||||||
|
httpsAgent,
|
||||||
|
});
|
||||||
|
|
||||||
|
// возвращаю комментарий + исправленное предложение + булево значение
|
||||||
|
const moderationLlm = llm.withStructuredOutput(z.object({
|
||||||
|
comment: z.string(),
|
||||||
|
fixedText: z.string().optional(),
|
||||||
|
isApproved: z.boolean(),
|
||||||
|
}) as any)
|
||||||
|
|
||||||
|
export const moderationText = async (title: string, body: string): Promise<[string, string | undefined, boolean]> => {
|
||||||
|
const prompt = `
|
||||||
|
Представь, что ты модерируешь предложения от жильцов многоквартирного дома (это личная инициатива по улучшения,
|
||||||
|
не имеющая отношения к Управляющей компании).
|
||||||
|
|
||||||
|
Заголовок: ${title}
|
||||||
|
Основной текст: ${body}
|
||||||
|
|
||||||
|
Твои задачи:
|
||||||
|
1. Проверь предложение и заголовок на спам.
|
||||||
|
2. Проверь, чтобы заголовок и текст были на одну тему.
|
||||||
|
3. Проверь само предложение пользователя на отсутствие грубой лексики и пошлостей.
|
||||||
|
4. Проверь грамматику.
|
||||||
|
5. Проверь на бессмысленность предложения. Оно не должно содержать только случайные символы.
|
||||||
|
6. Не должно быть рекламы, ссылок и т.д.
|
||||||
|
7. Проверь предложение на информативность, оно не должно быть слишком коротким.
|
||||||
|
8. Предложение должно быть в вежливой форме.
|
||||||
|
|
||||||
|
- Если все правила соблюдены, то предложение принимается!
|
||||||
|
|
||||||
|
Правила написания комментария:
|
||||||
|
- Если предложение отклоняется, верни комментарий со следующей формулировкой:
|
||||||
|
"Предложение отклонено. Причина: (укажи проблему)"
|
||||||
|
Правила написания fixedBody:
|
||||||
|
- Если предложение отклонено, то верни в поле "fixedBody" новый текст, который будет соответствовать правилам.
|
||||||
|
- Если предложение отклонено и содержит запрещённый контент (рекламу, личные данные), удали всю информацию,
|
||||||
|
которая противоречит правилам, и верни в только подходящий фрагмент, сохраняя общий смысл.
|
||||||
|
- Если текст не представляет никакой ценности, возврати в поле "fixedBody" правило,
|
||||||
|
по которому оно не прошло.
|
||||||
|
-Если предложение принимается, то ничего не возвращай в поле fixedBody.
|
||||||
|
`
|
||||||
|
const result = await moderationLlm.invoke(prompt);
|
||||||
|
|
||||||
|
return [result.comment, result.fixedText, result.isApproved];
|
||||||
|
};
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { GigaChat, detectImage } from 'gigachat';
|
||||||
|
import { Agent } from 'node:https';
|
||||||
|
|
||||||
|
const httpsAgent = new Agent({
|
||||||
|
rejectUnauthorized: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const llm = new GigaChat({
|
||||||
|
credentials: process.env.GIGA_AUTH,
|
||||||
|
model: 'GigaChat-2',
|
||||||
|
httpsAgent,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const generatePicture = async (prompt: string) => {
|
||||||
|
const resp = await llm.chat({
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
"role": "system",
|
||||||
|
"content": "Ты — Василий Кандинский для жильцов многоквартирного дома"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: `Старайся передать атмосферу уюта и безопасности.
|
||||||
|
Нарисуй картинку подходящую для такого события: ${prompt}
|
||||||
|
В картинке не должно быть текста, только изображение.`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
function_call: 'auto',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Получение изображения по идентификатору
|
||||||
|
const detectedImage = detectImage(resp.choices[0]?.message.content ?? '');
|
||||||
|
const image = await llm.getImage(detectedImage?.uuid ?? '');
|
||||||
|
|
||||||
|
// Возвращаем содержимое изображения
|
||||||
|
return image.content;
|
||||||
|
}
|
||||||
73
server/routers/kfu-m-24-1/sber_mobile/moderate.js
Normal file
73
server/routers/kfu-m-24-1/sber_mobile/moderate.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
const router = require('express').Router();
|
||||||
|
const { moderationText } = require('./initiatives-ai-agents/moderation');
|
||||||
|
const { generatePicture } = require('./initiatives-ai-agents/picture');
|
||||||
|
const { getSupabaseClient } = require('./supabaseClient');
|
||||||
|
|
||||||
|
// Обработчик для модерации текста
|
||||||
|
router.post('/moderate', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { title, body } = req.body;
|
||||||
|
if (!title || !body) {
|
||||||
|
res.status(400).json({ error: 'Заголовок и текст обязательны' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [comment, fixedText, isApproved] = await moderationText(title, body);
|
||||||
|
res.json({
|
||||||
|
comment,
|
||||||
|
fixedText,
|
||||||
|
isApproved
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: 'Внутренняя ошибка сервера' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Обработчик для генерации изображений
|
||||||
|
router.post('/generate-image', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { prompt, userId } = req.body;
|
||||||
|
if (!prompt) {
|
||||||
|
res.status(400).json({ error: 'Необходимо указать запрос для генерации' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем изображение
|
||||||
|
const imageBuffer = await generatePicture(prompt);
|
||||||
|
|
||||||
|
// Получаем Supabase клиент
|
||||||
|
const supabase = getSupabaseClient();
|
||||||
|
|
||||||
|
// Генерируем уникальное имя файла
|
||||||
|
const timestamp = Date.now();
|
||||||
|
const filename = `image_${userId || 'user'}_${timestamp}.jpg`;
|
||||||
|
|
||||||
|
// Загружаем в Supabase
|
||||||
|
const { data, error } = await supabase.storage
|
||||||
|
.from('images')
|
||||||
|
.upload(filename, imageBuffer, {
|
||||||
|
contentType: 'image/jpeg',
|
||||||
|
upsert: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
res.status(500).json({ error: 'Ошибка при сохранении изображения' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получаем публичный URL изображения
|
||||||
|
const { data: urlData } = supabase.storage
|
||||||
|
.from('images')
|
||||||
|
.getPublicUrl(filename);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
imageUrl: urlData.publicUrl,
|
||||||
|
imagePath: filename
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: 'Внутренняя ошибка сервера' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
Reference in New Issue
Block a user