NajmAI / app.py
Amjad1m's picture
Upload 2 files
d51ec5c verified
Raw
History Blame Contribute Delete
3 kB
import numpy as np
import faiss, torch, gradio as gr
from sentence_transformers import SentenceTransformer
from transformers import AutoTokenizer, AutoModelForCausalLM
DOCS = [
"The Generative AI Summer Bootcamp at Najran University runs for three weeks.",
"Week 1 covers the foundations of generative AI and prompt engineering.",
"Week 2 focuses on large language models, embeddings, and retrieval-augmented generation.",
"Week 3 covers multimodal AI: vision, audio, and image generation.",
"The bootcamp prepares students for the NVIDIA NCA-GENL and NCA-GENM associate exams.",
"The NCA-GENL exam has 50 to 60 questions and a time limit of one hour.",
"Students need a free Google Colab account and a free Hugging Face account.",
"The refund policy: tuition is fully refundable up to seven days before the start date.",
"All lab notebooks run on a free Colab T4 GPU with about 15 GB of memory.",
"Certificates are issued to students who complete every hands-on lab.",
]
embedder = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
emb = np.asarray(embedder.encode(DOCS, normalize_embeddings=True), dtype="float32")
index = faiss.IndexFlatIP(emb.shape[1]); index.add(emb)
GEN_ID = "Qwen/Qwen2.5-1.5B-Instruct"
tokenizer = AutoTokenizer.from_pretrained(GEN_ID)
model = AutoModelForCausalLM.from_pretrained(GEN_ID, torch_dtype=torch.float32)
def retrieve(query, k=3):
q = np.asarray(embedder.encode([query], normalize_embeddings=True), dtype="float32")
scores, idxs = index.search(q, k)
return [(DOCS[i], float(s)) for i, s in zip(idxs[0], scores[0])]
def generate(prompt, max_new_tokens=256):
msgs = [{"role": "user", "content": prompt}]
inp = tokenizer.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt")
out = model.generate(inp, max_new_tokens=max_new_tokens, do_sample=False,
pad_token_id=tokenizer.eos_token_id)
return tokenizer.decode(out[0][inp.shape[1]:], skip_special_tokens=True).strip()
def rag_answer(question, k=3, min_score=0.15):
chunks = retrieve(question, k=k)
if not chunks or chunks[0][1] < min_score:
return "I dont know. (No relevant context was found.)", []
ctx = "\n".join(f"[{i+1}] {t}" for i, (t, _) in enumerate(chunks))
prompt = ("Answer using ONLY the context below. If the answer is not in the context, "
"say: I dont know. Cite sources like [1], [2].\n\n"
f"Context:\n{ctx}\n\nQuestion: {question}\n\nAnswer:")
return generate(prompt), [t for t, _ in chunks]
def chat_fn(question):
answer, sources = rag_answer(question)
srcs = "\n".join(f"{i}. {s}" for i, s in enumerate(sources, 1)) or "(none)"
return answer, srcs
demo = gr.Interface(
fn=chat_fn,
inputs=gr.Textbox(label="Ask about the bootcamp"),
outputs=[gr.Textbox(label="Answer"), gr.Textbox(label="Sources")],
title="Najran Bootcamp RAG Chatbot",
)
if __name__ == "__main__":
demo.launch()