Skip to content

ayansk11/FinSight

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

9 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

FinSight

Agentic Financial Document Intelligence & Risk Analyst

FinSight is a multi-agent AI system that analyzes SEC filings (10-K, 10-Q, 8-K) using a LangGraph-orchestrated pipeline of specialized agents. It combines document intelligence, quantitative analysis, risk classification, and cross-document reasoning to generate investment-grade research reports β€” all powered by local Ollama inference with no cloud LLM dependencies.


Features

  • Multi-Agent LangGraph Workflow β€” Four specialized agents (Document Intelligence, Quantitative Analysis, Risk Classification, Synthesis) orchestrated via LangGraph StateGraph with conditional routing
  • PageIndex Tree Navigation β€” Hierarchical document structure maps for precise section-level extraction with citations
  • Docling Document AI β€” IBM's AI-powered document conversion with layout analysis, table extraction, and structured Markdown output as the default PDF processor
  • Local Ollama Inference β€” Runs entirely offline using Qwen3.5 via Ollama β€” no API keys required for core analysis. Supports multiple models (Qwen3.5:9b, Qwen3:8b, Qwen3.5:4b, or any Ollama-compatible model)
  • Groq Cloud Fallback β€” When Ollama times out on large documents (100+ pages), automatically falls back to Groq's fast cloud inference (free tier: 14,400 requests/day)
  • Market Data Integration β€” Real-time financial data from Yahoo Finance, FRED, Finnhub, Financial Modeling Prep, Alpha Vantage, and StockData via MCP-style data servers
  • MITRE F3 Risk Framework β€” Risk classification using a financial threat taxonomy inspired by MITRE ATT&CK
  • Cross-Document Reasoning (RLM) β€” Recursive Language Model integration for multi-filing comparative analysis. When multiple filings are loaded, the router activates RLM synthesis for cross-document reasoning with iterative refinement (up to 15 iterations)
  • Local Tree Generation β€” Heuristic heading detection + LLM refinement (Ollama β†’ Groq fallback) for generating document structure trees from raw PDFs
  • Streamlit Web UI β€” Interactive chat interface, document manager, analysis dashboard with findings/risk scores/export
  • iPhone Export β€” .finsight bundle export for companion iOS app

