ShubhamSetia's picture
finetune: add GGUF publish prep workflow
9ff127f
|
Raw
History Blame
28.6 kB

Actor SFT Dataset V0

This directory contains the first-pass dataset tooling for fine-tuning an AI Puppet Theater Actor agent. It prepares chat-style supervised fine-tuning rows for the target model openbmb/MiniCPM5-1B; it does not train, quantize, publish, or integrate a model into the Space.

The goal is to teach the Actor agent to return one compact, valid JSON object for a single puppet beat. The output shape matches the planned actor contract:

{
  "intent": "inspect_prop",
  "line": "This rubber duck squeaks exactly like a guilty witness.",
  "emotion": "investigative",
  "gesture": "leans toward the glowing prop",
  "stage_effect": "prop_table_glow",
  "memory_update": "Noted that the rubber duck behaved like evidence.",
  "tool_request": {
    "tool": "inspect_prop",
    "args": {"prop": "rubber duck"},
    "reason": "The prop may reveal a stage clue."
  }
}

memory_update may be null when no useful memory should be saved. tool_request may also be null. Allowed tools are inspect_prop, consult_stage_oracle, and change_lighting.

Schema

Each SFT row is JSONL with:

{
  "id": "actor-sft-v0-000001",
  "source_mix": ["synthetic_v0", "deterministic_templates", "ai_puppet_theater_runtime_schema"],
  "row_type": "prop_inspection",
  "messages": [
    {"role": "system", "content": "You are an Actor agent in AI Puppet Theater..."},
    {"role": "user", "content": "premise: ...\nshow_state JSON: ...\nactor JSON: ...\ndirector_instruction: ..."},
    {"role": "assistant", "content": "{\"intent\":\"...\",\"line\":\"...\"}"}
  ]
}

The assistant message content is a serialized JSON object, not a nested object, so it is directly usable as a chat SFT completion.

Rows created from optional local seed files also include:

{
  "source_dataset": "G-reen/TheatreLM-v2.1-Characters",
  "transformation": "seeded_synthetic_actor_json"
}

The raw external text is used only to seed premise, persona, setting, memory, prop, and Director-instruction material. Assistant completions are still generated by this repo's validated Actor JSON templates.

Row types in v0:

  • normal_reaction
  • prop_inspection
  • oracle_consult
  • lighting_change
  • memory_callback
  • secret_hint_or_reveal
  • finale
  • comedic_confusion

Generate

Run from the repository root:

python finetune/scripts/generate_actor_sft_v0.py

Generation is deterministic by default using a fixed seed, so the sample and eval files can be regenerated reproducibly. The synthetic-v0 pool currently uses 40 premises, 25 actor profiles, 30+ props, 10+ moods, 10+ stage/lighting states, multiple line templates per row type, multiple memory update templates, and multiple Director instructions per row type.

Optional external seed material can be provided as local JSONL files:

  • finetune/external_seeds/theatrelm_sample.jsonl
  • finetune/external_seeds/rpgpt_sample.jsonl

These files are optional. If they are absent, generation prints a short message and continues with synthetic-only data. To use another local path:

python finetune/scripts/generate_actor_sft_v0.py \
  --theatrelm-seed-path /path/to/theatrelm_sample.jsonl \
  --rpgpt-seed-path /path/to/rpgpt_sample.jsonl

The supported seed sources are:

Raw external rows are not committed. finetune/external_seeds/ is gitignored except for .gitkeep. Seeded rows include source metadata and should be credited when the full generated dataset is published separately as a Hugging Face Dataset repo.

External seed ingestion applies simple demo-safety filters and skips empty, malformed, very long, sexually explicit, heavily profane, or graphically violent rows. The filter is intentionally conservative and does not replace manual review before publishing.

Default output:

  • finetune/data/actor_sft_v0.jsonl
  • finetune/data/actor_sft_v0_train.jsonl
  • finetune/data/actor_sft_v0_val.jsonl
  • finetune/data_samples/actor_sft_v0_sample.jsonl
  • finetune/data_samples/actor_eval_prompts.jsonl

