✨ Creative Writing Assistant
Transform your ideas into captivating stories with AI-powered creativity
import os import gradio as gr import requests import json from datetime import datetime # Load secrets PAYWALLS_API_KEY = os.environ.get("PAYWALLS_API_KEY") PAYWALLS_API_URL = os.environ.get("PAYWALLS_API_URL", "https://api.paywalls.ai/v1") # Free tier limits FREE_MAX_TOKENS = 150 PREMIUM_MAX_TOKENS = 2048 # Style presets (premium feature) STYLE_PRESETS = { "neutral": "You are a creative writing assistant.", "poetic": "You are a poetic writing assistant. Write in lyrical, expressive language with vivid imagery.", "dramatic": "You are a dramatic writing assistant. Create tension, conflict, and emotional depth.", "comedic": "You are a comedic writing assistant. Use humor, wit, and light-hearted tone.", "horror": "You are a horror writing assistant. Build suspense and create eerie, unsettling atmospheres." } def check_paywall(user_id: str): """Check user payment status and generate wallet topup link""" headers = { "Authorization": f"Bearer {PAYWALLS_API_KEY}", "Content-Type": "application/json" } # Check if user has active balance/subscription try: check_response = requests.get( f"{PAYWALLS_API_URL}/payments/check", headers=headers, params={"user_id": user_id}, timeout=10 ) is_paid = check_response.status_code == 200 and check_response.json().get("paid", False) except: is_paid = False # Direct users to AI Wallet topup page paywall_url = f"https://wallet.paywalls.ai/topup?user={user_id}" return is_paid, paywall_url def free_tier_generation(system_message, history, user_message, max_tokens, temperature): try: from huggingface_hub import InferenceClient client = InferenceClient() messages = [{"role": "system", "content": system_message}] + history + [{"role": "user", "content": user_message}] reply = client.chat_completion( messages=messages, max_tokens=max_tokens, temperature=temperature, model="meta-llama/Llama-3.2-3B-Instruct" ).choices[0].message.content return reply except Exception as e: print(f"[Free Tier] Error: {e}") return f"⚠️ Free tier service error: {str(e)}" def premium_generation(user_id, system_message, history, user_message, max_tokens, temperature, top_p): """Premium tier using Paywalls proxy""" headers = { "Authorization": f"Bearer {PAYWALLS_API_KEY}", "Content-Type": "application/json" } messages = [{"role": "system", "content": system_message}] + history + [{"role": "user", "content": user_message}] payload = { "model": "gpt-3.5-turbo", "messages": messages, "max_tokens": max_tokens, "temperature": temperature, "top_p": top_p, "user": user_id } try: response = requests.post( f"{PAYWALLS_API_URL}/chat/completions", headers=headers, json=payload, timeout=60 ) response.raise_for_status() data = response.json() if data.get("choices"): return data["choices"][0]["message"]["content"] return "No response from premium model." except requests.exceptions.HTTPError as e: print(f"[Premium] HTTP Error: {e.response.status_code} - {e.response.text}") return f"⚠️ Premium service error: {e.response.status_code}" except Exception as e: print(f"[Premium] Error: {e}") return f"⚠️ Premium service error: {str(e)}" def respond(message, history, style, max_tokens, temperature, top_p): user_id = "demo_user" is_premium, paywall_url = check_paywall(user_id) # Check style restriction for free users if not is_premium: max_tokens = min(max_tokens, FREE_MAX_TOKENS) if style != "neutral": return history + [{"role": "assistant", "content": f"🔒 **Premium Feature Locked**\n\nStyle customization is available for Premium users only.\n\n[✨ Upgrade to Premium]({paywall_url})"}] system_message = STYLE_PRESETS.get(style, STYLE_PRESETS["neutral"]) # Generate response based on tier if is_premium: reply = premium_generation(user_id, system_message, history, message, max_tokens, temperature, top_p) tier_badge = "✨ **PREMIUM**" else: reply = free_tier_generation(system_message, history, message, max_tokens, temperature) tier_badge = f"🆓 **FREE TIER** • 150 tokens limit\n\n💎 [Unlock Premium Features]({paywall_url}) • Longer stories • Custom styles • Export" full_reply = f"{reply}\n\n---\n{tier_badge}" return history + [{"role": "user", "content": message}, {"role": "assistant", "content": full_reply}] def export_conversation(history): user_id = "demo_user" is_premium, paywall_url = check_paywall(user_id) if not is_premium: return None, f"🔒 Export feature requires Premium.\n\n[Upgrade Now]({paywall_url})" content = f"Creative Writing Session - {datetime.now().strftime('%Y-%m-%d %H:%M')}\n\n" for msg in history: role = msg["role"].upper() content += f"{role}: {msg['content']}\n\n" filepath = "/tmp/creative_writing.txt" with open(filepath, "w") as f: f.write(content) return filepath, "✅ Exported successfully!" # Custom CSS for elegant design custom_css = """ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); * { font-family: 'Inter', sans-serif !important; } .gradio-container { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; } .main-header { background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); border-radius: 20px; padding: 30px; margin-bottom: 25px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); text-align: center; } .main-header h1 { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-size: 2.5em; font-weight: 700; margin-bottom: 10px; } .main-header p { color: #64748b; font-size: 1.1em; } .chat-container { background: rgba(255, 255, 255, 0.98); border-radius: 20px; padding: 25px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); } .controls-container { background: rgba(255, 255, 255, 0.98); border-radius: 20px; padding: 25px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); } .premium-badge { background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; padding: 8px 16px; border-radius: 20px; font-weight: 600; font-size: 0.85em; display: inline-block; margin-left: 10px; } .feature-card { background: rgba(102, 126, 234, 0.1); border-radius: 12px; padding: 15px; margin-bottom: 15px; border-left: 4px solid #667eea; } button { border-radius: 12px !important; font-weight: 600 !important; transition: all 0.3s ease !important; } button:hover { transform: translateY(-2px) !important; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15) !important; } .primary-btn { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; } input, textarea, select { border-radius: 10px !important; border: 2px solid #e2e8f0 !important; transition: all 0.3s ease !important; } input:focus, textarea:focus, select:focus { border-color: #667eea !important; box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important; } .slider { accent-color: #667eea !important; } """ # Build UI with gr.Blocks(css=custom_css, title="Creative Writing Assistant", theme=gr.themes.Soft()) as demo: # Header with gr.Row(): with gr.Column(): gr.HTML("""
Transform your ideas into captivating stories with AI-powered creativity
Powered by AI • Built with ❤️ using Gradio & Paywalls.ai