habulaj commited on
Commit
76cb254
·
verified ·
1 Parent(s): 330cc3d

Update routers/inference_createposter.py

Browse files
Files changed (1) hide show
  1. routers/inference_createposter.py +88 -29
routers/inference_createposter.py CHANGED
@@ -1,5 +1,7 @@
1
  import os
2
  import logging
 
 
3
  from urllib.parse import urlencode, quote, parse_qs, urlparse, urlunparse
4
  from fastapi import APIRouter, HTTPException
5
  from pydantic import BaseModel
@@ -18,6 +20,56 @@ class PosterResponse(BaseModel):
18
  result: dict
19
  urls: list
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  def fix_citation_quotes(citation_text: str) -> str:
22
  """
23
  Corrige as aspas no texto de citação:
@@ -27,15 +79,14 @@ def fix_citation_quotes(citation_text: str) -> str:
27
  """
28
  if not citation_text or citation_text.strip() == "":
29
  return citation_text
30
-
31
  text = citation_text.strip()
32
 
33
  # Remover todas as tags HTML
34
- import re
35
  text = re.sub(r'<[^>]+>', '', text)
36
 
37
  # Verificar se já tem as aspas corretas
38
- if text.startswith('') and text.endswith(''):
39
  return text
40
 
41
  # Remover aspas existentes do início e fim
@@ -50,7 +101,7 @@ def fix_citation_quotes(citation_text: str) -> str:
50
  text = text[:-1]
51
 
52
  # Adicionar as aspas corretas
53
- return f"{text.strip()}"
54
 
55
  def clean_text_content_for_text_param(text: str) -> str:
