Marylene commited on
Commit
73a7679
·
1 Parent(s): 531d9ae
Files changed (3) hide show
  1. agent.py +25 -32
  2. app.py +19 -20
  3. email_sender.py +24 -18
agent.py CHANGED
@@ -1,22 +1,14 @@
1
- import os
2
  from huggingface_hub import InferenceClient
 
3
 
4
- def generate_email(model_id: str, to: str, context: str, tone: str) -> tuple[str, str]:
5
- """
6
- Génère un email en deux parties : sujet et corps du message.
7
-
8
- Args:
9
- model_id (str): ID du modèle HF.
10
- to (str): Adresse email cible.
11
- context (str): Contexte du message.
12
- tone (str): Ton souhaité (formel, amical, chaleureux...).
13
 
14
- Returns:
15
- tuple[str, str]: sujet, corps
16
- """
17
- client = InferenceClient(model=model_id, token=os.getenv("HF_TOKEN"))
18
 
19
- prompt = f"""Tu es un assistant virtuel. Rédige un email destiné à {to}.
 
20
 
21
  Contexte : {context}
22
  Ton : {tone}
@@ -25,21 +17,22 @@ Réponds en deux parties :
25
  1. Objet : ligne d'objet de l'email
26
  2. Corps : contenu de l'email bien rédigé, en respectant le ton demandé.
27
  Commence chaque partie par son étiquette.
28
- """
29
-
30
- response = client.text_generation(
31
- prompt,
32
- max_new_tokens=500,
33
- temperature=0.7,
34
- top_p=0.95,
35
- stop_sequences=["\n\n"]
36
- )
37
-
38
- if "Objet" in response and "Corps" in response:
39
- subject = response.split("Objet", 1)[-1].split("Corps")[0].strip(": \n")
40
- body = response.split("Corps", 1)[-1].strip()
41
- else:
42
- subject = "Sujet non généré"
43
- body = response.strip()
44
-
 
45
  return subject, body
 
 
1
  from huggingface_hub import InferenceClient
2
+ import os
3
 
4
+ # Utilise le token depuis les secrets HF
5
+ HF_TOKEN = os.getenv("HUGGINGFACEHUB_API_TOKEN")
 
 
 
 
 
 
 
6
 
7
+ def generate_email(model_id, to_email, context, tone):
8
+ client = InferenceClient(token=HF_TOKEN)
 
 
9
 
10
+ prompt = f"""
11
+ Tu es un assistant virtuel. Rédige un email destiné à {to_email}.
12
 
13
  Contexte : {context}
14
  Ton : {tone}
 
17
  1. Objet : ligne d'objet de l'email
18
  2. Corps : contenu de l'email bien rédigé, en respectant le ton demandé.
19
  Commence chaque partie par son étiquette.
20
+ """.strip()
21
+
22
+ try:
23
+ response = client.text_generation(
24
+ model=model_id,
25
+ prompt=prompt,
26
+ max_new_tokens=512,
27
+ temperature=0.7,
28
+ )
29
+ return parse_email(response)
30
+ except Exception as e:
31
+ return "Erreur", f"❌ Erreur de génération : {e}"
32
+
33
+ def parse_email(text):
34
+ lines = text.strip().split("\n")
35
+ subject = next((line for line in lines if line.lower().startswith("objet")), "Objet : (non trouvé)")
36
+ body_lines = [line for line in lines if not line.lower().startswith("objet")]
37
+ body = "\n".join(body_lines).strip()
38
  return subject, body
app.py CHANGED
@@ -6,31 +6,30 @@ def on_generate(to_email, context, tone):
6
  subject, body = generate_email("mistralai/Mistral-7B-Instruct-v0.1", to_email, context, tone)
7
  return subject, body
8
 
9
- def on_send(to_email, subject, body, sender_email, refresh_token):
10
- success, msg = send_email(sender_email, to_email, subject, body, refresh_token)
11
- return msg
12
 
13
- with gr.Blocks(theme="soft", css="body { background-color: #111; color: #eee; }") as demo:
14
- gr.Markdown("## ✉️ Assistant de Rédaction & Envoi d’Emails", elem_id="title")
15
 
16
  with gr.Row():
17
- to_email = gr.Textbox(label="📨 Destinataire")
18
- sender_email = gr.Textbox(label="📤 Votre email Gmail")
19
- refresh_token = gr.Textbox(label="🔐 Refresh token (coller ici)", type="password")
 
 
20
 
21
- context = gr.Textbox(lines=3, label="📝 Contexte")
22
- tone = gr.Dropdown(["Formel", "Amical", "Chaleureux", "Professionnel"], label="🎭 Ton", value="Formel")
 
23
 
24
  with gr.Row():
25
- generate_btn = gr.Button("💡 Générer l'email")
26
- send_btn = gr.Button("📤 Envoyer l'email")
 
 
27
 
28
- subject = gr.Textbox(label="✏️ Objet de l'email")
29
- body = gr.Textbox(lines=10, label="📄 Contenu de l'email")
30
 
31
- status = gr.Markdown("")
32
-
33
- generate_btn.click(fn=on_generate, inputs=[to_email, context, tone], outputs=[subject, body])
34
- send_btn.click(fn=on_send, inputs=[to_email, subject, body, sender_email, refresh_token], outputs=status)
35
-
36
- demo.launch()
 
6
  subject, body = generate_email("mistralai/Mistral-7B-Instruct-v0.1", to_email, context, tone)