Architecture

                              FinSight Architecture
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                       Streamlit Web UI                          β”‚
    β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
    β”‚   β”‚   Chat   β”‚   β”‚  Documents   β”‚   β”‚  Analysis Board   β”‚      β”‚
    β”‚   β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚                β”‚                     β”‚
             β–Ό                β–Ό                     β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                    LangGraph StateGraph                         β”‚
    β”‚                                                                 β”‚
    β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”               β”‚
    β”‚   β”‚  Router  │───>β”‚  Doc Intel  │───>β”‚  Quant   β”‚ (conditional) β”‚
    β”‚   β”‚  Node    β”‚    β”‚   Agent     β”‚    β”‚  Agent   β”‚               β”‚
    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜               β”‚
    β”‚                                          β”‚                      β”‚
    β”‚                                          β–Ό                      β”‚
    β”‚                                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                 β”‚
    β”‚                                    β”‚   Risk   β”‚ (conditional)   β”‚
    β”‚                                    β”‚  Agent   β”‚                 β”‚
    β”‚                                    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                 β”‚
    β”‚                                         β”‚                       β”‚
    β”‚                                    β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”                  β”‚
    β”‚                                    β–Ό         β–Ό                  β”‚
    β”‚                            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
    β”‚                            β”‚ Synthesis β”‚ β”‚    RLM     β”‚        β”‚
    β”‚                            β”‚   Agent   β”‚ β”‚ Synthesis  β”‚        β”‚
    β”‚                            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚                β”‚                     β”‚
             β–Ό                β–Ό                     β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Ollama LLM    β”‚ β”‚  PageIndex  β”‚ β”‚         MCP Data Servers              β”‚
    β”‚  (Qwen3.5:9b)  β”‚ β”‚   Trees     β”‚ β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”β”Œβ”€β”€β”€β”€β”€β”€β”€β”β”Œβ”€β”€β”€β”€β”€β”β”Œβ”€β”€β”€β”      β”‚
    β”‚  localhost:11434β”‚ β”‚  (JSON)     β”‚ β”‚  β”‚ FRED β”‚β”‚Finnhubβ”‚β”‚ yFinβ”‚β”‚FMPβ”‚      β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚  β””β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”˜      β”‚
                                        β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚
                                        β”‚  β”‚AlphaVantageβ”‚β”‚StockDataβ”‚          β”‚
                                        β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
                                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Data Flow

                              Query Processing Flow

    User Query: "What are Apple's main risk factors?"
         β”‚
         β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ 1. ROUTER                                                    β”‚
    β”‚    classify_query(query, num_filings)                        β”‚
    β”‚    β”œβ”€β”€ Detects: risk signals β†’ route = "risk_focused"        β”‚
    β”‚    β”œβ”€β”€ agents_to_run = ["doc_intel", "risk", "synthesis"]    β”‚
    β”‚    └── needs_rlm = False (single document)                   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ 2. DOC INTEL AGENT                                           β”‚
    β”‚    For each loaded filing:                                   β”‚
    β”‚    β”œβ”€β”€ Present PageIndex tree outline to LLM                 β”‚
    β”‚    β”œβ”€β”€ LLM selects relevant node IDs (e.g., Risk Factors)    β”‚
    β”‚    β”œβ”€β”€ Extract page text for selected sections               β”‚
    β”‚    β”œβ”€β”€ Analyze each section with LLM                         β”‚
    β”‚    └── Output: Findings[] with precise Citations             β”‚
    β”‚         (filing, section, page range, excerpt)               β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ 3. RISK AGENT (conditional β€” risk_focused route)             β”‚
    β”‚    β”œβ”€β”€ Classify findings using MITRE F3 taxonomy             β”‚
    β”‚    β”‚   β”œβ”€β”€ Disclosure Risk (DR-T001..T006)                   β”‚
    β”‚    β”‚   β”œβ”€β”€ Financial Health (FH-T001..T008)                  β”‚
    β”‚    β”‚   β”œβ”€β”€ Governance (GV-T001..T005)                        β”‚
    β”‚    β”‚   └── Market Risk (MR-T001..T004)                       β”‚
    β”‚    └── Output: RiskScore[] with severity (0.0-1.0)           β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ 4. SYNTHESIS AGENT                                           β”‚
    β”‚    β”œβ”€β”€ Aggregate all upstream findings + risk scores          β”‚
    β”‚    β”œβ”€β”€ If RLM: incorporate cross-document reasoning           β”‚
    β”‚    β”œβ”€β”€ Generate investment-grade report (markdown)            β”‚
    β”‚    └── Generate executive summary (one paragraph)             β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ 5. OUTPUT                                                    β”‚
    β”‚    β”œβ”€β”€ report: Full synthesis report                          β”‚
    β”‚    β”œβ”€β”€ executive_summary: One-paragraph summary               β”‚
    β”‚    β”œβ”€β”€ findings: [{content, agent, confidence, citations}]    β”‚
    β”‚    β”œβ”€β”€ risk_scores: [{tactic, technique, severity, evidence}] β”‚
    β”‚    └── agent_summaries: [{agent, summary, duration}]          β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Project Structure

