子平 · 玄元
辨伪
Auspice青鸾信

Why AI BaZi Skills Get the Chart Wrong

为什么 AI 算八字不准 · 错在排盘,不在解读

Most AI divination tools fail before interpretation begins. Casting a chart is arithmetic with exactly one right answer — it needs the exact timestamp of a solar term, a longitude and equation-of-time correction, and historical time-zone data. A language model asked to do that step returns something that looks like the answer, and nothing about the output reveals the error.

This is the reverse of how people assume it works. Chart casting looks like the easy mechanical part and interpretation looks like the hard part. In fact interpretation has no ground truth, so anything reads as plausible; casting has exactly one correct output, and it is where most implementations fail. Every chart below is computed at build time by the same engine that powers the calculator — none of these numbers are typed in by hand.

The year boundary is a timestamp, not a date

Shanghai, February 1990. Only the clock time changes between these rows:

Birth momentYearMonthDayHour
1990-02-03 23:00己巳丁丑己亥乙亥
1990-02-04 10:00己巳丁丑庚子辛巳
1990-02-04 12:00庚午戊寅庚子壬午
1990-02-04 14:00庚午戊寅庚子癸未
1990-02-05 01:00庚午戊寅辛丑戊子

Look at the three rows for 4 February. At 10:00 the first two pillars are 己巳 丁丑; at 12:00 they are 庚午 戊寅. The year and month pillars both changed in the middle of a single day, because the BaZi year turns at Lichun — the moment the sun reaches 315° of ecliptic longitude, not midnight and not Chinese New Year. Two people born the same calendar day, one before lunch and one after, differ in four of their eight characters.

So how does a tool know what time Lichun occurred in 1990? There are two ways: ship a table of every solar term for every year to minute precision (1900–2100 × 24 terms is roughly 48,000 timestamps), or compute the astronomy at runtime. A Skill that encodes solar term dates in a Markdown knowledge base has day granularity, which means everyone born on the boundary day gets a year pillar that is either entirely right or entirely wrong depending on which half the model guessed. That is not a difference of interpretive style — it is a quarter of the chart being incorrect.

The clock on the wall is not the sun

Same wall-clock reading, same official time zone, two cities — 15 June 1992, 07:10 Beijing time:

BirthplaceLongitudeSolar correctionHour pillar
Shanghai121.47°E+5 min甲辰
Ürümqi87.6°E-130 min壬寅

Different hour pillar — both characters change. China spans roughly four geographic time zones (73°E to 135°E) and runs on one official clock, but BaZi uses the sun where you were born. At 07:10 on the Ürümqi clock, local solar time is barely past 05:00 and the sun is only just up: that is the 寅 hour, not 辰, two full branches apart. Computing this needs the birth longitude, the UTC offset in force there on that date, and the equation of time — the ±15-minute daily discrepancy caused by Earth's elliptical orbit and axial tilt, which is a trigonometric series evaluated per day of year. Asking a model for that value yields a plausible number, not a computed one; and one degree of longitude error is four minutes, enough to flip a pillar near a boundary. The full arithmetic is on the true solar time page.

The hour that never existed

Shanghai, 1 July 1988, 08:00 on the clock. The engine's total correction is -58 minutes, and it decomposes into three separate terms: daylight saving -60, longitude +6, equation of time -4. Eight o'clock on that clock was really 7:02, because China observed daylight saving time from 1986 to 1991 — a fact almost nobody remembers now. People born in those six years are in their thirties today, squarely the demographic that goes looking for a reading, and their birth records show a clock that had been moved forward an hour. An hour is enough to cross an entire hour branch, and at the right time of night, the day pillar too.

It gets worse at the transition itself: on the spring-forward date local 02:00 jumps straight to 03:00, so that hour never existed locally. A birth record reading 1988-04-17 02:30 does not correspond to a real instant. This engine got that wrong at first — the original implementation reverse-solved the UTC instant by fixed-point iteration, which does not converge for a nonexistent input but returned a result anyway, so 02:59 and 03:00 mapped to the same real instant while producing different hour pillars. It is now pinned by a test that walks every minute of the gap across all six Chinese DST years.

None of these errors throw. The system quietly hands you eight tidy characters, and nothing about the output looks degraded. Feed that chart to any competent language model and it will fluently explain what those characters mean about your life — and the better the prose, the more thoroughly wrong the result.

Why it feels accurate anyway

Because this domain has no verification loop. You enter a birthday, you get a paragraph, and it feels like it fits. That feeling has three sources: the Barnum effect, where sufficiently general descriptions fit everyone; the model's genuine fluency, since it was trained to generate text you find apt; and your own cooperation, because people unconsciously supply confirming evidence for a reading they have already heard. Together those are more than enough to make a system working from a completely incorrect chart read as accurate.

In most domains a miscalculation produces feedback: the build breaks, the ledger does not balance, the bridge falls down. Here there is none. The user will not know, the model will not know, and the tool author will not know either — unless someone writes a test. Which is why user satisfaction is not evidence of correctness in this field, and the two can stay decoupled indefinitely.

The actual bug is the division of labor

Packaging divination as a Skill is not itself the problem — the task split is. Chart casting is pure computation: given an instant and a place, the eight characters are uniquely determined and there is zero interpretive latitude. That belongs in code — a pure function, unit tested, identical every run. Interpretation is language, and models are genuinely good at it. The failure is handing the first job to the model as well. An LLM's reliability at table lookup and its reliability at prose are not remotely the same number.

The engine decides what is said. The model decides only how to say it.

Here the eight characters, elemental strengths, favourable elements and luck cycles are all computed in TypeScript, unit tested, with every convention and scoring weight published on the method page. The model receives a block of facts and one directive: cite only what is given. There is a second benefit that is easy to miss — once the engine owns the facts, it can also own the uncertainty. When a birth hour is unknown we do not pick a default: there are exactly twelve possibilities, so all twelve charts are cast and intersected, and only conclusions true in every candidate are stated. The rest is left visibly blank. A stated hole beats a silent one.

Three questions that test any tool

If you are using an AI divination tool, these are checkable without any special knowledge:

  1. Born on a solar-term boundary day — does it know the exact time that term began that year?
  2. Born far from your time zone's meridian — does it correct for birth longitude? Born in China 1986–1991 — does it subtract the daylight saving hour?
  3. You do not know your birth hour — does it leave it blank, or quietly assign one?

If it cannot answer one of the three, the chart has a meaningful chance of being wrong — and it will read exactly as convincing either way. For a deliberate test with worked arithmetic, three reproducible birth times show what a correct engine must return and what each level of partial implementation returns instead.

For the derivation itself, see how a chart is calculated; for the solar-time arithmetic, true solar time. Every convention this engine uses is published on the method page, and every correction we have made is logged at corrections. Or cast your chart — free, no account, every step above applied.