Busabase
Busabase는 AI 에이전트를 위한 오픈소스(MIT) 데이터베이스 및 작업 공간입니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
Sales analytics assistant that only shows an answer when every number matches a query result. FastAPI, SQLite, validated tools, grounding checks, held-out evaluation.
README 전체를 불러오는 중입니다.
README 전문 보기 ↗AI analytics assistants can state numbers confidently that no query ever produced. GroundedBI shows the guardrails that prevent that: fixed validated tools, read-only SQL, and an answer withheld unless every number matches a query result.
You ask a question about a synthetic electronics retailer's sales, such as "Why did revenue drop in March compared with February?". A planner picks from six predefined, read-only tools; their arguments are validated and their SQL is fixed and parameterized. The answer is written only from the values those queries return, and then checked: every number in it must exactly match a query result, or the answer is withheld. An unclear question gets a clarifying question back, and a question the data can't answer (profit, forecasts, "delete the data") is declined before any query runs.
flowchart TD
Q([Question]) --> V{"Validate<br/>1-500 characters, plain text"}
V -- invalid --> E422[["422 validation error"]]
V -- valid --> S{"Within scope?"}
S -- "profit, forecasts, commands, creative requests" --> OOS[["Out of scope: declined"]]
S -- yes --> O["Data overview<br/>months, products, regions, categories"]
O --> P{"Plan"}
P -- "unknown name, vague period, no clear intent" --> C[["Clarifying question"]]
P -- "unrelated to sales data" --> OOS
P -- "tool calls" --> T["Validated tool call<br/>strict Pydantic arguments"]
T --> SQL[("Read-only, parameterized SQL<br/>SQLite, mode=ro")]
SQL --> W["Answer template<br/>quotes the query's display strings"]
W --> G{"Grounding check<br/>every number matches a result?"}
G -- yes --> A[["Answered, with evidence and trace"]]
G -- no --> X[["Withheld: grounding_failed"]]
Every /ask response carries a trace of each tool call and a request ID that matches the server's structured JSON logs. Answered questions also include the evidence tables the numbers came from.
Five layers of protection. Each works on its own, so one layer's mistake doesn't become a wrong answer or a changed database.
The planner is measured on question sets with labelled expectations: which tools should run, with which arguments, which status the response should have, and whether the answer passes the grounding check.
evals/datasets.json and its score is no longer an unbiased estimate.evals/check_expectations.py, so the labels themselves are checked.A confident wrong answer is an answered, grounded response to a question that still failed: the worst outcome, because it looks trustworthy.
| Run | Dev | Held-out v1 | Held-out v2 | Confident wrong |
|---|---|---|---|---|
| Baseline | 21/21 | 3/10 (fresh) | not yet written | 2 (held-out v1) |
| After the first fix round | 41/41 | 10/10 (seen) | 7/10 (fresh) | 1 (held-out v2) |
| After the second fix round | 51/51 | 10/10 (seen) | 10/10 (seen) | 0 |
After two fix rounds all 71 questions pass with no confident wrong answers, but every set has now been seen. The last unbiased number is 7/10 on the fresh held-out v2 set, with one confident wrong answer. Each row links to the report committed at that point.
Before public deployment the app was audited and hardened. What is in place:
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