Spaces:
Sleeping
Sleeping
| from flask import Flask, render_template, jsonify, request | |
| from src.helper import download_hugging_face_embeddings | |
| from langchain_pinecone import PineconeVectorStore | |
| from langchain_google_genai import ChatGoogleGenerativeAI | |
| from langchain.chains import create_retrieval_chain | |
| from langchain.chains.combine_documents import create_stuff_documents_chain | |
| from langchain_core.prompts import ChatPromptTemplate | |
| from dotenv import load_dotenv | |
| from src.prompt import * | |
| import os | |
| import traceback | |
| app = Flask(__name__) | |
| load_dotenv(override=True) | |
| PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY") | |
| GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY") | |
| os.environ["PINECONE_API_KEY"] = PINECONE_API_KEY | |
| if GOOGLE_API_KEY: | |
| os.environ["GOOGLE_API_KEY"] = GOOGLE_API_KEY | |
| embeddings = download_hugging_face_embeddings() | |
| index_name = os.environ.get("PINECONE_INDEX_NAME", "student-chatbot") | |
| # Embed each chunk and upsert the embeddings into your Pinecone index. | |
| docsearch = PineconeVectorStore.from_existing_index( | |
| index_name=index_name, embedding=embeddings | |
| ) | |
| retriever = docsearch.as_retriever(search_type="similarity", search_kwargs={"k": 3}) | |
| chatModel = ChatGoogleGenerativeAI( | |
| model="gemini-2.5-flash", | |
| temperature=0, | |
| max_retries=2, | |
| ) | |
| prompt = ChatPromptTemplate.from_messages( | |
| [ | |
| ("system", system_prompt), | |
| ("human", "{input}"), | |
| ] | |
| ) | |
| question_answer_chain = create_stuff_documents_chain(chatModel, prompt) | |
| rag_chain = create_retrieval_chain(retriever, question_answer_chain) | |
| def build_context_fallback_answer(user_query: str) -> str: | |
| """Return a best-effort answer using retrieved context only (no LLM call).""" | |
| try: | |
| docs = retriever.invoke(user_query) | |
| except Exception: | |
| return "Gemini quota is reached, and I could not fetch context right now. Please try again shortly." | |
| if not docs: | |
| return "Gemini quota is reached, and I could not find relevant context for this question right now." | |
| top_doc_text = (docs[0].page_content or "").strip() | |
| if not top_doc_text: | |
| return "Gemini quota is reached, but retrieved context is empty. Please try again later." | |
| answer_line = None | |
| for line in top_doc_text.splitlines(): | |
| if line.lower().startswith("answer:"): | |
| answer_line = line.split(":", 1)[1].strip() | |
| break | |
| if answer_line: | |
| return f"Gemini quota reached, so I am answering from stored context: {answer_line}" | |
| snippet = " ".join( | |
| part.strip() for part in top_doc_text.splitlines() if part.strip() | |
| ) | |
| snippet = snippet[:450] | |
| return "Gemini quota reached, so I am answering from stored context: " f"{snippet}" | |
| def index(): | |
| return render_template("chat.html") | |
| def chat(): | |
| msg = request.values.get("msg", "").strip() | |
| if not msg: | |
| return "Please enter a question.", 200 | |
| print(msg) | |
| if not GOOGLE_API_KEY: | |
| return ( | |
| "GOOGLE_API_KEY is missing. Add it to your .env file and restart the app.", | |
| 200, | |
| ) | |
| try: | |
| response = rag_chain.invoke({"input": msg}) | |
| answer = response.get("answer") if isinstance(response, dict) else None | |
| if not answer: | |
| return ( | |
| "I could not generate a response right now. Please try rephrasing your question.", | |
| 200, | |
| ) | |
| print("Response : ", answer) | |
| return str(answer), 200 | |
| except Exception as e: | |
| print("Error: ", str(e)) | |
| traceback.print_exc() | |
| error_text = str(e).lower() | |
| if ( | |
| "api key" in error_text | |
| or "permission" in error_text | |
| or "unauthorized" in error_text | |
| ): | |
| return ( | |
| "Your Gemini API key is invalid or missing permissions. Please verify GOOGLE_API_KEY.", | |
| 200, | |
| ) | |
| if "quota" in error_text or "rate" in error_text or "429" in error_text: | |
| fallback_answer = build_context_fallback_answer(msg) | |
| return fallback_answer, 200 | |
| return ( | |
| "I am having trouble reaching the AI service right now. Please try again in a few seconds.", | |
| 200, | |
| ) | |
| if __name__ == "__main__": | |
| port = int(os.environ.get("PORT", 7860)) | |
| app.run(host="0.0.0.0", port=port, debug=False) | |