File size: 3,237 Bytes
1c1f14a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d44db5a
1c1f14a
 
 
 
 
 
 
 
 
d44db5a
 
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import requests
import fitz
import numpy as np
import faiss
from sentence_transformers import SentenceTransformer
from groq import Groq
import gradio as gr
import os

# =========================
# 1. LOAD API KEY (HF SECRET)
# =========================
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
client = Groq(api_key=GROQ_API_KEY)

# =========================
# 2. LOAD PDF
# =========================
pdf_url = "https://huggingface.co/datasets/HuzaifaTech/rag_file/resolve/main/Hands_On_Machine_Learning_with_Scikit_Le.pdf"

pdf_path = "file.pdf"

if not os.path.exists(pdf_path):
    response = requests.get(pdf_url)
    with open(pdf_path, "wb") as f:
        f.write(response.content)

# =========================
# 3. EXTRACT TEXT
# =========================
doc = fitz.open(pdf_path)
text = ""

for page in doc:
    text += page.get_text()

# =========================
# 4. CHUNKING
# =========================
def chunk_text(text, chunk_size=800):
    paragraphs = text.split("\n")
    chunks = []
    current = ""

    for para in paragraphs:
        if len(current) + len(para) < chunk_size:
            current += para + "\n"
        else:
            chunks.append(current.strip())
            current = para

    if current:
        chunks.append(current.strip())

    return chunks

chunks = chunk_text(text)[:300]

# =========================
# 5. EMBEDDINGS
# =========================
model = SentenceTransformer("all-MiniLM-L6-v2")

embeddings = model.encode(chunks, batch_size=32)
faiss.normalize_L2(embeddings)

# =========================
# 6. FAISS
# =========================
dim = embeddings.shape[1]
index = faiss.IndexFlatL2(dim)
index.add(embeddings)

# =========================
# 7. RETRIEVAL
# =========================
def retrieve(query, k=4):
    q_emb = model.encode([query])
    faiss.normalize_L2(q_emb)
    _, idx = index.search(q_emb, k)
    return [chunks[i] for i in idx[0]]

# =========================
# 8. GENERATION
# =========================
def generate_answer(query):
    docs = retrieve(query)
    context = "\n\n".join(docs)

    prompt = f"""
Context:
{context}

Question:
{query}
"""

    try:
        res = client.chat.completions.create(
            model="llama-3.3-70b-versatile",
            messages=[
                {
                    "role": "system",
                    "content": "Answer ONLY from the provided context. If not found, say 'I don't know'."
                },
                {
                    "role": "user",
                    "content": prompt
                }
            ],
            temperature=0,
            max_tokens=500
        )
        return res.choices[0].message.content

    except Exception as e:
        return f"Error: {str(e)}"

# =========================
# 9. UI (PROFESSIONAL)
# =========================
def chat(message, history):
    return generate_answer(message)

with gr.Blocks() as demo:
    gr.Markdown("# 📚 RAG Chatbot (ML Book)")
    gr.Markdown("Ask questions from *Hands-On Machine Learning* PDF")

    chatbot = gr.ChatInterface(
        fn=chat,
        chatbot=gr.Chatbot(height=400),
        textbox=gr.Textbox(placeholder="Ask a question...", container=False),
    )

demo.launch(theme=gr.themes.Soft())