diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 18ff4a3..636f093 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -13,6 +13,6 @@ jobs: - name: Install locked dependencies run: | python -m pip install uv - uv sync --locked --extra train + uv sync --locked - name: Offline unit tests and current run evidence - run: uv run --extra train python -m unittest -v + run: uv run python -m unittest -v diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 82c8dca..ef6b4f3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing -Use Python 3.12+ and `uv sync --locked --extra train`. Run +Use Python 3.12+ and `uv sync --locked`. Run `uv run python -m unittest -v` before submitting changes. Follow the [dataset guide](docs/DATASET.md) for the separate data-build and validation steps. diff --git a/README.md b/README.md index 039261a..c743239 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,14 @@ We fine-tuned **Qwen3.5-4B on Together AI** to make decisions: give it context, a question, and 2–24 options, and it returns one answer letter. We're calling -it **tev1-4B-experimental**. A separate blog post will cover the project, how we -fine-tuned it, and what we learned. +it **tev1-4B-experimental**. This repo contains the data recipe, training example, and saved results so you can fine-tune your own decision model. +- [Learn how to train your own classifier for $17](https://www.together.ai/blog/how-to-train-your-own-jev) +- [Full model weights](https://huggingface.co/togethercomputer/Tev1-4B-experimental) + ```text State Returns are allowed within 30 days. This purchase was 12 days ago. Question Is this return within the allowed window? @@ -40,7 +42,7 @@ Requires Python 3.12+ and [uv](https://docs.astral.sh/uv/). Run these commands from the repository root: ```bash -uv sync --locked --extra train +uv sync --locked uv run python fetch_sources.py uv run python build_all.py ``` @@ -54,9 +56,9 @@ for validation, provenance, and how to adapt the recipe. Preview the training settings, then launch when ready: ```bash -uv run --extra train python examples/train_together.py +uv run python examples/train_together.py export TOGETHER_API_KEY='your-key' -uv run --extra train python examples/train_together.py --launch +uv run python examples/train_together.py --launch ``` `--launch` uploads `data/new-v1/instruction/train.jsonl` and `dev.jsonl` and starts diff --git a/docs/TRAINING.md b/docs/TRAINING.md index d688008..c2a0c06 100644 --- a/docs/TRAINING.md +++ b/docs/TRAINING.md @@ -17,8 +17,8 @@ verified export of the historical job's settings. | Early stopping / seed | Disabled / 42 | | Train on inputs | False; completion-only loss | -Install the locked SDK with `uv sync --locked --extra train`. Preview with -`uv run --extra train python examples/train_together.py`; append `--launch` to +Install the locked SDK with `uv sync --locked`. Preview with +`uv run python examples/train_together.py`; append `--launch` to upload and start a billed job. The script waits for both uploaded files to finish processing before submission. It uses the Python SDK directly to set LoRA rank. See Together's [fine-tuning API reference](https://docs.together.ai/reference/post-fine-tunes). @@ -47,23 +47,23 @@ request before calling the endpoint. Inference and hosting have separate charges ## Follow the job and deploy from the CLI -If using a `.env` file, load it explicitly for each command. Use the locked -`train` extra so the Python example and `tg` use the same SDK: +If using a `.env` file, load it explicitly for each command. The Together SDK and `tg` CLI are installed by `uv sync --locked`, so the +Python example and CLI use the same version: ```bash -uv sync --locked --extra train +uv sync --locked cp .env.example .env # Edit .env to set TOGETHER_API_KEY, then preview or launch: -uv run --extra train --env-file .env python examples/train_together.py -uv run --extra train --env-file .env python examples/train_together.py --launch +uv run --env-file .env python examples/train_together.py +uv run --env-file .env python examples/train_together.py --launch ``` Replace `YOUR_JOB_ID` below with the ID printed by that launch. Use the same ID for status and output-model lookup: ```bash -uv run --extra train --env-file .env tg fine-tuning retrieve YOUR_JOB_ID -uv run --extra train --env-file .env tg fine-tuning retrieve YOUR_JOB_ID --json +uv run --env-file .env tg fine-tuning retrieve YOUR_JOB_ID +uv run --env-file .env tg fine-tuning retrieve YOUR_JOB_ID --json ``` Once training completes, copy `model_output_name` from the JSON. In the next @@ -71,7 +71,7 @@ command, replace `MODEL_OUTPUT_NAME` and choose hardware available to your accou that supports your model. Creating the endpoint starts separately billed hosting: ```bash -uv run --extra train --env-file .env tg endpoints create MODEL_OUTPUT_NAME \ +uv run --env-file .env tg endpoints create MODEL_OUTPUT_NAME \ --hardware 1x_nvidia_h100_80gb_sxm --display-name tev1-4B-experimental --wait ``` @@ -89,7 +89,7 @@ model to emit that JSON object. Stop your dedicated endpoint when finished, using its **ID**: ```bash -uv run --extra train --env-file .env tg endpoints stop YOUR_ENDPOINT_ID +uv run --env-file .env tg endpoints stop YOUR_ENDPOINT_ID ``` Training cost and duration vary with settings and provider capacity. The original diff --git a/pyproject.toml b/pyproject.toml index e1bfa57..fb87f28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,9 +5,4 @@ description = "Fine-tune Qwen3.5-4B decision models on Together AI" readme = "README.md" license = "MIT" requires-python = ">=3.12" -dependencies = ["datasets==4.8.5", "transformers==5.17.0", "jinja2>=3.1,<4"] - -[project.optional-dependencies] -train = [ - "together==2.23.0", -] +dependencies = ["datasets==4.8.5", "transformers==5.17.0", "jinja2>=3.1,<4", "together==2.23.0"] diff --git a/test_workflow.py b/test_workflow.py index 924703d..f8ae0c2 100644 --- a/test_workflow.py +++ b/test_workflow.py @@ -38,7 +38,7 @@ def test_sdk_serializes_completion_only_lora_recipe(self): try: from together import Together except ImportError: - self.skipTest('Install the train extra to verify SDK serialization') + self.fail('Run uv sync --locked to install the required Together SDK') client = Together(api_key='fixture') # Intercept submission and model-limits lookup so this test is offline. with patch.object(client.fine_tuning, 'estimate_price', diff --git a/uv.lock b/uv.lock index 1670b3e..4a8739b 100644 --- a/uv.lock +++ b/uv.lock @@ -1583,6 +1583,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/55/db07de81b5c630da5cbf5c7df646580ca26dfaefa593667fc6f2fe016d2e/tabulate-0.10.0-py3-none-any.whl", hash = "sha256:f0b0622e567335c8fabaaa659f1b33bcb6ddfe2e496071b743aa113f8774f2d3", size = 39814, upload-time = "2026-03-04T18:55:31.284Z" }, ] +[[package]] +name = "tev1-4b-experimental" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "datasets" }, + { name = "jinja2" }, + { name = "together" }, + { name = "transformers" }, +] + +[package.metadata] +requires-dist = [ + { name = "datasets", specifier = "==4.8.5" }, + { name = "jinja2", specifier = ">=3.1,<4" }, + { name = "together", specifier = "==2.23.0" }, + { name = "transformers", specifier = "==5.17.0" }, +] + [[package]] name = "together" version = "2.23.0" @@ -1610,30 +1629,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b6/ee/e536dc5a151e1ded20a34f2d21dbbac34ca086d0ccad7158f8da5cdb9d38/together-2.23.0-py3-none-any.whl", hash = "sha256:7490d20ad02f13c776591087669cfdb2c44ad9a3a4da5c4bd7f23c1be1c555d4", size = 435031, upload-time = "2026-07-13T19:56:25.66Z" }, ] -[[package]] -name = "tev1-4b-experimental" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "datasets" }, - { name = "jinja2" }, - { name = "transformers" }, -] - -[package.optional-dependencies] -train = [ - { name = "together" }, -] - -[package.metadata] -requires-dist = [ - { name = "datasets", specifier = "==4.8.5" }, - { name = "jinja2", specifier = ">=3.1,<4" }, - { name = "together", marker = "extra == 'train'", specifier = "==2.23.0" }, - { name = "transformers", specifier = "==5.17.0" }, -] -provides-extras = ["train"] - [[package]] name = "tokenizers" version = "0.23.2"