CoolFace
Apppublic

ACxxxy/FinRAG

sourceHugging Faceupdated 4mo agoView on Hugging Face
0likes
App README

FinRAG

A production-grade, citation-enforced financial RAG system integrating state-of-the-art AI orchestration with robust enterprise software engineering.

![Python 3.11+](https://www.python.org/downloads/) ![License: MIT](https://opensource.org/licenses/MIT) ![Live Platform](https://fin-rag-five.vercel.app)

🌐 Live Platform: fin-rag-five.vercel.app


What This Does

FinRAG is an enterprise-grade financial research engine designed to query SEC filings (10-K, 10-Q, 8-K) and earnings call transcripts. It leverages advanced LLM reasoning to generate answers that are 100% grounded in source text, enforcing exact citations (company, filing period, section, and page). To eliminate hallucination, the system executes an automated refusal protocol if the evidence is insufficient.

Key Capabilities

  • β€”LangGraph Orchestration β€” Multi-agent state machine routing requests based on query intent and complexity.
  • β€”Hybrid Retrieval (RRF) β€” Fusing BM25 sparse search and dense sentence embeddings via Reciprocal Rank Fusion.
  • β€”Cross-Encoder Reranking β€” Second-stage transformer validation for precision retrieval.
  • β€”Multi-turn Session Memory β€” Thread-safe session tracking, coreference resolution, and entity memory.
  • β€”Automated LLM-as-a-Judge β€” Real-time generation evaluation scoring citation accuracy and faithfulness.
  • β€”Containerized Stack (Docker) β€” Multi-container local orchestration (Next.js frontend, FastAPI backend, Redis, PostgreSQL).
  • β€”Sub-Millisecond Caching (Redis) β€” Ultra-fast caching for frequent prompt/response pairs.
  • β€”Query Analytics Engine (PostgreSQL) β€” Persistent SQL logging tracking token costs, latency distribution, and evaluation metrics.
  • β€”Asynchronous Jobs (Async Tasks) β€” FastAPI background task workers for parallel filing downloads, section-aware chunking, and vector indexing.
  • β€”API Rate Limiting β€” Bulletproof client rate-limiting protection.
  • β€”Structured Logging β€” Standardized, production-grade JSON logging for observability and error tracing.
  • β€”Streaming API β€” Server-Sent Events for progressive UI rendering.
  • β€”Guardrails β€” Prompt injection detection, PII filtering, and output verification.
  • β€”CI Quality Gates β€” Automated testing builds failing if faithfulness < 0.85 or citation coverage < 0.90.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        FastAPI Layer                            β”‚
β”‚  POST /query  β”‚  POST /query/stream  β”‚  GET /metrics           β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                   β”‚                      β”‚
       β–Ό                   β–Ό                      β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    LangGraph Orchestration                    β”‚
β”‚                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚  Input    │──▢│ Retrieve │──▢│ Rerank   │──▢│ Route    β”‚ β”‚
β”‚  β”‚  Guard    β”‚   β”‚  (Hybrid)β”‚   β”‚ (Cross-  β”‚   β”‚ (Keyword β”‚ β”‚
β”‚  β”‚          β”‚   β”‚          β”‚   β”‚  Encoder) β”‚   β”‚  Router) β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                      β”‚       β”‚
β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β”‚                    β–Ό                 β–Ό                        β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚
β”‚              β”‚ Generate β”‚     β”‚ Calculate β”‚                   β”‚
β”‚              β”‚ (Gemini) β”‚     β”‚ (Gemini)  β”‚                   β”‚
β”‚              β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜                   β”‚
β”‚                   β”‚                β”‚                          β”‚
β”‚                   β–Ό                β–Ό                          β”‚
β”‚              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                     β”‚
β”‚              β”‚ Validate │──▢│ Output   β”‚                     β”‚
β”‚              β”‚ Citationsβ”‚   β”‚ Guard    β”‚                     β”‚
β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                                          β”‚
       β–Ό                                          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  ChromaDB    β”‚                        β”‚    Langfuse       β”‚
β”‚  + BM25      β”‚                        β”‚    Tracing        β”‚
β”‚  Vector Storeβ”‚                        β”‚    + Metrics      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tech Stack

ComponentTechnology
OrchestrationLangGraph (state machine with conditional routing)
Vector StoreChromaDB (persistent, metadata-filtered)
Sparse RetrievalBM25 via rank-bm25
Dense Retrievalsentence-transformers (all-MiniLM-L6-v2)
RerankingCross-encoder (ms-marco-MiniLM-L-6-v2)
GenerationGoogle Gemini 2.0 Flash via langchain-google-genai
APIFastAPI + SSE (sse-starlette)
CachingRedis (sub-millisecond prompt/response cache & rate limiting)
Analytics DatabasePostgreSQL / Neon DB (via SQLAlchemy & asyncpg)
Frontend UINext.js (React, TypeScript, TailwindCSS)
GuardrailsCustom regex + policy-based input/output guards
ObservabilityLangfuse (traces, spans, token costs)
EvaluationRAGAS metrics + LLM-as-Judge citation scorer
Configpydantic-settings + versioned YAML prompts
CIGitHub Actions (lint β†’ test β†’ eval gate)
InfrastructureDocker & Docker Compose (multi-container local orchestration)

Setup

Prerequisites

  • β€”Python 3.11+
  • β€”Google API key (for Gemini LLM)
  • β€”Docker & Docker Compose (optional, but highly recommended for complete multi-container setup)

Option 1: Docker Compose (Quickest & Recommended)

Run the entire stack (Next.js UI, FastAPI Backend, Redis prompt cache, and PostgreSQL analytics) with a single command:

bash
# Clone the repo
git clone https://github.com/ac265640/FinRAG.git
cd FinRAG

# Spin up all containers
docker-compose up --build

Make sure to edit the .env file generated in the project root with your credentials.

Option 2: Local Virtual Environment Installation

bash
# Clone the repo
git clone https://github.com/ac265640/FinRAG.git
cd FinRAG

# Create virtual environment
python -m venv .venv

# Activate (Windows)
.venv\Scripts\activate
# Activate (macOS/Linux)
source .venv/bin/activate

# Install with dev dependencies
pip install -e ".[dev]"

Environment Configuration

bash
# Copy example env file
cp .env.example .env

Edit .env with your credentials:

env
# Required: Google Gemini API key
GOOGLE_API_KEY=your_key_here

# Optional: Langfuse observability
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...

# Optional: API authentication
FINRAG_API_KEY=your_api_secret

Quick Start

1. Ingest a Filing

bash
# Download and process Apple's latest 10-K
python scripts/ingest.py --ticker AAPL --filing-type 10-K --count 1

This downloads the filing from SEC EDGAR, parses sections, chunks with metadata, and indexes into ChromaDB + BM25.

2. Start the API Server

bash
uvicorn finrag.api.app:app --reload --port 8000

3. Query the Pipeline

bash
# Synchronous query
curl -X POST http://localhost:8000/api/v1/query \
  -H "Content-Type: application/json" \
  -d '{"query": "What was Apple total net revenue for fiscal year 2024?"}'

# Streaming query (SSE)
curl -X POST http://localhost:8000/api/v1/query/stream \
  -H "Content-Type: application/json" \
  -d '{"query": "What was Apple total net revenue for fiscal year 2024?"}'

4. Check Metrics

bash
curl http://localhost:8000/api/v1/metrics

API Reference

EndpointMethodDescription
/api/v1/queryPOSTSynchronous JSON response
/api/v1/query/streamPOSTServer-Sent Events streaming
/api/v1/sessions/{id}GETSession state inspection
/api/v1/sessions/{id}DELETEClear a session
/api/v1/config/promptsGETActive prompt versions
/api/v1/metricsGETProduction metrics (p50/p95 latency, costs, rates)
/api/v1/available-filingsGETList processed filing details dynamically (companies, periods, types)
/api/v1/ingestPOSTQueue asynchronous background SEC filing download and vector storage
/api/v1/ingest/{id}/statusGETCheck async background ingestion progress status
/api/v1/analytics/queriesGETFetch query history, cost trackers, and performance metrics

Query Request

json
{
  "query": "What was Apple's free cash flow in FY2024?",
  "session_id": "optional-session-id",
  "metadata_filter": {"ticker": "AAPL"}
}

Query Response

json
{
  "answer": "Apple's free cash flow in FY2024 was...",
  "citations": [
    {
      "chunk_id": "abc123",
      "filing_reference": "AAPL 10-K FY2024, Item 7 - MD&A",
      "section": "Item 7",
      "relevance_score": 0.92
    }
  ],
  "session_id": "auto-generated-uuid",
  "confidence": 0.87,
  "route": "retrieve",
  "prompt_version": "v2",
  "metadata": {
    "request_id": "uuid",
    "trace_id": "langfuse-trace-id",
    "total_latency_ms": 1250
  }
}

Evaluation

Golden Dataset

50 manually verified Q/A pairs across 4 categories:

CategoryCountDescription
Numerical Extraction15Direct financial data queries
Multi-hop Comparison12Cross-document reasoning
Contradiction Detection11Narrative vs. data consistency
Out-of-scope12Should produce decline, not hallucination

Run Evaluations

bash
# RAGAS metrics (faithfulness, relevancy, precision, coverage)
python -m finrag.evaluation.run_eval --mode ragas --threshold 0.85

# LLM-as-Judge citation scoring
python -m finrag.evaluation.run_eval --mode judge --threshold 0.90

# Full evaluation (both)
python -m finrag.evaluation.run_eval --mode full --output report.json

# Filter by category
python -m finrag.evaluation.run_eval --mode ragas --category numerical

CI Quality Gates

Every PR triggers the quality gate workflow:

lint β†’ unit tests (60% coverage) β†’ RAGAS eval (β‰₯0.85) β†’ Judge eval (β‰₯0.90)

Builds fail if quality thresholds are not met.


Project Structure

FinRAG/
β”œβ”€β”€ .github/workflows/         # CI quality gate
β”‚   └── quality-gate.yml
β”œβ”€β”€ alembic/                   # PostgreSQL migration scripts & schema env
β”œβ”€β”€ configs/                    # Versioned prompt configs (YAML)
β”œβ”€β”€ data/                      # SEC filing database storage
β”‚   β”œβ”€β”€ chroma/                # ChromaDB SQLite3 persistence database
β”‚   └── raw/                   # SEC raw filing HTML files grouped by ticker
β”œβ”€β”€ finrag-ui/                 # Next.js 14 frontend interactive application
β”‚   β”œβ”€β”€ app/                   # App Router pages and analytics charts
β”‚   β”œβ”€β”€ components/            # Chat component, citations highlight, sidebar
β”‚   β”œβ”€β”€ lib/                   # API clients, types, and analytics helpers
β”‚   └── Dockerfile.frontend    # Frontend Docker image configuration
β”œβ”€β”€ scripts/
β”‚   └── ingest.py              # EDGAR ingestion CLI
β”œβ”€β”€ src/finrag/
β”‚   β”œβ”€β”€ ingestion/             # EDGAR client, section chunker
β”‚   β”œβ”€β”€ vectorstore/           # ChromaDB store
β”‚   β”œβ”€β”€ retrieval/             # BM25, hybrid retriever
β”‚   β”œβ”€β”€ orchestration/         # LangGraph, nodes, routing, memory
β”‚   β”œβ”€β”€ guardrails/            # Input/output guards
β”‚   β”œβ”€β”€ api/                   # FastAPI app, routes, middleware, MCP
β”‚   β”œβ”€β”€ observability/         # Langfuse tracer, metrics
β”‚   └── evaluation/            # Golden dataset, RAGAS, LLM-as-Judge
β”œβ”€β”€ tests/                     # 16 test modules, 300+ tests
β”œβ”€β”€ docker-compose.yml         # Local microservice container orchestration
β”œβ”€β”€ Dockerfile                 # Backend FastAPI space configuration
β”œβ”€β”€ DEBT_LEDGER.md             # Technical debt tracking
└── pyproject.toml             # Dependencies and tooling config

Development

Run Tests

bash
# All tests
python -m pytest tests/ -v --tb=short

# Specific day/module
python -m pytest tests/test_integration.py -v

# With coverage
python -m pytest tests/ --cov=finrag --cov-report=term-missing

Lint

bash
ruff check src/ tests/
ruff format src/ tests/

Environment Variables

VariableRequiredDescription
GOOGLE_API_KEYYesGoogle Gemini API key (for embedding and answer generation)
EDGAR_USER_AGENTYesSEC EDGAR required user agent string (e.g. Company info@company.com)
DATABASE_URLYesPostgreSQL connection URL for logging query analytic stats
REDIS_URLNoRedis connection URL for sub-millisecond API response caching
LANGFUSE_PUBLIC_KEYNoLangfuse observability metrics dashboard public identifier key
LANGFUSE_SECRET_KEYNoLangfuse observability metrics dashboard secret developer key
FINRAG_API_KEYNoSecret bearer security token required for production API authorization
FINRAG_INIT_PIPELINENoSet false to skip backend model pipeline initialization during testing
FINRAG_CORS_ORIGINSNoComma-separated list or JSON array defining allowed CORS request origins

License

MIT