PDF Generation & Filling
Relevant source files
The following files were used as context for generating this wiki page:
The PDF Generation & Filling module is a core component of the Rosy Tax Processor responsible for transforming extracted tax data and calculated results into a human-readable Form 1040. It supports three distinct modes of output: filling a pre-existing fillable PDF template, generating a fresh PDF layout using ReportLab, or falling back to a plain text draft if PDF libraries are unavailable.
The module acts as the final stage of the tax processing pipeline, bridging the gap between raw data extraction and the delivery of a completed tax document to the user. It utilizes semantic mapping to align internal data keys with the specific field names required by official or synthetic PDF forms.
Sources: forms.py:1-12, README.md:16-25, pipeline.py:11-20
System Architecture & Data Flow
The PDF generation process is orchestrated through a hierarchical decision tree. When a request is made to generate a draft, the system first checks for the existence of a fillable template (1040_fillable.pdf). If found, it attempts to map extracted fields to the template's AcroForm fields. If no template exists or the filling process fails, it creates a custom PDF via ReportLab.
The following diagram illustrates the decision logic and data flow within the generation module:
Logic flow for determining the PDF generation method.
Sources: forms.py:119-183, pipeline.py:80-95
Template-Based Form Filling
The system utilizes the pdfrw library to manipulate AcroForm fields within PDF templates. This process involves iterating through the annotations on each page of the PDF, identifying /Widget subtypes with a name (/T), and updating their value (/V).
Key Functions
| Function | Description |
|---|---|
fill_fillable_1040 | Opens a template, iterates through AcroForm fields, sets values, and sets NeedAppearances to True. |
create_exact_field_map | Provides a hardcoded mapping for the project's synthetic 1040 template. |
inspect | Tool-based function used to extract all field names from a PDF for development purposes. |
Sources: forms.py:32-55, forms.py:88-117, tools/inspect_pdf_fields.py:38-55
AcroForm Field Mapping
The system targets specific field names within the PDF. The synthetic template includes the following primary fields:
[
"(YourFirstName)", "(YourLastName)", "(SSN)",
"(Wages)", "(FederalIncomeTaxWithheld)",
"(AdjustedGrossIncome)", "(TaxableIncome)",
"(TotalTax)", "(TaxDue)"
]
Sources: templates/1040_fields.json:1-17, tools/generate_sample_1040_template.py:23-36
Semantic Auto-Mapping
When exact field names are unknown or the mapping is incomplete, the auto_mapper utility is invoked. This module uses semantic similarity to match parsed data (e.g., "wages") to template field names (e.g., "Box1_Wages").
Sequence of the semantic mapping process.
Sources: utils/auto_mapper.py:40-75, forms.py:155-175
Mapping Strategies
- Semantic Embeddings: Uses the
all-MiniLM-L6-v2model to compute cosine similarity between field names. - String Similarity: A fallback mechanism using
difflib.SequenceMatcherwith a token-based bonus if specific keywords match. - Thresholding: The system typically accepts mappings with a confidence score $\ge 0.4$.
Sources: utils/auto_mapper.py:17-38, forms.py:168-175
ReportLab Generation & Fallbacks
If a template is not available, the system uses the reportlab library to draw a fresh PDF from scratch.
ReportLab PDF Generation
The generate_1040_pdf function creates a two-page document:
- Page 1: Header and a list of all extracted fields.
- Page 2: A summary of the tax calculation results (AGI, taxable income, tax due).
Sources: forms.py:61-86
Plain Text Fallback
In environments where neither pdfrw nor reportlab is installed, the system defaults to _generate_text_draft. This produces a .txt file containing the same data as the PDF draft, ensuring the system remains functional on minimal installations.
Sources: forms.py:19-30, forms.py:68-70
Integration with Backend API
The generation logic is exposed via the /finalize endpoint in backend.py. This endpoint aggregates edited data from the frontend, re-computes the tax estimate, and triggers the PDF generation.
@app.route('/finalize', methods=['POST'])
def finalize():
# ... aggregation logic ...
tax = compute_tax_estimate(agg_fields, filing_status=filing_status)
form_path = generate_1040_draft(agg_fields, tax, out_dir)
return send_file(form_path, mimetype='application/pdf')
Sources: backend.py:100-141
Summary
The PDF Generation & Filling module provides a robust end-of-pipeline solution for document creation. By combining explicit field mapping for known templates with AI-driven semantic mapping for unknown forms, it ensures that tax data is accurately placed within official-style documents. Its multi-tiered fallback system (Fillable PDF $\rightarrow$ ReportLab PDF $\rightarrow$ Text) guarantees output generation regardless of the specific library support available in the host environment.