7
  return subject, body
8
 
9
+ def on_send(sender_email, to_email, subject, body, refresh_token):
10
+ return send_email(sender_email, to_email, subject, body, refresh_token)
 
11
 
12
+ with gr.Blocks(theme=gr.themes.Base(), css="body { background-color: #111; color: white; }") as app:
13
+ gr.Markdown("## ✉️ Agent d'envoi de mails", elem_id="title")
14
 
15
  with gr.Row():
16
+ with gr.Column():
17
+ to_email = gr.Text(label="Destinataire")
18
+ context = gr.Text(label="Contexte de l'email")
19
+ tone = gr.Dropdown(["Chaleureux", "Formel", "Amical"], value="Chaleureux", label="Ton")
20
+ generate_btn = gr.Button("✏️ Générer l'email")
21
 
22
+ with gr.Column():
23
+ subject_output = gr.Text(label="Objet")
24
+ body_output = gr.TextArea(label="Corps de l'email", lines=15)
25
 
26
  with gr.Row():
27
+ sender_email = gr.Text(label="Adresse d'envoi (Gmail)")
28
+ refresh_token = gr.Text(label="Refresh Token Gmail", type="password")
29
+ send_btn = gr.Button("📤 Envoyer le mail")
30
+ status = gr.Textbox(label="Statut")
31
 
32
+ generate_btn.click(on_generate, inputs=[to_email, context, tone], outputs=[subject_output, body_output])
33
+ send_btn.click(on_send, inputs=[sender_email, to_email, subject_output, body_output, refresh_token], outputs=status)
34
 
35
+ app.launch()
 
 
 
 
 
email_sender.py CHANGED
@@ -1,31 +1,37 @@
1
- import os
2
  import base64
 
3
  from email.mime.text import MIMEText
 
4
  from google.oauth2.credentials import Credentials
5
  from googleapiclient.discovery import build
6
 
7
- # Ces variables doivent être fournies via les secrets HF
8
- GMAIL_CLIENT_ID = os.getenv("GMAIL_CLIENT_ID")
9
- GMAIL_CLIENT_SECRET = os.getenv("GMAIL_CLIENT_SECRET")
 
 
 
 
 
 
 
 
 
 
10
 
11
- def send_email(from_email, to_email, subject, body, refresh_token):
12
- if not (GMAIL_CLIENT_ID and GMAIL_CLIENT_SECRET and refresh_token):
13
- return False, "❌ Paramètres Gmail manquants (client ID, secret ou refresh token)"
14
 
15
- creds = Credentials(
16
- token=None,
17
- refresh_token=refresh_token,
18
- token_uri="https://oauth2.googleapis.com/token",
19
- client_id=GMAIL_CLIENT_ID,
20
- client_secret=GMAIL_CLIENT_SECRET,
21
- scopes=["https://www.googleapis.com/auth/gmail.send"]
22
- )
23
 
 
24
  try:
25
- service = build("gmail", "v1", credentials=creds)
26
  message = MIMEText(body)
27
  message["to"] = to_email
28
- message["from"] = from_email
29
  message["subject"] = subject
30
 
31
  raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
@@ -34,4 +40,4 @@ def send_email(from_email, to_email, subject, body, refresh_token):
34
  sent = service.users().messages().send(userId="me", body=send_body).execute()
35
  return True, f"✅ Email envoyé à {to_email} (ID: {sent['id']})"
36
  except Exception as e:
37
- return False, f"❌ Erreur lors de l'envoi : {e}"
 
 
1
  import base64
2
+ import os
3
  from email.mime.text import MIMEText
4
+ from google.auth.transport.requests import Request
5
  from google.oauth2.credentials import Credentials
6
  from googleapiclient.discovery import build
7
 
8
+ # Client ID / secret à stocker dans les secrets HF (cf. variables d’environnement du Space)
9
+ CLIENT_ID = os.getenv("GMAIL_CLIENT_ID")
10
+ CLIENT_SECRET = os.getenv("GMAIL_CLIENT_SECRET")
11
+
12
+ def authenticate_gmail(sender_email, refresh_token):
13
+ creds_data = {
14
+ "token": "",
15
+ "refresh_token": refresh_token,
16
+ "token_uri": "https://oauth2.googleapis.com/token",
17
+ "client_id": CLIENT_ID,
18
+ "client_secret": CLIENT_SECRET,
19
+ "scopes": ["https://www.googleapis.com/auth/gmail.send"]
20
+ }
21
 
22
+ creds = Credentials.from_authorized_user_info(info=creds_data)
23
+ if not creds.valid and creds.expired and creds.refresh_token:
24
+ creds.refresh(Request())
25
 
26
+ service = build("gmail", "v1", credentials=creds)
27
+ return service
 
 
 
 
 
 
28
 
29
+ def send_email(sender_email, to_email, subject, body, refresh_token):
30
  try:
31
+ service = authenticate_gmail(sender_email, refresh_token)
32
  message = MIMEText(body)
33
  message["to"] = to_email
34
+ message["from"] = sender_email
35
  message["subject"] = subject
36
 
37
  raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode()
 
40
  sent = service.users().messages().send(userId="me", body=send_body).execute()
41
  return True, f"✅ Email envoyé à {to_email} (ID: {sent['id']})"
42
  except Exception as e:
43
+ return False, f"❌ Erreur d'envoi : {e}"