ResearchAgent β Local, Privacy-First RAG Research Assistant
A lightweight, local-first research assistant that helps you find, read, and ask questions about academic papers. Itβs built to run on your machine, keep your data private, and demonstrate a practical RAG workflow you can extend.
Note: Thereβs a screenshot placeholder at docs/screenshot.png. If you donβt see an image on the Hub, add a screenshot file (recommended 1280Γ720) or update the README to point to your own image.
One-line: ResearchAgent β a local RAG assistant for searching arXiv, ingesting PDFs, and asking Gemini-powered questions.
Tags: RAG β’ ChromaDB β’ SentenceTransformers β’ Google Gemini β’ LangGraph β’ LangSmith β’ Gradio β’ PDF ingestion β’ Vector search β’ Python
ResearchAgent is a practical prototype I built to explore how local tools and modern LLMs can help with literature review. It wires together a simple, reusable pipeline: search arXiv, download PDFs, extract text, chunk and embed passages, store them in a local vector store, and answer grounded questions using Google Gemini.
This repository is written for people who want a working demo they can run and customize. It shows real engineering trade-offs and useful patterns, such as:
- A local, persistent vector store using ChromaDB
- Lightweight embeddings with SentenceTransformers (all-MiniLM-L6-v2)
- Google Gemini integration (google.genai) with model-fallback and usage reporting
- A small LangGraph-based orchestrator to pick and run tools
- LangSmith-compatible tracing (direct HTTP) with a local JSON fallback for reliability
- A user-friendly Gradio UI, and conservative RAG fallbacks to avoid hallucination
Key features (what recruiters look for)
- Local-first: no OpenAI keys required; runs using Google Gemini and local embeddings
- End-to-end pipeline: arXiv search β PDF download β PDF parsing β chunking β embedding β ChromaDB ingestion β RAG answers
- Robust orchestration: LangGraph state machine drives tool selection and execution
- Observability: optional LangSmith run logging + safe local JSON fallback logs
- Resilience: automatic Gemini model fallback when facing token limits or deprecated models
- Developer-friendly: clear module boundaries, docstrings for tools, CLI fallback for MCP
Project layout
- requirements.txt
- arxiv_fetcher.py β arXiv search & PDF download
- database.py β PDF reading, chunking, embeddings, ChromaDB storage & query
- llm_provider.py β Gemini wrapper with model-selection and usage extraction
- langgraph_agent.py β LangGraph orchestration graph
- langsmith_integration.py β direct HTTP LangSmith logger + local fallback
- server.py β MCP tools, CLI fallback, ask_researchagent alias
- gradio_app.py β modern Gradio UI for end users
- [.env] (local; not committed) β stores API keys and flags
Quickstart (developer-friendly)
- Create & activate a Python 3.11+ venv in the project root: python3 -m venv venv source ./venv/bin/activate
- Install dependencies: ./venv/bin/pip install -r requirements.txt
- Copy
.env.exampleto.envand fill in required values (or create.env):- GOOGLE_API_KEY (required for Google Gemini)
- LANGSMITH_API_KEY (optional; required for remote tracing)
- LANGSMITH_ENDPOINT (optional)
- LANGSMITH_TRACING=true|false
- Launch the UI: ./venv/bin/python gradio_app.py Open http://localhost:7860
Usage summary (end-user flow)
- Find papers: Use the "Find papers" tab to search arXiv and download PDFs.
- Build your knowledge base: Select a downloaded PDF and ingest it into the local ChromaDB. PDF pages are chunked and embedded with SentenceTransformers.
- Ask ResearchAgent: Ask focused questions. The system performs retrieval and either returns a grounded, context-aware answer (RAG) or falls back to a concise general LLM answer when local context is missing.
- Agent helper: Give a single natural-language instruction and the LangGraph orchestrator chooses the right tools (search, ingest, query, or answer).
Developer notes (how it works internally)
- Ingestion: database.ingest_pdf uses PyMuPDF to extract per-page text, then RecursiveCharacterTextSplitter to create 1000-token chunks with 200-token overlap, then encodes with SentenceTransformers and stores embeddings in a persistent ChromaDB at
./chroma_data. - Retrieval: database.query_database embeds the query and performs a nearest-neighbors search returning documents, metadata and distances.
- LLM: llm_provider.chat_with_gemini calls Google Gemini using
google.genai; it auto-selects healthy models and retries on token-limit or model-deprecation errors. Token/usage metadata is extracted and forwarded to tracing. - Tracing: langsmith_integration.log_interaction posts runs to a LangSmith-compatible endpoint (uses
X-Api-Keyheader andrun_typefield) and falls back to safe local JSON logs at./langsmith_logs/when remote tracing fails. - Orchestration: langgraph_agent.py builds a small graph (decide_tool β execute_tool).
server.agent_orchestratedelegates to this graph; the graph uses Gemini to decide which tool to call and then executes it.
UX & product decisions
- The UI focuses on a linear research workflow (Find β Ingest β Ask β Agent) with progressive disclosure: result panels are hidden until actions produce output.
- Conservative RAG: If retrieved passages are weak (high distance) or empty, the system falls back to a concise LLM answer to avoid hallucination, and displays a short one-line guidance to ingest PDFs for paper-specific summaries.
- Privacy: All data (PDFs, embeddings, ChromaDB, and fallback logs) remain local unless remote tracing is explicitly enabled.
Troubleshooting & common issues
- LangSmith returns 401 or 404: verify
LANGSMITH_API_KEYandLANGSMITH_ENDPOINTin.env. Public LangSmith API expectsX-Api-Keyheader and/api/v1/runspath with arun_typefield. - Gemini model errors: SDK will auto-select available models. If you see
MODEL_NOT_FOUNDor deprecation errors, updateGEMINI_MODELin.envor let the app auto-pick a supported model. - PDF extraction issues: Some PDFs have poor text layers. Check
./pdfs/and ensure PyMuPDF can extract text; fallback is to OCR externally before ingest.