An AI-powered peer review system that simulates the full academic review process using multiple specialized agents. Upload a PDF and receive a structured review with reviewer critiques, independence audits, editorial decisions, and author revisions — all generated by coordinated AI agents.
Supports NIH grant reviews, foundation grant reviews, and journal manuscript peer reviews, with three AI backends: Claude, Gemini, and local open-source models.
Every review follows the same four-stage pipeline, regardless of review type:
PDF Document
|
v
+--------------------+
| 1. REVIEW PANEL | Multiple specialized reviewers independently
| (3-5 agents) | critique the document using domain-specific
+--------------------+ scoring criteria and rubrics
|
v
+--------------------+
| 2. INDEPENDENCE | A challenge agent audits all reviews for
| AUDIT | groupthink, confirmation bias, and
+--------------------+ produces addenda where warranted
|
v
+--------------------+
| 3. SYNTHESIZER | An SRO, Editor, or Panel Chair synthesizes
| (Decision) | the critiques into an official decision
+--------------------+ (e.g., Fundable, Accept, Revise, Reject)
|
v
+--------------------+
| 4. AUTHOR | The AI author/PI revises the document
| REVISION | based on all feedback, producing a
+--------------------+ point-by-point response and revised text
|
v
(Iterate or finish based on decision)
| Feature | NIH Grant Review | Foundation Grant Review | Journal Peer Review |
|---|---|---|---|
| Reviewers | Primary, Secondary, Tertiary, Biostatistician, Program Officer (5) | Scientific, Innovation, Program Advisor (3) | Domain Expert, Technical, Novelty (3) |
| Synthesizer | Scientific Review Officer (SRO) | Panel Chair | Editor |
| Author | Principal Investigator | Project Director | Author |
| Decision outcomes | Fundable, Resubmit (Minor/Major), NRFC | Fund, Fund with Conditions, Decline | Accept, Minor/Major Revision, Reject |
| Iteration mode | Iterative (up to N rounds) | Single pass (1 round) | Fixed 2 rounds |
| Scoring | NIH 1-9 scale | Foundation-specific criteria | Journal criteria |
Requires Python 3.10+ (3.11 recommended).
git clone https://github.com/mohebial/agentic_writing.git
cd agentic_writing
# Create and activate the environment
conda env create -f environment.yml
conda activate agentic_writing
git clone https://github.com/mohebial/agentic_writing.git
cd agentic_writing
pip install -r requirements.txt
To use local open-source models instead of cloud APIs:
# Required: PDF-to-markdown conversion
pip install markitdown
# For GGUF quantized models (recommended for most users):
pip install llama-cpp-python
# For standard HuggingFace models:
pip install transformers torch
Cloud backends require API keys set as environment variables:
# For Claude backend
export ANTHROPIC_API_KEY="sk-ant-..."
# For Gemini backend
export GEMINI_API_KEY="AI..."
You can also create a .env file in the project root:
ANTHROPIC_API_KEY=sk-ant-...
GEMINI_API_KEY=AI...
Local models require no API keys. Models are automatically downloaded from HuggingFace Hub on first use and cached at ~/.cache/huggingface/hub/.
The default model is Jackrong/Qwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled-GGUF.
To use a model you've already downloaded locally, pass the file path directly:
python -m review_engine nih proposal.pdf --backend local --model ~/models/my-model.gguf
streamlit run streamlit_app.py
This opens a browser-based GUI where you can:
The sidebar shows API key status (cloud backends) or dependency status (local backend). Results are displayed in the main area with download buttons for both Markdown and PDF formats.
python -m review_engine <type> <pdf> [options]
Arguments:
| Argument | Description |
|---|---|
type | Review type: nih, foundation, or journal |
pdf | Path to PDF file (omit to open file picker) |
Options:
| Flag | Description | Default |
|---|---|---|
--backend, -b | AI backend: claude, gemini, or local | gemini |
--model, -m | Specific model ID | Backend default |
--max-rounds, -r | Maximum review rounds | Depends on type |
--output, -o | Output file path | <pdf_stem>_review.md |
--n-gpu-layers | GPU layers to offload (-1 = all, 0 = CPU only). Local backend only. | -1 |
--n-ctx | Context window size. Local backend only. | 8192 |
Examples:
# NIH review with Claude
python -m review_engine nih proposal.pdf --backend claude
# Journal review with Gemini
python -m review_engine journal manuscript.pdf --backend gemini
# Foundation review with a specific Claude model
python -m review_engine nih "C:\Users\alimo\OneDrive - UW-Madison\0 - Lab\Grants\2026\BRF\Research_Strategy.pdf" --backend claude --model claude-haiku-4-5-20251001
```bash
# Foundation review with a specific Gemini model
python -m review_engine foundation "C:\Users\alimo\OneDrive - UW-Madison\0 - Lab\Grants\2026\BRF\Research_Strategy.pdf" --backend gemini --model gemini-3.0-flash
python -m review_engine nih proposal.pdf --max-rounds 3
python -m review_engine nih proposal.pdf --backend local
python -m review_engine nih proposal.pdf --backend local --model ~/models/qwen.gguf
python -m review_engine nih proposal.pdf --backend local --n-gpu-layers 0
python -m review_engine nih "C:\Users\alimo\OneDrive - UW-Madison\0 - Lab\Grants\2026\BRF\Research_Strategy.pdf" --backend local --model QWEN/Qwen3.5-9B
### Python API
```python
from review_engine.config import ensure_types_loaded, get_config
from review_engine.engine import run_review
ensure_types_loaded()
config = get_config("nih") # or "foundation", "journal"
result_md = run_review(
config=config,
backend="gemini", # "claude", "gemini", or "local"
pdf_path="proposal.pdf",
model="gemini-2.0-flash",
max_rounds=2,
output_path="proposal_review.md",
on_chunk=lambda t: print(t, end=""), # streaming callback
on_status=lambda s: print(f"[{s}]"), # progress callback
)
Requires ANTHROPIC_API_KEY. Sends the PDF as a base64-encoded document.
| Model | Description |
|---|---|
claude-opus-4-6 | Most capable |
claude-sonnet-4-6 | Balanced performance/cost |
claude-opus-4-5 | Previous generation |
claude-sonnet-4-5-20250514 | Previous generation |
claude-haiku-4-5-20251001 | Fastest, default |
Automatic fallback: if the selected model fails, the engine tries each model in the chain above.
Requires GEMINI_API_KEY. Uploads the PDF to Gemini's File API.
| Model | Description |
|---|---|
gemini-2.0-flash | Default |
gemini-2.5-flash | Latest |
gemini-2.5-flash-lite-preview-06-17 | Lightweight |
Automatic fallback through the chain above.
No API key required. Runs entirely on your machine. Uses markitdown to convert PDFs to markdown text before sending to the model.
Two inference paths (auto-detected):
| Path | When used | Install |
|---|---|---|
| llama-cpp-python | Model ID contains "gguf" or file ends in .gguf | pip install llama-cpp-python |
| transformers | Standard HuggingFace models | pip install transformers torch |
Default model: Jackrong/Qwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled-GGUF
GPU support:
--n-gpu-layers 0 to forceEach review produces a Markdown file (and optionally a PDF) with the following structure:
# NIH Grant Review (Claude): proposal.pdf
## Review Metadata
| Field | Value |
|-------------|--------------------------|
| Backend | Claude |
| Model | claude-haiku-4-5-20251001|
| Review Type | NIH Grant Review |
| Started | 2025-03-09 14:30 UTC |
| Completed | 2025-03-09 14:45 UTC |
| Duration | 15m 23s |
## Table of Contents
- [Review Round 1](#review-round-1)
- [Summary Statement](#summary-statement)
- ...
## Review Round 1
### Primary Reviewer
(detailed critique with scoring)
### Secondary Reviewer
...
## Summary Statement (SRO)
...
### SRO Decision: Resubmit — Minor Revisions
## PI Response & Revised Application
...
agentic_writing/
├── streamlit_app.py # Streamlit web interface
├── environment.yml # Conda environment definition
├── requirements.txt # pip dependencies
│
├── review_engine/
│ ├── __main__.py # CLI entry point
│ ├── engine.py # Review orchestrator (ReviewSession)
│ ├── config.py # ReviewConfig data model & registry
│ ├── helpers.py # Prompt loading, parsing, PDF export
│ │
│ ├── backends/
│ │ ├── claude.py # Anthropic Claude backend
│ │ ├── gemini.py # Google Gemini backend
│ │ └── local.py # Local LLM backend (GGUF / transformers)
│ │
│ └── review_types/
│ ├── nih/
│ │ ├── config.py # NIH review configuration
│ │ ├── prompts/ # Agent prompt files
│ │ │ ├── primary_reviewer.txt
│ │ │ ├── secondary_reviewer.txt
│ │ │ ├── tertiary_reviewer.txt
│ │ │ ├── biostatistics.txt
│ │ │ ├── program_officer.txt
│ │ │ ├── challenge_pass.txt
│ │ │ ├── combined_reviewers.txt
│ │ │ ├── sro.txt
│ │ │ └── pi.txt
│ │ └── instructions/ # Scoring & criteria rubrics
│ │ ├── nih_scoring_scale.txt
│ │ ├── nih_criteria.txt
│ │ └── global_rules.txt
│ │
│ ├── foundation/
│ │ ├── config.py
│ │ ├── prompts/ # scientific_reviewer, innovation_reviewer,
│ │ │ # program_advisor, panel_chair, applicant, ...
│ │ └── instructions/
│ │
│ └── journal/
│ ├── config.py
│ ├── prompts/ # domain_expert, technical_reviewer,
│ │ # novelty_reviewer, editor, author, ...
│ └── instructions/
│
├── _shared/
│ ├── text.py # Text utilities (TOC, slugify, banner)
│ └── pdf.py # PDF utilities
│
└── tests/
├── test_engine.py # Engine & workflow tests
├── test_config.py # Config registry tests
├── test_helpers.py # Parsing & helper tests
├── test_backends.py # Backend tests
├── test_local_backend.py # Local backend tests
└── test_text.py # Text utility tests
# Run all tests
python -m pytest tests/ -v
# Run a specific test file
python -m pytest tests/test_engine.py -v
# Run with coverage
python -m pytest tests/ --cov=review_engine --cov-report=term-missing
The test suite covers config validation, decision parsing, revision extraction, TOC generation, backend validation, and engine workflow logic. Tests that require optional dependencies (Gemini SDK, markitdown) are automatically skipped if not installed.
This project is provided as-is for research and educational purposes.
39 commits
Python
100.0%
An AI-powered peer review system that simulates the full academic review process using multiple specialized agents. Upload a PDF and receive a structured review with reviewer critiques, independence audits, editorial decisions, and author revisions — all generated by coordinated AI agents.
Supports NIH grant reviews, foundation grant reviews, and journal manuscript peer reviews, with three AI backends: Claude, Gemini, and local open-source models.
Every review follows the same four-stage pipeline, regardless of review type:
PDF Document
|
v
+--------------------+
| 1. REVIEW PANEL | Multiple specialized reviewers independently
| (3-5 agents) | critique the document using domain-specific
+--------------------+ scoring criteria and rubrics
|
v
+--------------------+
| 2. INDEPENDENCE | A challenge agent audits all reviews for
| AUDIT | groupthink, confirmation bias, and
+--------------------+ produces addenda where warranted
|
v
+--------------------+
| 3. SYNTHESIZER | An SRO, Editor, or Panel Chair synthesizes
| (Decision) | the critiques into an official decision
+--------------------+ (e.g., Fundable, Accept, Revise, Reject)
|
v
+--------------------+
| 4. AUTHOR | The AI author/PI revises the document
| REVISION | based on all feedback, producing a
+--------------------+ point-by-point response and revised text
|
v
(Iterate or finish based on decision)
| Feature | NIH Grant Review | Foundation Grant Review | Journal Peer Review |
|---|---|---|---|
| Reviewers | Primary, Secondary, Tertiary, Biostatistician, Program Officer (5) | Scientific, Innovation, Program Advisor (3) | Domain Expert, Technical, Novelty (3) |
| Synthesizer | Scientific Review Officer (SRO) | Panel Chair | Editor |
| Author | Principal Investigator | Project Director | Author |
| Decision outcomes | Fundable, Resubmit (Minor/Major), NRFC | Fund, Fund with Conditions, Decline | Accept, Minor/Major Revision, Reject |
| Iteration mode | Iterative (up to N rounds) | Single pass (1 round) | Fixed 2 rounds |
| Scoring | NIH 1-9 scale | Foundation-specific criteria | Journal criteria |
Requires Python 3.10+ (3.11 recommended).
git clone https://github.com/mohebial/agentic_writing.git
cd agentic_writing
# Create and activate the environment
conda env create -f environment.yml
conda activate agentic_writing
git clone https://github.com/mohebial/agentic_writing.git
cd agentic_writing
pip install -r requirements.txt
To use local open-source models instead of cloud APIs:
# Required: PDF-to-markdown conversion
pip install markitdown
# For GGUF quantized models (recommended for most users):
pip install llama-cpp-python
# For standard HuggingFace models:
pip install transformers torch
Cloud backends require API keys set as environment variables:
# For Claude backend
export ANTHROPIC_API_KEY="sk-ant-..."
# For Gemini backend
export GEMINI_API_KEY="AI..."
You can also create a .env file in the project root:
ANTHROPIC_API_KEY=sk-ant-...
GEMINI_API_KEY=AI...
Local models require no API keys. Models are automatically downloaded from HuggingFace Hub on first use and cached at ~/.cache/huggingface/hub/.
The default model is Jackrong/Qwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled-GGUF.
To use a model you've already downloaded locally, pass the file path directly:
python -m review_engine nih proposal.pdf --backend local --model ~/models/my-model.gguf
streamlit run streamlit_app.py
This opens a browser-based GUI where you can:
The sidebar shows API key status (cloud backends) or dependency status (local backend). Results are displayed in the main area with download buttons for both Markdown and PDF formats.
python -m review_engine <type> <pdf> [options]
Arguments:
| Argument | Description |
|---|---|
type | Review type: nih, foundation, or journal |
pdf | Path to PDF file (omit to open file picker) |
Options:
| Flag | Description | Default |
|---|---|---|
--backend, -b | AI backend: claude, gemini, or local | gemini |
--model, -m | Specific model ID | Backend default |
--max-rounds, -r | Maximum review rounds | Depends on type |
--output, -o | Output file path | <pdf_stem>_review.md |
--n-gpu-layers | GPU layers to offload (-1 = all, 0 = CPU only). Local backend only. | -1 |
--n-ctx | Context window size. Local backend only. | 8192 |
Examples:
# NIH review with Claude
python -m review_engine nih proposal.pdf --backend claude
# Journal review with Gemini
python -m review_engine journal manuscript.pdf --backend gemini
# Foundation review with a specific Claude model
python -m review_engine nih "C:\Users\alimo\OneDrive - UW-Madison\0 - Lab\Grants\2026\BRF\Research_Strategy.pdf" --backend claude --model claude-haiku-4-5-20251001
```bash
# Foundation review with a specific Gemini model
python -m review_engine foundation "C:\Users\alimo\OneDrive - UW-Madison\0 - Lab\Grants\2026\BRF\Research_Strategy.pdf" --backend gemini --model gemini-3.0-flash
python -m review_engine nih proposal.pdf --max-rounds 3
python -m review_engine nih proposal.pdf --backend local
python -m review_engine nih proposal.pdf --backend local --model ~/models/qwen.gguf
python -m review_engine nih proposal.pdf --backend local --n-gpu-layers 0
python -m review_engine nih "C:\Users\alimo\OneDrive - UW-Madison\0 - Lab\Grants\2026\BRF\Research_Strategy.pdf" --backend local --model QWEN/Qwen3.5-9B
### Python API
```python
from review_engine.config import ensure_types_loaded, get_config
from review_engine.engine import run_review
ensure_types_loaded()
config = get_config("nih") # or "foundation", "journal"
result_md = run_review(
config=config,
backend="gemini", # "claude", "gemini", or "local"
pdf_path="proposal.pdf",
model="gemini-2.0-flash",
max_rounds=2,
output_path="proposal_review.md",
on_chunk=lambda t: print(t, end=""), # streaming callback
on_status=lambda s: print(f"[{s}]"), # progress callback
)
Requires ANTHROPIC_API_KEY. Sends the PDF as a base64-encoded document.
| Model | Description |
|---|---|
claude-opus-4-6 | Most capable |
claude-sonnet-4-6 | Balanced performance/cost |
claude-opus-4-5 | Previous generation |
claude-sonnet-4-5-20250514 | Previous generation |
claude-haiku-4-5-20251001 | Fastest, default |
Automatic fallback: if the selected model fails, the engine tries each model in the chain above.
Requires GEMINI_API_KEY. Uploads the PDF to Gemini's File API.
| Model | Description |
|---|---|
gemini-2.0-flash | Default |
gemini-2.5-flash | Latest |
gemini-2.5-flash-lite-preview-06-17 | Lightweight |
Automatic fallback through the chain above.
No API key required. Runs entirely on your machine. Uses markitdown to convert PDFs to markdown text before sending to the model.
Two inference paths (auto-detected):
| Path | When used | Install |
|---|---|---|
| llama-cpp-python | Model ID contains "gguf" or file ends in .gguf | pip install llama-cpp-python |
| transformers | Standard HuggingFace models | pip install transformers torch |
Default model: Jackrong/Qwen3.5-27B-Claude-4.6-Opus-Reasoning-Distilled-GGUF
GPU support:
--n-gpu-layers 0 to forceEach review produces a Markdown file (and optionally a PDF) with the following structure:
# NIH Grant Review (Claude): proposal.pdf
## Review Metadata
| Field | Value |
|-------------|--------------------------|
| Backend | Claude |
| Model | claude-haiku-4-5-20251001|
| Review Type | NIH Grant Review |
| Started | 2025-03-09 14:30 UTC |
| Completed | 2025-03-09 14:45 UTC |
| Duration | 15m 23s |
## Table of Contents
- [Review Round 1](#review-round-1)
- [Summary Statement](#summary-statement)
- ...
## Review Round 1
### Primary Reviewer
(detailed critique with scoring)
### Secondary Reviewer
...
## Summary Statement (SRO)
...
### SRO Decision: Resubmit — Minor Revisions
## PI Response & Revised Application
...
agentic_writing/
├── streamlit_app.py # Streamlit web interface
├── environment.yml # Conda environment definition
├── requirements.txt # pip dependencies
│
├── review_engine/
│ ├── __main__.py # CLI entry point
│ ├── engine.py # Review orchestrator (ReviewSession)
│ ├── config.py # ReviewConfig data model & registry
│ ├── helpers.py # Prompt loading, parsing, PDF export
│ │
│ ├── backends/
│ │ ├── claude.py # Anthropic Claude backend
│ │ ├── gemini.py # Google Gemini backend
│ │ └── local.py # Local LLM backend (GGUF / transformers)
│ │
│ └── review_types/
│ ├── nih/
│ │ ├── config.py # NIH review configuration
│ │ ├── prompts/ # Agent prompt files
│ │ │ ├── primary_reviewer.txt
│ │ │ ├── secondary_reviewer.txt
│ │ │ ├── tertiary_reviewer.txt
│ │ │ ├── biostatistics.txt
│ │ │ ├── program_officer.txt
│ │ │ ├── challenge_pass.txt
│ │ │ ├── combined_reviewers.txt
│ │ │ ├── sro.txt
│ │ │ └── pi.txt
│ │ └── instructions/ # Scoring & criteria rubrics
│ │ ├── nih_scoring_scale.txt
│ │ ├── nih_criteria.txt
│ │ └── global_rules.txt
│ │
│ ├── foundation/
│ │ ├── config.py
│ │ ├── prompts/ # scientific_reviewer, innovation_reviewer,
│ │ │ # program_advisor, panel_chair, applicant, ...
│ │ └── instructions/
│ │
│ └── journal/
│ ├── config.py
│ ├── prompts/ # domain_expert, technical_reviewer,
│ │ # novelty_reviewer, editor, author, ...
│ └── instructions/
│
├── _shared/
│ ├── text.py # Text utilities (TOC, slugify, banner)
│ └── pdf.py # PDF utilities
│
└── tests/
├── test_engine.py # Engine & workflow tests
├── test_config.py # Config registry tests
├── test_helpers.py # Parsing & helper tests
├── test_backends.py # Backend tests
├── test_local_backend.py # Local backend tests
└── test_text.py # Text utility tests
# Run all tests
python -m pytest tests/ -v
# Run a specific test file
python -m pytest tests/test_engine.py -v
# Run with coverage
python -m pytest tests/ --cov=review_engine --cov-report=term-missing
The test suite covers config validation, decision parsing, revision extraction, TOC generation, backend validation, and engine workflow logic. Tests that require optional dependencies (Gemini SDK, markitdown) are automatically skipped if not installed.
This project is provided as-is for research and educational purposes.
39 commits
Python
100.0%