Safetensors
GGUF
English
Russian
lfm3
reasoning
test-time-compute
inference-time-scaling
code-generation
llama.cpp
negative-results
conversational
Instructions to use HelioAI/LFM3-1.7B-inference-modules-experiments with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use HelioAI/LFM3-1.7B-inference-modules-experiments with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M # Run inference directly in the terminal: llama cli -hf HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M # Run inference directly in the terminal: llama cli -hf HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M # Run inference directly in the terminal: ./build/bin/llama cli -hf HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
Use Docker
docker model run hf.co/HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
- Llama new
- LM Studio
- Jan
- Ollama
How to use HelioAI/LFM3-1.7B-inference-modules-experiments with Ollama:
ollama run hf.co/HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
- Unsloth Desktop
- Pi
How to use HelioAI/LFM3-1.7B-inference-modules-experiments with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use HelioAI/LFM3-1.7B-inference-modules-experiments with Docker Model Runner:
docker model run hf.co/HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
- Lemonade
How to use HelioAI/LFM3-1.7B-inference-modules-experiments with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
Run and chat with the model
lemonade run user.LFM3-1.7B-inference-modules-experiments-Q5_K_M
List all available models
lemonade list
- Hermes Agent
How to use HelioAI/LFM3-1.7B-inference-modules-experiments with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use HelioAI/LFM3-1.7B-inference-modules-experiments with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "HelioAI/LFM3-1.7B-inference-modules-experiments:Q5_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
File size: 6,813 Bytes
67ebcef | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | """Commitment bootstrap: turn truncated (budget-exhausted) reasoning into learning signal.
For every truncated math rollout, the reasoning is cut every --step tokens, thinking is closed by force and the
policy answers greedily. Each cut yields a candidate "stop here" continuation that is graded against the reference:
* the earliest cut whose forced answer is correct -> forced sample with reward 1 ("you could have stopped here")
* the latest cut before it whose answer is wrong -> forced sample with reward 0 ("stopping here is premature")
If no cut is correct, the last wrong cut is added with reward 0. Forced samples join the GRPO group of their prompt,
so advantages are computed against the policy's own full-length attempts.
Writes <out_dir>/forced.jsonl (rollout format, stop_type eos) and <out_dir>/forced_graded.jsonl.
usage: bc_probe.py --rollouts R --graded G --items P --out-dir D [--step 1024]"""
import argparse, json, sys, threading, urllib.request
from concurrent.futures import ThreadPoolExecutor
from transformers import AutoTokenizer
sys.path.insert(0, __file__.rsplit("\\", 1)[0].rsplit("/", 1)[0])
from grade import grade_math # noqa: E402
ap = argparse.ArgumentParser()
for a in ["--rollouts", "--graded", "--items", "--out-dir"]:
ap.add_argument(a, required=True)
ap.add_argument("--step", type=int, default=1024)
ap.add_argument("--stable", type=int, default=1,
help="a cut counts as 'answer known' only if it and the next stable-1 cuts are all correct")
ap.add_argument("--tokenizer", default="models/LFM3-1.7B")
ap.add_argument("--from-probes", default=None, help="probes.jsonl of an earlier run with the same cuts")
ap.add_argument("--unpaired-neg", action="store_true",
help="also add a negative forced stop for rollouts whose answer is never right (unbalances the signal)")
args = ap.parse_args()
tok = AutoTokenizer.from_pretrained(args.tokenizer)
items = {json.loads(l)["id"]: json.loads(l) for l in open(args.items, encoding="utf-8")}
recs = [json.loads(l) for l in open(args.rollouts, encoding="utf-8")]
recs = [r for r in recs if r["truncated"] and items[r["id"]]["task"] == "math" and "tokens" in r]
THINK_END = 124902 # </think>; the model itself closes thinking right after a sentence end: "...}." + </think> + "The"
SUFFIX = "The final answer is $\\boxed{"
suffix_ids = [THINK_END] + tok(SUFFIX, add_special_tokens=False)["input_ids"]
ENDS = set()
for i_ in range(len(tok)):
t_ = tok.convert_ids_to_tokens(i_)
if t_ is not None and (t_.endswith(".") or t_.endswith("\u010a")):
ENDS.add(i_)
def snap(tokens, k, lo):
"""last sentence/paragraph end at or before k (cut right after it), strictly after lo; None if there is none"""
for j in range(k, lo, -1):
if tokens[j - 1] in ENDS:
return j
return None
prompts = {i: tok.apply_chat_template([{"role": "user", "content": items[i]["prompt"]}], tokenize=True,
add_generation_prompt=True, return_dict=False) for i in {r["id"] for r in recs}}
jobs = []
for r in recs:
prev = 0
for k in range(args.step, len(r["tokens"]), args.step):
j = snap(r["tokens"], k, prev)
if j:
jobs.append((r, j))
prev = j
print(len(recs), "truncated math rollouts,", len(jobs), "probes", flush=True)
res = {}
lock = threading.Lock()
def run(job):
r, k = job
body = {"prompt": prompts[r["id"]] + r["tokens"][:k] + suffix_ids, "n_predict": 48, "temperature": 0.0,
"cache_prompt": False, "stop": ["}$", "}\n", "$"]}
try:
out = json.loads(urllib.request.urlopen(urllib.request.Request(
"http://localhost:8080/completion", data=json.dumps(body).encode(),
headers={"Content-Type": "application/json"}), timeout=900).read())["content"]
except urllib.error.HTTPError as e: # e.g. prompt + cut exceeds the slot context: skip this cut
print("probe skipped:", e.code, flush=True)
return
depth, cut = 1, len(out)
for i, ch in enumerate(out):
depth += (ch == "{") - (ch == "}")
if depth == 0:
cut = i
break
pred = out[:cut].strip()
ok = bool(pred) and grade_math("\\boxed{" + pred + "}", items[r["id"]]["answer"])
with lock:
res[(r["id"], r["sample"], k)] = (pred, ok)
if args.from_probes: # reuse saved probe results (no server needed)
for l in open(args.from_probes, encoding="utf-8"):
q = json.loads(l)
res[(q["id"], q["sample"], q["k"])] = (q["pred"], q["ok"])
else:
with ThreadPoolExecutor(32) as ex:
list(ex.map(run, jobs))
with open(f"{args.out_dir}/probes.jsonl", "w", encoding="utf-8") as f:
f.writelines(json.dumps({"id": i, "sample": s_, "k": k, "pred": v[0], "ok": v[1]}) + "\n" for (i, s_, k), v in res.items())
forced, graded, n_pos, n_neg, n_any = [], [], 0, 0, 0
for r in recs:
cuts = sorted(k for (i, s, k) in res if i == r["id"] and s == r["sample"])
oks = [res[(r["id"], r["sample"], k)] for k in cuts]
first_ok = next((j for j in range(len(oks)) if all(ok for _, ok in oks[j: j + args.stable])), None)
picks = []
if first_ok is not None:
n_any += 1
picks.append((cuts[first_ok], 1.0))
wrong_before = [j for j in range(first_ok) if not oks[j][1]]
if wrong_before:
picks.append((cuts[wrong_before[-1]], 0.0))
elif cuts and args.unpaired_neg:
picks.append((cuts[-1], 0.0)) # off by default: 'no answer anywhere' is not a premature-stop signal
for k, rew in picks:
pred = res[(r["id"], r["sample"], k)][0]
tail = [THINK_END] + tok(SUFFIX + pred + "}$", add_special_tokens=False)["input_ids"]
sid = 1000 + r["sample"] * 100 + k // 256
forced.append({"id": r["id"], "task": "math", "sample": sid, "tokens": r["tokens"][:k] + tail,
"stop_type": "eos", "truncated": False, "forced": True, "cut": k, "loss_from": k})
graded.append({"id": r["id"], "task": "math", "sample": sid, "correct": rew, "forced": True})
n_pos += rew == 1.0
n_neg += rew == 0.0
with open(f"{args.out_dir}/forced.jsonl", "w", encoding="utf-8") as f:
f.writelines(json.dumps(x) + "\n" for x in forced)
with open(f"{args.out_dir}/forced_graded.jsonl", "w", encoding="utf-8") as f:
f.writelines(json.dumps(x) + "\n" for x in graded)
print(f"truncated rollouts whose forced answer is right at some cut: {n_any}/{len(recs)}; "
f"forced samples: {n_pos} positive, {n_neg} negative", flush=True)
probe_acc = sum(ok for _, ok in res.values()) / max(1, len(res))
print(f"probe accuracy over all cuts: {probe_acc:.3f}")
|