Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fd57583
feat: :sparkles: first implementation of the benchmark, including fro…
marcvergees Aug 1, 2026
91fd496
fix: :bug: fixing test passing with empty structure of everything
marcvergees Aug 3, 2026
4927d9a
style: :lipstick: adding notes for guys
marcvergees Aug 3, 2026
73a382c
feat: add large-model reference evaluator
vharkins1 Aug 12, 2026
684ebfa
ics201 & 202
marcvergees Aug 13, 2026
fe000b1
ics203
marcvergees Aug 13, 2026
d9f0499
ics204
marcvergees Aug 13, 2026
a3ab05a
ics205 & ics205a
marcvergees Aug 13, 2026
2f24ff8
ics 206 & ics 213
marcvergees Aug 13, 2026
559030d
ics207 & ics 208
marcvergees Aug 13, 2026
2a6cd2b
ICS dataset generation markdown
marcvergees Aug 13, 2026
ce908a5
Merge pull request #663 from fireform-core/659-dataset-creations
vharkins1 Aug 13, 2026
2dd9e3a
refactor: :recycle: linting errors
marcvergees Aug 13, 2026
157e01a
linter errors 2
marcvergees Aug 13, 2026
86ade1b
Merge pull request #662 from fireform-core/612-feat-benchmark-module-…
marcvergees Aug 13, 2026
ee498da
Merge branch 'development' into development-approach-b-benchmark
marcvergees Aug 14, 2026
ce13416
feat: :sparkles: first approach of pipeline B implementation
marcvergees Aug 14, 2026
cb25b47
feat: :sparkles: add ics201-208 & 213 pdfs
marcvergees Aug 14, 2026
13806d2
refactor: :recycle: delete reference_benchmarks
marcvergees Aug 14, 2026
2378c26
feat: :sparkles: implementation of pdfs in the runner
marcvergees Aug 14, 2026
57d3d3b
Merge pull request #668 from fireform-core/667-add-pdfs-to-benchmark
marcvergees Aug 14, 2026
c6eebea
Merge branch 'development' into development-approach-b-benchmark
marcvergees Aug 14, 2026
9d02116
feat: :sparkles: template creation adjusted based on pdf_path
marcvergees Aug 14, 2026
9b22dbd
refactor: :recycle: linter
marcvergees Aug 14, 2026
1cca27d
fix: :bug: removing field confidence in pipelineextractionoutput stru…
marcvergees Aug 14, 2026
2e2dee6
fix: :bug: sqlalchemy errors
marcvergees Aug 14, 2026
a74f5a5
fix: :bug: celery.py was importing celery but never calling it
marcvergees Aug 14, 2026
5b67c73
fix: :bug: Added ConfigDict to the pydantic import. Replaced the nest…
marcvergees Aug 14, 2026
bbcfa76
style: :lipstick: runner logging
marcvergees Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Run Pipeline Benchmark

on:
pull_request:
branches: [ main, development ]

jobs:
benchmark:
runs-on: ubuntu-latest

services:
ollama:
image: ollama/ollama:latest
ports:
- 11434:11434

steps:
- name: Checkout PR Branch
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'

- name: Install dependencies
run: |
pip install -r requirements.txt
pip install pytest

- name: Run PR Branch Benchmark
run: |
pytest benchmark/test_benchmark.py -v
mv benchmark/benchmark_report.json branch_report.json

- name: Checkout Target Branch
uses: actions/checkout@v4
with:
ref: ${{ github.base_ref }}
clean: false

- name: Run Target Branch Benchmark
run: |
pytest benchmark/test_benchmark.py -v
mv benchmark/benchmark_report.json target_report.json

- name: Compare Benchmarks
id: compare
run: |
python benchmark/compare_benchmarks.py branch_report.json target_report.json > comparison.md
cat comparison.md

- name: Comment PR with results
uses: thollander/actions-comment-pull-request@v3
with:
filePath: comparison.md
14 changes: 11 additions & 3 deletions alembic/env.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
from logging.config import fileConfig

from alembic import context
from sqlalchemy import engine_from_config, pool

from sqlmodel import SQLModel

from alembic import context
from app.core.config import DATABASE_URL
from app.models import Extraction, Form, FormSubmission, Incident, Input, Job, Report, Template # noqa: F401
from app.models import ( # noqa: F401
Extraction,
Form,
FormSubmission,
Incident,
Input,
Job,
Report,
Template,
)

config = context.config

Expand Down
3 changes: 2 additions & 1 deletion alembic/versions/001_initial_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"""
from collections.abc import Sequence

from alembic import op
import sqlalchemy as sa
import sqlmodel

from alembic import op

revision: str = "001"
down_revision: str | None = None
branch_labels: str | Sequence[str] | None = None
Expand Down
3 changes: 2 additions & 1 deletion alembic/versions/002_v1_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@

from collections.abc import Sequence

from alembic import op
import sqlalchemy as sa
import sqlmodel

from alembic import op

revision: str = "002"
down_revision: str | None = "001"
branch_labels: str | Sequence[str] | None = None
Expand Down
4 changes: 3 additions & 1 deletion app/api/deps.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from app.db.database import get_session
from fastapi import Header, Request

from app.core.config import FIREFORM_API_KEY
from app.core.errors.base import AppError
from app.db.database import get_session


def get_db():
yield from get_session()
Expand Down
4 changes: 2 additions & 2 deletions app/api/routes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from . import templates, forms
from . import forms, templates

__all__ = ["templates", "forms"]
__all__ = ["forms", "templates"]
14 changes: 10 additions & 4 deletions app/api/routes/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from pathlib import Path

import requests
from fastapi import APIRouter, Depends, File, UploadFile, Query
from fastapi import APIRouter, Depends, File, Query, UploadFile
from sqlmodel import Session

from app.api.deps import get_db, verify_api_key
Expand All @@ -10,11 +11,16 @@
ModelsResponse,
TranscriptionResponse,
)
from app.core.config import OLLAMA_HOST, OLLAMA_MODEL, BASE_DIR, RETENTION_PERIOD_DAYS
from app.services.whisper import call_whisper_asr
from app.core.config import BASE_DIR, OLLAMA_HOST, OLLAMA_MODEL, RETENTION_PERIOD_DAYS
from app.core.errors.base import AppError
from app.db.repositories import get_template, get_form_submission, delete_form_submission
from app.db.repositories import (
delete_form_submission,
get_form_submission,
get_template,
)
from app.models import FormSubmission

Check failure on line 21 in app/api/routes/forms.py

View workflow job for this annotation

GitHub Actions / lint

ruff (F401)

app/api/routes/forms.py:21:24: F401 `app.models.FormSubmission` imported but unused help: Remove unused import: `app.models.FormSubmission`
from app.services.form import FormService
from app.services.whisper import call_whisper_asr

PROJECT_ROOT = BASE_DIR

Expand Down
3 changes: 2 additions & 1 deletion app/api/routes/input.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
INPUT_POLL_INTERVAL_SECONDS,
)
from app.core.errors.base import AppError
from app.db.repositories import create_input, get_input as repo_get_input
from app.db.repositories import create_input
from app.db.repositories import get_input as repo_get_input
from app.services.input import InputService
from app.services.whisper import check_whisper_available

Expand Down
4 changes: 2 additions & 2 deletions app/api/routes/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

from app.api.deps import get_db, verify_api_key
from app.api.schemas.templates import (
MakeFillableRequest,
MakeFillableResponse,
TemplateCreate,
TemplateResponse,
TemplateUploadResponse,
MakeFillableRequest,
MakeFillableResponse,
)
from app.core.config import DEFAULT_TEMPLATE_DIR
from app.db.repositories import get_template
Expand Down
8 changes: 4 additions & 4 deletions app/api/schemas/templates.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict


class TemplateCreate(BaseModel):
name: str
Expand All @@ -15,15 +16,14 @@ class MakeFillableResponse(BaseModel):
field_count: int | None = None

class TemplateResponse(BaseModel):
model_config = ConfigDict(from_attributes=True)

id: int
name: str
pdf_path: str
fields: dict
field_count: int | None = None

class Config:
from_attributes = True


class ExtractedField(BaseModel):
name: str
Expand Down
22 changes: 2 additions & 20 deletions app/core/celery.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
from celery import Celery
from celery.schedules import crontab

from app.core.config import CELERY_BROKER_URL, CELERY_RESULT_BACKEND
celery_app = Celery("fireform")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore Celery task discovery configuration

The checked Docker worker starts from app.core.celery:celery_app, but this module no longer imports or includes app.tasks.fill, app.tasks.purge, or app.tasks.transcribe. Consequently the separate worker process does not register those tasks and will reject queued form-fill and transcription messages as unregistered; restore the task includes/imports (and the existing app configuration) when constructing the Celery application.

Useful? React with 👍 / 👎.


celery_app = Celery(
"fireform",
broker=CELERY_BROKER_URL,
backend=CELERY_RESULT_BACKEND,
)

celery_app.conf.update(
task_serializer="json",
result_serializer="json",
accept_content=["json"],
task_track_started=True,
result_expires=86400,
)

celery_app.conf.include = ["app.tasks.fill", "app.tasks.purge", "app.tasks.transcribe"]

# Optional Celery Beat schedule — runs purge_old_submissions once a day.
# Enable by running: celery -A app.core.celery beat
from celery.schedules import crontab # noqa: E402
celery_app.conf.beat_schedule = {
"daily-submission-purge": {
"task": "purge_old_submissions",
Expand Down
2 changes: 1 addition & 1 deletion app/db/init_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import logging
from pathlib import Path

from alembic import command
from alembic.config import Config
from sqlmodel import Session, select

from alembic import command
from app.core.config import DEFAULT_TEMPLATE_DIR
from app.db.database import engine
from app.models import FormSubmission, Template # noqa: F401
Expand Down
3 changes: 2 additions & 1 deletion app/db/repositories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

from sqlmodel import Session, select

from app.models import Template, FormSubmission, Job, Input
from app.models import FormSubmission, Input, Job, Template


# Templates
def create_template(session: Session, template: Template) -> Template:
Expand Down
10 changes: 5 additions & 5 deletions app/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
)

__all__ = [
"Template",
"FormSubmission",
"Job",
"Input",
"Extraction",
"Incident",
"Form",
"FormSubmission",
"Incident",
"Input",
"Job",
"Report",
"Template",
]
7 changes: 4 additions & 3 deletions app/models/models.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import uuid as uuid_mod
from uuid import UUID, uuid4
from datetime import date, datetime, timezone
from uuid import UUID, uuid4

from sqlalchemy import Column, JSON
from sqlmodel import SQLModel, Field
from sqlalchemy import JSON, Column
from sqlmodel import Field, SQLModel
from sqlmodel.sql.sqltypes import AutoString

from app.api.schemas.enums import (
Expand Down Expand Up @@ -32,6 +32,7 @@ class FormSubmission(SQLModel, table=True):
template_id: int = Field(foreign_key="template.id")
input_id: UUID | None = Field(default=None, foreign_key="inputs.input_id")
input_text: str
extracted_fields: dict | None = Field(default=None, sa_column=Column(JSON))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add extracted_fields to migration 003

The new ORM column is not created by migration 003, which only adds input_id. On any database initialized or upgraded through Alembic, ORM reads and writes of FormSubmission will therefore reference a nonexistent extracted_fields column, breaking form filling, submission listing, analytics, and deletion; the migration and downgrade need to add and remove this JSON column as well.

Useful? React with 👍 / 👎.

output_pdf_path: str
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

Expand Down
2 changes: 1 addition & 1 deletion app/services/controller.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from app.services.file_manipulator import FileManipulator
from app.services.external_apis_coordinator import ExternalAPIsCoordinator
from app.services.file_manipulator import FileManipulator


class Controller:
Expand Down
1 change: 0 additions & 1 deletion app/services/external_apis/weather_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import openmeteo_requests

import pandas as pd
import requests_cache
from retry_requests import retry
Expand Down
2 changes: 1 addition & 1 deletion app/services/external_apis/zipcode_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from geopy.exc import GeocoderServiceError, GeocoderTimedOut
from geopy.geocoders import Nominatim
from geopy.exc import GeocoderTimedOut, GeocoderServiceError

from app.core.logging import get_logger

Expand Down
3 changes: 2 additions & 1 deletion app/services/external_apis_coordinator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from app.services.external_apis.zipcode_api import ZipCodeAPI
from app.services.external_apis.weather_api import WeatherAPI
from app.services.external_apis.zipcode_api import ZipCodeAPI


class ExternalAPIsCoordinator:
def __init__(self):
Expand Down
3 changes: 2 additions & 1 deletion app/services/file_manipulator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os

from app.core.logging import get_logger
from app.services.filler import Filler
from app.services.llm import LLM
from app.core.logging import get_logger

logger = get_logger(__name__)

Expand Down
4 changes: 3 additions & 1 deletion app/services/filler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from datetime import datetime

from pdfrw import PdfReader, PdfWriter

from app.services.llm import LLM
from datetime import datetime


def _pdf_text(value) -> str:
Expand Down
3 changes: 3 additions & 0 deletions app/services/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,13 @@ def fill_and_persist(
model=model,
)

extracted_fields = self.controller.file_manipulator.llm._json

submission = FormSubmission(
template_id=template.id,
input_id=input_id,
input_text=transcript,
extracted_fields=extracted_fields,
output_pdf_path=path,
)
return create_form(session, submission)
Expand Down
4 changes: 2 additions & 2 deletions app/services/llm.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import json
import os

import requests
from requests.exceptions import Timeout, RequestException
from requests.exceptions import RequestException, Timeout

from app.core.config import OLLAMA_HOST, OLLAMA_MODEL
from app.core.logging import get_logger
Expand Down Expand Up @@ -92,7 +93,6 @@ def add_response_to_json(self, field: str, value: str):
else:
self._json[field] = parsed_value

return


def get_data(self):
Expand Down
3 changes: 2 additions & 1 deletion app/tasks/purge.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
from datetime import datetime, timedelta, timezone
from pathlib import Path

from sqlmodel import select

from app.core.celery import celery_app
from app.core.config import BASE_DIR, RETENTION_PERIOD_DAYS
from app.db.database import get_session
from app.db.repositories import delete_form_submission
from app.models import FormSubmission
from sqlmodel import select

logger = logging.getLogger(__name__)

Expand Down
Loading
Loading