The full generated dataset under finetune/data/ is gitignored. Keep only the small sample, eval prompt files, scripts, and docs in this repo.

Targeted V1 Hardening Dataset

V1 is a targeted synthetic hardening set for the v0 Actor LoRA failure modes seen in eval. It keeps v0 reproducible and adds a separate dataset version with more oracle, prop, lighting, and memory callback rows.

Generate v1:

python finetune/scripts/generate_actor_sft_v0.py --version v1

Default v1 output:

  • finetune/data/actor_sft_v1.jsonl
  • finetune/data/actor_sft_v1_train.jsonl
  • finetune/data/actor_sft_v1_val.jsonl
  • finetune/data_samples/actor_sft_v1_sample.jsonl

V1 defaults to 2,200 rows. Use --rows if you want a different size in the accepted 2,000-2,500 range:

python finetune/scripts/generate_actor_sft_v0.py --version v1 --rows 2400

V1 hardening examples enforce the same seven assistant top-level fields and over-sample:

  • clean consult_stage_oracle calls with only tool, args.question, and reason
  • clean inspect_prop calls with only tool, args.prop, and reason
  • clean change_lighting calls with only tool, args.mood, and reason
  • memory callbacks that include line and do not copy input/state fields into assistant JSON
  • non-finale reactions that avoid deliver_finale and final_bow_lights
  • single serialized JSON objects with no markdown, continuation, duplicate object, or copied state fields

Validate

Run:

python finetune/scripts/validate_actor_sft.py finetune/data/actor_sft_v0.jsonl

Validate v1:

python finetune/scripts/validate_actor_sft.py finetune/data/actor_sft_v1.jsonl

The validator checks row shape, chat roles, assistant JSON parsing, exact assistant fields, line length, allowed row types, tool request shape, and allowed tools. It prints total rows, valid and invalid counts, train/val counts when sibling split files are present, row type distribution, and tool distribution.

For v1, validation also rejects change_lighting args that do not use the current app runtime key mood, extra tool keys, copied state/input fields such as show_state, recent_transcript, held_props, latest_prop, latest_audience_action, or tool_results, and finale intent/effects outside finale context.

Strict Local Audit

Before retraining after a regression, run the stricter local audit. It checks that assistant completions are exactly one JSON object, detects duplicate top-level keys, rejects missing or extra assistant fields, rejects copied state/input fields, validates strict tool shapes, and checks finale intent/effects against show_state.

python finetune/scripts/audit_actor_sft.py finetune/data/actor_sft_v1.jsonl
python finetune/scripts/audit_actor_sft.py finetune/data/actor_sft_v0.jsonl

The audit intentionally follows the current app runtime tool schema. At the time of writing, change_lighting expects args: {"mood": "..."} in puppet_theater/tools.py.

Synthetic-v0 Status

This is a deterministic synthetic v0 dataset. It is intentionally small, safe, and template-driven so the pipeline can be reviewed before model training. It covers no-tool responses, prop inspection, oracle consultation, lighting changes, memory callbacks, secret hints/reveals, finales, and comedic confusion.

The full generated dataset is expected to be published separately as a Hugging Face Dataset repo after review. This codebase keeps only reproducible scripts plus small committed examples. If optional external seeds are used in a published dataset, credit the source datasets above.

Modal LoRA Training

The first training target is a LoRA/QLoRA adapter for openbmb/MiniCPM5-1B. LoRA trains a small adapter on top of the base model instead of fully retraining all model weights. The first output is an adapter directory. Later tasks can merge that adapter into the base model and convert or quantize the merged model to GGUF for llama.cpp.

Training dependencies are isolated in finetune/requirements-train.txt; the main Gradio app does not import them.

Setup

Install and authenticate Modal locally:

pip install modal
modal setup

Generate the local train/val files before launching Modal:

python finetune/scripts/generate_actor_sft_v0.py
python finetune/scripts/validate_actor_sft.py finetune/data/actor_sft_v0.jsonl

