LeemAI / app.py
makaram's picture
Upload 4 files
1153a3e verified
Raw
History Blame Contribute Delete
4.04 kB
import json
import numpy as np
from flask import Flask, request, jsonify
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import os
app = Flask(__name__)
# --- Configuration --- #
# IMPORTANT: For Cloud Run deployment, ensure these files are available in the deployment environment.
# You would typically upload them with your Docker image or fetch from Google Cloud Storage.
CHUNKS_FILE = 'leemai_all_chunks.json'
EMBEDDINGS_FILE = 'leemai_document_embeddings.npy'
# --- Load Model and Data --- #
# These are loaded once when the application starts
print("Loading SentenceTransformer model...")
embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
print("Model loaded successfully.")
# Load chunks
print(f"Loading chunks from {CHUNKS_FILE}...")
if not os.path.exists(CHUNKS_FILE):
print(f"Error: {CHUNKS_FILE} not found. Please ensure it's in the same directory as app.py or provide the correct path.")
all_leemai_chunks = []
else:
with open(CHUNKS_FILE, 'r') as f:
all_leemai_chunks = json.load(f)
print(f"Loaded {len(all_leemai_chunks)} chunks.")
# Load embeddings
print(f"Loading embeddings from {EMBEDDINGS_FILE}...")
if not os.path.exists(EMBEDDINGS_FILE):
print(f"Error: {EMBEDDINGS_FILE} not found. Please ensure it's in the same directory as app.py or provide the correct path.")
document_embeddings = np.array([]) # Initialize as empty array if not found
else:
document_embeddings = np.load(EMBEDDINGS_FILE)
print(f"Loaded embeddings with shape: {document_embeddings.shape}")
# --- Helper Functions (Copied from previous steps) ---
def get_relevant_chunks(query, model, document_chunks, document_embeddings, top_k=3):
"""Finds the most semantically similar document chunks to a given query."""
if not document_chunks or document_embeddings.size == 0:
return []
query_embedding = model.encode([query])
similarities = cosine_similarity(query_embedding, document_embeddings)[0]
top_k_indices = similarities.argsort()[-top_k:][::-1]
relevant_chunks = []
for i in top_k_indices:
relevant_chunks.append({
'chunk': document_chunks[i],
'similarity': similarities[i]
})
return relevant_chunks
def generate_response_from_chunks(relevant_chunks):
"""Generates a basic response by concatenating relevant chunks with improved formatting."""
if not relevant_chunks:
return "I couldn't find relevant information for your query in my knowledge base."
response_text = "Based on the information I have, here are some relevant details:\n\n"
for i, item in enumerate(relevant_chunks):
response_text += f"**Information Block {i+1}:**\n"
response_text += f"{item['chunk']}\n\n"
response_text += "I hope these details provide a comprehensive answer to your query!"
return response_text
# --- Flask Routes ---
@app.route('/')
def home():
return "LeemAI is running! Use the /ask endpoint to query."
@app.route('/ask', methods=['POST'])
def ask():
data = request.get_json()
user_query = data.get('query')
if not user_query:
return jsonify({'error': 'No query provided'}), 400
if not all_leemai_chunks or document_embeddings.size == 0:
return jsonify({'error': 'LeemAI knowledge base not loaded. Check server logs.'}), 500
relevant_chunks = get_relevant_chunks(
user_query, embedding_model, all_leemai_chunks, document_embeddings
)
leemai_response = generate_response_from_chunks(relevant_chunks)
return jsonify({'response': leemai_response})
# --- Main Entry Point ---
if __name__ == '__main__':
# In a production environment like Cloud Run, Flask applications are typically
# run by a WSGI server (like Gunicorn). This block is for local testing.
# For Cloud Run, ensure your Dockerfile specifies the entrypoint for Gunicorn
# or equivalent.
app.run(debug=False, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))