Spaces:
Sleeping
Sleeping
| import os | |
| import gradio as gr | |
| import pandas as pd | |
| import faiss | |
| from sentence_transformers import SentenceTransformer | |
| from huggingface_hub import hf_hub_download, InferenceClient | |
| # ---------- Load data + search index from the dataset repo ---------- | |
| REPO = "adiprog14/lingrow-support-tickets" | |
| idx_path = hf_hub_download(repo_id=REPO, filename="lingrow_faiss.index", repo_type="dataset") | |
| uniq_path = hf_hub_download(repo_id=REPO, filename="lingrow_unique_tickets.parquet", repo_type="dataset") | |
| index = faiss.read_index(idx_path) | |
| unique_df = pd.read_parquet(uniq_path) | |
| embedder = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2") | |
| # ---------- Generation client (RAG) ---------- | |
| GEN_MODEL = "meta-llama/Llama-3.3-70B-Instruct" | |
| CONFIDENCE_THRESHOLD = 0.5 | |
| client = InferenceClient(token=os.environ.get("HF_TOKEN")) | |
| def find_similar(query, k=4): | |
| q = embedder.encode([query], convert_to_numpy=True) | |
| faiss.normalize_L2(q) | |
| scores, idx = index.search(q, k) | |
| out = [] | |
| for s, i in zip(scores[0], idx[0]): | |
| row = unique_df.iloc[i] | |
| out.append((float(s), row["topic_key"], row["customer_message"], row["resolution_steps"])) | |
| return out | |
| def generate_reply(question, results): | |
| context = "\n\n".join( | |
| f"Ticket {i+1} (topic: {t}):\nCustomer: {m}\nVerified solution: {a}" | |
| for i, (s, t, m, a) in enumerate(results) | |
| ) | |
| prompt = f"""You are the Lingrow Support Copilot. Lingrow is a real-time | |
| multilingual translation app (live captions, spoken translation, QR-join sessions). | |
| A customer asked: "{question}" | |
| Here are the most similar past tickets and their VERIFIED solutions: | |
| {context} | |
| Write ONE helpful support reply (3-5 sentences max). Rules: | |
| - Base your answer ONLY on the verified solutions above. Do not invent features. | |
| - If the question has multiple issues, address each one using the matching ticket. | |
| - Be friendly, direct, and specific (mention exact buttons/icons when given). | |
| - IMPORTANT: Reply in the SAME language the customer used. If the question is in | |
| Hebrew, your entire reply must be in Hebrew. If Spanish, reply in Spanish.""" | |
| resp = client.chat_completion( | |
| model=GEN_MODEL, | |
| messages=[{"role": "user", "content": prompt}], | |
| max_tokens=220, | |
| temperature=0.3, | |
| ) | |
| return resp.choices[0].message.content.strip() | |
| def support_copilot(message, history): | |
| results = find_similar(message, k=4) | |
| top_score = results[0][0] | |
| if top_score < CONFIDENCE_THRESHOLD: | |
| return rtl_wrap("I'm not confident I found a matching case for this. " | |
| "Could you describe the issue in a bit more detail? " | |
| "For example: what were you doing, and what did you see on screen?") | |
| try: | |
| return rtl_wrap(generate_reply(message, results)) | |
| except Exception as e: | |
| print(f"GENERATION FAILED: {e}", flush=True) | |
| best = results[0] | |
| return rtl_wrap(f"Thanks for reaching out! Here's how to solve this: {best[3]}") | |
| rtl_css = """ | |
| .message-wrap .message, .message-wrap p, .prose p, .prose li { | |
| unicode-bidi: plaintext; | |
| text-align: start; | |
| } | |
| textarea, input[type="text"] { | |
| unicode-bidi: plaintext; | |
| text-align: start; | |
| } | |
| """ | |
| def rtl_wrap(text): | |
| """Wrap reply so the browser aligns it by its language (Hebrew -> right).""" | |
| return f'<div dir="auto">{text}</div>' | |
| demo = gr.ChatInterface( | |
| fn=support_copilot, | |
| title="Lingrow Support Copilot", | |
| description=("Ask about any Lingrow issue — login, sessions, captions, audio, " | |
| "translation — and get an answer based on verified past solutions."), | |
| examples=[ | |
| "I keep getting an invalid token error when I log in", | |
| "The subtitles are too small and I can't hear any audio", | |
| "How do I invite more people into my live session?", | |
| ], | |
| ) | |
| demo.launch() |