Financial Report AI turns an uploaded company document into a structured, equity-research-style PDF report. It combines document parsing, LLM-based extraction, chart generation, and a Playwright-rendered HTML/CSS report template in one local web workflow.
- Open the Next.js app at
http://localhost:3000. - Enter a company name and upload a PDF, TXT, or CSV document.
- The FastAPI service extracts source text and tables, then asks the configured LLM for structured report data.
- The service generates charts, renders the teal research-report PDF, and returns a preview and download link.
The report gracefully shows Not Available where the source document does not contain a requested metric.
Document upload
-> parser (PDF / TXT / CSV)
-> LLM JSON extraction
-> normalized report data
-> matplotlib charts + Jinja report template
-> Playwright / Chromium PDF
-> browser preview and download
See architecture.md for component boundaries and data persistence details.
- Frontend: Next.js 15, React, TypeScript, Tailwind CSS, React Hook Form, Axios
- API: FastAPI, Pydantic, Uvicorn
- Parsing: PyMuPDF, pdfplumber, pandas
- AI extraction: OpenAI-compatible Chat Completions API or Mistral
- Report generation: Jinja2, matplotlib, Playwright/Chromium
- Python 3.11+
- Node.js 18+
- An OpenAI or Mistral API key
Open two terminals from the repository root.
cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python -m playwright install chromium
cp .env.example .envEdit backend/.env, choose exactly one provider, and add its API key. For OpenAI:
PROVIDER=openai
OPENAI_API_KEY=your_api_key
MODEL=gpt-4.1For Mistral:
PROVIDER=mistral
MISTRAL_API_KEY=your_api_key
MISTRAL_MODEL=mistral-large-latest
MISTRAL_API_BASE=https://api.mistral.aiStart the API:
uvicorn main:app --reload --host 0.0.0.0 --port 8000The API is served at http://localhost:8000/api.
cd frontend
npm install
npm run devOpen http://localhost:3000.
| Endpoint | Purpose |
|---|---|
POST /api/upload |
Accepts a multipart file, parses it, extracts structured report data, and returns a job_id. |
POST /api/generate |
Accepts { "job_id": "..." }, generates chart assets and the PDF, and returns a download path. |
GET /api/download/{job_id} |
Streams the generated PDF. |
Example API flow:
curl -F "file=@company-results.pdf" http://localhost:8000/api/upload
curl -X POST http://localhost:8000/api/generate \
-H "Content-Type: application/json" \
-d '{"job_id":"<job-id-from-upload>"}'
curl -OJ http://localhost:8000/api/download/<job-id>backend/
app/api/routes.py # upload, generation, and download endpoints
app/services/parser.py # PDF, TXT, and CSV parsing
app/services/extractor.py # LLM prompting and response normalization
app/services/chart_generator.py # matplotlib chart assets
app/services/pdf_generator.py # Jinja + Playwright PDF generation
app/templates/report.html/.css # research-report layout
.env.example # provider configuration template
frontend/
app/page.tsx # upload, progress, preview, and download UI
Before sharing changes, run:
# backend, with the virtual environment activated
python -m compileall -q app
# frontend
cd ../frontend
npm run build- The application is a report-generation MVP, not investment advice or a valuation engine.
- The LLM is instructed to extract only source-supported information, but generated output should be reviewed before any professional use.
- Jobs and generated assets are stored locally for the current implementation; there is no authentication, database, or object storage layer.
- The frontend is configured for the local API at
http://localhost:8000; update the client and CORS policy before deployment.
Do not commit backend/.env, virtual environments, generated reports, job stores, or logs. These are excluded by .gitignore.