Skip to main content

AI-powered academic paper generation SDK

Project description

EasyPaper

EasyPaper is a multi-agent academic paper generation system. It turns a small set of metadata (title, idea, method, data, experiments, references) into a structured LaTeX paper and optionally compiles it into a PDF through a typesetting agent.

Features

  • Python SDKpip install easypaper, then import easypaper in your own project
  • Streaming generation — async generator yields real-time progress events at each phase
  • Multi-agent pipeline: planning, writing, review, typesetting, and optional VLM review
  • Optional FastAPI server mode with health and agent discovery endpoints
  • LaTeX output with citation validation, figure/table injection, and review loop

Requirements

  • Python 3.11+
  • LaTeX toolchain (pdflatex + bibtex) for PDF compilation
  • Poppler — required by pdf2image for PDF-to-image conversion
    • macOS: brew install poppler
    • Ubuntu/Debian: apt install poppler-utils
  • Model API keys configured in YAML (see Config)

SDK Usage

Install from PyPI:

pip install easypaper

One-shot generation

Inline metadata:

import asyncio
from easypaper import EasyPaper, PaperMetaData

async def main():
    ep = EasyPaper(config_path="config.yaml")

    metadata = PaperMetaData(
        title="My Paper Title",
        idea_hypothesis="...",
        method="...",
        data="...",
        experiments="...",
    )

    result = await ep.generate(metadata)
    print(result.status, result.total_word_count)
    for sec in result.sections:
        print(f"  {sec.section_type}: {sec.word_count} words")

asyncio.run(main())

Load metadata from a JSON file (recommended):
Prepare a metadata.json (see examples/meta.json for the full schema). The clean SDK flow is to parse as PaperGenerationRequest, then split into content metadata and runtime options:

import asyncio
from easypaper import EasyPaper, PaperGenerationRequest

async def main():
    ep = EasyPaper(config_path="config.yaml")

    request = PaperGenerationRequest.model_validate_json_file("metadata.json")
    metadata = request.to_metadata()
    options = request.to_generate_options()

    result = await ep.generate(metadata, **options)
    print(result.status, result.total_word_count)

asyncio.run(main())

For a minimal metadata-only JSON (no runtime options), you can use:

metadata = PaperMetaData.model_validate_json_file("metadata.json")
result = await ep.generate(metadata)

Streaming generation

Use generate_stream() to receive real-time progress events via async generator. Metadata can be built inline or loaded from a JSON file (e.g. PaperMetaData.model_validate_json_file("metadata.json")).

import asyncio
from easypaper import EasyPaper, PaperMetaData, EventType

async def main():
    ep = EasyPaper(config_path="config.yaml")
    metadata = PaperMetaData.model_validate_json_file("metadata.json")  # or build inline

    async for event in ep.generate_stream(metadata):
        if event.event_type == EventType.PHASE_START:
            print(f"▶ [{event.phase}] {event.message}")
        elif event.event_type == EventType.SECTION_COMPLETE:
            print(f"  ✎ {event.phase} done")
        elif event.event_type == EventType.COMPLETE:
            result = event.data["result"]
            print(f"Done! {result['total_word_count']} words")

asyncio.run(main())

GenerationEvent fields:

Field Type Description
event_type EventType PHASE_START, PHASE_COMPLETE, SECTION_COMPLETE, PROGRESS, WARNING, ERROR, COMPLETE
phase str Logical phase name (e.g. "planning", "introduction", "body")
message str Human-readable description
data dict | None Structured payload (section content, final result, etc.)
timestamp datetime When the event was created

A complete working example is available in user_case/.

Server Mode

To run EasyPaper as a FastAPI service (requires the server extra):

pip install "easypaper[server]"
  1. Copy the example config and fill in your API keys:
cp configs/example.yaml configs/dev.yaml
  1. Start the server:
uvicorn easypaper.main:app --reload --port 8000
  1. Generate via API:
curl -X POST http://localhost:8000/metadata/generate \
  -H "Content-Type: application/json" \
  -d @economist_example/metadata.json

Skills

EasyPaper includes a pluggable Skills system that injects writing constraints, venue-specific formatting rules, and reviewer checkers into the generation pipeline. Built-in skills are bundled as static assets inside the easypaper package:

Category Skills Description
Writing anti-ai-style, academic-polish, latex-conventions Style constraints applied to all sections — eliminates AI-flavored phrasing, enforces academic tone, ensures LaTeX best practices
Venues neurips, icml, iclr, acl, aaai, colm, nature Conference/journal profiles with page limits, formatting rules, and venue-specific style requirements
Reviewing logic-check, style-check Reviewer checker prompts — detects logical contradictions, terminology inconsistencies, and style violations

Enabling skills

Built-in skills are loaded by default. You only need enabled/active_skills in config:

skills:
  enabled: true
  active_skills:
    - "*"                   # "*" = load all skills; or list specific names

If you add skills.skills_dir, EasyPaper merges bundled skills with that directory: same skill name → your file wins. If the path is missing, bundled skills still load and a warning is logged.

Venue profiles

To apply venue-specific constraints (e.g. page limits, formatting), set style_guide in your PaperMetaData to match a venue profile name:

metadata = PaperMetaData(
    title="...",
    idea_hypothesis="...",
    method="...",
    data="...",
    experiments="...",
    style_guide="neurips",   # activates the neurips venue profile
)

Custom skills

Each skill is a single YAML file with the following structure:

name: my-custom-skill
description: "What this skill does"
type: writing_constraint   # writing_constraint | reviewer_checker | venue_profile
target_sections: ["*"]     # ["*"] = all sections, or specific ones
priority: 10               # lower = higher priority

system_prompt_append: |
  ## My Custom Rules
  - Rule 1: ...
  - Rule 2: ...

anti_patterns:
  - "word to avoid"

Drop the file into your skills_dir and it will be automatically loaded on the next run. See the built-in skills in easypaper/assets/skills/ for complete examples.

Config

The application loads configuration from AGENT_CONFIG_PATH (defaults to ./configs/dev.yaml). You can also set this variable in a .env file at the project root.

See configs/example.yaml for a fully commented configuration template. Each agent entry defines its model and optional agent-specific settings.

Key fields per agent:

  • model_name — LLM model identifier
  • api_key — API key for the model provider
  • base_url — API endpoint URL

Additional top-level sections:

  • skills — skills system toggle and active skill list (see Skills)
  • tools — ReAct tool configuration (citation validation, paper search, etc.)
  • vlm_service — shared VLM provider for visual review (supports OpenAI-compatible and Claude)

Repository Layout

  • easypaper/ — SDK core, agent implementations, event system, shared utilities
  • configs/ — YAML configs for agents and models
  • skills/ — backend YAML skills loaded by the Python service
  • plugins/easypaper/ — Claude/OpenCode plugin root (commands + SKILL.md prompts)
  • .claude-plugin/marketplace.json — marketplace catalog
  • .opencode/opencode.json — OpenCode/OpenClaw runtime configuration
  • AGENTS.md — repository-level instructions for coding agents
  • scripts/ — CLI utilities and demos
  • user_case/ — standalone usage example (independent environment)
  • economist_example/ — sample metadata input

Claude Code Plugin Market

This repository ships a Claude Code marketplace with one installable plugin located at plugins/easypaper.

Installation

Add the marketplace:

/plugin marketplace add https://github.com/your-username/easypaper

Install the plugin from this marketplace:

/plugin install easypaper@easypaper

Available Plugin

Plugin Source Description
easypaper ./plugins/easypaper Generate AI-powered academic papers from metadata interactively

Usage

After installation:

/easypaper

Related commands:

/paper-from-metadata
/paper-section

Plugin Prerequisites

  • Python 3.11+
  • easypaper package installed (pip install easypaper)
  • LaTeX toolchain (pdflatex + bibtex) for PDF compilation
  • API key for LLM provider (configured via config file)

OpenCode / OpenClaw Usage

This repository includes native OpenCode/OpenClaw configuration in .opencode/opencode.json.

Run directly in this repository

opencode

The runtime loads:

  • Plugin path: ./plugins/easypaper
  • Skills: plugins/easypaper/skills/*/SKILL.md
  • Commands: easypaper, paper-from-metadata, paper-section

For both Claude Code and OpenCode/OpenClaw workflows, start the EasyPaper API service before generation:

uv run uvicorn easypaper.main:app --reload --port 8000

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

easypaper-0.1.5.tar.gz (303.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

easypaper-0.1.5-py3-none-any.whl (341.1 kB view details)

Uploaded Python 3

File details

Details for the file easypaper-0.1.5.tar.gz.

File metadata

  • Download URL: easypaper-0.1.5.tar.gz
  • Upload date:
  • Size: 303.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for easypaper-0.1.5.tar.gz
Algorithm Hash digest
SHA256 ea20039274c6e7cd95d6a66d33962055528fe34a4ce7318a51f3ea02c4b377d5
MD5 abdaa563da7d576cec52c73037d24f24
BLAKE2b-256 d07146f5e24731414b3920391d385f8fb596a087871da2ee2317cb50a2064b76

See more details on using hashes here.

File details

Details for the file easypaper-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: easypaper-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 341.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for easypaper-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 47fc3f6b3ca8acf77370c36025e90c0fdb4440405bc20402d3e702e722f0babf
MD5 ed8050da734a68041e5974c48c92139f
BLAKE2b-256 26d341ae93ad6aed1f4c98d3a53cd0ded09fbc53a2ad54564740e8eb1e354f04

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page