import gradio as gr import pandas as pd import numpy as np import faiss import os import re import random from openai import OpenAI # Initialize OpenAI client securely client = OpenAI(api_key=os.environ["OPENAI_API_KEY"]) # Convert a CRM row into readable text for embeddings def row_to_text(row): return ( f"Clinic: {row.get('Account_Name', 'N/A')}\n" f"Interaction Focus: {row.get('Recent_Interaction_Focus', 'N/A')}\n" f"Interaction Notes: {row.get('Recent_Interaction_Notes', 'N/A')}\n" f"Region: {row.get('Region', 'Unknown')}\n" f"Account Manager: {row.get('Account_Manager', 'Unknown')}\n" f"Revenue: €{row.get('Revenue', 'N/A')}\n" f"Last Purchase: {row.get('Last_Purchase_Date', 'N/A')}\n" f"Churn Risk: {row.get('Churn_Risk', 'N/A')}\n" f"Satisfaction Score: {row.get('Satisfaction_Score', 'N/A')}/10\n" f"Product Interest: {row.get('Product_Interest', 'N/A')}\n" f"Notes: {row.get('Account_Notes', 'N/A')}" ) # Get embedding for a given text def get_embedding(text): response = client.embeddings.create( input=[text], model="text-embedding-3-small" ) return response.data[0].embedding # Core function: generate contextual pitch def contextual_pitch_assistant(csv_file, query, sender_name): df = pd.read_csv(csv_file.name) text_chunks = df.apply(row_to_text, axis=1).tolist() embeddings = [get_embedding(t) for t in text_chunks] dim = len(embeddings[0]) index = faiss.IndexFlatL2(dim) index.add(np.array(embeddings).astype("float32")) q_emb = np.array([get_embedding(query)]).astype("float32") D, I = index.search(q_emb, 3) retrieved = [df.iloc[i] for i in I[0]] # Extract contextual fields row = retrieved[0] account_manager = row.get("Account_Manager", "team") account_name = row.get("Account_Name", "your clinic") focus = str(row.get("Recent_Interaction_Focus", "")).lower() notes_focus = str(row.get("Recent_Interaction_Notes", "")) notes_background = str(row.get("Account_Notes", "")) if not sender_name.strip(): sender_name = "The Sales Team" # Map focus → style instruction if "business" in focus: style_instruction = "Emphasize ROI, efficiency, and competitive advantage." elif "patient" in focus: style_instruction = "Emphasize patient comfort, satisfaction, and outcomes." elif "clinical" in focus: style_instruction = "Emphasize precision, innovation, and clinical quality." else: style_instruction = "Balance clinical, patient, and business value." # Build prompt prompt = f""" You are an expert in B2B sales messaging, inspired by Challenger Sales and Jeb Blount’s prospecting techniques. Your job is to write a short, natural-sounding HTML email pitch to a dental clinic. Rules: - Begin with "Dear {account_manager}," as the greeting. - Anchor immediately in the clinic’s recent concern: "{notes_focus}". - Use background context if relevant: "{notes_background}". - Adapt the pitch style: {style_instruction} - Apply Challenger logic: * Start with the client’s concern in their own terms. * Reframe with an insight (show a broader problem or missed opportunity). * Link features → outcomes → impact (business, patient, or clinical). * Confident but helpful tone. - Keep under 150 words. - End with a strong, specific CTA (e.g. propose a short call or demo, suggest a time). - Close with "Best regards," followed by "{sender_name}". - Return only HTML — no markdown, no code fences. Query: {query} CRM context (for your understanding, do not copy verbatim): {row_to_text(row)} """ response = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": prompt}], temperature=0.7 ) output_text = response.choices[0].message.content # TEMP FIX: use random pre-uploaded header image image_choices = [ "https://huggingface.co/spaces/nmcamacho/RAGdemo/resolve/main/dental_header_1.png", "https://huggingface.co/spaces/nmcamacho/RAGdemo/resolve/main/dental_header_2.png", "https://huggingface.co/spaces/nmcamacho/RAGdemo/resolve/main/dental_header_3.png" ] image_url = random.choice(image_choices) # Clean output text output_text = re.sub(r"(?is)dall[-·]e.*?```", "", output_text) output_text = re.sub(r"###.*?HTML Email Pitch", "", output_text) output_text = re.sub(r"```html|```", "", output_text) output_text = output_text.strip() clinic_note = f"""
⏳ Processing... please wait 30–60 seconds.
", inputs=None, outputs=output, queue=False ) app.launch()