The Modal wrapper mounts the local finetune/ directory into the job image, including the generated finetune/data/actor_sft_v0_train.jsonl and finetune/data/actor_sft_v0_val.jsonl files. Outputs and model cache live in a persistent Modal Volume named ai-puppet-theater-finetune.

openbmb/MiniCPM5-1B may be publicly downloadable. If Hugging Face access is required, create a Modal secret containing HF_TOKEN and opt in to using it:

modal secret create huggingface-secret HF_TOKEN=hf_...
MODAL_HF_SECRET_NAME=huggingface-secret modal run finetune/modal_train_actor_lora.py::smoke_test

Do not commit tokens or put them in dataset files.

Smoke Test

Run a tiny Modal training job that uses only 20 train rows and 10 eval rows:

modal run finetune/modal_train_actor_lora.py::smoke_test

The smoke test defaults to an A10 GPU. To change the GPU class:

MODAL_GPU=A10G modal run finetune/modal_train_actor_lora.py::smoke_test

The smoke-test adapter is saved in the Modal Volume under:

/vol/outputs/minicpm5-actor-lora-smoke

Full Run

Run against the full generated train/val split:

modal run finetune/modal_train_actor_lora.py::train_full

Default training settings:

  • model: openbmb/MiniCPM5-1B
  • max sequence length: 1024
  • epochs: 2
  • learning rate: 2e-4
  • LoRA rank/alpha/dropout: 16 / 32 / 0.05
  • per-device train batch size: 2
  • gradient accumulation: 8
  • save/eval strategy: epoch
  • seed: 42
  • QLoRA: enabled by default

The full adapter is saved in the Modal Volume under:

/vol/outputs/minicpm5-actor-lora

V1 Hardening Run

Generate and validate the targeted v1 dataset first:

python finetune/scripts/generate_actor_sft_v0.py --version v1
python finetune/scripts/validate_actor_sft.py finetune/data/actor_sft_v1.jsonl

Train a separate v1 adapter on Modal without deleting or overwriting the v0 adapter:

modal run finetune/modal_train_actor_lora.py::train_v1

This uses:

  • train file: finetune/data/actor_sft_v1_train.jsonl
  • val file: finetune/data/actor_sft_v1_val.jsonl
  • base model: openbmb/MiniCPM5-1B
  • epochs: 2
  • output dir: /vol/outputs/minicpm5-actor-lora-v1

The downloaded/local adapter name should be:

finetune/outputs/minicpm5-actor-lora-v1

Retrieve Outputs

Use the Modal volume CLI to download the trained adapter directory from the persistent Volume:

mkdir -p finetune
cd finetune
modal volume get --force ai-puppet-theater-finetune /outputs/minicpm5-actor-lora
cd ..

This writes the Modal directory /vol/outputs/minicpm5-actor-lora to local finetune/outputs/minicpm5-actor-lora. Passing finetune/outputs/minicpm5-actor-lora as the local destination can fail if that directory already exists.

After download, confirm the adapter files are present locally. Full runs may have adapter files at the output root and/or inside epoch checkpoints such as checkpoint-158:

ls finetune/outputs/minicpm5-actor-lora
find finetune/outputs/minicpm5-actor-lora -name adapter_config.json -o -name adapter_model.safetensors

The source directory in Modal is /vol/outputs/minicpm5-actor-lora; the local destination is finetune/outputs/minicpm5-actor-lora. Local adapter outputs under finetune/outputs/ are gitignored.

Retrieve the v1 adapter similarly:

mkdir -p finetune
cd finetune
modal volume get --force ai-puppet-theater-finetune /outputs/minicpm5-actor-lora-v1
cd ..

This writes /vol/outputs/minicpm5-actor-lora-v1 to local finetune/outputs/minicpm5-actor-lora-v1.

Local Script

The training script can also run directly in a CUDA environment with the training requirements installed:

