Spaces:
Running
Running
luanpoppe
commited on
Commit
·
63cd221
1
Parent(s):
aae4d3d
feat: adicionando mais refatorações e a nova rota para chamadas simples a LLMs
Browse files- _utils/gerar_documento_utils/GerarDocumento.py +72 -67
- setup/installed_apps.py +1 -0
- setup/urls.py +1 -0
- simple_llm/__init__.py +0 -0
- simple_llm/admin.py +3 -0
- simple_llm/apps.py +6 -0
- simple_llm/migrations/__init__.py +0 -0
- simple_llm/models.py +3 -0
- simple_llm/serializer.py +57 -0
- simple_llm/tests.py +3 -0
- simple_llm/urls.py +11 -0
- simple_llm/views.py +73 -0
_utils/gerar_documento_utils/GerarDocumento.py
CHANGED
|
@@ -42,6 +42,7 @@ import time
|
|
| 42 |
from setup.tokens import openai_api_key, cohere_api_key
|
| 43 |
from setup.logging import Axiom
|
| 44 |
import tiktoken
|
|
|
|
| 45 |
|
| 46 |
|
| 47 |
def reciprocal_rank_fusion(result_lists, weights=None):
|
|
@@ -65,6 +66,10 @@ def reciprocal_rank_fusion(result_lists, weights=None):
|
|
| 65 |
|
| 66 |
@dataclass
|
| 67 |
class GerarDocumentoUtils:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
def criar_output_estruturado(self, summaries: List[str | Any], sources: Any):
|
| 69 |
structured_output = []
|
| 70 |
for idx, summary in enumerate(summaries):
|
|
@@ -109,6 +114,65 @@ class GerarDocumentoUtils:
|
|
| 109 |
chunk_overlap=serializer.chunk_overlap,
|
| 110 |
)
|
| 111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
|
| 113 |
class GerarDocumento:
|
| 114 |
lista_pdfs: List[str]
|
|
@@ -118,7 +182,7 @@ class GerarDocumento:
|
|
| 118 |
isBubble: bool
|
| 119 |
chunks_processados: List[ContextualizedChunk] | List[DocumentChunk]
|
| 120 |
resumo_auxiliar: str
|
| 121 |
-
gerar_documento_utils
|
| 122 |
utils = UtilsClass()
|
| 123 |
llm = LLM()
|
| 124 |
enhanced_vector_store: tuple[Chroma, BM25Okapi, List[str]]
|
|
@@ -143,6 +207,7 @@ class GerarDocumento:
|
|
| 143 |
self.config = self.gerar_documento_utils.create_retrieval_config(serializer)
|
| 144 |
self.logger = logging.getLogger(__name__)
|
| 145 |
# self.prompt_auxiliar = prompt_auxiliar
|
|
|
|
| 146 |
self.gpt_model = serializer.model
|
| 147 |
self.gpt_temperature = serializer.gpt_temperature
|
| 148 |
self.prompt_gerar_documento = serializer.prompt_gerar_documento
|
|
@@ -318,29 +383,6 @@ class GerarDocumento:
|
|
| 318 |
|
| 319 |
return sources, contexts
|
| 320 |
|
| 321 |
-
def select_model_for_last_requests(
|
| 322 |
-
self,
|
| 323 |
-
llm_ultimas_requests: Literal[
|
| 324 |
-
"gpt-4o-mini", "deepseek-chat", "gemini-2.0-flash", "gemini-2.5-pro"
|
| 325 |
-
],
|
| 326 |
-
):
|
| 327 |
-
llm_instance = LLM()
|
| 328 |
-
if llm_ultimas_requests == "gpt-4o-mini":
|
| 329 |
-
llm = ChatOpenAI(
|
| 330 |
-
temperature=self.gpt_temperature,
|
| 331 |
-
model=self.gpt_model,
|
| 332 |
-
api_key=SecretStr(openai_api_key),
|
| 333 |
-
)
|
| 334 |
-
elif llm_ultimas_requests == "deepseek-chat":
|
| 335 |
-
llm = llm_instance.deepseek()
|
| 336 |
-
elif llm_ultimas_requests == "gemini-2.0-flash":
|
| 337 |
-
llm = llm_instance.google_gemini("gemini-2.0-flash")
|
| 338 |
-
elif llm_ultimas_requests == "gemini-2.5-pro":
|
| 339 |
-
llm = llm_instance.google_gemini("gemini-2.5-pro-preview-05-06")
|
| 340 |
-
elif llm_ultimas_requests == "gemini-2.5-flash":
|
| 341 |
-
llm = llm_instance.google_gemini("gemini-2.5-flash-preview-04-17")
|
| 342 |
-
return llm
|
| 343 |
-
|
| 344 |
async def do_last_requests(
|
| 345 |
self,
|
| 346 |
) -> List[Dict]:
|
|
@@ -361,14 +403,15 @@ class GerarDocumento:
|
|
| 361 |
)
|
| 362 |
|
| 363 |
llm_ultimas_requests = self.llm_ultimas_requests
|
| 364 |
-
llm = self.select_model_for_last_requests(llm_ultimas_requests) # type: ignore
|
| 365 |
prompt_instance = Prompt()
|
| 366 |
context_do_prompt_primeira_etapa = "\n\n".join(contexts)
|
| 367 |
prompt_primeira_etapa = prompt_gerar_documento.format(
|
| 368 |
context=context_do_prompt_primeira_etapa,
|
| 369 |
)
|
| 370 |
|
| 371 |
-
|
|
|
|
|
|
|
| 372 |
llm_ultimas_requests, prompt_primeira_etapa
|
| 373 |
)
|
| 374 |
|
|
@@ -386,7 +429,7 @@ class GerarDocumento:
|
|
| 386 |
dynamic_dict={"context": context_do_prompt_primeira_etapa},
|
| 387 |
)
|
| 388 |
# documento_gerado = llm.invoke(prompt_etapa_2).content
|
| 389 |
-
documento_gerado = self.checar_se_resposta_vazia_do_documento_final(
|
| 390 |
llm_ultimas_requests, prompt_etapa_2.to_string()
|
| 391 |
)
|
| 392 |
resposta_segunda_etapa = documento_gerado
|
|
@@ -404,7 +447,7 @@ class GerarDocumento:
|
|
| 404 |
},
|
| 405 |
)
|
| 406 |
# documento_gerado = llm.invoke(prompt_etapa_3).content
|
| 407 |
-
documento_gerado = self.checar_se_resposta_vazia_do_documento_final(
|
| 408 |
llm_ultimas_requests, prompt_etapa_3.to_string()
|
| 409 |
)
|
| 410 |
texto_final_juntando_as_etapas += f"\n\n{documento_gerado}"
|
|
@@ -468,44 +511,6 @@ class GerarDocumento:
|
|
| 468 |
|
| 469 |
self.axiom_instance.send_axiom("TERMINOU A REQUISIÇÃO FINAL PARA O BUBBLE")
|
| 470 |
|
| 471 |
-
async def checar_se_resposta_vazia_do_documento_final(
|
| 472 |
-
self, llm_ultimas_requests: str, prompt: str
|
| 473 |
-
):
|
| 474 |
-
llm = self.select_model_for_last_requests(llm_ultimas_requests) # type: ignore
|
| 475 |
-
documento_gerado = ""
|
| 476 |
-
tentativas = 0
|
| 477 |
-
|
| 478 |
-
while tentativas < 5 and not documento_gerado:
|
| 479 |
-
tentativas += 1
|
| 480 |
-
try:
|
| 481 |
-
resposta = llm.invoke(prompt)
|
| 482 |
-
if hasattr(resposta, "content") and resposta.content.strip(): # type: ignore
|
| 483 |
-
if isinstance(resposta.content, list):
|
| 484 |
-
resposta.content = "\n".join(resposta.content) # type: ignore
|
| 485 |
-
|
| 486 |
-
documento_gerado = resposta.content.strip() # type: ignore
|
| 487 |
-
else:
|
| 488 |
-
print(f"Tentativa {tentativas}: resposta vazia ou inexistente.")
|
| 489 |
-
except Exception as e:
|
| 490 |
-
llm = self.select_model_for_last_requests("gemini-2.0-flash")
|
| 491 |
-
print(f"Tentativa {tentativas}: erro ao invocar o modelo: {e}")
|
| 492 |
-
time.sleep(5)
|
| 493 |
-
|
| 494 |
-
if not documento_gerado:
|
| 495 |
-
try:
|
| 496 |
-
self.axiom_instance.send_axiom(
|
| 497 |
-
"TENTANDO GERAR DOCUMENTO FINAL COM GPT 4o-mini COMO ÚLTIMA TENTATIVA"
|
| 498 |
-
)
|
| 499 |
-
documento_gerado = (
|
| 500 |
-
self.gerar_documento_utils.ultima_tentativa_requisicao(prompt)
|
| 501 |
-
)
|
| 502 |
-
except Exception as e:
|
| 503 |
-
raise Exception(
|
| 504 |
-
"Falha ao gerar o documento final na última tentativa."
|
| 505 |
-
) from e
|
| 506 |
-
|
| 507 |
-
return documento_gerado
|
| 508 |
-
|
| 509 |
async def gerar_ementa_final(
|
| 510 |
self,
|
| 511 |
llm_ultimas_requests: str,
|
|
@@ -516,7 +521,7 @@ class GerarDocumento:
|
|
| 516 |
llm = self.select_model_for_last_requests(llm_ultimas_requests) # type: ignore
|
| 517 |
prompt_instance = Prompt()
|
| 518 |
|
| 519 |
-
documento_gerado = await self.checar_se_resposta_vazia_do_documento_final(
|
| 520 |
llm_ultimas_requests, prompt_primeira_etapa
|
| 521 |
)
|
| 522 |
|
|
|
|
| 42 |
from setup.tokens import openai_api_key, cohere_api_key
|
| 43 |
from setup.logging import Axiom
|
| 44 |
import tiktoken
|
| 45 |
+
from setup.environment import default_model
|
| 46 |
|
| 47 |
|
| 48 |
def reciprocal_rank_fusion(result_lists, weights=None):
|
|
|
|
| 66 |
|
| 67 |
@dataclass
|
| 68 |
class GerarDocumentoUtils:
|
| 69 |
+
axiom_instance: Axiom
|
| 70 |
+
temperature = 0.0
|
| 71 |
+
model = default_model
|
| 72 |
+
|
| 73 |
def criar_output_estruturado(self, summaries: List[str | Any], sources: Any):
|
| 74 |
structured_output = []
|
| 75 |
for idx, summary in enumerate(summaries):
|
|
|
|
| 114 |
chunk_overlap=serializer.chunk_overlap,
|
| 115 |
)
|
| 116 |
|
| 117 |
+
async def checar_se_resposta_vazia_do_documento_final(
|
| 118 |
+
self, llm_ultimas_requests: str, prompt: str
|
| 119 |
+
):
|
| 120 |
+
llm = self.select_model_for_last_requests(llm_ultimas_requests) # type: ignore
|
| 121 |
+
documento_gerado = ""
|
| 122 |
+
tentativas = 0
|
| 123 |
+
|
| 124 |
+
while tentativas < 5 and not documento_gerado:
|
| 125 |
+
tentativas += 1
|
| 126 |
+
try:
|
| 127 |
+
resposta = llm.invoke(prompt)
|
| 128 |
+
if hasattr(resposta, "content") and resposta.content.strip(): # type: ignore
|
| 129 |
+
if isinstance(resposta.content, list):
|
| 130 |
+
resposta.content = "\n".join(resposta.content) # type: ignore
|
| 131 |
+
|
| 132 |
+
documento_gerado = resposta.content.strip() # type: ignore
|
| 133 |
+
else:
|
| 134 |
+
print(f"Tentativa {tentativas}: resposta vazia ou inexistente.")
|
| 135 |
+
except Exception as e:
|
| 136 |
+
llm = self.select_model_for_last_requests("gemini-2.0-flash")
|
| 137 |
+
print(f"Tentativa {tentativas}: erro ao invocar o modelo: {e}")
|
| 138 |
+
time.sleep(5)
|
| 139 |
+
|
| 140 |
+
if not documento_gerado:
|
| 141 |
+
try:
|
| 142 |
+
self.axiom_instance.send_axiom(
|
| 143 |
+
"TENTANDO GERAR DOCUMENTO FINAL COM GPT 4o-mini COMO ÚLTIMA TENTATIVA"
|
| 144 |
+
)
|
| 145 |
+
documento_gerado = self.ultima_tentativa_requisicao(prompt)
|
| 146 |
+
except Exception as e:
|
| 147 |
+
raise Exception(
|
| 148 |
+
"Falha ao gerar o documento final na última tentativa."
|
| 149 |
+
) from e
|
| 150 |
+
|
| 151 |
+
return documento_gerado
|
| 152 |
+
|
| 153 |
+
def select_model_for_last_requests(
|
| 154 |
+
self,
|
| 155 |
+
llm_ultimas_requests: Literal[
|
| 156 |
+
"gpt-4o-mini", "deepseek-chat", "gemini-2.0-flash", "gemini-2.5-pro"
|
| 157 |
+
],
|
| 158 |
+
):
|
| 159 |
+
llm_instance = LLM()
|
| 160 |
+
if llm_ultimas_requests == "gpt-4o-mini":
|
| 161 |
+
llm = ChatOpenAI(
|
| 162 |
+
temperature=self.temperature,
|
| 163 |
+
model=self.model,
|
| 164 |
+
api_key=SecretStr(openai_api_key),
|
| 165 |
+
)
|
| 166 |
+
elif llm_ultimas_requests == "deepseek-chat":
|
| 167 |
+
llm = llm_instance.deepseek()
|
| 168 |
+
elif llm_ultimas_requests == "gemini-2.0-flash":
|
| 169 |
+
llm = llm_instance.google_gemini("gemini-2.0-flash")
|
| 170 |
+
elif llm_ultimas_requests == "gemini-2.5-pro":
|
| 171 |
+
llm = llm_instance.google_gemini("gemini-2.5-pro-preview-05-06")
|
| 172 |
+
elif llm_ultimas_requests == "gemini-2.5-flash":
|
| 173 |
+
llm = llm_instance.google_gemini("gemini-2.5-flash-preview-04-17")
|
| 174 |
+
return llm
|
| 175 |
+
|
| 176 |
|
| 177 |
class GerarDocumento:
|
| 178 |
lista_pdfs: List[str]
|
|
|
|
| 182 |
isBubble: bool
|
| 183 |
chunks_processados: List[ContextualizedChunk] | List[DocumentChunk]
|
| 184 |
resumo_auxiliar: str
|
| 185 |
+
gerar_documento_utils: GerarDocumentoUtils
|
| 186 |
utils = UtilsClass()
|
| 187 |
llm = LLM()
|
| 188 |
enhanced_vector_store: tuple[Chroma, BM25Okapi, List[str]]
|
|
|
|
| 207 |
self.config = self.gerar_documento_utils.create_retrieval_config(serializer)
|
| 208 |
self.logger = logging.getLogger(__name__)
|
| 209 |
# self.prompt_auxiliar = prompt_auxiliar
|
| 210 |
+
self.gerar_documento_utils = GerarDocumentoUtils(axiom_instance)
|
| 211 |
self.gpt_model = serializer.model
|
| 212 |
self.gpt_temperature = serializer.gpt_temperature
|
| 213 |
self.prompt_gerar_documento = serializer.prompt_gerar_documento
|
|
|
|
| 383 |
|
| 384 |
return sources, contexts
|
| 385 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 386 |
async def do_last_requests(
|
| 387 |
self,
|
| 388 |
) -> List[Dict]:
|
|
|
|
| 403 |
)
|
| 404 |
|
| 405 |
llm_ultimas_requests = self.llm_ultimas_requests
|
|
|
|
| 406 |
prompt_instance = Prompt()
|
| 407 |
context_do_prompt_primeira_etapa = "\n\n".join(contexts)
|
| 408 |
prompt_primeira_etapa = prompt_gerar_documento.format(
|
| 409 |
context=context_do_prompt_primeira_etapa,
|
| 410 |
)
|
| 411 |
|
| 412 |
+
self.gerar_documento_utils.model = self.gpt_model
|
| 413 |
+
self.gerar_documento_utils.temperature = self.gpt_temperature
|
| 414 |
+
documento_gerado = await self.gerar_documento_utils.checar_se_resposta_vazia_do_documento_final(
|
| 415 |
llm_ultimas_requests, prompt_primeira_etapa
|
| 416 |
)
|
| 417 |
|
|
|
|
| 429 |
dynamic_dict={"context": context_do_prompt_primeira_etapa},
|
| 430 |
)
|
| 431 |
# documento_gerado = llm.invoke(prompt_etapa_2).content
|
| 432 |
+
documento_gerado = self.gerar_documento_utils.checar_se_resposta_vazia_do_documento_final(
|
| 433 |
llm_ultimas_requests, prompt_etapa_2.to_string()
|
| 434 |
)
|
| 435 |
resposta_segunda_etapa = documento_gerado
|
|
|
|
| 447 |
},
|
| 448 |
)
|
| 449 |
# documento_gerado = llm.invoke(prompt_etapa_3).content
|
| 450 |
+
documento_gerado = self.gerar_documento_utils.checar_se_resposta_vazia_do_documento_final(
|
| 451 |
llm_ultimas_requests, prompt_etapa_3.to_string()
|
| 452 |
)
|
| 453 |
texto_final_juntando_as_etapas += f"\n\n{documento_gerado}"
|
|
|
|
| 511 |
|
| 512 |
self.axiom_instance.send_axiom("TERMINOU A REQUISIÇÃO FINAL PARA O BUBBLE")
|
| 513 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 514 |
async def gerar_ementa_final(
|
| 515 |
self,
|
| 516 |
llm_ultimas_requests: str,
|
|
|
|
| 521 |
llm = self.select_model_for_last_requests(llm_ultimas_requests) # type: ignore
|
| 522 |
prompt_instance = Prompt()
|
| 523 |
|
| 524 |
+
documento_gerado = await self.gerar_documento_utils.checar_se_resposta_vazia_do_documento_final(
|
| 525 |
llm_ultimas_requests, prompt_primeira_etapa
|
| 526 |
)
|
| 527 |
|
setup/installed_apps.py
CHANGED
|
@@ -16,4 +16,5 @@ INSTALLED_APPS = config_apps + [
|
|
| 16 |
"modelos_usuarios",
|
| 17 |
"ragas_api",
|
| 18 |
"gerar_documento",
|
|
|
|
| 19 |
]
|
|
|
|
| 16 |
"modelos_usuarios",
|
| 17 |
"ragas_api",
|
| 18 |
"gerar_documento",
|
| 19 |
+
"simple_llm",
|
| 20 |
]
|
setup/urls.py
CHANGED
|
@@ -19,4 +19,5 @@ urlpatterns = config_urls + [
|
|
| 19 |
path("", include("gerar_documento.urls")),
|
| 20 |
path("", include("ragas_api.urls")),
|
| 21 |
path("", include("modelos_usuarios.urls")),
|
|
|
|
| 22 |
]
|
|
|
|
| 19 |
path("", include("gerar_documento.urls")),
|
| 20 |
path("", include("ragas_api.urls")),
|
| 21 |
path("", include("modelos_usuarios.urls")),
|
| 22 |
+
path("", include("simple_llm.urls")),
|
| 23 |
]
|
simple_llm/__init__.py
ADDED
|
File without changes
|
simple_llm/admin.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.contrib import admin
|
| 2 |
+
|
| 3 |
+
# Register your models here.
|
simple_llm/apps.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.apps import AppConfig
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class SimpleLlmConfig(AppConfig):
|
| 5 |
+
default_auto_field = 'django.db.models.BigAutoField'
|
| 6 |
+
name = 'simple_llm'
|
simple_llm/migrations/__init__.py
ADDED
|
File without changes
|
simple_llm/models.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.db import models
|
| 2 |
+
|
| 3 |
+
# Create your models here.
|
simple_llm/serializer.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from dataclasses import dataclass, field
|
| 2 |
+
from typing import List, Optional, Union
|
| 3 |
+
from rest_framework import serializers
|
| 4 |
+
from _utils.gerar_documento_utils.prompts import (
|
| 5 |
+
prompt_gerar_documento,
|
| 6 |
+
)
|
| 7 |
+
from gerar_documento.serializer import FileInfoSerializer, FileInfoSerializerData
|
| 8 |
+
from gerar_documento.serializer_base import (
|
| 9 |
+
GerarDocumentoParametros,
|
| 10 |
+
GerarDocumentoParametrosData,
|
| 11 |
+
)
|
| 12 |
+
from setup.environment import default_model
|
| 13 |
+
from django.core.files.uploadedfile import UploadedFile
|
| 14 |
+
|
| 15 |
+
user_message = "What are the main points of this document?"
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class SimpleLLMInitialSerializer(serializers.Serializer):
|
| 19 |
+
files = serializers.ListField(child=serializers.FileField(), required=False)
|
| 20 |
+
user_text = serializers.CharField(required=False, default=user_message)
|
| 21 |
+
model = serializers.CharField(required=False, default=default_model)
|
| 22 |
+
prompt = serializers.CharField(required=False, default=prompt_gerar_documento)
|
| 23 |
+
llm_ultimas_requests = serializers.CharField(
|
| 24 |
+
required=False, default="gemini-2.0-flash"
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
@dataclass
|
| 29 |
+
class SimpleLLMInitialSerializerData:
|
| 30 |
+
files: List[dict] = field(default_factory=list)
|
| 31 |
+
user_text: str = ""
|
| 32 |
+
model: str = default_model
|
| 33 |
+
prompt: str = ""
|
| 34 |
+
llm_ultimas_requests: str = "gemini-2.0-flash"
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class SimpleLLMSerializer(SimpleLLMInitialSerializer):
|
| 38 |
+
files = serializers.ListField(child=FileInfoSerializer(), required=False)
|
| 39 |
+
bubble_editor_version = serializers.CharField(
|
| 40 |
+
required=False, default="version-test"
|
| 41 |
+
) # Será o valor utilizado dentro da URL da requisição pro Bubble
|
| 42 |
+
doc_id = serializers.CharField(required=True)
|
| 43 |
+
form_response_id = serializers.CharField(required=True)
|
| 44 |
+
version = serializers.CharField(required=True)
|
| 45 |
+
|
| 46 |
+
def get_obj(self):
|
| 47 |
+
return SimpleSerializerData(**self.validated_data) # type: ignore
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
@dataclass
|
| 51 |
+
class SimpleSerializerData(SimpleLLMInitialSerializerData):
|
| 52 |
+
files: List[FileInfoSerializerData] = field(default_factory=list)
|
| 53 |
+
bubble_editor_version: str = "version-test"
|
| 54 |
+
|
| 55 |
+
doc_id: str = ""
|
| 56 |
+
form_response_id: str = ""
|
| 57 |
+
version: str = ""
|
simple_llm/tests.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.test import TestCase
|
| 2 |
+
|
| 3 |
+
# Create your tests here.
|
simple_llm/urls.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from django.urls import path
|
| 2 |
+
|
| 3 |
+
from simple_llm.views import SimpleLLMView
|
| 4 |
+
|
| 5 |
+
urlpatterns = [
|
| 6 |
+
path(
|
| 7 |
+
"llm",
|
| 8 |
+
SimpleLLMView.as_view(),
|
| 9 |
+
name="simple-llm",
|
| 10 |
+
),
|
| 11 |
+
]
|
simple_llm/views.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime
|
| 2 |
+
from _utils.custom_exception_handler import custom_exception_handler_without_api_handler
|
| 3 |
+
from _utils.gerar_documento import gerar_documento
|
| 4 |
+
from _utils.gerar_documento_utils.GerarDocumento import (
|
| 5 |
+
GerarDocumento,
|
| 6 |
+
GerarDocumentoUtils,
|
| 7 |
+
)
|
| 8 |
+
from _utils.langchain_utils.Prompt_class import Prompt
|
| 9 |
+
from _utils.utils import convert_markdown_to_HTML
|
| 10 |
+
from setup.logging import Axiom
|
| 11 |
+
from setup.easy_imports import (
|
| 12 |
+
Response,
|
| 13 |
+
AsyncAPIView,
|
| 14 |
+
extend_schema,
|
| 15 |
+
)
|
| 16 |
+
from simple_llm.serializer import SimpleLLMSerializer
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class SimpleLLMView(AsyncAPIView):
|
| 20 |
+
# parser_classes = [MultiPartParser]
|
| 21 |
+
serializer = {}
|
| 22 |
+
axiom_instance = Axiom()
|
| 23 |
+
|
| 24 |
+
@extend_schema(
|
| 25 |
+
request=SimpleLLMSerializer,
|
| 26 |
+
)
|
| 27 |
+
async def post(self, request):
|
| 28 |
+
try:
|
| 29 |
+
self.axiom_instance.generate_new_uuid()
|
| 30 |
+
print(f"\n\nDATA E HORA DA REQUISIÇÃO: {datetime.now()}")
|
| 31 |
+
self.axiom_instance.send_axiom(
|
| 32 |
+
f"COMEÇOU NOVA REQUISIÇÃO - request.data: {request.data}"
|
| 33 |
+
)
|
| 34 |
+
serializer = SimpleLLMSerializer(data=request.data)
|
| 35 |
+
if serializer.is_valid(raise_exception=True):
|
| 36 |
+
obj = serializer.get_obj() # type: ignore
|
| 37 |
+
if not serializer.validated_data:
|
| 38 |
+
raise ValueError("Erro no validated_data")
|
| 39 |
+
|
| 40 |
+
self.serializer = obj
|
| 41 |
+
|
| 42 |
+
listaPDFs = [l.link_arquivo for l in obj.files]
|
| 43 |
+
self.axiom_instance.send_axiom(f"listaPDFs: {listaPDFs}")
|
| 44 |
+
|
| 45 |
+
summarizer = GerarDocumentoUtils(self.axiom_instance)
|
| 46 |
+
|
| 47 |
+
prompt_instance = Prompt()
|
| 48 |
+
prompt = prompt_instance.create_and_invoke_prompt(
|
| 49 |
+
obj.prompt,
|
| 50 |
+
dynamic_dict={"context": obj.user_text},
|
| 51 |
+
)
|
| 52 |
+
|
| 53 |
+
resposta_llm = (
|
| 54 |
+
await summarizer.checar_se_resposta_vazia_do_documento_final(
|
| 55 |
+
obj.llm_ultimas_requests, prompt.to_string()
|
| 56 |
+
)
|
| 57 |
+
)
|
| 58 |
+
self.axiom_instance.send_axiom(f"resposta_llm: {resposta_llm}")
|
| 59 |
+
|
| 60 |
+
texto_completo_como_html = convert_markdown_to_HTML(
|
| 61 |
+
resposta_llm
|
| 62 |
+
).replace("resposta_segunda_etapa:", "<br><br>")
|
| 63 |
+
|
| 64 |
+
self.axiom_instance.send_axiom(
|
| 65 |
+
f"texto_completo_como_html: {texto_completo_como_html}"
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
return Response({"resposta": texto_completo_como_html})
|
| 69 |
+
except Exception as e:
|
| 70 |
+
custom_exception_handler_without_api_handler(
|
| 71 |
+
e, serializer, self.axiom_instance
|
| 72 |
+
)
|
| 73 |
+
raise
|