Astrology software looks like it should be trivial — dates and planet positions — until you meet the actual numerics. Building TianJi's chart engine taught us where the hard parts live.
Ephemeris first. You need planet positions accurate to arcminutes across decades. You either embed VSOP87 (analytic, ~200KB of series coefficients) or call Swiss Ephemeris (precise, native dependency). We embedded a compact analytic series: fast, dependency-free, accurate enough for house cusp and aspect work.
Aspects are a tolerance-search problem. A trine is a 120° separation with an orb (tolerance) of, say, 6°. Naively you compare all planet pairs — fine for 10 bodies. Add centaurs and asteroids and you're comparing 30+ bodies across time ranges to find when an aspect becomes exact. The interesting version is inverting the question: "when does this aspect next perfect?" — which becomes a root-finding problem over the ephemeris.
Timezones and birth data. Birth time in 1987 in a city whose timezone rules changed twice since. Historical tz data (with LMT fallbacks for pre-standardization towns) is non-negotiable, or every ascendant is wrong by degrees.
Where LLMs fit — and don't. The model does not compute charts; it interprets them. We hand it the structured chart (verified by the engine) plus the user's question, and it produces the reading. Hallucination risk is contained by making the numeric layer authoritative: the LLM never generates positions, only prose about positions that already exist.
That split — deterministic math core, generative language shell — is the architecture we'd recommend for any "AI + domain" product where the domain has exact facts.
TianJi puts this in an app with daily transits, natal charts, and AI readings.
Top comments (0)