pip install -r finetune/requirements-train.txt
python finetune/scripts/train_minicpm5_actor_lora.py \
  --train_file finetune/data/actor_sft_v0_train.jsonl \
  --val_file finetune/data/actor_sft_v0_val.jsonl \
  --output_dir finetune/outputs/minicpm5-actor-lora \
  --max_train_samples 20 \
  --max_eval_samples 10 \
  --epochs 0.05

The Mac local machine is best used for repo work and later GGUF/llama.cpp testing. The intended training path is Modal/CUDA, not the Hugging Face Space runtime.

Adapter Eval

Before merging, quantizing, publishing, or integrating the adapter, run generation against the held-out Actor eval prompts and validate whether responses are clean Actor JSON.

Default local eval command:

python finetune/scripts/eval_minicpm5_actor_lora.py \
  --adapter_dir finetune/minicpm5-actor-lora \
  --eval_file finetune/data_samples/actor_eval_prompts.jsonl \
  --output_file finetune/eval_outputs/minicpm5_actor_lora_eval.jsonl

Quick local smoke eval:

python finetune/scripts/eval_minicpm5_actor_lora.py --limit 3

The script loads openbmb/MiniCPM5-1B, applies the local LoRA adapter from finetune/minicpm5-actor-lora, generates short deterministic responses with temperature=0.0 and max_new_tokens=192 by default, validates JSON shape/tool calls/line length, prints aggregate metrics, and writes detailed generations to:

finetune/eval_outputs/minicpm5_actor_lora_eval.jsonl

Eval distinguishes JSON and schema quality levels:

  • Raw clean JSON means the model returned exactly one JSON object and no extra text.
  • Extracted usable JSON means the evaluator found and parsed the first complete balanced JSON object, even if the model continued with extra text afterwards.
  • Has required fields means the parsed object includes usable intent, line, emotion, gesture, stage_effect, memory_update, and tool_request fields.
  • Exact top-level schema means the parsed object has only those seven top-level fields.
  • Sanitized actor JSON usable means extra top-level fields were dropped and tool args were normalized into the runtime schema while preserving the required Actor output.

Detailed eval rows keep assistant_text, extracted json_text, parsed JSON, sanitized_actor_json, and validation diagnostics such as parse_error, clean_json_error, tool_error, missing_required_fields, extra_top_level_field_names, and forbidden_top_level_field_names. Forbidden top-level fields include copied persona/state fields such as speaking_style, show_state, recent_transcript, tool_results, setting, and story_phase.

Tool requests are validated strictly and also sanitized for demo/runtime reliability. For example, inspect_prop keeps only {"prop": ...}, consult_stage_oracle keeps only {"question": ...}, and change_lighting keeps the current runtime shape {"mood": ...}. Generated change_lighting aliases such as {"lighting": ...} or {"color": ...} are normalized to {"mood": ...} for app compatibility. Tool-name aliases such as consult oracle and consult_oracle are normalized to consult_stage_oracle for diagnostics. If a generated tool request has extra args or a normalizable tool name but can be reduced safely, the eval output records sanitization_needed: true, preserves original_tool_request, and writes sanitized_tool_request. Unparsed outputs are not counted as sanitized usable.

For experiments, --append_eval_suffix adds a stricter reminder to return exactly one JSON object with only the seven Actor keys and not copy input fields. It is off by default because eval metrics should reflect the adapter's normal prompt behavior, and some adapters become less stable with extra instruction text.

If local Mac inference is too slow or unsupported, run eval on Modal/CUDA from the repository root. This uses the local adapter directory mounted into the Modal image and writes eval details to the persistent Modal Volume:

cd /Users/shubhamsetia/learn/huggingface_hackathon/AI-Puppet-Theater
modal run finetune/modal_train_actor_lora.py::eval_adapter --limit 3

Run the full eval by omitting --limit:

modal run finetune/modal_train_actor_lora.py::eval_adapter

Evaluate the v1 adapter stored in the Modal Volume:

cd /Users/shubhamsetia/learn/huggingface_hackathon/AI-Puppet-Theater
modal run finetune/modal_train_actor_lora.py::eval_adapter_v1 --limit 10

Run the full v1 eval by omitting --limit:

modal run finetune/modal_train_actor_lora.py::eval_adapter_v1

The Modal eval output path is:

/vol/eval_outputs/minicpm5_actor_lora_eval.jsonl

The Modal v1 eval output path is:

/vol/eval_outputs/minicpm5_actor_lora_v1_eval.jsonl

Evaluate the merged v0 model after running merge_v0:

modal run finetune/modal_train_actor_lora.py::eval_merged_v0 --limit 10

The Modal merged-model eval output path is:

/vol/eval_outputs/minicpm5_actor_merged_v0_eval.jsonl

Download it locally with:

mkdir -p finetune/eval_outputs
modal volume get --force ai-puppet-theater-finetune \
  /eval_outputs/minicpm5_actor_lora_eval.jsonl \
  finetune/eval_outputs/minicpm5_actor_lora_eval.jsonl

Download the v1 eval output locally with:

mkdir -p finetune/eval_outputs
modal volume get --force ai-puppet-theater-finetune \
  /eval_outputs/minicpm5_actor_lora_v1_eval.jsonl \
  finetune/eval_outputs/minicpm5_actor_lora_v1_eval.jsonl

Download the merged-model eval output locally with:

mkdir -p finetune/eval_outputs
modal volume get --force ai-puppet-theater-finetune \
  /eval_outputs/minicpm5_actor_merged_v0_eval.jsonl \
  finetune/eval_outputs/minicpm5_actor_merged_v0_eval.jsonl

Keep this as eval only: do not merge, convert to GGUF, publish, or integrate the model in this step.

Merge LoRA Adapter

The current best Actor adapter is v0:

  • local adapter path: finetune/minicpm5-actor-lora/
  • published adapter: build-small-hackathon/AI-Puppet-Theater-MiniCPM5-Actor-LoRA

Merge v0 into openbmb/MiniCPM5-1B to create a standalone Hugging Face model folder for later GGUF conversion:

python finetune/scripts/merge_actor_lora.py

Default merge inputs and output:

  • base model: openbmb/MiniCPM5-1B
  • adapter dir: finetune/minicpm5-actor-lora
  • output dir: finetune/outputs/minicpm5-actor-merged

The script saves the merged model with safe_serialization=True, saves tokenizer files, and writes merge_manifest.json. Use --dtype float16, --dtype bfloat16, or --dtype float32 to control merge dtype.

If local memory is tight, run the Modal merge entrypoint instead. It merges the v0 adapter from /vol/outputs/minicpm5-actor-lora and writes the merged model to /vol/outputs/minicpm5-actor-merged:

modal run finetune/modal_train_actor_lora.py::merge_v0

This step only creates a merged Hugging Face model folder. It does not convert to GGUF, quantize, publish, or integrate the model into the Space.

GGUF Conversion

After merging the v0 Actor LoRA adapter, convert the standalone Hugging Face model folder to GGUF for later llama.cpp testing. Do not commit generated .gguf files; finetune/outputs/gguf/ and *.gguf are gitignored.

Install and build llama.cpp locally on Mac outside this repo, for example as a sibling directory:

cd ..
git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
cmake -B build
cmake --build build --config Release -j
cd ../AI-Puppet-Theater

If you already have llama.cpp somewhere else, set LLAMA_CPP_DIR when running the conversion script.

Make sure the merged model is available locally at:

finetune/outputs/minicpm5-actor-merged

If it was merged on Modal, download it first:

mkdir -p finetune
cd finetune
modal volume get --force ai-puppet-theater-finetune /outputs/minicpm5-actor-merged
cd ..

Convert only to f16 GGUF:

LLAMA_CPP_DIR=../llama.cpp \
MERGED_MODEL_DIR=finetune/outputs/minicpm5-actor-merged \
GGUF_OUT_DIR=finetune/outputs/gguf \
OUTTYPE=f16 \
PYTHON_BIN="uv run --with sentencepiece python" \
bash finetune/scripts/convert_actor_merged_to_gguf.sh convert

This writes:

