manaskhan commited on
Commit
1fcc803
·
verified ·
1 Parent(s): cc62f17

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -0
app.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import faiss
4
+ import numpy as np
5
+ from groq import Groq
6
+ from sentence_transformers import SentenceTransformer
7
+ from PyPDF2 import PdfReader
8
+ import requests
9
+ from io import BytesIO
10
+
11
+ # -------- SETTINGS --------
12
+ EMBED_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
13
+ INDEX_FILE = "faiss_index.bin"
14
+ CHUNKS_FILE = "chunks.npy"
15
+ CHUNK_SIZE = 500
16
+ TOP_K = 3
17
+
18
+ # ASME PDF URLs (fixed for this app)
19
+ PDF_URLS = [
20
+ "https://www.asme.org/wwwasmeorg/media/resourcefiles/aboutasme/who%20we%20are/standards_and_certification/asme_codes_and_standards-examples_of_use_for_mechanical_engineering_students.pdf",
21
+ "https://www.asme.org/wwwasmeorg/media/resourcefiles/campaigns/marketing/2012/the-state-of-mechanical-engineering-survey.pdf"
22
+ ]
23
+
24
+ # Load embedding model
25
+ embedder = SentenceTransformer(EMBED_MODEL)
26
+ embed_dim = embedder.get_sentence_embedding_dimension()
27
+
28
+ # Initialize or load FAISS + chunks
29
+ if os.path.exists(INDEX_FILE) and os.path.exists(CHUNKS_FILE):
30
+ index = faiss.read_index(INDEX_FILE)
31
+ chunks = np.load(CHUNKS_FILE, allow_pickle=True).tolist()
32
+ else:
33
+ index = faiss.IndexFlatL2(embed_dim)
34
+ chunks = []
35
+
36
+ # Groq client
37
+ client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
38
+
39
+ # -------- FUNCTIONS --------
40
+ def pdf_url_to_chunks(pdf_url, chunk_size=CHUNK_SIZE):
41
+ resp = requests.get(pdf_url)
42
+ resp.raise_for_status()
43
+ pdf_bytes = BytesIO(resp.content)
44
+ reader = PdfReader(pdf_bytes)
45
+ text_all = ""
46
+ for page in reader.pages:
47
+ page_text = page.extract_text()
48
+ if page_text:
49
+ text_all += page_text + " "
50
+ words = text_all.split()
51
+ return [
52
+ " ".join(words[i:i+chunk_size])
53
+ for i in range(0, len(words), chunk_size)
54
+ if len(words[i:i+chunk_size]) > 20
55
+ ]
56
+
57
+ def build_vector_db():
58
+ global index, chunks
59
+ if len(chunks) > 0:
60
+ return f"✅ Knowledge base already built with {len(chunks)} chunks."
61
+ new_chunks = []
62
+ for url in PDF_URLS:
63
+ url_chunks = pdf_url_to_chunks(url)
64
+ new_chunks.extend(url_chunks)
65
+ embeddings = embedder.encode(new_chunks, convert_to_numpy=True)
66
+ index.add(embeddings)
67
+ chunks.extend(new_chunks)
68
+ faiss.write_index(index, INDEX_FILE)
69
+ np.save(CHUNKS_FILE, np.array(chunks, dtype=object))
70
+ return f"✅ Knowledge base built with {len(chunks)} chunks."
71
+
72
+ def retrieve_chunks(query, top_k=TOP_K):
73
+ if len(chunks) == 0:
74
+ return []
75
+ query_vec = embedder.encode([query], convert_to_numpy=True)
76
+ distances, indices = index.search(query_vec, top_k)
77
+ return [chunks[i] for i in indices[0] if i < len(chunks)]
78
+
79
+ def ask_with_rag(query):
80
+ if len(chunks) == 0:
81
+ return "⚠️ Please build the knowledge base first."
82
+ retrieved = retrieve_chunks(query)
83
+ context = "\n\n".join(retrieved)
84
+ prompt = f"""You are an assistant knowledgeable in ASME Standards.
85
+ Context:
86
+ {context}
87
+
88
+ User Query:
89
+ {query}
90
+
91
+ Answer using the context. If not found, reply: “I could not find it in the provided ASME documents.”"""
92
+
93
+ chat_completion = client.chat.completions.create(
94
+ messages=[{"role": "user", "content": prompt}],
95
+ model="llama-3.3-70b-versatile",
96
+ )
97
+ return chat_completion.choices[0].message.content
98
+
99
+ # -------- GRADIO UI --------
100
+ with gr.Blocks() as demo:
101
+ gr.Markdown("# 📘 ASME RAG Assistant")
102
+ gr.Markdown("This app is powered by FAISS + Groq LLM. Knowledge base is built from 2 official ASME PDFs.")
103
+
104
+ build_btn = gr.Button("Build Knowledge Base")
105
+ build_status = gr.Textbox(label="Status")
106
+
107
+ build_btn.click(build_vector_db, inputs=None, outputs=build_status)
108
+
109
+ query_input = gr.Textbox(label="Ask a Question", lines=1)
110
+ answer_output = gr.Textbox(label="Answer", lines=5)
111
+ query_btn = gr.Button("Ask")
112
+
113
+ query_btn.click(ask_with_rag, inputs=query_input, outputs=answer_output)
114
+
115
+ demo.launch()