@@ -42,3 +42,4 @@ from ml_model.services.wan import Wan from ml_model.services.whisper import Whisper from ml_model.services.qwen_235B import Qwen_235B from ml_model.services.minimaxvideo import Minimaxvideo +from ml_model.services.kling import Kling @@ -0,0 +1,58 @@ +import base64 +import time +from datetime import timedelta +from decimal import Decimal +from io import BytesIO + +import filetype +import requests +from django.core.files import File +import logging +from messages.models import Message +from ml_model.services.base import SimpleService +from ml_model.tasks import replicate_run + +from payments.exceptions.insufficient_balance import InsufficientBalance +from payments.selectors.payment_plan_selector import PaymentPlanSelector + + +class Kling(SimpleService): + TOKENS_COST = { + 'standard': Decimal('15'), + 'pro': Decimal('27') + } + + def calculate_price(self, mode: str, duration: int) -> Decimal: + price = self.TOKENS_COST[mode] * duration + return price.quantize(Decimal('0.1'), rounding='ROUND_UP') + + def save_results(self, content: str, t: timedelta, video: str, save: bool = True) -> list[Message]: + msg = Message( + content=content, + content_object=self.store, + elapsed_time=t, + file=File(BytesIO(requests.get(video).content), '.mp4'), + ) + if save: + return Message.objects.bulk_create([msg]) + return [msg] + + def make(self, input_message: Message, save: bool = True) -> list[Message]: + mode = input_message.info.pop('mode', 'standard') + duration = input_message.info.get('duration', 5) + if (balance := PaymentPlanSelector(self.store.user).get_current_balance()) < (cost := self.TOKENS_COST[mode] * duration): + raise InsufficientBalance(balance, cost) + callback_data = dict({'prompt': self.translate_prompt(input_message.content), 'mode': mode, **input_message.info}) + if input_message.file: + kind = filetype.guess(input_message.file.read(20)) + mime = kind.mime if kind else 'application/octet-stream' + input_message.file.seek(0) + image = f'data:{mime};base64,{base64.b64encode(input_message.file.read()).decode("utf-8")}' + input_message.file.close() + callback_data.update({'start_image': image}) + start_time = time.time() + video = replicate_run('kwaivgi/kling-v2.1', callback_data) + process_time = timedelta(seconds=(time.time() - start_time)) + self.handle_invoice(input_message.content_object.model, mode=mode, duration=duration) + msgs = self.save_results(input_message.content, process_time, video, save) + return msgs