import gradio as gr import pandas as pd from sentence_transformers import SentenceTransformer, util # ---------- Load data & model (all CPU-friendly) ---------- faq_df = pd.read_csv("faqs.csv") questions = faq_df["question"].tolist() answers = faq_df["answer"].tolist() model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2") question_embeddings = model.encode(questions, convert_to_tensor=True, normalize_embeddings=True) # ---------- Search function ---------- def semantic_search(user_query, top_k=3): query_embedding = model.encode(user_query, convert_to_tensor=True, normalize_embeddings=True) scores = util.cos_sim(query_embedding, question_embeddings)[0] top_k_idx = scores.topk(k=top_k).indices.cpu().numpy() results = [] for idx in top_k_idx: results.append( { "FAQ Question": questions[idx], "FAQ Answer" : answers[idx], "Similarity" : f"{scores[idx]:.3f}" } ) return results # ---------- Gradio UI ---------- with gr.Blocks(title="MiniLM Semantic FAQ Search") as demo: gr.Markdown( """ # 🔍 Semantic FAQ Search Enter a salon-related question. The model finds the closest FAQs and displays their answers. """) with gr.Row(): query_box = gr.Textbox( label="Ask a question", placeholder="e.g. Which spray protects hair from heat?" ) topk_slider = gr.Slider( 1, 5, value=3, step=1, label="Number of results" ) search_btn = gr.Button("Search") out = gr.Dataframe(headers=["FAQ Question", "FAQ Answer", "Similarity"], visible=True, wrap=True) search_btn.click(semantic_search, [query_box, topk_slider], out) if __name__ == "__main__": demo.launch(server_name="0.0.0.0", show_error=True)