Download app.py from Ommodi07/Chatbot: direct link, hf CLI and curl.
- Browser
- Download file 8.78 kB
-
https://huggingface.co/spaces/Ommodi07/Chatbot/resolve/main/app.py
- Command line
-
hf download hf://spaces/Ommodi07/Chatbot/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Ommodi07/Chatbot/resolve/main/app.py
8.78 kB
| from flask import Flask, request, jsonify, render_template | |
| from langchain_huggingface import HuggingFaceEmbeddings | |
| from langchain_community.document_loaders import PyPDFLoader | |
| from langchain.text_splitter import RecursiveCharacterTextSplitter | |
| from langchain_community.vectorstores import FAISS | |
| from langchain_google_genai import ChatGoogleGenerativeAI | |
| import os | |
| import json | |
| app = Flask(__name__) | |
| # Create templates directory if it doesn't exist | |
| os.makedirs('templates', exist_ok=True) | |
| # Create HTML template for the chatbot interface | |
| with open('templates/index.html', 'w') as f: | |
| f.write(''' | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Cirrhosis Toolkit Chatbot</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| margin: 0; | |
| padding: 0; | |
| display: flex; | |
| flex-direction: column; | |
| height: 100vh; | |
| background-color: #f5f5f5; | |
| } | |
| .header { | |
| background-color: #2c3e50; | |
| color: white; | |
| text-align: center; | |
| padding: 1rem; | |
| } | |
| .chat-container { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| max-width: 800px; | |
| margin: 0 auto; | |
| padding: 1rem; | |
| width: 100%; | |
| box-sizing: border-box; | |
| } | |
| .messages { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 1rem; | |
| background-color: white; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 10px rgba(0,0,0,0.1); | |
| margin-bottom: 1rem; | |
| } | |
| .message { | |
| margin-bottom: 1rem; | |
| padding: 0.8rem; | |
| border-radius: 8px; | |
| max-width: 80%; | |
| } | |
| .user-message { | |
| background-color: #3498db; | |
| color: white; | |
| align-self: flex-end; | |
| margin-left: auto; | |
| } | |
| .bot-message { | |
| background-color: #ecf0f1; | |
| color: #333; | |
| align-self: flex-start; | |
| } | |
| .input-area { | |
| display: flex; | |
| gap: 0.5rem; | |
| } | |
| #user-input { | |
| flex: 1; | |
| padding: 0.8rem; | |
| border: 1px solid #ddd; | |
| border-radius: 4px; | |
| font-size: 1rem; | |
| } | |
| button { | |
| padding: 0.8rem 1.5rem; | |
| background-color: #2c3e50; | |
| color: white; | |
| border: none; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| font-size: 1rem; | |
| } | |
| button:hover { | |
| background-color: #1a252f; | |
| } | |
| .loading { | |
| display: none; | |
| text-align: center; | |
| margin: 1rem 0; | |
| } | |
| .loading-dots { | |
| display: inline-block; | |
| } | |
| .loading-dots::after { | |
| content: '.'; | |
| animation: dots 1.5s steps(5, end) infinite; | |
| } | |
| @keyframes dots { | |
| 0%, 20% { content: '.'; } | |
| 40% { content: '..'; } | |
| 60% { content: '...'; } | |
| 80%, 100% { content: ''; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header"> | |
| <h1>Cirrhosis Toolkit Assistant</h1> | |
| </div> | |
| <div class="chat-container"> | |
| <div class="messages" id="chat-messages"> | |
| <div class="message bot-message"> | |
| Hello! I'm your Cirrhosis Toolkit assistant. Ask me any questions about cirrhosis management and treatment. | |
| </div> | |
| </div> | |
| <div class="loading" id="loading"> | |
| Thinking<span class="loading-dots"></span> | |
| </div> | |
| <div class="input-area"> | |
| <input type="text" id="user-input" placeholder="Ask a question..." autocomplete="off"> | |
| <button id="send-btn">Send</button> | |
| </div> | |
| </div> | |
| <script> | |
| const chatMessages = document.getElementById('chat-messages'); | |
| const userInput = document.getElementById('user-input'); | |
| const sendBtn = document.getElementById('send-btn'); | |
| const loadingIndicator = document.getElementById('loading'); | |
| // Function to add a message to the chat | |
| function addMessage(message, isUser = false) { | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = `message ${isUser ? 'user-message' : 'bot-message'}`; | |
| messageDiv.textContent = message; | |
| chatMessages.appendChild(messageDiv); | |
| chatMessages.scrollTop = chatMessages.scrollHeight; | |
| } | |
| // Function to send user query to backend | |
| async function sendQuery(query) { | |
| loadingIndicator.style.display = 'block'; | |
| try { | |
| const response = await fetch('/query', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ query }), | |
| }); | |
| const data = await response.json(); | |
| if (response.ok) { | |
| addMessage(data.response); | |
| } else { | |
| addMessage(`Error: ${data.error || 'Something went wrong'}`); | |
| } | |
| } catch (error) { | |
| addMessage(`Error: ${error.message}`); | |
| } finally { | |
| loadingIndicator.style.display = 'none'; | |
| } | |
| } | |
| // Event listener for send button | |
| sendBtn.addEventListener('click', () => { | |
| const query = userInput.value.trim(); | |
| if (query) { | |
| addMessage(query, true); | |
| userInput.value = ''; | |
| sendQuery(query); | |
| } | |
| }); | |
| // Event listener for Enter key | |
| userInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') { | |
| const query = userInput.value.trim(); | |
| if (query) { | |
| addMessage(query, true); | |
| userInput.value = ''; | |
| sendQuery(query); | |
| } | |
| } | |
| }); | |
| // Focus input on page load | |
| userInput.focus(); | |
| </script> | |
| </body> | |
| </html> | |
| ''') | |
| # Set your Google API key | |
| os.environ["GOOGLE_API_KEY"] = "AIzaSyCOsco3wW-yHA074FTp-Mbz8NgUptGUY_8" # Replace with your actual API key | |
| # Use a lightweight embedding model to reduce memory usage | |
| embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") | |
| # Google Gemini LLM setup | |
| llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash-lite", temperature=0.7) | |
| # FAISS index path (stored on disk) | |
| FAISS_INDEX_PATH = "faiss_index" | |
| # PDF path | |
| PDF_PATH = "CirrhosisToolkit.pdf" | |
| def process_pdf(pdf_path): | |
| """Processes the PDF and stores FAISS index on disk to save memory.""" | |
| loader = PyPDFLoader(pdf_path) | |
| documents = loader.lazy_load() # Lazy load to avoid high memory usage | |
| # Reduce chunk size to save memory | |
| text_splitter = RecursiveCharacterTextSplitter(chunk_size=150, chunk_overlap=30) | |
| texts = text_splitter.split_documents(documents) | |
| # Store FAISS on disk to avoid keeping everything in RAM | |
| vectordb = FAISS.from_documents(texts, embeddings) | |
| vectordb.save_local(FAISS_INDEX_PATH) | |
| # Load FAISS index if available, else process the PDF | |
| if os.path.exists(FAISS_INDEX_PATH): | |
| vectordb = FAISS.load_local(FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True) | |
| else: | |
| process_pdf(PDF_PATH) | |
| vectordb = FAISS.load_local(FAISS_INDEX_PATH, embeddings, allow_dangerous_deserialization=True) | |
| def index(): | |
| """Renders the chatbot frontend.""" | |
| return render_template('index.html') | |
| def query_pdf(): | |
| """Handles user queries and retrieves relevant document context.""" | |
| if vectordb is None: | |
| return jsonify({'error': 'No PDF processed yet'}), 400 | |
| data = request.get_json() | |
| query_text = data.get("query", "") | |
| if not query_text: | |
| return jsonify({'error': 'No query provided'}), 400 | |
| # Perform similarity search with reduced results (k=2) to save memory | |
| results = vectordb.similarity_search(query_text, k=2) | |
| context = "\n".join([res.page_content for res in results]) | |
| # Generate response with Gemini | |
| prompt = f"Using the following document context, answer the query concisely.\n\nContext:\n{context}\n\nQuery: {query_text}" | |
| gemini_response = llm.invoke(prompt) | |
| return jsonify({'response': gemini_response.content}) | |
| if __name__ == '__main__': | |
| app.run(debug=True) |