コンテンツにスキップ

基本コンセプト

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 からしか読めないデータベースではあり ません。実験のトラッキング を参照してください。

次に読むもの