Skip to content

Commit c754ecb

Browse files
Federico De PonteFederico De Ponte
authored andcommitted
feat: add Chicago (Author-Date) and MLA 9th Edition citation styles
Implement full formatting support for Chicago and MLA citation styles across in-text citations, reference lists, and the generation pipeline. Wire citation_style parameter through CLI, backend worker, and both copies of draft_generator. Add 17 tests covering all formatters.
1 parent 2ef2cd9 commit c754ecb

7 files changed

Lines changed: 644 additions & 6 deletions

File tree

docs/ARCHITECTURE.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# OpenDraft Architecture
2+
3+
## Engine Overview
4+
5+
OpenDraft uses a multi-agent pipeline to generate academic papers. The engine is in `engine/` with a backend copy in `backend/` for the web worker.
6+
7+
### Core Pipeline
8+
9+
```
10+
CLI / Web API
11+
-> generate_draft()
12+
-> Scout Agent (research + citations)
13+
-> Architect Agent (outline)
14+
-> Formatter Agent (style)
15+
-> Scribe/Crafter/Enhancer Agents (writing)
16+
-> Citation Compiler (replace {cite_XXX} with formatted citations)
17+
-> Export (PDF + DOCX)
18+
```
19+
20+
---
21+
22+
## Citation System
23+
24+
### Components
25+
26+
| Component | File | Purpose |
27+
|-----------|------|---------|
28+
| Citation model | `engine/utils/citation_database.py` | `Citation` class, `CitationDatabase`, `CitationStyle` type |
29+
| Citation compiler | `engine/utils/citation_compiler.py` | In-text formatting, reference list generation, missing citation research |
30+
| Citation researcher | `engine/utils/api_citations/` | Crossref, Semantic Scholar, Gemini fallback chain |
31+
32+
### Supported Citation Styles
33+
34+
The citation compiler supports four styles, configured via the `CitationStyle` literal type:
35+
36+
- **APA 7th** -- `(Author, Year)` in-text, alphabetical references
37+
- **IEEE** -- `[N]` numbered in-text, order-of-appearance references
38+
- **Chicago (Author-Date)** -- `(Author Year)` in-text, alphabetical references
39+
- **MLA 9th Edition** -- `(Author)` in-text (no year), alphabetical Works Cited
40+
41+
Style is selected in the CLI (`--style` flag or interactive menu) and flows through `generate_draft()` -> `CitationDatabase` -> `CitationCompiler`.
42+
43+
### Citation Flow
44+
45+
1. Scout agent discovers citations via API (Crossref, Semantic Scholar)
46+
2. Citations stored in `CitationDatabase` with chosen style
47+
3. Writing agents reference citations as `{cite_001}`, `{cite_002}`, etc.
48+
4. `CitationCompiler.compile_citations()` replaces placeholders with formatted in-text citations
49+
5. `CitationCompiler.generate_reference_list()` appends the reference/bibliography section
50+
51+
---
52+
53+
## Entry Points
54+
55+
| Entry Point | File | Notes |
56+
|-------------|------|-------|
57+
| CLI (interactive + quick) | `engine/opendraft/cli.py` | `--style` flag for citation style |
58+
| Backend worker | `backend/worker.py` | Reads from job record, defaults to APA |
59+
| Web API | `app/app/api/thesis/generate/route.ts` | Citation style not yet exposed |
60+
| Benchmarks | `benchmark/run_opendraft.py` | Always uses default APA |