FinSight/
β”œβ”€β”€ shared/                          # Shared core library (finsight_core)
β”‚   └── src/finsight_core/
β”‚       β”œβ”€β”€ models/
β”‚       β”‚   β”œβ”€β”€ state.py             # FinSightState β€” LangGraph state schema
β”‚       β”‚   β”œβ”€β”€ analysis.py          # Finding, RiskScore, Citation, AgentOutput
β”‚       β”‚   β”œβ”€β”€ document.py          # Filing, PageIndexTree, TreeNode
β”‚       β”‚   └── export.py            # ExportBundle for iPhone
β”‚       β”œβ”€β”€ prompts/                 # All LLM prompt templates
β”‚       β”œβ”€β”€ pageindex/               # PageIndex tree parser & navigator
β”‚       β”œβ”€β”€ taxonomy/                # MITRE F3 risk taxonomy
β”‚       └── finance/                 # Financial ratio calculations
β”‚
β”œβ”€β”€ mac/                             # Mac application (finsight_mac)
β”‚   └── src/finsight_mac/
β”‚       β”œβ”€β”€ agents/                  # Four specialized agents
β”‚       β”‚   β”œβ”€β”€ doc_intel.py         # Document Intelligence Agent
β”‚       β”‚   β”œβ”€β”€ quant.py             # Quantitative Analysis Agent
β”‚       β”‚   β”œβ”€β”€ risk.py              # Risk Classification Agent
β”‚       β”‚   └── synthesis.py         # Synthesis & Report Agent
β”‚       β”œβ”€β”€ graph/
β”‚       β”‚   β”œβ”€β”€ workflow.py          # LangGraph StateGraph definition
β”‚       β”‚   └── router.py            # Query classification & routing
β”‚       β”œβ”€β”€ document/
β”‚       β”‚   β”œβ”€β”€ pipeline.py          # PDF β†’ PageIndex tree pipeline
β”‚       β”‚   └── local_tree_generator.py  # Offline tree generation
β”‚       β”œβ”€β”€ mcp/                     # Market data servers
β”‚       β”‚   β”œβ”€β”€ market_data.py       # Aggregator (all data sources)
β”‚       β”‚   β”œβ”€β”€ fred.py              # Federal Reserve data
β”‚       β”‚   β”œβ”€β”€ finnhub_client.py    # Market quotes & fundamentals
β”‚       β”‚   β”œβ”€β”€ yfinance_client.py   # Yahoo Finance (no API key)
β”‚       β”‚   β”œβ”€β”€ fmp_client.py        # Financial Modeling Prep (statements, ratios)
β”‚       β”‚   β”œβ”€β”€ alpha_vantage_client.py  # Historical data & technical indicators
β”‚       β”‚   └── stockdata_client.py  # Market news & sentiment
β”‚       β”œβ”€β”€ llm/
β”‚       β”‚   β”œβ”€β”€ ollama_client.py     # Async Ollama wrapper
β”‚       β”‚   β”œβ”€β”€ groq_client.py       # Groq cloud fallback client
β”‚       β”‚   └── rlm_client.py        # Recursive Language Model client
β”‚       β”œβ”€β”€ ui/                      # Streamlit web interface
β”‚       β”‚   β”œβ”€β”€ app.py               # Main entry point
β”‚       β”‚   β”œβ”€β”€ pages/
β”‚       β”‚   β”‚   β”œβ”€β”€ chat.py          # Chat Q&A interface
β”‚       β”‚   β”‚   β”œβ”€β”€ documents.py     # PDF/tree management
β”‚       β”‚   β”‚   └── analysis.py      # Analysis dashboard
β”‚       β”‚   └── components/
β”‚       β”‚       β”œβ”€β”€ tree_viewer.py   # PageIndex tree renderer
β”‚       β”‚       β”œβ”€β”€ findings_viewer.py
β”‚       β”‚       └── risk_viewer.py
β”‚       └── config.py                # Settings (Pydantic BaseSettings)
β”‚
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ shared/                      # Core library unit tests
β”‚   β”œβ”€β”€ mac/                         # Agent & workflow unit tests
β”‚   └── e2e/                         # End-to-end tests (requires Ollama)
β”‚
β”œβ”€β”€ scripts/                         # CLI utilities
β”‚   β”œβ”€β”€ setup_sample_data.py         # One-command sample data setup
β”‚   β”œβ”€β”€ test_e2e.py                  # Manual E2E test runner
β”‚   β”œβ”€β”€ generate_tree.py             # Tree generation CLI
β”‚   └── export_for_iphone.py         # .finsight bundle exporter
β”‚
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ filings/                     # SEC filing PDFs (gitignored)
β”‚   └── trees/                       # Generated PageIndex trees (gitignored)
β”‚
└── references/                      # Design specs & documentation

Getting Started

Prerequisites

  • Python 3.11+
  • Ollama with qwen3.5:9b model
  • uv package manager

Installation

# Clone the repo
git clone https://github.com/ayansk11/FinSight.git
cd FinSight

# Install dependencies with uv
uv sync

# Pull the Ollama model
ollama pull qwen3.5:9b

# Copy environment config
cp .env.example .env
# Edit .env to add optional API keys (FRED, Finnhub, PageIndex)

Sample Data Setup

# Download a sample 10-K from SEC EDGAR and generate a PageIndex tree
# (requires Ollama running with a model pulled)
uv run python scripts/setup_sample_data.py

# Or for a different company:
uv run python scripts/setup_sample_data.py --ticker MSFT

Supported tickers: AAPL, MSFT, GOOGL, AMZN, TSLA, META, NVDA, JPM, V, JNJ.

Running the UI

# Start Ollama (if not already running)
ollama serve

# Launch Streamlit
uv run streamlit run mac/src/finsight_mac/ui/app.py

Running Tests

# Unit tests (no Ollama required)
uv run python -m pytest tests/ -q -m "not e2e"

# E2E tests (requires Ollama + qwen3.5:9b)
uv run python -m pytest tests/e2e/ -v

# Lint
uv run ruff check .

Quick CLI Test

# Run the full pipeline from command line
uv run python scripts/test_e2e.py --query "What are Apple's main risk factors?"

Configuration

