503: Publish to Hub - Tinker Documentation

Tutorial 503: Publish to HuggingFace Hub

Prerequisites

Run it interactively source

curl -O https://raw.githubusercontent.com/thinking-machines-lab/tinker-cookbook/main/tutorials/503_publish_hub.py && marimo edit 503_publish_hub.py

Once you have a merged model or PEFT adapter on disk, you can upload it to HuggingFace Hub for sharing, deployment, or version control.

The publish workflow:

  1. Build your model (merged via build_hf_model or adapter via build_lora_adapter)
  2. Optionally configure a model card with training metadata
  3. Push to Hub with publish_to_hf_hub

You need a HuggingFace token with write access. Set it via HF_TOKEN environment variable or huggingface-cli login.

Basic publish

The simplest case -- push a model directory to a Hub repository. Repositories are created as private by default.

from tinker_cookbook import weights

url = weights.publish_to_hf_hub(
    model_path="./merged_model",
    repo_id="my-org/my-finetuned-qwen3",
)
print(f"Published to: {url}")
# -> Published to: https://huggingface.co/my-org/my-finetuned-qwen3

Custom model card

Use ModelCardConfig to auto-generate a README.md with HuggingFace metadata (base model, datasets, tags, license). The model card is created during upload.

from tinker_cookbook.weights import ModelCardConfig

card_config = ModelCardConfig(
    base_model="Qwen/Qwen3.5-4B",
    datasets=["my-org/my-sft-dataset"],
    tags=["sft", "chat"],
    license="apache-2.0",
    language=["en"],
)

print("Model card config:")
print(f"  base_model: {card_config.base_model}")
print(f"  tags:       {card_config.tags}")
print(f"  license:    {card_config.license}")

Output

Model card config:
  base_model: Qwen/Qwen3.5-4B
  tags:       ['sft', 'chat']
  license:    apache-2.0

Preview the model card

You can preview the generated model card without publishing by calling generate_model_card directly.

from tinker_cookbook.weights import generate_model_card

_card = generate_model_card(
    config=card_config,
    repo_id="my-org/my-finetuned-qwen3",
)
print(str(_card))

Output

---
base_model: Qwen/Qwen3.5-4B
datasets:
- my-org/my-sft-dataset
language:
- en
library_name: transformers
license: apache-2.0
pipeline_tag: text-generation
tags:
- tinker
- tinker-cookbook
- sft
- chat
---

# my-org/my-finetuned-qwen3

This model was fine-tuned from [Qwen/Qwen3.5-4B](https://huggingface.co/Qwen/Qwen3.5-4B) using [Tinker](/content/tinker/index.html) and [tinker-cookbook](https://github.com/thinking-machines-lab/tinker-cookbook).

## Model details

- **Base model:** [Qwen/Qwen3.5-4B](https://huggingface.co/Qwen/Qwen3.5-4B)
- **Format:** Merged model

## Usage

```python
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained("my-org/my-finetuned-qwen3")
```

## Framework versions

- tinker-cookbook: 0.4.2.dev30+gba719c09e
- transformers: 5.5.3
- torch: 2.12.0
  ```

## Publishing with a model card

Pass the config to `publish_to_hf_hub` and the model card is created automatically:

```
url = weights.publish_to_hf_hub(
    model_path="./merged_model",
    repo_id="my-org/my-finetuned-qwen3",
    model_card=card_config,
)
# -> Published to: https://huggingface.co/my-org/my-finetuned-qwen3
```

## Publishing a PEFT adapter

The same `publish_to_hf_hub` works for adapter directories too. When `model_path` contains `adapter_config.json`, the model card auto-detects the format.

```
adapter_card = ModelCardConfig(
    base_model="Qwen/Qwen3.5-4B",
    tags=["sft"],
    license="apache-2.0",
)

url = weights.publish_to_hf_hub(
    model_path="./peft_adapter",
    repo_id="my-org/my-qwen3-lora",
    model_card=adapter_card,
    private=False,  # make public
)
# -> Published to: https://huggingface.co/my-org/my-qwen3-lora
```

## CLI alternative

You can also publish from the command line with the `tinker` CLI:

```
# Push a merged model
tinker checkpoint push-hf \
    --model-path ./merged_model \
    --repo-id my-org/my-finetuned-qwen3

# Push a PEFT adapter
tinker checkpoint push-hf \
    --model-path ./peft_adapter \
    --repo-id my-org/my-qwen3-lora \
    --public
```

The CLI supports the same options as the Python API (model card fields, privacy settings, custom HF tokens).

## Next steps

- **[Export a Merged HuggingFace Model](https://tinker-docs.thinkingmachines.ai/tutorials/deployment/export-hf/)** 
- **[Build a PEFT LoRA Adapter](https://tinker-docs.thinkingmachines.ai/tutorials/deployment/lora-adapter/)**