@@ -242,6 +242,16 @@ class Chatgpt(SimpleService): {'type': 'input_text', 'text': input_message.content}, {'type': 'input_image', 'image_url': image_data['image_url']['url']} ] + elif file: + if sum([len(chunk.content) for chunk in chunks]) > 20_000: + document_name = chunks[0].content.partition(f':{chr(10)}')[2].split(f'{chr(10)}')[0][:100] + embedding_tokens, file_data = self.get_large_file_data(chunks, proxy, input_message.content) + messages[-1]['content'] = self.make_embeddings_prompt( + document_name=document_name, section_texts=file_data, question=input_message.content + ) + else: + messages[-1]['content'] = (f'Используй системный промпт. Содержание файла: ' + f'{chunks}. Вопрос: {input_message.content}') json_data = { 'model': model_name, 'input': messages, @@ -305,6 +315,16 @@ class Chatgpt(SimpleService): {'type': 'text', 'text': input_message.content}, image_data, ] + elif file: + if sum([len(chunk.content) for chunk in chunks]) > 20_000: + document_name = chunks[0].content.partition(f':{chr(10)}')[2].split(f'{chr(10)}')[0][:100] + embedding_tokens, file_data = self.get_large_file_data(chunks, proxy, input_message.content) + messages[-1]['content'] = self.make_embeddings_prompt( + document_name=document_name, section_texts=file_data, question=input_message.content + ) + else: + messages[-1]['content'] = (f'Используй системный промпт. Содержание файла: ' + f'{chunks}. Вопрос: {input_message.content}') json_data = { 'model': model_name, 'messages': messages @@ -326,6 +346,16 @@ class Chatgpt(SimpleService): messages ) info['web_search'] = search_context_size + if file: + if sum([len(chunk.content) for chunk in chunks]) > 20_000: + document_name = chunks[0].content.partition(f':{chr(10)}')[2].split(f'{chr(10)}')[0][:100] + embedding_tokens, file_data = self.get_large_file_data(chunks, proxy, input_message.content) + messages[-1]['content'] = self.make_embeddings_prompt( + document_name=document_name, section_texts=file_data, question=input_message.content + ) + else: + messages[-1]['content'] = (f'Используй системный промпт. Содержание файла: ' + f'{chunks}. Вопрос: {input_message.content}') input_tokens, output_tokens, response = self.call_openai_api(proxy=proxy, endpoint='responses',json_data=json_data) elif image: response = self.llm.invoke(llm_input) @@ -333,46 +363,19 @@ class Chatgpt(SimpleService): elif file: input_tokens = self.count_text_tokens([*chat_history.messages]) if sum([len(chunk.content) for chunk in chunks]) > 20_000: - redis_client = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0) document_name = chunks[0].content.partition(f':{chr(10)}')[2].split(f'{chr(10)}')[0][:100] - message_uid = str(self.store.messages.first().pk).replace('-', '_') - with httpx.Client( - base_url='https://api.openai.com/v1/', - proxy=f'{proxy.protocol}://{proxy.address}', - headers={'Authorization': f'Bearer {settings.OPENAI_API_KEY}'}, - timeout=600, - ) as client: - threads = [] - with ThreadPoolExecutor(max_workers=settings.MAX_THREADS) as executor: - for chunk_id, chunk in enumerate(chunks): - threads.append( - executor.submit(self.process_chunk, client, chunk, redis_client, message_uid, chunk_id) - ) - for thread in as_completed(threads): - embedding_tokens += thread.result() - query_embedding, e_total_tokens = self.get_embedding(client=client, content=input_message.content) - embedding_tokens += e_total_tokens - result = [ - s['section_text'] - for s in self.search_via_embeddings( - redis_client=redis_client, - message_uid=message_uid, - user_query_embeddings=query_embedding - ) - ] - user_input = [ - SystemMessage(content=user_system_prompt), - HumanMessage(self.make_embeddings_prompt( - document_name=document_name, section_texts=result, question=input_message.content - )) - ] - input_tokens += self.count_text_tokens(user_input) - response = conversation.invoke( - {'input': user_input}, - config={'configurable': {'session_id': 'default'}}, - ) - drop_redis_vectors.delay(message_uid) - redis_client.close() + embedding_tokens, file_data = self.get_large_file_data(chunks, proxy, input_message.content) + user_input = [ + SystemMessage(content=user_system_prompt), + HumanMessage(self.make_embeddings_prompt( + document_name=document_name, section_texts=file_data, question=input_message.content + )) + ] + input_tokens += self.count_text_tokens(user_input) + response = conversation.invoke( + {'input': user_input}, + config={'configurable': {'session_id': 'default'}}, + ) else: input = [ SystemMessage(content=user_system_prompt), @@ -562,6 +565,37 @@ class Chatgpt(SimpleService): return total_tokens + def get_large_file_data(self, chunks, proxy, user_content): + redis_client = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0) + embedding_tokens = 0 + message_uid = str(self.store.messages.first().pk).replace('-', '_') + with httpx.Client( + base_url='https://api.openai.com/v1/', + proxy=f'{proxy.protocol}://{proxy.address}', + headers={'Authorization': f'Bearer {settings.OPENAI_API_KEY}'}, + timeout=600, + ) as client: + threads = [] + with ThreadPoolExecutor(max_workers=settings.MAX_THREADS) as executor: + for chunk_id, chunk in enumerate(chunks): + threads.append( + executor.submit(self.process_chunk, client, chunk, redis_client, message_uid, chunk_id) + ) + for thread in as_completed(threads): + embedding_tokens += thread.result() + query_embedding, e_total_tokens = self.get_embedding(client=client, content=user_content) + embedding_tokens += e_total_tokens + result = [ + s['section_text'] + for s in self.search_via_embeddings( + redis_client=redis_client, + message_uid=message_uid, + user_query_embeddings=query_embedding + ) + ] + drop_redis_vectors.delay(message_uid) + redis_client.close() + return embedding_tokens, result def get_web_search_data(self, search_size: str, model_name: str, messages: List[Dict[str, any]]): search_context_sizes = { @@ -14,7 +14,7 @@ services: python manage.py collectstatic --no-input python manage.py compilemessages (python manage.py createsuperuser --no-input || true) - python -m uvicorn backend.asgi:application --host 0.0.0.0 --ws wsproto --http httptools --lifespan off --log-level info + python -m uvicorn backend.asgi:application --host 0.0.0.0 --ws wsproto --http httptools --lifespan off --log-level info --reload volumes: - .:/code ports: