--- license: gemma base_model: google/gemma-4-31B-it library_name: gguf pipeline_tag: text-generation language: - en tags: - gguf - llama.cpp - unsloth - qlora - gemma - gemma-4 - calendar - scheduling - structured-output - multimodal - vision --- # gemma-4-cal-gguf — a calendar-scheduling fine-tune of Gemma 4 (GGUF) Fine-tuned **Gemma 4 31B Instruct**, quantized to **GGUF / Q4_K_M**, that turns a messy group-chat thread (or a screenshot of a flyer / invite) into a single, constrained **ActionPlan**: the calendar events, a conflict check, proposed alternative times, and a ready-to-send reply. Built to run **fully locally via [llama.cpp](https://github.com/ggml-org/llama.cpp)** — no cloud AI APIs. It powers the **OffGridSchedula** Space: (code: ). ## Files in this repo (both models) | File | Size | What it is | | --- | --- | --- | | `gemma-cal-Q4_K_M.gguf` | ~18.7 GB | The fine-tuned **Gemma 4 31B** LLM, quantized to Q4_K_M. The text model that produces the ActionPlan. | | `mmproj-F16.gguf` | ~1.2 GB | The **vision projector** (multimodal mmproj). Pass it to `llama-server`/`llama-mtmd` with `--mmproj` to accept image input (screenshots, flyers, invites). | Fine-tuning updates only the language model (QLoRA adapters merged in); the vision encoder is left frozen, so the projector is the standard Gemma 4 mmproj — included here so the model + its vision companion load from one place. ## Intended use - **Task:** extract scheduling intent from natural-language chat and images and emit a strict JSON `ActionPlan` (`reasoning`, `events[]`, `conflicts[]`, `proposed_times[]`, `reply_draft`, `needs_clarification`). - **Use case:** a busy parent pastes a class group chat (or snaps a flyer) and gets back the events, a conflict check against their calendar, and a drafted reply — reviewed before anything is saved. - **Out of scope:** general-purpose chat, factual Q&A, code, or anything outside scheduling extraction. It is a small, task-specialized fine-tune. ## How to run ### llama.cpp server (text + vision) ```bash # Downloads both files from this repo on first run. llama-server -hf ParetoOptimal/gemma-4-cal-gguf:Q4_K_M \ --mmproj "$(python -c "from huggingface_hub import hf_hub_download as d; print(d('ParetoOptimal/gemma-4-cal-gguf','mmproj-F16.gguf'))")" \ -ngl 999 -c 8192 --jinja --host 0.0.0.0 --port 8080 ``` Then call its OpenAI-compatible endpoint at `http://localhost:8080/v1` (text, or `image_url` content parts for screenshots). ### In the OffGridSchedula Space Set these Space variables so the app loads this fine-tune instead of the community default: ``` MODEL_HF_REPO = ParetoOptimal/gemma-4-cal-gguf MODEL_QUANT = Q4_K_M MMPROJ_FILE = mmproj-F16.gguf ``` ## Prompt / output format The model is trained to answer with **only** an `ActionPlan` JSON object. A typical user turn: ``` Current datetime: 2026-06-08T09:00:00 Existing calendar: (none provided) Conversation: Room parent: Picture day is Thursday — photos at 9am, wear the green shirt! Me: thanks! Return the ActionPlan JSON now. ``` → ```json { "reasoning": "School picture day Thursday Jun 11 at 9am; wear green shirt.", "events": [{"title": "School picture day", "start": "2026-06-11T09:00:00", "end": null, "location": "School", "attendees": [], "reminder_minutes": 720, "notes": "Wear green class shirt"}], "conflicts": [], "proposed_times": [], "reply_draft": "Got it — green shirt Thursday!", "needs_clarification": null } ``` Conflict detection in the app is done deterministically in Python against the user's calendar; the model proposes alternatives but does not invent the clash math. ## Training - **Base:** `google/gemma-4-31B-it` - **Method:** QLoRA (4-bit) with [Unsloth](https://github.com/unslothai/unsloth), LoRA adapters merged back to 16-bit before GGUF conversion. - **LoRA:** r=16, alpha=16, dropout=0, targets `q,k,v,o,gate,up,down` projections. - **Hyperparameters:** lr=2e-4, 2 epochs, batch 2 × grad-accum 4, max sequence length 4096, bf16. - **Data:** ~69 synthetic `ActionPlan` examples covering school events, carpool, appointments, parties/RSVPs, sports, relative dates, calendar conflicts, multi-event threads, no-event chitchat, ambiguous (needs-clarification) cases, and image-derived events. - **Hardware:** a single A100-80GB on Modal (serverless); `convert_hf_to_gguf.py` + `llama-quantize` for the GGUF export. Reproduce: `training/modal_train.py` in the [project repo](https://github.com/n8mauer/imessage-calendar-agent). ## Limitations & responsible use - Small, synthetic training set → strong on the patterns it has seen; verify dates/times before trusting blindly (the app surfaces everything for review before saving). - Q4_K_M quantization trades some fidelity for size/speed. - English only; assumes the "current datetime" is supplied in the prompt for relative-date math. - Derivative of Gemma 4 — use is subject to Google's [Gemma Terms of Use](https://ai.google.dev/gemma/terms). ## Citation / acknowledgements Base model: Google **Gemma 4**. Tooling: **Unsloth** (training), **llama.cpp** (conversion + inference). Part of the **OffGridSchedula** project.