Give it a topic → Get a complete, evidence-backed research report with charts, citations, and PDF export.
ResearchPilot AI runs a coordinated team of specialised AI agents — each with a focused job — orchestrated by LangGraph. It plans, routes, searches, analyses, fact-checks, visualises, writes, and self-grades, all from one query.
🚀 Test_Live Demo (Hosted on Railway) · 🤗Hosted on Hugging Face · 🎥 Demo Video · 👨💻 Portfolio
ResearchPilot AI is a multi-agent AI research system built with LangGraph. You type one query — say, "Impact of AI on healthcare market growth" — and it autonomously runs an 8-node pipeline:
Query → Plan → Route → Research + Analyse → Visualise → Write → Grade → Deliver
The system produces:
- ✅ A structured markdown report (Executive Summary → Key Findings → Analysis → Expert Perspective → Conclusion → References)
- 📊 Up to 6 interactive Plotly charts generated from real statistical data
- 📄 A professional academic PDF with embedded charts and APA citations
- 🗂️ A CSV file of the raw statistics for further analysis
This is not a chatbot wrapper. It implements the planner → router → workers → critic pattern used in production agentic AI systems.
| 🎓 Students | 💼 Professionals | 🧑💻 Developers |
|---|---|---|
| Research papers, literature reviews, assignment prep | Market research, competitive analysis, technology evaluation | Learn LangGraph, conditional routing, agentic design patterns |
| Feature | What it does |
|---|---|
| 🔀 Dynamic Router Agent | One LLM call decides per-query which of 5 specialist agents to activate. A history question never wastes time running a Statistics agent. A finance query gets Fact Checker. Nothing runs unless it adds value. |
| 📊 Statistics → Charts pipeline | The Statistics agent returns structured JSON (not prose) — metrics, time-series, regional breakdowns — which directly drives 6 Plotly chart types with no extra LLM calls. |
| 🎓 Persona-driven Domain Expert | Adopts a credentialed persona per domain ("Dr. Sarah Chen, Harvard physician" for healthcare; "Marcus Reid, ex-Goldman analyst" for finance) — sharper than a generic "you are an expert" prompt. |
| ✅ Dedicated Fact Checker | Extracts specific claims, runs independent search evidence per claim, labels each: Verified / Partially True / Disputed / Unverifiable. |
| 🏆 Self-grading + auto-retry | Quality Gate scores the report 0–10 against five weighted criteria. Below 7 → automatic retry with explicit feedback. Capped at 2 retries to prevent runaway cost. |
| 🖼️ Cover runs after scoring | The SVG cover card is generated last — after Quality Gate — so it always shows the real quality score, not zero. |
| 📄 ReportLab academic PDF | Flowable single-column layout, deep-blue academic headings, horizontal rule separators, charts embedded directly under their matching report section. |
Exact node execution order as wired in
graph/graph_builder.py:
📂 Virtual File System
Query typed: "Impact of AI on healthcare market growth: adoption rates, investment trends and future outlook"

| Step | Node | What happens |
|---|---|---|
| 1 | Planner | Detects topic_domain = "healthcare". Creates tasks: search clinical data, find market numbers, locate key organisations. |
| 2 | Router | One LLM call → ["research", "statistics", "domain_expert", "fact_checker", "citation"]. All 5 activate because healthcare needs everything. |
| 3a | Research | Runs 3 Tavily searches: raw query + "latest developments 2025" + "key findings evidence". LLM synthesises into structured deep-research. Writes research_deep.txt to VFS. |
| 3b | Statistics | Searches for "$45B market size", "29% CAGR" etc. Forces LLM to return exact JSON schema (metrics array + trends array + comparisons array). Writes statistics.txt + statistics_data.csv. |
| 3c | Domain Expert | Persona: "Dr. Sarah Chen, Harvard-trained physician". Reads research_deep.txt, adds clinical nuance. Writes expert_analysis.txt. |
| 3d | Fact Checker | Extracts 6 specific claims. Verifies 4 individually via fresh Tavily searches. Labels ✅/fact_check.txt. |
| 3e | References | Formats all sources from raw_search.txt into APA JSON. Writes references.txt. Returns structured citations list. |
| 4 | Visualization | No LLM call. Reads structured_data dict → builds 6 Plotly figures → stores as JSON strings in chart_json. |
| 5 | Writer | Checks each VFS key. Builds context from whichever files exist. One large LLM call produces 9-section markdown report. |
| 6 | Quality Gate | LLM scores the report: 7.5/10. should_retry() returns "done". Routes to Cover. |
| 7 | Cover | Now has quality_score = 7.5. Generates SVG card with real score baked in. |
| End | UI | 5 sections rendered. Download MD + CSV + PDF available. |
ResearchPilot AI/ ← root folder
│
├── graph/ ← LangGraph nodes (the "brain")
│ ├── __init__.py
│ ├── state.py ← ResearchState TypedDict — shared memory
│ │ every node reads from and writes to
│ ├── llm_factory.py ← get_llm() — Groq primary, Gemini fallback
│ │ every node imports this, never hardcodes
│ ├── planner.py ← Node 1: detects domain, builds task list
│ ├── router.py ← Node 2: LLM → active_agents list
│ ├── workers.py ← Node 3: all 5 specialist agents
│ │ conditionally called by if "agent" in active_agents
│ ├── visualization.py ← Node 4: structured_data JSON → 6 Plotly charts
│ │ (no LLM call — pure Python/Plotly)
│ ├── synthesizer.py ← Node 5 (displayed as "Writer"):
│ │ reads VFS → one LLM call → final report
│ ├── quality_gate.py ← Node 6: scores report + should_retry() function
│ │ drives the conditional edge / retry loop
│ ├── thumbnail.py ← Node 7 (displayed as "Cover"):
│ │ runs AFTER quality_gate so score exists
│ └── graph_builder.py ← Wires all 7 nodes + edges + conditional edge
│ into one compiled StateGraph object
│
├── tools/ ← Utilities used by nodes (not nodes themselves)
│ ├── __init__.py
│ ├── search_tool.py ← web_search() wraps Tavily API
│ │ returns plain string for LLM context
│ ├── file_system.py ← vfs_write() / vfs_read() helpers
│ │ copy-on-write to keep state immutable
│ └── pdf_generator.py ← ReportLab flowable PDF
│ strips duplicate References section,
│ embeds charts under matching headings
│
├── ui/
│ └── app.py ← Single-page Streamlit UI
│ st.session_state caches results so
│ download clicks don't re-run the pipeline
│
├── .streamlit/
│ └── config.toml ← Dark theme + port 7860 for HF Spaces
│
├── Dockerfile ← Production Docker image for HF Spaces
├── main.py ← Terminal test runner (no UI)
├── app.py ← HF Spaces entry point
├── requirements.txt
├── .env ← API key template
├── .gitignore ← Excludes .env, __pycache__, *.pdf
└── README.md
| Agent | File | Activates when | What it produces |
|---|---|---|---|
| Research | workers.py |
Always | 3-angle Tavily search + LLM synthesis → research_deep.txt |
| Statistics | workers.py |
Topic has numbers/trends | Structured JSON (metrics + trends + comparisons) + CSV → statistics.txt |
| Domain Expert | workers.py |
Specialised topic | Persona-primed analysis → expert_analysis.txt |
| Fact Checker | workers.py |
Claims need verification | Per-claim Tavily verify → fact_check.txt |
| References | workers.py |
Citations add value | APA-formatted JSON list → references.txt |
All agents share data through the Virtual File System — a Dict[str, str] inside LangGraph state. Zero disk I/O.
Gain complete visibility into every stage of the ResearchPilot AI multi-agent workflow using LangSmith. Each research request is fully traced, making it easy to inspect execution, debug agent behavior, analyze latency, and monitor LLM interactions.
- 🧠 Planner detects the research domain and creates structured tasks.
- 🔀 Router dynamically selects only the required specialist agents.
- ⚙️ Workers execute conditionally (Research, Statistics, Domain Expert, Fact Checker, References).
- 📂 Virtual File System (VFS) stores and shares intermediate outputs across agents.
- 📈 Visualization generates interactive Plotly charts without additional LLM calls.
- ✍️ Writer synthesizes all agent outputs into a structured research report.
- 🏆 Quality Gate evaluates report quality and automatically retries if necessary.
- 🖼️ Cover Generator creates the final SVG cover card with the actual quality score.
Benefits
- 🔍 End-to-end execution visibility
- 📊 Performance and latency monitoring
- 🐞 Faster debugging of multi-agent workflows
- 🔄 Easy inspection of prompts, responses, and state transitions
- 🚀 Production-ready observability powered by LangSmith
All generated from Statistics agent JSON with zero extra LLM calls:
| # | Chart | Driven by |
|---|---|---|
| 1 | Horizontal Bar | metrics array |
| 2 | Multi-series Area / Trend | trends[].data_points |
| 3 | Donut / Pie | comparisons array |
| 4 | Gauge | First 0–100 metric value |
| 5 | Bubble Scatter | All metrics (size = relative value) |
| 6 | Year-on-Year Bar | trends[0].data_points |
Fast open-source inference (14,400 free requests/day):
- console.groq.com → Sign up → API Keys → Create
- Copy:
gsk_...
Real-time web search for agents:
- app.tavily.com → Sign up → Dashboard
- Copy:
tvly-... - Free: 1,000 searches/month
Only needed if no Groq key:
- aistudio.google.com → Get API Key
- Copy:
AIzaSy...
See every node execution, LLM call, and retry as a visual timeline:
- smith.langchain.com → Settings → API Keys → Create
- Copy:
lsv2_...
Prerequisites: Python 3.11+, Git
# 1. Clone
git clone https://github.com/vishal815/ResearchPilot-AI.git
cd ResearchPilot-AI
# 2. Virtual environment
python -m venv .venv
# 3. Activate
# Windows:
.venv\Scripts\activate
# Mac/Linux:
source .venv/bin/activate
# 4. Install dependencies
pip install -r requirements.txt
# 5. Set up API keys
cp .env.example .env
# Now open .env and fill in your keysYour .env file:
GROQ_API_KEY=gsk_your_key_here
TAVILY_API_KEY=tvly_your_key_here
# GOOGLE_API_KEY=AIzaSy_your_key_here (optional fallback)
# LANGCHAIN_API_KEY=lsv2_your_key_here (optional tracing)
# LANGCHAIN_TRACING_V2=true
# LANGCHAIN_PROJECT=researchpilot-aipython main.pyOutput:
============================================================
ResearchPilot AI
Query: Impact of AI on healthcare market growth...
============================================================
[NODE: PLANNER] Domain detected: healthcare | 3 tasks created
[NODE: ROUTER] Activated: ['research', 'statistics', 'domain_expert', 'fact_checker', 'citation']
[NODE: WORKERS] Research done | Statistics: 8 metrics, 3 trends | Expert done | FactCheck done | Refs: 8 sources
[NODE: VISUALIZATION] 6 charts generated
[NODE: WRITER] Report generated
[NODE: QUALITY_GATE] Score: 7.5/10
[NODE: COVER] SVG cover card generated
============================================================
Total time: 52.3s | Saved to output_report_v2.md
streamlit run ui/app.pyOpens at http://localhost:8501
| Concept | Where in code | One-line description |
|---|---|---|
| Agentic AI | All nodes | Agents decide and act, not just reply |
| LangGraph StateGraph | graph_builder.py |
Stateful multi-node orchestration with cycles |
| Conditional Edge / Routing | graph_builder.py + quality_gate.py |
should_retry() returns string → LangGraph picks next node |
| Shared State (TypedDict) | state.py |
One dict flows through every node — how agents "talk" |
| Tool Use | search_tool.py |
Agents calling Tavily external API |
| Virtual File System | file_system.py |
Dict-as-filesystem for zero-I/O context sharing |
| Persona Priming | workers.py |
Named, credentialed identity → sharper domain output |
| Structured Output Forcing | workers.py |
Force LLM to return exact JSON schema for deterministic chart rendering |
| LLM-as-Judge | quality_gate.py |
Separate LLM call evaluates the first LLM's output |
| Self-Correction Loop | quality_gate.py |
Cycle in graph capped by retry_count |
| RAG | workers.py |
Search first → synthesise over retrieved context |
| Flowable PDF | pdf_generator.py |
ReportLab auto-layout vs. manual x/y coordinate mess |
| Streamlit Session State | ui/app.py |
Cache results across reruns so downloads don't re-trigger agents |
| Error | Cause | Fix |
|---|---|---|
ModuleNotFoundError |
venv not activated | .venv\Scripts\activate then pip install -r requirements.txt |
ImportError: cannot import name 'web_search' |
Old search_tool.py |
Confirm file has def web_search(query, max_results=5): |
| Charts missing / only 1 chart | rgba color bug (old version) | Make sure you have the latest visualization.py |
Cover shows Score: 0.0 |
Old graph wiring (cover before quality_gate) | Make sure you have the latest graph_builder.py |
| PDF has two References sections | LLM writes its own + structured list | Make sure you have latest pdf_generator.py with _strip_references_section() |
kaleido error in PDF |
Wrong kaleido version | pip install kaleido==0.2.1 (pin to 0.2.1 exactly) |
| Page "resets" on download | Old app.py without session_state cache |
Make sure you have latest ui/app.py |
429 rate limit |
Hit LLM free tier | Wait 60s and retry, or switch to Gemini fallback |
MIT License — free to use, modify, and distribute with attribution.
LangGraph · Groq · Google Gemini · Tavily · Plotly · Streamlit · ReportLab · LangSmith
## Final PPT downloaded O/P report
🌐 Portfolio • 💼 LinkedIn • 🐙 GitHub
If this helped you learn something, give it a ⭐ on GitHub!
Built by Vishal Lazrus during AI Internship at Infosys, June 2026

