My_Self_Bot / src /rag.py
BOB0920's picture
Update src/rag.py
f76308d verified
Raw
History Blame Contribute Delete
4.13 kB
import os
from functools import lru_cache
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_community.vectorstores import FAISS
from dotenv import load_dotenv
load_dotenv()
# Use absolute path relative to this file's location
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
DB_FAISS_PATH = os.path.join(SCRIPT_DIR, "vectorstore", "db_faiss")
# Global cache for embeddings and database
_embeddings = None
_db = None
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
@lru_cache(maxsize=1)
def get_embeddings():
"""Load embeddings model once and cache it"""
try:
from langchain_huggingface import HuggingFaceEmbeddings
return HuggingFaceEmbeddings(
model_name='sentence-transformers/all-MiniLM-L6-v2',
model_kwargs={'device': 'cpu'}
)
except Exception as e:
raise ImportError(f"Failed to load HuggingFaceEmbeddings: {e}")
def get_vector_db():
"""Load vector database once and cache it"""
global _db
if _db is None:
try:
embeddings = get_embeddings()
_db = FAISS.load_local(DB_FAISS_PATH, embeddings, allow_dangerous_deserialization=True)
except Exception as e:
raise RuntimeError(f"Error loading FAISS index: {e}\n(Did you run ingest.py?)")
return _db
def get_answer(query, status_placeholder=None):
"""Get answer for query. status_placeholder is an optional st.empty() for status updates."""
def update_status(text):
if status_placeholder:
status_placeholder.markdown(text)
# Load cached embeddings and database
try:
update_status("πŸ” *Searching knowledge base...*")
db = get_vector_db()
except Exception as e:
return f"❌ Database error: {str(e)}"
# Setup LLM
try:
update_status("πŸ€– *Connecting to AI...*")
llm = ChatOpenAI(
model="google/gemini-2.5-flash",
api_key=os.getenv("OPENROUTER_API_KEY"),
base_url="https://openrouter.ai/api/v1",
temperature=0.7,
timeout=30,
max_tokens=2000,
)
except Exception as e:
return f"❌ LLM init error: {str(e)}"
# Define Prompt
template = """You are Sagar's personal assistant! 🌟 You're a friendly, warm, and always helpful AI assistant.
Your personality traits:
- You're enthusiastic and positive! 😊
- You use emojis naturally in your responses to make conversations more engaging πŸŽ‰
- You're helpful and always try your best to assist
- You speak in a warm, conversational tone like a good friend would
- You're supportive and encouraging πŸ’ͺ
Answer questions based on the following context about Sagar:
{context}
Guidelines:
1. Answer based on the provided context about Sagar.
2. Be friendly, warm, and use emojis naturally throughout your response! πŸ˜„
3. Keep your responses conversational and engaging.
4. If the answer is not in the context, say something like: "Hmm, I don't have that info yet! πŸ€” But you can always reach out to Sagar directly at sagar_rathi@zohomail.in πŸ“§"
5. Do not make up facts - only share what's in the context.
6. Make the person feel welcome and helped! ✨
Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
# Create LCEL Chain
update_status("πŸ“š *Finding relevant info...*")
retriever = db.as_retriever()
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
update_status("οΏ½ *Thinking...*")
try:
response = rag_chain.invoke(query)
# Clear the status when done
if status_placeholder:
status_placeholder.empty()
return response
except Exception as e:
return f"❌ API call error: {str(e)}"