Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 7 additions & 21 deletions .github/workflows/publish-ollama.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
name: publish-ollama
# Every change to main that touches a Modelfile or an Ollama page is published on ollama.com:
# the changed models are rebuilt and pushed as Tromset/<name>, then the pages are updated from docs/ollama/.
# Needs two repository secrets (Settings > Secrets and variables > Actions):
# OLLAMA_KEY the private key ~/.ollama/id_ed25519 of a machine linked to the Tromset account (`ollama signin`)
# OLLAMA_API_KEY an API key from https://ollama.com/settings/keys
# Every change to main that touches a Modelfile is published on ollama.com:
# the changed models are rebuilt and pushed as Tromset/<name>.
# The model pages are pasted by hand from docs/ollama/: ollama.com refuses page edits made with an API key.
# Needs one repository secret (Settings > Secrets and variables > Actions):
# OLLAMA_KEY the private key ~/.ollama/id_ed25519 of a machine linked to the Tromset account (`ollama signin`)
on:
push:
branches: [main]
paths:
- 'Modelfile*'
- 'docs/ollama/**'
- 'scripts/publish.sh'
- 'scripts/update-ollama-pages.sh'
- '.github/workflows/publish-ollama.yml'
workflow_dispatch:
inputs:
models:
description: 'Models to publish (space-separated names, "all", or "none" for pages only)'
description: 'Models to publish (space-separated names, or "all")'
default: all
concurrency:
group: publish-ollama
Expand All @@ -28,7 +26,6 @@ jobs:
timeout-minutes: 120
env:
OLLAMA_KEY: ${{ secrets.OLLAMA_KEY }}
OLLAMA_API_KEY: ${{ secrets.OLLAMA_API_KEY }}
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -61,10 +58,9 @@ jobs:
echo "Models to publish: $models"
echo "models=$models" >> "$GITHUB_OUTPUT"

- name: Check the secrets
- name: Check the secret
run: |
[ -n "$OLLAMA_KEY" ] || { echo "::error::Add the OLLAMA_KEY secret (contents of ~/.ollama/id_ed25519 from a machine signed in to the Tromset account)."; exit 1; }
[ -n "$OLLAMA_API_KEY" ] || echo "::warning::OLLAMA_API_KEY is not set: the model pages will not be updated."

- name: Free disk space for the base models
if: steps.pick.outputs.models != 'none'
Expand Down Expand Up @@ -96,16 +92,6 @@ jobs:
# shellcheck disable=SC2086
if [ "$MODELS" = all ]; then sh scripts/publish.sh Tromset; else sh scripts/publish.sh Tromset $MODELS; fi

- name: Update the model pages
if: env.OLLAMA_API_KEY != ''
run: |
if sh scripts/update-ollama-pages.sh Tromset; then
echo "Model pages updated from docs/ollama/." >> "$GITHUB_STEP_SUMMARY"
else
echo "::warning::Some ollama.com pages were not updated (see the log). Paste docs/ollama/<model>.md into the page by hand."
echo "Some ollama.com pages were not updated: paste docs/ollama/<model>.md by hand." >> "$GITHUB_STEP_SUMMARY"
fi

- name: Remove the key
if: always()
run: rm -f ~/.ollama/id_ed25519 ~/.ollama/id_ed25519.pub
18 changes: 7 additions & 11 deletions Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,23 +352,19 @@ With one attempt per problem, a gap of one problem is noise; the gap to the firs

## 8. Publishing on ollama.com

Publishing is automatic. On every change to `main` that touches a Modelfile, a page in `docs/ollama/` or the publishing scripts, the [publish-ollama](.github/workflows/publish-ollama.yml) workflow:
Publishing is automatic. On every change to `main` that touches a Modelfile or the publishing script, the [publish-ollama](.github/workflows/publish-ollama.yml) workflow rebuilds the changed models from their Modelfiles and pushes them as `Tromset/flycoder0.3`, `Tromset/flycoder0.3fast`, `Tromset/flycoder0.3pro`, `Tromset/flycoder0.3:lite` and `Tromset/flycoder0.3:router`.

