From 018add739a402b77ca1b0f5045bee2900ee947b7 Mon Sep 17 00:00:00 2001 From: jerem Date: Sat, 13 Jun 2026 23:33:30 +0200 Subject: [PATCH] =?UTF-8?q?Infos=20du=20groupe=20dans=20les=20r=C3=A9glage?= =?UTF-8?q?s,=20inject=C3=A9es=20au=20prompt=20IA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nouveaux champs (nom, style, description, lien) en réglages, transmis au prompt système de génération de messages dans les deux modes (générer et peaufiner). La consigne de format reste en dernière position, non éditable. Bloc omis si aucun champ rempli : prompt identique à l'ancien. --- app.py | 13 ++++- ia.py | 49 +++++++++++++++--- static/index.html | 124 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 171 insertions(+), 15 deletions(-) diff --git a/app.py b/app.py index 3c515c8..726b3bb 100644 --- a/app.py +++ b/app.py @@ -46,6 +46,10 @@ CONFIG_DEFAUT = { "Bien cordialement," ), "ia_modele": ia.MODELE_DEFAUT, + "groupe_nom": "", + "groupe_style": "", + "groupe_description": "", + "groupe_lien": "", } app = Flask(__name__, static_folder="static") @@ -368,7 +372,8 @@ def api_config_lire(): def api_config_ecrire(): donnees = request.get_json(silent=True) or {} config = lire_config() - for cle in ("adresse_depart", "modele_message", "ia_modele"): + for cle in ("adresse_depart", "modele_message", "ia_modele", + "groupe_nom", "groupe_style", "groupe_description", "groupe_lien"): if cle in donnees: config[cle] = str(donnees[cle]) for cle in ("conso_l_100km", "prix_carburant", "cout_peage_km"): @@ -411,6 +416,12 @@ def api_message(): message = ia.generer_message( prospect, config.get("modele_message", ""), mode, nom_modele=config.get("ia_modele") or ia.MODELE_DEFAUT, + groupe={ + "nom": config.get("groupe_nom", ""), + "style": config.get("groupe_style", ""), + "description": config.get("groupe_description", ""), + "lien": config.get("groupe_lien", ""), + }, ) return jsonify({"message": message}) except ia.IANonConnecte as e: diff --git a/ia.py b/ia.py index 4259355..14df0f4 100644 --- a/ia.py +++ b/ia.py @@ -127,6 +127,25 @@ def _infos_prospect(prospect): return "\n".join(f"- {cle} : {val}" for cle, val in champs if (val or "").strip()) +def _infos_groupe(groupe): + """Bloc décrivant le groupe (depuis les réglages), injecté dans le prompt système. + + Ne liste que les champs renseignés ; renvoie "" si rien n'est fourni. + """ + if not groupe: + return "" + champs = [ + ("Nom du groupe", groupe.get("nom")), + ("Style", groupe.get("style")), + ("Description", groupe.get("description")), + ("Lien", groupe.get("lien")), + ] + lignes = [f"- {cle} : {(val or '').strip()}" for cle, val in champs if (val or "").strip()] + if not lignes: + return "" + return "Tu représentes le groupe suivant :\n" + "\n".join(lignes) + + def _message_erreur(exc): bas = str(exc).lower() if "rate" in bas or "429" in bas or "limit" in bas or "quota" in bas: @@ -136,12 +155,15 @@ def _message_erreur(exc): return f"Échec de la génération : {exc}" -def generer_message(prospect, modele, mode="generer", nom_modele=None): +def generer_message(prospect, modele, mode="generer", nom_modele=None, groupe=None): """Génère un message de prise de contact pour un prospect. mode == "generer" : l'IA rédige un message sur mesure (modèle = guide de ton/style). mode == "peaufiner" : on substitue d'abord le modèle, puis l'IA le reformule sans en changer le sens. + + `groupe` : dict optionnel (nom, style, description, lien) issu des réglages ; ses champs + renseignés sont injectés dans le prompt système pour personnaliser la rédaction. """ nom_modele = nom_modele or MODELE_DEFAUT if not est_connecte(): @@ -150,25 +172,36 @@ def generer_message(prospect, modele, mode="generer", nom_modele=None): ) infos = _infos_prospect(prospect) or "- (aucune information détaillée disponible)" + bloc_groupe = _infos_groupe(groupe) if mode == "peaufiner": brouillon = _message_modele(prospect, modele) - systeme = ( + parties = [ "Tu rédiges des messages de prise de contact en français pour proposer " - "l'organisation de concerts à des établissements. On te donne un brouillon : " - "reformule-le pour le rendre plus naturel, chaleureux et engageant, sans inventer " - "d'information ni changer le sens. Réponds UNIQUEMENT par le message final, sans " - "commentaire." + "l'organisation de concerts à des établissements." + ] + if bloc_groupe: + parties.append(bloc_groupe) + parties.append( + "On te donne un brouillon : reformule-le pour le rendre plus naturel, chaleureux " + "et engageant, sans inventer d'information ni changer le sens. Réponds UNIQUEMENT " + "par le message final, sans commentaire." ) + systeme = "\n\n".join(parties) utilisateur = f"Brouillon à améliorer :\n{brouillon}\n\nInfos sur l'établissement :\n{infos}" else: - systeme = ( + parties = [ "Tu rédiges des messages de prise de contact en français pour proposer " - "l'organisation de concerts à des établissements (bars, restaurants, salles...). " + "l'organisation de concerts à des établissements (bars, restaurants, salles...)." + ] + if bloc_groupe: + parties.append(bloc_groupe) + parties.append( "Le message doit être court, personnalisé, chaleureux et se terminer par une " "question ouvrant l'échange. Réponds UNIQUEMENT par le message final, sans " "commentaire ni objet d'e-mail." ) + systeme = "\n\n".join(parties) utilisateur = ( f"Rédige un message de prise de contact pour cet établissement :\n{infos}\n\n" f"Inspire-toi de ce modèle pour le ton et le style :\n{modele}" diff --git a/static/index.html b/static/index.html index 8a6eca8..873c0ad 100644 --- a/static/index.html +++ b/static/index.html @@ -136,6 +136,23 @@ .spinner.sombre { border-color: var(--accent); border-top-color: transparent; } @keyframes tourne { to { transform: rotate(360deg); } } + /* ===== Disposition « modale » : liste en grand + détail en fenêtre centrale ===== */ + body[data-disposition="modale"] .deux-colonnes { grid-template-columns: 1fr; } + body[data-disposition="modale"] .colonne-detail { display: none; } + body[data-disposition="modale"] #liste { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--e3); } + body[data-disposition="modale"] .item { margin-bottom: 0; padding: var(--e3) var(--e4); } + body.modale-ouverte { overflow: hidden; } + + .modale-fond { position: fixed; inset: 0; z-index: 50; background: rgba(29,27,46,.45); display: flex; align-items: flex-start; justify-content: center; padding: var(--e8) var(--e4); overflow-y: auto; } + .modale-fond[hidden] { display: none; } + .modale { position: relative; width: 100%; max-width: 720px; background: var(--fond); border: 1px solid var(--bordure); border-radius: var(--r-m); box-shadow: 0 12px 48px rgba(29,27,46,.3); padding: var(--e6); } + .modale-fermer { position: absolute; top: var(--e3); right: var(--e3); width: 32px; height: 32px; padding: 0; font-size: 16px; line-height: 1; background: var(--accent-doux); color: var(--accent); } + .modale-fermer:hover { background: #e3e0f6; } + @media (max-width: 640px) { + .modale { padding: var(--e4); } + .modale-fond { padding: var(--e4) var(--e2); } + } + @media (max-width: 860px) { .deux-colonnes { grid-template-columns: 1fr; } .colonne-detail { position: static; max-height: none; } @@ -228,6 +245,18 @@