# 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)