Spaces:
Sleeping
Sleeping
| # app.py - FINAL, 100% WORKING | |
| import os | |
| import subprocess | |
| import gradio as gr | |
| from langchain_community.vectorstores import Weaviate | |
| from langchain.chains import RetrievalQA | |
| from langchain.prompts import PromptTemplate | |
| from sentence_transformers import SentenceTransformer | |
| import weaviate | |
| import time | |
| import requests | |
| # === FIX: Correct Groq import === | |
| from langchain_groq import ChatGroq | |
| # === SECRETS === | |
| WEAVIATE_URL = os.environ["WEAVIATE_URL"] | |
| WEAVIATE_KEY = os.environ["WEAVIATE_KEY"] | |
| os.environ["GROQ_API_KEY"] = os.environ["GROQ_API_KEY"] | |
| # === WAIT FOR WEAVIATE TO BE READY === | |
| def wait_for_weaviate(url, key, timeout=120): | |
| headers = {"Authorization": f"Bearer {key}"} | |
| ready_url = f"{url}/v1/.well-known/ready" | |
| print("Waiting for Weaviate to be ready...") | |
| for i in range(timeout): | |
| try: | |
| response = requests.get(ready_url, headers=headers) | |
| if response.status_code == 200: | |
| print("Weaviate is ready!") | |
| return True | |
| except: | |
| pass | |
| print(f"Attempt {i+1}/{timeout}... waiting 1s") | |
| time.sleep(1) | |
| print("Weaviate did not start in time.") | |
| return False | |
| # === AUTO-INGEST ON START === | |
| def run_ingestion(): | |
| print("Starting ingestion...") | |
| if not wait_for_weaviate(WEAVIATE_URL, WEAVIATE_KEY): | |
| print("Cannot connect to Weaviate. Skipping ingestion.") | |
| return | |
| result = subprocess.run(["python", "ingest.py"], capture_output=True, text=True) | |
| print(result.stdout) | |
| if result.returncode != 0: | |
| print("Ingestion failed:", result.stderr) | |
| else: | |
| print("Ingestion complete!") | |
| # Run once | |
| run_ingestion() | |
| # === RAG CHAIN (NO @gr.cache) === | |
| def get_rag_chain(): | |
| client = weaviate.Client( | |
| url=WEAVIATE_URL, | |
| auth_client_secret=weaviate.AuthApiKey(WEAVIATE_KEY) | |
| ) | |
| embedder = SentenceTransformer("all-MiniLM-L6-v2") | |
| vectorstore = Weaviate(client, "Paper", "text", embedding=embedder) | |
| retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) | |
| llm = ChatGroq(model="llama-3.1-70b-instruct", temperature=0) | |
| prompt = PromptTemplate.from_template( | |
| "Answer using only this context:\n{context}\n\nQuestion: {question}\nAnswer:" | |
| ) | |
| return RetrievalQA.from_chain_type( | |
| llm=llm, retriever=retriever, chain_type_kwargs={"prompt": prompt} | |
| ) | |
| def search(query): | |
| try: | |
| qa = get_rag_chain() | |
| result = qa.invoke({"query": query}) | |
| answer = result["result"] | |
| sources = "\n\n".join([ | |
| f"**{doc.metadata.get('title', 'No Title')}**\n{doc.page_content[:300]}..." | |
| for doc in result["source_documents"] | |
| ]) | |
| return answer, sources or "No sources found." | |
| except Exception as e: | |
| return f"Error: {str(e)}", "Check logs." | |
| # === GRADIO UI === | |
| with gr.Blocks(title="ArXiv RAG") as demo: | |
| gr.Markdown("# ArXiv RAG Search") | |
| gr.Markdown("10K+ papers • Llama-3.1 • Weaviate") | |
| txt = gr.Textbox(label="Ask", placeholder="What is attention?", lines=2) | |
| btn = gr.Button("Search", variant="primary") | |
| out1 = gr.Markdown(); out2 = gr.Markdown() | |
| btn.click(search, txt, [out1, out2]) | |
| demo.launch() |