1. rebuilds the changed models from their Modelfiles and pushes them as `Tromset/flycoder0.3`, `Tromset/flycoder0.3fast`, `Tromset/flycoder0.3pro`, `Tromset/flycoder0.3:lite` and `Tromset/flycoder0.3:router`;
2. updates each model page on ollama.com from `docs/ollama/<model>.md`.

It can also be started by hand from the Actions tab (Run workflow), with a list of models or `none` to update only the pages.
It can also be started by hand from the Actions tab (Run workflow), with a list of models or `all`.

One-time setup, in the repository's Settings > Secrets and variables > Actions:

| Secret | Value |
|---|---|
| `OLLAMA_KEY` | the private key `~/.ollama/id_ed25519` of a machine linked to the Tromset account (`ollama signin` on that machine first) |
| `OLLAMA_API_KEY` | an API key created at https://ollama.com/settings/keys, used to update the pages |

Updating a page uses the same request as the page's Edit button; Ollama does not document it. If it is refused, the workflow shows a warning and the page can still be pasted by hand.
The model pages are not published automatically: ollama.com accepts page edits only from a signed-in browser and refuses API keys. After changing `docs/ollama/<model>.md`, open the model's page on ollama.com, click Edit and paste the file.

By hand, from any machine signed in to the account: `sh scripts/publish.sh` (all models) or `sh scripts/publish.sh Tromset flycoder0.3fast` (one model), then `OLLAMA_API_KEY=... sh scripts/update-ollama-pages.sh`.
By hand, from any machine signed in to the account: `sh scripts/publish.sh` (all models) or `sh scripts/publish.sh Tromset flycoder0.3fast` (one model).

For a new version, update the version in `package.json`, `install.sh`, `scripts/publish.sh`, `scripts/publish-hf.sh`, the system prompt of the Modelfiles and the pages. `npm test` checks that they agree.

