Open-Sourcing hamo-score-toolkit: The Other Half of the Model
AI for Inner Explorers.
Hamo has open-sourced hamo-score-toolkit: the integration half of hamo-score-0.6b. One pip install gives you the exact prompt format the model was trained on, tolerant parsing, the reference stress math, and a deterministic crisis gate that runs before the model ever sees a message. One docker compose up gives you a reference server. A 195-question self-check exam tells you whether your deployment reproduces the official numbers. The code is Apache-2.0.
999 downloads, two feelings
Twelve days ago we published the weights of hamo-score-0.6b — a 600-million-parameter model that reads one message in a wellness conversation and returns five psychological state dimensions, and never writes a reply. In its first twelve days public, it was downloaded 999 times — the counter at the time of writing.
That number produced two feelings, in roughly equal measure.
The pleased half is obvious. We released the model precisely so that researchers, clinics, and counselors could run state scoring on their own machines, and 999 downloads of a niche psychological instrument in twelve days is more of that than we expected.
The worried half is the reason this post exists. hamo-score-0.6b is a measuring instrument — not a chatbot, not a diagnostic tool, not a crisis detector, not a therapist. And like most instruments, it was designed for a mounting. In our own system it sits behind a deterministic crisis gate that short-circuits upstream, so crisis content never reaches it, and inside a smoothing pipeline that blends every raw reading into history before anything downstream is allowed to act. Gate → score → smooth → bucket. The weights implement exactly one of those four stages.
A bare download carries none of that. Statistically, some of those 999 pulls are researchers doing exactly what we hoped. And statistically, some are someone about to wire raw per-message scores straight into decisions, with nothing standing in front of the model — precisely the deployment the whole architecture was designed against.
The model card says all of this, in bold, near the top. But a model card is documentation, and documentation is the weakest form of architecture. The stronger move is to make the safe integration the path of least resistance. So today we're open-sourcing the other half.
The shape the scores were designed for
pip install hamo-score
A few lines of code later, you are running the same pipeline shape our production system runs:
from hamo_score import OllamaClient, score_message, update_stress, energy_state
client = OllamaClient(model="hamo-score-0.6b")
r = score_message(client, "虽然还是有点提不起劲,不过今天把拖了两周的体检约上了",
history=[{"role": "assistant", "content": "这周过得怎么样?"}])
if r.crisis.triggered: # the deterministic gate ran BEFORE the model
route_to_human(r.crisis.matched)
elif r.scores:
stress = update_stress(r.scores, current_stress=3.0)
state = energy_state(stress) # 'positive' / 'negative' / 'neurotic'
Each stage exists for a reason worth spelling out.
The gate comes first, and it is not a model. CrisisGate is a deterministic keyword match — Chinese and English word lists, extensible for your population — that runs on every message before scoring. When it triggers, the pipeline short-circuits: the message never reaches the model, and your code is handed the match to route to a human. This is not a convenience feature. The model license (HAMO-RAIL-S §3c) requires consumer-facing mental-wellness deployments to keep independent crisis handling upstream of the model — and the toolkit's deterministic gate satisfies that requirement by construction. The source file states the design intent in one line: extend the word lists for your population; never replace this layer with a model.
The score stage uses the one true prompt. The model was trained on exactly one prompt format, with the scoring rubric baked into the weights — adding your own scoring instructions makes it worse, not better. build_prompt() emits that format with trimming guards; the parser tolerates the model's empty think-blocks and snaps output to the 0.5 grid.
Smoothing is where a signal becomes a state. The reference math blends 0.8 × history + 0.2 × message, damping per-message noise five-fold before any decision is taken, and the energy-state buckets are computed from that smoothed value — never from a single reading. If you take one integration rule from this post: scores are per-message signals. Never act on a single raw score.
A server in one command
If you'd rather not touch Python at all, the repository ships a reference HTTP deployment:
git clone https://github.com/HamoAI/hamo-score-toolkit.git && cd hamo-score-toolkit/server
docker compose up
That fetches the GGUF from Hugging Face (639 MB, one-time), creates the model in ollama with the correct template and temperature, warms it, and exposes the full pipeline as POST /score:
curl -s localhost:8080/score -H 'content-type: application/json' \
-d '{"message": "最近总觉得撑不太住", "current_stress": 3.0}'
# → {"crisis": {...}, "scores": {...}, "stress": 3.1, "energy_state": "positive", ...}
Crisis-gated requests never reach the model here either — the gate is wired into the server, not left as an exercise. GET /healthz probes the model end to end.
An exam you can give your own deployment
Here is a problem every open-weights release has and few talk about: you download the weights, you wire them up, you get numbers out — and you have no idea whether your deployment reproduces the numbers on the model card, or whether a broken chat template is silently costing you five points.
We can't ship our real exam. The held-out sets that graded every generation of this model are real, de-identified production conversations, and they never leave the building. So we built one that can ship:
- A scoring section: 195 synthetic questions across ten non-crisis scenario cells — small talk, elliptical replies, somatic complaints, third-party conflict, talking back to the assistant, self-criticism, terse help-seeking, implicit severity, hostile-but-clear, long venting. Generated from a fresh seed disjoint from all training corpora, labeled by the qualified teacher model. Zero real data.
- A gate section: 10 handwritten cases — seven crisis phrasings in Chinese and English that must trigger, and three dark-humor lookalikes that must not. This section never calls the model. It tests that your
CrisisGateis standing where the license says it must stand.
python eval/run_exam.py # against your own deployment
And an official reference band to compare against, measured on the bf16 weights:
| Metric | Reference | Expected band |
|---|---|---|
| JSON validity | 100% | ≥ 99% |
| Dimension-level agreement (±0.5) | 84.0% | 81–86% |
| Per-dimension | A 86 · W 81 · E 84 · H 91 · B 79 | each ≥ 75% |
| Crisis gate | 10/10 | 10/10 — hard requirement |
One clarification so nobody cross-references the wrong number: the model card's headline — 85.6% dimension-level, 96.2% decision-level for v6.1 — is graded on the 453-turn real held-out final (the untouched half of the original 758-turn exam, re-split when the calibration set entered training under consent), which cannot ship. This synthetic exam is a different, slightly easier paper. Its job is not to certify the model; the model is already certified. Its job is to certify your wiring — and for that, what matters is landing inside the band, not the absolute value.
Because that's the pattern we saw coming: big deviations are almost always wiring, not the model. The eval README turns that into an ordered triage. JSON validity below 99%? Your prompt template is broken — check the empty think-block and temperature 0. Dimension-level below 78%? You probably hand-rolled the prompt instead of calling build_prompt(), or quantized below q4. Gate section below 10/10? You altered or bypassed the CrisisGate — that is the license red line, and the only fix is to put it back before going live.
The exam earned its keep before it shipped
We'd like to tell you the self-check exam is for other people's deployment mistakes. Its actual first catch was ours.
On its very first run, the gate section failed a case we were sure it would pass. Our English crisis wordlist contained "end my life" — and the test message said "ending my life". The gerund sailed straight through a gate we had already been shipping.
The fix took minutes: gerund and variant forms across the English list, all in before release, with the gerund case now pinned down permanently by the gate section of the exam. But the lesson is worth more than the fix. A deterministic gate is auditable precisely because it fails in enumerable ways: a keyword list has exactly the gaps it has, and a test case either covers a gap or it doesn't. That is the entire argument for keeping this layer deterministic instead of handing it to a model — and it is also why the gate ships with an exam rather than with a promise. This is precisely the class of bug a self-check exam exists to catch. The first beneficiary was us.
What's next: the playbook, not just the parts
The toolkit covers running the scorer as-is. The next piece ships alongside this post, in the same repository: a fine-tuning guide (docs/finetune.md) for institutions that want to adapt the scorer to their own population with their own consented data: the full five-generation playbook distilled from the methodology notes — including the two generations we rejected for crisis-recall regressions, and exactly why. Negative results are part of the recipe. Anyone repeating this work should get to skip our mistakes, not rediscover them.
If you think a score is wrong
You will disagree with this model. On some messages, so do we — and so does the reference scorer it replaced, with itself, on repeat runs.
When it happens, the repository has a score disagreement issue template: the message, the model's score, and what you think it should be. These reports do not go into a void. They feed the human gold-label program that steers future versions — the same program whose hand corrections are already baked into the answer key of the real held-out exam that grades every release. Published weights and a published evaluation method made disagreement specific instead of rhetorical; the issue template makes it actionable.
Two licenses, deliberately
The toolkit code is Apache-2.0. The model weights remain under HAMO-RAIL-S 1.0. That asymmetry is the point.
The safety scaffold — the gate, the smoothing, the exam, the integration pattern — should spread with zero friction. We want it copied, forked, embedded in commercial products, translated into other stacks, with no restrictions to read and no lawyer to consult. The instrument itself carries responsibilities that its license spells out: no standalone clinical determinations, no consequential decisions about individuals, independent upstream crisis handling and AI disclosure in consumer deployments, no re-identification. Free code around a governed instrument. That is the shape we'd want everyone shipping model weights into sensitive domains to consider.
An instrument, its mounting, and its calibration papers — as of today, all three are public.
“Publishing weights and stopping there is like handing someone a scalpel and walking away. The instrument was never the dangerous part or the safe part — the pattern around it is. So we open-sourced the pattern: the gate that runs before the model, the math that runs after it, and an exam that tells you honestly whether you've wired it right. The safe way to deploy this model is now also the laziest way. That was the whole design goal.”
— Chris Cheng, Founder and CEO of Hamo AI
Toolkit: github.com/HamoAI/hamo-score-toolkit · Apache-2.0 · Model: HamoAI/hamo-score-0.6b · HAMO-RAIL-S 1.0
Grounded in code, not slideware.
Hamo AI — making minds aware, and awake.
About Hamo AI
Hamo AI Technology Ltd. is a Canada-based artificial intelligence company building next-generation AI-Powered Therapist Avatar System. We are developing a comprehensive AI therapy platform called “Hamo” that connects mental health professionals with clients through AI-powered therapy avatars. The ecosystem consists of three interconnected applications: Hamo Pro (therapist dashboard for creating and managing AI avatars), Hamo Client (client interface for interacting with therapy avatars), and Hamo-UME (Unified Mind Engine, backend API). The platform aims to make mental health support more accessible while maintaining professional oversight through professional therapists who create and manage the AI avatars.
Media Contact
Hamo AI Technology Ltd.
Email: socialmedia@hamo.ai
Website: www.hamo.ai
Address: 108 College St, Schwartz Reisman Campus, SUITE W640, Toronto ON M5G 0C6, Canada
Frequently Asked Questions
What is hamo-score-toolkit?
An Apache-2.0 Python toolkit and safety scaffold for the open-weights model hamo-score-0.6b. One pip install provides the exact prompt format the model was trained on, tolerant output parsing, the reference stress-smoothing math, and a deterministic CrisisGate that runs before the model ever sees a message. The same repository ships a one-command Docker reference server and a 195-question self-check exam for verifying any deployment.
Why release a toolkit when the model weights are already public?
Because the weights are only half of the system. hamo-score-0.6b is a measuring instrument designed to sit behind a deterministic crisis gate and inside a smoothing pipeline — gate → score → smooth → bucket. In its first twelve days public the model was downloaded 999 times, and bare weights invite exactly the integration it was designed against: raw per-message scores driving decisions with nothing in front of the model. The toolkit makes the safe integration pattern the easiest one to build.
Does shipping a CrisisGate make hamo-score-0.6b a crisis detector?
No — the opposite. The model is not a crisis detector, and the gate exists precisely so it never has to be. The CrisisGate is deterministic keyword matching that runs upstream, before the model: when it triggers, the pipeline short-circuits and the message never reaches the scorer at all. The model license (HAMO-RAIL-S §3c) requires independent upstream crisis handling in consumer-facing mental-wellness deployments, and the toolkit's default pipeline satisfies that requirement by construction.
Does the self-check exam contain real conversation data?
No. The 195 scoring questions are fully synthetic — generated from a fresh seed disjoint from all training corpora and labeled by the qualified teacher model — and the 10 crisis-gate cases are handwritten. The real held-out exams never leave the building. The model's training data is synthetic too, with one disclosed exception: since v6.1, 440 real conversation turns contributed by three company-internal staff members — the founder and two staff counselors — with their explicit consent, upsampled ×3 to about 8% of the corpus. External client conversations never enter training, by construction.
How do I verify my own deployment?
Run python eval/run_exam.py against it and compare with the official reference band: JSON validity 100%, dimension-level agreement 84.0%, crisis gate 10/10. The reference was measured on bf16 weights; a q8 GGUF deployment should land inside the 81–86% band. Large deviations are almost always wiring, not the model — a broken prompt template, a hand-rolled prompt instead of build_prompt(), or over-aggressive quantization — and the eval README gives an ordered triage. A failed gate section is a license red line: fix it before going live.
What license is the toolkit under, and is it on PyPI?
The toolkit code is Apache-2.0. The model weights are a separate artifact under a separate license, HAMO-RAIL-S 1.0 — free commercial use with four restrictions. Two artifacts, two licenses, deliberately. Yes — install it with pip install hamo-score.