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.1

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.1
File Size Uploaded
jiujiubiao-0.3.1.tar.gz 114.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jiujiubiao 0.3.1
File Interpreter ABI Platform
jiujiubiao-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 176.2 kB

Release files / jiujiubiao-0.3.1.tar.gz

Download URL jiujiubiao-0.3.1.tar.gz
Size 114.5 kB
Tags Source
SHA-256 checksum
How to use checksums
39a9c6f85a52e0f0b805e45074b79d17ec335d9df904a5938b21c0f7686fbcba
BLAKE2b-256 checksum
How to use checksums
aef7269f7dbe652537cbb52087b7239c43161fe9d90551c9bcda06d00aa1e868
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.1-py3-none-any.whl

Download URL jiujiubiao-0.3.1-py3-none-any.whl
Size 61.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c681bb6b3980e4252b84ec9a9a4f4f6f61994487920eaa496616199417471887
BLAKE2b-256 checksum
How to use checksums
d042e9f4884d86acb7795297b1e5e8971a0a010777188a10dd7a81c53717c354
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

This release

0.3.1 This release

2 release files

0.3.0

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