Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check out the spec for record validation
uses: actions/checkout@v4
with:
repository: apache/sourcelume-spec
path: sourcelume-spec
- uses: actions/setup-python@v5
with:
python-version: '3.12'
Expand All @@ -38,12 +43,7 @@ jobs:
run: uv run python src/train.py --epochs 1 --chars 20000
- name: Validate records against the spec
env:
# TODO: pin to the spec release once PR #10 (TrainingProvenanceRecord)
# is merged and published; until then CI validates offline only.
SOURCELUME_SPEC: ''
run: |
if [ -n "$SOURCELUME_SPEC" ]; then
uv run python scripts/validate-records.py
else
echo "record validation skipped: no spec checkout available in CI yet"
fi
# Unpinned main for now: the spec has no published release yet, and
# validating against the current spec is the point of this check.
SOURCELUME_SPEC: ${{ github.workspace }}/sourcelume-spec
run: uv run python scripts/validate-records.py
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ make demo
|---|---|
| Dataset record: spec + registry validation | ✅ works today |
| Dataset record: publish to Atlas | ✅ works with the Atlas stack up |
| Training record: spec validation | ✅ works — **requires a spec checkout at the `model-usage-record` (PR #10) state or later**; set `SOURCELUME_SPEC` accordingly |
| Training record: spec validation | ✅ works — validate against a `sourcelume-spec` checkout at `main` (the `TrainingProvenanceRecord` type was merged with PR #10); set `SOURCELUME_SPEC` accordingly |
| Training record: plugin validate/publish | ❌ **expected to fail** — the Python plugin itself only models `ProvenanceRecord` (its Pydantic model rejects the record client-side). The plugin needs the same type-dispatch the spec validator has (tooling follow-up; see `make registry-validate`). |
| Training record: registry validate/publish | ❌ **expected to fail** until the registry learns the `TrainingProvenanceRecord` type (registry follow-up to PR #10). Direct `curl -X POST .../records/validate` shows the registry's own rejection (HTTP 422, `must be the constant value 'ProvenanceRecord'`) — the demo's exhibit for that follow-up. |
| Training record: registry validate/publish | ❌ **expected to fail** until the registry learns the `TrainingProvenanceRecord` type (registry follow-up to PR #10, currently in review as sourcelume-registry#15). Direct `curl -X POST .../records/validate` shows the registry's own rejection (HTTP 422, `must be the constant value 'ProvenanceRecord'`) — the demo's exhibit for that follow-up. |

This demo **builds on PR #10 as given**: the training record type, the
type-dispatching validator and the record examples come from that branch.
Expand Down
2 changes: 1 addition & 1 deletion data/provenance-record.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"created": "2026-10-15T00:00:00Z",
"added": "2026-10-15T00:00:00Z",
"contentCreated": "1865-11-26T00:00:00Z",
"origin": "Plain text of Lewis Carroll's 'Alice's Adventures in Wonderland' (first published 26 November 1865), fetched verbatim from Project Gutenberg (ebook #11, https://www.gutenberg.org/ebooks/11) in October 2026 and bundled unchanged at data/corpus/alice-in-wonderland-1865.txt as demo training data. The work is in the public domain worldwide (published 1865, author died 1898); the Project Gutenberg framing text included in the file is distributed under the Project Gutenberg License (www.gutenberg.org). This record is authored and published by the Sourcelume training demo itself: the demo bootstraps its own registry preconditions instead of assuming records it did not create. Form: verbatim.",
"origin": "Plain text of Lewis Carroll's 'Alice's Adventures in Wonderland' (first published 26 November 1865), fetched verbatim from Project Gutenberg (ebook #11, https://www.gutenberg.org/ebooks/11) in October 2026 and bundled unchanged at data/corpus/alice-in-wonderland-1865.txt as demo training data. The work is in the public domain worldwide (published 1865, author died 1898); the Project Gutenberg framing text included in the file is distributed under the Project Gutenberg License (www.gutenberg.org). This record is authored and published by the Sourcelume sample itself: the sample bootstraps its own registry preconditions instead of assuming records it did not create. Form: verbatim.",
"custodyChain": [
{
"agent": "https://www.gutenberg.org/",
Expand Down
13 changes: 10 additions & 3 deletions scripts/validate-records.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
SHACL), reusing the spec's own validator.

SOURCELUME_SPEC must point at a sourcelume-spec checkout that includes the
TrainingProvenanceRecord type — i.e. the model-usage-record branch (PR #10)
until it is merged into main. Defaults to the local worktree of that branch.
TrainingProvenanceRecord type (spec main since PR #10). There is no default:
point it at your local checkout, e.g. SOURCELUME_SPEC=../sourcelume-spec.
"""

import json
Expand All @@ -28,7 +28,14 @@
from pathlib import Path

BASE = Path(__file__).resolve().parent.parent
SPEC = Path(os.environ.get("SOURCELUME_SPEC", "/private/tmp/wt-model")).resolve()
spec_env = os.environ.get("SOURCELUME_SPEC", "")
if not spec_env:
print(
"SOURCELUME_SPEC must point at a sourcelume-spec checkout (e.g. ../sourcelume-spec)",
file=sys.stderr,
)
sys.exit(2)
SPEC = Path(spec_env).resolve()
if not (SPEC / "tools" / "validate.py").is_file():
print(f"SOURCELUME_SPEC is not a spec checkout: {SPEC}", file=sys.stderr)
sys.exit(2)
Expand Down
6 changes: 3 additions & 3 deletions src/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ def main() -> int:
"id": MODEL_ID,
"type": "TrainingProvenanceRecord",
"identifier": "tiny-lm",
"name": "Tiny char-LM (Apache Sourcelume training demo)",
"name": "Tiny char-LM (Apache Sourcelume sample)",
"version": "v1",
"creator": [
{
"type": "schema:Organization",
"name": "Apache Sourcelume training demo",
"name": "Apache Sourcelume sample",
"role": "originator"
}
],
Expand All @@ -167,7 +167,7 @@ def main() -> int:
f"{tokens_per_epoch}-character slice of the referenced corpus "
f"({len(vocab)}-character vocabulary, {params} parameters, "
f"final loss {history[-1]:.4f}, see model/training-run.json). "
f"The referenced dataset record is published by this demo itself "
f"The referenced dataset record is published by this sample itself "
f"(data/provenance-record.json). Unsigned producer claim — see README."
),
}
Expand Down
Loading