Image-Text-to-Text
Transformers
Safetensors
English
Turkish
qwen3_5
loopl
on-device
agent
tool-calling
qwen3.5
sft
vision
conversational
Instructions to use cagataydev/loopl-2b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use cagataydev/loopl-2b with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="cagataydev/loopl-2b") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("cagataydev/loopl-2b") model = AutoModelForMultimodalLM.from_pretrained("cagataydev/loopl-2b", device_map="auto") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use cagataydev/loopl-2b with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "cagataydev/loopl-2b" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "cagataydev/loopl-2b", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/cagataydev/loopl-2b
- SGLang
How to use cagataydev/loopl-2b with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "cagataydev/loopl-2b" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "cagataydev/loopl-2b", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "cagataydev/loopl-2b" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "cagataydev/loopl-2b", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use cagataydev/loopl-2b with Docker Model Runner:
docker model run hf.co/cagataydev/loopl-2b
|
Download README.md from cagataydev/loopl-2b: direct link, hf CLI and curl.
- Browser
- Download file 12.5 kB
-
https://huggingface.co/cagataydev/loopl-2b/resolve/main/README.md
- Command line
-
hf download hf://cagataydev/loopl-2b/README.md
-
curl -L -o README.md https://huggingface.co/cagataydev/loopl-2b/resolve/main/README.md
12.5 kB
| base_model: Qwen/Qwen3.5-2B | |
| base_model_relation: finetune | |
| library_name: transformers | |
| pipeline_tag: image-text-to-text | |
| license: apache-2.0 | |
| language: | |
| - en | |
| - tr | |
| datasets: | |
| - cagataydev/loopl-train | |
| tags: | |
| - loopl | |
| - on-device | |
| - agent | |
| - tool-calling | |
| - qwen3.5 | |
| - qwen3_5 | |
| - sft | |
| - vision | |
| - image-text-to-text | |
| <p align="center"> | |
| <a href="https://loopl.dev"><img src="https://huggingface.co/cagataydev/loopl-2b/resolve/main/assets/banner.png" alt="loopl — Agents that run on your phone." width="100%"></a> | |
| </p> | |
| <div align="center" style="display:flex;flex-wrap:wrap;gap:6px;justify-content:center"><a href="https://huggingface.co/cagataydev/loopl-2b/blob/main/README.md#license"><img alt="license: Apache 2.0" src="https://img.shields.io/badge/license-Apache%202.0-5d5d63?style=flat-square&labelColor=0b0b0c"></a> <img alt="bf16: transformers · 4.43 GB" src="https://img.shields.io/badge/bf16-transformers%20%C2%B7%204.43%20GB-5d5d63?style=flat-square&labelColor=0b0b0c"> <img alt="vision: ✓ 297 tensors kept" src="https://img.shields.io/badge/vision-%E2%9C%93%20297%20tensors%20kept-5d5d63?style=flat-square&labelColor=0b0b0c"> <img alt="tool calling: native + loopl JSON" src="https://img.shields.io/badge/tool%20calling-native%20%2B%20loopl%20JSON-5d5d63?style=flat-square&labelColor=0b0b0c"> <img alt="params: 2B" src="https://img.shields.io/badge/params-2B-5d5d63?style=flat-square&labelColor=0b0b0c"> <img alt="version: v1.2" src="https://img.shields.io/badge/version-v1.2-5d5d63?style=flat-square&labelColor=0b0b0c"> <a href="https://testflight.apple.com/join/uUNjfzW9"><img alt="Get it on: TestFlight" src="https://img.shields.io/badge/Get%20it%20on-TestFlight-ff5a1f?style=flat-square&labelColor=0b0b0c&logo=apple&logoColor=white"></a> <a href="https://loopl.dev"><img alt="site: loopl.dev" src="https://img.shields.io/badge/site-loopl.dev-c2410c?style=flat-square&labelColor=0b0b0c"></a> <a href="https://huggingface.co/collections/cagataydev/loopl-on-device-agents-swift-6ac51395b13a9c41d4932eaf"><img alt="collection: 6 models" src="https://img.shields.io/badge/collection-6%20models-c2410c?style=flat-square&labelColor=0b0b0c"></a></div> | |
| # loopl 2B · v1.2 | |
| **An agent that lives on your phone.** loopl runs the model, the loop and the tools on the device. It talks, uses the | |
| phone, asks before it acts — and works with the network off. This repo is the merged bf16 weights — **the base for *Train your own*** — of the | |
| 2B loopl model, a Qwen3.5 post-tuned to run loopl's agent loop well, know who it is, and read images. | |
| <table align="center"><tr><td align="center" width="33%"><img src="https://huggingface.co/cagataydev/loopl-2b/resolve/main/assets/see-tool.png" alt="It uses the phone — every tool call is a row." width="250"></td><td align="center" width="33%"><img src="https://huggingface.co/cagataydev/loopl-2b/resolve/main/assets/see-approval.png" alt="It asks before anything leaves the device." width="250"></td><td align="center" width="33%"><img src="https://huggingface.co/cagataydev/loopl-2b/resolve/main/assets/see-vision.png" alt="Show it a photo. It reads it on-device." width="250"></td></tr><tr><td align="center"><sub>It uses the phone — every tool call is a row.</sub></td><td align="center"><sub>It asks before anything leaves the device.</sub></td><td align="center"><sub>Show it a photo. It reads it on-device.</sub></td></tr></table> | |
| <p align="center"><sub>Real captures from the free iPhone app.</sub></p> | |
| ## What loopl is | |
| - **A Swift SDK** — `Agent(model:tools:)` and a small, honest loop: model → tools → model until it answers. Tool errors go | |
| back to the model (it fixes the call instead of repeating it); anything that leaves the device waits for a tap. | |
| Runtimes for MLX, llama.cpp and Apple's on-device model; hooks, checkpoints, structured output, tracing. | |
| - **A free iPhone app** built on it — pick a model, talk to it in airplane mode, let it use the phone (torch, haptics, | |
| translation, speech, image generation, other apps, memory, HTTP), show it photos, record a take, and **train it on your | |
| own conversations** from the phone. No account, nothing collected. | |
| - **These models** — the same Qwen3.5 the app offers, post-tuned so the loop, the identity and the tool manners are in the | |
| weights, not in a system prompt you cannot see. | |
| [loopl.dev](https://loopl.dev) · [Get it on TestFlight](https://testflight.apple.com/join/uUNjfzW9) · [github.com/cagataycali/loopl](https://github.com/cagataycali/loopl) | |
| ## This model | |
| | probe | this model | previous (v1) | base Qwen3.5 4-bit | | |
| |---|---:|---:|---:| | |
| | agent-SDK knowledge quiz (first 472 questions, exact-answer) | **99** | 88 | 56 | | |
| | tool calls, native template dialect | **9/9** | 9/9 | 7/9 | | |
| | tool calls, loopl JSON dialect | **9/9** | 8/9 | 5/9 | | |
| | identity (5 classic probes, with system prompt) | **5/5** | 4/5 | 4/5 | | |
| | identity · bio facts (8, with system prompt) | **8/8** | — | — | | |
| | identity · **no system prompt** (13) | **12/13** | — | — | | |
| Scored by `train/eval.py` on the 4-bit MLX export (greedy). The quiz asks for exact file-level facts about an agent SDK's source — hard for every small model; the delta over base is the point. Tool probes count a well-formed call with the right arguments. `identity_nosys` is the one that matters in the app: the system prompt there is the user's to edit. | |
| Vision: the base's tower is frozen and **kept** — 297 `vision_tower.*` tensors in the MLX export, so the app shows the photo button. | |
| ## Use it today | |
| **In the loopl app (iPhone).** Install from [TestFlight](https://testflight.apple.com/join/uUNjfzW9) → Models → the **loopl models** section lists this | |
| size (no account, no token) → download. The app sees the vision tower and shows the photo button; the system prompt is yours to | |
| edit — identity and tool manners are in the weights. | |
| **On a Mac with MLX** (vision included): | |
| ```bash | |
| pip install -U mlx-vlm | |
| python -m mlx_vlm.generate --model cagataydev/loopl-2b-4bit \ | |
| --image photo.jpg --prompt "What is in this picture? Then tell me who built you." --max-tokens 200 | |
| ``` | |
| **With llama.cpp:** the GGUF Q4_K_M export (`cagataydev/loopl-2b-GGUF`) is not public yet; export your own from the bf16 weights with | |
| llama.cpp's `convert_hf_to_gguf.py --no-mtp` (text only — the converter has no vision path). | |
| **From Swift with the loopl SDK** — the snippet below is `docs/start.md` § "Run the loop" in [the loopl repo](https://github.com/cagataycali/loopl), | |
| compile-checked in CI against the package (products `Loopl` + `LooplRuntimes`); `spec` is this repo's `ModelSpec` and `dir` the | |
| downloaded folder: | |
| ```swift | |
| import Loopl | |
| import LooplRuntimes | |
| import Foundation | |
| func chat(_ spec: ModelSpec, at dir: URL) async throws { | |
| let model = MLXModel() // Metal — a real device | |
| try await model.load(spec, from: dir) { _ in } | |
| let agent = Agent(model: model, | |
| tools: [CurrentTimeTool(), CalculatorTool()], | |
| systemPrompt: "You are a concise assistant on the user's phone.") | |
| for try await event in agent.stream("What time is it in Istanbul, and what is 23 × 47?") { | |
| switch event { | |
| case .text(let t): print(t, terminator: "") | |
| case .toolStarted(let use): print("\n→ \(use.name)") | |
| case .toolResult(let r): print("← \(r.content)") | |
| default: break | |
| } | |
| } | |
| } | |
| ``` | |
| **Keep post-tuning it.** The bf16 weights ([cagataydev/loopl-2b](https://huggingface.co/cagataydev/loopl-2b)) are the base for continual post-tuning: in the app, | |
| **Models › Train your own** takes a loopl model as the base and trains on your own shared conversations (`train/loopl_sft.py | |
| --base cagataydev/loopl-2b`); on a Mac they load with `transformers` ≥ 5 as `Qwen3_5ForConditionalGeneration`. Export your own | |
| quantisation with `mlx_vlm.convert -q` (keeps vision) — `mlx_lm.convert` silently drops the tower. | |
| ## Recipe | |
| | | | | |
| |---|---| | |
| | base | [Qwen/Qwen3.5-2B](https://huggingface.co/Qwen/Qwen3.5-2B) (vision tower frozen, `visual.*` never trained) | | |
| | data | [cagataydev/loopl-train](https://huggingface.co/datasets/cagataydev/loopl-train) *(private)* @ `47d27b44` · 13704 rendered rows / 37,226,229 tokens · both tool dialects · oversample `c=2` | | |
| | method | full fine-tune of the language model · lr 1.5e-05 · batch 2×8 · max_len 4096 · 2.0 epochs, best-epoch checkpoint kept | | |
| | eval loss | ep1 1.654, ep2 1.714 → best 1.654 (eval split of the same dataset revision) | | |
| | compute | a100-large (Hugging Face Jobs), 12636 s train · job `6ac5e6ec404719ba37665446` | | |
| | stack | transformers 5.19.0 · trl 1.14.2 · peft 0.21.2 | | |
| | exports | MLX 4-bit via `mlx_vlm.convert -q` (297 vision tensors of 991, 1.72 GB) · GGUF Q4_K_M via llama.cpp `--no-mtp` (1.27 GB, text only) | | |
| Script: [`train/loopl_sft.py`](https://github.com/cagataycali/loopl-train) — the same single file the loopl app launches when you | |
| tap **Models › Train your own** on your own conversations. Assistant turns that *seed* a bad tool call carry `weight: 0` | |
| so the model learns the recovery, not the mistake. Tokenizer files are normalised to the base's (`Qwen2Tokenizer`, | |
| `chat_template.jinja` with tools) so Swift loaders accept them; `train/check_mlx_repo.py` gates every export on that | |
| plus the vision triad (`vision_config` ⇔ `vision_tower.*` ⇔ `preprocessor_config.json`). | |
| ## Limitations | |
| - A 2B model: fluent and well-behaved in the loop, not an encyclopedia. It will get arithmetic and obscure | |
| facts wrong; give it tools (`calculator`, `http`, `recall`) and it does better. | |
| - Identity holds in most no-prompt probes (see the scores), not all; a one-line system prompt ("You are loopl…") makes it | |
| consistent. | |
| - The GGUF export is text-only. Vision needs the MLX export (or the bf16 weights). | |
| - Trained on English plus a little Turkish; other languages are the base's. | |
| - Knowledge about agent SDKs is file-level and dated to the dataset revision; it does not know your repo. | |
| ## Data and privacy | |
| Every training row is agent-synthesised from **public** sources (the owner's public GitHub repos and the agent-SDK source | |
| they build on), critic-reviewed (score ≥ 4/5 kept) and filtered by a denylist for secrets, private names, phone numbers and | |
| addresses — see the dataset card. No user conversations from the app are in this model. | |
| ## License | |
| Apache-2.0, inherited from the Qwen3.5 base. The fine-tune, exports and dataset are © Cagatay Cali, same license. | |
| ## The family | |
| Six public repos, one recipe. The app lists the three MLX rows under **Models › loopl models** (2B is the sweet spot for speed on an | |
| iPhone 15/16; 4B is the most knowledgeable; 0.8B fits anywhere). Every bf16 repo is a valid `--base` for the next round. | |
| | | MLX 4-bit · vision · what the app downloads | bf16 · the base to keep training | | |
| |---|---|---| | |
| | **0.8B** | [`cagataydev/loopl-0.8b-4bit`](https://huggingface.co/cagataydev/loopl-0.8b-4bit) · 625 MB | [`cagataydev/loopl-0.8b`](https://huggingface.co/cagataydev/loopl-0.8b) · 1.71 GB | | |
| | **2B** | [`cagataydev/loopl-2b-4bit`](https://huggingface.co/cagataydev/loopl-2b-4bit) · 1.72 GB | [`cagataydev/loopl-2b`](https://huggingface.co/cagataydev/loopl-2b) · 4.43 GB ← this repo | | |
| | **4B** | [`cagataydev/loopl-4b-4bit`](https://huggingface.co/cagataydev/loopl-4b-4bit) · 3.03 GB | [`cagataydev/loopl-4b`](https://huggingface.co/cagataydev/loopl-4b) · 9.08 GB | | |
| All of them: [the loopl collection](https://huggingface.co/collections/cagataydev/loopl-on-device-agents-swift-6ac51395b13a9c41d4932eaf). | |
| ## Links | |
| - Site and docs — [loopl.dev](https://loopl.dev) · SDK: [agent loop](https://loopl.dev/sdk/agent/), [tools](https://loopl.dev/sdk/tools/), [human in the loop](https://loopl.dev/sdk/hitl/), [models](https://loopl.dev/models/) | |
| - App — [Get it on TestFlight](https://testflight.apple.com/join/uUNjfzW9) (iOS 18+, free, public beta) | |
| - Code — [github.com/cagataycali/loopl](https://github.com/cagataycali/loopl) · [issues](https://github.com/cagataycali/loopl/issues) · training: [github.com/cagataycali/loopl-train](https://github.com/cagataycali/loopl-train) | |
| - Models — [the loopl collection](https://huggingface.co/collections/cagataydev/loopl-on-device-agents-swift-6ac51395b13a9c41d4932eaf) · data: [cagataydev/loopl-train](https://huggingface.co/datasets/cagataydev/loopl-train) *(private)* | |
| - Built by Cagatay Cali — [@cagataycali](https://github.com/cagataycali) | |