Expand Down Expand Up @@ -408,7 +404,7 @@ By hand: `pip install huggingface_hub`, then `HF_TOKEN=... sh scripts/publish-hf
| Thinking takes too long | simple question handled in thinking mode | `--think=false` or `/set nothink` |
| Endless repetition | temperature changed to a value that is too low | go back to the Modelfile's settings |
| `npm run bench`: "Reference solution failed" | `python3` or `node` missing, or sandbox refused | `xcode-select --install`, Node 22, or `--no-sandbox` |
| The publish workflow fails at "Check the secrets" | `OLLAMA_KEY` is missing | add it (section 8) |
| The publish workflow fails at "Check the secret" | `OLLAMA_KEY` is missing | add it (section 8) |
| publish-huggingface warns "HF_TOKEN is not set" and publishes nothing | `HF_TOKEN` is missing | add it (section 8.1) |

## 10. Development
Expand All @@ -422,8 +418,8 @@ By hand: `pip install huggingface_hub`, then `HF_TOKEN=... sh scripts/publish-hf
| `brain/flybrain.mjs`, `brain/router.mjs` | FlyBrain server and routing rules |
| `brain/eval-router.mjs`, `tests/fixtures/route-prompts.json` | router accuracy measurement |
| `install.sh` | one-command installer |
| `scripts/publish.sh`, `scripts/update-ollama-pages.sh` | publishing models and pages on ollama.com |
| `docs/ollama/` | the ollama.com pages, one file per model |
| `scripts/publish.sh` | publishing the models on ollama.com |
| `docs/ollama/` | the ollama.com pages, one file per model, pasted by hand |
| `docs/huggingface/`, `scripts/publish-hf.sh` | the Hugging Face model cards and their publisher |
| `bench/bench.mjs`, `bench/problems.mjs` | benchmark and problems |
| `bench/baselines/` | 0.1 profile, for comparison |
Expand Down
4 changes: 2 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Details: [Documentation.md, section 5.5](Documentation.md#55-flybrain-the-router

## Publishing

Every change to `main` that touches a Modelfile or a page in `docs/ollama/` is published on ollama.com by the [publish-ollama](.github/workflows/publish-ollama.yml) workflow: models first, then their pages. It needs two repository secrets, `OLLAMA_KEY` and `OLLAMA_API_KEY` ([Documentation.md, section 8](Documentation.md#8-publishing-on-ollamacom)).
Every change to `main` that touches a Modelfile is published on ollama.com by the [publish-ollama](.github/workflows/publish-ollama.yml) workflow. It needs the repository secret `OLLAMA_KEY` ([Documentation.md, section 8](Documentation.md#8-publishing-on-ollamacom)). The model pages are pasted by hand from `docs/ollama/`.

Each publication is then mirrored on Hugging Face by the [publish-huggingface](.github/workflows/publish-huggingface.yml) workflow: the same GGUF weights, vision projector, system prompt and sampling settings, with a model card from `docs/huggingface/`, under [huggingface.co/Tromset](https://huggingface.co/Tromset). It needs the `HF_TOKEN` secret ([Documentation.md, section 8.1](Documentation.md#81-publishing-on-hugging-face)).

Expand All @@ -72,7 +72,7 @@ Each publication is then mirrored on Hugging Face by the [publish-huggingface](.
- `Modelfile`, `Modelfile.fast`, `Modelfile.pro`: the three variants. `Modelfile.lite`, `Modelfile.router`: FlyBrain's experts.
- `docs/ollama/`: the ollama.com page of each model. `docs/huggingface/`: the Hugging Face model card of each model.
- `brain/`: the FlyBrain server and its routing rules.
- `install.sh`: one-command install. `scripts/publish.sh`, `scripts/update-ollama-pages.sh`, `scripts/publish-hf.sh`: publishing.
- `install.sh`: one-command install. `scripts/publish.sh`, `scripts/publish-hf.sh`: publishing.
- `bench/`: quality and speed benchmark. `tests/`: `npm test`.
- `training/`, `scripts/build_language_dataset.js`, `server/fly-language.js`: the former FlyBrain voice pipeline, independent of FlyCoder.

Expand Down
24 changes: 0 additions & 24 deletions scripts/update-ollama-pages.sh

This file was deleted.

7 changes: 3 additions & 4 deletions tests/modelfile.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,11 @@ test('every published model has a short, up-to-date Ollama page', () => {
}
});

test('the publish workflow runs the publisher and updates every page', () => {
test('the publish workflow runs the publisher with the Tromset key', () => {
const workflow = read('.github/workflows/publish-ollama.yml');
assert.match(workflow, /branches: \[main\]/);
assert.match(workflow, /sh scripts\/publish\.sh Tromset/);
for (const v of VARIANTS.filter(v => v.page)) assert.ok(workflow.includes(v.page.split('/').pop()) || workflow.includes('docs/ollama/'), `workflow uploads ${v.page}`);
for (const secret of ['OLLAMA_KEY', 'OLLAMA_API_KEY']) assert.ok(workflow.includes(`secrets.${secret}`), `workflow uses ${secret}`);
assert.ok(workflow.includes('secrets.OLLAMA_KEY'), 'workflow uses OLLAMA_KEY');
});

test('every published model has a Hugging Face model card and is mirrored by the Hugging Face publisher', () => {
Expand All @@ -117,5 +116,5 @@ test('every published model has a Hugging Face model card and is mirrored by the
});

test('shell scripts parse with POSIX sh', () => {
for (const file of ['install.sh', 'scripts/publish.sh', 'scripts/publish-hf.sh', 'scripts/update-ollama-pages.sh']) execFileSync('sh', ['-n', new URL(`../${file}`, import.meta.url).pathname]);
for (const file of ['install.sh', 'scripts/publish.sh', 'scripts/publish-hf.sh']) execFileSync('sh', ['-n', new URL(`../${file}`, import.meta.url).pathname]);
});
Loading