docs/CITATION_STYLES_ROADMAP.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Citation Styles Roadmap
2+
3+
## Overview
4+
5+
Multi-style citation support for the OpenDraft citation compiler. Citations are formatted for both in-text references and full reference lists.
6+
7+
---
8+
9+
## Phase 1: Chicago & MLA (Complete)
10+
11+
**Status:** Complete
12+
13+
**Styles added:**
14+
- **Chicago (Author-Date)** -- In-text: `(Smith 2023)`, `(Smith and Johnson 2023)`, `(Smith et al. 2023)`
15+
- **MLA 9th Edition** -- In-text: `(Smith)`, `(Smith and Johnson)`, `(Smith et al.)`
16+
17+
**Files changed:**
18+
- `engine/utils/citation_compiler.py` -- Formatter methods + dispatch
19+
- `engine/draft_generator.py` -- `citation_style` parameter, style resolution
20+
- `backend/draft_generator.py` -- Same as above (backend copy)
21+
- `backend/worker.py` -- Pass-through from job record
22+
- `engine/opendraft/cli.py` -- Wire style to `generate_draft()`
23+
- `tests/test_citation_styles.py` -- 17 tests
24+
25+
**Reference formats supported per source type:** journal, book, conference, report/website, fallback.
26+
27+
**Sorting:** Chicago and MLA reference lists are sorted alphabetically by first author (same as APA).
28+
29+
---
30+
31+
## Phase 2: Harvard & Vancouver (Planned)
32+
33+
**Status:** Not started
34+
35+
- **Harvard** -- Similar to APA but with minor formatting differences
36+
- **Vancouver** -- Numbered style similar to IEEE, used in medical/biomedical fields
37+
38+
---
39+
40+
## Phase 3: Web API Integration (Planned)
41+
42+
**Status:** Not started
43+
44+
- Expose `citation_style` in the web API route (`app/app/api/thesis/generate/route.ts`)
45+
- Add `citation_style` column to the database schema
46+
- Frontend UI for style selection
47+
48+
---
49+
50+
## Supported Styles Summary
51+
52+
| Style | In-Text Format | Reference Sorting | Status |
53+
|-------|---------------|-------------------|--------|
54+
| APA 7th | `(Smith, 2023)` | Alphabetical | Shipped |
55+
| IEEE | `[1]` | Order of appearance | Shipped |
56+
| Chicago | `(Smith 2023)` | Alphabetical | Shipped |
57+
| MLA | `(Smith)` | Alphabetical | Shipped |
58+
| Harvard | TBD | TBD | Planned |
59+
| Vancouver | TBD | TBD | Planned |

engine/draft_generator.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,7 @@ def generate_draft(
714714
second_examiner: Optional[str] = None,
715715
location: Optional[str] = None,
716716
student_id: Optional[str] = None,
717+
citation_style: str = "apa",
717718
) -> Tuple[Path, Path]:
718719
"""
719720
Generate a complete academic draft using 19 specialized AI agents.
@@ -737,6 +738,7 @@ def generate_draft(
737738
second_examiner: Second examiner name
738739
location: City/location for date line
739740
student_id: Student matriculation number
741+
citation_style: Citation style shorthand ('apa', 'ieee', 'chicago', 'mla')
740742
741743
Returns:
742744
Tuple[Path, Path]: (pdf_path, docx_path) - Paths to generated draft files
@@ -760,6 +762,11 @@ def generate_draft(
760762
# STARTUP AND INITIALIZATION
761763
# ====================================================================
762764
draft_start_time = time.time()
765+
766+
# Resolve citation style shorthand to full name
767+
style_map = {"apa": "APA 7th", "ieee": "IEEE", "chicago": "Chicago", "mla": "MLA"}
768+
resolved_style = style_map.get(citation_style, "APA 7th")
769+
763770
logger.info("="*80)
764771
logger.info("DRAFT GENERATION STARTED")
765772
logger.info("="*80)
@@ -1015,7 +1022,7 @@ def progress_callback(message: str, event_type: str) -> None:
10151022
model=model,
10161023
name="Formatter - Apply Style",
10171024
prompt_path="prompts/02_structure/formatter.md",
1018-
user_input=f"Apply academic formatting:\n\n{architect_output[:2500]}\n\nStyle: APA 7th edition",
1025+
user_input=f"Apply academic formatting:\n\n{architect_output[:2500]}\n\nStyle: {resolved_style} edition",
10191026
save_to=folders['drafts'] / "00_formatted_outline.md",
10201027
skip_validation=skip_validation,
10211028
verbose=verbose
@@ -1049,7 +1056,7 @@ def progress_callback(message: str, event_type: str) -> None:
10491056

10501057
citation_database = CitationDatabase(
10511058
citations=scout_citations,
1052-
citation_style="APA 7th",
1059+
citation_style=resolved_style,
10531060
draft_language=get_language_name(language).lower()
10541061
)
10551062

engine/opendraft/cli.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,8 @@ def run_interactive():
666666
author_name=author_name,
667667
institution=institution,
668668
department=department,
669-
advisor=advisor
669+
advisor=advisor,
670+
citation_style=style
670671
)
671672

672673
print()
@@ -919,7 +920,8 @@ def main():
919920
author_name=args.author,
920921
institution=args.institution,
921922
department=args.department,
922-
advisor=args.advisor
923+
advisor=args.advisor,
924+
citation_style=args.style
923925
)
924926

925927
print()

0 commit comments

Comments
 (0)