레지스트리
레지스트리는 가장 우수한 아티팩트 버전의 공유 카탈로그입니다. 프로젝트는 실험에서 생성된 아티팩트를 나열하고, 레지스트리는 여러 프로젝트에 걸쳐 선택된 아티팩트를 나열합니다.
레지스트리에는 컬렉션이 포함됩니다. 각 컬렉션은 하나의 자산, 즉 시간이 지남에 따라 재학습하는 모델이나 골든 평가 세트 등을 나타내며, 게시하기로 선택한 해당 자산의 버전들을 보유합니다. 아티팩트 버전을 컬렉션에 연결합니다. 링크는 소스 버전을 가리키는 포인터이며, 아무것도 복사되지 않습니다. 그런 다음 staging 및 production과 같은 별칭을 이동시켜 연결된 버전을 라이프사이클 단계별로 승격합니다.
예를 들어, models이라는 이름의 레지스트리에는 배포 가능한 모델마다 하나의 컬렉션을, datasets이라는 이름의 레지스트리에는 벤치마크마다 하나의 컬렉션을 포함할 수 있습니다. 레지스트리와 컬렉션에 자산을 어떻게 나누어 둘지는 사용자의 판단에 맡깁니다.

컬렉션은 소스 아티팩트의 버전 번호와 독립적인 자체 버전 라인(v0, v1, …)을 가지며, 각 버전은 서로 다른 프로젝트의 서로 다른 소스 아티팩트를 가리킬 수 있습니다. 별칭은 컬렉션당 정확히 하나의 버전을 지정합니다.
레지스트리는 로컬이거나 — registry-models이라는 이름의 프로젝트로 다른 Trackio 데이터 옆에 저장되며(registry- 접두사는 예약되어 있음) — Hugging Face 버킷에 기반할 수 있습니다. 후자의 경우 다른 머신과 Space에 로깅하는 런(run)에서 접근할 수 있게 됩니다. 원격 레지스트리를 참조하세요.
레지스트리 생성
Api.create_registry()로 레지스트리를 생성합니다:
import trackio
registry = trackio.Api().create_registry("models", description="Our deployable models")선택 사항인 description은 레지스트리에 저장되며 registry.description으로 읽을 수 있습니다.
Registries는 암시적으로 생성되지 않습니다. 존재하지 않는 registry에 링크하면 오류가 발생합니다.
Api.registry()를 사용하여 기존 레지스트리를 가져옵니다. 레지스트리가 존재하지 않으면 예외가 발생합니다.
컬렉션 만들기
collection은 레지스트리 내에서 연결된 아티팩트 버전들의 집합으로, 단일 버전 히스토리를 가집니다. 버전은 서로 다른 소스 아티팩트에서 유래할 수 있습니다. resnet 기반 모델과 unet 기반 모델이 동일한 배포 가능한 제품의 후보라면, 이들을 하나의 collection에 연결하면 해당 제품의 연속된 버전이 됩니다. 서로 다른 제품이라면 각각에 별도의 collection을 지정하세요.
보통 컬렉션을 수동으로 생성하지 않습니다. 존재하지 않는 컬렉션에 링크를 연결하면 자동으로 생성됩니다. 설명을 미리 설정하려면 컬렉션을 명시적으로 생성하세요:
registry.create_collection("my-model", "model", description="The model we deploy")컬렉션 유형
각 컬렉션은 생성 시점에 고정되는 단일 type의 아티팩트를 허용합니다. 이 type은 아티팩트 자체에서 가져오며, trackio.Artifact 또는 trackio.log_artifact에 전달하는 type 필드입니다. 따라서 첫 번째 링크로 생성된 컬렉션은 해당 아티팩트의 type을 채택합니다.
예를 들어, "model" 아티팩트를 허용하는 컬렉션에 "dataset" 아티팩트를 연결하면 Trackio가 오류를 발생시킵니다.
레지스트리 자체는 모든 유형을 허용합니다. 모델 컬렉션과 데이터셋 컬렉션이 동일한 레지스트리에 나란히 존재할 수 있습니다.
아티팩트 버전을 컬렉션에 연결
Run.link_artifact()로 아티팩트 버전을 게시합니다:
import trackio
trackio.Api().create_registry("models")
run = trackio.init(project="my-experiments")
artifact = trackio.log_artifact("model.pt", name="resnet", type="model")
run.link_artifact(artifact, "registry-models/my-model", aliases=["staging"])대상 경로는 "registry-<registry>/<collection>"입니다. 첫 번째 세그먼트는 접두사를 포함한 레지스트리의 전체 이름입니다.
link_artifact는 아티팩트 객체 자체를 인수로 받으므로, 사용자가 보유한 버전이 바로 게시되는 버전입니다:
| 사용 사례 | How | 기록되는 항목 |
|---|---|---|
| 방금 기록한 아티팩트를 연결합니다 | run.link_artifact(artifact, ...) | 런에 의해 게시된 링크 |
| 특정 기존 버전 연결 | run.link_artifact(run.use_artifact("resnet:v3"), ...) | 실행은 resnet:v3를 소비한 다음, 실행이 게시한 링크를 소비합니다 |
| 로그되지 않은 아티팩트를 연결 | run.link_artifact(draft_artifact, ...) | 아티팩트는 먼저 실행의 프로젝트에 기록된 후 연결됩니다 |
실행(run)이 스코프에 없는 경우 유용한 Artifact.link()를 사용하여 아티팩트 자체에서 링크를 만들 수도 있습니다:
artifact.link("registry-models/my-model", aliases=["staging"])Artifact.link는 이미 기록되었거나 가져온 아티팩트를 요구합니다. 초안을 대신 기록하지 않으며, 링크에는 게시 실행이 기록되지 않습니다.
링크된 아티팩트
link_artifact는 아티팩트를 레지스트리 위치에 반환합니다. name은 컬렉션, project는 레지스트리이며, version과 aliases는 해당 컬렉션의 것입니다. 콘텐츠인 manifest, manifest_digest, size, metadata는 소스 버전의 것이며, source_project, source_name, source_version, source_qualified_name 속성은 해당 소스 버전으로 다시 가리킵니다:
linked = run.link_artifact(artifact, "registry-models/my-model")
linked.qualified_name # "registry-models/my-model:v0"
linked.source_qualified_name # "my-experiments/resnet:v0"링크된 아티팩트를 링크하면 경고와 함께 해당 소스 버전이 직접 링크되므로, 링크가 체인되지 않습니다.
Consumer는 use_artifact를 통해 레지스트리 위치를 직접 해결하며, 해당 산출물을 생성한 프로젝트나 산출물을 알지 못합니다:
model = run.use_artifact("registry-models/my-model:production")
model.download() # fetches the source version's files컬렉션 이후의 스펙은 컬렉션 버전("v1"), 별칭("production"), 또는 최신 링크된 버전을 나타내는 빈 값을 허용합니다. 링크된 아티팩트를 다운로드하면 해당 아티팩트가 가리키는 소스 버전의 바이트를 가져옵니다.
Registry 위치는 현재 로컬 실행에서만, 그리고 소스 아티팩트가 로컬에 사용 가능한 경우에만 해석될 수 있습니다. Space, 버킷, 또는 셀프호스트드 서버에 저장된 소스는 버킷 기반 registry에 게시할 수 있지만, 후속 프로세스에서 해당 링크를 해석하는 기능은 아직 지원되지 않습니다. link_artifact가 직접 반환하는 링크된 아티팩트는 Space 또는 셀프호스트드 소스를 유지하며, 해당 소스에서 다운로드할 수 있습니다.
컬렉션 버전
각 새 링크는 컬렉션에서 v0부터 시작하는 다음 버전 번호를 부여받습니다. 링크된 버전은 일반적으로 서로 다른 아티팩트와 프로젝트에서 가져오기 때문에, 컬렉션 버전은 소스 아티팩트 자체의 버전 번호와 독립적입니다.
컬렉션에 이미 존재하는 소스 버전을 연결하면 새 버전이 생성되지 않습니다. 기존 버전이 반환되며, 전달한 aliases는 여전히 이동합니다. 버전 번호는 재사용되지 않으므로, 게시된 my-model:v3의 의미가 조용히 변경될 수 없습니다.
별칭이 있는 버전 승격
에이리어스는 컬렉션당 하나의 버전을 참조합니다. 다른 버전이 이미 보유하고 있는 에이리어스를 할당하면 해당 에이리어스가 이동하며, 이 이동이 프로모션입니다. my-model:production을 해석하는 사용자는 에이리어스를 따르므로, 에이리어스가 이동해도 다운스트림에 변경 사항이 발생하지 않습니다.
대부분의 프로모션은 게시 시점에 수행됩니다. 새 버전을 연결하고 같은 호출에서 별명을 지정합니다.
run.link_artifact(artifact, "registry-models/my-model", aliases=["staging"])컬렉션에 이미 포함된 버전을 승격하려면, 해당 별칭으로 다시 링크하세요. 다시 링크하면 새로운 것이 생성되지 않으며, 기존 컬렉션 버전을 다시 가져오고 전달한 별칭이 해당 버전에 이동합니다. 컬렉션의 링크에서 해당 버전의 소스를 찾아 가져온 후 다시 링크하세요:
registry.collection("my-model").links
# [..., {"collection_version": 1, "source_project": "my-experiments",
# "source_artifact": "resnet", "source_version": 3, ...}]
candidate = run.use_artifact("resnet:v3")
run.link_artifact(candidate, "registry-models/my-model", aliases=["production"])또한 레지스트리에서 직접 가져올 수도 있습니다:
candidate = run.use_artifact("registry-models/my-model:v1")
run.link_artifact(candidate, "registry-models/my-model", aliases=["production"])alias를 이전 버전으로 되돌리는 방법도 동일합니다.
Trackio는 latest 별칭을 자동으로 관리합니다. 항상 최신 연결된 버전을 가리킵니다.
버전 연결 해제
링크된 아티팩트에서 Artifact.unlink()를 호출하여 링크를 제거합니다:
linked = run.link_artifact(artifact, "registry-models/my-model")
linked.unlink()소스 아티팩트와 그 파일은 그대로 유지되며, 컬렉션 소속만 제거됩니다. 링크에 있는 모든 별칭도 함께 제거되고, 컬렉션 버전 번호는 다시 사용되지 않으므로 my-model:v0는 나중에 다른 의미를 갖지 않습니다. 제거한 버전이 latest를 가지고 있었다면, 해당 별칭은 남은 버전 중 가장 높은 버전으로 이동하여 latest가 컬렉션의 최신 버전을 계속 가리키도록 합니다.
원격 레지스트리
로컬 레지스트리는 작성한 머신에만 존재합니다. 여러 머신 간에 카탈로그를 공유하거나, Space 또는 자체 호스팅 서버에 로깅되는 런에서 게시하려면 bucket_id를 전달하여 Hugging Face 버킷으로 레지스트리를 백업하세요:
registry = trackio.Api().create_registry(
"models", description="Our deployable models", bucket_id="my-org/models-registry"
)버킷이 존재하지 않으면(비공개로) 생성됩니다. TRACKIO_REGISTRY_BUCKET_ID를 설정하면 프로세스 내 모든 레지스트리 호출에 대해 기본값으로 사용되므로, 스크립트에서 매번 전달할 필요가 없습니다.
가져오기, 검사, 게시 모두 동일한 인수를 사용합니다:
registry = trackio.Api().registry("models", bucket_id="my-org/models-registry")
run = trackio.init(project="my-experiments", space_id="my-org/my-dashboard")
artifact = trackio.log_artifact("model.pt", name="resnet", type="model")
run.link_artifact(
artifact,
"registry-models/my-model",
aliases=["staging"],
bucket_id="my-org/models-registry",
)버킷에 접근 권한이 있는 모든 사용자는 각자의 Hugging Face 자격 증명을 사용하여 버킷에 직접 작성합니다. 경로에 서버가 없으므로 레지스트리는 특정 Space에 종속되지 않으며 모든 Space보다 오래 유지됩니다. Artifact.link와 Artifact.unlink는 bucket_id를 동일한 방식으로 받아들이며, 링크된 아티팩트는 출처가 된 버킷을 기억하므로 linked.unlink()는 올바른 레지스트리로 되돌아갑니다.
레지스트리의 자체 버킷은 의도적으로 실행의 버킷이 아닙니다. 레지스트리는 프로젝트 간 카탈로그이므로, 메트릭이 어디에 저장되든 상관없이 명시적으로 이름을 지정합니다.
버킷에 저장된 내용
각 mutation은 하나의 불변 객체로 저장되며, state는 해당 로그의 fold입니다:
trackio/registries/<registry>/registry.json name, description, created_at trackio/registries/<registry>/events/<event_uid>.json one object per mutation
원격 레지스트리를 읽으면 해당 이벤트가 registry-cache/ 아래에 있는 로컬 투영 데이터베이스로 병합됩니다. 이 데이터베이스는 캐시이므로 삭제하면 다음 읽기 시 버킷에서 다시 구축됩니다.
동시성
Object storage에는 compare-and-swap이 없으므로, 작성자는 잠금을 사용할 수 없습니다. 다른 사람이 작성하지 않는 객체를 추가하는 것만 가능합니다. 이는 모두 의도된 설계로, 두 가지 결과가 있습니다:
- 버전 번호는 작성자가 아닌 폴드(fold)에 의해 할당됩니다. 동시 링크는 이벤트 ID(타임스탬프, 작성자, 시퀀스 순)로 정렬되므로 각 링크에는 고유하고 재사용되지 않는 번호가 부여됩니다. 한 작성자가 보고한 버전은 동시 작성자의 이벤트가 폴드(fold)에 반영되면 변경될 수 있습니다.
- 같은 순서에서 Alias 이동은 마지막 작성자가 우선하며,
latest도 포함됩니다. 두 사람이 동시에production으로 승격하는 경우 이벤트 순서로 결정됩니다.
링크는 순수한 포인터로 유지됩니다: 레지스트리 버킷에 아무것도 복사되지 않으므로, 소스 프로젝트의 스토리지가 계속 접근 가능해야 합니다. 소스가 원격인 링크의 해석은 아직 지원되지 않습니다. 버전의 바이트를 레지스트리에 복사(고정)하는 작업은 후속 작업으로 계획되어 있습니다.
레지스트리 검사
Registry 핸들은 컬렉션과 해당 컬렉션에 연결된 버전을 나열합니다. 읽기 연산은 Collection 스냅샷을 반환합니다:
registry = trackio.Api().registry("models")
registry.collections()
# [Collection(name="my-model", type="model", num_links=2, latest_version=1, ...)]
registry.collection("my-model").links
# [{"collection_version": 1, "source_project": "my-experiments",
# "source_artifact": "resnet", "source_version": 4,
# "aliases": ["latest", "production"], ...}]각 링크는 버전의 출처(source_project, source_artifact, source_version), 로컬이 아닌 경우의 소스 저장 좌표(source_space_id, source_bucket_id, 또는 source_server_base_url), 그리고 현재 해당 링크에 설정된 별명을 기록합니다. 링크는 해당 소스 버전을 가리키는 순수한 포인터입니다.
명령줄 인터페이스
trackio registry 명령어는 Python 스크립트 없이 동일한 게시 및 검사 워크플로를 지원합니다:
trackio registry create models --description "Models we deploy"
trackio registry create-collection models/churn-model --type model
trackio registry link models/churn-model my-experiments/resnet:v3 --alias staging
trackio registry promote models/churn-model production v0
trackio registry list models
trackio registry show models/churn-model
trackio registry events models
trackio registry unlink models/churn-model v0link은 로컬 Trackio 데이터에서 소스를 해석합니다. 명시적인 버전 또는 별명을 허용하며, 접미사가 생략된 경우 기본값은 latest입니다. 레지스트리는 여전히 버킷 기반일 수 있습니다. 모든 명령에 --bucket-id my-org/models-registry를 전달하세요. 스크립트에 적합한 구조화된 출력을 위해 --json을 사용하세요.
CLI는 models/churn-model과 Python API의 전체 registry-models/churn-model 대상 구문을 모두 지원합니다. 전체 명령어 참조는 CLI Commands를 확인하세요.
대시보드에서 레지스트리 탐색
레지스트리 설명, 컬렉션, 연결된 버전, 별칭, 소스 위치, 감사 이벤트를 탐색하기 위해 독립형 읽기 전용 레지스트리 대시보드를 시작합니다:
trackio show registry
또는 trackio.show(dashboard="registry")를 사용하여 Python에서 실행할 수 있습니다. 레지스트리 대시보드는 프로젝트 대시보드와 별도로 제공되며, 이는 레지스트리가 여러 프로젝트에 걸쳐 산출물을 카탈로그화하기 때문입니다.
Local 소스는 대시보드 머신에 저장된 레지스트리를 표시합니다. 접근 가능한 Hugging Face 버킷을 선택하려면 HF Bucket을 선택하거나, my-org/models-registry와 같은 버킷 ID를 입력하세요. Space에서 개인 버킷에 액세스할 때는 로그인한 사용자의 Hugging Face 자격 증명이 사용됩니다. 셀프 호스팅된 대시보드는 쓰기 액세스 URL을 연 사용자의 경우에만 저장된 Hugging Face 토큰을 사용합니다. 공개 읽기 전용 대시보드는 서버 소유의 토큰을 통해 버킷을 노출하지 않습니다. 정적 대시보드 스냅샷에는 레지스트리 탐색 기능이 포함되지 않습니다.
감사 이력
모든 변경 사항은 레지스트리의 감사 로그에 이벤트를 추가합니다: 레지스트리 및 컬렉션 생성(create), link, promote, 설명 변경(update), unlink. 이 로그는 “지난달 프로덕션에 사용된 버전은 무엇이며, 어떤 실행이 이를 게시했는가?”와 같은 질문에 답합니다:
registry.events()
# [{"id": 1, "ts": "...", "kind": "create", "payload": {...}},
# {"id": 2, "ts": "...", "kind": "link",
# "payload": {"collection": "my-model", "collection_version": 0,
# "source_project": "my-experiments", "run_name": "exp-1", ...}},
# {"id": 3, "ts": "...", "kind": "promote",
# "payload": {"alias": "staging", "collection_version": 0,
# "previous_version": None, ...}}]Link 및 promote 이벤트는 게시 실행을 기록합니다. Promote 이벤트는 별칭이 이동한 이전 버전도 기록합니다.
Update on GitHub