finetune/outputs/gguf/minicpm5-actor-f16.gguf

Quantize to the default Q4_K_M GGUF:

LLAMA_CPP_DIR=../llama.cpp \
GGUF_OUT_DIR=finetune/outputs/gguf \
OUTTYPE=f16 \
QUANT_TYPE=Q4_K_M \
bash finetune/scripts/convert_actor_merged_to_gguf.sh quantize

This writes:

finetune/outputs/gguf/minicpm5-actor-q4_k_m.gguf

Run conversion and quantization together:

LLAMA_CPP_DIR=../llama.cpp \
PYTHON_BIN="uv run --with sentencepiece python" \
bash finetune/scripts/convert_actor_merged_to_gguf.sh all

For automated GGUF eval, prefer llama-completion with -no-cnv. This local llama.cpp build reports that --no-conversation is not supported by llama-cli and asks callers to use llama-completion for non-interactive one-shot generation.

Quick llama-completion smoke test:

../llama.cpp/build/bin/llama-completion \
  -m finetune/outputs/gguf/minicpm5-actor-q4_k_m.gguf \
  -no-cnv \
  -n 192 \
  --temp 0 \
  --reasoning off \
  --reasoning-budget 0 \
  -p 'SYSTEM: You are an Actor agent in AI Puppet Theater. Return only one valid JSON object. No markdown. No commentary. Keep the puppet line short, theatrical, and speakable.

USER: premise: A moon mayor denies stealing the town last spoon
show_state JSON: {"story_phase":"complication","latest_prop":"silver spoon","finale_requested":false}
actor JSON: {"name":"Mina Moonbutton","mood":"curious","tools":["inspect_prop"]}
director_instruction: Inspect the latest prop and keep the line short.

Return exactly one JSON object with exactly these keys: intent, line, emotion, gesture, stage_effect, memory_update, tool_request. Do not omit stage_effect.

ASSISTANT JSON:'

Run the local GGUF eval harness against the same Actor eval prompts:

python finetune/scripts/eval_actor_gguf.py \
  --llama_bin ../llama.cpp/build/bin/llama-completion \
  --model finetune/outputs/gguf/minicpm5-actor-q4_k_m.gguf \
  --limit 3 \
  --prompt_format simple_json

Run a 10-prompt comparison across supported prompt formats:

python finetune/scripts/eval_actor_gguf.py \
  --llama_bin ../llama.cpp/build/bin/llama-completion \
  --model finetune/outputs/gguf/minicpm5-actor-q4_k_m.gguf \
  --limit 10 \
  --prompt_format auto

Supported GGUF prompt formats are raw, simple_json, chatml, and system_user_assistant. The auto mode runs all of them and prints metrics per format. The eval details are written to:

finetune/eval_outputs/minicpm5_actor_gguf_eval.jsonl

The GGUF eval harness uses the same first-balanced-JSON extraction and Actor JSON sanitizer metrics as the Transformers eval. It uses one-shot command arguments, not interactive stdin. It probes llama-completion --help and passes --reasoning off, --reasoning-budget 0, and stop strings only when the installed binary supports those flags.

For this build, the harness prefers -no-cnv when available and falls back to --no-conversation only if the binary advertises that flag. It prints progress for each row, captures stdout/stderr in the eval JSONL, and records runtime marker diagnostics. If a GGUF output uses tool_request: [], strict tool_request remains false, but the eval sanitizer may convert that empty list to null and count it as sanitization_needed for runtime usability.

If outputs contain [Start thinking], repeated JSON: prefixes, assistant continuations, available commands:, chat template is available, enabling conversation mode, please use llama-completion instead, or interactive prompts like >, treat that as a prompt/template or binary mismatch and compare the prompt formats before judging the merged model itself. --llama_cli remains as a backward-compatible alias for --llama_bin, but llama-cli may enter interactive mode for this model/build and should be used only for manual smoke checks. Do not publish the GGUF until llama.cpp eval is acceptable.

Expected shape:

