FINCH
A personal AI investing assistant built on your portfolio

Screens
Overview
- Period
- Aug – Sep 2026 (6 weeks)
- Team
- 5 people · 2 frontend, 1 backend, 1 AI, 1 infra
- Role
- AI lead
The problem
Prices, news and filings in stock apps are the same for everyone, so you have to work out what they mean for your own portfolio. The goal: personalized information based on your holdings and trades, without the LLM making up numbers or giving investment advice.
The approach
- 01Numbers come from a calculation engineReturns, weights and P&L are computed by an engine. The AI writes sentences with markers where those values go.
- 02Answers are checked before they go outTen checks cover numbers, sources and buy/sell advice. A failed answer is regenerated, and dropped if it fails again.
- 03The AI only reads account dataOnly the backend changes account data. The AI uses a read-only internal API.
- 04Answers show their sourcesNews and filings are collected daily, and the ones used in an answer are attached as footnotes.
My work
Led the design and build of the AI server (FastAPI): briefing, chat, stock analysis and portfolio diagnosis, plus the output checks and data collection and search behind them.
- 01Number substitutionThe LLM writes only allowed keys and the server fills in engine values, so no uncomputed number can reach an answer.The LLM writes allowed keys like {{return_005930}}; the server substitutes engine values (+2.48%) · responses split into text/number segments
- 02Ten output checksNumbers, sources and banned phrases are checked; a failing answer is regenerated with the reason attached and blocked if it fails again.Raw numbers · engine mismatch · citation integrity · banned phrases · schema, and more
- 03Tool-using chat agentPicks the lookup tools a question needs (account, returns, prices, news, filings) and answers only from what they return.Tool selection → narration · 7 tools in parallel, max 3 turns / 12 calls · job queue (Postgres SKIP LOCKED)
- 04News and filing collection and searchScheduled collection of news, filings and prices, searched as evidence for answers and the daily briefing.Naver News · DART filings → chunking · embeddings (text-embedding-3-small) → pgvector + lexical search, RRF fusion
- 05Test-driven developmentChecks, number substitution and tool calls were defined as tests first, then implemented. Golden tests on a fixed portfolio catch calculation regressions.pytest · golden tests · 708 tests
Fixed in production
- 01Answers that only said "could not be confirmed"Found and fixed the root cause: depending on how the account was read, numbers never reached the AI.
- 02Slow chat answersSwitched models, turned off reasoning in the tool-picking step and had tools called together to cut the wait.
- 03Guards blocking good answersCounted why answers were blocked in production and fixed the top cause: sentences split wrongly around footnotes.
- 04A polluted experimentFailed responses left in the cache were hiding the A/B comparison; experiments now bypass the cache.
Stack
- AI
- Python · FastAPI · OpenAI · PostgreSQL + pgvector
- Backend
- Spring Boot 4 · PostgreSQL · Redis
- Frontend
- React 19 · TypeScript · Vite · TanStack Query · PWA
- Infra
- k3s · Helm · Cloudflare Tunnel
Related posts
No related posts yet.