56
  """
@@ -62,12 +113,9 @@ def clean_text_content_for_text_param(text: str) -> str:
62
  if not text:
63
  return text
64
 
65
- import re
66
-
67
  # Primeiro, resolver conflitos de tags aninhadas - priorizar a segunda (mais interna)
68
  # <strong><em>conteúdo</em></strong> -> <em>conteúdo</em>
69
  text = re.sub(r'<strong>\s*<em>(.*?)</em>\s*</strong>', r'<em>\1</em>', text)
70
-
71
  # <em><strong>conteúdo</strong></em> -> <strong>conteúdo</strong>
72
  text = re.sub(r'<em>\s*<strong>(.*?)</strong>\s*</em>', r'<strong>\1</strong>', text)
73
 
@@ -84,8 +132,6 @@ def clean_text_content_remove_all_tags(text: str) -> str:
84
  if not text:
85
  return text
86
 
87
- import re
88
-
89
  # Remove TODAS as tags HTML usando regex mais ampla
90
  text = re.sub(r'<[^>]*>', '', text)
91
 
@@ -143,14 +189,14 @@ def fix_url_citation(url: str) -> str:
143
 
144
  # Reconstruir a query string
145
  new_query = urlencode(
146
- {k: v[0] if isinstance(v, list) and len(v) == 1 else v for k, v in query_params.items()},
147
  quote_via=quote
148
  )
149
 
150
  # Reconstruir a URL
151
  new_parsed_url = parsed_url._replace(query=new_query)
152
  return urlunparse(new_parsed_url)
153
-
154
  except Exception as e:
155
  logger.warning(f"Erro ao processar URL para correção de texto: {e}")
156
  return url
@@ -172,7 +218,6 @@ def format_url(base_url: str, endpoint: str, params: dict) -> str:
172
 
173
  # Construir query string
174
  query_string = urlencode(url_params, quote_via=quote)
175
-
176
  return f"{full_url}?{query_string}"
177
 
178
  def generate_urls_from_result(result: dict, base_url: str = "https://habulaj-newapi-clone.hf.space") -> list:
@@ -193,8 +238,8 @@ def generate_urls_from_result(result: dict, base_url: str = "https://habulaj-new
193
  # Adicionar URL da capa
194
  if "cover" in result:
195
  cover_url = format_url(
196
- base_url,
197
- result["cover"]["endpoint"],
198
  result["cover"]["params"]
199
  )
200
  # Corrigir citation na URL se presente
@@ -579,9 +624,9 @@ Atenção: este artigo contém spoilers importantes sobre o enredo e o final do
579
  contents=contents,
580
  config=config
581
  )
582
-
583
  logger.info("Resposta do modelo recebida com sucesso")
584
-
585
  # Extrair texto da resposta
586
  response_text = ""
587
  if hasattr(response, 'text') and response.text:
@@ -593,34 +638,48 @@ Atenção: este artigo contém spoilers importantes sobre o enredo e o final do
593
  for part in candidate.content.parts:
594
  if hasattr(part, 'text') and part.text:
595
  response_text += part.text
596
-
597
  if not response_text or response_text.strip() == "":
598
  logger.error("Resposta do modelo está vazia")
599
  raise HTTPException(
600
- status_code=500,
601
  detail="Modelo não retornou conteúdo válido"
602
  )
 
 
 
603
 
604
  # Parse do JSON
605
- import json
606
  try:
607
- result_json = json.loads(response_text)
608
  except json.JSONDecodeError as e:
609
  logger.error(f"Erro ao fazer parse do JSON: {e}")
610
- logger.error(f"Resposta recebida: {response_text}")
611
- raise HTTPException(
612
- status_code=500,
613
- detail=f"Resposta do modelo não é um JSON válido: {str(e)}"
614
- )
615
-
 
 
 
 
 
 
 
 
 
 
 
 
616
  # Gerar URLs formatadas
617
  formatted_urls = generate_urls_from_result(result_json)
618
-
619
  logger.info("Processamento concluído com sucesso")
620
  logger.info(f"URLs geradas: {formatted_urls}")
621
-
622
  return PosterResponse(result=result_json, urls=formatted_urls)
623
-
624
  except HTTPException:
625
  raise
626
  except Exception as e:
 
1
  import os
2
  import logging
3
+ import re
4
+ import json
5
  from urllib.parse import urlencode, quote, parse_qs, urlparse, urlunparse
6
  from fastapi import APIRouter, HTTPException
7
  from pydantic import BaseModel
 
20
  result: dict
21
  urls: list
22
 
23
+ def clean_json_string(json_string: str) -> str:
24
+ """
25
+ Remove caracteres de controle inválidos do JSON antes do parse.
26
+ """
27
+ if not json_string:
28
+ return json_string
29
+
30
+ # Remove caracteres de controle (exceto \t, \n, \r que são válidos em JSON)
31
+ # mas precisamos escapar corretamente dentro das strings
32
+ cleaned = ""
33
+ i = 0
34
+ in_string = False
35
+ escape_next = False
36
+
37
+ while i < len(json_string):
38
+ char = json_string[i]
39
+
40
+ if escape_next:
41
+ # Se o caractere anterior foi \, adiciona este caractere escapado
42
+ cleaned += char
43
+ escape_next = False
44
+ elif char == '\\' and in_string:
45
+ # Caractere de escape dentro de string
46
+ cleaned += char
47
+ escape_next = True
48
+ elif char == '"' and not escape_next:
49
+ # Início ou fim de string (se não estiver escapado)
50
+ cleaned += char
51
+ in_string = not in_string
52
+ elif in_string:
53
+ # Dentro de string - tratar caracteres especiais
54
+ if ord(char) < 32 and char not in ['\t']: # Remove controles exceto tab
55
+ if char == '\n':
56
+ cleaned += '\\n' # Escapa quebra de linha
57
+ elif char == '\r':
58
+ cleaned += '\\r' # Escapa carriage return
59
+ else:
60
+ # Remove outros caracteres de controle
61
+ pass
62
+ else:
63
+ cleaned += char
64
+ else:
65
+ # Fora de string - remove apenas caracteres de controle problemáticos
66
+ if ord(char) >= 32 or char in ['\t', '\n', '\r', ' ']:
67
+ cleaned += char
68
+
69
+ i += 1
70
+
71
+ return cleaned
72
+
73
  def fix_citation_quotes(citation_text: str) -> str:
74
  """
75
  Corrige as aspas no texto de citação:
 
79
  """
80
  if not citation_text or citation_text.strip() == "":
81
  return citation_text
82
+
83
  text = citation_text.strip()
84
 
85
  # Remover todas as tags HTML
 
86
  text = re.sub(r'<[^>]+>', '', text)
87
 
88
  # Verificar se já tem as aspas corretas
89
+ if text.startswith('"') and text.endswith('"'):
90
  return text
91
 
92
  # Remover aspas existentes do início e fim
 
101
  text = text[:-1]
102
 
103
  # Adicionar as aspas corretas
104
+ return f""{text.strip()}""
105
 
106
  def clean_text_content_for_text_param(text: str) -> str:
107
  """
 
