@@ -31,3 +31,4 @@ from ml_model.services.stablediffusion import Stablediffusion from ml_model.services.upscaleai import Upscaleai from ml_model.services.vicuna import Vicuna from ml_model.services.whisper import Whisper +from ml_model.services.geminiimage import Geminiimage @@ -26,17 +26,45 @@ class Gemini(SimpleService): 'gemini-2.0-flash-001': { 'input': Decimal('30'), 'output': Decimal('120'), - 'input_imgs': Decimal('7.740'), + 'input_imgs': Decimal('7.8'), }, + 'gemini-2.0-flash-lite-001': { + 'input': Decimal('22.5'), + 'output': Decimal('90'), + }, + 'gemini-2.5-pro': { + 'input': Decimal('375'), + 'output': Decimal('3000'), + 'input_imgs': Decimal('1548'), + 'highest_prices': { + 'input': Decimal('750'), + 'output': Decimal('4500') + } + }, + 'gemini-2.5-flash': { + 'input': Decimal('90'), + 'output': Decimal('750'), + 'input_imgs': Decimal('371.4'), + }, + 'gemini-2.5-flash-lite': { + 'input': Decimal('30'), + 'output': Decimal('120'), + } } def calculate_price( self, version: str, input_tokens: int, output_tokens: int, image: FieldFile ) -> Decimal: price_map = self.TOKENS_COST[version.split('/')[1]] - price = ( - input_tokens * price_map['input'] / 1_000_000 + output_tokens * price_map['output'] / 1_000_000 - ) + if version.split('/')[1] == 'gemini-2.5-pro' and input_tokens > 200_000: + price = ( + input_tokens * price_map['highest_prices']['input'] / 1_000_000 + + output_tokens * price_map['highest_prices']['output'] / 1_000_000 + ) + else: + price = ( + input_tokens * price_map['input'] / 1_000_000 + output_tokens * price_map['output'] / 1_000_000 + ) if image: price += price_map['input_imgs'] / 1_000 return price.quantize(Decimal('0.1'), rounding='ROUND_UP') @@ -0,0 +1,73 @@ +import base64 +import time +from datetime import timedelta +from decimal import Decimal +from io import BytesIO + +import requests +from django.core.files import File +import filetype + +from messages.models import Message +from ml_model.services.base import SimpleService +from ml_model.tasks import fal_ai_run + + +class Geminiimage(SimpleService): + """ + Gemini Service + contains abstract method make, which makes a generation + """ + + TOKENS_COST = Decimal('11.7') + + def calculate_price(self, num_images: int) -> Decimal: + price = num_images * self.TOKENS_COST + return price.quantize(Decimal('0.1'), rounding='ROUND_UP') + + + def save_results(self, content: str, t: timedelta, images: list[str], save: bool = True) -> list[Message]: + msgs = [] + for image in images: + msgs.append( + Message( + content=content, + content_object=self.store, + elapsed_time=t, + file=File(BytesIO(requests.get(image).content), '.png') + ) + ) + if save: + return Message.objects.bulk_create(msgs) + return msgs + + def make(self, input_message: Message, save: bool = True) -> list[Message]: + callback_data = dict( + { + 'prompt': self.translate_prompt(input_message.content), + **input_message.info, + } + ) + file = input_message.file + if file: + kind = filetype.guess(file.read(20)) + mime = kind.mime if kind else 'application/octet-stream' + file.seek(0) + image = f'data:{mime};base64,{base64.b64encode(file.read()).decode("utf-8")}' + file.close() + callback_data.update( + {'image_urls': [image]} + ) + start_time = time.time() + result = fal_ai_run( + 'fal-ai/gemini-25-flash-image' if not file else 'fal-ai/gemini-25-flash-image/edit', + callback_data + ) + images = [r['url'] for r in result['images']] + process_time = timedelta(seconds=(time.time() - start_time)) + self.handle_invoice( + input_message.content_object.model, + num_images=input_message.info['num_images'], + ) + msgs = self.save_results(input_message.content, process_time, images, save) + return msgs @@ -142,7 +142,9 @@ def openrouter_run(version: str, messages: list, callback_data: dict, model_name ) reasoning = re.sub(r'Вывод:|Основная мысль:|Рассуждение:|\*\*', '', reasoning) answer = reasoning - if reasoning and content: + if 'google/gemini' in data['model']: + answer = content + elif reasoning and content: # TODO: переделать рендеринг сообщения на Jinja 2 answer = f'**Рассуждение:**\n\n{reasoning}\n\n**Основная мысль:**\n\n{content}' elif content: @@ -182,12 +184,11 @@ def fal_ai_run(model, payload): while True: status = client.get(result['status_url']).json() if status.get('status') == 'COMPLETED': - break + return client.get(status.get('response_url')).json() requests_number += 1 if requests_number == 271: raise ModelTimeoutError time.sleep(1 / 3) - return client.get(result['response_url']).json()['images'] @shared_task