ResearchPilot-AI / README.md
Visal9252's picture
Update README.md
cf58d99 verified
|
Raw
History Blame Contribute Delete
26.7 kB
metadata
title: 'ResearchPilot AI '
sdk: docker
emoji: 🌍
colorFrom: indigo
colorTo: purple
thumbnail: >-
  https://cdn-uploads.huggingface.co/production/uploads/64ea5e1dc68ddc867b5ec02f/r8wTLNQPQIfsQjgazt_I5.png
short_description: ResearchPilot AI is an Autonomous Multi-Agent Research Syste

🧭 ResearchPilot AI

Autonomous Multi-Agent Research System

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.

Python LangGraph Groq Streamlit Plotly ReportLab License: MIT

πŸš€ Live Demo Β· πŸ“„ Report Sample Β· πŸ‘¨β€πŸ’» Portfolio


πŸ“Œ Table of Contents


πŸ€” What is ResearchPilot AI?

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.

Who is this for?

πŸŽ“ Students πŸ’Ό Professionals πŸ§‘β€πŸ’» Developers
Research papers, literature reviews, assignment prep Market research, competitive analysis, technology evaluation Learn LangGraph, conditional routing, agentic design patterns

✨ What Makes It Different

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.

πŸ—οΈ Architecture

Exact node execution order as wired in graph/graph_builder.py:

                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚         USER QUERY               β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                     β”‚
                                     β–Ό
                          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                          β”‚    🧠 PLANNER    β”‚
                          β”‚                  β”‚
                          β”‚ β€’ Detects domain β”‚
                          β”‚ β€’ Builds 3 tasks β”‚
                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
                                   β–Ό
                          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                          β”‚    πŸ”€ ROUTER     β”‚
                          β”‚                  β”‚
                          β”‚ Single LLM call  β”‚
                          β”‚ β†’ active_agents  β”‚
                          β”‚   list in state  β”‚
                          β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                   β”‚
                                   β–Ό
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚                  βš™οΈ WORKERS NODE                        β”‚
     β”‚           Only activated agents run                      β”‚
     β”‚                                                          β”‚
     β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
     β”‚  β”‚ πŸ”Research β”‚  β”‚ πŸ“ŠStats    β”‚  β”‚ πŸŽ“Domain Expert  β”‚   β”‚
     β”‚  β”‚            β”‚  β”‚            β”‚  β”‚                  β”‚   β”‚
     β”‚  β”‚ 3 Tavily   β”‚  β”‚ Structured β”‚  β”‚ Persona prompt   β”‚   β”‚
     β”‚  β”‚ searches   β”‚  β”‚ JSON β†’     β”‚  β”‚ per domain       β”‚   β”‚
     β”‚  β”‚ β†’ LLM      β”‚  β”‚ chart data β”‚  β”‚                  β”‚   β”‚
     β”‚  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
     β”‚        β”‚               β”‚                   β”‚             β”‚
     β”‚  β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”           β”‚             β”‚
     β”‚  β”‚ βœ…Fact     β”‚  β”‚ πŸ“–Refs     β”‚           β”‚             β”‚
     β”‚  β”‚ Checker    β”‚  β”‚            β”‚           β”‚             β”‚
     β”‚  β”‚ Claim-by-  β”‚  β”‚ APA format β”‚           β”‚             β”‚
     β”‚  β”‚ claim      β”‚  β”‚ citations  β”‚           β”‚             β”‚
     β”‚  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜           β”‚             β”‚
     β”‚        β”‚               β”‚                   β”‚             β”‚
     β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β”‚
     β”‚                    Virtual File System                    β”‚
     β”‚              (shared dict living in state)                β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                 β”‚
                                 β–Ό
                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β”‚  πŸ“ˆ VISUALIZATION β”‚
                      β”‚                  β”‚
                      β”‚ Statistics JSON  β”‚
                      β”‚ β†’ 6 Plotly chartsβ”‚
                      β”‚ (no LLM call)    β”‚
                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               β–Ό
                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β”‚   ✍️ WRITER      β”‚
                      β”‚                  β”‚
                      β”‚ Reads all 5 VFS  β”‚
                      β”‚ files β†’ builds   β”‚
                      β”‚ final report     β”‚
                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               β–Ό
                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€  πŸ† QUALITY GATE │◄────────────────────┐
             β”‚        β”‚                  β”‚                      β”‚
             β”‚        β”‚ LLM scores 0-10  β”‚                      β”‚
             β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                      β”‚
             β”‚                 β”‚                                 β”‚
             β”‚    score β‰₯ 7    β”‚    score < 7 (max 2 retries)    β”‚
             β”‚        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”˜        └──────────────────────► Writer
             β”‚        β–Ό
             β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚ β”‚   πŸ–ΌοΈ COVER       β”‚
             β”‚ β”‚                  β”‚
             β”‚ β”‚ SVG card with    β”‚
             β”‚ β”‚ real score baked β”‚
             β”‚ β”‚ in (runs last)   β”‚
             β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚          β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
                    STREAMLIT UI
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚ πŸ”¬ Research  β”‚ πŸ“Š Data&Charts  β”‚
          β”‚ πŸ“– Referencesβ”‚ πŸ“„ Report       β”‚
          β”‚              β”‚ ⏱️ Trace        β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 MD Β· CSV Β· PDF downloads

⚑ How It Works β€” Real Example

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 βœ…/⚠️/❌. Writes 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.

πŸ“ Folder Structure

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 (~800 lines)
β”‚                                      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.example                    ← API key template
β”œβ”€β”€ .gitignore                      ← Excludes .env, __pycache__, *.pdf
└── README.md

πŸ€– The Five Agents

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.


πŸ“Š The Six Chart Types

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

πŸ”‘ Getting API Keys (Free)

Groq β€” Primary LLM ⭐ Required

Fast open-source inference (14,400 free requests/day):

  1. console.groq.com β†’ Sign up β†’ API Keys β†’ Create
  2. Copy: gsk_...

Tavily β€” Web Search βœ… Required

Real-time web search for agents:

  1. app.tavily.com β†’ Sign up β†’ Dashboard
  2. Copy: tvly-...
  3. Free: 1,000 searches/month

Google Gemini β€” Fallback LLM (optional)

Only needed if no Groq key:

  1. aistudio.google.com β†’ Get API Key
  2. Copy: AIzaSy...

LangSmith β€” Tracing (optional but recommended)

See every node execution, LLM call, and retry as a visual timeline:

  1. smith.langchain.com β†’ Settings β†’ API Keys β†’ Create
  2. Copy: lsv2_...

βš™οΈ Installation & Setup

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 keys

Your .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-ai

▢️ Running the Project

Terminal mode (test the pipeline first)

python main.py

Output: ```

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 Web UI

```bash
streamlit run ui/app.py

Opens at http://localhost:8501


🐳 Deploy to Hugging Face Spaces

The project ships with a ready Dockerfile that targets port 7860 (Hugging Face's required port).

Step 1 β€” Push to GitHub

git add .
git commit -m "Initial ResearchPilot AI upload"
git push origin main

Step 2 β€” Create a Hugging Face Space

  1. Go to huggingface.co/spaces
  2. Click Create new Space
  3. Set:
    • Space name: ResearchPilot-AI
    • License: MIT
    • SDK: Docker ← important, not Streamlit
    • Visibility: Public

Step 3 β€” Add API Keys as Secrets

⚠️ Never put real API keys in code or Dockerfile. Use HF Secrets β€” they're injected as environment variables at runtime, invisible in the repo.

Go to your Space β†’ Settings β†’ Repository secrets β†’ New secret:

Secret Name Value Required?
GROQ_API_KEY Your Groq key (gsk_...) βœ… Required
TAVILY_API_KEY Your Tavily key (tvly_...) βœ… Required
LANGCHAIN_API_KEY Your LangSmith key (lsv2_...) Optional
LANGCHAIN_TRACING_V2 true Optional (with LangSmith)
GOOGLE_API_KEY Your Gemini key Optional fallback

Why secrets, not .env? HF Spaces clones your repo publicly β€” your .env must never be committed (it's in .gitignore). Secrets are stored encrypted in HF's vault and injected at container start time.

Your Dockerfile already sets:

ENV LANGCHAIN_PROJECT="researchpilot-ai"

This constant is safe to hardcode because it's not sensitive β€” it's just the project name in LangSmith's dashboard.

The LANGCHAIN_TRACING_V2=true env var activates LangSmith auto-tracing β€” set it as a secret alongside your LANGCHAIN_API_KEY. Once both are set, every run appears in your LangSmith dashboard showing exactly which node ran, how long each LLM call took, and the full prompt/response for every agent call.

Step 4 β€” Link GitHub Repo

In your Space β†’ Files β†’ Connect to GitHub repo β†’ select your repo β†’ HF auto-builds on every push.

Or push directly to the HF Space's git remote:

git remote add hf https://huggingface.co/spaces/YOUR_HF_USERNAME/ResearchPilot-AI
git push hf main

Step 5 β€” Wait for Build

HF Spaces shows a build log. The first build takes ~3-5 minutes (downloads dependencies). After that, code-only pushes rebuild in ~60 seconds.


πŸ“š Concepts Covered

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

πŸ”§ Troubleshooting

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

πŸ›£οΈ Roadmap

  • AI-generated cover image via Pollinations AI (free, no key needed)
  • LangGraph checkpointing for session memory across multiple queries
  • Upload a PDF/document as additional research context
  • Model selector in UI (Groq / Gemini / OpenRouter)
  • Auto-generate PowerPoint slide deck from the report
  • LangSmith evaluation dashboard integration

πŸ“œ License

MIT License β€” free to use, modify, and distribute with attribution.


πŸ™ Acknowledgements

LangGraph Β· Groq Β· Google Gemini Β· Tavily Β· Plotly Β· Streamlit Β· ReportLab Β· LangSmith


πŸ‘¨β€πŸ’» Connect With Me

🌐 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