Skip to content

Selected work / ForecastGPT

ForecastGPT

Turns quarterly filings and earnings calls into structured next-quarter outlooks.

Role
Solo
Status
Live on a free tier · Indian listed companies
License
MIT, open source
Stack
Python · FastAPI · LangChain · FAISS · pdfplumber · Redis / RQ · SQLAlchemy

The problem

Analysts spend hours reading quarterly PDFs to pull out revenue and margin trends, management tone, and the risks worth flagging.

Constraints

  • A forecast is slow. It fetches and reads several PDFs and calls a model, so it runs as a job: the API answers 202 with a job ID and the client polls.

  • No GPU in production. Ollama is the local default. A hosted deploy swaps in a cloud provider through configuration, with no code change.

  • Documents come from the open web. Filings are discovered from each company’s Screener page and fetched through SSRF-hardened code.

Architecture

  1. 01 · Data

    Request

    company + question

  2. 02 · Code

    API

    202 + job ID

  3. 03 · Data

    Job queue

    Redis · RQ

  4. 04 · Code

    Worker

    embedded or separate

  5. 05 · Code

    Fetch filings

    SSRF-hardened

  6. 06 · Code

    Extract figures

    pdfplumber + regex

  7. 07 · Code

    Retrieve passages

    FAISS · 6 themes

    Best-effort: if transcript analysis fails, the outlook proceeds on the financials and says so.

  8. 08 · LLM step

    Write outlook

    LLM · given inputs only

  9. 09 · Code

    Parse JSON

    structured outlook

  10. 10 · Data

    Result

    logged to SQL

  11. 11 · Code

    Poll

    GET /forecasts/{id}

The numbers never pass through the model as raw text: code parses them out of the filings and hands them over.

Decisions

Code extracts the numbers.

Chose
pdfplumber and regular expressions pull the figures out of the quarterly results. The model gets them already parsed, with retrieved transcript passages, and is told to use only those inputs.
Over
Asking the model to read figures out of the PDFs itself.
Gain
The model interprets numbers; it never has to find them. An ungrounded model will happily invent a margin figure.

A job queue, with an embedded worker.

Chose
Forecasts run as Redis/RQ jobs. On one free instance the API process starts its own worker thread.
Over
Holding an HTTP request open for the whole run.
Gain
Moving to a dedicated worker later is a configuration change, not a rewrite.

Transcript analysis may fail; the forecast may not.

Chose
Retrieval over earnings-call transcripts is best-effort. If it fails, the outlook proceeds on the financials and says so.
Over
Failing the whole job when one input is missing.

Outcome

  • Live on a free Render instance; the first request after idle takes about 40 seconds.
  • Covers Indian listed companies with Screener coverage. Adding one is a single registry line.
  • 122 test functions run in CI with Ruff and a front-end build.

What I’d change next

Visual-native retrieval over investor decks, so figures in charts can be read without OCR. It is designed, on ColPali-style models, but not started.