基本コンセプト¶
thinkingface の土台にあるモデルはごく小さなものです。すべてが git リポジトリであり、すべてのリポ ジトリはネームスペースに属し、すべてのバイト列は内容から導かれたキーでオブジェクトストレージに置 かれます。この 3 つが腑に落ちれば、あとのページはすべて詳細にすぎません。このページではその考え方 を説明します。実際のコマンドは各ガイドにあります。
リポジトリ¶
リポジトリの実体は、bare な git リポジトリと、サーバーがそれについて保持しているインデックス (ファイル一覧、カード、Parquet のスキーマ、サイズ)だけです。それ以外にはありません。別立ての 「アーティファクトレジストリ」層もなければ、データのコピーを抱えたデータベースの行もありません。
リポジトリには 2 種類あります。
| 種類 | 入るもの | アドレス |
|---|---|---|
dataset |
学習・評価用のデータ。多くは Parquet、CSV、JSONL | /datasets/{ns}/{name} |
model |
チェックポイントとその設定ファイル。safetensors、PyTorch、GGUF、ONNX | /models/{ns}/{name} |
種類によって、クライアントからのアドレスの指定方法と、Web UI が提供する機能が変わります(データ セットなら Parquet のテーブル表示、モデルならチェックポイントのメタデータパネル)。ただし仕組みそ のものは変わりません。どちらも git であり、どちらも Git LFS を使い、push と pull の方法も同じで す。実験のログもデータセットリポジトリです。下の 実験 を参照して ください。
新しいリポジトリには必ず 2 つのファイルが用意されます。デフォルトの LFS ルールを持つ
.gitattributes と、YAML フロントマターの付いた README.md です。これにより、最初のアップロード
から LFS の振り分けが機能します。ルールは種類によって異なり、データセットでは音声・画像・動画の
ファイルも追跡対象になりますが、モデルリポジトリではそれらを通常の blob のままにします。
ファイルが Git LFS に振り分けられる仕組み
を参照してください。
書き込み経路はただ 1 つ
ブラウザでの Markdown ファイルの編集も、Python からの upload_file も、tf up も、
git push も、最終的にはすべてブランチ上の git コミットになります。使ったツールによって履歴が
分かれることはなく、git log は常にリポジトリのすべてを語ります。
リポジトリごとの公開設定はありません。サーバーに到達できる人は誰でもすべてのリポジトリを読めま す。アクセストークンとネームスペースのロールが決めるのは、誰が書き込めるかです。ネットワーク境 界はそれを前提に設計してください。デプロイ を参照してください。
ネームスペース¶
リポジトリの名前は必ず {namespace}/{name} の形をとります。ネームスペースは所有者を表す部分で、
ユーザーと Organization は 1 つの名前空間を共有します。つまり acme というユーザーが存在すれば、
acme という名前の Organization は作れませんし、その逆も同じです。名前を取得できるのは、先に確保
した所有者ただ 1 人です。
ネームスペース名は作成時に決まり、あとから変えられません。ユーザー名も Organization ID も改名でき ないのは、その名前が配下すべてのアドレスそのものだからです。リポジトリを別の場所へ移したい場合 は、所有者の名前を変えるのではなくリポジトリを移譲してください。
名前は大文字・小文字を区別せずに一意で、どちらの種類の所有者でも /{ns} が唯一のページになりま
す。プロフィールに加えて Models・Datasets・Experiments のタブがあり、Organization では Members
タブも表示されます。異なる表記でアクセスすると、正規の表記へリダイレクトされます。
Organization にはさらにロールが加わります。admin、write、read の 3 つで、詳細は
Organization にあります。
リビジョン¶
リビジョンとは、ブランチ名、タグ、またはコミット SHA のことです。デフォルトブランチは main で
す。
リビジョンを指定できる場所ではどれも、この 3 通りの書き方がすべて使えます。ファイルツリーの URL
(/datasets/admin/imdb-reviews/tree/main/data)、huggingface_hub の revision= 引数、tf CLI
の --rev などです。SHA を指定して固定すれば、あとから動くことのないスナップショットが得られま
す。
どのブランチやタグに push しても、そのリビジョンのファイルがインデックスされ、実体がストレージに 公開されます。デフォルトブランチだけから読まれるものもいくつかあります。リポジトリのカード、一覧 に表示される説明とタグ、そして宣言された系譜 (lineage) です。これによって、フィーチャーブランチも 閲覧できる状態を保ちながら、デフォルトブランチがリポジトリの表の顔になります。
ファイルの保存方法¶
ここはホスティング型の Hub と最も違うところであり、自分のバケットからデータを直接読めるのはこの仕 組みのおかげなので、理解しておく価値があります。
ファイルは 3 つの層で保持されます。
1. git リポジトリ。 コミット、ref、履歴に加えて、小さなテキストファイルの中身が通常の git blob
として入ります。git clone で手に入るのはこの部分です。
2. Git LFS。 大きなファイルは git の履歴にはまったく保存されません。git が持つのは小さなポイン
タファイルだけで、実体は内容の SHA-256 をキーとして lfs/{oid[0:2]}/{oid[2:4]}/{oid} に置かれます。
3. 公開された blob。 サーバーは push のたびに、LFS を経由しないファイルの中身も
blobs/{sha[0:2]}/{sha[2:4]}/{sha} に公開します。キーは git の blob SHA です。これにより、リビジョンに含まれるものが大
きなファイルも小さなファイルもすべて、LFS 側だけでなくバケットから到達できるようになります。
あるファイルが LFS を通るかどうかを決めるのは .gitattributes で、これは Hub とまったく同じです。
サーバーが書き込むデフォルトは、よくある対象を一通り押さえています。*.parquet、*.safetensors、
*.bin、*.gguf、*.ckpt、*.pt、*.onnx、*.zip、*.tar.* などです。どのルールにも一致しな
いファイルが API 経由(Python、tf CLI、ブラウザ)でアップロードされた場合は、10 MiB 以上であれば
やはり LFS に振り分けられます。素の git push の場合は、ローカルの git-lfs が
.gitattributes を自分で適用するため、新しく大きな形式をコミットするならまず track する必要があ
ります。
バケットにフォルダがない理由¶
どちらのストレージ層も 内容アドレス方式 です。キーはバイト列から計算され、ネームスペースにも、 リポジトリ名にも、ブランチにも依存しません。
gs://{bucket}/
├── lfs/{oid[0:2]}/{oid[2:4]}/{oid} LFS の実体。内容の SHA-256 がキー
├── blobs/{sha[0:2]}/{sha[2:4]}/{sha} LFS 以外のファイルの実体。git blob SHA がキー
└── ... サーバー内部用のキー(git の履歴、アップロードの作業領域)
バケットの中を見ても、あるオブジェクトがどのリポジトリのものかは分かりません。これは意図した設計 で、次の 3 つが得られます。
- 同じ内容は 1 度しか保存されない — どのリポジトリ、どのブランチに含まれていても同じです。
- リポジトリの名前変更や移譲でバイト列は動かない — キーはもともと名前に触れていないからです。
- オブジェクトは不変 — キーは一度書かれたら上書きされないので、以前読めたものは今も同じバイト 列として読めます。
その代わり、cp -r できる人間に読める形のフォルダは存在しません。人間に読めるレイアウトは、消費
する側で再構成します。リポジトリページの GCS access ダイアログ(とその背後の API)が、リビジョ
ンに含まれる内容アドレス方式のキーをすべて元のパスへ対応づける gcloud storage cp スクリプトを生
成します。
#!/bin/sh
set -eu
DEST="${DEST:-./imdb-ja}"
cp_one 'gs://my-bucket/blobs/3f/2a/3f2a9c…' "$DEST"/'README.md'
cp_one 'gs://my-bucket/lfs/9b/1d/9b1de4…' "$DEST"/'data/train-00000-of-00002.parquet'
DEST にローカルのディレクトリを指定すればダウンロードになり、gs:// のプレフィックスを指定すれ
ばバケット間コピーになります。Parquet を含むリビジョンであれば、同じレスポンスに同じキーに対する
DuckDB のクエリも含まれ、それらのキーはそのまま BigQuery の外部テーブルに渡せます。詳しくは
ファイルのダウンロード で順を追って説明しています。
リポジトリカード¶
カードとは README.md の先頭にある YAML フロントマターのことです。Hugging Face Hub と同じ規約なの
で、Hub 向けに書いたカードはそのまま通用します。
---
license: apache-2.0
tags:
- sentiment
- japanese
task_categories:
- text-classification
---
カードは飾りではありません。デフォルトブランチへの push のたびにサーバーが読み直し、次のものを動 かします。
- 検索とフィルタ —
tags、license、そしてタスク(モデルカードならpipeline_tag、データ セットカードならtask_categories)が、Models と Datasets の一覧のファセットになります。 - 一覧や検索結果に出る説明 — カードに
descriptionフィールドがあればそれを、なければ README 本文の最初のまともな段落を使います。 - データセットビューアへのヒント —
dataset_info.featuresは、どの列が単なるスカラーではなく 画像・音声・クラスラベルなのかをビューアに伝えます。 - 系譜 (lineage) —
lineage:ブロック(あるいは Hub 自身のdatasets:、base_model:、model-index:フィールド)は、モデルがどのデータセットで学習されたか、どのチェックポイントから 始まったか、どの run が生成したかを記録します。これにより UI は来歴を双方向にたどれます。 - 実験の目印 —
trackioタグ、またはリポジトリ内のmetrics.parquetがあると、そのデータ セットリポジトリが Experiments に現れます。
カードは git 上のファイルの先頭部分にすぎないので、編集方法も他のファイルと同じです。ブラウザ上で も、コミットでも構いません。フロントマターのパースに失敗してもアップロードが失敗することはなく、 README はそのまま表示され、カードが空になるだけです。
アクセストークン¶
アクセストークンは Settings → Access tokens で作成して一度だけコピーする tf_... という文字列
です。値が再表示されることはありません。トークンごとに read または write のスコープを持ち、1
人のユーザーに属します。
必要な資格情報はこのトークン 1 つだけです。クライアントが提示しうるあらゆる場面で、thinkingface は 同じ値を受け付けます。
| 使う場面 | 渡し方 |
|---|---|
| HTTP 経由の git | HTTP Basic 認証のパスワード(ユーザー名は任意) |
| REST API | Authorization: Bearer tf_... |
huggingface_hub / datasets |
HF_TOKEN |
tf CLI |
tf login で保存、または環境変数 THINKINGFACE_API_KEY |
| trackio 互換クライアント | THINKINGFACE_TOKEN |
Web UI へのサインインはこれとは別で、ブラウザが受け取るのはトークンではなくセッションクッキーで す。また SSH 経由の git では、トークンではなく登録した公開鍵を使います。トークンで実際にできるこ とは、そのスコープと、書き込み先ネームスペースにおける自分の権限との積になります。詳細は 認証 にあります。
実験: プロジェクトと run¶
実験のトラッキングは独立したサブシステムではありません。実験はごく普通のデータセットリポジトリ
(デフォルトでは {your-namespace}/trackio-metrics)の中にあり、真実の源はその中の Parquet ファイ
ルです。
データを整理する単位は 2 つです。
- run は学習スクリプトの 1 回の実行です。名前、開始時の config、状態 (
running、finished、failed)、そしてステップごとに記録されたメトリクスの系列を持ちます。 - プロジェクト は、比較したい run をまとめたものです。ディスク上ではプロジェクトは
metrics.parquetを含むディレクトリなので、mnist/metrics.parquetはプロジェクトmnistを意 味します。
メトリクスがそのファイルに届く経路は 2 つあります。1 つは、自分のインスタンスに向けた trackio の
スクリプトが定期的に Parquet を同期し、サーバーが見つけた内容をインデックスする経路です。もう 1
つは、同梱の shim が log() の呼び出しごとに ingest エンドポイントへ送り、そこでリアルタイムのグ
ラフ用にポイントをバッファしつつ、定期的にまったく同じ Parquet ファイルへコミットする経路です。い
ずれの場合も、ハードウェアのテレメトリは system/ プレフィックスの下に置かれるため、スクリプトが
出力するメトリクスと衝突することはありません。
そこから得られる結果こそが有用な部分です。実験の履歴は git でバージョン管理され、リポジトリを
clone すれば一緒に付いてきて、他のデータセットと同じように DuckDB や gcloud storage から読めま
す。Web UI のグラフはそのファイルに対するビューであって、UI からしか読めないデータベースではあり
ません。実験のトラッキング を参照してください。
次に読むもの¶
- クイックスタート — インスタンスを立ち上げてデータセットを入れる。
- ファイルのアップロード と ファイルのダウンロード — ここでの考え方をコマンドに落としたもの。
- 互換性 — Hugging Face Hub API のうち thinkingface が実装している部 分と、していない部分。