import gradio as gr import os import json import time from collections import defaultdict from datetime import datetime # ============================================================ # đ ContentGenius AI â Suite de CrĂ©ation de Contenu IA # ============================================================ # MonĂ©tisation : Freemium (5 gratuits/jour) + Pro (15âŹ/mois) # Stack : Gradio 6 + HF Inference API (gratuit !) # Pas besoin d'OpenAI â on utilise les modĂšles HF gratuits # ============================================================ from huggingface_hub import InferenceClient # Client HF Inference (gratuit avec token HF) client = InferenceClient(token=os.getenv("HF_TOKEN")) # --- Rate Limiting (Freemium Gate) --- usage_tracker = defaultdict(list) FREE_DAILY_LIMIT = 5 def check_rate_limit(request: gr.Request = None): """VĂ©rifie si l'utilisateur a dĂ©passĂ© sa limite gratuite""" user_id = "anonymous" if request: user_id = request.username or request.client.host or "anonymous" now = time.time() day_start = now - 86400 # 24h usage_tracker[user_id] = [t for t in usage_tracker[user_id] if t > day_start] if len(usage_tracker[user_id]) >= FREE_DAILY_LIMIT: return False, len(usage_tracker[user_id]) usage_tracker[user_id].append(now) return True, len(usage_tracker[user_id]) def call_llm(system_prompt: str, user_prompt: str, max_tokens: int = 2000) -> str: """Appelle le modĂšle LLM via HF Inference API""" try: response = client.chat_completion( model="Qwen/Qwen2.5-72B-Instruct", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ], max_tokens=max_tokens, temperature=0.7, ) return response.choices[0].message.content except Exception as e: return f"â Erreur : {str(e)}\n\nAstuce : Ajoutez votre HF_TOKEN dans les secrets du Space pour dĂ©bloquer l'API." # ============================================================ # đ OUTIL 1 : GĂ©nĂ©rateur d'Articles de Blog SEO # ============================================================ def generate_blog(topic, keywords, tone, length, language, request: gr.Request = None): allowed, count = check_rate_limit(request) if not allowed: return f"â ïž **Limite gratuite atteinte ({FREE_DAILY_LIMIT}/jour)**\n\nđ Passez Ă **ContentGenius Pro** pour un accĂšs illimitĂ© !\n\nđł [Upgrader maintenant â](https://buy.stripe.com/test)" length_map = {"Court (~500 mots)": 500, "Moyen (~1000 mots)": 1000, "Long (~2000 mots)": 2000} word_count = length_map.get(length, 1000) system = f"""Tu es un expert en rĂ©daction SEO et marketing de contenu. Tu rĂ©diges en {language}. Ton style est {tone.lower()}. Tu dois produire du contenu optimisĂ© pour les moteurs de recherche.""" prompt = f"""RĂ©dige un article de blog complet d'environ {word_count} mots sur le sujet suivant : **Sujet :** {topic} **Mots-clĂ©s SEO Ă intĂ©grer naturellement :** {keywords} **Ton :** {tone} Structure obligatoire : 1. **Titre H1** accrocheur avec le mot-clĂ© principal 2. **Meta description** (155 caractĂšres max) 3. **Introduction** captivante avec un hook 4. **3-5 sections H2** avec sous-sections H3 si nĂ©cessaire 5. **Conclusion** avec un call-to-action 6. **3 suggestions de titres alternatifs** pour A/B testing IntĂšgre les mots-clĂ©s naturellement. Utilise des listes Ă puces, des statistiques et des exemples concrets. Optimise pour la lisibilitĂ© (phrases courtes, paragraphes aĂ©rĂ©s).""" result = call_llm(system, prompt, max_tokens=3000) remaining = FREE_DAILY_LIMIT - count return f"{result}\n\n---\n*âš GĂ©nĂ©rĂ© par ContentGenius AI | {remaining} gĂ©nĂ©ration(s) gratuite(s) restante(s) aujourd'hui*" # ============================================================ # đŒ OUTIL 2 : GĂ©nĂ©rateur de Posts LinkedIn # ============================================================ def generate_linkedin(topic, context, style, include_emoji, include_hashtags, request: gr.Request = None): allowed, count = check_rate_limit(request) if not allowed: return f"â ïž **Limite gratuite atteinte ({FREE_DAILY_LIMIT}/jour)**\n\nđ Passez Ă **ContentGenius Pro** !" system = """Tu es un expert en personal branding LinkedIn. Tu crĂ©es des posts viraux qui gĂ©nĂšrent de l'engagement (likes, commentaires, partages). Tu connais parfaitement l'algorithme LinkedIn.""" emoji_instruction = "Utilise des emojis stratĂ©giquement pour aĂ©rer le texte." if include_emoji else "N'utilise PAS d'emojis." hashtag_instruction = "Ajoute 3-5 hashtags pertinents Ă la fin." if include_hashtags else "Pas de hashtags." prompt = f"""CrĂ©e un post LinkedIn viral sur le sujet suivant : **Sujet :** {topic} **Contexte/ExpĂ©rience personnelle :** {context} **Style :** {style} RĂšgles : - PremiĂšre ligne = HOOK puissant (question provocante, stat choquante, ou affirmation contraire) - Utilise le format "1 ligne = 1 idĂ©e" (sauts de ligne frĂ©quents) - Maximum 1300 caractĂšres (optimal pour LinkedIn) - Termine par une question ouverte pour gĂ©nĂ©rer des commentaires - {emoji_instruction} - {hashtag_instruction} GĂ©nĂšre 3 versions diffĂ©rentes du post (Version A, B, C) pour A/B testing.""" result = call_llm(system, prompt, max_tokens=2000) remaining = FREE_DAILY_LIMIT - count return f"{result}\n\n---\n*âš {remaining} gĂ©nĂ©ration(s) gratuite(s) restante(s)*" # ============================================================ # đ§ OUTIL 3 : GĂ©nĂ©rateur d'Emails Marketing # ============================================================ def generate_email(objective, product, audience, tone, email_type, request: gr.Request = None): allowed, count = check_rate_limit(request) if not allowed: return f"â ïž **Limite gratuite atteinte ({FREE_DAILY_LIMIT}/jour)**\n\nđ Passez Ă **ContentGenius Pro** !" system = """Tu es un expert en email marketing avec 15 ans d'expĂ©rience. Tu connais les techniques de copywriting (AIDA, PAS, Before-After-Bridge). Ton objectif : maximiser les taux d'ouverture et de clic.""" prompt = f"""CrĂ©e un email marketing complet : **Type :** {email_type} **Objectif :** {objective} **Produit/Service :** {product} **Audience cible :** {audience} **Ton :** {tone} Fournis : 1. **5 objets d'email** (subject lines) optimisĂ©s pour le taux d'ouverture - Utilise la curiositĂ©, l'urgence ou la personnalisation 2. **Texte de preview** (40 caractĂšres) 3. **Corps de l'email complet** avec : - Hook d'ouverture personnalisĂ© - ProblĂšme â Solution â BĂ©nĂ©fice - Preuve sociale (template Ă remplir) - CTA principal clair et urgent - P.S. avec offre bonus 4. **Version courte** (mobile-optimisĂ©e, <100 mots)""" result = call_llm(system, prompt, max_tokens=2500) remaining = FREE_DAILY_LIMIT - count return f"{result}\n\n---\n*âš {remaining} gĂ©nĂ©ration(s) gratuite(s) restante(s)*" # ============================================================ # đŻ OUTIL 4 : GĂ©nĂ©rateur de PublicitĂ©s (Google/Meta Ads) # ============================================================ def generate_ads(product, target_audience, platform, budget_range, usp, request: gr.Request = None): allowed, count = check_rate_limit(request) if not allowed: return f"â ïž **Limite gratuite atteinte ({FREE_DAILY_LIMIT}/jour)**\n\nđ Passez Ă **ContentGenius Pro** !" system = """Tu es un expert en publicitĂ© digitale (Google Ads, Meta Ads, TikTok Ads). Tu crĂ©es des publicitĂ©s Ă fort ROI avec des techniques de copywriting avancĂ©es. Tu respectes les limites de caractĂšres de chaque plateforme.""" prompt = f"""CrĂ©e des publicitĂ©s pour la plateforme {platform} : **Produit/Service :** {product} **Audience cible :** {target_audience} **USP (argument unique) :** {usp} **Budget indicatif :** {budget_range} GĂ©nĂšre : **Pour Google Ads :** - 5 titres (max 30 caractĂšres chacun) - 3 descriptions (max 90 caractĂšres chacune) - 10 mots-clĂ©s suggĂ©rĂ©s (avec type de correspondance) - Extensions d'annonce recommandĂ©es **Pour Meta/Instagram Ads :** - 3 copies publicitaires (version courte, moyenne, longue) - Suggestions de visuels/crĂ©atifs - Audiences suggĂ©rĂ©es (intĂ©rĂȘts, comportements) - Hook pour les 3 premiĂšres secondes (vidĂ©o) **Pour les deux :** - Estimation du CPC/CPM par audience - Suggestions de landing page - A/B tests recommandĂ©s""" result = call_llm(system, prompt, max_tokens=2500) remaining = FREE_DAILY_LIMIT - count return f"{result}\n\n---\n*âš {remaining} gĂ©nĂ©ration(s) gratuite(s) restante(s)*" # ============================================================ # đ± OUTIL 5 : GĂ©nĂ©rateur de Contenu RĂ©seaux Sociaux # ============================================================ def generate_social(topic, platforms, brand_voice, content_goal, request: gr.Request = None): allowed, count = check_rate_limit(request) if not allowed: return f"â ïž **Limite gratuite atteinte ({FREE_DAILY_LIMIT}/jour)**\n\nđ Passez Ă **ContentGenius Pro** !" platforms_str = ", ".join(platforms) if isinstance(platforms, list) else platforms system = """Tu es un community manager expert multi-plateformes. Tu connais les algorithmes et best practices de chaque rĂ©seau social. Tu crĂ©es du contenu adaptĂ© Ă chaque plateforme.""" prompt = f"""CrĂ©e du contenu pour les rĂ©seaux sociaux suivants : {platforms_str} **Sujet :** {topic} **Voix de marque :** {brand_voice} **Objectif :** {content_goal} Pour CHAQUE plateforme, fournis : 1. **Texte du post** (adaptĂ© au format et Ă la longueur optimale) 2. **Meilleur moment de publication** (jour + heure) 3. **Hashtags recommandĂ©s** (nombre optimal par plateforme) 4. **Type de visuel suggĂ©rĂ©** (photo, carrousel, vidĂ©o, infographie) 5. **CTA adaptĂ©** Ă la plateforme 6. **IdĂ©e de story/reel** associĂ©e Adapte le ton et le format Ă chaque plateforme : - Instagram : visuel, Ă©motionnel, storytelling - Twitter/X : concis, provocant, thread si nĂ©cessaire - TikTok : trend-based, hook 1 seconde, casual - Facebook : communautaire, engageant, plus long""" result = call_llm(system, prompt, max_tokens=2500) remaining = FREE_DAILY_LIMIT - count return f"{result}\n\n---\n*âš {remaining} gĂ©nĂ©ration(s) gratuite(s) restante(s)*" # ============================================================ # đ·ïž OUTIL 6 : GĂ©nĂ©rateur de Fiches Produit E-commerce # ============================================================ def generate_product_desc(product_name, features, target_customer, platform, tone, request: gr.Request = None): allowed, count = check_rate_limit(request) if not allowed: return f"â ïž **Limite gratuite atteinte ({FREE_DAILY_LIMIT}/jour)**\n\nđ Passez Ă **ContentGenius Pro** !" system = """Tu es un expert en e-commerce et copywriting produit. Tu crĂ©es des fiches produit qui convertissent, optimisĂ©es SEO. Tu connais les best practices Amazon, Shopify, Etsy et WooCommerce.""" prompt = f"""CrĂ©e une fiche produit complĂšte et vendeuse : **Produit :** {product_name} **CaractĂ©ristiques :** {features} **Client cible :** {target_customer} **Plateforme :** {platform} **Ton :** {tone} Fournis : 1. **Titre produit optimisĂ© SEO** (avec mots-clĂ©s) 2. **Bullet points** (5 bĂ©nĂ©fices clĂ©s, format Amazon) 3. **Description longue** (200-300 mots, storytelling + bĂ©nĂ©fices) 4. **Description courte** (50 mots, pour les rĂ©sultats de recherche) 5. **Tags/Mots-clĂ©s** (10 termes SEO) 6. **FAQ produit** (5 questions frĂ©quentes avec rĂ©ponses) 7. **Suggestions de cross-sell** (3 produits complĂ©mentaires) 8. **Script de vidĂ©o produit** (30 secondes)""" result = call_llm(system, prompt, max_tokens=2500) remaining = FREE_DAILY_LIMIT - count return f"{result}\n\n---\n*âš {remaining} gĂ©nĂ©ration(s) gratuite(s) restante(s)*" # ============================================================ # âïž OUTIL 7 : Réécrivain & AmĂ©liorateur de Texte # ============================================================ def rewrite_text(original_text, goal, tone, instructions, request: gr.Request = None): allowed, count = check_rate_limit(request) if not allowed: return f"â ïž **Limite gratuite atteinte ({FREE_DAILY_LIMIT}/jour)**\n\nđ Passez Ă **ContentGenius Pro** !" system = """Tu es un rĂ©dacteur et Ă©diteur professionnel. Tu amĂ©liores les textes en prĂ©servant le message original. Tu es expert en clartĂ©, impact et optimisation SEO.""" prompt = f"""Réécris et amĂ©liore ce texte : **Texte original :** {original_text} **Objectif de la réécriture :** {goal} **Ton souhaitĂ© :** {tone} **Instructions supplĂ©mentaires :** {instructions} Fournis : 1. **Version amĂ©liorĂ©e** du texte 2. **Liste des changements** effectuĂ©s (et pourquoi) 3. **Score de lisibilitĂ©** avant/aprĂšs (estimation Flesch) 4. **Variante plus courte** (-30% de mots, mĂȘme impact) 5. **Variante plus percutante** (copywriting, plus de punch)""" result = call_llm(system, prompt, max_tokens=2500) remaining = FREE_DAILY_LIMIT - count return f"{result}\n\n---\n*âš {remaining} gĂ©nĂ©ration(s) gratuite(s) restante(s)*" # ============================================================ # đš INTERFACE GRADIO â Design Professionnel # ============================================================ CUSTOM_CSS = """ /* Hero Header */ .hero-section { background: linear-gradient(135deg, #6366f1 0%, #a855f7 50%, #ec4899 100%); padding: 2rem 2.5rem; border-radius: 16px; color: white; text-align: center; margin-bottom: 1.5rem; box-shadow: 0 10px 40px rgba(99, 102, 241, 0.3); } .hero-section h1 { font-size: 2.2rem; font-weight: 800; margin: 0; letter-spacing: -0.5px; } .hero-section p { font-size: 1.1rem; opacity: 0.9; margin-top: 0.5rem; } /* Stats Banner */ .stats-banner { display: flex; justify-content: center; gap: 2rem; padding: 1rem; background: rgba(255,255,255,0.1); border-radius: 12px; margin-top: 1rem; } .stat-item { text-align: center; } .stat-number { font-size: 1.5rem; font-weight: 700; } .stat-label { font-size: 0.8rem; opacity: 0.8; } /* Pro Badge */ .pro-badge { background: linear-gradient(135deg, #f59e0b, #ef4444); color: white; padding: 0.3rem 0.8rem; border-radius: 20px; font-size: 0.75rem; font-weight: 700; display: inline-block; margin-left: 0.5rem; } /* Tab styling */ .tab-nav button { font-weight: 600 !important; font-size: 0.95rem !important; } /* CTA Section */ .cta-section { background: linear-gradient(135deg, #1e1b4b, #312e81); padding: 2rem; border-radius: 16px; color: white; text-align: center; margin-top: 1.5rem; } .cta-section h2 { color: white; margin-bottom: 0.5rem; } .cta-section a { background: linear-gradient(135deg, #f59e0b, #ef4444); color: white; padding: 0.8rem 2rem; border-radius: 10px; text-decoration: none; font-weight: 700; display: inline-block; margin-top: 1rem; transition: transform 0.2s; } .cta-section a:hover { transform: scale(1.05); } /* Footer */ .footer-info { text-align: center; padding: 1rem; opacity: 0.6; font-size: 0.85rem; } """ with gr.Blocks(title="ContentGenius AI â CrĂ©ez du Contenu qui Convertit") as demo: # --- HERO HEADER --- gr.HTML("""
Créez du contenu marketing professionnel en 30 secondes grùce à l'IA
Générations illimitées ⹠API Access ⹠Support prioritaire ⹠Tous les outils
15âŹ/mois
soit 0.50âŹ/jour pour un contenu marketing illimitĂ©
⥠Commencer l'essai gratuit de 7 jours