Leo’s Build Log
PostsProjectsAbout한국어

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

  1. 01
    Numbers come from a calculation engineReturns, weights and P&L are computed by an engine. The AI writes sentences with markers where those values go.
  2. 02
    Answers 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.
  3. 03
    The AI only reads account dataOnly the backend changes account data. The AI uses a read-only internal API.
  4. 04
    Answers 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.

  1. 01
    Number 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
  2. 02
    Ten 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
  3. 03
    Tool-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)
  4. 04
    News 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
  5. 05
    Test-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

  1. 01
    Answers 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.
  2. 02
    Slow chat answersSwitched models, turned off reasoning in the tool-picking step and had tools called together to cut the wait.
  3. 03
    Guards blocking good answersCounted why answers were blocked in production and fixed the top cause: sentences split wrongly around footnotes.
  4. 04
    A 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.