Spaces:
Sleeping
Sleeping
rombak
Browse files- app.py +226 -264
- requirements.txt +6 -7
app.py
CHANGED
@@ -1,279 +1,241 @@
|
|
1 |
-
|
2 |
import gradio as gr
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
5 |
from langchain_community.embeddings import HuggingFaceEmbeddings
|
6 |
from langchain_community.vectorstores import FAISS
|
7 |
-
from langchain_community.llms import HuggingFaceHub
|
8 |
from langchain.chains import RetrievalQA
|
9 |
-
from
|
10 |
-
from
|
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 |
-
max_results=max_results,
|
40 |
-
sort_by=arxiv.SortCriterion.Relevance,
|
41 |
-
sort_order=arxiv.SortOrder.Descending
|
42 |
-
)
|
43 |
-
|
44 |
-
papers = []
|
45 |
-
try:
|
46 |
-
for result in client.results(search_query):
|
47 |
-
# Menggabungkan judul, abstrak, dan penulis sebagai konten dokumen
|
48 |
-
# Anda bisa memilih untuk mengunduh full text jika diperlukan,
|
49 |
-
# namun abstrak biasanya cukup untuk RAG awal.
|
50 |
-
content = f"Title: {result.title}\nAuthors: {', '.join([a.name for a in result.authors])}\nAbstract: {result.summary}"
|
51 |
|
52 |
-
#
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
"
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
num_arxiv_papers = 5 # Jumlah paper yang ingin diambil
|
72 |
-
documents = fetch_papers_from_arxiv(arxiv_search_query, num_arxiv_papers)
|
73 |
-
|
74 |
-
# Jika tidak ada dokumen yang diambil, gunakan dummy data sebagai fallback
|
75 |
-
if not documents:
|
76 |
-
print("Tidak ada paper yang diambil dari arXiv. Menggunakan dummy data sebagai fallback.")
|
77 |
-
dummy_ai_papers_content = [
|
78 |
-
"""
|
79 |
-
Paper Title: Deep Learning for Natural Language Processing: A Review
|
80 |
-
Abstract: This paper reviews the advancements in deep learning techniques applied to Natural Language Processing (NLP). We discuss various architectures such as Recurrent Neural Networks (RNNs), Convolutional Neural Networks (CNNs), and Transformers, highlighting their impact on tasks like machine translation, sentiment analysis, and text summarization. The rise of large language models (LLMs) has significantly pushed the boundaries of what's possible in NLP.
|
81 |
-
Keywords: Deep Learning, NLP, Transformers, RNN, CNN, LLM, Machine Translation, Sentiment Analysis.
|
82 |
-
""",
|
83 |
-
"""
|
84 |
-
Paper Title: Reinforcement Learning in Robotics: Challenges and Future Directions
|
85 |
-
Abstract: Reinforcement Learning (RL) has shown promise in enabling robots to learn complex behaviors through interaction with their environment. This paper explores the current challenges in applying RL to robotics, including sample efficiency, sim-to-real transfer, and safety. We also discuss potential future directions and the integration of RL with other AI paradigms like computer vision.
|
86 |
-
Keywords: Reinforcement Learning, Robotics, AI, Sample Efficiency, Sim-to-Real, Computer Vision.
|
87 |
-
""",
|
88 |
"""
|
89 |
-
|
90 |
-
|
91 |
-
Keywords: Explainable AI, XAI, Interpretability, LIME, SHAP, Healthcare AI, Finance AI.
|
92 |
-
""",
|
93 |
"""
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
"""
|
99 |
-
|
100 |
-
|
101 |
-
Keywords: GANs, Generative Models, Image Synthesis, Anomaly Detection, Neural Networks.
|
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 |
-
|
138 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
139 |
)
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
def __call__(self, prompt, **kwargs):
|
146 |
-
return self.invoke(prompt, **kwargs)
|
147 |
-
llm = DummyLLM()
|
148 |
-
print("Menggunakan DummyLLM karena HUGGINGFACEHUB_API_TOKEN tidak disetel.")
|
149 |
-
|
150 |
-
|
151 |
-
# --- 6. Membuat Chain RAG (RetrievalQA) ---
|
152 |
-
# Chain ini akan mengambil dokumen yang relevan dan meneruskannya ke LLM untuk menghasilkan jawaban.
|
153 |
-
qa_chain = RetrievalQA.from_chain_type(
|
154 |
-
llm=llm,
|
155 |
-
chain_type="stuff", # "stuff" menggabungkan semua dokumen ke dalam satu prompt
|
156 |
-
retriever=vectorstore.as_retriever(),
|
157 |
-
return_source_documents=True, # Untuk melihat dokumen sumber yang diambil
|
158 |
-
)
|
159 |
-
|
160 |
-
# --- 7. Membuat Agentic RAG Logic ---
|
161 |
-
# Kita akan membuat "tool" yang membungkus chain RAG kita.
|
162 |
-
# Agent kemudian dapat memutuskan kapan harus menggunakan tool ini.
|
163 |
-
tool_description = (
|
164 |
-
"Berguna untuk menjawab pertanyaan tentang paper Artificial Intelligence, "
|
165 |
-
"termasuk konsep, metodologi, tantangan, dan aplikasi yang dibahas dalam paper."
|
166 |
-
"Gunakan tool ini untuk mengambil informasi dari basis pengetahuan paper AI."
|
167 |
-
)
|
168 |
-
|
169 |
-
tools = [
|
170 |
-
Tool(
|
171 |
-
name="AI_Paper_Retriever",
|
172 |
-
func=qa_chain.invoke, # Menggunakan .invoke() untuk Langchain Expression Language
|
173 |
-
description=tool_description,
|
174 |
-
return_direct=False # Agent akan memproses output tool ini
|
175 |
)
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
content=(
|
185 |
-
"Anda adalah asisten AI yang sangat membantu dan berpengetahuan luas, "
|
186 |
-
"khususnya dalam bidang Artificial Intelligence dan paper penelitian terkait."
|
187 |
-
"Tugas utama Anda adalah membantu pengguna memahami dan menavigasi informasi dari paper AI."
|
188 |
-
"Gunakan tool 'AI_Paper_Retriever' jika pertanyaan pengguna berkaitan dengan konten paper AI "
|
189 |
-
"atau memerlukan informasi spesifik dari basis pengetahuan Anda."
|
190 |
-
"Jika pertanyaan bersifat umum atau tidak memerlukan pengambilan data, jawablah langsung."
|
191 |
-
"Selalu berikan jawaban yang komprehensif dan relevan."
|
192 |
-
)
|
193 |
-
),
|
194 |
-
MessagesPlaceholder(variable_name="chat_history"),
|
195 |
-
("human", "{input}"),
|
196 |
-
MessagesPlaceholder(variable_name="tools"),
|
197 |
-
MessagesPlaceholder(variable_name="agent_scratchpad"),
|
198 |
-
MessagesPlaceholder(variable_name="tool_names"),
|
199 |
-
]
|
200 |
-
)
|
201 |
-
|
202 |
-
# Membuat Agent
|
203 |
-
# Menggunakan create_react_agent untuk agent yang berbasis ReAct
|
204 |
-
agent = create_react_agent(llm, tools, agent_prompt)
|
205 |
-
|
206 |
-
# Membuat Agent Executor
|
207 |
-
# Ini adalah runtime untuk agent, yang menjalankan loop pemikiran-aksi.
|
208 |
-
agent_executor = AgentExecutor(
|
209 |
-
agent=agent,
|
210 |
-
tools=tools,
|
211 |
-
verbose=True, # Untuk melihat langkah-langkah pemikiran agent
|
212 |
-
handle_parsing_errors=True, # Menangani kesalahan parsing agent
|
213 |
-
max_iterations=5 # Batasi iterasi untuk menghindari loop tak terbatas
|
214 |
-
)
|
215 |
-
|
216 |
-
# --- 8. Gradio Interface ---
|
217 |
-
# Fungsi untuk memproses pertanyaan pengguna menggunakan agent
|
218 |
-
def process_query(query, chat_history_tuples):
|
219 |
-
# Mengubah riwayat chat dari Gradio ke format Langchain
|
220 |
-
from langchain_core.messages import HumanMessage, AIMessage
|
221 |
-
formatted_chat_history = []
|
222 |
-
for human_msg, ai_msg in chat_history_tuples:
|
223 |
-
formatted_chat_history.append(HumanMessage(content=human_msg))
|
224 |
-
formatted_chat_history.append(AIMessage(content=ai_msg))
|
225 |
-
|
226 |
-
try:
|
227 |
-
# Panggil agent executor
|
228 |
-
response = agent_executor.invoke({
|
229 |
-
"input": query,
|
230 |
-
"chat_history": formatted_chat_history
|
231 |
-
})
|
232 |
-
answer = response["output"]
|
233 |
-
|
234 |
-
# Jika agent menggunakan tool RAG, kita bisa menampilkan sumbernya juga
|
235 |
-
# Ini memerlukan sedikit modifikasi jika Anda ingin menampilkan sumber
|
236 |
-
# secara eksplisit dari dalam agent_executor.invoke().
|
237 |
-
# Untuk kesederhanaan, kita hanya akan menampilkan jawaban agent.
|
238 |
-
# Jika Anda ingin menampilkan sumber, Anda perlu memodifikasi tool
|
239 |
-
# atau agent_executor untuk mengembalikan informasi sumber secara eksplisit.
|
240 |
-
|
241 |
-
except Exception as e:
|
242 |
-
answer = f"Terjadi kesalahan saat memproses pertanyaan: {e}"
|
243 |
-
if "HUGGINGFACEHUB_API_TOKEN" not in os.environ:
|
244 |
-
answer += "\nPastikan HUGGINGFACEHUB_API_TOKEN Anda disetel dengan benar."
|
245 |
-
|
246 |
-
return answer
|
247 |
-
|
248 |
-
# Membuat antarmuka Gradio
|
249 |
-
with gr.Blocks() as demo:
|
250 |
-
gr.Markdown("# Agentic RAG untuk Literasi Paper AI")
|
251 |
-
gr.Markdown("Tanyakan apa pun tentang paper AI yang diambil dari arXiv.")
|
252 |
-
|
253 |
-
chatbot = gr.Chatbot(label="Percakapan")
|
254 |
-
msg = gr.Textbox(label="Pertanyaan Anda")
|
255 |
-
clear = gr.Button("Clear")
|
256 |
-
|
257 |
-
def user_message(user_message, history):
|
258 |
-
return "", history + [[user_message, None]]
|
259 |
-
|
260 |
-
def bot_response(history):
|
261 |
-
query = history[-1][0]
|
262 |
-
# Mengirimkan riwayat chat tanpa respons bot terakhir yang masih None
|
263 |
-
chat_history_for_agent = history[:-1]
|
264 |
-
response = process_query(query, chat_history_for_agent)
|
265 |
-
history[-1][1] = response
|
266 |
-
return history
|
267 |
-
|
268 |
-
msg.submit(user_message, [msg, chatbot], [msg, chatbot], queue=False).then(
|
269 |
-
bot_response, chatbot, chatbot
|
270 |
)
|
271 |
-
clear.click(lambda: None, None, chatbot, queue=False)
|
272 |
|
273 |
-
#
|
274 |
-
# Untuk menjalankan di Hugging Face Spaces, Anda mungkin perlu mengatur share=True
|
275 |
-
# atau cukup jalankan tanpa share=True jika sudah di dalam lingkungan Space.
|
276 |
if __name__ == "__main__":
|
277 |
-
print("
|
278 |
-
|
279 |
-
|
|
|
|
1 |
+
# app.py
|
2 |
import gradio as gr
|
3 |
+
import os
|
4 |
+
import re
|
5 |
+
import shutil
|
6 |
+
import torch
|
7 |
+
|
8 |
+
# LangChain imports
|
9 |
+
from langchain_community.document_loaders import ArxivLoader, PyPDFLoader
|
10 |
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
11 |
from langchain_community.embeddings import HuggingFaceEmbeddings
|
12 |
from langchain_community.vectorstores import FAISS
|
|
|
13 |
from langchain.chains import RetrievalQA
|
14 |
+
from langchain_community.llms import HuggingFacePipeline
|
15 |
+
from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
|
16 |
+
|
17 |
+
# --- Configuration ---
|
18 |
+
ARXIV_DIR = "./arxiv_papers" # Directory to save downloaded papers
|
19 |
+
CHUNK_SIZE = 500 # Characters per chunk
|
20 |
+
CHUNK_OVERLAP = 50 # Overlap between chunks
|
21 |
+
EMBEDDING_MODEL_NAME = 'all-MiniLM-L6-v2'
|
22 |
+
LLM_MODEL_NAME = "google/flan-t5-small"
|
23 |
+
|
24 |
+
# --- RAGAgent Class ---
|
25 |
+
|
26 |
+
class RAGAgent:
|
27 |
+
def __init__(self):
|
28 |
+
self.embedding_model = None
|
29 |
+
self.llm = None
|
30 |
+
self.vectorstore = None
|
31 |
+
self.qa_chain = None
|
32 |
+
self.is_initialized = False
|
33 |
+
|
34 |
+
def _load_models(self):
|
35 |
+
"""Loads the embedding and generation models if not already loaded."""
|
36 |
+
if self.embedding_model is None:
|
37 |
+
print(f"Loading Embedding Model: {EMBEDDING_MODEL_NAME}...")
|
38 |
+
self.embedding_model = HuggingFaceEmbeddings(model_name=EMBEDDING_MODEL_NAME)
|
39 |
+
|
40 |
+
if self.llm is None:
|
41 |
+
print(f"Loading LLM Model: {LLM_MODEL_NAME}...")
|
42 |
+
tokenizer = AutoTokenizer.from_pretrained(LLM_MODEL_NAME)
|
43 |
+
model = AutoModelForSeq2SeqLM.from_pretrained(LLM_MODEL_NAME)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
+
# Determine device for pipeline
|
46 |
+
device = 0 if torch.cuda.is_available() else -1
|
47 |
+
|
48 |
+
# Create a Hugging Face pipeline for text generation
|
49 |
+
text_generation_pipeline = pipeline(
|
50 |
+
"text2text-generation",
|
51 |
+
model=model,
|
52 |
+
tokenizer=tokenizer,
|
53 |
+
max_new_tokens=150, # Set a default max_new_tokens for the pipeline
|
54 |
+
min_length=20,
|
55 |
+
num_beams=5,
|
56 |
+
early_stopping=True,
|
57 |
+
device=device
|
58 |
+
)
|
59 |
+
self.llm = HuggingFacePipeline(pipeline=text_generation_pipeline)
|
60 |
+
|
61 |
+
self.is_initialized = True
|
62 |
+
|
63 |
+
def initialize_knowledge_base(self, arxiv_query: str, max_papers: int = 5) -> str:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
"""
|
65 |
+
Initializes the knowledge base by downloading, extracting, and chunking
|
66 |
+
arXiv papers using LangChain components, then building a FAISS vectorstore.
|
|
|
|
|
67 |
"""
|
68 |
+
self._load_models() # Ensure models are loaded first
|
69 |
+
|
70 |
+
# Clear existing papers before downloading new ones
|
71 |
+
if os.path.exists(ARXIV_DIR):
|
72 |
+
shutil.rmtree(ARXIV_DIR)
|
73 |
+
os.makedirs(ARXIV_DIR, exist_ok=True)
|
74 |
+
|
75 |
+
self.vectorstore = None
|
76 |
+
self.qa_chain = None
|
77 |
+
|
78 |
+
print(f"Searching arXiv for '{arxiv_query}' and downloading up to {max_papers} papers...")
|
79 |
+
try:
|
80 |
+
# Use LangChain's ArxivLoader
|
81 |
+
# ArxivLoader downloads PDFs to a temporary directory by default,
|
82 |
+
# but we can specify a custom path to ensure cleanup.
|
83 |
+
# For simplicity, we'll let it download to its default temp dir
|
84 |
+
# and then process. Or, we can manually download and use PyPDFLoader.
|
85 |
+
# Let's stick to manual download for better control and consistency with previous code.
|
86 |
+
|
87 |
+
# Manual download using arxiv library (as it offers more control over filenames)
|
88 |
+
search_results = arxiv.Search(
|
89 |
+
query=arxiv_query,
|
90 |
+
max_results=max_papers,
|
91 |
+
sort_by=arxiv.SortCriterion.Relevance,
|
92 |
+
sort_order=arxiv.SortOrder.Descending
|
93 |
+
)
|
94 |
+
pdf_paths = []
|
95 |
+
for i, result in enumerate(search_results.results()):
|
96 |
+
try:
|
97 |
+
safe_title = re.sub(r'[\\/:*?"<>|]', '', result.title)
|
98 |
+
filename = f"{ARXIV_DIR}/{safe_title[:100]}_{result.arxiv_id}.pdf"
|
99 |
+
print(f"Downloading paper {i+1}/{max_papers}: {result.title}")
|
100 |
+
result.download_pdf(filename=filename)
|
101 |
+
pdf_paths.append(filename)
|
102 |
+
except Exception as e:
|
103 |
+
print(f"Could not download {result.title}: {e}")
|
104 |
+
|
105 |
+
if not pdf_paths:
|
106 |
+
return "No papers found or downloaded for the given query. Please try a different query."
|
107 |
+
|
108 |
+
# Load documents from downloaded PDFs using PyPDFLoader
|
109 |
+
all_documents = []
|
110 |
+
for pdf_path in pdf_paths:
|
111 |
+
try:
|
112 |
+
loader = PyPDFLoader(pdf_path)
|
113 |
+
all_documents.extend(loader.load())
|
114 |
+
except Exception as e:
|
115 |
+
print(f"Error loading PDF {pdf_path}: {e}")
|
116 |
+
|
117 |
+
if not all_documents:
|
118 |
+
return "Could not load any documents from downloaded PDFs. Please try a different query or fewer papers."
|
119 |
+
|
120 |
+
print(f"Loaded {len(all_documents)} raw documents from PDFs.")
|
121 |
+
|
122 |
+
# Split documents into chunks using RecursiveCharacterTextSplitter
|
123 |
+
text_splitter = RecursiveCharacterTextSplitter(
|
124 |
+
chunk_size=CHUNK_SIZE,
|
125 |
+
chunk_overlap=CHUNK_OVERLAP,
|
126 |
+
length_function=len,
|
127 |
+
is_separator_regex=False,
|
128 |
+
)
|
129 |
+
self.knowledge_base_chunks = text_splitter.split_documents(all_documents)
|
130 |
+
|
131 |
+
if not self.knowledge_base_chunks:
|
132 |
+
return "No meaningful text chunks could be created from the papers after splitting."
|
133 |
+
|
134 |
+
print(f"Total chunks created: {len(self.knowledge_base_chunks)}")
|
135 |
+
|
136 |
+
# Create FAISS vectorstore from chunks and embeddings
|
137 |
+
print("Creating FAISS vectorstore from chunks...")
|
138 |
+
self.vectorstore = FAISS.from_documents(self.knowledge_base_chunks, self.embedding_model)
|
139 |
+
print(f"FAISS vectorstore created with {len(self.knowledge_base_chunks)} documents.")
|
140 |
+
|
141 |
+
# Create RetrievalQA chain
|
142 |
+
self.qa_chain = RetrievalQA.from_chain_type(
|
143 |
+
llm=self.llm,
|
144 |
+
chain_type="stuff", # "stuff" puts all retrieved docs into one prompt
|
145 |
+
retriever=self.vectorstore.as_retriever(search_kwargs={"k": 3}), # Retrieve top 3 docs
|
146 |
+
return_source_documents=False # Set to True if you want to return source docs
|
147 |
+
)
|
148 |
+
|
149 |
+
return f"Knowledge base loaded with {len(self.knowledge_base_chunks)} chunks from {len(pdf_paths)} arXiv papers on '{arxiv_query}'."
|
150 |
+
|
151 |
+
except Exception as e:
|
152 |
+
print(f"Error during knowledge base initialization: {e}")
|
153 |
+
return f"An error occurred during knowledge base initialization: {e}"
|
154 |
+
|
155 |
+
def query_agent(self, query: str) -> str:
|
156 |
"""
|
157 |
+
Retrieves relevant information from the knowledge base and generates an answer
|
158 |
+
using the LangChain RetrievalQA chain.
|
|
|
159 |
"""
|
160 |
+
if not query.strip():
|
161 |
+
return "Please enter a question."
|
162 |
+
if not self.is_initialized or self.qa_chain is None:
|
163 |
+
return "Knowledge base not loaded. Please initialize it by providing an arXiv query."
|
164 |
+
|
165 |
+
print(f"\n--- Querying LLM with LangChain QA Chain ---\nQuestion: {query}\n----------------------")
|
166 |
+
|
167 |
+
try:
|
168 |
+
# Use the RetrievalQA chain to get the answer
|
169 |
+
result = self.qa_chain.invoke({"query": query})
|
170 |
+
answer = result["result"].strip()
|
171 |
+
except Exception as e:
|
172 |
+
print(f"Error during generation: {e}")
|
173 |
+
answer = "I apologize, but I encountered an error while generating the answer. Please try again or rephrase your question."
|
174 |
+
|
175 |
+
return answer
|
176 |
+
|
177 |
+
# --- Gradio Interface ---
|
178 |
+
|
179 |
+
# Instantiate the RAGAgent
|
180 |
+
rag_agent_instance = RAGAgent()
|
181 |
+
|
182 |
+
print("Setting up Gradio interface...")
|
183 |
+
|
184 |
+
with gr.Blocks() as demo:
|
185 |
+
gr.Markdown("# 📚 Educational RAG Agent with arXiv Knowledge Base (LangChain)")
|
186 |
+
gr.Markdown("First, load a knowledge base by specifying an arXiv search query. Then, ask questions!")
|
187 |
+
|
188 |
+
with gr.Row():
|
189 |
+
arxiv_input = gr.Textbox(
|
190 |
+
label="arXiv Search Query (e.g., 'Large Language Models', 'Reinforcement Learning')",
|
191 |
+
placeholder="Enter a topic to search for papers on arXiv...",
|
192 |
+
lines=1
|
193 |
+
)
|
194 |
+
max_papers_slider = gr.Slider(
|
195 |
+
minimum=1,
|
196 |
+
maximum=10,
|
197 |
+
step=1,
|
198 |
+
value=3,
|
199 |
+
label="Max Papers to Download"
|
200 |
+
)
|
201 |
+
load_kb_button = gr.Button("Load Knowledge Base from arXiv")
|
202 |
+
|
203 |
+
kb_status_output = gr.Textbox(label="Knowledge Base Status", interactive=False)
|
204 |
+
|
205 |
+
with gr.Row():
|
206 |
+
question_input = gr.Textbox(
|
207 |
+
lines=3,
|
208 |
+
placeholder="Ask a question based on the loaded arXiv papers...",
|
209 |
+
label="Your Question"
|
210 |
+
)
|
211 |
+
answer_output = gr.Textbox(label="Answer", lines=7, interactive=False)
|
212 |
+
|
213 |
+
submit_button = gr.Button("Get Answer")
|
214 |
+
|
215 |
+
load_kb_button.click(
|
216 |
+
fn=rag_agent_instance.initialize_knowledge_base, # Call method of instance
|
217 |
+
inputs=[arxiv_input, max_papers_slider],
|
218 |
+
outputs=kb_status_output
|
219 |
)
|
220 |
+
|
221 |
+
submit_button.click(
|
222 |
+
fn=rag_agent_instance.query_agent, # Call method of instance
|
223 |
+
inputs=question_input,
|
224 |
+
outputs=answer_output
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
)
|
226 |
+
|
227 |
+
gr.Examples(
|
228 |
+
examples=[
|
229 |
+
["What is the transformer architecture?"],
|
230 |
+
["Explain attention mechanisms in deep learning."],
|
231 |
+
["What are the challenges in reinforcement learning?"],
|
232 |
+
],
|
233 |
+
inputs=question_input
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
)
|
|
|
235 |
|
236 |
+
# Launch the Gradio app
|
|
|
|
|
237 |
if __name__ == "__main__":
|
238 |
+
print("Launching Gradio app...")
|
239 |
+
demo.launch(share=False)
|
240 |
+
```
|
241 |
+
```text
|
requirements.txt
CHANGED
@@ -1,11 +1,10 @@
|
|
1 |
huggingface_hub==0.25.2
|
2 |
-
|
3 |
transformers
|
4 |
-
|
5 |
-
langchain
|
6 |
faiss-cpu
|
7 |
-
|
8 |
-
huggingface_hub
|
9 |
arxiv
|
10 |
-
|
11 |
-
|
|
|
|
1 |
huggingface_hub==0.25.2
|
2 |
+
gradio
|
3 |
transformers
|
4 |
+
sentence-transformers
|
|
|
5 |
faiss-cpu
|
6 |
+
torch
|
|
|
7 |
arxiv
|
8 |
+
pypdf2
|
9 |
+
langchain
|
10 |
+
langchain-community
|