import gradio as gr import pandas as pd import faiss import torch from transformers import AutoTokenizer, AutoModelForCausalLM from sentence_transformers import SentenceTransformer import time # ------------------------------- # Load dataset # ------------------------------- file_path = "marketing-campaigns.csv" # file uploaded in Hugging Face space df = pd.read_csv(file_path) df = df.dropna() # drop completely empty rows df["text"] = df.astype(str).agg(" | ".join, axis=1) # merge all cols into text # ------------------------------- # Embeddings + FAISS # ------------------------------- embed_model = SentenceTransformer("all-MiniLM-L6-v2") embeddings = embed_model.encode(df["text"].tolist(), convert_to_tensor=True, show_progress_bar=True) embeddings_np = embeddings.detach().cpu().numpy() d = embeddings_np.shape[1] index = faiss.IndexFlatL2(d) index.add(embeddings_np) # ------------------------------- # Load LLM (default Phi-4-mini) # ------------------------------- model_choices = { "openai/gpt-oss-120b": "microsoft/phi-2", "openai/gpt-oss-20b": "microsoft/phi-2" # placeholder, can map to another HF model } current_model_id = "openai/gpt-oss-120b" hf_model = model_choices[current_model_id] tokenizer = AutoTokenizer.from_pretrained(hf_model) model = AutoModelForCausalLM.from_pretrained( hf_model, torch_dtype=torch.float32, device_map="auto" ) # ------------------------------- # RAG Functions # ------------------------------- def retrieve_context(query, k=3): query_vec = embed_model.encode([query], convert_to_tensor=True).cpu().numpy() D, I = index.search(query_vec, k) results = [df.iloc[i]["text"] for i in I[0]] return results def generate_with_rag(prompt, temperature=0.8, max_tokens=250): # Step 1: Retrieve context context = retrieve_context(prompt, k=3) context_str = "\n".join(context) # Step 2: Construct grounded prompt rag_prompt = f""" You are a creative AI campaign assistant. Use the following supporting data to ground your answer: {context_str} Task: Generate a unique and creative marketing campaign idea for: {prompt} """ # Step 3: Generate inputs = tokenizer(rag_prompt, return_tensors="pt").to(model.device) outputs = model.generate( **inputs, max_length=max_tokens, temperature=temperature, top_p=0.9 ) return tokenizer.decode(outputs[0], skip_special_tokens=True) def switch_model(model_choice): """Switch between available models.""" global model, tokenizer, current_model_id hf_model = model_choices.get(model_choice, "microsoft/phi-4-mini") tokenizer = AutoTokenizer.from_pretrained(hf_model) model = AutoModelForCausalLM.from_pretrained( hf_model, torch_dtype=torch.float32, device_map="auto" ) current_model_id = model_choice return gr.update(visible=(model_choice=="openai/gpt-oss-120b")), gr.update(visible=(model_choice=="openai/gpt-oss-20b")), model_choice # ------------------------------- # Custom CSS with enterprise styling # ------------------------------- custom_css = """ :root { --primary: #2563eb; --primary-dark: #1d4ed8; --secondary: #64748b; --dark: #1e293b; --light: #f8fafc; --success: #10b981; --warning: #f59e0b; --danger: #ef4444; --gray-100: #f1f5f9; --gray-200: #e2e8f0; --gray-300: #cbd5e1; --gray-700: #334155; --radius: 12px; --shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); } .gradio-container { font-family: 'Inter', 'Segoe UI', system-ui, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; padding: 20px; } .main-container { background-color: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); border-radius: var(--radius); padding: 24px; box-shadow: var(--shadow); border: 1px solid rgba(255, 255, 255, 0.18); margin-bottom: 20px; } .dark .main-container { background-color: rgba(30, 41, 59, 0.95); color: var(--light); } .header { display: flex; justify-content: space-between; align-items: center; padding: 16px 0; margin-bottom: 24px; border-bottom: 1px solid var(--gray-200); } .dark .header { border-bottom: 1px solid var(--gray-700); } .logo { display: flex; align-items: center; gap: 12px; font-weight: 700; font-size: 24px; color: var(--dark); } .dark .logo { color: var(--light); } .logo-icon { background: var(--primary); color: white; width: 40px; height: 40px; border-radius: 8px; display: flex; align-items: center; justify-content: center; } .nav-links { display: flex; gap: 24px; } .nav-link { color: var(--secondary); text-decoration: none; font-weight: 500; transition: color 0.2s; } .nav-link:hover, .nav-link.active { color: var(--primary); } .dark .nav-link { color: var(--gray-300); } .dark .nav-link:hover, .dark .nav-link.active { color: var(--primary); } .badge-container { margin-bottom: 24px; } h1, h2, h3, h4 { color: var(--dark); font-weight: 700; } .dark h1, .dark h2, .dark h3, .dark h4 { color: var(--light); } .label { font-weight: 600; color: var(--dark); margin-bottom: 8px; } .dark .label { color: var(--light); } input, textarea { border-radius: var(--radius) !important; padding: 12px 16px !important; border: 1px solid var(--gray-300) !important; background: white !important; } .dark input, .dark textarea { border: 1px solid var(--gray-700) !important; background: var(--dark) !important; color: var(--light) !important; } button { border-radius: var(--radius) !important; padding: 12px 24px !important; font-weight: 600 !important; transition: all 0.2s !important; border: none !important; } button.primary { background: var(--primary) !important; color: white !important; } button.primary:hover { background: var(--primary-dark) !important; transform: translateY(-2px); } .dropdown { border-radius: var(--radius) !important; } .accordion { border-radius: var(--radius) !important; border: 1px solid var(--gray-200) !important; } .dark .accordion { border: 1px solid var(--gray-700) !important; } .footer { text-align: center; padding: 24px 0; margin-top: 40px; color: var(--secondary); font-size: 14px; } .dark .footer { color: var(--gray-300); } .stats { display: flex; gap: 24px; margin: 20px 0; } .stat-card { background: white; padding: 16px; border-radius: var(--radius); box-shadow: var(--shadow); flex: 1; text-align: center; } .dark .stat-card { background: var(--dark); } .stat-value { font-size: 24px; font-weight: 700; color: var(--primary); } .stat-label { font-size: 14px; color: var(--secondary); } .processing-bar { height: 4px; width: 100%; background: var(--gray-200); border-radius: 2px; overflow: hidden; margin: 16px 0; } .progress { height: 100%; background: var(--primary); width: 0%; transition: width 0.4s; } @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } } .pulse { animation: pulse 2s infinite; } .model-badge { display: inline-block; padding: 4px 12px; background: var(--gray-100); color: var(--gray-700); border-radius: 20px; font-size: 12px; font-weight: 600; margin-left: 12px; } .dark .model-badge { background: var(--gray-700); color: var(--gray-200); } .tabs { display: flex; gap: 8px; margin-bottom: 20px; } .tab { padding: 8px 16px; background: var(--gray-100); border-radius: var(--radius); cursor: pointer; font-weight: 500; } .tab.active { background: var(--primary); color: white; } .dark .tab { background: var(--gray-700); color: var(--gray-200); } .dark .tab.active { background: var(--primary); color: white; } """ js = """ """ # ------------------------------- # Gradio UI # ------------------------------- with gr.Blocks(fill_height=True, theme=gr.themes.Soft(), css=custom_css) as demo: # Add custom JavaScript gr.HTML(js) # Top badges with gr.Row(elem_classes="badge-container"): gr.HTML("""
""") with gr.Row(): # Sidebar with gr.Column(scale=1): with gr.Group(elem_classes="main-container"): gr.Markdown("## 🚀 Inference Provider") model_dropdown = gr.Dropdown( choices=list(model_choices.keys()), value=current_model_id, label="📊 Select Model" ) reload_btn = gr.Button("🔄 Apply Model Change", variant="primary", elem_classes="primary") with gr.Accordion("⚙️ Advanced Options", open=False): temperature = gr.Slider( minimum=0, maximum=2, value=0.8, step=0.1, label="Temperature" ) max_tokens = gr.Slider( minimum=50, maximum=1024, value=250, step=10, label="Max Tokens" ) gr.Markdown("---") gr.Markdown("### 📈 Recent Activity") gr.HTML("""✅ Campaign for Tech Startup - 2 hours ago
✅ Holiday Promotion - 5 hours ago
✅ Product Launch - Yesterday