From 69c280b266206f999bdcf0154dcc4f9a528b4fb1 Mon Sep 17 00:00:00 2001 From: RustamRu Date: Mon, 3 Mar 2025 18:21:32 +0300 Subject: [PATCH] evaluate with ai car dirtiness by image --- server/routers/dry-wash/image.js | 91 ----------------- server/routers/dry-wash/index.js | 2 - .../routers/dry-wash/model/order.car-img.js | 4 +- server/routers/dry-wash/order.js | 99 ++++++++++++++++++- 4 files changed, 100 insertions(+), 96 deletions(-) delete mode 100644 server/routers/dry-wash/image.js diff --git a/server/routers/dry-wash/image.js b/server/routers/dry-wash/image.js deleted file mode 100644 index 263e342..0000000 --- a/server/routers/dry-wash/image.js +++ /dev/null @@ -1,91 +0,0 @@ -const API_URL = "https://gigachat.devices.sberbank.ru/api/v1" -const router = require('express').Router() -const { v4: uuidv4 } = require("uuid"); - -process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0" - -const token = 'MTQwMmNmZjgtZjA5OC00OGMxLWI0OTUtNWU3ZTU4YzMzZjdjOmU5OGFiYmNiLThmMDItNGVmOC1hNjhhLTA4Y2QxYjVmOGRmMA==' - - -const getToken = async (req, res) => { - - const rqUID = uuidv4() - const body = new URLSearchParams({ - scope: "GIGACHAT_API_PERS", - }) - - const response = await fetch("https://ngw.devices.sberbank.ru:9443/api/v2/oauth", { - method: "POST", - headers: { - Authorization: `Basic ${token}`, - "Content-Type": "application/x-www-form-urlencoded", - Accept: "application/json", - RqUID: rqUID, - }, - body, - }) - - if (!response.ok) { - const errorData = await response.json(); - console.error(" Ошибка запроса:", errorData); - return res.status(response.status).json(errorData); - } - - return await response.json() -} - -async function analyzeImage(fileId,token) { - const response = await fetch(`${API_URL}/chat/completions`, { - method: "POST", - headers: { - "Content-Type": "application/json", - Accept: "application/json", - Authorization: `Bearer ${token}`, - }, - body: JSON.stringify({ - model: "GigaChat-Max", - stream: false, - update_interval: 0, - messages: [ - { - role: "system", - content: - "Ты эксперт по оценке чистоты автомобилей. Твоя задача — анализировать фотографии машин и определять степень их чистоты по 10-балльной шкале, где 1 — очень грязная, 10 — полностью чистая. Отвечай только числом от 1 до 10, без пояснений и дополнительных слов.", - }, - { - role: "user", - content: "Что с чистотой машины? Отвечай на основе приложенного документа", - attachments: [fileId], - }, - ], - }), - }); - - const data = await response.json() - console.log(" Результат анализа:", data) - return data -} - -router.post("/upload", async (req, res) => { - - const {access_token} = await getToken(req, res) - - const response = await fetch(`${API_URL}/files`, { - method: "POST", - headers: { - Authorization: `Bearer ${access_token}`, - contentType: "multipart/form-data", - }, - body: req.body, - }) - - const data = await response.json() - - const analysisResponse = await analyzeImage(data.id,access_token) - - res.json({ fileId: data.id, analysis: analysisResponse }) -}) - - - -module.exports = router diff --git a/server/routers/dry-wash/index.js b/server/routers/dry-wash/index.js index b1dda9f..5a89a80 100644 --- a/server/routers/dry-wash/index.js +++ b/server/routers/dry-wash/index.js @@ -2,13 +2,11 @@ const router = require('express').Router() const armMasterRouter = require('./arm-master') const armOrdersRouter = require('./arm-orders') const orderRouter = require('./order') -const imageRouter = require('./image') router.use('/arm', armMasterRouter) router.use('/arm', armOrdersRouter) router.use('/order', orderRouter) -router.use('/image', imageRouter) module.exports = router diff --git a/server/routers/dry-wash/model/order.car-img.js b/server/routers/dry-wash/model/order.car-img.js index 1cc9793..9b653f0 100644 --- a/server/routers/dry-wash/model/order.car-img.js +++ b/server/routers/dry-wash/model/order.car-img.js @@ -1,7 +1,9 @@ const { Schema, model } = require('mongoose') const schema = new Schema({ - file: String, + image: String, + imageRating: String, + imageDescription: String, orderId: { type: Schema.Types.ObjectId, ref: 'dry-wash-order' diff --git a/server/routers/dry-wash/order.js b/server/routers/dry-wash/order.js index 30dbd70..6ee245f 100644 --- a/server/routers/dry-wash/order.js +++ b/server/routers/dry-wash/order.js @@ -273,6 +273,94 @@ const upload = multer({ } }) +const { v4: uuidv4 } = require("uuid") +const axios = require('axios') + +const GIGA_CHAT_ACCESS_TOKEN = 'OGJmMDQ4MzAtNDIwNS00NzRmLTkwOTQtNTdmNGNlYzkxZjc0OjFiZDQ0MDM4LTkyYTktNDdiNy04N2M5LWIzNjAwNjBjZTVjNQ==' +const GIGA_CHAT_OAUTH = 'https://ngw.devices.sberbank.ru:9443/api/v2/oauth' +const GIGA_CHAT_API = 'https://gigachat.devices.sberbank.ru/api/v1' + +const getToken = async (req, res) => { + const rqUID = uuidv4() + const body = new URLSearchParams({ + scope: "GIGACHAT_API_PERS", + }) + + const response = await fetch(GIGA_CHAT_OAUTH, { + method: "POST", + headers: { + Authorization: `Basic ${GIGA_CHAT_ACCESS_TOKEN}`, + "Content-Type": "application/x-www-form-urlencoded", + Accept: "application/json", + RqUID: rqUID, + }, + body, + }) + + if (!response.ok) { + const errorData = await response.json() + console.error("Ошибка запроса: ", errorData) + return res.status(response.status).json(errorData) + } + + return await response.json() +} + +const uploadImage = async (file, accessToken) => { + const formData = new FormData() + const blob = new Blob([file.buffer], { type: file.mimetype }) + formData.append('file', blob, file.originalname) + formData.append('purpose', 'general') + + const config = { + maxBodyLength: Infinity, + headers: { + 'Content-Type': 'multipart/form-data', + 'Accept': 'application/json', + 'Authorization': `Bearer ${accessToken}` + } + } + + try { + const response = await axios.post(`${GIGA_CHAT_API}/files`, formData, config) + return response.data.id + } catch (error) { + console.error(error) + } +} + +const analyzeImage = async (fileId, token) => { + const response = await fetch(`${GIGA_CHAT_API}/chat/completions`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + Authorization: `Bearer ${token}`, + }, + body: JSON.stringify({ + model: "GigaChat-Max", + stream: false, + update_interval: 0, + messages: [ + { + role: "user", + content: + `Ты эксперт по оценке степени загрязнения автомобилей. Твоя задача — анализировать фотографии машин и определять степень их загрязнения. Ответ должен содержать: 1. Оценку степени загрязнения в виде числа от 0 до 10, где 0 - без загрязнений, 10 - загрязнена на 100%. 2. Пояснение к оценке в виде абзаца текста с обоснованием выставленной оценки. + Ответ должен быть в виде объекта следующего вида: + { + "value": число от 0 до 10, + "description": "текст с обоснованием оценки" + }`, + attachments: [fileId], + }, + ], + }), + }) + + const data = await response.json() + return JSON.parse(data.choices[0].message.content) +} + const convertFileToBase64 = (file) => { const base64Image = file.buffer.toString('base64') return base64Image @@ -292,8 +380,15 @@ router.post('/:id/upload-car-img', upload.single('file'), async (req, res) => { throw new Error(VALIDATION_MESSAGES.carImg.required) } + const { access_token } = await getToken(req, res) + + const fileId = await uploadImage(req.file, access_token) + const { value, description } = await analyzeImage(fileId, access_token) ?? {} + const orderCarImg = await OrderCarImgModel.create({ - file: convertFileToBase64(req.file), + image: convertFileToBase64(req.file), + imageRating: value, + imageDescription: description, orderId, created: new Date().toISOString(), }) @@ -310,7 +405,7 @@ router.use((err, req, res, next) => { return res.status(400).json({ success: false, error: err.message }) } } - + throw new Error(err.message) })