Spaces:
Building
Building
File size: 3,750 Bytes
e27e999 ed6b1d2 e27e999 22d1e2b e27e999 1abe985 e27e999 22d1e2b e27e999 22d1e2b e27e999 22d1e2b e27e999 22d1e2b 1abe985 22d1e2b 1abe985 22d1e2b e27e999 1abe985 22d1e2b e27e999 22d1e2b e27e999 22d1e2b e27e999 1abe985 e27e999 1abe985 e27e999 1abe985 22d1e2b e27e999 22d1e2b e27e999 1abe985 7e867e7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
import os
import logging
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from dotenv import load_dotenv
from langchain_groq import ChatGroq
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import SupabaseVectorStore
from supabase.client import create_client
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import create_retrieval_chain
# Load environment variables
load_dotenv()
# Router and logger
router = APIRouter()
logger = logging.getLogger("custom_chatbot")
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
# Validate GROQ API Key
groq_api_key = os.getenv("GROQ_API_KEY")
if not groq_api_key:
logger.error("β GROQ_API_KEY is not set in the environment.")
raise RuntimeError("GROQ_API_KEY must be set in .env or environment variables.")
# Supabase Initialization
supabase_url = os.getenv("SUPABASE_URL")
supabase_key = os.getenv("SUPABASE_KEY")
if not supabase_url or not supabase_key:
logger.error("β SUPABASE_URL or SUPABASE_KEY is not set in the environment.")
raise RuntimeError("SUPABASE_URL and SUPABASE_KEY must be set in .env or environment variables.")
try:
supabase_client = create_client(supabase_url, supabase_key)
logger.info("β
Supabase client initialized successfully.")
except Exception as e:
logger.exception("β Failed to initialize Supabase client.")
raise
# LLM Initialization
try:
llm = ChatGroq(groq_api_key=groq_api_key, model_name="llama-3.3-70b-versatile")
logger.info("β
ChatGroq LLM initialized successfully.")
except Exception as e:
logger.exception("β Failed to initialize ChatGroq LLM.")
raise
# Prompt Template
prompt_template = ChatPromptTemplate.from_template("""
Answer the question based only on the provided context.
<context>
{context}
</context>
Question: {input}
""")
generic_prompt_template = ChatPromptTemplate.from_template("""
You are a helpful AI assistant. Answer the following question:
<context>
{context}
</context>
Question: {input}
""")
# Input schema
class ChatRequest(BaseModel):
query: str
user_id: int
# Main chatbot endpoint
@router.post("/custom-chatbot")
async def custom_chatbot(request: ChatRequest):
query = request.query
user_id = request.user_id
logger.info(f"π€ Received query from user {user_id}: {query}")
try:
embeddings = OpenAIEmbeddings()
# Changed table_name and query_name to fixed values, and added filter to query
vector_store = SupabaseVectorStore(client=supabase_client, embedding=embeddings, table_name="documents", query_name="match_documents")
retriever = vector_store.as_retriever(search_kwargs={"filter": {"user_id": user_id}})
doc_chain = create_stuff_documents_chain(llm, prompt_template)
rag_chain = create_retrieval_chain(retriever, doc_chain)
response = rag_chain.invoke({"input": query})
logger.info(f"β
Response generated for user {user_id} using RAG.")
return {
"answer": response["answer"],
"sources": [doc.page_content for doc in response.get("context", [])],
}
except Exception as e:
logger.warning(f"π€· Falling back to generic response due to: {e}")
generic_chain = create_stuff_documents_chain(llm, generic_prompt_template)
generic_response = generic_chain.invoke({"input": query, "context": []}) # Pass empty context for generic response
return {
"answer": generic_response,
"sources": []
}
|