Variable Required Description
OLLAMA_MODEL No Ollama model name (default: qwen3.5:9b)
OLLAMA_BASE_URL No Ollama endpoint (default: http://localhost:11434)
FRED_API_KEY No FRED macroeconomic data (free at fred.stlouisfed.org)
FINNHUB_API_KEY No Finnhub market data (free at finnhub.io)
ALPHA_VANTAGE_API_KEY No Alpha Vantage historical data & technical indicators (free at alphavantage.co)
STOCKDATA_API_KEY No StockData.org market news & sentiment (free at stockdata.org)
GROQ_API_KEY No Groq cloud fallback when Ollama times out (free at console.groq.com)
PAGEINDEX_API_KEY No PageIndex cloud tree generation
OPENAI_API_KEY No OpenAI for cloud tree generation fallback

Core analysis works with zero API keys β€” only Ollama is required. Market data APIs are optional and enhance the Quantitative Agent. Groq is strongly recommended for generating trees from large (100+ page) filings β€” it prevents timeout issues on consumer hardware.


How It Works

PageIndex Trees

FinSight uses hierarchical PageIndex trees to navigate SEC filings efficiently. Instead of processing entire 100+ page documents, the system:

  1. Generates a structural tree (PART I β†’ Item 1 β†’ Business β†’ ...) with page ranges
  2. Presents the tree outline to the LLM for intelligent section selection
  3. Extracts only relevant pages, maintaining precise citations

Trees can be generated via:

  • Local Ollama β†’ Groq fallback β€” Heuristic heading detection + LLM refinement. Tries local Ollama first; auto-falls back to Groq cloud when Ollama times out on large documents
  • PageIndex Cloud API β€” High-quality cloud-based generation
  • Pre-generated β€” Load from data/trees/ directory

Agent Routing

The Router analyzes query intent and selects the appropriate agent combination:

Route Agents Trigger
single_doc doc_intel β†’ synthesis Default for single-filing queries
quantitative doc_intel β†’ quant β†’ synthesis Revenue, ratios, margins, P/E
risk_focused doc_intel β†’ risk β†’ synthesis Risk factors, governance, fraud
multi_doc doc_intel β†’ quant/risk β†’ RLM synthesis Cross-filing comparison queries

Supported LLM Models

FinSight uses Ollama for local inference and supports any Ollama-compatible model. Configure via the OLLAMA_MODEL environment variable:

Model Ollama ID Size Notes
Qwen3.5-9B qwen3.5:9b ~6GB Default β€” best balance of quality and speed
Qwen3-8B (RLM) qwen3:8b-q4_K_M ~5GB Optimized for cross-document reasoning
Qwen3.5-4B qwen3.5:4b ~3GB Lightweight, good for quick queries
Qwen3.5-2B qwen3.5:2b ~1.5GB Minimal memory footprint
Qwen3.5-0.8B qwen3.5:0.8b ~0.5GB Ultra-light, fastest inference

Select your model from the dropdown in the Streamlit sidebar. The default (OLLAMA_MODEL env var) can be overridden at runtime.

Recursive Language Model (RLM)

When multiple filings are loaded (e.g., comparing AAPL 10-K 2023 vs 2024), the Router automatically activates RLM synthesis instead of standard synthesis. RLM performs iterative cross-document reasoning:

  1. Generates initial comparative analysis from all upstream findings
  2. Iteratively refines the analysis (up to MAX_RLM_ITERATIONS, default 15)
  3. Produces a unified cross-filing report with comparative insights

RLM is triggered automatically β€” no configuration needed beyond loading multiple documents.

Docling Document AI

FinSight uses Docling (IBM) as its default PDF processor for:

  • Layout analysis β€” Correct reading order for multi-column layouts
  • Table extraction β€” Structured table data from financial statements
  • Page-level Markdown β€” Clean formatted text preserving document structure

Docling results are cached to disk for fast reprocessing. Falls back to PyMuPDF if Docling processing fails on a specific document.

Risk Classification

The Risk Agent uses a financial threat taxonomy inspired by MITRE ATT&CK:

  • Disclosure Risk β€” Material omissions, vague language, delayed reporting
  • Financial Health β€” Revenue concentration, debt levels, cash flow issues
  • Governance β€” Related party transactions, executive compensation, board independence
  • Market Risk β€” Concentration risk, regulatory exposure, competitive threats

Each risk receives a severity score (0.0–1.0) with supporting evidence and citations.


Test Coverage

  • 129 unit tests β€” Models, agents, workflow routing, tree generation, MCP clients
  • 10 E2E tests β€” Full pipeline, live market data, real PDF processing
  • All tests auto-skip when Ollama/network unavailable

Tech Stack

Component Technology
Orchestration LangGraph (StateGraph)
LLM Ollama (Qwen3.5:9b default, multi-model) + Groq cloud fallback
Document AI Docling (IBM) β€” layout analysis, tables
Document Parsing PyMuPDF, PageIndex
Cross-Doc Reasoning RLM (Recursive Language Model)
Market Data yfinance, FRED API, Finnhub, FMP, Alpha Vantage, StockData
Data Models Pydantic v2
Web UI Streamlit
Package Manager uv (workspace)
Testing pytest, pytest-asyncio
Linting Ruff

License

MIT

About

Agentic Financial Document Intelligence & Risk Analyst - Multi-agent LangGraph system for SEC filing analysis with local Ollama inference

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors