|
|
import faiss |
|
|
import pickle |
|
|
import os |
|
|
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline |
|
|
from langchain.llms import HuggingFacePipeline |
|
|
from langchain.vectorstores import FAISS as LangChainFAISS |
|
|
from langchain.docstore import InMemoryDocstore |
|
|
from langchain.schema import Document |
|
|
from langchain.chains import RetrievalQA |
|
|
import gradio as gr |
|
|
|
|
|
|
|
|
vector_path = "vector_store_faiss_chroma/faiss_index.index" |
|
|
metadata_path = "vector_store_faiss_chroma/metadata.pkl" |
|
|
|
|
|
model_path = "tiiuae/Falcon3-1B-Instruct" |
|
|
|
|
|
|
|
|
faiss_index = faiss.read_index(f"{vector_path}") |
|
|
|
|
|
|
|
|
with open(f"{metadata_path}", "rb") as f: |
|
|
metadata = pickle.load(f) |
|
|
|
|
|
|
|
|
docs = [Document(page_content=doc["page_content"]) for doc in metadata] |
|
|
|
|
|
|
|
|
docstore = InMemoryDocstore({str(i): docs[i] for i in range(len(docs))}) |
|
|
id_map = {i: str(i) for i in range(len(docs))} |
|
|
|
|
|
|
|
|
tokenizer = AutoTokenizer.from_pretrained(model_path) |
|
|
model = AutoModelForCausalLM.from_pretrained(model_path) |
|
|
|
|
|
|
|
|
text_generator_pipeline = pipeline( |
|
|
model=model, |
|
|
tokenizer=tokenizer, |
|
|
task="text-generation", |
|
|
return_full_text=False, |
|
|
max_new_tokens=512, |
|
|
temperature=0.2 |
|
|
) |
|
|
|
|
|
llm = HuggingFacePipeline(pipeline=text_generator_pipeline) |
|
|
|
|
|
|
|
|
embed_fn = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") |
|
|
|
|
|
|
|
|
vectorstore_faiss = LangChainFAISS( |
|
|
index=faiss_index, |
|
|
docstore=docstore, |
|
|
index_to_docstore_id=id_map, |
|
|
embedding_function=embed_fn |
|
|
) |
|
|
|
|
|
|
|
|
retriever = vectorstore_faiss.as_retriever(search_kwargs={"k": 3}) |
|
|
|
|
|
|
|
|
qa_chain = RetrievalQA.from_chain_type( |
|
|
llm=llm, |
|
|
chain_type="stuff", |
|
|
retriever=retriever, |
|
|
return_source_documents=True |
|
|
) |
|
|
|
|
|
|
|
|
def ask_rag(query): |
|
|
result = qa_chain({"query": query}) |
|
|
answer = result["result"] |
|
|
|
|
|
|
|
|
sources = result.get("source_documents", []) |
|
|
source_texts = "\n\n".join([f"πΉ Source {i+1}:\n{doc.page_content[:300]}..." for i, doc in enumerate(sources[:2])]) |
|
|
|
|
|
return f"π Answer:\n{answer}\n\nπ Sources:\n{source_texts}" |
|
|
|
|
|
|
|
|
gr.Interface( |
|
|
fn=ask_rag, |
|
|
inputs=gr.Textbox(lines=2, placeholder="Ask me about UCT admissions, housing, fees..."), |
|
|
outputs="text", |
|
|
title="π University of Cape Town Course Advisor Chatbot", |
|
|
description="Ask academic questions. Powered by FAISS + Falcon-E-1B + LangChain.", |
|
|
allow_flagging="never" |
|
|
).launch() |