{"intent":"inspect_prop","line":"This silver spoon squeaks like a guilty witness.","emotion":"investigative","gesture":"leans toward the glowing prop","stage_effect":"prop_table_glow","memory_update":"Noted the silver spoon as evidence.","tool_request":{"tool":"inspect_prop","args":{"prop":"silver spoon"},"reason":"The prop may reveal one concrete stage clue."}}

If conversion fails due to MiniCPM5 architecture or tokenizer support, capture the exact convert_hf_to_gguf.py error. The likely next step is updating to the latest llama.cpp or using an alternate conversion path once MiniCPM5 support is available.

Publishing GGUF

The existing LoRA adapter publisher is separate from GGUF publishing and should not be reused for the quantized llama.cpp artifact. The LoRA publisher uploads adapter files such as adapter_model.safetensors and adapter_config.json; the GGUF path stages the standalone quantized file plus a GGUF-specific model card.

Target GGUF model repo:

build-small-hackathon/AI-Puppet-Theater-MiniCPM5-Actor-GGUF

Prepare a local publish directory without uploading anything:

python finetune/scripts/prepare_gguf_publish.py --clean

Dry-run the publish prep plan:

python finetune/scripts/prepare_gguf_publish.py --dry_run

The prep script creates:

finetune/publish_gguf/
  README.md
  minicpm5-actor-q4_k_m.gguf
  publish_manifest.json
  eval/minicpm5_actor_gguf_eval.jsonl  # if the eval file exists locally

The script does not call Hugging Face APIs and does not run hf upload. When you are ready to publish manually, run:

hf repo create build-small-hackathon/AI-Puppet-Theater-MiniCPM5-Actor-GGUF --type model --public
hf upload build-small-hackathon/AI-Puppet-Theater-MiniCPM5-Actor-GGUF finetune/publish_gguf . --repo-type model --commit-message "Add Q4_K_M GGUF actor model"

After publishing, verify the repo at:

https://huggingface.co/build-small-hackathon/AI-Puppet-Theater-MiniCPM5-Actor-GGUF

Hugging Face Publishing

Publishing scripts are provided for the Actor SFT dataset and current best MiniCPM5 Actor LoRA adapter. They default to dry-run mode and do not upload unless you explicitly pass --no-dry_run with Hugging Face authentication available.

Install or use an environment with huggingface_hub available. It is included in finetune/requirements-train.txt.

Authenticate only when you are ready to upload:

hf auth login

Dry-run the dataset publish plan:

python finetune/scripts/publish_actor_sft_dataset.py --dry_run

Dry-run the adapter publish plan:

python finetune/scripts/publish_actor_lora_adapter.py \
  --adapter_dir finetune/minicpm5-actor-lora \
  --dry_run

The adapter script uploads only the deployable adapter files by default. Checkpoint directories and optimizer state are skipped unless you explicitly pass --include_checkpoints.

Default target repos are placeholders and may need to change based on org permissions:

  • dataset: build-small-hackathon/AI-Puppet-Theater-Actor-SFT
  • model: build-small-hackathon/AI-Puppet-Theater-MiniCPM5-Actor-LoRA

Actual upload commands, when intentionally publishing:

python finetune/scripts/publish_actor_sft_dataset.py \
  --repo_id build-small-hackathon/AI-Puppet-Theater-Actor-SFT \
  --no-dry_run

python finetune/scripts/publish_actor_lora_adapter.py \
  --repo_id build-small-hackathon/AI-Puppet-Theater-MiniCPM5-Actor-LoRA \
  --adapter_dir finetune/minicpm5-actor-lora \
  --no-dry_run

The scripts fail clearly without HF_TOKEN or HUGGINGFACEHUB_API_TOKEN for real uploads. They upload the prepared cards from:

  • finetune/dataset_cards/actor_sft_README.md
  • finetune/model_cards/actor_lora_v0_README.md

After publishing, paste the actual dataset/model URLs into the main Space README. The v0 adapter is currently the best candidate; v1 remains a hardening experiment and tooling path unless a later eval shows it outperforming v0.