| import gradio as gr |
| import os |
| import torch |
| from transformers import AutoTokenizer, AutoModelForCausalLM |
| from sentence_transformers import SentenceTransformer |
| from faiss import IndexFlatL2, normalize_L2 |
| import numpy as np |
|
|
| |
| |
| |
| HF_TOKEN = os.getenv("HF_TOKEN") |
| MODEL_ID = "google/gemma-2b-it" |
|
|
| |
| |
| device = "cuda" if torch.cuda.is_available() else "cpu" |
| tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, token=HF_TOKEN) |
| model = AutoModelForCausalLM.from_pretrained(MODEL_ID, device_map=device, token=HF_TOKEN) |
|
|
| |
| |
| rag_model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2") |
| |
| faiss_index = IndexFlatL2(384) |
| |
| processed_document_content = "" |
|
|
| |
| def generate_response(question, context): |
| |
| prompt = f"Given the following context: {context}\n\nAnswer the question: {question}" |
| |
| |
| inputs = tokenizer(prompt, return_tensors="pt").to(device) |
|
|
| |
| outputs = model.generate(**inputs, max_new_tokens=200, pad_token_id=tokenizer.eos_token_id) |
|
|
| |
| response = tokenizer.decode(outputs[0], skip_special_tokens=True) |
|
|
| |
| if prompt in response: |
| response = response.replace(prompt, "").strip() |
| |
| return response |
|
|
| |
| def process_file(file_obj): |
| global processed_document_content, faiss_index |
|
|
| if file_obj is None: |
| return "Please upload a file first." |
|
|
| |
| with open(file_obj.name, "r", encoding="utf-8") as f: |
| processed_document_content = f.read() |
|
|
| |
| sentences = processed_document_content.split(".") |
|
|
| |
| embeddings = rag_model.encode(sentences) |
|
|
| |
| embeddings_normalized = normalize_L2(embeddings) |
|
|
| |
| |
| faiss_index = IndexFlatL2(embeddings_normalized.shape[1]) |
| faiss_index.add(embeddings_normalized) |
|
|
| return f"Successfully processed file with {len(sentences)} chunks." |
|
|
| |
| def rag_answer(question): |
| if faiss_index.ntotal == 0: |
| return "No document loaded. Please upload a file first." |
|
|
| |
| question_embedding = rag_model.encode([question]) |
| question_embedding_normalized = normalize_L2(question_embedding) |
|
|
| |
| _, indices = faiss_index.search(question_embedding_normalized, 1) |
| |
| |
| context_sentence_index = indices[0][0] |
| sentences = processed_document_content.split(".") |
| context = sentences[context_sentence_index] |
| |
| |
| return generate_response(question, context) |
|
|
| |
| with gr.Blocks(theme="soft") as demo: |
| gr.Markdown("# <center>Code & Data Analysis Chatbot</center>") |
| gr.Markdown("I'm a chatbot specialized in coding and data analysis. You can ask me questions or upload a `.csv` or `.txt` file for me to analyze!") |
|
|
| with gr.Row(): |
| with gr.Column(scale=1): |
| file_upload = gr.File(label="Upload a file for analysis (.txt or .csv)") |
| file_output = gr.Textbox(label="File Status") |
| upload_button = gr.Button("Process File") |
|
|
| with gr.Column(scale=2): |
| chatbot = gr.Chatbot(label="Chat History") |
| msg = gr.Textbox(label="Your message", placeholder="Ask a question...") |
| with gr.Row(): |
| submit_btn = gr.Button("Submit") |
| clear_btn = gr.Button("Clear Chat") |
|
|
| |
| upload_button.click( |
| fn=process_file, |
| inputs=file_upload, |
| outputs=file_output |
| ) |
|
|
| submit_btn.click( |
| fn=lambda msg, history: (rag_answer(msg), history + [[msg, rag_answer(msg)]]), |
| inputs=[msg, chatbot], |
| outputs=[msg, chatbot] |
| ) |
|
|
| clear_btn.click( |
| fn=lambda: (None, []), |
| inputs=None, |
| outputs=[msg, chatbot] |
| ) |
|
|
| demo.launch() |
|
|