@@ -144,13 +144,13 @@ AUTH_PASSWORD_VALIDATORS = [ 'password_validation.UserAttributeSimilarityValidator', }, { - 'NAME': 'django.contrib.auth.' 'password_validation.MinimumLengthValidator', + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { - 'NAME': 'django.contrib.auth.' 'password_validation.CommonPasswordValidator', + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { - 'NAME': 'django.contrib.auth.' 'password_validation.NumericPasswordValidator', + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] @@ -325,6 +325,7 @@ CLAUDE_API_KEY = env.str('CLAUDE_API_KEY', default='defaultapikey') GOOGLE_API_KEY = env.str('GOOGLE_API_KEY', default='defaultapikey') SERPER_API_KEY = env.str('SERPER_API_KEY', 'defaultapikey') FLUX_API_KEY = env.str('FLUX_API_KEY', 'defaultapikey') +OPENROUTER_API_KEY = env.str('OPENROUTER_API_KEY', 'defaultapikey') OPENAI_PROXY_HOST = env.str('OPENAI_PROXY_HOST', 'neuron-proxy:8080') UPSCALE_MULTIPLIER_HOST = env.str('UPSCALE_MULTIPLIER_HOST', 'packet:8080') @@ -11,7 +11,7 @@ class MessageSerializer(serializers.ModelSerializer): elapsed_time = serializers.DurationField(read_only=True) from_model = serializers.BooleanField(read_only=True) model = serializers.SlugField( - source='content_object.model', default=None, required=False + source='content_object.model', default=None, required=False, read_only=True ) is_favourite = serializers.BooleanField(read_only=True) is_sent = serializers.BooleanField(read_only=True) @@ -3,6 +3,7 @@ from ml_model.services.claude import Claude from ml_model.services.codellama import Codellama from ml_model.services.dalle import Dalle from ml_model.services.deepl import Deepl +from ml_model.services.deepseek import Deepseek from ml_model.services.djourney import Djourney from ml_model.services.epicphotogasm import Epicphotogasm from ml_model.services.flux import Flux @@ -25,30 +25,23 @@ class SimpleService(ABC): self.translator = Translator() @property - @abstractmethod def title(self) -> str: ... @property - @abstractmethod - def description(self) -> str: - return '' + def description(self) -> str: ... @property - @abstractmethod def category(self) -> ModelCategory: ... @property - @abstractmethod def inputs(self) -> list[ModelInput] | list[Never]: return [] @property - @abstractmethod def versions(self) -> list[ModelVersion] | list[Never]: return [] @property - @abstractmethod def parameters(self) -> list[ModelParameter] | list[Never]: return [] @@ -1,5 +1,5 @@ -import base64 import itertools +import base64 import logging import subprocess import time @@ -12,7 +12,9 @@ from typing import Generator, List, Optional import docx2txt import filetype +import httpx import tiktoken +from django.conf import settings from django.core.files.uploadedfile import UploadedFile from langchain import hub from langchain.agents import AgentExecutor, create_structured_chat_agent @@ -21,14 +23,15 @@ from langchain.memory import ConversationTokenBufferMemory from langchain_community.tools.google_serper import GoogleSerperResults from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage from langchain_core.prompts.prompt import PromptTemplate +from langchain_core.runnables import RunnableWithMessageHistory from langchain_openai.chat_models import ChatOpenAI from langchain_text_splitters import RecursiveCharacterTextSplitter from PIL import Image from PyPDF2 import PdfReader from backend import settings -from messages.models import BaseStore, Message from ml_model.constants import TEMPORARY_TEST_TEXT +from messages.models import Message, BaseStore from ml_model.models import ( ModelCategory, ModelConfiguration, @@ -98,6 +101,7 @@ class Chatgpt(SimpleService): category = ModelCategory(title='Чат-боты', slug='chat-bots') TOKENS_COST = { + 'o3-mini': {'input': Decimal('0.000605'), 'output': Decimal('0.002420')}, 'o1-preview': {'input': Decimal('0.008250'), 'output': Decimal('0.033000')}, 'o1-mini': {'input': Decimal('0.001650'), 'output': Decimal('0.006600')}, 'gpt-4o-mini': {'input': Decimal('0.000083'), 'output': Decimal('0.000330')}, @@ -144,11 +148,6 @@ class Chatgpt(SimpleService): input_content.append({'type': 'image_url', 'image_url': {'url': image_url}}) self.llm = ChatOpenAI( model=model_name, - temperature=info.pop('temperature', 0.5), - model_kwargs={ - 'presence_penalty': info.pop('presence', 0), - 'top_p': info.pop('top_p', 0.5), - }, openai_api_base=f'http://{settings.OPENAI_PROXY_HOST}?' + '&'.join( f'proxies={proxy.protocol}://{proxy.address}' @@ -169,35 +168,42 @@ class Chatgpt(SimpleService): } if info.get('use_web'): del info['use_web'] + else: + self.llm.temperature = info.pop('temperature', 0.5) + self.llm.model_kwargs = { + 'presence_penalty': info.pop('presence', 0), + 'top_p': info.pop('top_p', 0.5), + } if model_name in ( 'gpt-4', 'gpt-4o', 'gpt-4o-mini', 'o1-preview', 'o1-mini', + 'o3-mini', ): self.llm.tiktoken_model_name = 'gpt-4' chat_history = self.get_chat_history() - conversation = ConversationChain( - llm=self.llm, - memory=chat_history, - prompt=PromptTemplate( - input_variables=['history', 'input'], - template='Human: История диалога:{history}. Human: {input} AI:', - ), + conversation = RunnableWithMessageHistory( + runnable=self.llm, + get_session_history= lambda _: self.get_chat_history().chat_memory ) llm_input = HumanMessage(content=input_content) if file and not image: input_tokens = self.count_text_tokens( [*chat_history.buffer_as_messages, llm_input, *chunks] ) + elif image: + input_tokens = self.count_text_tokens( + [llm_input] + ) else: input_tokens = self.count_text_tokens( [*chat_history.buffer_as_messages, llm_input] ) self.assert_enough_balance(input_tokens, image_size, model=self.llm.model_name) if image: - response = conversation.llm.invoke([llm_input]) + response = self.llm.invoke([llm_input]) chat_history.chat_memory.add_ai_message(response) elif file: human_messages = [] @@ -212,8 +218,10 @@ class Chatgpt(SimpleService): ] human_message = HumanMessage(content=prompt) human_messages.append(human_message) - invoked = conversation.invoke([human_message]) - response = AIMessage(content=invoked['response']) + response = conversation.invoke( + {'input': human_message.content[0]['text']}, + config={"configurable": {"session_id": "default"}} + ) chunk_responses.append(response.content) combined_summary = ' '.join(chunk_responses) user_prompt = input_message.content if input_message.content.split() else 'Суммируй текст' @@ -223,7 +231,10 @@ class Chatgpt(SimpleService): ) input = HumanMessage(content=question_content) input_tokens = self.count_text_tokens(human_messages + [input]) - response = conversation.llm.invoke([input]) + response = conversation.invoke( + {'input': human_message.content[0]['text']}, + config={"configurable": {"session_id": "default"}} + ) elif info.get('use_web', False): prompt_schema = hub.pull('hwchase17/structured-chat-agent') tools = [GoogleSerperResults()] @@ -251,10 +262,50 @@ class Chatgpt(SimpleService): } )['output'] ) + elif model_name == 'o3-mini': + with httpx.Client( + base_url=f'http://{settings.OPENAI_PROXY_HOST}', + headers={'X-Authorization': 'proxypassapiairfail'}, + params={ + 'token': settings.OPENAI_API_KEY, + 'proxies': [ + f'{proxy.protocol}://{proxy.address}' + for proxy in Proxy.objects.all() + ], + 'uri': 'chat/completions', + }, + timeout=None, + ) as client: + resp = client.post( + '', + json={ + 'model': model_name, + 'messages': [ + {'role': 'user', 'content': input_message.content}, + ], + }, + ) + if ( + (data := resp.json()) + and data.get('choices') + and ( + content := ','.join( + [ + choice['message']['content'] + for choice in data.get('choices') + ] + ) + ) + ): + response = AIMessage(content=content) + else: + raise Exception('GPT not answer correctly, please retry later') else: # Somehow this chain doesn't support Vision, even though ChatOpenAI (above) does. - invoked = conversation.invoke([llm_input]) - response = AIMessage(content=invoked['response']) + response = conversation.invoke( + {'input': llm_input.content[0]['text']}, + config={"configurable": {"session_id": "default"}} + ) chat_history.chat_memory.add_ai_message(response) process_time = timedelta(seconds=time.time() - start_time) @@ -382,7 +433,7 @@ class Chatgpt(SimpleService): ) def count_text_tokens(self, messages: list[BaseMessage]) -> int: - encoding = tiktoken.get_encoding('cl100k_base') + encoding = tiktoken.get_encoding('o200k_base') total_tokens = 0 for message in messages: total_tokens += len( @@ -0,0 +1,86 @@ +import time +from _decimal import Decimal +from datetime import timedelta +from typing import Any, Iterator + +import httpx +from django.conf import settings + +from messages.models import Message +from ml_model.services.base import SimpleService + + +class Deepseek(SimpleService): + TOKENS_COST = { + 'deepseek/deepseek-chat': { + 'input': Decimal('107.800') / 1_000_000, + 'output': Decimal('195.800') / 1_000_000, + }, + 'deepseek/deepseek-r1:free': {'input': Decimal('0'), 'output': Decimal('0')}, + 'deepseek/deepseek-r1': { + 'input': Decimal('176.0') / 1_000_000, + 'output': Decimal('528.0') / 1_000_000, + }, + } + PRICE_BIAS = Decimal('0.05') + + def calculate_price( + self, version: str, input_tokens: int, output_tokens: int + ) -> Decimal: + price_map = self.TOKENS_COST[version] + price = ( + input_tokens * price_map['input'] + + output_tokens * price_map['output'] + + self.PRICE_BIAS + ) + return price.quantize(Decimal('0.1'), rounding='ROUND_UP') + + def save_results( + self, content: Iterator[Any], t: timedelta, save: bool = True + ) -> list[Message]: + msgs = [ + Message( + content=content, + content_object=self.store, + elapsed_time=t, + ) + ] + if save: + return Message.objects.bulk_create(msgs) + return msgs + + def make(self, input_message: Message, save: bool = True) -> list[Message]: + info = input_message.info.copy() + version = info.pop('version') + start_time = time.time() + with httpx.Client( + base_url='https://openrouter.ai/api/v1', + headers={'Authorization': f'Bearer {settings.OPENROUTER_API_KEY}'}, + ) as client: + resp = client.post( + 'chat/completions', + json={ + 'model': version, + 'messages': [{'role': 'user', 'content': input_message.content}], + }, + ) + if ( + (data := resp.json()) + and data.get('choices') + and ( + content := ','.join( + [choice['message']['content'] for choice in data.get('choices')] + ) + ) + ): + result = content + process_time = timedelta(seconds=(time.time() - start_time)) + self.handle_invoice( + input_message.content_object.model, + version=version, + input_tokens=data['usage']['prompt_tokens'], + output_tokens=data['usage']['completion_tokens'], + ) + msgs = self.save_results(result, process_time) + return msgs + raise Exception('No answer from Deepseek, please retry later') @@ -28,7 +28,7 @@ class Epicphotogasm(SimpleService): parameters = [ ModelParameter( name='Количество изображений', - key='num_images', + key='num_outputs', type=ModelParameter.TypeChoices.INTRANGE, values={'start': 1, 'end': 10, 'step': 1, 'default': 1}, ), @@ -64,10 +64,7 @@ class Epicphotogasm(SimpleService): content_object=self.store, elapsed_time=t, content=input_prompt, - file=File( - BytesIO(requests.get(link).content), - link.split('/')[-1], - ), + file=File(BytesIO(requests.get(link).content), '.png'), ) ) if self.store: @@ -18,6 +18,7 @@ from ml_model.models import ( ModelVersion, ) from ml_model.services.base import SimpleService +from ml_model.tasks import replicate_run class Flux(SimpleService): @@ -148,69 +149,28 @@ class Flux(SimpleService): ), } - def __init__(self, store: BaseStore) -> None: - super().__init__(store) - self.bfl_urls = { + _CALLBACK_BASE = 'black-forest-labs/' + + def _call_bfl_api(self, payload: dict) -> list: + bfl_headers = { + 'Content-Type': 'application/json', + 'X-Key': settings.FLUX_API_KEY, + } + bfl_urls = { 'generate': 'https://api.bfl.ml/v1/', 'get': 'https://api.bfl.ml/v1/get_result?id=', } - self.replicate_urls = { - 'generate': 'https://api.replicate.com/v1/models/black-forest-labs/', - 'get': 'https://api.replicate.com/v1/predictions/', - } - - def _get_results( - self, url: str, generation_id: str, headers: dict, statuses: tuple - ) -> dict: - result = requests.get(url=f'{url}{generation_id}', headers=headers) - while result.json()['status'] not in statuses: - result = requests.get(url=f'{url}{generation_id}', headers=headers) - return result.json() - - def _call_api(self, payload: dict) -> list: - if payload['version'] == self.versions[0].slug: - bfl_headers = { - 'Content-Type': 'application/json', - 'X-Key': settings.FLUX_API_KEY, - } - response = requests.post( - url=f'{self.bfl_urls['generate']}{payload['version']}', - headers=bfl_headers, - json=payload, - ) - if response.status_code != 200: - raise Exception(response.json()) - - return [ - self._get_results( - self.bfl_urls['get'], - response.json().get('id'), - bfl_headers, - ('Ready', 'Error'), - )['result']['sample'] - ] - else: - replicate_headers = { - 'Authorization': f'Bearer {settings.REPLICATE_API_KEY}', - 'Prefer': 'wait', - } - data = {'input': payload} - response = requests.post( - url=f'{self.replicate_urls['generate']}{payload['version']}/predictions', - headers=replicate_headers, - json=data, - ) - if response.status_code != 201: - raise Exception(response.json()) - - result = self._get_results( - self.replicate_urls['get'], - response.json().get('id'), - replicate_headers, - ('succeeded', 'failed', 'canceled'), - )['output'] - - return result if isinstance(result, list) else [result] + response = requests.post( + url=f'{bfl_urls['generate']}{payload['version']}', + headers=bfl_headers, + json=payload, + ) + if response.status_code != 200: + raise Exception(response.json()) + result = requests.get(url=f'{bfl_urls['get']}{response.json().get('id')}', headers=bfl_headers) + while result.json()['status'] not in ('Ready', 'Error'): + result = requests.get(url=f'{bfl_urls['get']}{response.json().get('id')}', headers=bfl_headers) + return result.json()['result']['sample'] def calculate_price(self, input_message: Message) -> Decimal: version_slug = input_message.info.get('version', 'flux-pro-1.1') @@ -218,7 +178,10 @@ class Flux(SimpleService): if not payment_rule.pk: payment_rule.model = self.neuron_model payment_rule.save() - return payment_rule.rate * input_message.info.get('num_outputs', 1) + if version_slug in (self.versions[1].slug,): + return payment_rule.rate * input_message.info.get('num_outputs', 1) + else: + return payment_rule.rate def save_results( self, @@ -259,7 +222,11 @@ class Flux(SimpleService): ) input_message.file.close() callback_data.update({'image': image}) - images = self._call_api(payload=callback_data) + if callback_data['version'] == 'flux-pro-1.1': + images = [self._call_bfl_api(payload=callback_data)] + else: + runner = replicate_run(f'{self._CALLBACK_BASE}{callback_data['version']}', callback_data) + images = runner if isinstance(runner, list) else [runner] process_time = timedelta(seconds=(time.time() - start_time)) self.handle_invoice(input_message.content_object.model, input_message) msgs = self.save_results(input_message.content, images, process_time, save) @@ -28,7 +28,7 @@ class Kandinsky(SimpleService): parameters = [ ModelParameter( name='Количество изображений', - key='num_images', + key='num_outputs', type=ModelParameter.TypeChoices.INTRANGE, values={'start': 1, 'end': 10, 'step': 1, 'default': 1}, ), @@ -73,10 +73,7 @@ class Kandinsky(SimpleService): content_object=self.store, elapsed_time=t, content=input_prompt, - file=File( - BytesIO(requests.get(link).content), - link.split('/')[-1], - ), + file=File(BytesIO(requests.get(link).content), '.png'), ) ) if self.store: @@ -89,10 +86,19 @@ class Kandinsky(SimpleService): activation_prompt = f'{translated_prompt}' negative_prompt = input_message.info.pop('negative_prompt', '') callback_data = dict( - prompt=f"Do not include any nudity, sexual content, or suggestive themes. " - "Avoid any graphic violence, explicit scenes, or offensive symbols. " - f"Generate a safe version of this: {activation_prompt}", - negative_prompt=negative_prompt, + prompt=activation_prompt, + negative_prompt=( + "any form of nudity, sexual content, explicit or suggestive themes, " + "graphic violence, disturbing imagery, offensive symbols, hate speech, abusive language, " + "discriminatory content, illegal activities, or any form of inappropriate or harmful material. " + "This includes, but is not limited to, full or partial nudity, suggestive body imagery, sexual innuendos, " + "pornographic content, sexual acts, and anything that could be perceived as sexual or inappropriate. " + "Also, avoid any form of graphic violence, torture, gore, blood, or injury depiction. " + "Do not include offensive symbols, hate speech, racial or ethnic slurs, or any material promoting hatred or discrimination. " + "Any content promoting illegal activities, substance abuse, self-harm, or violence is strictly prohibited. " + "Furthermore, avoid any content that is offensive, harmful, inappropriate for minors, or unsuitable for a general audience. " + f"Additionally, {negative_prompt} should be strictly avoided in any generated material." + ), **input_message.info, ) result = replicate_run(self._CALLBACK, callback_data) @@ -64,10 +64,7 @@ class Musicgen(SimpleService): Message( content_object=self.store, elapsed_time=t, - file=File( - BytesIO(requests.get(r).content), - r.split('/')[-1], - ), + file=File(BytesIO(requests.get(r).content), '.wav'), ) ] if save: @@ -27,7 +27,7 @@ class Openjourney(SimpleService): parameters = [ ModelParameter( name='Количество изображений', - key='num_images', + key='num_outputs', type=ModelParameter.TypeChoices.INTRANGE, values={'start': 1, 'end': 10, 'step': 1, 'default': 1}, ), @@ -66,10 +66,7 @@ class Openjourney(SimpleService): content_object=self.store, elapsed_time=t, content=input_prompt, - file=File( - BytesIO(requests.get(link).content), - link.split('/')[-1], - ), + file=File(BytesIO(requests.get(link).content), '.png'), ) ) if save: @@ -15,6 +15,7 @@ from ml_model.models import ( ModelVersion, ) from ml_model.services.base import SimpleService +from ml_model.tasks import replicate_run class Recraft(SimpleService): @@ -97,11 +98,6 @@ class Recraft(SimpleService): versions[1].slug: Decimal('44'), } - def __init__(self, store: BaseStore) -> None: - super().__init__(store) - self.generate_url = 'https://api.replicate.com/v1/models/recraft-ai/' - self.get_url = 'https://api.replicate.com/v1/predictions/' - def _get_size(self, width: int, height: int) -> str: available_sizes = ( (1024, 1024), (1365, 1024), (1024, 1365), (1536, 1024), (1024, 1536), @@ -114,26 +110,6 @@ class Recraft(SimpleService): size = min(available_sizes, key=lambda size: abs(height - size[1])) return f'{size[0]}x{size[1]}' - def _call_api(self, payload: dict) -> list: - headers = { - 'Authorization': f'Bearer {settings.REPLICATE_API_KEY}', - 'Content-Type': 'application/json', - 'Prefer': 'wait', - } - data = {'input': payload} - response = requests.post( - url=f'{self.generate_url}{payload.get('version', 'recraft-v3')}/predictions', - headers=headers, - json=data, - ) - if response.status_code != 201: - raise Exception(response.json()) - - result = requests.get(url=f'{self.get_url}{response.json().get('id')}', headers=headers) - while result.json()['status'] not in ('succeeded', 'failed', 'canceled'): - result = requests.get(url=f'{self.get_url}{response.json().get('id')}', headers=headers) - return result.json()['output'] - def calculate_price(self, input_message: Message) -> Decimal: return self.payment_rules[input_message.info.get('version', 'recraft-v3')] @@ -187,6 +163,7 @@ class Recraft(SimpleService): start_time = time.time() extension = '.svg' if input_message.info.get('version', 'recraft-v3') == self.versions[1].slug else '.png' size = self._get_size(input_message.info.pop('width', 1024), input_message.info.pop('height', 1024)) + callback_url = f'recraft-ai/{input_message.info.get('version', 'recraft-v3')}' callback_data = dict( { 'prompt': ( @@ -194,11 +171,11 @@ class Recraft(SimpleService): f'Input description: {self.translate_prompt(input_message.content)}' ), 'size': size, - 'style': styles.get(input_message.info.get('style', 'любой')), + 'style': styles.get(input_message.info.pop('style'), 'любой'), **input_message.info } ) - image = self._call_api(payload=callback_data) + image = replicate_run(callback_url, callback_data) process_time = timedelta(seconds=(time.time() - start_time)) self.handle_invoice(input_message.content_object.model, input_message) message = self.save_results(input_message.content, image, extension, process_time, save) @@ -91,7 +91,8 @@ class NeuronModelModelAdmin( @admin.display(description='Активна?', boolean=True) def is_active(self, obj: NeuronModel): - return obj.settings.is_active + if obj.settings: + return obj.settings.is_active @admin.display(description='Категория', boolean=True) def category(self, obj: NeuronModel): @@ -87,7 +87,14 @@ class NeuronModel(BaseModel, OrderedModel): @property def settings(self) -> 'ModelSettings': - return self.model_settings + try: + return self.model_settings + except ModelSettings.DoesNotExist: + return None + + @property + def blocked(self) -> bool: + return bool(self.settings) and self.settings.is_active and self.inputs.count() > 0 def __str__(self): return self.title @@ -5,7 +5,6 @@ from ml_model.models import ( ModelInput, ModelParameter, ModelSettings, - ModelStat, ModelVersion, NeuronModel, ) @@ -39,12 +38,6 @@ class ModelInputSerializer(serializers.ModelSerializer): exclude = ('id', 'model') -class ModelStatSerializer(serializers.ModelSerializer): - class Meta: - model = ModelStat - exclude = ('id', 'created_at', 'model') - - class NeuronModelSerializer(serializers.ModelSerializer): settings = ModelSettingsSerializer() parameters = ModelParameterSerializer(many=True) @@ -57,7 +50,7 @@ class NeuronModelSerializer(serializers.ModelSerializer): class NeuronModelsSerializer(serializers.ModelSerializer): - actual_stat = ModelStatSerializer(source='first_stat') + blocked = serializers.BooleanField() class Meta: model = NeuronModel @@ -107,7 +107,7 @@ def transcript_audio(payload: dict[str, Any]): def replicate_run(callback_url: str, payload: dict[str, Any]): replicate_client = replicate.Client(settings.REPLICATE_API_KEY) return replicate_client.run( - model_version=callback_url, + ref=callback_url, input=payload, ) @@ -54,8 +54,7 @@ class APIKeyService(BaseService): api_key.name = new_name if expires_at is not None: api_key.expires_at = expires_at - if token_limit is not None: - api_key.token_limit = token_limit + api_key.token_limit = token_limit api_key.save() if serialize: @@ -1,6 +1,8 @@ services: app: restart: unless-stopped + container_name: app + user: '1000' build: context: . dockerfile: Dockerfile.dev @@ -18,24 +20,49 @@ services: env_file: - .env depends_on: - - cache-mdb - - s3 - - db + migrator: + condition: service_completed_successfully + cache-mdb: + condition: service_started + s3: + condition: service_started + db: + condition: service_started + + migrator: + restart: on-failure:1 + container_name: migrator + build: + context: . + dockerfile: Dockerfile.dev + volumes: + - .:/code + command: + - /bin/sh + - -c + - | + python manage.py migrate + env_file: + - .env cache-mdb: + container_name: cache-mdb image: redis:alpine restart: unless-stopped celery-mdb: + container_name: celery-mdb image: redis:alpine restart: unless-stopped channels-mdb: + container_name: channels-mdb image: redis:alpine restart: unless-stopped celery: restart: unless-stopped + container_name: celery build: context: . dockerfile: Dockerfile.dev @@ -51,6 +78,7 @@ services: celery_beat: restart: unless-stopped + container_name: celery-beat build: context: . dockerfile: Dockerfile.dev @@ -63,8 +91,8 @@ services: - celery-mdb db: restart: unless-stopped - image: postgres:alpine container_name: db + image: postgres:alpine volumes: - pgdata:/var/lib/postgresql/data env_file: @@ -74,6 +102,7 @@ services: s3: image: webcenter/alpine-minio + container_name: s3 restart: unless-stopped volumes: - s3data:/data @@ -15,12 +15,27 @@ services: python manage.py collectstatic --no-input python manage.py compilemessages python -m uvicorn --host 0.0.0.0 --workers 1 --timeout-keep-alive 300 --ws wsproto --loop uvloop --http httptools --lifespan off --log-level info backend.asgi:application - ports: - - "8000:8000" env_file: - $ENV depends_on: - - cache-mdb + migrator: + condition: service_completed_successfully + cache_mdb: + condition: service_started + + migrator: + restart: on-failure:1 + container_name: migrator + build: + context: . + dockerfile: Dockerfile + command: + - /bin/sh + - -c + - python manage.py migrate + env_file: + - .env + celery: restart: unless-stopped image: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA @@ -1813,20 +1813,24 @@ test = ["cffi (>=1.17.1)", "coverage (>=5.0)", "dnspython (>=1.16.0,<2.0)", "idn [[package]] name = "google-ai-generativelanguage" -version = "0.4.0" +version = "0.6.15" description = "Google Ai Generativelanguage API client library" optional = false python-versions = ">=3.7" groups = ["main"] files = [ - {file = "google-ai-generativelanguage-0.4.0.tar.gz", hash = "sha256:c8199066c08f74c4e91290778329bb9f357ba1ea5d6f82de2bc0d10552bf4f8c"}, - {file = "google_ai_generativelanguage-0.4.0-py3-none-any.whl", hash = "sha256:e4c425376c1ee26c78acbc49a24f735f90ebfa81bf1a06495fae509a2433232c"}, + {file = "google_ai_generativelanguage-0.6.15-py3-none-any.whl", hash = "sha256:5a03ef86377aa184ffef3662ca28f19eeee158733e45d7947982eb953c6ebb6c"}, + {file = "google_ai_generativelanguage-0.6.15.tar.gz", hash = "sha256:8f6d9dc4c12b065fe2d0289026171acea5183ebf2d0b11cefe12f3821e159ec3"}, ] [package.dependencies] -google-api-core = {version = ">=1.34.0,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" +proto-plus = [ + {version = ">=1.22.3,<2.0.0dev", markers = "python_version < \"3.13\""}, + {version = ">=1.25.0,<2.0.0dev", markers = "python_version >= \"3.13\""}, +] +protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" [[package]] name = "google-api-core" @@ -1858,6 +1862,25 @@ grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] +[[package]] +name = "google-api-python-client" +version = "2.161.0" +description = "Google API Client Library for Python" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "google_api_python_client-2.161.0-py2.py3-none-any.whl", hash = "sha256:9476a5a4f200bae368140453df40f9cda36be53fa7d0e9a9aac4cdb859a26448"}, + {file = "google_api_python_client-2.161.0.tar.gz", hash = "sha256:324c0cce73e9ea0a0d2afd5937e01b7c2d6a4d7e2579cdb6c384f9699d6c9f37"}, +] + +[package.dependencies] +google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0.dev0" +google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" +google-auth-httplib2 = ">=0.2.0,<1.0.0" +httplib2 = ">=0.19.0,<1.dev0" +uritemplate = ">=3.0.1,<5" + [[package]] name = "google-auth" version = "2.37.0" @@ -1883,22 +1906,40 @@ pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] requests = ["requests (>=2.20.0,<3.0.0.dev0)"] +[[package]] +name = "google-auth-httplib2" +version = "0.2.0" +description = "Google Authentication Library: httplib2 transport" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"}, + {file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"}, +] + +[package.dependencies] +google-auth = "*" +httplib2 = ">=0.19.0" + [[package]] name = "google-generativeai" -version = "0.3.2" +version = "0.8.4" description = "Google Generative AI High level API client library and tools." optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "google_generativeai-0.3.2-py3-none-any.whl", hash = "sha256:8761147e6e167141932dc14a7b7af08f2310dd56668a78d206c19bb8bd85bcd7"}, + {file = "google_generativeai-0.8.4-py3-none-any.whl", hash = "sha256:e987b33ea6decde1e69191ddcaec6ef974458864d243de7191db50c21a7c5b82"}, ] [package.dependencies] -google-ai-generativelanguage = "0.4.0" +google-ai-generativelanguage = "0.6.15" google-api-core = "*" -google-auth = "*" +google-api-python-client = "*" +google-auth = ">=2.15.0" protobuf = "*" +pydantic = "*" tqdm = "*" typing-extensions = "*" @@ -2196,6 +2237,21 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] trio = ["trio (>=0.22.0,<1.0)"] +[[package]] +name = "httplib2" +version = "0.22.0" +description = "A comprehensive HTTP client library." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["main"] +files = [ + {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, + {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, +] + +[package.dependencies] +pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} + [[package]] name = "httptools" version = "0.6.4" @@ -2575,148 +2631,144 @@ zookeeper = ["kazoo (>=2.8.0)"] [[package]] name = "langchain" -version = "0.1.20" +version = "0.3.19" description = "Building applications with LLMs through composability" optional = false -python-versions = "<4.0,>=3.8.1" +python-versions = "<4.0,>=3.9" groups = ["main"] files = [ - {file = "langchain-0.1.20-py3-none-any.whl", hash = "sha256:09991999fbd6c3421a12db3c7d1f52d55601fc41d9b2a3ef51aab2e0e9c38da9"}, - {file = "langchain-0.1.20.tar.gz", hash = "sha256:f35c95eed8c8375e02dce95a34f2fd4856a4c98269d6dc34547a23dba5beab7e"}, + {file = "langchain-0.3.19-py3-none-any.whl", hash = "sha256:1e16d97db9106640b7de4c69f8f5ed22eeda56b45b9241279e83f111640eff16"}, + {file = "langchain-0.3.19.tar.gz", hash = "sha256:b96f8a445f01d15d522129ffe77cc89c8468dbd65830d153a676de8f6b899e7b"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" -dataclasses-json = ">=0.5.7,<0.7" -langchain-community = ">=0.0.38,<0.1" -langchain-core = ">=0.1.52,<0.2.0" -langchain-text-splitters = ">=0.0.1,<0.1" -langsmith = ">=0.1.17,<0.2.0" -numpy = ">=1,<2" -pydantic = ">=1,<3" +langchain-core = ">=0.3.35,<1.0.0" +langchain-text-splitters = ">=0.3.6,<1.0.0" +langsmith = ">=0.1.17,<0.4" +numpy = {version = ">=1.26.2,<3", markers = "python_version >= \"3.12\""} +pydantic = ">=2.7.4,<3.0.0" PyYAML = ">=5.3" requests = ">=2,<3" SQLAlchemy = ">=1.4,<3" -tenacity = ">=8.1.0,<9.0.0" +tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10" [package.extras] -azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] -clarifai = ["clarifai (>=9.1.0)"] -cli = ["typer (>=0.9.0,<0.10.0)"] -cohere = ["cohere (>=4,<6)"] -docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] -embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<6)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] -javascript = ["esprima (>=4.0.1,<5.0.0)"] -llms = ["clarifai (>=9.1.0)", "cohere (>=4,<6)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] -openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"] -qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] -text-helpers = ["chardet (>=5.1.0,<6.0.0)"] +anthropic = ["langchain-anthropic"] +aws = ["langchain-aws"] +cohere = ["langchain-cohere"] +community = ["langchain-community"] +deepseek = ["langchain-deepseek"] +fireworks = ["langchain-fireworks"] +google-genai = ["langchain-google-genai"] +google-vertexai = ["langchain-google-vertexai"] +groq = ["langchain-groq"] +huggingface = ["langchain-huggingface"] +mistralai = ["langchain-mistralai"] +ollama = ["langchain-ollama"] +openai = ["langchain-openai"] +together = ["langchain-together"] +xai = ["langchain-xai"] [[package]] name = "langchain-community" -version = "0.0.38" +version = "0.3.18" description = "Community contributed LangChain integrations." optional = false -python-versions = "<4.0,>=3.8.1" +python-versions = "<4.0,>=3.9" groups = ["main"] files = [ - {file = "langchain_community-0.0.38-py3-none-any.whl", hash = "sha256:ecb48660a70a08c90229be46b0cc5f6bc9f38f2833ee44c57dfab9bf3a2c121a"}, - {file = "langchain_community-0.0.38.tar.gz", hash = "sha256:127fc4b75bc67b62fe827c66c02e715a730fef8fe69bd2023d466bab06b5810d"}, + {file = "langchain_community-0.3.18-py3-none-any.whl", hash = "sha256:0d4a70144a1750045c4f726f9a43379ed2484178f76e4b8295bcef3a7fdf41d5"}, + {file = "langchain_community-0.3.18.tar.gz", hash = "sha256:fa2889a8f0b2d22b5c306fd1b070c0970e1f11b604bf55fad2f4a1d0bf68a077"}, ] [package.dependencies] aiohttp = ">=3.8.3,<4.0.0" dataclasses-json = ">=0.5.7,<0.7" -langchain-core = ">=0.1.52,<0.2.0" -langsmith = ">=0.1.0,<0.2.0" -numpy = ">=1,<2" +httpx-sse = ">=0.4.0,<1.0.0" +langchain = ">=0.3.19,<1.0.0" +langchain-core = ">=0.3.37,<1.0.0" +langsmith = ">=0.1.125,<0.4" +numpy = {version = ">=1.26.2,<3", markers = "python_version >= \"3.12\""} +pydantic-settings = ">=2.4.0,<3.0.0" PyYAML = ">=5.3" requests = ">=2,<3" SQLAlchemy = ">=1.4,<3" -tenacity = ">=8.1.0,<9.0.0" - -[package.extras] -cli = ["typer (>=0.9.0,<0.10.0)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "azure-identity (>=1.15.0,<2.0.0)", "azure-search-documents (==11.4.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.6,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "httpx-sse (>=0.4.0,<0.5.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.3,<6.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "oracledb (>=2.2.0,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "premai (>=0.3.25,<0.4.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pyjwt (>=2.8.0,<3.0.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "vdms (>=0.0.20,<0.0.21)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] +tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10" [[package]] name = "langchain-core" -version = "0.1.53" +version = "0.3.37" description = "Building applications with LLMs through composability" optional = false -python-versions = "<4.0,>=3.8.1" +python-versions = "<4.0,>=3.9" groups = ["main"] files = [ - {file = "langchain_core-0.1.53-py3-none-any.whl", hash = "sha256:02a88a21e3bd294441b5b741625fa4b53b1c684fd58ba6e5d9028e53cbe8542f"}, - {file = "langchain_core-0.1.53.tar.gz", hash = "sha256:df3773a553b5335eb645827b99a61a7018cea4b11dc45efa2613fde156441cec"}, + {file = "langchain_core-0.3.37-py3-none-any.whl", hash = "sha256:8202fd6506ce139a3a1b1c4c3006216b1c7fffa40bdd1779f7d2c67f75eb5f79"}, + {file = "langchain_core-0.3.37.tar.gz", hash = "sha256:cda8786e616caa2f68f7cc9e811b9b50e3b63fb2094333318b348e5961a7ea01"}, ] [package.dependencies] jsonpatch = ">=1.33,<2.0" -langsmith = ">=0.1.0,<0.2.0" -packaging = ">=23.2,<24.0" -pydantic = ">=1,<3" +langsmith = ">=0.1.125,<0.4" +packaging = ">=23.2,<25" +pydantic = [ + {version = ">=2.5.2,<3.0.0", markers = "python_full_version < \"3.12.4\""}, + {version = ">=2.7.4,<3.0.0", markers = "python_full_version >= \"3.12.4\""}, +] PyYAML = ">=5.3" -tenacity = ">=8.1.0,<9.0.0" - -[package.extras] -extended-testing = ["jinja2 (>=3,<4)"] +tenacity = ">=8.1.0,<8.4.0 || >8.4.0,<10.0.0" +typing-extensions = ">=4.7" [[package]] name = "langchain-google-genai" -version = "0.0.9" +version = "2.0.9" description = "An integration package connecting Google's genai package and LangChain" optional = false -python-versions = ">=3.9,<4.0" +python-versions = "<4.0,>=3.9" groups = ["main"] files = [ - {file = "langchain_google_genai-0.0.9-py3-none-any.whl", hash = "sha256:82c0ca9540132a59b09fc38ff249a2dd06f8a587ed37c291a4fe7678d5566d15"}, - {file = "langchain_google_genai-0.0.9.tar.gz", hash = "sha256:466a228032bb06b0c1def822e57cbf2dfe9e4d1cc91dffa473a3025eb760f0ef"}, + {file = "langchain_google_genai-2.0.9-py3-none-any.whl", hash = "sha256:48d8c78c42048d54f40dff333db9d359746644e0feb0e08b5eabdf34ad7149ca"}, + {file = "langchain_google_genai-2.0.9.tar.gz", hash = "sha256:65205089da1f72688a0ed6e7c6914af308b6514ab8038fd8126ecb20f1df234c"}, ] [package.dependencies] -google-generativeai = ">=0.3.1,<0.4.0" -langchain-core = ">=0.1,<0.2" - -[package.extras] -images = ["pillow (>=10.1.0,<11.0.0)"] +filetype = ">=1.2.0,<2.0.0" +google-generativeai = ">=0.8.0,<0.9.0" +langchain-core = ">=0.3.27,<0.4.0" +pydantic = ">=2,<3" [[package]] name = "langchain-openai" -version = "0.0.2.post1" +version = "0.3.6" description = "An integration package connecting OpenAI and LangChain" optional = false -python-versions = ">=3.8.1,<4.0" +python-versions = "<4.0,>=3.9" groups = ["main"] files = [ - {file = "langchain_openai-0.0.2.post1-py3-none-any.whl", hash = "sha256:ba468b94c23da9d8ccefe5d5a3c1c65b4b9702292523e53acc689a9110022e26"}, - {file = "langchain_openai-0.0.2.post1.tar.gz", hash = "sha256:f8e78db4a663feeac71d9f036b9422406c199ea3ef4c97d99ff392c93530e073"}, + {file = "langchain_openai-0.3.6-py3-none-any.whl", hash = "sha256:05f0869f6cc963e2ec9e2e54ea1038d9c2af784c67f0e217040dfc918b31649a"}, + {file = "langchain_openai-0.3.6.tar.gz", hash = "sha256:7daf92e1cd98865ab5213ec5bec2cbd6c28f011e250714978b3a99c7e4fc88ce"}, ] [package.dependencies] -langchain-core = ">=0.1.7,<0.2" -numpy = ">=1,<2" -openai = ">=1.6.1,<2.0.0" -tiktoken = ">=0.5.2,<0.6.0" +langchain-core = ">=0.3.35,<1.0.0" +openai = ">=1.58.1,<2.0.0" +tiktoken = ">=0.7,<1" [[package]] name = "langchain-text-splitters" -version = "0.0.2" +version = "0.3.6" description = "LangChain text splitting utilities" optional = false -python-versions = "<4.0,>=3.8.1" +python-versions = "<4.0,>=3.9" groups = ["main"] files = [ - {file = "langchain_text_splitters-0.0.2-py3-none-any.whl", hash = "sha256:13887f32705862c1e1454213cb7834a63aae57c26fcd80346703a1d09c46168d"}, - {file = "langchain_text_splitters-0.0.2.tar.gz", hash = "sha256:ac8927dc0ba08eba702f6961c9ed7df7cead8de19a9f7101ab2b5ea34201b3c1"}, + {file = "langchain_text_splitters-0.3.6-py3-none-any.whl", hash = "sha256:e5d7b850f6c14259ea930be4a964a65fa95d9df7e1dbdd8bad8416db72292f4e"}, + {file = "langchain_text_splitters-0.3.6.tar.gz", hash = "sha256:c537972f4b7c07451df431353a538019ad9dadff7a1073ea363946cea97e1bee"}, ] [package.dependencies] -langchain-core = ">=0.1.28,<0.3" - -[package.extras] -extended-testing = ["beautifulsoup4 (>=4.12.3,<5.0.0)", "lxml (>=4.9.3,<6.0)"] +langchain-core = ">=0.3.34,<1.0.0" [[package]] name = "langchainhub" @@ -4031,6 +4083,27 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +[[package]] +name = "pydantic-settings" +version = "2.7.1" +description = "Settings management using Pydantic" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd"}, + {file = "pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93"}, +] + +[package.dependencies] +pydantic = ">=2.7.0" +python-dotenv = ">=0.21.0" + +[package.extras] +azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0)"] +toml = ["tomli (>=2.0.1)"] +yaml = ["pyyaml (>=6.0.1)"] + [[package]] name = "pyjwt" version = "2.10.1" @@ -4081,6 +4154,21 @@ files = [ {file = "pypandoc-1.15.tar.gz", hash = "sha256:ea25beebe712ae41d63f7410c08741a3cab0e420f6703f95bc9b3a749192ce13"}, ] +[[package]] +name = "pyparsing" +version = "3.2.1" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pyparsing-3.2.1-py3-none-any.whl", hash = "sha256:506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1"}, + {file = "pyparsing-3.2.1.tar.gz", hash = "sha256:61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + [[package]] name = "pypdf2" version = "3.0.1" @@ -4532,23 +4620,21 @@ files = [ [[package]] name = "replicate" -version = "0.10.0" +version = "1.0.4" description = "Python client for Replicate" optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "replicate-0.10.0-py3-none-any.whl", hash = "sha256:71464d62259b22a17f5383e83ebaf158cace69ba0153a9de21061283ac2c3a4b"}, - {file = "replicate-0.10.0.tar.gz", hash = "sha256:f714944be0c65eef7b3ebf740eb132d573a52e811a02f0031b9f1ae077a50696"}, + {file = "replicate-1.0.4-py3-none-any.whl", hash = "sha256:f568f6271ff715067901b6094c23c37373bbcfd7de0ff9b85e9c9ead567e09e7"}, + {file = "replicate-1.0.4.tar.gz", hash = "sha256:f718601863ef1f419aa7dcdab1ea8770ba5489b571b86edf840cd506d68758ef"}, ] [package.dependencies] +httpx = ">=0.21.0,<1" packaging = "*" -pydantic = ">1" -requests = ">2" - -[package.extras] -dev = ["black", "mypy", "pytest", "responses", "ruff"] +pydantic = ">1.10.7" +typing_extensions = ">=4.5.0" [[package]] name = "requests" @@ -4736,29 +4822,30 @@ pyasn1 = ">=0.1.3" [[package]] name = "ruff" -version = "0.4.10" +version = "0.9.9" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" -groups = ["lint"] -files = [ - {file = "ruff-0.4.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5c2c4d0859305ac5a16310eec40e4e9a9dec5dcdfbe92697acd99624e8638dac"}, - {file = "ruff-0.4.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a79489607d1495685cdd911a323a35871abfb7a95d4f98fc6f85e799227ac46e"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1dd1681dfa90a41b8376a61af05cc4dc5ff32c8f14f5fe20dba9ff5deb80cd6"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c75c53bb79d71310dc79fb69eb4902fba804a81f374bc86a9b117a8d077a1784"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18238c80ee3d9100d3535d8eb15a59c4a0753b45cc55f8bf38f38d6a597b9739"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d8f71885bce242da344989cae08e263de29752f094233f932d4f5cfb4ef36a81"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:330421543bd3222cdfec481e8ff3460e8702ed1e58b494cf9d9e4bf90db52b9d"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e9b6fb3a37b772628415b00c4fc892f97954275394ed611056a4b8a2631365e"}, - {file = "ruff-0.4.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f54c481b39a762d48f64d97351048e842861c6662d63ec599f67d515cb417f6"}, - {file = "ruff-0.4.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:67fe086b433b965c22de0b4259ddfe6fa541c95bf418499bedb9ad5fb8d1c631"}, - {file = "ruff-0.4.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:acfaaab59543382085f9eb51f8e87bac26bf96b164839955f244d07125a982ef"}, - {file = "ruff-0.4.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3cea07079962b2941244191569cf3a05541477286f5cafea638cd3aa94b56815"}, - {file = "ruff-0.4.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:338a64ef0748f8c3a80d7f05785930f7965d71ca260904a9321d13be24b79695"}, - {file = "ruff-0.4.10-py3-none-win32.whl", hash = "sha256:ffe3cd2f89cb54561c62e5fa20e8f182c0a444934bf430515a4b422f1ab7b7ca"}, - {file = "ruff-0.4.10-py3-none-win_amd64.whl", hash = "sha256:67f67cef43c55ffc8cc59e8e0b97e9e60b4837c8f21e8ab5ffd5d66e196e25f7"}, - {file = "ruff-0.4.10-py3-none-win_arm64.whl", hash = "sha256:dd1fcee327c20addac7916ca4e2653fbbf2e8388d8a6477ce5b4e986b68ae6c0"}, - {file = "ruff-0.4.10.tar.gz", hash = "sha256:3aa4f2bc388a30d346c56524f7cacca85945ba124945fe489952aadb6b5cd804"}, +groups = ["main"] +files = [ + {file = "ruff-0.9.9-py3-none-linux_armv6l.whl", hash = "sha256:628abb5ea10345e53dff55b167595a159d3e174d6720bf19761f5e467e68d367"}, + {file = "ruff-0.9.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b6cd1428e834b35d7493354723543b28cc11dc14d1ce19b685f6e68e07c05ec7"}, + {file = "ruff-0.9.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5ee162652869120ad260670706f3cd36cd3f32b0c651f02b6da142652c54941d"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3aa0f6b75082c9be1ec5a1db78c6d4b02e2375c3068438241dc19c7c306cc61a"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:584cc66e89fb5f80f84b05133dd677a17cdd86901d6479712c96597a3f28e7fe"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf3369325761a35aba75cd5c55ba1b5eb17d772f12ab168fbfac54be85cf18c"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3403a53a32a90ce929aa2f758542aca9234befa133e29f4933dcef28a24317be"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18454e7fa4e4d72cffe28a37cf6a73cb2594f81ec9f4eca31a0aaa9ccdfb1590"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fadfe2c88724c9617339f62319ed40dcdadadf2888d5afb88bf3adee7b35bfb"}, + {file = "ruff-0.9.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6df104d08c442a1aabcfd254279b8cc1e2cbf41a605aa3e26610ba1ec4acf0b0"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d7c62939daf5b2a15af48abbd23bea1efdd38c312d6e7c4cedf5a24e03207e17"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9494ba82a37a4b81b6a798076e4a3251c13243fc37967e998efe4cce58c8a8d1"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4efd7a96ed6d36ef011ae798bf794c5501a514be369296c672dab7921087fa57"}, + {file = "ruff-0.9.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ab90a7944c5a1296f3ecb08d1cbf8c2da34c7e68114b1271a431a3ad30cb660e"}, + {file = "ruff-0.9.9-py3-none-win32.whl", hash = "sha256:6b4c376d929c25ecd6d87e182a230fa4377b8e5125a4ff52d506ee8c087153c1"}, + {file = "ruff-0.9.9-py3-none-win_amd64.whl", hash = "sha256:837982ea24091d4c1700ddb2f63b7070e5baec508e43b01de013dc7eff974ff1"}, + {file = "ruff-0.9.9-py3-none-win_arm64.whl", hash = "sha256:3ac78f127517209fe6d96ab00f3ba97cafe38718b23b1db3e96d8b2d39e37ddf"}, + {file = "ruff-0.9.9.tar.gz", hash = "sha256:0062ed13f22173e85f8f7056f9a24016e692efeea8704d1a5e8011b8aa850933"}, ] [[package]] @@ -5119,48 +5206,43 @@ tests = ["pytest", "pytest-cov"] [[package]] name = "tiktoken" -version = "0.5.2" +version = "0.9.0" description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "tiktoken-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c4e654282ef05ec1bd06ead22141a9a1687991cef2c6a81bdd1284301abc71d"}, - {file = "tiktoken-0.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7b3134aa24319f42c27718c6967f3c1916a38a715a0fa73d33717ba121231307"}, - {file = "tiktoken-0.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6092e6e77730929c8c6a51bb0d7cfdf1b72b63c4d033d6258d1f2ee81052e9e5"}, - {file = "tiktoken-0.5.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ad8ae2a747622efae75837abba59be6c15a8f31b4ac3c6156bc56ec7a8e631"}, - {file = "tiktoken-0.5.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51cba7c8711afa0b885445f0637f0fcc366740798c40b981f08c5f984e02c9d1"}, - {file = "tiktoken-0.5.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3d8c7d2c9313f8e92e987d585ee2ba0f7c40a0de84f4805b093b634f792124f5"}, - {file = "tiktoken-0.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:692eca18c5fd8d1e0dde767f895c17686faaa102f37640e884eecb6854e7cca7"}, - {file = "tiktoken-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:138d173abbf1ec75863ad68ca289d4da30caa3245f3c8d4bfb274c4d629a2f77"}, - {file = "tiktoken-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7388fdd684690973fdc450b47dfd24d7f0cbe658f58a576169baef5ae4658607"}, - {file = "tiktoken-0.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a114391790113bcff670c70c24e166a841f7ea8f47ee2fe0e71e08b49d0bf2d4"}, - {file = "tiktoken-0.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca96f001e69f6859dd52926d950cfcc610480e920e576183497ab954e645e6ac"}, - {file = "tiktoken-0.5.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:15fed1dd88e30dfadcdd8e53a8927f04e1f6f81ad08a5ca824858a593ab476c7"}, - {file = "tiktoken-0.5.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:93f8e692db5756f7ea8cb0cfca34638316dcf0841fb8469de8ed7f6a015ba0b0"}, - {file = "tiktoken-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:bcae1c4c92df2ffc4fe9f475bf8148dbb0ee2404743168bbeb9dcc4b79dc1fdd"}, - {file = "tiktoken-0.5.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b76a1e17d4eb4357d00f0622d9a48ffbb23401dcf36f9716d9bd9c8e79d421aa"}, - {file = "tiktoken-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:01d8b171bb5df4035580bc26d4f5339a6fd58d06f069091899d4a798ea279d3e"}, - {file = "tiktoken-0.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42adf7d4fb1ed8de6e0ff2e794a6a15005f056a0d83d22d1d6755a39bffd9e7f"}, - {file = "tiktoken-0.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3f894dbe0adb44609f3d532b8ea10820d61fdcb288b325a458dfc60fefb7db"}, - {file = "tiktoken-0.5.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:58ccfddb4e62f0df974e8f7e34a667981d9bb553a811256e617731bf1d007d19"}, - {file = "tiktoken-0.5.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58902a8bad2de4268c2a701f1c844d22bfa3cbcc485b10e8e3e28a050179330b"}, - {file = "tiktoken-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:5e39257826d0647fcac403d8fa0a474b30d02ec8ffc012cfaf13083e9b5e82c5"}, - {file = "tiktoken-0.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bde3b0fbf09a23072d39c1ede0e0821f759b4fa254a5f00078909158e90ae1f"}, - {file = "tiktoken-0.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2ddee082dcf1231ccf3a591d234935e6acf3e82ee28521fe99af9630bc8d2a60"}, - {file = "tiktoken-0.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35c057a6a4e777b5966a7540481a75a31429fc1cb4c9da87b71c8b75b5143037"}, - {file = "tiktoken-0.5.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c4a049b87e28f1dc60509f8eb7790bc8d11f9a70d99b9dd18dfdd81a084ffe6"}, - {file = "tiktoken-0.5.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5bf5ce759089f4f6521ea6ed89d8f988f7b396e9f4afb503b945f5c949c6bec2"}, - {file = "tiktoken-0.5.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0c964f554af1a96884e01188f480dad3fc224c4bbcf7af75d4b74c4b74ae0125"}, - {file = "tiktoken-0.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:368dd5726d2e8788e47ea04f32e20f72a2012a8a67af5b0b003d1e059f1d30a3"}, - {file = "tiktoken-0.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a2deef9115b8cd55536c0a02c0203512f8deb2447f41585e6d929a0b878a0dd2"}, - {file = "tiktoken-0.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2ed7d380195affbf886e2f8b92b14edfe13f4768ff5fc8de315adba5b773815e"}, - {file = "tiktoken-0.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76fce01309c8140ffe15eb34ded2bb94789614b7d1d09e206838fc173776a18"}, - {file = "tiktoken-0.5.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60a5654d6a2e2d152637dd9a880b4482267dfc8a86ccf3ab1cec31a8c76bfae8"}, - {file = "tiktoken-0.5.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41d4d3228e051b779245a8ddd21d4336f8975563e92375662f42d05a19bdff41"}, - {file = "tiktoken-0.5.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c1cdec2c92fcde8c17a50814b525ae6a88e8e5b02030dc120b76e11db93f13"}, - {file = "tiktoken-0.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:84ddb36faedb448a50b246e13d1b6ee3437f60b7169b723a4b2abad75e914f3e"}, - {file = "tiktoken-0.5.2.tar.gz", hash = "sha256:f54c581f134a8ea96ce2023ab221d4d4d81ab614efa0b2fbce926387deb56c80"}, + {file = "tiktoken-0.9.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:586c16358138b96ea804c034b8acf3f5d3f0258bd2bc3b0227af4af5d622e382"}, + {file = "tiktoken-0.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d9c59ccc528c6c5dd51820b3474402f69d9a9e1d656226848ad68a8d5b2e5108"}, + {file = "tiktoken-0.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0968d5beeafbca2a72c595e8385a1a1f8af58feaebb02b227229b69ca5357fd"}, + {file = "tiktoken-0.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92a5fb085a6a3b7350b8fc838baf493317ca0e17bd95e8642f95fc69ecfed1de"}, + {file = "tiktoken-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:15a2752dea63d93b0332fb0ddb05dd909371ededa145fe6a3242f46724fa7990"}, + {file = "tiktoken-0.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:26113fec3bd7a352e4b33dbaf1bd8948de2507e30bd95a44e2b1156647bc01b4"}, + {file = "tiktoken-0.9.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f32cc56168eac4851109e9b5d327637f15fd662aa30dd79f964b7c39fbadd26e"}, + {file = "tiktoken-0.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:45556bc41241e5294063508caf901bf92ba52d8ef9222023f83d2483a3055348"}, + {file = "tiktoken-0.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03935988a91d6d3216e2ec7c645afbb3d870b37bcb67ada1943ec48678e7ee33"}, + {file = "tiktoken-0.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b3d80aad8d2c6b9238fc1a5524542087c52b860b10cbf952429ffb714bc1136"}, + {file = "tiktoken-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b2a21133be05dc116b1d0372af051cd2c6aa1d2188250c9b553f9fa49301b336"}, + {file = "tiktoken-0.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:11a20e67fdf58b0e2dea7b8654a288e481bb4fc0289d3ad21291f8d0849915fb"}, + {file = "tiktoken-0.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e88f121c1c22b726649ce67c089b90ddda8b9662545a8aeb03cfef15967ddd03"}, + {file = "tiktoken-0.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a6600660f2f72369acb13a57fb3e212434ed38b045fd8cc6cdd74947b4b5d210"}, + {file = "tiktoken-0.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95e811743b5dfa74f4b227927ed86cbc57cad4df859cb3b643be797914e41794"}, + {file = "tiktoken-0.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99376e1370d59bcf6935c933cb9ba64adc29033b7e73f5f7569f3aad86552b22"}, + {file = "tiktoken-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:badb947c32739fb6ddde173e14885fb3de4d32ab9d8c591cbd013c22b4c31dd2"}, + {file = "tiktoken-0.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:5a62d7a25225bafed786a524c1b9f0910a1128f4232615bf3f8257a73aaa3b16"}, + {file = "tiktoken-0.9.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2b0e8e05a26eda1249e824156d537015480af7ae222ccb798e5234ae0285dbdb"}, + {file = "tiktoken-0.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:27d457f096f87685195eea0165a1807fae87b97b2161fe8c9b1df5bd74ca6f63"}, + {file = "tiktoken-0.9.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cf8ded49cddf825390e36dd1ad35cd49589e8161fdcb52aa25f0583e90a3e01"}, + {file = "tiktoken-0.9.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc156cb314119a8bb9748257a2eaebd5cc0753b6cb491d26694ed42fc7cb3139"}, + {file = "tiktoken-0.9.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:cd69372e8c9dd761f0ab873112aba55a0e3e506332dd9f7522ca466e817b1b7a"}, + {file = "tiktoken-0.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:5ea0edb6f83dc56d794723286215918c1cde03712cbbafa0348b33448faf5b95"}, + {file = "tiktoken-0.9.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c6386ca815e7d96ef5b4ac61e0048cd32ca5a92d5781255e13b31381d28667dc"}, + {file = "tiktoken-0.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:75f6d5db5bc2c6274b674ceab1615c1778e6416b14705827d19b40e6355f03e0"}, + {file = "tiktoken-0.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e15b16f61e6f4625a57a36496d28dd182a8a60ec20a534c5343ba3cafa156ac7"}, + {file = "tiktoken-0.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebcec91babf21297022882344c3f7d9eed855931466c3311b1ad6b64befb3df"}, + {file = "tiktoken-0.9.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e5fd49e7799579240f03913447c0cdfa1129625ebd5ac440787afc4345990427"}, + {file = "tiktoken-0.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:26242ca9dc8b58e875ff4ca078b9a94d2f0813e6a535dcd2205df5d49d927cc7"}, + {file = "tiktoken-0.9.0.tar.gz", hash = "sha256:d02a5ca6a938e0490e1ff957bc48c8b078c88cb83977be1625b1fd8aac792c5d"}, ] [package.dependencies] @@ -5821,4 +5903,4 @@ testing = ["coverage[toml]", "zope.event", "zope.testing"] [metadata] lock-version = "2.1" python-versions = "^3.12" -content-hash = "05b49eeacc304695f22cd6a2942fc3ea572e8b24b55b4698da75f97db81c35fa" +content-hash = "11aef76704403641d1d4f24a0e6525cb38c7fcf331df77983fd1da009dd8116d" @@ -9,7 +9,6 @@ package-mode = false [tool.poetry.dependencies] python = "^3.12" -replicate = "^0.10.0" deepl = "^1.15.0" django = "5.0.*" django-cors-headers = "^4.2.0" @@ -32,10 +31,7 @@ openpyxl = "^3.1.2" pypdf2 = "^3.0.1" python-docx = "^1.1.0" mutagen = "^1.47.0" -langchain = "^0.1.0" -langchain-openai = "^0.0.2" pillow = "^10.2.0" -langchain-google-genai = "^0.0.9" langserve = {extras = ["client"], version = "^0.0.46"} django-ordered-model = "^3.7.4" langchainhub = "^0.1.15" @@ -57,10 +53,16 @@ httptools = "^0.6.4" uvloop = "^0.21.0" wsproto = "^1.2.0" channels-redis = "^4.2.1" -tiktoken = "<0.6.0" +langchain = "^0.3.19" +langchain-openai = "^0.3.6" +langchain-google-genai = "^2.0.9" +tiktoken = "^0.9.0" +langchain-community = "^0.3.17" docx2txt = "^0.8" pypandoc = "^1.15" faiss-cpu = "^1.10.0" +replicate = "^1.0.4" +ruff = "^0.9.9" [tool.poetry.group.test.dependencies] @@ -76,10 +78,6 @@ pytest-factoryboy = "^2.5.1" pytest-cov = "^4.1.0" -[tool.poetry.group.lint.dependencies] -ruff = "^0.4.8" - - [tool.poetry.group.typing.dependencies] mypy = "^1.5.1" django-stubs = "^4.2.4"