luanpoppe commited on
Commit
85ee925
·
1 Parent(s): b909baa

feat: adicionar gerador de ementa

Browse files
_utils/gerar_documento_utils/GerarDocumento.py CHANGED
@@ -247,31 +247,14 @@ class GerarDocumento:
247
 
248
  llm = self.select_model_for_last_requests(llm_ultimas_requests) # type: ignore
249
  prompt_instance = Prompt()
250
- documento_gerado = ""
251
- tentativas = 0
252
  context_do_prompt_primeira_etapa = "\n\n".join(contexts)
253
  prompt_primeira_etapa = prompt_gerar_documento.format(
254
  context=context_do_prompt_primeira_etapa,
255
  )
256
 
257
- while tentativas < 5 and not documento_gerado:
258
- tentativas += 1
259
- resposta = llm.invoke(prompt_primeira_etapa)
260
- if hasattr(resposta, "content") and resposta.content.strip(): # type: ignore
261
- documento_gerado = resposta.content.strip() # type: ignore
262
- else:
263
- print(f"Tentativa {tentativas}: resposta vazia ou inexistente.")
264
- time.sleep(5)
265
-
266
- if not documento_gerado:
267
- self.axiom_instance.send_axiom(
268
- "TENTANDO GERAR DOCUMENTO FINAL COM GPT 4o-mini COMO ÚLTIMA TENTATIVA"
269
- )
270
- documento_gerado = (
271
- self.gerar_documento_utils.ultima_tentativa_requisicao(
272
- prompt_primeira_etapa
273
- )
274
- )
275
 
276
  texto_final_juntando_as_etapas = ""
277
  resposta_primeira_etapa = documento_gerado
@@ -318,3 +301,29 @@ class GerarDocumento:
318
  except Exception as e:
319
  self.logger.error(f"Error generating enhanced summary: {str(e)}")
320
  raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
 
248
  llm = self.select_model_for_last_requests(llm_ultimas_requests) # type: ignore
249
  prompt_instance = Prompt()
 
 
250
  context_do_prompt_primeira_etapa = "\n\n".join(contexts)
251
  prompt_primeira_etapa = prompt_gerar_documento.format(
252
  context=context_do_prompt_primeira_etapa,
253
  )
254
 
