xELMXx/ELMX_Chatbot
0
1import os2import json3import glob4from sentence_transformers import SentenceTransformer5import faiss6import numpy as np7import gradio as gr8 9 10# Load all JSON files11json_files = glob.glob("data/*.json")12 13# Prepare containers14project_entries = {}15general_entries = []16 17# Classify files18for file_path in json_files:19 with open(file_path, 'r', encoding='utf-8') as f:20 data = json.load(f)21 if os.path.basename(file_path) in ['d35.json', 'greeting.json']:22 general_entries.extend(data)23 else:24 for entry in data:25 project_title = entry.get('metadata', {}).get('project_title')26 if project_title:27 project_entries.setdefault(project_title, []).append(entry)28 29# Check result30print(f"Loaded {len(project_entries)} projects and {len(general_entries)} general entries.")31 32 33# Load sentence transformer model34embedder = SentenceTransformer('all-MiniLM-L6-v2')35 36# Prepare FAISS indexes37faiss_indexes = {}38faiss_general_index = None39project_embeddings = {}40general_embeddings = None41 42# Build indexes for projects43for title, entries in project_entries.items():44 questions = [e['question'] for e in entries]45 embeddings = embedder.encode(questions, convert_to_numpy=True)46 index = faiss.IndexFlatL2(embeddings.shape[1])47 index.add(embeddings)48 faiss_indexes[title] = (index, entries)49 project_embeddings[title] = embeddings50 51# Build index for general files52if general_entries:53 questions = [e['question'] for e in general_entries]54 general_embeddings = embedder.encode(questions, convert_to_numpy=True)55 faiss_general_index = faiss.IndexFlatL2(general_embeddings.shape[1])56 faiss_general_index.add(general_embeddings)57 58 59 60def chatbot_response(question, selected_project, chat_history):61 if not question.strip():62 return chat_history, ""63 64 embedding = embedder.encode([question])[0]65 k = 1 # top-1 result only66 67 if selected_project and selected_project in faiss_indexes:68 index, entries = faiss_indexes[selected_project]69 D, I = index.search(np.array([embedding]), k)70 result = entries[I[0][0]]['answer']71 elif faiss_general_index is not None:72 D, I = faiss_general_index.search(np.array([embedding]), k)73 result = general_entries[I[0][0]]['answer']74 else:75 result = "Sorry, no data available."76 77 chat_history.append(("๐ง You: " + question, "๐ค " + result))78 return chat_history, ""79 80 81 82 83 84# Get unique project titles85unique_project_titles = ["-- Select a Project --"] + list(project_entries.keys())86 87with gr.Blocks() as demo:88 project_dropdown = gr.Dropdown(89 label="Select Project (optional)",90 choices=unique_project_titles,91 value="-- Select a Project --"92 )93 94 project_label = gr.Markdown()95 96 chatbot = gr.Chatbot()97 user_input = gr.Textbox(placeholder="Type your question and press Enter...", label="")98 clear_button = gr.Button("๐๏ธ Clear Chat")99 100 # Confirm project selection101 def update_project_label(proj):102 if proj and proj != "-- Select a Project --":103 return f"โ
**Project selected:** {proj}"104 else:105 return "โ No project selected"106 107 project_dropdown.change(fn=update_project_label, inputs=project_dropdown, outputs=project_label)108 109 # Handle sending message110 state = gr.State([]) # chat history state111 user_input.submit(112 fn=chatbot_response,113 inputs=[user_input, project_dropdown, state],114 outputs=[chatbot, user_input]115 )116 117 # Clear chat and reset118 def clear_all():119 return [], "-- Select a Project --", "โ No project selected"120 121 clear_button.click(fn=clear_all, outputs=[chatbot, project_dropdown, project_label])122 123 gr.Markdown("#### Built with โจ for ELMX")124 125 126demo.launch(share=True)127 