JiuJiuBiao 九九表
三七——二十一。 — Every Chinese schoolchild learns the 九九表 (multiplication table): a grid you interrogate and it answers, instantly. JiuJiuBiao does this for your data — one table, every question.
JiuJiuBiao is a unified question-answering toolkit for tables and databases. One pipeline covers the full chain, each stage pluggable:
question + table/database
→ [1] Disambiguation (optional, CLEAR-style): detect ambiguity, clarify, rewrite
→ [2] Solving — two interchangeable engines:
• Solver: ReAct agent + self-consistency over a tool registry
(long tables, messy formats, databases) [TALON/RAISR family]
• Refiner: init → self-criticism → multi-tool refinement →
multi-tool consistency vote [TableCritic family]
→ [3] Output check: normalization, refusal detection, format gating
Quickstart
import jiujiubiao
engine = jiujiubiao.JiuJiuBiao() # endpoint from env (see below)
result = engine.ask(
"In which venue did the athlete win the first place?",
table=[["Year", "Venue", "Position"],
["2001", "Edmonton", "3rd"],
["2003", "Paris", "1st"]],
)
print(result.answer) # Paris
print(result.mode) # "refine" (small table) — "solve" for long tables / DBs
Databases are first-class — the solver grounds itself with schema tools and executes real SQL:
from jiujiubiao import Database
db = Database.from_sqlite("concert_singer.db") # or Database.from_dataframe(df)
result = engine.ask("How many singers are from France?", db=db)
Offline development / tests need no endpoint at all:
from jiujiubiao import FakeLLM, JiuJiuBiao
llm = FakeLLM(rules=[(r"Now it's your turn", ["Answer: Paris"] * 3)])
engine = JiuJiuBiao(llm=llm, refiner_kwargs={"n_samples": 3})
Endpoint configuration
No SDK dependency — plain HTTP to any OpenAI-compatible endpoint
(vLLM, Ollama, DeepSeek, OpenAI, ...) or an Anthropic-messages endpoint
(JIUJIUBIAO_BACKEND=anthropic):
| Variable | Default | Purpose |
|---|---|---|
JIUJIUBIAO_BACKEND |
openai |
openai (chat/completions) or anthropic (messages API) |
JIUJIUBIAO_BASE_URL / OPENAI_BASE_URL |
https://api.openai.com/v1 |
endpoint |
JIUJIUBIAO_API_KEY / OPENAI_API_KEY |
— | API key |
JIUJIUBIAO_MODEL / OPENAI_MODEL |
— | model name (required) |
JIUJIUBIAO_TIMEOUT / JIUJIUBIAO_RETRIES |
180 / 6 |
request tuning (rate-limit-aware backoff) |
Benchmarks (public, reproducible)
Seeded stratified samples, K3-class endpoint, sc=3, mode=auto:
| Benchmark | Sample | Accuracy | Notes |
|---|---|---|---|
| WikiTableQuestions (test) | 100 | 0.82 | misses cluster on subtle counting (dedup/temporal filters) and gold-format quirks |
| TabFact (validation) | 100 | 0.97 | balanced labels (51/49); misses are subtle "only X" claims |
Reproduce:
JIUJIUBIAO_BACKEND=anthropic python benchmarks/run_benchmark.py --benchmark wtq --n 100
CLI
jiujiubiao --dataset data/examples/wtq.json --task tqa --limit 10 --output results.json
Dataset format: a JSON array of
{"id", "table_caption", "table_text": [[header], [row]...], "question", "label"}
(TabFact style: statement + boolean label).
Extending
Register a solver tool and it joins the action space — prompt and dispatch update automatically:
from jiujiubiao import register_tool
@register_tool
def count_rows(ctx, arg):
"count_rows() — Return the number of rows in the current table."
return str(len(ctx.memory.get("df", ctx.df)))
Refine-stage tools (each with generate + critic) register via
@register_refine_tool in jiujiubiao.agents.refine_tools.
Installation
pip install -e . # pandas + cloudpickle only
pip install -e ".[fuzzy]" # faster fuzzy matching (rapidfuzz)
pip install -e ".[dev]" # tests + lint
Training-side utilities
jiujiubiao.training carries the CORES composite process reward (format gate +
schema grounding + structure similarity + execution correctness against a
SQLite database), with everything injected — usable standalone or as a
verl/GRPO reward function:
from jiujiubiao.training import compute_process_reward
reward = compute_process_reward(
response, gold_sql, gold_python,
schema={"results": ["venue", "wins"]}, db_path="data/results.db",
)
print(reward.total, reward.r_schema, reward.r_struct, reward.r_exec)
Research lineage
JiuJiuBiao consolidates five peer-reviewed works from one lab:
- CLEAR (ICDE 2025) — parser-independent NL2SQL disambiguation → stage [1]
- TALON (EMNLP 2025) — multi-agent long-table exploration → solver
- RAISR (ICASSP 2026) — collaborative database agents, execution grounding, output checking → database tools, stage [3]
- TableCritic (CogSci 2025) — self-criticism + tool library → refiner
- CORES (ACL 2026 Findings) — code-oriented reasoning (Python as pivot);
the
def()code tool follows this paradigm
If you use JiuJiuBiao, please cite the relevant papers (see CITATION.cff).
License
Apache-2.0. Ported modules retain their original notices (solver prompts and execution sandbox: Apache-2.0, Google Research; refiner: CC-BY, TableCritic).
Metadata
Release files for jiujiubiao 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jiujiubiao-0.3.0.tar.gz | 105.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jiujiubiao-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 164.9 kB
Release files / jiujiubiao-0.3.0.tar.gz
| Download URL | jiujiubiao-0.3.0.tar.gz |
|---|---|
| Size | 105.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bbe9230d7fc0a64dc80496b3e83fadb24c064dfc12469f97ed431959e8c1a797
|
|
BLAKE2b-256 checksum How to use checksums |
cec456bfe42ee34c689e73cd288a1c79b33c37a20b0972a33de606cfc162b82e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency logRelease files / jiujiubiao-0.3.0-py3-none-any.whl
| Download URL | jiujiubiao-0.3.0-py3-none-any.whl |
|---|---|
| Size | 59.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3d7a3fb27ef75f09753c088d6845d7cbd01b68eaf618f59fa63ead96abd7db4e
|
|
BLAKE2b-256 checksum How to use checksums |
9cb6fb4e5a386ad5ac2fa3607d4755bd5d3c12cdaac2d2c94548254866326959
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 11, 2026.
Transparency log