255
+ documento_gerado = await self.checar_se_resposta_vazia_do_documento_final(
256
+ llm_ultimas_requests, prompt_primeira_etapa
257
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
 
259
  texto_final_juntando_as_etapas = ""
260
  resposta_primeira_etapa = documento_gerado
 
301
  except Exception as e:
302
  self.logger.error(f"Error generating enhanced summary: {str(e)}")
303
  raise
304
+
305
+ async def checar_se_resposta_vazia_do_documento_final(
306
+ self, llm_ultimas_requests: str, prompt: str
307
+ ):
308
+ llm = self.select_model_for_last_requests(llm_ultimas_requests) # type: ignore
309
+ documento_gerado = ""
310
+ tentativas = 0
311
+
312
+ while tentativas < 5 and not documento_gerado:
313
+ tentativas += 1
314
+ resposta = llm.invoke(prompt)
315
+ if hasattr(resposta, "content") and resposta.content.strip(): # type: ignore
316
+ documento_gerado = resposta.content.strip() # type: ignore
317
+ else:
318
+ print(f"Tentativa {tentativas}: resposta vazia ou inexistente.")
319
+ time.sleep(5)
320
+
321
+ if not documento_gerado:
322
+ self.axiom_instance.send_axiom(
323
+ "TENTANDO GERAR DOCUMENTO FINAL COM GPT 4o-mini COMO ÚLTIMA TENTATIVA"
324
+ )
325
+ documento_gerado = self.gerar_documento_utils.ultima_tentativa_requisicao(
326
+ prompt
327
+ )
328
+
329
+ return documento_gerado
_utils/gerar_documento_utils/contextual_retriever.py CHANGED
@@ -274,7 +274,6 @@ class ContextualRetrieverUtils:
274
  resultado = None
275
  for pattern in patterns:
276
  matches: List[str] = re.findall(pattern, context, re.DOTALL)
277
- print("\n\nmatches", matches)
278
  condition_tuples_3_items = all(len(m) == 3 for m in matches)
279
  if len(matches) == len(lista_de_document_ids) and condition_tuples_3_items:
280
  print("\n--------------- REGEX DO CONTEXTUAL FUNCIONOU")
 
274
  resultado = None
275
  for pattern in patterns:
276
  matches: List[str] = re.findall(pattern, context, re.DOTALL)
 
277
  condition_tuples_3_items = all(len(m) == 3 for m in matches)
278
  if len(matches) == len(lista_de_document_ids) and condition_tuples_3_items:
279
  print("\n--------------- REGEX DO CONTEXTUAL FUNCIONOU")
_utils/gerar_documento_utils/utils.py CHANGED
@@ -11,6 +11,9 @@ from _utils.gerar_documento_utils.prompts import (
11
 
12
  from _utils.models.gerar_documento import DocumentChunk
13
  from gerar_documento.serializer import GerarDocumentoSerializerData
 
 
 
14
 
15
 
16
  def gerar_resposta_compilada(serializer: Union[GerarDocumentoSerializerData, Any]):
@@ -37,9 +40,6 @@ def gerar_resposta_compilada(serializer: Union[GerarDocumentoSerializerData, Any
37
 
38
  # Esta função gera a resposta que será usada em cada um das requisições de cada chunk
39
  async def get_response_from_auxiliar_contextual_prompt(full_text_as_array: List[str]):
40
- import tiktoken
41
-
42
- encoding = tiktoken.get_encoding("cl100k_base")
43
  llms = LLM()
44
  responses = []
45
 
@@ -86,12 +86,27 @@ async def get_response_from_auxiliar_contextual_prompt(full_text_as_array: List[
86
  return "".join(responses)
87
 
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  async def get_full_text_and_all_PDFs_chunks(
90
  listaPDFs: List[str],
91
  splitterObject: Splitter,
92
  should_use_llama_parse: bool,
93
  isBubble: bool,
94
- ):
95
  all_PDFs_chunks: List[DocumentChunk] = []
96
 
97
  pages: List[str] = []
 
11
 
12
  from _utils.models.gerar_documento import DocumentChunk
13
  from gerar_documento.serializer import GerarDocumentoSerializerData
14
+ import tiktoken
15
+
16
+ encoding = tiktoken.get_encoding("cl100k_base")
17
 
18
 
19
  def gerar_resposta_compilada(serializer: Union[GerarDocumentoSerializerData, Any]):
 
40
 
41
  # Esta função gera a resposta que será usada em cada um das requisições de cada chunk
42
  async def get_response_from_auxiliar_contextual_prompt(full_text_as_array: List[str]):
 
 
 
43
  llms = LLM()
44
  responses = []
45
 
 
86
  return "".join(responses)
87
 
88
 
89
+ def split_text_by_tokens(full_text: str):
90
+ tokens = encoding.encode(full_text)
91
+ max_tokens = 60000
92
+
93
+ # Divide os tokens em partes de no máximo max_tokens
94
+ token_chunks = [
95
+ tokens[i : i + max_tokens] for i in range(0, len(tokens), max_tokens)
96
+ ]
97
+
98
+ # Decodifica cada pedaço de tokens de volta para texto
99
+ text_chunks = [encoding.decode(chunk) for chunk in token_chunks]
100
+
101
+ return text_chunks
102
+
103
+
104
  async def get_full_text_and_all_PDFs_chunks(
105
  listaPDFs: List[str],
106
  splitterObject: Splitter,
107
  should_use_llama_parse: bool,
108
  isBubble: bool,
109
+ ) -> Tuple[List[DocumentChunk], List[str]]:
110
  all_PDFs_chunks: List[DocumentChunk] = []
111
 
112
  pages: List[str] = []
gerar_documento/views.py CHANGED
@@ -1,11 +1,17 @@
1
  from typing import Any, Dict, cast
2
  from langchain.prompts import PromptTemplate
 
 
 
3
  from _utils.langchain_utils.LLM_class import LLM
4
  from _utils.gerar_documento_utils.utils import (
 
 
5
  get_full_text_and_all_PDFs_chunks,
 
6
  )
7
  from _utils.langchain_utils.Prompt_class import Prompt
8
- from _utils.utils import print_sentry, sentry_add_breadcrumb
9
  from setup.easy_imports import (
10
  Response,
11
  AsyncAPIView,
@@ -40,8 +46,9 @@ class GerarDocumentoView(AsyncAPIView):
40
  async def post(self, request):
41
  self.axiom_instance.generate_new_uuid()
42
  print(f"\n\nDATA E HORA DA REQUISIÇÃO: {datetime.now()}")
43
- self.axiom_instance.send_axiom("COMEÇOU NOVA REQUISIÇÃO")
44
- self.axiom_instance.send_axiom(f"request.data: {request.data}")
 
45
  serializer = GerarDocumentoSerializer(data=request.data)
46
  if serializer.is_valid(raise_exception=True):
47
  obj = serializer.get_obj() # type: ignore
@@ -125,43 +132,82 @@ class GerarEmentaView(AsyncAPIView):
125
  )
126
  serializer = GerarDocumentoSerializer(data=request.data)
127
  if serializer.is_valid(raise_exception=True):
 
128
  if not serializer.validated_data:
129
  raise ValueError("Erro no validated_data")
130
 
131
  async def proccess_data_after_response():
132
- data = cast(Dict[str, Any], serializer.validated_data)
133
- serializer_obj = serializer.get_obj()
134
- self.serializer = data
135
 
136
- listaPDFs = [l["link_arquivo"] for l in data["files"]]
137
- self.axiom_instance.send_axiom(
138
- f"listaPDFs: {listaPDFs}",
139
- )
140
 
141
- all_PDFs_chunks, full_text_as_array = (
142
- await get_full_text_and_all_PDFs_chunks(
143
- listaPDFs,
144
- Splitter(
145
- serializer_obj.chunk_size, serializer_obj.chunk_overlap
146
- ),
147
- False,
148
- True,
 
 
 
 
 
 
 
149
  )
150
- )
151
- full_text = "".join(full_text_as_array)
152
- self.axiom_instance.send_axiom(
153
- f"full_text gerado dos pdfs: {full_text}"
154
- )
155
 
156
- llm = LLM()
157
- prompt_template = PromptTemplate(
158
- input_variables=["context"], template=full_text
159
- )
160
- response = await llm.google_gemini().ainvoke(
161
- prompt_template.format(context=full_text)
162
- )
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
- print("\n\nresposta_llm: ", response.content)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
 
166
  # asyncio.create_task(proccess_data_after_response())
167
  loop = asyncio.get_running_loop()
@@ -193,10 +239,11 @@ class GerarEmentaComPDFProprioView(AsyncAPIView):
193
  data = cast(Dict[str, Any], serializer.validated_data)
194
  self.axiom_instance.send_axiom(f"data: {data}")
195
  self.serializer = data
196
-
197
- data = cast(Dict[str, Any], serializer.validated_data)
198
  serializer_obj = serializer.get_obj()
199
- self.serializer = data
 
 
 
200
 
201
  listaPDFs = handle_pdf_files_from_serializer(
202
  data["files"], self.axiom_instance
@@ -208,7 +255,7 @@ class GerarEmentaComPDFProprioView(AsyncAPIView):
208
  listaPDFs,
209
  Splitter(serializer_obj.chunk_size, serializer_obj.chunk_overlap),
210
  False,
211
- True,
212
  )
213
  )
214
  full_text = "".join(full_text_as_array)
@@ -216,18 +263,36 @@ class GerarEmentaComPDFProprioView(AsyncAPIView):
216
  f"full_text[0:100] gerado do PDF: {full_text[0:100]}"
217
  )
218
 
219
- llm = LLM()
220
- prompt_template = PromptTemplate(
221
- input_variables=["context"], template=full_text
222
- )
223
- response = await llm.google_gemini().ainvoke(
224
- prompt_template.format(context=full_text)
 
 
 
 
 
 
 
 
 
225
  )
 
226
 
227
- self.axiom_instance.send_axiom(f"resposta_llm: {response.content}")
 
 
228
 
229
  remove_pdf_temp_files(listaPDFs)
230
  self.axiom_instance.send_axiom(
231
  "PRÓXIMA LINHA ENVIA A RESPOSTA A QUEM FEZ A REQUISIÇÃO"
232
  )
233
- return Response({"resposta": response.content})
 
 
 
 
 
 
 
1
  from typing import Any, Dict, cast
2
  from langchain.prompts import PromptTemplate
3
+ from _utils.bubble_integrations.enviar_resposta_final import enviar_resposta_final
4
+ from _utils.custom_exception_handler import custom_exception_handler_wihout_api_handler
5
+ from _utils.gerar_documento_utils.GerarDocumento import GerarDocumento
6
  from _utils.langchain_utils.LLM_class import LLM
7
  from _utils.gerar_documento_utils.utils import (
8
+ generate_document_title,
9
+ gerar_resposta_compilada,
10
  get_full_text_and_all_PDFs_chunks,
11
+ split_text_by_tokens,
12
  )
13
  from _utils.langchain_utils.Prompt_class import Prompt
14
+ from _utils.utils import convert_markdown_to_HTML, print_sentry, sentry_add_breadcrumb
15
  from setup.easy_imports import (
16
  Response,
17
  AsyncAPIView,
 
46
  async def post(self, request):
47
  self.axiom_instance.generate_new_uuid()
48
  print(f"\n\nDATA E HORA DA REQUISIÇÃO: {datetime.now()}")
49
+ self.axiom_instance.send_axiom(
50
+ f"COMEÇOU NOVA REQUISIÇÃO - request.data: {request.data}"
51
+ )
52
  serializer = GerarDocumentoSerializer(data=request.data)
53
  if serializer.is_valid(raise_exception=True):
54
  obj = serializer.get_obj() # type: ignore
 
132
  )
133
  serializer = GerarDocumentoSerializer(data=request.data)
134
  if serializer.is_valid(raise_exception=True):
135
+ obj = serializer.get_obj() # type: ignore
136
  if not serializer.validated_data:
137
  raise ValueError("Erro no validated_data")
138
 
139
  async def proccess_data_after_response():
140
+ try:
141
+ data = cast(Dict[str, Any], serializer.validated_data)
142
+ self.serializer = data
143
 
144
+ gerar_documento_instance = GerarDocumento(obj, self.axiom_instance)
 
 
 
145
 
146
+ listaPDFs = [l["link_arquivo"] for l in data["files"]]
147
+
148
+ self.axiom_instance.send_axiom(f"listaPDFs: {listaPDFs}")
149
+
150
+ all_PDFs_chunks, full_text_as_array = (
151
+ await get_full_text_and_all_PDFs_chunks(
152
+ listaPDFs,
153
+ Splitter(obj.chunk_size, obj.chunk_overlap),
154
+ False,
155
+ True,
156
+ )
157
+ )
158
+ full_text = "".join(full_text_as_array)
159
+ self.axiom_instance.send_axiom(
160
+ f"full_text[0:100] gerado do PDF: {full_text[0:100]}"
161
  )
 
 
 
 
 
162
 
163
+ texto_completo = ""
164
+ text_splitted_by_tokens = split_text_by_tokens(full_text)
165
+ for text in text_splitted_by_tokens:
166
+ prompt_template = PromptTemplate(
167
+ input_variables=["context"], template=obj.user_message
168
+ )
169
+ texto_da_parte = await gerar_documento_instance.checar_se_resposta_vazia_do_documento_final(
170
+ obj.llm_ultimas_requests,
171
+ prompt_template.format(context=text),
172
+ )
173
+
174
+ texto_completo += texto_da_parte
175
+
176
+ texto_completo_como_html = convert_markdown_to_HTML(
177
+ texto_completo
178
+ ).replace("resposta_segunda_etapa:", "<br><br>")
179
+ self.axiom_instance.send_axiom(
180
+ f"resposta_llm: {texto_completo_como_html}"
181
+ )
182
 
183
+ titulo_do_documento = await generate_document_title(
184
+ cast(str, texto_completo_como_html)
185
+ )
186
+
187
+ self.axiom_instance.send_axiom(
188
+ "PRÓXIMA LINHA ENVIA A RESPOSTA A QUEM FEZ A REQUISIÇÃO"
189
+ )
190
+
191
+ self.axiom_instance.send_axiom(
192
+ "COMEÇANDO A REQUISIÇÃO FINAL PARA O BUBBLE"
193
+ )
194
+ enviar_resposta_final(
195
+ obj.doc_id, # type: ignore
196
+ obj.form_response_id, # type: ignore
197
+ obj.version, # type: ignore
198
+ texto_completo_como_html,
199
+ False,
200
+ cast(str, titulo_do_documento),
201
+ )
202
+ self.axiom_instance.send_axiom(
203
+ "TERMINOU A REQUISIÇÃO FINAL PARA O BUBBLE"
204
+ )
205
+ except Exception as e:
206
+ print(f"ERRO GERAR EMENTA: {e}")
207
+ custom_exception_handler_wihout_api_handler(
208
+ e, serializer, self.axiom_instance
209
+ )
210
+ raise
211
 
212
  # asyncio.create_task(proccess_data_after_response())
213
  loop = asyncio.get_running_loop()
 
239
  data = cast(Dict[str, Any], serializer.validated_data)
240
  self.axiom_instance.send_axiom(f"data: {data}")
241
  self.serializer = data
 
 
242
  serializer_obj = serializer.get_obj()
243
+
244
+ gerar_documento_instance = GerarDocumento(
245
+ serializer_obj, self.axiom_instance
246
+ )
247
 
248
  listaPDFs = handle_pdf_files_from_serializer(
249
  data["files"], self.axiom_instance
 
255
  listaPDFs,
256
  Splitter(serializer_obj.chunk_size, serializer_obj.chunk_overlap),
257
  False,
258
+ False,
259
  )
260
  )
261
  full_text = "".join(full_text_as_array)
 
263
  f"full_text[0:100] gerado do PDF: {full_text[0:100]}"
264
  )
265
 
266
+ texto_completo = ""
267
+ text_splitted_by_tokens = split_text_by_tokens(full_text)
268
+ for text in text_splitted_by_tokens:
269
+ prompt_template = PromptTemplate(
270
+ input_variables=["context"], template=serializer_obj.user_message
271
+ )
272
+ texto_da_parte = await gerar_documento_instance.checar_se_resposta_vazia_do_documento_final(
273
+ serializer_obj.llm_ultimas_requests,
274
+ prompt_template.format(context=text),
275
+ )
276
+
277
+ texto_completo += texto_da_parte
278
+
279
+ texto_completo_como_html = convert_markdown_to_HTML(texto_completo).replace(
280
+ "resposta_segunda_etapa:", "<br><br>"
281
  )
282
+ self.axiom_instance.send_axiom(f"resposta_llm: {texto_completo_como_html}")
283
 
284
+ titulo_do_documento = await generate_document_title(
285
+ cast(str, texto_completo_como_html)
286
+ )
287
 
288
  remove_pdf_temp_files(listaPDFs)
289
  self.axiom_instance.send_axiom(
290
  "PRÓXIMA LINHA ENVIA A RESPOSTA A QUEM FEZ A REQUISIÇÃO"
291
  )
292
+
293
+ return Response(
294
+ {
295
+ "texto_completo": texto_completo_como_html,
296
+ "titulo_do_documento": titulo_do_documento,
297
+ }
298
+ )