Open-source AI equity research agent with evidence-grounded reports, resilient workflow orchestration, and RAG evaluation.
FinSight turns filings, financial reports, research notes, market data, and company events into source-grounded answers and versioned AI research reports. The project is intentionally backend-heavy: it shows how to build the infrastructure around an AI agent, not just how to call a model.
Most RAG demos stop at "retrieve chunks and ask an LLM." FinSight focuses on the parts that make an AI research system dependable:
- long-running agent workflows with explicit state transitions;
- idempotent task submission and duplicate execution control;
- Redis Lua single-flight leases with fencing tokens;
- report caching tied to data snapshots instead of loose prompt strings;
- PostgreSQL/pgvector hybrid retrieval with evidence traceability;
- RAG and agent quality evaluation for regression checks.
| Area | What FinSight Implements |
|---|---|
| Agent workflow | Data ingestion, metric recalculation, document indexing, intelligence build, and AI report generation as recoverable stages |
| Concurrency control | Idempotency keys, repository-level createIfAbsent, Redis Lua single-flight lease, fencing token, local fallback lock |
| Failure recovery | Task status machine, stage tracking, retry, dead letter state, timeout takeover scheduler |
| Trustworthy AI cache | contextHash, dataSnapshotHash, reportVersion, Redis/PostgreSQL-backed report reuse |
| Retrieval | PostgreSQL JSONB, full-text search, pgvector embeddings, hybrid recall, deduped evidence chunks |
| Evaluation | RAG hit rate, evidence coverage, answer coverage, hallucination risk, conclusion consistency, confidence calibration, latency |
| Demo surface | Spring Boot API, static dashboard, sample data flow, Actuator and Prometheus metrics |
flowchart LR
UI["Dashboard / REST API"] --> Backend["Spring Boot Backend"]
Backend --> Workflow["Agent Workflow Orchestrator"]
Workflow --> MQ["RabbitMQ Async Queue"]
Workflow --> Redis["Redis Lua Lease + Cache"]
Workflow --> PG["PostgreSQL + pgvector"]
Backend --> AI["FastAPI AI Service / Ollama fallback"]
PG --> Retrieval["Hybrid Retrieval + Evidence"]
Retrieval --> Backend
AI --> Report["Versioned AI Report"]
Report --> PG
Backend --> Eval["RAG / Agent Evaluation"]
More detail: Architecture Notes
- Architecture Notes
- Research API
- Agent Workflow Design
- Benchmark And Evaluation Notes
- Resume And Interview Notes
- GitHub Presentation Snippets
- Troubleshooting
- Roadmap
- Contributing
./scripts/run-full-stack.shThen open:
open http://localhost:8080This starts the backend, dashboard, PostgreSQL/pgvector, RabbitMQ, Redis, the FastAPI AI sidecar, and supporting infrastructure. If Ollama is not running, the AI service returns deterministic fallback analysis so the demo still works.
In another terminal:
./scripts/quick-demo.shOr run the smaller flows separately:
./scripts/demo-flow.sh
./scripts/demo-workflow.shUseful endpoints:
GET /api/workflows/summary
POST /api/evaluations/rag/run
GET /api/companies/600519/ai-analysis/latest
GET /api/document-index/600519/search?q=现金流风险Example demo output after ./scripts/quick-demo.sh:
| Signal | Example Result |
|---|---|
| Agent workflow | 1/1 tasks, 0 failed/dead-letter |
| RAG evaluation | 85 / 100, 2/3 cases passed |
| Evidence index | 6 documents, 6 chunks for 600519 |
| Intelligence graph | 20 events, 36 entities, 47 relations |
| Report cache | dataSnapshotHash + contextHash + reportVersion |
For a lightweight local backend using in-memory repositories:
cd backend
mvn spring-boot:run
open http://localhost:8080backend: Spring Boot service for APIs, domain workflow, metrics, and RAG orchestration.ai-service: FastAPI service for document parsing, entity extraction, embedding, rerank, and answer generation stubs.docker: local infrastructure placeholders.
Backend:
cd backend
mvn spring-boot:runDashboard:
open http://localhost:8080Backend with PostgreSQL profile:
docker compose up -d postgres
cd backend
mvn spring-boot:run -Dspring-boot.run.profiles=postgres,prodBackend with PostgreSQL + RabbitMQ workflow:
./scripts/run-backend-workflow.shProduction-like stack with PostgreSQL, pgvector, RabbitMQ, FastAPI AI service, Actuator, and the dashboard:
./scripts/run-full-stack.sh
open http://localhost:8080AI service:
cd ai-service
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8001Optional local Ollama analysis:
ollama serve
ollama pull qwen2.5:7bThe FastAPI sidecar calls OLLAMA_BASE_URL (http://localhost:11434 by default) and OLLAMA_MODEL
(qwen2.5:7b by default) from /analyze-stock. If Ollama is not installed, not running, or the model is
missing, the endpoint returns a deterministic rule-based fallback with aiGenerated=false, so the dashboard
keeps working.
POST /api/ingestion/demoseeds a sample company document and financial statements.POST /api/metrics/recalculate/600519calculates financial indicators and risk signals.POST /api/analysis/askasks a source-grounded question.POST /api/document-index/{symbol}/rebuildrebuilds document chunks for retrieval.POST /api/intelligence/{symbol}/rebuildbuilds timeline events and a lightweight knowledge graph.
Async workflow:
POST /api/ingestion/demo/async
GET /api/workflows
GET /api/document-index/600519/search?q=现金流风险
GET /api/metrics/600519/runs
GET /api/intelligence/600519/timeline
GET /api/intelligence/600519/graph
POST /api/evaluations/rag/runThe PostgreSQL implementation is enabled by postgres,prod profiles. Flyway creates the core schema:
companiesfinancial_documentsfinancial_statementsfinancial_metricsrisk_signalsworkflow_taskscompany_eventsrag_tracesstock_analysis_reportsuser_watchlists
Default profile still uses in-memory repositories so the backend remains easy to run without Docker.
The workflow stage splits long financial data processing into task lifecycle and execution:
WorkflowTaskstores idempotency key, status, agent stage, attempt count, payload, error message, lease owner, fencing token, and update time.WorkflowTaskPublisherhas two implementations:- default direct publisher for local development;
- RabbitMQ publisher enabled by
rabbitmqprofile.
WorkflowOrchestratoruses Redis Lua single-flight leases, idempotency keys, and local fallback locking to prevent duplicate cross-node execution.WorkflowRecoverySchedulerscans timed-outRUNNINGtasks, marks them recoverable/dead-lettered, and republishes retryable work.- Agent stages model the long-running research flow from ingestion to metrics, indexing, intelligence build, AI analysis, success, failure, and recovery.
DOCUMENT_INDEX_BUILDchunks ingested documents and writes retrieval-ready evidence chunks.COMPANY_INTELLIGENCE_BUILDturns documents, metrics, and risk signals into timeline events and graph relations.STOCK_AI_ANALYSIScreates source-grounded AI stock reports and persists them for history and caching.RabbitWorkflowListenerconsumes messages and moves failed messages to a dead-letter queue when RabbitMQ rejects them.
Run:
./scripts/run-backend-workflow.sh
./scripts/demo-workflow.shThe retrieval stage indexes financial documents at evidence-chunk granularity:
DocumentChunkersplits long documents with overlap and section metadata.EmbeddingServicecreates deterministic 384-dimensional embeddings for local demos, and can call the FastAPI AI sidecar/embedendpoint whenfinsight.ai-service.enabled=true.DocumentChunkRepositorysupports keyword search, vector search, and chunk replacement.- PostgreSQL profile stores chunks in
document_chunkswith JSONB metadata, full-text GIN index, and pgvector cosine index. HybridRetrievalGatewaymerges keyword and vector channels, deduplicates chunks, and passes source-bound evidence to RAG.
Useful endpoints:
POST /api/document-index/600519/rebuild
GET /api/document-index/600519/count
GET /api/document-index/600519/search?q=现金流风险The metric engine stage turns hard-coded ratios into a governed calculation pipeline:
MetricDefinitionCatalogdefines source metrics, ratio metrics, year-over-year metrics, and derived spreads.CoreFinancialMetricCalculatorevaluates metrics in fiscal-year order and stores results with a plan version.MetricCalculationRunrecords each calculation run with statement count, metric count, risk count, timestamps, and metadata.RiskRulecomponents evaluate financial risk signals from the metric map:- cash earnings quality;
- receivable pressure;
- profitability trend weakening;
- leverage risk.
Useful endpoints:
GET /api/metrics/definitions
POST /api/metrics/recalculate/600519
GET /api/metrics/600519
GET /api/metrics/600519/risks
GET /api/metrics/600519/runsThe intelligence stage upgrades isolated documents and metrics into company state modeling:
CompanyIntelligenceServiceextracts standard events from filings, research notes, metrics, and risk signals.CompanyEventRepositorystores a company timeline ordered by event date.KnowledgeGraphRepositorystores lightweight graph nodes and relations in PostgreSQL.- Graph entities include company, industry, document, product/keyword, financial metric, and risk event.
- Graph relations include industry membership, published documents, mentioned keywords, financial metrics, risks, and timeline events.
Useful endpoints:
POST /api/intelligence/600519/rebuild
GET /api/intelligence/600519/timeline
GET /api/intelligence/600519/graphThe final stage adds a demo console and regression-style RAG evaluation:
- Static dashboard is served by Spring Boot from
/. - The dashboard shows workflow tasks, metric output, retrieval evidence, timeline events, graph counts, and evaluation results.
EvaluationCaseCatalogdefines fixed financial QA test cases.RagEvaluationServicechecks RAG hit rate, evidence coverage, answer coverage, citation presence, hallucination risk, conclusion consistency, confidence calibration, and latency.
Useful endpoints:
GET /
GET /api/evaluations/rag/cases
POST /api/evaluations/rag/runThe stock AI stage turns the dashboard into a practical A-share research workflow:
StockUniverseServicesyncs 5500+ A-share symbols from free public providers and falls back to Eastmoney search.StockAnalysisApplicationServicesubmits single-stock and batch analysis as workflow tasks.StockAiAnalysisServicebuilds a prompt context from quote data, financial metrics, risk signals, and RAG evidence chunks.- AI analysis calls the FastAPI sidecar and local Ollama when available, then falls back to deterministic rules when the model is unavailable.
stock_analysis_reportsstores every generated report with model/source metadata, citations, context hash,data_snapshot_hash, report version, and generated time.StockAnalysisCachehas an in-memory local implementation and a Redis implementation enabled by theredisprofile; cache keys are tied to the data snapshot hash so stale AI conclusions are not reused after evidence changes.StockMarketSchedulercan sync the stock universe and submit a morning batch scan on a configurable cron schedule.user_watchlistsprovides a simple user-scoped stock watchlist foundation using theX-Finsight-Userrequest header.
Useful endpoints:
POST /api/companies/sync-a-shares
POST /api/companies/batch-analysis
GET /api/companies/600519/ai-analysis
GET /api/companies/600519/ai-analysis/latest
GET /api/companies/600519/ai-analysis/history
GET /api/watchlist
POST /api/watchlist/600519
DELETE /api/watchlist/600519The production-like stage makes the prototype easier to present as a backend/AI system:
- Docker Compose builds and runs
backend,ai-service, PostgreSQL/pgvector, RabbitMQ, Redis, Elasticsearch, and MinIO. postgres,rabbitmq,redis,prodprofiles enable persistent repositories, Flyway migrations, pgvector search, Redis analysis cache, and RabbitMQ task dispatch.RestAiServiceClientcalls FastAPI/rerankand/generate-answer, while keeping deterministic local fallback for demos and tests.- Workflow APIs expose task listing, task detail, status summary, and manual retry for failed/dead-letter tasks.
- Spring Boot Actuator exposes health, metrics, and Prometheus scrape output at
/actuator/health,/actuator/metrics, and/actuator/prometheus. - Test coverage includes deterministic embedding tests and a Testcontainers smoke test for PostgreSQL/pgvector + RabbitMQ profiles.
Useful endpoints:
GET /actuator/health
GET /actuator/prometheus
GET /api/workflows/summary
GET /api/workflows/{taskId}
POST /api/workflows/{taskId}/retry