Skip to main content

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)

Source distribution for jiujiubiao 0.3.0
File Size Uploaded
jiujiubiao-0.3.0.tar.gz 105.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jiujiubiao 0.3.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

0.3.2

2 release files

0.3.1

2 release files

This release

0.3.0 This release

2 release 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