Spaces:
Sleeping
Sleeping
import os | |
import gradio as gr | |
from datasets import Dataset | |
from langchain.text_splitter import RecursiveCharacterTextSplitter | |
from langchain_community.embeddings import HuggingFaceEmbeddings | |
from langchain_community.vectorstores import FAISS | |
from langchain_community.llms import HuggingFaceHub | |
from langchain.chains import RetrievalQA | |
from langchain.agents import AgentExecutor, create_react_agent, Tool | |
from langchain_core.prompts import PromptTemplate | |
from langchain_core.messages import SystemMessage | |
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder | |
from langchain_core.documents import Document | |
import arxiv # Import library arxiv | |
# --- Konfigurasi dan Setup Awal --- | |
# Pastikan Anda memiliki token API Hugging Face. | |
# Anda bisa mendapatkannya dari https://huggingface.co/settings/tokens | |
# Simpan sebagai variabel lingkungan di Hugging Face Spaces (Settings -> Repository secrets) | |
# dengan nama HUGGINGFACEHUB_API_TOKEN. | |
# os.environ["HUGGINGFACEHUB_API_TOKEN"] = "hf_YOUR_API_TOKEN_HERE" # Jangan hardcode di sini! | |
# Periksa apakah token API telah disetel | |
if "HUGGINGFACEHUB_API_TOKEN" not in os.environ: | |
print("WARNING: Variabel lingkungan 'HUGGINGFACEHUB_API_TOKEN' tidak disetel.") | |
print("Silakan setel token Anda sebagai 'Repository secret' di Hugging Face Spaces.") | |
# Jika token tidak disetel, kita akan menggunakan placeholder untuk LLM | |
# Untuk demo ini, jika token tidak ada, LLM akan menghasilkan pesan peringatan. | |
# --- Fungsi untuk Mengambil Paper dari ArXiv --- | |
def fetch_papers_from_arxiv(query: str, max_results: int = 5) -> list[Document]: | |
""" | |
Mengambil paper dari arXiv berdasarkan query pencarian. | |
Mengembalikan list objek Document Langchain. | |
""" | |
client = arxiv.Client() | |
search_query = arxiv.Search( | |
query=query, | |
max_results=max_results, | |
sort_by=arxiv.SortCriterion.Relevance, | |
sort_order=arxiv.SortOrder.Descending | |
) | |
papers = [] | |
try: | |
for result in client.results(search_query): | |
# Menggabungkan judul, abstrak, dan penulis sebagai konten dokumen | |
# Anda bisa memilih untuk mengunduh full text jika diperlukan, | |
# namun abstrak biasanya cukup untuk RAG awal. | |
content = f"Title: {result.title}\nAuthors: {', '.join([a.name for a in result.authors])}\nAbstract: {result.summary}" | |
# Menambahkan metadata seperti URL dan ID ArXiv | |
metadata = { | |
"title": result.title, | |
"authors": [a.name for a in result.authors], | |
"published": result.published.strftime("%Y-%m-%d"), | |
"arxiv_url": result.entry_id, | |
"pdf_url": result.pdf_url | |
} | |
papers.append(Document(page_content=content, metadata=metadata)) | |
print(f"Berhasil mengambil {len(papers)} paper dari arXiv untuk query: '{query}'") | |
except Exception as e: | |
print(f"Gagal mengambil paper dari arXiv: {e}") | |
print("Pastikan ada koneksi internet dan query valid.") | |
return papers | |
# --- 1. Memuat Data Paper AI dari ArXiv --- | |
# Ganti dummy data dengan paper nyata dari arXiv. | |
# Anda bisa menyesuaikan query dan jumlah hasil yang diinginkan. | |
arxiv_search_query = "large language models" # Contoh query pencarian | |
num_arxiv_papers = 5 # Jumlah paper yang ingin diambil | |
documents = fetch_papers_from_arxiv(arxiv_search_query, num_arxiv_papers) | |
# Jika tidak ada dokumen yang diambil, gunakan dummy data sebagai fallback | |
if not documents: | |
print("Tidak ada paper yang diambil dari arXiv. Menggunakan dummy data sebagai fallback.") | |
dummy_ai_papers_content = [ | |
""" | |
Paper Title: Deep Learning for Natural Language Processing: A Review | |
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. | |
Keywords: Deep Learning, NLP, Transformers, RNN, CNN, LLM, Machine Translation, Sentiment Analysis. | |
""", | |
""" | |
Paper Title: Reinforcement Learning in Robotics: Challenges and Future Directions | |
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. | |
Keywords: Reinforcement Learning, Robotics, AI, Sample Efficiency, Sim-to-Real, Computer Vision. | |
""", | |
""" | |
Paper Title: Explainable AI (XAI): Methods and Applications | |
Abstract: As AI models become more complex, the need for Explainable AI (XAI) grows. This paper surveys various XAI methods, including LIME, SHAP, and attention mechanisms, which aim to make AI decisions more transparent and understandable to humans. We examine their applications in critical domains like healthcare and finance, where interpretability is paramount. | |
Keywords: Explainable AI, XAI, Interpretability, LIME, SHAP, Healthcare AI, Finance AI. | |
""", | |
""" | |
Paper Title: Federated Learning: A Privacy-Preserving Machine Learning Paradigm | |
Abstract: Federated Learning (FL) is an emerging machine learning approach that enables collaborative model training across decentralized devices or organizations while keeping raw data localized. This paper discusses the architectural principles of FL, its privacy benefits, and challenges such as communication overhead, heterogeneity, and security vulnerabilities. | |
Keywords: Federated Learning, FL, Privacy, Decentralized AI, Machine Learning, Security. | |
""", | |
""" | |
Paper Title: Generative Adversarial Networks (GANs): Architectures and Applications | |
Abstract: Generative Adversarial Networks (GANs) are a class of AI algorithms used in unsupervised machine learning, implemented by a system of two neural networks contesting with each other in a zero-sum game framework. This paper reviews the foundational architectures of GANs, including DCGAN, CycleGAN, and StyleGAN, and explores their diverse applications in image synthesis, data augmentation, and anomaly detection. | |
Keywords: GANs, Generative Models, Image Synthesis, Anomaly Detection, Neural Networks. | |
""" | |
] | |
documents = [Document(page_content=text) for text in dummy_ai_papers_content] | |
print(f"Jumlah dokumen awal: {len(documents)}") | |
# --- 2. Pemisahan Teks (Text Splitting) --- | |
# Memecah dokumen menjadi chunks yang lebih kecil untuk retrieval yang lebih baik. | |
text_splitter = RecursiveCharacterTextSplitter( | |
chunk_size=1000, | |
chunk_overlap=200, | |
length_function=len, | |
add_start_index=True, | |
) | |
chunks = text_splitter.split_documents(documents) | |
print(f"Jumlah chunks setelah pemisahan: {len(chunks)}") | |
# --- 3. Embeddings --- | |
# Menginisialisasi model embedding dari Hugging Face. | |
# Ini akan mengunduh model jika belum ada. | |
embedding_model_name = "sentence-transformers/all-MiniLM-L6-v2" | |
embeddings = HuggingFaceEmbeddings(model_name=embedding_model_name) | |
# --- 4. Vector Store (FAISS) --- | |
# Membuat indeks FAISS dari chunks dan embeddings. | |
print("Membuat indeks FAISS... Ini mungkin butuh waktu tergantung ukuran data.") | |
vectorstore = FAISS.from_documents(chunks, embeddings) | |
print("Indeks FAISS berhasil dibuat.") | |
# --- 5. Inisialisasi LLM --- | |
# Menggunakan HuggingFaceHub untuk LLM. | |
# Anda bisa menggantinya dengan model lokal atau API LLM lainnya jika diinginkan. | |
if "HUGGINGFACEHUB_API_TOKEN" in os.environ: | |
llm = HuggingFaceHub( | |
repo_id="mistralai/Mistral-7B-Instruct-v0.2", # Contoh model yang bagus | |
model_kwargs={"temperature": 0.1, "max_length": 512} | |
) | |
else: | |
# Placeholder LLM jika token tidak disetel | |
class DummyLLM: | |
def invoke(self, prompt, **kwargs): | |
return "Maaf, LLM tidak dapat diinisialisasi karena HUGGINGFACEHUB_API_TOKEN tidak disetel. Silakan setel token Anda." | |
def __call__(self, prompt, **kwargs): | |
return self.invoke(prompt, **kwargs) | |
llm = DummyLLM() | |
print("Menggunakan DummyLLM karena HUGGINGFACEHUB_API_TOKEN tidak disetel.") | |
# --- 6. Membuat Chain RAG (RetrievalQA) --- | |
# Chain ini akan mengambil dokumen yang relevan dan meneruskannya ke LLM untuk menghasilkan jawaban. | |
qa_chain = RetrievalQA.from_chain_type( | |
llm=llm, | |
chain_type="stuff", # "stuff" menggabungkan semua dokumen ke dalam satu prompt | |
retriever=vectorstore.as_retriever(), | |
return_source_documents=True, # Untuk melihat dokumen sumber yang diambil | |
) | |
# --- 7. Membuat Agentic RAG Logic --- | |
# Kita akan membuat "tool" yang membungkus chain RAG kita. | |
# Agent kemudian dapat memutuskan kapan harus menggunakan tool ini. | |
tool_description = ( | |
"Berguna untuk menjawab pertanyaan tentang paper Artificial Intelligence, " | |
"termasuk konsep, metodologi, tantangan, dan aplikasi yang dibahas dalam paper." | |
"Gunakan tool ini untuk mengambil informasi dari basis pengetahuan paper AI." | |
) | |
tools = [ | |
Tool( | |
name="AI_Paper_Retriever", | |
func=qa_chain.invoke, # Menggunakan .invoke() untuk Langchain Expression Language | |
description=tool_description, | |
return_direct=False # Agent akan memproses output tool ini | |
) | |
] | |
# Prompt untuk Agent | |
# Agent akan memutuskan tool mana yang akan digunakan berdasarkan prompt ini. | |
# Kita menggunakan ReAct (Reasoning and Acting) prompt. | |
agent_prompt = ChatPromptTemplate.from_messages( | |
[ | |
SystemMessage( | |
content=( | |
"Anda adalah asisten AI yang sangat membantu dan berpengetahuan luas, " | |
"khususnya dalam bidang Artificial Intelligence dan paper penelitian terkait." | |
"Tugas utama Anda adalah membantu pengguna memahami dan menavigasi informasi dari paper AI." | |
"Gunakan tool 'AI_Paper_Retriever' jika pertanyaan pengguna berkaitan dengan konten paper AI " | |
"atau memerlukan informasi spesifik dari basis pengetahuan Anda." | |
"Jika pertanyaan bersifat umum atau tidak memerlukan pengambilan data, jawablah langsung." | |
"Selalu berikan jawaban yang komprehensif dan relevan." | |
) | |
), | |
MessagesPlaceholder(variable_name="chat_history"), | |
("human", "{input}"), | |
MessagesPlaceholder(variable_name="tools"), | |
MessagesPlaceholder(variable_name="agent_scratchpad"), | |
MessagesPlaceholder(variable_name="tool_names"), | |
] | |
) | |
# Membuat Agent | |
# Menggunakan create_react_agent untuk agent yang berbasis ReAct | |
agent = create_react_agent(llm, tools, agent_prompt) | |
# Membuat Agent Executor | |
# Ini adalah runtime untuk agent, yang menjalankan loop pemikiran-aksi. | |
agent_executor = AgentExecutor( | |
agent=agent, | |
tools=tools, | |
verbose=True, # Untuk melihat langkah-langkah pemikiran agent | |
handle_parsing_errors=True, # Menangani kesalahan parsing agent | |
max_iterations=5 # Batasi iterasi untuk menghindari loop tak terbatas | |
) | |
# --- 8. Gradio Interface --- | |
# Fungsi untuk memproses pertanyaan pengguna menggunakan agent | |
def process_query(query, chat_history_tuples): | |
# Mengubah riwayat chat dari Gradio ke format Langchain | |
from langchain_core.messages import HumanMessage, AIMessage | |
formatted_chat_history = [] | |
for human_msg, ai_msg in chat_history_tuples: | |
formatted_chat_history.append(HumanMessage(content=human_msg)) | |
formatted_chat_history.append(AIMessage(content=ai_msg)) | |
try: | |
# Panggil agent executor | |
response = agent_executor.invoke({ | |
"input": query, | |
"chat_history": formatted_chat_history | |
}) | |
answer = response["output"] | |
# Jika agent menggunakan tool RAG, kita bisa menampilkan sumbernya juga | |
# Ini memerlukan sedikit modifikasi jika Anda ingin menampilkan sumber | |
# secara eksplisit dari dalam agent_executor.invoke(). | |
# Untuk kesederhanaan, kita hanya akan menampilkan jawaban agent. | |
# Jika Anda ingin menampilkan sumber, Anda perlu memodifikasi tool | |
# atau agent_executor untuk mengembalikan informasi sumber secara eksplisit. | |
except Exception as e: | |
answer = f"Terjadi kesalahan saat memproses pertanyaan: {e}" | |
if "HUGGINGFACEHUB_API_TOKEN" not in os.environ: | |
answer += "\nPastikan HUGGINGFACEHUB_API_TOKEN Anda disetel dengan benar." | |
return answer | |
# Membuat antarmuka Gradio | |
with gr.Blocks() as demo: | |
gr.Markdown("# Agentic RAG untuk Literasi Paper AI") | |
gr.Markdown("Tanyakan apa pun tentang paper AI yang diambil dari arXiv.") | |
chatbot = gr.Chatbot(label="Percakapan") | |
msg = gr.Textbox(label="Pertanyaan Anda") | |
clear = gr.Button("Clear") | |
def user_message(user_message, history): | |
return "", history + [[user_message, None]] | |
def bot_response(history): | |
query = history[-1][0] | |
# Mengirimkan riwayat chat tanpa respons bot terakhir yang masih None | |
chat_history_for_agent = history[:-1] | |
response = process_query(query, chat_history_for_agent) | |
history[-1][1] = response | |
return history | |
msg.submit(user_message, [msg, chatbot], [msg, chatbot], queue=False).then( | |
bot_response, chatbot, chatbot | |
) | |
clear.click(lambda: None, None, chatbot, queue=False) | |
# Jalankan aplikasi Gradio | |
# Untuk menjalankan di Hugging Face Spaces, Anda mungkin perlu mengatur share=True | |
# atau cukup jalankan tanpa share=True jika sudah di dalam lingkungan Space. | |
if __name__ == "__main__": | |
print("\nAplikasi Gradio siap dijalankan. Buka URL yang diberikan setelah 'Running on local URL:'.") | |
print("Jika Anda melihat pesan peringatan tentang HUGGINGFACEHUB_API_TOKEN, pastikan Anda menyetelnya.") | |
demo.launch(debug=True) # debug=True untuk melihat log di konsol | |