From 2300ec0b3a404810b40885e1a0606d1f8f833e46 Mon Sep 17 00:00:00 2001 From: dev-belly Date: Mon, 19 Oct 2026 20:31:08 +0800 Subject: [PATCH] docs: connect tool choice with the public snapshot API --- CONTRIBUTING.md | 6 +++-- README.md | 2 +- README.zh-CN.md | 2 ++ docs/CHOOSING.md | 65 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 docs/CHOOSING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eec3281..31e871c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -86,8 +86,10 @@ correct. Explain any intentional contract change before changing saved data. ## Useful small contributions - A synthetic counterexample for a rule that is not yet covered. -- A runnable optional pandas/CSV adapter example, keeping pandas out of the - package's runtime dependencies and preserving timezone-aware values. +- A small counterexample or pandas-version compatibility improvement for the + [existing CSV adapter](examples/pandas_csv.py), with a + [minimal reproduction](#where-to-work). Keep pandas optional and preserve + timezone-aware values. - A [trial report](https://github.com/dev-belly/PITBridge/issues/new?template=trial_feedback.md) showing which invoice or CSV instruction worked, or where you got stuck. - A clearer worked example or a correction to the English/Chinese docs. diff --git a/README.md b/README.md index 5269305..672e9aa 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The notebook installs **dev-belly/PITBridge** from a full source URL pinned to o commit; no local checkout is needed. Change a decision or ingestion time to see which invoice revision remains available. -[Methodology](docs/METHODOLOGY.md) · [Data contract](docs/DATA_CONTRACT.md) · [Interview notes](docs/INTERVIEW.md) +[Choosing a tool / API reuse](docs/CHOOSING.md) · [Methodology](docs/METHODOLOGY.md) · [Data contract](docs/DATA_CONTRACT.md) · [Interview notes](docs/INTERVIEW.md) [Scale measurements](docs/SCALING.md): three isolated trials each at 100,000 and 1,000,000 observations, with late corrections, tombstones, TTL and an independent diff --git a/README.zh-CN.md b/README.zh-CN.md index fb5bd52..22e9864 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -9,6 +9,8 @@ Notebook 使用 **dev-belly/PITBridge** 的完整源码 URL,固定到一个提交版本,无需克隆。 修改决策或入库时间,即可查看当时应选择哪个发票版本。 +[何时选 PITBridge、SQL/pandas 或 Feast,以及如何复用已有 API](docs/CHOOSING.md) + 例如,一月份开票金额在二月份公开、三月份才进入银行系统,四月份又被修订。直接按照“一月份”去关联历史申请,会把后来的信息放进早期特征,导致回测过于乐观。 PITBridge 同时处理数据发生时间、公开时间、入库时间和修订版本;以 SQLite SQL 生成特征,用独立 Python 枚举结果核验,并保留每一个特征的来源记录。 diff --git a/docs/CHOOSING.md b/docs/CHOOSING.md new file mode 100644 index 0000000..b8c3b67 --- /dev/null +++ b/docs/CHOOSING.md @@ -0,0 +1,65 @@ +# Choosing a tool and reusing PITBridge + +Choose by the time contract and deployment task. These are documented use cases; +no cross-tool performance or correctness benchmark is implied. + +| Your task | A useful starting point | Check before using it | +| :--- | :--- | :--- | +| Inspect local financial observations with publication/ingestion times, revisions, missingness and source-record lineage | **PITBridge** and the [invoice notebook](../examples/decision_time.ipynb) | Upstream timestamps/version IDs must be trustworthy; use the [input contract](DATA_CONTRACT.md). For capacity, consult the [measured workloads](SCALING.md). | +| Keep historical selection in an existing database and own its business rules | **SQL** with explicit filters and ranking; see [SQLite window functions](https://www.sqlite.org/windowfunctions.html) and [this implementation](../src/pitbridge/core.py) | Define availability, revision ordering, deletion, freshness and ties, then test those rules against small expected cases. | +| Match sorted tables by the nearest prior value of a chosen key | **pandas `merge_asof`**, with `direction="backward"`; see the [official API](https://pandas.pydata.org/docs/reference/api/pandas.merge_asof.html) | Sort by the merge key; choose grouping, tolerance and exact-match policy. Define how your publication, ingestion and revision rules map to the tables before joining. | +| Manage feature definitions, historical training retrieval and online serving across infrastructure | **Feast**; start with its [local quickstart](https://docs.feast.dev/getting-started/quickstart) | Choose the source/store and its time semantics. Its [PIT guide](https://docs.feast.dev/getting-started/concepts/point-in-time-joins) also documents `filter_by_created_timestamp=True`; check the behavior for your version/store and the meaning of the created timestamp. | + +PITBridge's scope is scalar financial observations and explicit rolling aggregates. +Streaming ingestion, access control and label generation belong to the surrounding +system. The table makes no claim about features absent from other tools. + +## Reuse the existing public API + +These signatures describe pre-1.0 source `6d6524b`, checked on 2026-10-19. +Pin the tag or source commit used by your example and retain its inputs and report +bundle. The documented input rules and verifiers describe that snapshot; they do +not establish cross-version API or bundle compatibility. Before adopting another +snapshot, review its contract changes and rerun the existing invoice and replay +checks. Public imports are listed in [the package](../src/pitbridge/__init__.py) +and implemented in [core.py](../src/pitbridge/core.py). + +```text +Observation(record_id: str, entity_id: str, source: str, feature: str, + event_at: str, published_at: str, ingested_at: str, + revision: int, value: float | None, deleted: bool = False) +Decision(decision_id: str, entity_id: str, decision_at: str) +FeatureSpec(source: str, feature: str, max_age_days: float | None = None) +build_snapshot(observations, decisions, specs) -> list[Snapshot] +reference_snapshot(observations, decisions, specs) -> list[Snapshot] +``` + +Pass iterables of `Observation`, `Decision` and `FeatureSpec` respectively. +A generator is exhausted after one call; use lists when comparing SQL selection +with the independent Python reference. The [runnable invoice example](../examples/decision_time.py) +constructs those lists and checks both the full rows and three expected selections. + +The return is a list of `Snapshot` dataclasses, one per decision/spec pair, +ordered by `decision_id`, `source`, `feature`. Each row contains the decision, +value/status and selected source record's ID, revision and timestamps. +Missing selections keep `value=None` and a reason: `no_history`, `not_available`, +`deleted` or `stale`; they are not filled with zero. Use `dataclasses.asdict(row)` +for a dictionary. Feature values follow the finite binary64 contract; integer +conversion can round above `2^53`. + +Invalid timestamps, revisions, freshness limits, duplicate identities or missing +specs raise `ValueError` through the constructors/validation. Wrong Python call +shapes can still raise `TypeError`. Python calls raise exceptions; the CLI reports +handled contract errors on stderr with exit code 2. Full field/error rules remain +in the [input contract](DATA_CONTRACT.md); [the method](METHODOLOGY.md) explains +selection, and [rolling features](ROLLING.md) have their own contract and entry points. + +## Continue with your input + +Use the [optional CSV example](../examples/README.md#optional-pandascsv-input) +for three table inputs, or the `build --inputs` JSON route in the input contract. +Pandas is optional. For a mismatch, keep a minimal synthetic input, the expected +record and the actual status, then [share trial feedback](https://github.com/dev-belly/PITBridge/issues/new?template=trial_feedback.md). + +External references above were checked on 2026-10-19. They describe those tools' +contracts, not an implemented adapter or compatibility promise from PITBridge.