chat-bot / app.py
jarvis0852's picture
Update app.py
db99a4e verified
Raw
History Blame Contribute Delete
13.4 kB
# from flask import Flask, request, jsonify
# from flask_cors import CORS
# import os
# # Prevent native runtime conflicts between TensorFlow's and PyTorch's bundled
# # protobuf / OpenMP libraries, which can cause a silent segfault (exit 139)
# # when both libraries are loaded in the same process.
# os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python"
# os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
# os.environ["OMP_NUM_THREADS"] = "1"
# import pickle
# import numpy as np
# import re
# import random
# # import spaces
# # Import sentence-transformers (and its PyTorch dependency) BEFORE TensorFlow.
# # Whichever loads its native protobuf/OpenMP runtime first tends to avoid the
# # conflict that causes the segfault.
# print("Step 0a: Importing SentenceTransformer...")
# from sentence_transformers import SentenceTransformer, util
# print("Step 0a done: sentence-transformers imported OK")
# print("Step 0: Importing TensorFlow / Keras...")
# from tensorflow.keras.models import load_model
# from tensorflow.keras.preprocessing.sequence import pad_sequences
# print("Step 0 done: TensorFlow imported OK")
# app = Flask(__name__)
# CORS(app) # Zaroori hai! Isse Vercel (alag domain) se API call allow hogi
# # ----------------------------
# # Load all saved files
# # ----------------------------
# print("Loading model and data... please wait")
# print("Step 1: Loading LSTM model (chatbot_lstm.h5)...")
# model_lstm = load_model("chatbot_lstm.h5")
# print("Step 1 done: LSTM model loaded OK")
# print("Step 2: Loading tokenizer.pickle...")
# with open("tokenizer.pickle", "rb") as f:
# tokenizer = pickle.load(f)
# print("Step 2 done")
# print("Step 3: Loading label_encoder.pickle...")
# with open("label_encoder.pickle", "rb") as f:
# label_encoder = pickle.load(f)
# print("Step 3 done")
# print("Step 4: Loading responses_dict.pickle...")
# with open("responses_dict.pickle", "rb") as f:
# responses_dict = pickle.load(f)
# print("Step 4 done")
# print("Step 5: Loading intent_keywords.pickle...")
# with open("intent_keywords.pickle", "rb") as f:
# intent_keywords = pickle.load(f)
# print("Step 5 done")
# print("Step 6: Loading pattern_embeddings.pickle...")
# with open("pattern_embeddings.pickle", "rb") as f:
# pattern_embeddings = pickle.load(f)
# print("Step 6 done")
# print("Step 7: Loading semantic_pattern_to_intent.pickle...")
# with open("semantic_pattern_to_intent.pickle", "rb") as f:
# semantic_pattern_to_intent = pickle.load(f)
# print("Step 7 done")
# print("Step 8: Loading SentenceTransformer('all-MiniLM-L6-v2')...")
# embedder = SentenceTransformer('all-MiniLM-L6-v2')
# print("Step 8 done: embedder loaded OK")
# max_len = 25 # training ke waqt jo value use ki thi wahi yahan bhi rakhna
# print("Everything loaded successfully!")
# # ----------------------------
# # Typo fix + text cleaning
# # ----------------------------
# typo_fix = {
# 'hlo': 'hello', 'helo': 'hello', 'hii': 'hi', 'hey': 'hi',
# 'thanx': 'thanks', 'thnx': 'thanks', 'thx': 'thanks',
# 'plz': 'please', 'pls': 'please', 'u': 'you', 'ur': 'your',
# 'r': 'are', 'wat': 'what', 'wht': 'what', 'y': 'why'
# }
# def clean_text(text):
# text = text.lower().strip()
# words = text.split()
# words = [typo_fix.get(w, w) for w in words]
# text = " ".join(words)
# text = re.sub(r"[^a-zA-Z0-9\s']", " ", text)
# text = re.sub(r"\s+", " ", text).strip()
# return text
# # ----------------------------
# # Prediction layers
# # ----------------------------
# def predict_lstm_raw(text):
# seq = tokenizer.texts_to_sequences([text])
# padded = pad_sequences(seq, maxlen=max_len, padding='post')
# pred = model_lstm.predict(padded, verbose=0)[0]
# idx = int(np.argmax(pred))
# return label_encoder.inverse_transform([idx])[0], float(pred[idx])
# def predict_keyword(text):
# query_words = set(text.split())
# scores = {}
# for intent, keywords in intent_keywords.items():
# overlap = len(query_words & keywords)
# if overlap > 0:
# scores[intent] = overlap
# if not scores:
# return None, 0
# best_intent = max(scores, key=scores.get)
# return best_intent, scores[best_intent]
# def predict_semantic(text, threshold=0.45):
# query_embedding = embedder.encode(text, convert_to_tensor=True)
# scores = util.cos_sim(query_embedding, pattern_embeddings)[0]
# best_idx = int(scores.argmax())
# best_score = float(scores[best_idx])
# if best_score < threshold:
# return None, best_score
# return semantic_pattern_to_intent[best_idx], best_score
# def predict_intent_final(user_text):
# text = clean_text(user_text)
# lstm_intent, lstm_conf = predict_lstm_raw(text)
# sem_intent, sem_score = predict_semantic(text)
# kw_intent, kw_score = predict_keyword(text)
# if sem_intent is not None and lstm_intent == sem_intent:
# return lstm_intent, "LSTM+Semantic Agree", (lstm_conf + sem_score) / 2
# if sem_intent is not None and sem_score >= 0.5:
# return sem_intent, "Semantic", sem_score
# if kw_intent is not None and kw_score >= 1:
# return kw_intent, "Keyword", kw_score
# if lstm_conf >= 0.9:
# return lstm_intent, "LSTM-only (risky)", lstm_conf
# return None, "None", 0
# # @spaces.GPU # Not needed on CPU basic hardware — leave commented/removed
# def chatbot_response(user_text):
# intent, source, confidence = predict_intent_final(user_text)
# if intent is None:
# return "Sorry, mujhe samajh nahi aaya. Kya aap admission, fees, courses, ya contact details ke baare mein pooch rahe hain?"
# return random.choice(responses_dict[intent])
# # ----------------------------
# # Routes
# # ----------------------------
# @app.route("/", methods=["GET"])
# def health_check():
# return jsonify({"status": "ILS Chatbot API is running!"})
# @app.route("/chat", methods=["POST"])
# def chat():
# try:
# user_message = request.json.get("message", "")
# if not user_message.strip():
# return jsonify({"response": "Kuch toh likho!"})
# response = chatbot_response(user_message)
# return jsonify({"response": response})
# except Exception as e:
# # Surface real errors instead of letting the process crash silently
# print(f"Error in /chat: {e}")
# return jsonify({"response": "Kuch technical issue ho gaya, thodi der baad try karo."}), 500
# if __name__ == "__main__":
# app.run(host="0.0.0.0", port=7860)
from flask import Flask, request, jsonify
from flask_cors import CORS
import os
# Prevent native runtime conflicts between TensorFlow's and PyTorch's bundled
# protobuf / OpenMP libraries, which can cause a silent segfault (exit 139)
# when both libraries are loaded in the same process.
os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python"
os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE"
os.environ["OMP_NUM_THREADS"] = "1"
import pickle
import numpy as np
import re
import random
from huggingface_hub import hf_hub_download
# --- CORRECT CONFIGURATION ---
STORAGE_REPO_ID = "jarvis0852/path-ils-bot"
# Import sentence-transformers (and its PyTorch dependency) BEFORE TensorFlow.
print("Step 0a: Importing SentenceTransformer...")
from sentence_transformers import SentenceTransformer, util
print("Step 0a done: sentence-transformers imported OK")
print("Step 0: Importing TensorFlow / Keras...")
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.sequence import pad_sequences
print("Step 0 done: TensorFlow imported OK")
app = Flask(__name__)
CORS(app)
# Helper function to dynamically fetch files from your large repository
def fetch_from_hub(filename):
print(f"Fetching {filename} from storage repository...")
return hf_hub_download(repo_id=STORAGE_REPO_ID, filename=filename)
# ----------------------------
# Load all saved files from Hub
# ----------------------------
print("Loading model and data... please wait")
print("Step 1: Loading LSTM model (chatbot_lstm.h5)...")
lstm_path = fetch_from_hub("chatbot_lstm.h5")
model_lstm = load_model(lstm_path)
print("Step 1 done: LSTM model loaded OK")
print("Step 2: Loading tokenizer.pickle...")
# NOTE: Make sure "tokenizer.pickle" is uploaded to jarvis0852/path-ils-bot!
tokenizer_path = fetch_from_hub("tokenizer.pickle")
with open(tokenizer_path, "rb") as f:
tokenizer = pickle.load(f)
print("Step 2 done")
print("Step 3: Loading label_encoder.pickle...")
le_path = fetch_from_hub("label_encoder.pickle")
with open(le_path, "rb") as f:
label_encoder = pickle.load(f)
print("Step 3 done")
print("Step 4: Loading responses_dict.pickle...")
resp_path = fetch_from_hub("responses_dict.pickle")
with open(resp_path, "rb") as f:
responses_dict = pickle.load(f)
print("Step 4 done")
print("Step 5: Loading intent_keywords.pickle...")
kw_path = fetch_from_hub("intent_keywords.pickle")
with open(kw_path, "rb") as f:
intent_keywords = pickle.load(f)
print("Step 5 done")
print("Step 6: Loading pattern_embeddings.pickle...")
embed_path = fetch_from_hub("pattern_embeddings.pickle")
# --- FIX FOR CUDA TO CPU DESERIALIZATION ERROR ---
import torch
torch.serialization._validate_device = lambda location, backend_name: torch.device('cpu')
# ------------------------------------------------
with open(embed_path, "rb") as f:
pattern_embeddings = pickle.load(f)
print("Step 6 done")
print("Step 7: Loading semantic_pattern_to_intent.pickle...")
sem_path = fetch_from_hub("semantic_pattern_to_intent.pickle")
with open(sem_path, "rb") as f:
semantic_pattern_to_intent = pickle.load(f)
print("Step 7 done")
print("Step 8: Loading SentenceTransformer('all-MiniLM-L6-v2')...")
embedder = SentenceTransformer('all-MiniLM-L6-v2')
print("Step 8 done: embedder loaded OK")
max_len = 25
print("Everything loaded successfully!")
# ----------------------------
# Typo fix + text cleaning
# ----------------------------
typo_fix = {
'hlo': 'hello', 'helo': 'hello', 'hii': 'hi', 'hey': 'hi',
'thanx': 'thanks', 'thnx': 'thanks', 'thx': 'thanks',
'plz': 'please', 'pls': 'please', 'u': 'you', 'ur': 'your',
'r': 'are', 'wat': 'what', 'wht': 'what', 'y': 'why'
}
def clean_text(text):
text = text.lower().strip()
words = text.split()
words = [typo_fix.get(w, w) for w in words]
text = " ".join(words)
text = re.sub(r"[^a-zA-Z0-9\s']", " ", text)
text = re.sub(r"\s+", " ", text).strip()
return text
# ----------------------------
# Prediction layers
# ----------------------------
def predict_lstm_raw(text):
seq = tokenizer.texts_to_sequences([text])
padded = pad_sequences(seq, maxlen=max_len, padding='post')
pred = model_lstm.predict(padded, verbose=0)[0]
idx = int(np.argmax(pred))
return label_encoder.inverse_transform([idx])[0], float(pred[idx])
def predict_keyword(text):
query_words = set(text.split())
scores = {}
for intent, keywords in intent_keywords.items():
overlap = len(query_words & keywords)
if overlap > 0:
scores[intent] = overlap
if not scores:
return None, 0
best_intent = max(scores, key=scores.get)
return best_intent, scores[best_intent]
def predict_semantic(text, threshold=0.45):
query_embedding = embedder.encode(text, convert_to_tensor=True)
scores = util.cos_sim(query_embedding, pattern_embeddings)[0]
best_idx = int(scores.argmax())
best_score = float(scores[best_idx])
if best_score < threshold:
return None, best_score
return semantic_pattern_to_intent[best_idx], best_score
def predict_intent_final(user_text):
text = clean_text(user_text)
lstm_intent, lstm_conf = predict_lstm_raw(text)
sem_intent, sem_score = predict_semantic(text)
kw_intent, kw_score = predict_keyword(text)
if sem_intent is not None and lstm_intent == sem_intent:
return lstm_intent, "LSTM+Semantic Agree", (lstm_conf + sem_score) / 2
if sem_intent is not None and sem_score >= 0.5:
return sem_intent, "Semantic", sem_score
if kw_intent is not None and kw_score >= 1:
return kw_intent, "Keyword", kw_score
if lstm_conf >= 0.9:
return lstm_intent, "LSTM-only (risky)", lstm_conf
return None, "None", 0
def chatbot_response(user_text):
intent, source, confidence = predict_intent_final(user_text)
if intent is None:
return "Sorry, mujhe samajh nahi aaya. Kya aap admission, fees, courses, ya contact details ke baare mein pooch rahe hain?"
return random.choice(responses_dict[intent])
# ----------------------------
# Routes
# ----------------------------
@app.route("/", methods=["GET"])
def health_check():
return jsonify({"status": "ILS Chatbot API is running!"})
@app.route("/chat", methods=["POST"])
def chat():
try:
user_message = request.json.get("message", "")
if not user_message.strip():
return jsonify({"response": "Kuch toh likho!"})
response = chatbot_response(user_message)
return jsonify({"response": response})
except Exception as e:
print(f"Error in /chat: {e}")
return jsonify({"response": "Kuch technical issue ho gaya, thodi der baad try karo."}), 500
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7860)