import gradio as gr import os import uuid import threading import pandas as pd import torch from langchain.document_loaders.csv_loader import CSVLoader from langchain.embeddings import HuggingFaceEmbeddings from langchain.vectorstores import FAISS from langchain.llms import CTransformers from langchain.chains import ConversationalRetrievalChain # Global model cache MODEL_CACHE = { "model": None, "init_lock": threading.Lock() } # Create directories for user data os.makedirs("user_data", exist_ok=True) def initialize_model_once(): """Initialize the model once and cache it""" with MODEL_CACHE["init_lock"]: if MODEL_CACHE["model"] is None: # Path ke model local dalam repository model_path = "tinyllama-1.1b-chat-v1.0.Q5_K_M.gguf" MODEL_CACHE["model"] = CTransformers( model=model_path, model_type="tinyllama", max_new_tokens=512, temperature=0.2, top_p=0.9, top_k=50, repetition_penalty=1.2 ) return MODEL_CACHE["model"] class ChatBot: def __init__(self, session_id): self.session_id = session_id self.chat_history = [] self.chain = None self.user_dir = f"user_data/{session_id}" os.makedirs(self.user_dir, exist_ok=True) def process_file(self, file): if file is None: return "Mohon upload file CSV terlebih dahulu." try: # Handle file from Gradio file_path = file.name if hasattr(file, 'name') else str(file) # Copy to user directory user_file_path = f"{self.user_dir}/uploaded.csv" # For debugging print(f"Processing file: {file_path}") print(f"Saving to: {user_file_path}") # Verify the CSV can be loaded try: df = pd.read_csv(file_path) print(f"CSV verified: {df.shape[0]} rows, {len(df.columns)} columns") # Save a copy in user directory df.to_csv(user_file_path, index=False) except Exception as e: return f"Error membaca CSV: {str(e)}" # Load document try: loader = CSVLoader(file_path=file_path, encoding="utf-8", csv_args={ 'delimiter': ','}) data = loader.load() print(f"Documents loaded: {len(data)}") except Exception as e: return f"Error loading documents: {str(e)}" # Create vector database try: db_path = f"{self.user_dir}/db_faiss" embeddings = HuggingFaceEmbeddings( model_name='sentence-transformers/all-MiniLM-L6-v2', model_kwargs={'device': 'cuda' if torch.cuda.is_available() else 'cpu'} ) db = FAISS.from_documents(data, embeddings) db.save_local(db_path) print(f"Vector database created at {db_path}") except Exception as e: return f"Error creating vector database: {str(e)}" # Create LLM and chain try: llm = initialize_model_once() self.chain = ConversationalRetrievalChain.from_llm( llm=llm, retriever=db.as_retriever(search_kwargs={"k": 4}) ) print("Chain created successfully") except Exception as e: return f"Error creating chain: {str(e)}" # Add basic file info to chat history for context file_info = f"CSV berhasil dimuat dengan {df.shape[0]} baris dan {len(df.columns)} kolom. Kolom: {', '.join(df.columns.tolist())}" self.chat_history.append(("System", file_info)) return "File CSV berhasil diproses! Anda dapat mulai chat dengan model Llama2." except Exception as e: import traceback print(traceback.format_exc()) return f"Error pemrosesan file: {str(e)}" def chat(self, message, history): if self.chain is None: return "Mohon upload file CSV terlebih dahulu." try: # Process the question with the chain result = self.chain({"question": message, "chat_history": self.chat_history}) # Update internal chat history answer = result["answer"] self.chat_history.append((message, answer)) # Return just the answer for Gradio return answer except Exception as e: import traceback print(traceback.format_exc()) return f"Error: {str(e)}" def cleanup(self): """Release resources when session ends""" self.chain = None def create_gradio_interface(): with gr.Blocks(title="Chat with CSV using Llama2 🦙") as interface: # Create unique session ID for each user session_id = gr.State(lambda: str(uuid.uuid4())) # Create user-specific chatbot instance chatbot_state = gr.State(lambda: None) gr.HTML("