import pandas as pd from datasets import load_dataset from sentence_transformers import SentenceTransformer, util from huggingface_hub import InferenceClient import gradio as gr import os import torch # ========================== # LOAD DATASET # ========================== print("1. Ingesting Data...") try: raw_data = load_dataset("Kaludi/Customer-Support-Responses") df = pd.DataFrame(raw_data["train"]) df = df[["query", "response"]] df.columns = ["customer_query", "historical_resolution"] print("Cloud dataset loaded successfully.") except Exception as e: print(f"Cloud dataset unavailable ({e}). Using backup dataset...") backup_data = [ { "customer_query": "How do I reset my password?", "historical_resolution": "To reset your password, navigate to login and click Forgot Password. A reset email will be sent." }, { "customer_query": "Where is my invoice?", "historical_resolution": "Invoices are available in Billing & Payments under your account dashboard." }, { "customer_query": "How do I cancel subscription?", "historical_resolution": "Navigate to Settings > Subscription > Cancel Plan." }, { "customer_query": "Can I upgrade my account?", "historical_resolution": "Yes, go to Account Settings > Upgrade Plan." }, { "customer_query": "App crashes on startup", "historical_resolution": "Please update the app and clear cache. If issue persists, contact support." } ] df = pd.DataFrame(backup_data) # ========================== # LOAD EMBEDDING MODEL # ========================== print("2. Loading Embedding Model...") embedding_model = SentenceTransformer( "paraphrase-multilingual-MiniLM-L12-v2" ) sample_resolutions = df["historical_resolution"].head(100).tolist() resolution_embeddings = embedding_model.encode( sample_resolutions, convert_to_tensor=True ) # ========================== # CONNECT TO LLM # ========================== print("3. Connecting to Qwen 2.5...") hf_token = os.environ.get("HF_TOKEN") client = InferenceClient( model="Qwen/Qwen2.5-7B-Instruct", token=hf_token ) # ========================== # MAIN FUNCTION # ========================== def resolve_ticket(customer_query): if not customer_query.strip(): return ( "⚠️ Please enter a support ticket.", "", "0%" ) query_embedding = embedding_model.encode( customer_query, convert_to_tensor=True ) hits = util.semantic_search( query_embedding, resolution_embeddings, top_k=1 ) best_match = hits[0][0] best_match_index = best_match["corpus_id"] similarity_score = float(best_match["score"]) confidence = round(similarity_score * 100, 2) retrieved_context = ( df["historical_resolution"] .iloc[best_match_index] ) messages = [ { "role": "system", "content": """ You are a professional multilingual customer support assistant. Rules: - Respond ONLY using the provided internal document - Use professional tone - Reply in the EXACT SAME LANGUAGE as the user's query - Be concise but helpful """ }, { "role": "user", "content": f""" Customer Query: {customer_query} Internal Document: {retrieved_context} """ } ] try: response = client.chat.completions.create( messages=messages, max_tokens=250, temperature=0.3 ) final_response = ( response.choices[0] .message.content.strip() ) return ( final_response, retrieved_context, f"{confidence}%" ) except Exception as e: return ( f"❌ Error: {str(e)}", retrieved_context, f"{confidence}%" ) # ========================== # CUSTOM CSS # ========================== custom_css = """ body { background: linear-gradient( 135deg, #050816, #0f172a ); } .gradio-container { background: linear-gradient( 135deg, #050816, #0f172a ) !important; font-family: 'Segoe UI', sans-serif !important; } .glass-card { background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.15); backdrop-filter: blur(18px); border-radius: 20px; padding: 20px; box-shadow: 0 0 25px rgba(0,255,255,0.18); } h1 { text-align: center; color: #00f5ff; text-shadow: 0px 0px 20px #00f5ff; } textarea { border-radius: 15px !important; border: 1px solid #00f5ff !important; box-shadow: 0px 0px 15px rgba( 0, 245, 255, 0.4 ) !important; } button { background: linear-gradient( 90deg, #7c3aed, #00f5ff ) !important; color: white !important; border: none !important; border-radius: 14px !important; font-size: 18px !important; font-weight: bold !important; height: 55px !important; box-shadow: 0 0 20px rgba( 0, 245, 255, 0.7 ) !important; } button:hover { transform: scale(1.03); transition: 0.2s ease; } footer { visibility: hidden; } """ # ========================== # UI # ========================== with gr.Blocks( theme=gr.themes.Glass(), css=custom_css, title="Multilingual AI Support" ) as demo: gr.Markdown(""" # 🌌 Multilingual AI Support Triage ### ⚡ Enterprise AI Ticket Resolution System 🟢 **Status:** Online 🌍 **Languages:** 100+ 🧠 **AI Model:** Qwen 2.5 7B 🔍 **Pipeline:** Retrieval-Augmented Generation (RAG) --- """) with gr.Row(): with gr.Column(scale=1): gr.Markdown("## 📨 Customer Ticket") input_query = gr.Textbox( label="Enter support query", placeholder= "Try Spanish, Hindi, German...", lines=7 ) submit_btn = gr.Button( "🚀 Resolve Ticket" ) gr.Markdown("### 🌍 Example Queries") gr.Examples( examples=[ ["¿Cómo restablezco mi contraseña?"], ["Mein Konto wurde doppelt belastet"], ["मेरा पासवर्ड रीसेट नहीं हो रहा"], ["Comment annuler mon abonnement ?"] ], inputs=input_query ) with gr.Column(scale=1): gr.Markdown("## 🤖 AI Resolution") output_reply = gr.Textbox( label="Generated Response", lines=8 ) retrieved_doc = gr.Textbox( label= "Retrieved Internal Document", lines=5 ) confidence_box = gr.Textbox( label="🎯 Match Confidence" ) submit_btn.click( fn=resolve_ticket, inputs=input_query, outputs=[ output_reply, retrieved_doc, confidence_box ], show_progress=True ) demo.launch()