Build story

Building a BlackRock-Aladdin-style intelligence platform with a free-LLM cascade

By Dmitry · DigiWorks · ·~12 min read

BlackRock's Aladdin runs risk analysis on something like a fifth of the world's investable assets. It is a decision-support system: it ingests everything, models the relationships, and hands portfolio managers a coherent view of exposure. I wanted a small, self-hosted version of that idea — not the scale, but the shape: pull signal from across the open (and deeper) web, score how much you can trust each piece, fuse it into entity-level views, and reserve expensive reasoning for the moment a decision actually gets made.

I called it Aladdin too, because the pattern is the point. This is a build story about the architecture — the parts I'd defend in a design review, and the one part that turned out to be mostly noise. No fabricated benchmarks: the numbers below are what the system actually processed.

The one idea worth stealing: a tiered-LLM cascade

The expensive mistake with LLM pipelines is treating every token as if it deserves a frontier model. Most of the work in an intelligence system is not reasoning — it's grunt work: collecting, deduplicating, summarizing, pulling entities out of a paragraph. That work is high-volume and low-stakes. You do not need Claude to tell you that a Reddit post mentions Nvidia.

So Aladdin runs a cost cascade. Every distill task tries the cheapest capable tier first and only escalates when a tier fails or declines. Concretely, in order:

distill(item):
  try  nim-llama-3.3-70b   # free NVIDIA NIM, via LiteLLM proxy
  else try  ollama          # local model, zero marginal cost
  else try  claude-haiku    # cheap frontier fallback
  else      heuristic()     # dependency-free, always answers

The bottom rung matters as much as the top. The heuristic fallback is a plain-Python distiller — regexes, keyword frequency, a couple of scoring rules — that produces a usable summary and entity list with no network call and no model at all. It means the pipeline never hard-stops on a distill task. A rate limit or a cold Ollama node degrades quality; it does not halt ingestion.

This is not a new idea — it's the practical version of what the FrugalGPT and RouteLLM papers argue: route by difficulty, cascade on cost, and you keep most of the quality for a fraction of the spend. What I can tell you is that it held up in production.

Of ~28,000 signals the system processed, roughly 14,600 were distilled by the free NVIDIA model. The cheap tier didn't just handle the easy cases at the margin — it did the bulk of the work. Claude was reserved for the top of the funnel: fusing Gold-layer entity views and producing the actual decision-ready analysis. That's the whole trick. Spend frontier-model money where a wrong answer costs you, not where volume lives.

The cascade in one diagram

  volume  ┌──────────────────────────────────────────────┐
   high   │  TIER 0  free NVIDIA NIM (nim-llama-3.3-70b)  │  ~14.6k items
    │     │          via LiteLLM proxy                    │
    │     ├──────────────────────────────────────────────┤
    │     │  TIER 1  local Ollama                         │  fallback
    │     ├──────────────────────────────────────────────┤
    │     │  TIER 2  Claude Haiku                         │  cheap escalation
    │     ├──────────────────────────────────────────────┤
    v     │  TIER 3  heuristic (no model, never fails)    │  floor
   low    └──────────────────────────────────────────────┘
  stakes           ▲ only Gold-layer FUSION + final
                     decisions escalate to a frontier model

Medallion architecture on Postgres + pgvector

The data layer is a classic medallion: Bronze → Silver → Gold, all in Postgres with pgvector for embedding search. I didn't reach for a lakehouse or a streaming stack. One Postgres instance with three logical tiers is enough to keep the transforms honest and the lineage traceable.

Keeping the tiers physically separate is what lets the cheap-model noise in Silver stay contained. Bronze is always re-derivable, and Gold never sees a raw item it hasn't been scored and fused.

Eleven sources, and being honest about signal vs. noise

Aladdin pulls from eleven data sources: SEC EDGAR (Form-D capital-raise filings), FRED macro series, GDELT global news, Reddit, Hacker News, the academic stack (OpenAlex, Crossref, Semantic Scholar), Stack Exchange, Steam, and Wikimedia. Deliberately eclectic — the goal was breadth of signal type, not one clean feed.

Here's the honest part. About 76% of the raw feed is GDELT — global news at firehose volume. And GDELT is noisy. It's broad, it's repetitive, and a huge fraction of it is restatement of the same wire story across outlets. If I'd judged the system by feed volume, I'd have concluded most of it was news.

The real value came from the narrow, high-signal sources. EDGAR Form-D filings — companies disclosing capital raises — are structured, sparse, and hard to fake. When I fused those in Gold, a pattern fell out that the news volume completely buried: AI capital was concentrating in health-AI. That's a finding you can act on, and it came from a source contributing a rounding error's worth of raw items.

The lesson I'd underline for anyone building this: volume is not signal. A system that optimizes for how much it ingests will drown itself. The credibility layer exists precisely so the sparse, trustworthy sources aren't outvoted by the loud ones.

Credibility scoring, grounded in the literature

"Trust score" is easy to hand-wave. I didn't want a made-up weighting, so each component maps to a published method, and each lives in its own module:

The point of layering these is defense in depth against manufactured consensus. TrustRank handles provenance, CRH handles agreement, copy-cluster handles duplication, and the Beta prior handles "we've barely seen this source." A single astroturf campaign has to beat all four to move a Gold-layer view.

Entity resolution without an ML model

Cross-source fusion is only useful if "Musk," "Elon Musk," and "@elonmusk" collapse to one entity. I resolved this deterministically rather than reaching for a learned linker: normalize names (case, punctuation, whitespace), then merge on token-subset containment. If one normalized name's tokens are a subset of another's, they cluster — so "Musk" merges into "Elon Musk" across sources without a training set, without embeddings, and without non-determinism.

It's not perfect — token-subset merging can over-merge in adversarial cases — but for an intelligence feed it's fast, explainable, and reproducible. When a merge is wrong, I can see exactly why and add a rule. That's worth more here than a marginal accuracy bump from a model I can't audit.

A shared brain other agents can query

Aladdin isn't only for me. It exposes an MCP server with 5 tools, so other AI agents can query the shared brain over HTTP — in parallel — instead of each one re-crawling the web. One agent researches a company, another checks macro conditions, a third pulls sentiment, and they all hit the same scored, fused Gold layer. The credibility work is done once and reused everywhere. That's the leverage: the expensive part (trust, fusion, resolution) is centralized, and every downstream agent inherits it for the cost of an HTTP call.

What I'd tell you if you were about to build one

The satisfying result wasn't the scale — 28,000 signals is modest. It was watching the architecture do its job: a free model handling the grunt work, a credibility layer refusing to let the loud sources drown the trustworthy ones, and a single sparse feed surfacing a real pattern the firehose had buried.

Want a system like this built for your domain — the real architecture, not a demo?

Let's talk →