pareaud commited on
Commit
b1abcde
·
verified ·
1 Parent(s): cef6b45

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -104
app.py CHANGED
@@ -1,18 +1,12 @@
1
- """
2
- Gradio app utilisant la nouvelle API OpenAI (>=1.0) + tool calls
3
- ----------------------------------------------------------------
4
- • Le recours à l’outil `extract_user_info` est forcé et relancé au besoin.
5
- • La clé API est désormais **codée en dur** (non recommandé en production).
6
- """
7
-
8
  import json
9
- from typing import Dict, Any
10
 
11
  import gradio as gr
 
12
  from openai import OpenAI
13
 
14
  # ------------------------------------------------------------------
15
- # 1 — Initialisation du client OpenAI (clé codée en dur)
16
  # ------------------------------------------------------------------
17
 
18
  client = OpenAI(
@@ -20,108 +14,64 @@ client = OpenAI(
20
  )
21
 
22
  # ------------------------------------------------------------------
23
- # 2 — Définition du schéma JSON (outil)
24
  # ------------------------------------------------------------------
25
 
26
- extraction_schema: Dict[str, Any] = {
27
- "name": "extract_user_info",
28
- "description": (
29
- "Extrait des informations personnelles depuis un texte libre pour "
30
- "remplir un formulaire administratif"
31
- ),
32
- "parameters": {
33
- "type": "object",
34
- "properties": {
35
- "nom": {"type": "string"},
36
- "prenom": {"type": "string"},
37
- "date_naissance": {
38
- "type": "string",
39
- "description": "au format YYYY-MM-DD",
40
- },
41
- "lieu_naissance": {"type": "string"},
42
- "nationalite": {"type": "string"},
43
- "adresse": {
44
- "type": "object",
45
- "properties": {
46
- "numero": {"type": "string"},
47
- "rue": {"type": "string"},
48
- "batiment": {"type": "string"},
49
- "appartement": {"type": "string"},
50
- "code_postal": {"type": "string"},
51
- "ville": {"type": "string"},
52
- },
53
- },
54
- "email": {"type": "string"},
55
- "telephone": {"type": "string"},
56
- "situation_familiale": {"type": "string"},
57
- "nombre_enfants": {"type": "integer"},
58
- "emploi": {"type": "string"},
59
- "nom_employeur": {"type": "string"},
60
- "type_piece_identite": {"type": "string"},
61
- "numero_piece_identite": {"type": "string"},
62
- "date_delivrance_piece": {"type": "string"},
63
- "lieu_delivrance_piece": {"type": "string"},
64
- "situation_logement": {"type": "string"},
65
- },
66
- "required": ["nom", "prenom", "date_naissance", "adresse"],
67
- },
68
- }
69
-
70
- TOOLS = [{"type": "function", "function": extraction_schema}]
71
 
72
  SYSTEM_PROMPT = (
73
  "Tu es un assistant administratif. À partir d’un texte mal rédigé, "
74
- "tu dois extraire les informations personnelles sous forme de JSON "
75
- "conforme au schéma fourni. Ne réponds JAMAIS hors JSON. "
76
- "Utilise IMPÉRATIVEMENT l'outil extract_user_info."
77
  )
78
 
79
  # ------------------------------------------------------------------
80
- # 3 — Fonction d'extraction avec relance forcée
81
  # ------------------------------------------------------------------
82
 
83
  def extraire_infos(texte: str) -> str:
84
- """Renvoie le JSON extrait ou une erreur si l’outil n’est jamais appelé."""
85
-
86
- messages = [
87
- {"role": "system", "content": SYSTEM_PROMPT},
88
- {"role": "user", "content": texte},
89
- ]
90
-
91
- for attempt in range(2): # on tente deux fois maximum
92
- response = client.chat.completions.create(
93
- model="gpt-4o-mini", # ou gpt-3.5-turbo-0125
94
  temperature=0,
95
- messages=messages,
96
- tools=TOOLS,
97
- tool_choice={
98
- "type": "function",
99
- "function": {"name": "extract_user_info"},
100
- },
101
  )
102
 
103
- choice = response.choices[0]
104
- if choice.finish_reason == "tool_calls":
105
- args_str = choice.message.tool_calls[0].function.arguments
106
- parsed = json.loads(args_str)
107
- return json.dumps(parsed, indent=2, ensure_ascii=False)
108
-
109
- # Pas d'appel d'outil : on renforce l'instruction et on réessaie
110
- messages.insert(
111
- 0,
112
- {
113
- "role": "system",
114
- "content": (
115
- "⚠️ Utilise OBLIGATOIREMENT l'outil extract_user_info et "
116
- "ne renvoie jamais de texte libre."
117
- ),
118
- },
119
- )
120
 
121
- return (
122
- "❌ Erreur : le modèle n'a pas renvoyé d'appel d'outil après deux "
123
- "tentatives."
124
- )
125
 
126
  # ------------------------------------------------------------------
127
  # 4 — Interface Gradio
@@ -142,16 +92,10 @@ with gr.Blocks(title="Extracteur intelligent de données CERFA") as demo:
142
  "L'IA le transforme en JSON prêt pour l'administration."
143
  )
144
 
145
- input_box = gr.Textbox(
146
- lines=14,
147
- label="Texte à corriger et structurer",
148
- value=texte_exemple,
149
- )
150
  output_box = gr.Code(label="Résultat JSON structuré")
151
 
152
- extract_btn = gr.Button("Extraire les données")
153
-
154
- extract_btn.click(extraire_infos, input_box, output_box)
155
 
156
  # ------------------------------------------------------------------
157
  # 5 — Lancement
 
 
 
 
 
 
 
 
1
  import json
2
+ from typing import Optional, List
3
 
4
  import gradio as gr
5
+ from pydantic import BaseModel
6
  from openai import OpenAI
7
 
8
  # ------------------------------------------------------------------
9
+ # 1 — Initialisation OpenAI (clé codée)
10
  # ------------------------------------------------------------------
11
 
12
  client = OpenAI(
 
14
  )
15
 
16
  # ------------------------------------------------------------------
17
+ # 2 — Définition du schéma via Pydantic
18
  # ------------------------------------------------------------------
19
 
20
+ class Adresse(BaseModel):
21
+ numero: str | None
22
+ rue: str | None
23
+ batiment: str | None
24
+ appartement: str | None
25
+ code_postal: str | None
26
+ ville: str | None
27
+
28
+ class UserInfo(BaseModel):
29
+ nom: str
30
+ prenom: str
31
+ date_naissance: str # YYYY-MM-DD
32
+ lieu_naissance: Optional[str]
33
+ nationalite: Optional[str]
34
+ adresse: Adresse
35
+ email: Optional[str]
36
+ telephone: Optional[str]
37
+ situation_familiale: Optional[str]
38
+ nombre_enfants: Optional[int]
39
+ emploi: Optional[str]
40
+ nom_employeur: Optional[str]
41
+ type_piece_identite: Optional[str]
42
+ numero_piece_identite: Optional[str]
43
+ date_delivrance_piece: Optional[str]
44
+ lieu_delivrance_piece: Optional[str]
45
+ situation_logement: Optional[str]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
  SYSTEM_PROMPT = (
48
  "Tu es un assistant administratif. À partir d’un texte mal rédigé, "
49
+ "tu dois extraire les informations personnelles et renvoyer un JSON "
50
+ "conforme au schéma. N'utilise jamais de prose."
 
51
  )
52
 
53
  # ------------------------------------------------------------------
54
+ # 3 — Fonction d'extraction (Structured Outputs)
55
  # ------------------------------------------------------------------
56
 
57
  def extraire_infos(texte: str) -> str:
58
+ try:
59
+ response = client.responses.parse(
60
+ model="gpt-4o-mini", # compatible Structured Outputs
61
+ input=[
62
+ {"role": "system", "content": SYSTEM_PROMPT},
63
+ {"role": "user", "content": texte},
64
+ ],
65
+ text_format=UserInfo, # Pydantic -> JSON Schema
66
+ strict=True,
 
67
  temperature=0,
 
 
 
 
 
 
68
  )
69
 
70
+ parsed = response.output_parsed # instance de UserInfo
71
+ return json.dumps(parsed.model_dump(), indent=2, ensure_ascii=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
+ except Exception as e:
74
+ return f"❌ Erreur : {e}"
 
 
75
 
76
  # ------------------------------------------------------------------
77
  # 4 — Interface Gradio
 
92
  "L'IA le transforme en JSON prêt pour l'administration."
93
  )
94
 
95
+ input_box = gr.Textbox(lines=14, label="Texte à corriger et structurer", value=texte_exemple)
 
 
 
 
96
  output_box = gr.Code(label="Résultat JSON structuré")
97
 
98
+ gr.Button("Extraire les données").click(extraire_infos, input_box, output_box)
 
 
99
 
100
  # ------------------------------------------------------------------
101
  # 5 — Lancement