Trackio documentation
Artifacts
Artifacts
Giới thiệu
Một artifact là một gói tệp có phiên bản và có tên, được gắn với một dự án — một mô hình đã được huấn luyện, một tập dữ liệu, một bộ kết quả đánh giá. Việc ghi log các tệp dưới dạng artifact (thay vì để chúng trên đĩa) mang lại cho bạn:
- Phiên bản hóa — mỗi lần bạn ghi log dưới cùng một tên, Trackio sẽ ghi nhận một phiên bản mới (
v0,v1, …). Nội dung giống hệt nhau sẽ được khử trùng lặp, do đó việc ghi log lại các tệp không thay đổi sẽ tái sử dụng phiên bản hiện có. - Biệt danh — các con trỏ di động như
latest(được gán tự động) hoặc do bạn tạo (prod,best) luôn trỏ đến một phiên bản duy nhất. - Lineage — các artifact được liên kết với các run đã tạo ra và sử dụng chúng, giúp bạn truy vết run nào đã tạo ra một model và những run nào đã sử dụng model đó.
Artifacts hoạt động hoàn toàn ngoại tuyến với bộ nhớ cục bộ, và đồng bộ hóa lên một Hugging Face Space (hoặc máy chủ tự lưu trữ) khi được cấu hình, giống hệt như các chỉ số.
Ghi log một artifact
Cách nhanh nhất là ghi log một tệp hoặc thư mục trực tiếp. Thao tác này sẽ tạo một artifact mới, thêm đường dẫn và ghi nhận nó như một đầu ra của lần chạy hiện tại:
import trackio
trackio.init(project="my_project")
# ... training ...
trackio.log_artifact("checkpoints/model.safetensors", type="model")Khi bạn truyền một đường dẫn, name của artifact mặc định là run-<run_id>-<basename> và type mặc định là "unspecified". Truyền name và type để đặt chúng một cách rõ ràng:
trackio.log_artifact("checkpoints/", name="my-model", type="model")Các loại artifact
Loại type của Artifact là một chuỗi phân loại tự do. Trackio không áp đặt một danh sách các loại cố định, nhưng các quy ước phổ biến là:
| Loại | Sử dụng cho |
|---|---|
"model" | Các checkpoint của mô hình, trọng số adapter, bộ phân tách token, cấu hình mô hình |
"dataset" | Bộ dữ liệu huấn luyện, xác thực, kiểm tra hoặc tạo |
"evaluation" | Đầu ra đánh giá, dự đoán, kết quả benchmark, tệp điểm |
"report" | Các hình, biểu đồ, bảng, notebook hoặc các gói phân tích có thể đọc được bằng người |
"unspecified" | Giá trị mặc định khi không cung cấp kiểu |
Sử dụng tên kiểu ổn định trong một dự án để bạn có thể lọc các artifact nhất quán và dùng trackio.use_artifact(..., type="...") để khẳng định rằng một run đang tiêu thụ đúng loại artifact mong đợi.
Xây dựng một artifact một cách rõ ràng
Để kiểm soát chi tiết hơn — nhiều tệp, đường dẫn logic tùy chỉnh, mô tả hoặc metadata — hãy tạo một Artifact, thêm tệp vào đó, sau đó ghi log:
artifact = trackio.Artifact(
name="my-model",
type="model",
description="Fine-tuned on the v2 dataset",
metadata={"base_model": "bert-base", "epochs": 3},
)
artifact.add_file("checkpoints/model.safetensors")
artifact.add_file("checkpoints/config.json")
artifact.add_dir("tokenizer/")
logged = trackio.log_artifact(artifact)Sau khi ghi nhật ký, artifact sẽ được đóng băng và version, aliases, size, cùng manifest của nó sẽ được điền đầy đủ:
print(logged.version) # "v0"
print(logged.aliases) # ("latest",)Phiên bản và tên gọi khác
Mỗi lần ghi log dưới một tên hiện có sẽ tạo ra phiên bản số nguyên tiếp theo và di chuyển alias latest sang phiên bản đó. Gán alias của riêng bạn bằng aliases=:
trackio.log_artifact(artifact, aliases=["prod", "best"])Alias là các con trỏ động: khi ghi log một phiên bản mới với cùng một alias, nó sẽ được trỏ lại. Các chỉ định phiên bản (v0, v1, …) được dành riêng và không thể dùng làm alias.
Nếu bạn ghi log nội dung giống hệt một phiên bản hiện có, Trackio sẽ tái sử dụng phiên bản đó thay vì tạo một phiên bản mới. Bất kỳ aliases nào bạn truyền vào một cách tường minh vẫn sẽ xoay vòng lên phiên bản đó, nhưng latest sẽ được giữ nguyên tại vị trí hiện tại — việc ghi log lại nội dung giống hệt (hoặc cũ hơn) sẽ không bao giờ di chuyển nó lùi về phía trước.
Sử dụng một artifact
use_artifact() lấy một artifact và ghi nhận nó là một input cho run hiện tại, đây là cách xây dựng quan hệ nguồn gốc (lineage) giữa run sử dụng và artifact mà nó đã dùng:
trackio.init(project="my_project")
artifact = trackio.use_artifact("my-model") # resolves to :latest
artifact = trackio.use_artifact("my-model:v2") # pin a version
artifact = trackio.use_artifact("my-model:prod") # resolve an aliasTruyền type để xác nhận kiểu của artifact, và gây ra lỗi nếu không khớp:
artifact = trackio.use_artifact("my-model", type="model")Tải xuống tệp
use_artifact trả về một Artifact mà bạn có thể vật chất hóa các tệp của nó bằng download():
artifact = trackio.use_artifact("my-model:latest")
path = artifact.download()
# files are now under ./.trackio/artifact-downloads/my_project/my-model_v2/Mặc định, các tệp được ghi vào ./.trackio/artifact-downloads/<project>/<name>_v<version>/, được phân biệt theo project để các artifact cùng tên từ các project khác nhau không bao giờ xung đột; truyền root để chọn một thư mục khác. download() là idempotent — các tệp đã có sẵn sẽ bị bỏ qua — và khi run được hỗ trợ bởi một Space, bất kỳ tệp nào thiếu cục bộ sẽ được tải về từ remote.
Tham chiếu dữ liệu bên ngoài
Một số dữ liệu quá lớn để sao chép, hoặc đã nằm trong bộ lưu trữ bền vững mà bạn không muốn nhân bản. add_reference ghi nhận các dữ liệu như vậy theo URI trong manifest mà không đưa bất kỳ byte nào vào bộ lưu trữ của Trackio, nhờ đó bạn vẫn có phiên bản, khử trùng lặp, alias và dòng dõi (lineage) cho dữ liệu không bao giờ di chuyển:
artifact = trackio.Artifact(name="training-set", type="dataset")
artifact.add_reference("file:///mnt/nvme/datasets/corpus.parquet")
artifact.add_reference("file:///mnt/nvme/datasets/shards/") # a directory — expands to one entry per file
artifact.add_reference("https://example.com/data/eval.json")
artifact.add_reference("hf://datasets/username/my-dataset/train.parquet")
trackio.log_artifact(artifact)Các scheme tích hợp sẵn là file://, http(s):// và hf:// — tất cả đều được cung cấp bởi các dependency có sẵn của Trackio. Mọi scheme khác (s3://, gs://, URL blob của Azure, …) đều được hỗ trợ bằng cách đăng ký một handler tùy chỉnh; xem Tham chiếu các kho lưu trữ khác bên dưới để có các ví dụ đầy đủ về S3, GCS và Azure. Với checksum=True (mặc định), Trackio sẽ thăm dò nguồn để điền vào size và một checksum:
file://được băm theo luồng thành sha256; kích thước của nó được đọc từ đĩa.hf://sử dụng LFS sha256 (hoặc git blob id);http(s)://sử dụngETagcủa máy chủ.
Mọi checksum đều được lưu trữ trong một trường digest duy nhất — là sha256 cho các tham chiếu local/LFS, hoặc ETag của nhà cung cấp cho các tham chiếu HTTP hoặc object-store.
URI chỉ định một thư mục (file://) hoặc một đường dẫn repo (hf://) sẽ được mở rộng thành một mục tham chiếu cho mỗi đối tượng, mỗi mục được đặt tên theo đường dẫn tương đối so với tiền tố (được đặt lồng bên trong name= nếu có). max_objects (mặc định là 10.000) giới hạn quá trình mở rộng và sẽ gây ra lỗi nếu vượt quá giới hạn này.
Khi không thể lấy được checksum — ví dụ một máy chủ không có ETag — tham chiếu vẫn được ghi lại, sử dụng chính URI làm digest, và một cảnh báo sẽ được phát ra. Ngoại lệ là một đường dẫn file:// cục bộ không tồn tại: nó sẽ gây ra lỗi thay vì được ghi lại, vì một tệp cục bộ bị thiếu gần như luôn là một sai sót — hãy dùng add_file để chuẩn bị một tệp cục bộ. Truyền checksum=False để bỏ qua checksum cho từng đối tượng — khi đó một đối tượng chỉ ghi lại URI của nó — và name= để đặt đường dẫn logic.
Bản dạng phiên bản của một tham chiếu được xác định bởi URI, kích thước và digest của nó, do đó việc ghi log lại các tham chiếu giống hệt nhau sẽ khử trùng lặp về một phiên bản duy nhất, trong khi URI, kích thước hoặc checksum bị thay đổi sẽ tạo ra một phiên bản mới — giống hệt như nội dung tệp. Khi URI được dùng làm digest, bản dạng do đó sẽ bám theo URI chứ không phải nội dung.
URI được ghi lại nguyên văn và manifest có thể được đồng bộ hóa với một Dataset trên Hugging Face. Một URI nhúng thông tin xác thực — một URL https:// đã ký trước hoặc một token SAS của Azure — sẽ phơi bày thông tin xác thực đó cho bất kỳ ai có thể đọc Dataset, do đó add_reference sẽ cảnh báo khi chuỗi truy vấn của URI trông giống như đã được ký; hãy ưu tiên sử dụng URI không ký chính tắc của đối tượng (ví dụ: s3://bucket/key).
Các byte tham chiếu không bao giờ được tải lên Space hoặc bucket, nhưng chúng có thể được lấy theo yêu cầu. download() tải xuống mỗi đối tượng được tham chiếu vào thư mục (thông qua httpx2, huggingface_hub, hoặc trình xử lý đã đăng ký của bạn), điều này có thể truyền tải một lượng dữ liệu lớn. Trước khi lấy, nguồn của mỗi đối tượng được dò lại và checksum hiện tại của nó được so sánh với checksum đã ghi lại — nếu không khớp, một cảnh báo sẽ được phát ra rằng nguồn có thể đã thay đổi nhưng quá trình tải xuống vẫn tiếp tục. Mỗi đối tượng được ghi một cách nguyên tử, và một đối tượng đã có sẵn trên đĩa sẽ bị bỏ qua mà không cần kiểm tra lại nguồn, do đó các lần gọi lặp lại sẽ rẻ và có tính chất idempotent:
artifact = trackio.use_artifact("training-set:latest")
path = artifact.download() # downloads staged files AND referenced objectsĐể làm việc với các con trỏ mà không tải xuống, hãy đọc chúng từ artifact thay vào đó:
print(artifact.references) # [{'path': ..., 'ref': 's3://...', 'size': ..., 'digest': ...}, ...]
print(artifact.get_entry_uri("eval.json")) # "s3://my-bucket/eval.json"Tham chiếu không thể tải (tệp cục bộ bị thiếu, URL không thể truy cập, hoặc scheme không có trình xử lý được đăng ký) sẽ gây ra lỗi khi download() gặp phải nó.
Tham chiếu đến các kho lưu trữ khác (S3, GCS, Azure)
Trackio cố ý không cung cấp các SDK của nhà cung cấp cloud. Để tham chiếu các đối tượng trong một kho lưu trữ mà nó không xử lý một cách bản địa, hãy kế thừa trackio.ReferenceHandler và đăng ký một instance bằng trackio.register_reference_handler. Một handler cài đặt bốn phương thức:
matches(scheme, uri)— xác định xem trình xử lý này có sở hữu URI hay không. Các trình xử lý đã đăng ký được tham khảo trước các trình xử lý tích hợp sẵn, do đó một trình xử lý cũng có thể nhận các hosthttps://cụ thể (như ví dụ Azure bên dưới) trước trình xử lý HTTP chung.resolve(uri, checksum, max_objects)— thăm dò nguồn và trả về một danh sách các mụctrackio.ResolvedReference: một mục vớirelkey=Nonecho một đối tượng đơn lẻ, hoặc một mục cho mỗi đối tượng (vớirelkeyđược đặt thành đường dẫn của đối tượng tương đối so với tiền tố) khi URI chỉ định một tiền tố. Đặtsizevàdigestkhi nguồn có thể được thăm dò (ETag của nhà cung cấp hoạt động tốt như một digest — Trackio coi các digest tham chiếu là các token mờ); trả về chúng làNoneđể ghi lại tham chiếu không có checksum, trong trường hợp đó Trackio sẽ dùng URI làm digest và đưa ra cảnh báo.fetch(uri, dest)— tải đối tượng đơn tạiurixuống đường dẫn cục bộdest(được gọi bởiArtifact.download()).hint()— một thông điệp hành động ngắn gọn được hiển thị trong cảnh báo khiresolvekhông tạo ra checksum nào.
Các khóa được phát hiện trong quá trình mở rộng tiền tố phải được mã hóa phần trăm khi tổng hợp uri của từng mục (và được giải mã trong fetch), vì URI của manifest có thể không chứa khoảng trắng.
S3 ( s3:// , thông qua boto3 )
from urllib.parse import quote, unquote, urlsplit
import boto3
import trackio
class S3Handler(trackio.ReferenceHandler):
def matches(self, scheme, uri):
return scheme == "s3"
def resolve(self, uri, checksum, max_objects):
parts = urlsplit(uri)
bucket, key = parts.netloc, unquote(parts.path.lstrip("/"))
client = boto3.client("s3")
if key and not key.endswith("/"):
head = client.head_object(Bucket=bucket, Key=key)
return [
trackio.ResolvedReference(
relkey=None,
uri=uri,
size=int(head["ContentLength"]),
digest=head["ETag"].strip('"') if checksum else None,
)
]
base = key[: key.rfind("/") + 1]
entries = []
pages = client.get_paginator("list_objects_v2").paginate(
Bucket=bucket, Prefix=key
)
for page in pages:
for obj in page.get("Contents", []):
if obj["Key"].endswith("/"):
continue
if len(entries) >= max_objects:
raise ValueError(
f"{uri} expands to more than {max_objects} objects; "
"pass max_objects= to raise the limit."
)
entries.append(
trackio.ResolvedReference(
relkey=obj["Key"][len(base):],
uri=f"s3://{bucket}/{quote(obj['Key'], safe='/')}",
size=int(obj["Size"]),
digest=obj["ETag"].strip('"') if checksum else None,
)
)
return entries
def fetch(self, uri, dest):
parts = urlsplit(uri)
with open(dest, "wb") as f:
boto3.client("s3").download_fileobj(
parts.netloc, unquote(parts.path.lstrip("/")), f
)
def hint(self):
return "Configure AWS credentials so the object can be probed for an ETag."
trackio.register_reference_handler(S3Handler())
artifact = trackio.Artifact(name="training-set", type="dataset")
artifact.add_reference("s3://my-bucket/shards/") # expands to one entry per object
trackio.log_artifact(artifact)Google Cloud Storage ( gs:// , thông qua google-cloud-storage )
from urllib.parse import quote, unquote, urlsplit
from google.cloud import storage
import trackio
class GcsHandler(trackio.ReferenceHandler):
def matches(self, scheme, uri):
return scheme == "gs"
def resolve(self, uri, checksum, max_objects):
parts = urlsplit(uri)
bucket, key = parts.netloc, unquote(parts.path.lstrip("/"))
client = storage.Client()
if key and not key.endswith("/"):
blob = client.bucket(bucket).get_blob(key)
if blob is None:
raise ValueError(f"No such GCS object: {uri}")
return [
trackio.ResolvedReference(
relkey=None,
uri=uri,
size=blob.size,
digest=blob.etag.strip('"') if checksum else None,
)
]
base = key[: key.rfind("/") + 1]
entries = []
for blob in client.list_blobs(bucket, prefix=key):
if blob.name.endswith("/"):
continue
if len(entries) >= max_objects:
raise ValueError(
f"{uri} expands to more than {max_objects} objects; "
"pass max_objects= to raise the limit."
)
entries.append(
trackio.ResolvedReference(
relkey=blob.name[len(base):],
uri=f"gs://{bucket}/{quote(blob.name, safe='/')}",
size=blob.size,
digest=blob.etag.strip('"') if checksum else None,
)
)
return entries
def fetch(self, uri, dest):
parts = urlsplit(uri)
key = unquote(parts.path.lstrip("/"))
storage.Client().bucket(parts.netloc).blob(key).download_to_filename(
str(dest)
)
def hint(self):
return "Configure GCP credentials so the object can be probed for an ETag."
trackio.register_reference_handler(GcsHandler())Azure Blob Storage (thông qua azure-storage-blob + azure-identity)
Azure blobs được định danh bằng các URL https:// thông thường (https://<account>.blob.core.windows.net/<container>/<blob>), do đó trình xử lý này nhận diện chúng dựa trên hậu tố host — việc đăng ký nó sẽ giúp nó ưu tiên hơn trình xử lý HTTP chung của Trackio:
from urllib.parse import quote, unquote, urlsplit
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient
import trackio
class AzureHandler(trackio.ReferenceHandler):
def matches(self, scheme, uri):
return scheme in ("http", "https") and urlsplit(
uri
).netloc.lower().endswith(".blob.core.windows.net")
def _split(self, uri):
parts = urlsplit(uri)
container, _, blob_name = parts.path.lstrip("/").partition("/")
return f"{parts.scheme}://{parts.netloc}", container, unquote(blob_name)
def _service(self, account_url):
return BlobServiceClient(account_url, credential=DefaultAzureCredential())
def resolve(self, uri, checksum, max_objects):
account_url, container, blob_name = self._split(uri)
service = self._service(account_url)
if blob_name and not blob_name.endswith("/"):
props = service.get_blob_client(container, blob_name).get_blob_properties()
return [
trackio.ResolvedReference(
relkey=None,
uri=uri,
size=props.size,
digest=props.etag.strip('"') if checksum else None,
)
]
base = blob_name[: blob_name.rfind("/") + 1]
entries = []
container_client = service.get_container_client(container)
for blob in container_client.list_blobs(name_starts_with=blob_name):
if blob.name.endswith("/"):
continue
if len(entries) >= max_objects:
raise ValueError(
f"{uri} expands to more than {max_objects} objects; "
"pass max_objects= to raise the limit."
)
entries.append(
trackio.ResolvedReference(
relkey=blob.name[len(base):],
uri=f"{account_url}/{container}/{quote(blob.name, safe='/')}",
size=blob.size,
digest=blob.etag.strip('"') if checksum else None,
)
)
return entries
def fetch(self, uri, dest):
account_url, container, blob_name = self._split(uri)
downloader = (
self._service(account_url)
.get_blob_client(container, blob_name)
.download_blob()
)
with open(dest, "wb") as f:
downloader.readinto(f)
def hint(self):
return "Configure Azure credentials so the blob can be probed for an ETag."
trackio.register_reference_handler(AzureHandler())Các handler này sẽ gây ra lỗi khi không thể kiểm tra nguồn; nếu bạn muốn ghi lại một tham chiếu không có checksum trong trường hợp đó (ví dụ, khi lập danh mục dữ liệu phía sau xác thực mà bạn không thể truy cập được tại thời điểm ghi log), hãy bắt lỗi của provider bên trong resolve và trả về [trackio.ResolvedReference(relkey=None, uri=uri)] — Trackio sẽ dùng URI làm digest dự phòng và phát cảnh báo, sử dụng hint() của bạn.
Đăng ký handler trong mọi tiến trình thêm hoặc tải xuống các tham chiếu như vậy: Artifact.download() cần handler để lấy các byte, và một URI có scheme không có handler được đăng ký sẽ gây ra lỗi.
Duyệt các artifact trên dashboard
Tab Artifacts của bảng điều khiển (hiện ra khi một dự án có các artifact) liệt kê các artifact được nhóm theo loại, kèm theo các alias, kích thước và số lượng tệp của mỗi phiên bản. Chọn một phiên bản sẽ hiển thị danh sách tệp của nó — nhấp vào một tệp để tải xuống — cùng với metadata và nguồn gốc (lineage) của nó: run đã tạo ra nó và các run đã sử dụng nó, mỗi run đều có liên kết đến trang chi tiết của run đó.
Mỗi phiên bản cũng có một phần Lineage hiển thị đồ thị tương tác về nguồn gốc của phiên bản: các phiên bản artifact và các lần chạy (runs) là các nút, với mũi tên từ một lần chạy đến các artifact mà nó đã ghi log và từ một artifact đến các lần chạy đã sử dụng nó. Phiên bản được chọn sẽ được làm nổi bật. Để giữ cho các đồ thị lớn dễ đọc, năm hoặc nhiều nút tương tự có kết nối giống hệt nhau (ví dụ: nhiều checkpoint mà một lần chạy đã ghi log) sẽ được nhóm thành một nút cluster duy nhất hiển thị số lượng — nhấp vào cluster để tìm kiếm các thành viên của nó và trích xuất từng thành viên riêng lẻ trở lại đồ thị. Kéo để di chuyển, sử dụng Ctrl/Cmd + cuộn (hoặc các nút +/−) để thu phóng, và nhấp vào bất kỳ nút nào để mở một bản tóm tắt với liên kết đến lần chạy hoặc phiên bản artifact đó.
Trang chi tiết chạy hiển thị cùng một nguồn gốc theo hướng ngược lại, với các phần Sản phẩm đầu ra và Sản phẩm đầu vào liên kết ngược lại tab Artifacts.
Lưu trữ từ xa
Khi run của bạn nhắm đến một Hugging Face Space hoặc máy chủ tự lưu trữ (xem Track), các tệp artifact được định danh theo nội dung và chỉ được tải lên một lần: Trackio sẽ bỏ qua các blob mà máy chủ đã có, nên việc ghi log lại các tệp dùng chung sẽ tiết kiệm chi phí. Metadata và blob của artifact được lưu trữ cùng với dữ liệu run khác của bạn vào HF Dataset hoặc bucket đã cấu hình.
Update on GitHub