113
  if not text:
114
  return text
115
 
 
 
116
  # Primeiro, resolver conflitos de tags aninhadas - priorizar a segunda (mais interna)
117
  # <strong><em>conteúdo</em></strong> -> <em>conteúdo</em>
118
  text = re.sub(r'<strong>\s*<em>(.*?)</em>\s*</strong>', r'<em>\1</em>', text)
 
119
  # <em><strong>conteúdo</strong></em> -> <strong>conteúdo</strong>
120
  text = re.sub(r'<em>\s*<strong>(.*?)</strong>\s*</em>', r'<strong>\1</strong>', text)
121
 
 
132
  if not text:
133
  return text
134
 
 
 
135
  # Remove TODAS as tags HTML usando regex mais ampla
136
  text = re.sub(r'<[^>]*>', '', text)
137
 
 
189
 
190
  # Reconstruir a query string
191
  new_query = urlencode(
192
+ {k: v[0] if isinstance(v, list) and len(v) == 1 else v for k, v in query_params.items()},
193
  quote_via=quote
194
  )
195
 
196
  # Reconstruir a URL
197
  new_parsed_url = parsed_url._replace(query=new_query)
198
  return urlunparse(new_parsed_url)
199
+
200
  except Exception as e:
201
  logger.warning(f"Erro ao processar URL para correção de texto: {e}")
202
  return url
 
218
 
219
  # Construir query string
220
  query_string = urlencode(url_params, quote_via=quote)
 
221
  return f"{full_url}?{query_string}"
222
 
223
  def generate_urls_from_result(result: dict, base_url: str = "https://habulaj-newapi-clone.hf.space") -> list:
 
238
  # Adicionar URL da capa
239
  if "cover" in result:
240
  cover_url = format_url(
241
+ base_url,
242
+ result["cover"]["endpoint"],
243
  result["cover"]["params"]
244
  )
245
  # Corrigir citation na URL se presente
 
624
  contents=contents,
625
  config=config
626
  )
627
+
628
  logger.info("Resposta do modelo recebida com sucesso")
629
+
630
  # Extrair texto da resposta
631
  response_text = ""
632
  if hasattr(response, 'text') and response.text:
 
638
  for part in candidate.content.parts:
639
  if hasattr(part, 'text') and part.text:
640
  response_text += part.text
641
+
642
  if not response_text or response_text.strip() == "":
643
  logger.error("Resposta do modelo está vazia")
644
  raise HTTPException(
645
+ status_code=500,
646
  detail="Modelo não retornou conteúdo válido"
647
  )
648
+
649
+ # Limpar caracteres de controle antes do parse
650
+ clean_response = clean_json_string(response_text)
651
 
652
  # Parse do JSON
 
653
  try:
654
+ result_json = json.loads(clean_response)
655
  except json.JSONDecodeError as e:
656
  logger.error(f"Erro ao fazer parse do JSON: {e}")
657
+ logger.error(f"Resposta original: {response_text}")
658
+ logger.error(f"Resposta limpa: {clean_response}")
659
+
660
+ # Tentar uma limpeza mais agressiva como fallback
661
+ try:
662
+ # Remove quebras de linha e espaços extras
663
+ fallback_clean = re.sub(r'\s+', ' ', response_text.strip())
664
+ # Remove caracteres de controle
665
+ fallback_clean = ''.join(char for char in fallback_clean if ord(char) >= 32 or char in [' ', '\t'])
666
+ result_json = json.loads(fallback_clean)
667
+ logger.info("Parse bem-sucedido com limpeza de fallback")
668
+ except json.JSONDecodeError as fallback_error:
669
+ logger.error(f"Erro no fallback também: {fallback_error}")
670
+ raise HTTPException(
671
+ status_code=500,
672
+ detail=f"Resposta do modelo não é um JSON válido: {str(e)}"
673
+ )
674
+
675
  # Gerar URLs formatadas
676
  formatted_urls = generate_urls_from_result(result_json)
677
+
678
  logger.info("Processamento concluído com sucesso")
679
  logger.info(f"URLs geradas: {formatted_urls}")
680
+
681
  return PosterResponse(result=result_json, urls=formatted_urls)
682
+
683
  except HTTPException:
684
  raise
685
  except Exception as e: