Insight Generator

An AI analyst for finance teams’ spreadsheets

Insight Generator is a web app that turns the Excel and CSV files finance teams live in into clean data, Excel-style pivot tables, charts and written analysis. Analysts upload a workbook, clean and reshape it, build pivots and ask an assistant questions in plain language. Every number in an answer comes from a query that actually ran on their data.

Context
Natixis, Groupe BPCE. Paris, 2026
Role
Data Scientist, GenAI
Users
Finance and reporting teams
Interface
French and English
Stack
Python 3.13, FastAPI, pandas, DuckDB, ChromaDB, SQLAlchemy, vanilla JavaScript

This page explains how Insight Generator works. It contains no client data, internal system names or business figures, and the worked example uses synthetic data.

Why build it

Month-end in a finance team still runs on spreadsheets. Files arrive from different systems with French and English number formats, periods written five different ways, Excel errors, and total rows mixed in with the data. Analysts clean them by hand, rebuild the same pivot tables every month, then rewrite the commentary in Word, PowerPoint or an e-mail.

A general-purpose chatbot doesn’t fix this, because it can’t be trusted with figures. Insight Generator gives the language model the job of planning and explaining, and leaves every calculation to a database engine.

The two leaning glass towers of Tours Duo in Paris, the taller one carrying the Groupe BPCE sign, above railway tracks.
Tours Duo, Paris 13e, headquarters of Natixis and Groupe BPCE.

How it works

Every file is read, normalised, checked and versioned before anyone analyses it. Follow one export through.

One workbook, from upload to a clean table
Workbook .xlsx, .xls, .csv… Sniff the content not the extension Clear message password-protected Read the sheet skip report preambles Normalise values amounts, periods, codes Quality report errors, totals, dupes Version 1 every change versioned Workbook .xlsx, .xls, .csv… Sniff the content not the extension Clear message password-protected Read the sheet skip report preambles Normalise values amounts, periods, codes Quality report errors, totals, dupes Version 1 every change versioned
  • Input or output
  • Code
  • Data store
  • Check or gate
  1. Workbook A month-end export saved as .xls that is really an HTML table.
  2. Sniff the content The bytes decide the reader: real Excel, HTML table, SpreadsheetML 2003, CSV or JSON.
  3. Read the sheet Picks the sheet, skips the report preamble above the header, flags hidden and chart sheets.
  4. Normalise values “1 234,56 €” becomes 1234.56, “T1 2025” becomes 2025-Q1, and account code “0100” stays text.
  5. Quality report Flags #N/A and #REF!, mixed currencies and rows that look like totals, and checks the file’s own Total row against the recomputed sum.
  6. Version 1 Stored as version 1. Every filter, rename or computed column after this is a new version that can be undone and audited.

The assistant computes; it doesn’t guess

The assistant is an agent that works across every table in a session. It doesn’t answer from memory: it writes SQL, runs it on DuckDB, builds pivots and draws charts, including waterfall (bridge) charts, then explains what the results show.

Finance-specific SQL macros (fiscal_year, fiscal_quarter and fiscal_period, with a configurable fiscal-year start) make year-to-date and prior-year comparisons a single line of SQL. Suggested questions adapt to the data: budget vs actual, variances, bridges.

One question, from the analyst to the answer
Analyst asks a question Knowledge base templates, examples Agent plans, then explains Tools SQL, pivots, charts Answer figures, chart, export Versioned tables DuckDB, this session Analyst asks a question Knowledge base templates, examples Agent plans, then explains Tools SQL, pivots, charts Answer figures, chart, export Versioned tables DuckDB, this session
  • Input or output
  • LLM call
  • Code
  • Data store
  1. Analyst “How did Q1 2025 revenue compare with budget, by region?”
  2. Agent Decides the figures have to come from a query, not from memory, and writes SQL with the fiscal_year() and fiscal_quarter() macros.
  3. Tools run_sql executes on DuckDB over the session’s tables: four rows, actual against budget, by region.
  4. Agent Reads the result and asks for a bridge chart.
  5. Tools waterfall_chart draws budget, the four regional variances and actual, from those same rows.
  6. Agent Writes the commentary from the numbers it was handed, nothing else.
  7. Answer €13.34M against a €13.75M budget, €411k (3.0%) short; South and West explain most of the gap. One click exports it to Excel, Word or PowerPoint.

The same question as the agent’s own trace, with the SQL it wrote and the chart it drew:

  1. Question

    How did Q1 2025 revenue compare with budget, by region?

  2. Tool call run_sql

    SELECT region,
           SUM(revenue)               AS actual,
           SUM(budget)                AS budget,
           SUM(revenue) - SUM(budget) AS variance
    FROM   sales
    WHERE  fiscal_year(order_date) = 2025
      AND  fiscal_quarter(order_date) = 1
    GROUP  BY region
    ORDER  BY variance;
  3. Result, € thousands

    region actual budget variance
    South 3,128 3,396 −268
    West 2,890 3,011 −121
    East 3,102 3,180 −78
    North 4,216 4,160 +56
    Total 13,336 13,747 −411
  4. Tool call waterfall_chart

    Q1 2025 revenue, budget to actual by region (synthetic data) Waterfall from a budget of 13,747 to an actual of 13,336 thousand euros: South −268, West −121, East −78, North +56. 13,747 Budget −268 South −121 West −78 East +56 North 13,336 Actual € thousands, axis starts at 13,200

    Select a bar to read its row.

    Q1 2025 revenue, budget to actual by region (synthetic data) Waterfall from a budget of 13,747 to an actual of 13,336 thousand euros: South −268, West −121, East −78, North +56. 13,747 Budget −268 South −121 West −78 East +56 North 13,336 Actual € thousands, axis starts at 13,200

    Select a bar to read its row.

  5. Answer

    Q1 2025 revenue came in at €13.34M against a €13.75M budget: €411k (3.0%) short. South (−€268k) and West (−€121k) explain most of the gap; East is €78k under and North finished €56k ahead.

An illustrative run on synthetic data: one question, two tool calls, one chart and an answer whose figures all come from the query result.

Context from documents

Users can add documents to a private knowledge base: Word, PowerPoint, PDF (layout kept), spreadsheets, HTML pages and e-mails (.eml and Outlook .msg). They are indexed in ChromaDB and retrieved by the assistant and the analysis tab (RAG). Each document belongs to its owner. A document can also be marked as one of three kinds:

Template
Rules and placeholders for a report. Ask “fais le rapport selon le modèle” (write the report following the template) and the assistant follows it. Word and PowerPoint exports take the template’s look, and Excel reporting templates are filled cell by cell.
Example
A past e-mail, PDF or Word deliverable to imitate. Figures in examples are masked before the agent reads them, and any old figure that reaches an answer is flagged.
Reference
A lookup table such as a chart of accounts or FX rates, which the agent can join in SQL.

Engineering choices

  • The content picks the parser

    Files are sniffed, not trusted by their extension, so real-world exports load instead of failing.

  • Numbers come from queries

    The model plans and explains; DuckDB and pandas compute. Figures in an answer can always be traced to a query.

  • Exact subtotals

    Subtotals are recomputed from raw rows, never summed from their children, so non-additive measures stay correct.

  • Every change is a version

    Undo, audit trails and the month-end replay all come from the same versioned history.

  • Model-agnostic

    Runs on the bank’s internal GenAI platform or on any OpenAI-compatible endpoint, including local models. The LLM features can also be switched off entirely.

  • Secure by default

    Single sign-on (OpenID Connect), user roles, audit logs, prompt management and documents private to their owner. Development shortcuts are refused in production.

  • Tested like a product

    pytest unit, integration and regression suites run against fakes of the LLM SDK and document storage, with a temporary database per test. Node tests cover translations, charts and the pivot layout, and a sample workbook ships with test questions and their expected answers.

Stack

Backend
Python 3.13, FastAPI, pandas, DuckDB, SQLAlchemy (SQLite)
AI
LLM agent with tool calling, RAG on ChromaDB, optional local Hugging Face embeddings
Frontend
HTML, CSS and vanilla ES modules served by the backend, no build step, PivotTable.js
Exports
XLSX, CSV, DOCX, PDF, PPTX, EML
Quality
pytest, node:test, golden questions with expected answers

More GenAI work at BPCE & Natixis

  • Steering ALM Metrics

    Platform automating liquidity (LCR) monitoring and reporting across Groupe BPCE, built and deployed with Treasury, ALM and IT teams to analyze large-scale balance-sheet data and explain each change. An LLM-powered AI agent answers analysts’ questions in plain language and drills into the data.

  • AAR (Accounting Analytical Review)

    App streamlining quarterly statutory and consolidated accounting reviews for about 200 Natixis entities. It drafts analyses of significant account movements and Audit Committee report sections for reviewers to edit and validate. Used by Permanent Controls and Consolidation teams to cut manual effort and standardize a process behind management decisions and audits.

  • APAC T&E Policy Chatbot

    Generative AI chatbot (LLM, RAG) for the APAC travel and entertainment (T&E) policy. It automates answers to employees’ questions, grounded in official guidelines with links to sources. Administrators add documents, set custom rules and review feedback from a dedicated dashboard.

See my full experience

Building something similar?

I’m happy to talk through agents on top of spreadsheets, RAG for finance documents, or how to keep an LLM honest with numbers.