Skip to main content

Fihrist

Place a book on a lattice that stays even-handed when you change the model underneath it.

pip install fihrist

Fihrist ships a faceted classification artifact — 3,660 leaves across 10 axes — built so that no tradition sits at the centre as the unmarked default. Give it a book's contents and it tells you where that book belongs. The placement is earned from what the work is about, never from the author's nationality or the country it was published in.

Named for the Kitāb al-Fihrist (Baghdad, 987 CE), a bookseller's attempt to index every book then known, across every language he could reach.


What you need before you start

Fihrist takes an enriched book record, not a title.

A title and an author are not enough, and that is the whole point rather than a missing feature. The lattice slots on what a book contains. Feed it a bare title and the only thing a model can classify on is the author's name and origin — which is precisely the bias the artifact exists to remove.

So the input is a record carrying idea units: the handful of things the book is actually about. Step 2 below shows how to get them.

What Fihrist does and does not do

Fihrist makes no network calls and never sees an API key. It builds prompts and checks answers. The model call is yours, on your account, with your choice of provider.

Fihrist owns You own
the artifact, verified against its sha256 on load the API key
leaf and parent lookup, the 9 embedded parity audits the model call
building the research prompt running it
building the slot prompt running it
validating the reply — invented leaves are dropped

Reads as a limitation for about ten seconds, and as a feature forever: no key, no telemetry, no surprise bill, and it works on a plane.


1 — Inspect the artifact

Offline, immediate, free.

import fihrist

lat = fihrist.load()              # hash-verified against the shipped sha256
len(lat)                          # 3660
lat.axes                          # ['Discipline', 'Place', 'Time', 'Form', 'Genre', ...]
len(lat.leaves("Discipline"))     # 1246

lat.find("Meiji")                 # [Leaf('Modern Japan (Meiji–Shōwa)', axis='Discipline', ...)]
lat.parents_of("Modern Japan (Meiji–Shōwa)", "Discipline")
# ['Japanese history']

lat.audits                        # the 9 parity audit reports, carried inside the file

The artifact carries its own audits. You do not have to take the parity claim on trust — open lat.audits and read what was checked.

From the shell:

fihrist verify
fihrist axes
fihrist leaves --axis Discipline --grep literature

2 — Enrich a book

Fihrist writes the research prompt. You run it against any model that can search the web.

prompt = fihrist.enrich_prompt("I Am a Cat", "Natsume Sōseki")
record = fihrist.parse_enrichment(your_model(prompt))

record["ideaUnits"]
# [{'id': 'the-outsider-narrator-sees-clearest-1',
#   'title': 'The Outsider Narrator Sees Clearest',
#   'tags': ['narration', 'satire', 'detachment']}, ...]

The instruction body is frozen and byte-identical for every book — only the assignment block at the end changes. That constancy is deliberate. A prompt that said more about a Japanese novel than a French one would manufacture the very difference the artifact exists to measure, then hand it to the slotter as though the lattice had caused it.

3 — Slot it

prompt = fihrist.slot_prompt([record])
results = fihrist.validate(your_model(prompt), [record])

results[0].attached[0]
{"axis": "Discipline", "parent": "Japanese history", "leaf": "Modern Japan (Meiji–Shōwa)",
 "confidence": "stretch", "culture": "Japanese", "status": "valid"}

Batch as many books into one slot_prompt call as your context window allows. The lattice index is rendered first and identically every time, so a prompt-caching backend caches it across a whole run.

Validation is not a formality

fihrist.summarise(results)
# {'books': 1, 'attachments': 7, 'rejectedAttachments': 1,
#  'booksWithNoAttachment': 0, 'leavesPerBook': 7.0, 'byAxis': {...}}

Three things worth knowing:

  • Invented leaves are dropped. Models produce plausible leaves in the artifact's own house style. An invented one that survives into your results is worse than a missing one, because it looks like evidence. Anything not on the lattice goes to rejected with a reason, never into attached.
  • A wrong parent is repaired, and the repair is recorded in parentRepaired. Polyhierarchy means a leaf can hang from several parents; any true one is accepted.
  • Check booksWithNoAttachment first. A batch that comes back structurally valid and substantively empty is the quietest way a run fails — the JSON parses, nothing raises, and the numbers are simply thin. That counter is where it shows.

From the shell

fihrist verify                                    # hash check
fihrist axes                                      # the 10 axes
fihrist leaves --axis Genre --grep thriller
fihrist prompt enrich --title "I Am a Cat" --author "Natsume Sōseki"
fihrist prompt slot books.json > prompt.txt
fihrist validate response.json --books books.json --out slotted.json

The claim, and its limits

Seven engines — Claude, GPT, DeepSeek, and local Qwen models from 30B to 235B — slotted the same 1,232 books onto this lattice. All of them top-ranked India, China and Japan on the Place axis. A biased engine buries those. None did. The correction lives in the artifact rather than in a prompt or a model, so swapping the model does not bring the bias back.

What is not established: a later 425-book corpus run, pre-registered and sealed, did not confirm this at corpus scale — its three gates all counted Discipline leaves, and the registered engine produces 0.20 Discipline leaves per book on fiction, so the probes largely measured the instrument rather than the artifact. That run, its failure, and the reasoning are published alongside the evidence rather than quietly dropped. See the corpus dataset.

Seven of the ten axes carry a published parity audit. Three — Agent/Entity, Action/Process, Thing/Matter — are provisional and marked as such (fihrist.PROVISIONAL_AXES).

The guard rules

fihrist.GUARDS is the anti-bias correction, carried verbatim from the run that produced the published results. Rewording it invalidates every parity claim attached to this artifact. If you need different behaviour, write your own prompt rather than editing those lines, and do not report the result as a Fihrist placement.

Cost

Fihrist itself is free and offline. Steps 2 and 3 are your own model calls — roughly one search-enabled call and one slot call per book.

Just want to look?

The evidence is being published as datasets — 425 books slotted independently by three engines, the artifact with its audits, and a browsable view of the result. Until those land, everything the package needs is in the wheel, and the source repo is bk2022-ui/lattice.

Licence

Code: Apache-2.0. The artifact (world-lattice.json) and the corpus: CC-BY-4.0.

Attribution is the point. If the lattice is doing work for you, cite it.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fihrist-0.1.0.tar.gz (249.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fihrist-0.1.0-py3-none-any.whl (254.7 kB view details)

Uploaded Python 3

File details

Details for the file fihrist-0.1.0.tar.gz.

File metadata

  • Download URL: fihrist-0.1.0.tar.gz
  • Upload date:
  • Size: 249.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for fihrist-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d6770c842bbd792452c22cbcc3d553a819343f431688b3a2feafc5a06e733e63
MD5 4c49a674cb05245e7d1ae0b9a0699f96
BLAKE2b-256 6ed5947b914c789911c0011b97571d418387be8b739e981e37fbed1586705944

See more details on using hashes here.

File details

Details for the file fihrist-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: fihrist-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 254.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for fihrist-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0eac8e4d7ac5641aca44f823a8a96c84153a49ba299bd7326b00c097147e34b9
MD5 bd1fdb822cb11ed0738ccf1bf60c23f9
BLAKE2b-256 e5837fc106975bf8aabb49f2a66da50c5f4436da1e8691bc716a18434f8623f1

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.1

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page