import gradio as gr import nltk from nltk.tokenize import sent_tokenize from transformers import AutoTokenizer, AutoModel import torch import faiss import numpy as np import openai # Set up OpenAI API key openai.api_key = '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' # Download NLTK data nltk.download('punkt') # Load the tokenizer and model tokenizer = AutoTokenizer.from_pretrained("microsoft/MiniLM-L12-H384-uncased") model = AutoModel.from_pretrained("microsoft/MiniLM-L12-H384-uncased") manual_path = "ubuntu_manual.txt" # Load the Ubuntu manual from a .txt file with open(manual_path, "r", encoding="utf-8") as file: full_text = file.read() # Function to chunk the text into smaller pieces def chunk_text(text, chunk_size=500): sentences = sent_tokenize(text) chunks = [] current_chunk = [] for sentence in sentences: if len(current_chunk) + len(sentence.split()) <= chunk_size: current_chunk.append(sentence) else: chunks.append(" ".join(current_chunk)) current_chunk = [sentence] if current_chunk: chunks.append(" ".join(current_chunk)) return chunks # Apply chunking to the entire text manual_chunks = chunk_text(full_text, chunk_size=500) # Function to generate embeddings for each chunk def embed_text(texts): inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt", max_length=512) with torch.no_grad(): outputs = model(**inputs) embeddings = outputs.last_hidden_state[:, 0, :].cpu().numpy() # CLS token representation return embeddings # Generate embeddings for the chunks chunk_embeddings = embed_text(manual_chunks) # Convert embeddings to a numpy array chunk_embeddings_np = np.array(chunk_embeddings) # Create a FAISS index and add the embeddings dimension = chunk_embeddings_np.shape[1] index = faiss.IndexFlatL2(dimension) index.add(chunk_embeddings_np) # Function to retrieve relevant chunks for a user query and print indices and distances def retrieve_chunks(query, k=5): query_embedding = embed_text([query]) distances, indices = index.search(query_embedding, k=k) valid_indices = [i for i in indices[0] if i < len(manual_chunks)] relevant_chunks = [manual_chunks[i] for i in valid_indices] # Print indices and distances for i, idx in enumerate(valid_indices): print(f"Index: {idx}, Distance: {distances[0][i]}") return relevant_chunks, indices[0], distances[0] # Function to perform RAG: Retrieve chunks and generate a response using GPT-3.5 def rag_response_gpt3_5(query, k=3, max_tokens=150): relevant_chunks, indices, distances = retrieve_chunks(query, k=k) if not relevant_chunks: return "Sorry, I couldn't find relevant information." # Combine the query with a limited number of retrieved chunks augmented_input = query + "\n" + "\n".join(relevant_chunks) # Tokenize the augmented input and ensure it fits within model token limits input_ids = tokenizer(augmented_input, return_tensors="pt").input_ids[0] if len(input_ids) > 512: input_ids = input_ids[:512] augmented_input = tokenizer.decode(input_ids, skip_special_tokens=True) response = openai.ChatCompletion.create( model="gpt-3.5-turbo", messages=[ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": augmented_input} ], max_tokens=max_tokens, temperature=0.7 ) return response.choices[0].message['content'].strip() # Chat history to maintain conversation context def chatbot(query, history): if history is None: history = [] # Retrieve relevant chunks along with their indices and distances relevant_chunks, indices, distances = retrieve_chunks(query) # Print the indices and distances of the retrieved chunks print(f"Retrieved Indices: {indices}") print(f"Retrieved Distances: {distances}") response = rag_response_gpt3_5(query) history.append((query, response)) # Combine all messages into a single string chat_history = "" for user_input, bot_response in history: chat_history += f"User: {user_input}\nBot: {bot_response}\n\n" return chat_history, history # Create the Gradio interface iface = gr.Interface(fn=chatbot, inputs=["text", "state"], outputs=["text", "state"], title="Ubuntu Manual Chatbot", description="Ask me anything about the Ubuntu manual.") # Launch the app if __name__ == "__main__": iface.launch()