| 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 |
|
|
| |
| |
| |
| 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) |
|
|
| |
| |
| |
| 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 |
| ) |
|
|
| |
| |
| |
| 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 |
| ) |
|
|
| |
| |
| |
| 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 = """ |
| 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; |
| } |
| """ |
|
|
| |
| |
| |
| 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() |