LCA commited on
Commit
6808fce
·
verified ·
1 Parent(s): f8b1038

Un coup de copilote pour gérer la déviance du modèle, le dialogue : l'objectif est de partir sur un modele d'extraction et pas un modele de chat quand même.

Browse files
Files changed (1) hide show
  1. app.py +81 -21
app.py CHANGED
@@ -68,24 +68,52 @@ def rechercher_article(articleSource):
68
  def extract_json_from_response(response):
69
  """
70
  Extrait le premier bloc JSON valide d'une chaîne de texte contenant potentiellement du texte en vrac.
 
71
  Retourne un objet Python (dict) ou None si extraction impossible.
72
  """
73
- # Recherche tous les blocs JSON potentiels dans la réponse
74
- json_candidates = re.findall(r'({[\s\S]*?})', response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  for candidate in json_candidates:
76
  try:
77
- return json.loads(candidate)
 
 
 
 
 
78
  except Exception:
79
  continue
 
80
  # Si aucun bloc JSON valide trouvé, essayer de corriger les crochets manquants
81
  try:
82
- start = response.index('{')
83
- end = response.rindex('}') + 1
84
- json_str = response[start:end]
85
  return json.loads(json_str)
86
  except Exception as e:
87
  print("Erreur lors du parsing JSON extrait:", e)
88
- print("Aucun JSON trouvé dans la réponse.")
 
89
  return None
90
 
91
 
@@ -94,19 +122,32 @@ def respond(message):
94
  print(message)
95
  print(" ------------------ ")
96
  # Prompt par défaut
97
- custom_prompt = """Tu es un programme chargé de générer un fichier JSON à partir d'un message.
98
- Ta mission est de déterminer dans le messages fourni quels sont les articles qui sont demandés et pour quelle quantité.
99
- La réponse est au format json et donne uniquement une liste d'article.
100
- Pour chaque article 2 informations par article identifié : la désignation et le nombre
101
- La désignation peut être est formée du type d'article et des caractéristiques comme la matière ou les dimensions
102
-
103
- Return only JSON content.
 
 
 
 
 
 
 
104
 
 
 
 
 
 
105
  """
106
 
107
  messages = [{"role": "system", "content": custom_prompt}]
108
  messages += [{"role": "user", "content": message}]
109
 
 
110
  client = InferenceClient("HuggingFaceH4/zephyr-7b-beta", token=os.getenv("HF_TOKEN"))
111
  # client = InferenceClient(
112
  # "deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
@@ -118,10 +159,11 @@ def respond(message):
118
  full_response = ""
119
  for chunk in client.chat_completion(
120
  messages,
121
- max_tokens=512,
122
  stream=True,
123
- temperature=0.1,
124
- top_p=0.1,
 
125
  ):
126
  token = chunk.choices[0].delta.content
127
  if token:
@@ -139,11 +181,29 @@ def respond(message):
139
  # try:
140
  order = {}
141
  try:
 
 
 
142
 
143
  articles = []
144
- for article in json_response.get("articles", []):
145
- found_article = rechercher_article(article)
146
- articles.append(found_article)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  order["articles"] = articles
148
  # Ajouter les champs destinataire et delai avec des valeurs figées
149
  order["destinataire"] = {
@@ -182,4 +242,4 @@ with gr.Blocks() as demo:
182
  )
183
 
184
  if __name__ == "__main__":
185
- demo.launch(share=True)
 
68
  def extract_json_from_response(response):
69
  """
70
  Extrait le premier bloc JSON valide d'une chaîne de texte contenant potentiellement du texte en vrac.
71
+ Gère les dialogues USER/INST et autres artefacts de modèles de chat.
72
  Retourne un objet Python (dict) ou None si extraction impossible.
73
  """
74
+ # Nettoyer la réponse des balises de dialogue communes
75
+ cleaned_response = response
76
+
77
+ # Supprimer les balises de dialogue courantes
78
+ patterns_to_remove = [
79
+ r'USER:.*?(?=\{|$)',
80
+ r'INST:.*?(?=\{|$)',
81
+ r'ASSISTANT:.*?(?=\{|$)',
82
+ r'AI:.*?(?=\{|$)',
83
+ r'```json',
84
+ r'```',
85
+ r'Here is the JSON:',
86
+ r'The JSON response is:',
87
+ r'Response:',
88
+ ]
89
+
90
+ for pattern in patterns_to_remove:
91
+ cleaned_response = re.sub(pattern, '', cleaned_response, flags=re.IGNORECASE | re.DOTALL)
92
+
93
+ # Recherche tous les blocs JSON potentiels dans la réponse nettoyée
94
+ json_candidates = re.findall(r'({[\s\S]*?})', cleaned_response)
95
+
96
  for candidate in json_candidates:
97
  try:
98
+ # Nettoyer le candidat des caractères parasites
99
+ candidate = candidate.strip()
100
+ parsed = json.loads(candidate)
101
+ # Vérifier que c'est un objet avec la structure attendue
102
+ if isinstance(parsed, dict):
103
+ return parsed
104
  except Exception:
105
  continue
106
+
107
  # Si aucun bloc JSON valide trouvé, essayer de corriger les crochets manquants
108
  try:
109
+ start = cleaned_response.index('{')
110
+ end = cleaned_response.rindex('}') + 1
111
+ json_str = cleaned_response[start:end]
112
  return json.loads(json_str)
113
  except Exception as e:
114
  print("Erreur lors du parsing JSON extrait:", e)
115
+ print("Réponse brute:", response)
116
+ print("Réponse nettoyée:", cleaned_response)
117
  return None
118
 
119
 
 
122
  print(message)
123
  print(" ------------------ ")
124
  # Prompt par défaut
125
+ custom_prompt = """Tu es un analyseur de texte qui extrait des informations d'articles.
126
+ Tu dois analyser le message et identifier les articles demandés avec leurs quantités.
127
+
128
+ IMPORTANT: Réponds UNIQUEMENT avec un objet JSON valide, sans texte supplémentaire.
129
+
130
+ Format de réponse attendu:
131
+ {
132
+ "articles": [
133
+ {
134
+ "designation": "description de l'article",
135
+ "quantite": nombre_ou_null
136
+ }
137
+ ]
138
+ }
139
 
140
+ Règles:
141
+ - Pas de texte avant ou après le JSON
142
+ - Pas de commentaires
143
+ - Pas de dialogue USER/INST
144
+ - Juste le JSON brut
145
  """
146
 
147
  messages = [{"role": "system", "content": custom_prompt}]
148
  messages += [{"role": "user", "content": message}]
149
 
150
+ # Utiliser zephyr avec des paramètres plus stricts pour éviter les dialogues
151
  client = InferenceClient("HuggingFaceH4/zephyr-7b-beta", token=os.getenv("HF_TOKEN"))
152
  # client = InferenceClient(
153
  # "deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
 
159
  full_response = ""
160
  for chunk in client.chat_completion(
161
  messages,
162
+ max_tokens=256, # Réduire pour éviter les dialogues longs
163
  stream=True,
164
+ temperature=0.05, # Très faible pour plus de déterminisme
165
+ top_p=0.3, # Plus restrictif
166
+ do_sample=False, # Mode déterministe
167
  ):
168
  token = chunk.choices[0].delta.content
169
  if token:
 
181
  # try:
182
  order = {}
183
  try:
184
+ if json_response is None:
185
+ print("Aucun JSON valide trouvé dans la réponse")
186
+ return {"articles": [], "erreur": "Impossible de parser la réponse"}
187
 
188
  articles = []
189
+ # Vérifier si la réponse a la structure attendue
190
+ if "articles" in json_response:
191
+ articles_data = json_response["articles"]
192
+ else:
193
+ # Si pas de clé "articles", essayer d'utiliser la réponse directement si c'est une liste
194
+ if isinstance(json_response, list):
195
+ articles_data = json_response
196
+ else:
197
+ print("Structure JSON inattendue:", json_response)
198
+ return {"articles": [], "erreur": "Structure JSON inattendue"}
199
+
200
+ for article in articles_data:
201
+ if isinstance(article, dict) and "designation" in article:
202
+ found_article = rechercher_article(article)
203
+ articles.append(found_article)
204
+ else:
205
+ print("Article mal formaté:", article)
206
+
207
  order["articles"] = articles
208
  # Ajouter les champs destinataire et delai avec des valeurs figées
209
  order["destinataire"] = {
 
242
  )
243
 
244
  if __name__ == "__main__":
245
+ demo.launch(share=True)