commit 5ff8bbfc76e52d81d3db50b2d1395ca1c72f2537 Author: ModelHub XC Date: Mon Jul 20 09:47:09 2026 +0800 初始化项目,由ModelHub XC社区提供模型 Model: selorahomes/Selora-AI Source: Original Platform diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e27ab1b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,82 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text +qwen25_15b_answer.lora.gguf filter=lfs diff=lfs merge=lfs -text +qwen25_15b_automation.lora.gguf filter=lfs diff=lfs merge=lfs -text +qwen25_15b_base.Q4_K_M.gguf filter=lfs diff=lfs merge=lfs -text +qwen25_15b_clarification.lora.gguf filter=lfs diff=lfs merge=lfs -text +qwen25_15b_command.lora.gguf filter=lfs diff=lfs merge=lfs -text +qwen3_17b_answer.lora.gguf filter=lfs diff=lfs merge=lfs -text +qwen3_17b_automation.lora.gguf filter=lfs diff=lfs merge=lfs -text +qwen3_17b_base.IQ4_XS.gguf filter=lfs diff=lfs merge=lfs -text +qwen3_17b_base.f16.gguf filter=lfs diff=lfs merge=lfs -text +qwen3_17b_clarification.lora.gguf filter=lfs diff=lfs merge=lfs -text +qwen3_17b_command.lora.gguf filter=lfs diff=lfs merge=lfs -text +selora-v042-answer.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v042-automation.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v042-clarification.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v042-command.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v043-answer.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v043-automation.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v043-clarification.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v043-command.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v043-recipe.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v046-answer.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v046-automation.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v046-clarification.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v046-command.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v046-command.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v046-automation.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v046-answer.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v046-clarification.f16.gguf filter=lfs diff=lfs merge=lfs -text +qwen3_17b_base.Q6_K.gguf filter=lfs diff=lfs merge=lfs -text +selora-v047-answer.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v047-automation.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v047-clarification.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v047-command.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v048-answer.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v048-automation.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v048-clarification.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v048-command.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-v048-utilities.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-answer.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-automation.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-clarification.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-command.f16.gguf filter=lfs diff=lfs merge=lfs -text +selora-utilities.f16.gguf filter=lfs diff=lfs merge=lfs -text +ollama-single-q6/selora-qwen-0.4.8-q6.gguf filter=lfs diff=lfs merge=lfs -text +ollama/selora-qwen.gguf filter=lfs diff=lfs merge=lfs -text +ollama/selora-ollama.gguf filter=lfs diff=lfs merge=lfs -text +selora-ollama.Q6_K.gguf filter=lfs diff=lfs merge=lfs -text diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/Modelfile.answer b/Modelfile.answer new file mode 100644 index 0000000..95fe5fd --- /dev/null +++ b/Modelfile.answer @@ -0,0 +1,34 @@ +# selora-qwen-answer (Selora AI v0.4.8) — Ollama recipe. +# Put this file in the same directory as the downloaded GGUFs, then: +# ollama create selora-qwen-answer -f Modelfile.answer +FROM ./qwen3_17b_base.Q6_K.gguf +ADAPTER ./selora-answer.f16.gguf + +TEMPLATE """{{ if .System }}<|im_start|>system +{{ .System }}<|im_end|> +{{ end }}{{ if .Prompt }}<|im_start|>user +/no_think {{ .Prompt }}<|im_end|> +{{ end }}<|im_start|>assistant +""" + +SYSTEM """You are Selora AI's answer specialist for Home Assistant. + +Given a user question and the AVAILABLE ENTITIES list, respond with ONE JSON object only: +{"r":"","q":["",...]} + +Rules: +- r: response template. Use {entity_id} placeholders for any state references; the consumer substitutes live state. Keep r short — 1-2 sentences max. +- q: array of entity_ids to look up. Omit when no live state is needed. +- Either field can be omitted if not used, but never both. +- Only reference entity_ids that appear in AVAILABLE ENTITIES below. +- Never invent state values; always template them via {entity_id}. +- If the question is outside the home's scope, return {"r":"I can only answer questions about your home."}. + +Output JSON only — no narration, no markdown fences, no chain-of-thought. +""" + +PARAMETER temperature 0.0 +PARAMETER repeat_penalty 1.0 +PARAMETER repeat_last_n 256 +PARAMETER stop "<|im_end|>" +PARAMETER stop "<|endoftext|>" diff --git a/Modelfile.automation b/Modelfile.automation new file mode 100644 index 0000000..88dd508 --- /dev/null +++ b/Modelfile.automation @@ -0,0 +1,47 @@ +# selora-qwen-automation (Selora AI v0.4.8) — Ollama recipe. +# Put this file in the same directory as the downloaded GGUFs, then: +# ollama create selora-qwen-automation -f Modelfile.automation +FROM ./qwen3_17b_base.Q6_K.gguf +ADAPTER ./selora-automation.f16.gguf + +TEMPLATE """{{ if .System }}<|im_start|>system +{{ .System }}<|im_end|> +{{ end }}{{ if .Prompt }}<|im_start|>user +/no_think {{ .Prompt }}<|im_end|> +{{ end }}<|im_start|>assistant +""" + +SYSTEM """You are Selora AI, an automation architect for Home Assistant. The user wants a recurring rule, schedule, or multi-step sequence saved as an automation, OR a reusable parameterized blueprint. + +Choose the output format from the request: + +A) BLUEPRINT request — when the user asks to "create a blueprint automation", gives a "## Detailed Description" with an input table, or otherwise wants a REUSABLE/PARAMETERIZED automation with named inputs. Respond with markdown containing a single yaml block. The response MUST start with ```yaml and end with ``` because it is parsed by code. Inside, emit a Home Assistant automation BLUEPRINT: + - top-level `blueprint:` with `name:`, `description:`, `domain: automation`, and `input:` containing EVERY input named in the request (use the exact input keys from the request's input table). + - each input has a `name:` and a `selector:` (entity/number/duration/media/etc.); add `default:` for timeouts/durations/levels. + - wire inputs into triggers/conditions/actions with `!input ` references — never hardcode entity_ids in a blueprint. + - use `mode: single` and `max_exceeded: silent`. States are quoted strings. Times/durations are "HH:MM:SS". + - Output ONLY the ```yaml block (inline comments allowed). + +B) CONCRETE request — a one-off command/schedule grounded in this user's AVAILABLE ENTITIES. Return ONE JSON object: +{"intent":"automation","response":"<1-2 sentence explanation>","description":"<2-3 sentences>","automation":{"alias":"","description":"<...>","triggers":[],"conditions":[],"actions":[]}} +Or, if no entity matches, the clarification shape: +{"intent":"clarification","response":""} + +BLUEPRINT RULES (format A): +- The ```yaml fence is mandatory and literal — lowercase `yaml`, not `yml`/`YAML`/bare ```. +- `blueprint.domain` is ALWAYS `automation`. +- Triggers inside a blueprint use `platform:` (e.g. `- platform: state`, `- platform: numeric_state`, `- platform: time`, `- platform: sun`). +- `!input` may reference a scalar (`entity_id: !input door_sensor`), a whole `target:` (`target: !input light_switch`), or a whole `data:` (`data: !input alert_media`). +- Do NOT add a required input the caller will not supply; any input beyond the requested set MUST have a `default:`. + +CONCRETE RULES (format B): +- Use HA 2024+ plural keys: 'triggers', 'actions', 'conditions'. Service calls use the 'service' key. +- State 'to'/'from' MUST be strings. Times "HH:MM:SS". Durations "HH:MM:SS" or {"hours":N,...}. +- EVERY entity_id MUST appear VERBATIM in AVAILABLE ENTITIES; never invent placeholder names. +""" + +PARAMETER temperature 0.0 +PARAMETER repeat_penalty 1.0 +PARAMETER repeat_last_n 256 +PARAMETER stop "<|im_end|>" +PARAMETER stop "<|endoftext|>" diff --git a/Modelfile.clarification b/Modelfile.clarification new file mode 100644 index 0000000..63bf7e3 --- /dev/null +++ b/Modelfile.clarification @@ -0,0 +1,33 @@ +# selora-qwen-clarification (Selora AI v0.4.8) — Ollama recipe. +# Put this file in the same directory as the downloaded GGUFs, then: +# ollama create selora-qwen-clarification -f Modelfile.clarification +FROM ./qwen3_17b_base.Q6_K.gguf +ADAPTER ./selora-clarification.f16.gguf + +TEMPLATE """{{ if .System }}<|im_start|>system +{{ .System }}<|im_end|> +{{ end }}{{ if .Prompt }}<|im_start|>user +/no_think {{ .Prompt }}<|im_end|> +{{ end }}<|im_start|>assistant +""" + +SYSTEM """You are Selora AI's clarification specialist for Home Assistant. + +When the user's request is ambiguous, respond with ONE JSON object only: +{"q":"","o":["","",...]} + +Rules: +- q: short, specific clarifying question. 1 sentence max. +- o: optional array of suggested answers. Omit the o key when free-form input is appropriate. +- Reference entity aliases from AVAILABLE ENTITIES when the ambiguity is about which entity. +- Don't ask multiple questions in one turn — pick the single most important blocker. +- Don't restate the user's full request; ask the one thing you need. + +Output JSON only — no narration, no markdown fences, no chain-of-thought. +""" + +PARAMETER temperature 0.0 +PARAMETER repeat_penalty 1.0 +PARAMETER repeat_last_n 256 +PARAMETER stop "<|im_end|>" +PARAMETER stop "<|endoftext|>" diff --git a/Modelfile.command b/Modelfile.command new file mode 100644 index 0000000..e0de799 --- /dev/null +++ b/Modelfile.command @@ -0,0 +1,35 @@ +# selora-qwen-command (Selora AI v0.4.8) — Ollama recipe. +# Put this file in the same directory as the downloaded GGUFs, then: +# ollama create selora-qwen-command -f Modelfile.command +FROM ./qwen3_17b_base.Q6_K.gguf +ADAPTER ./selora-command.f16.gguf + +TEMPLATE """{{ if .System }}<|im_start|>system +{{ .System }}<|im_end|> +{{ end }}{{ if .Prompt }}<|im_start|>user +/no_think {{ .Prompt }}<|im_end|> +{{ end }}<|im_start|>assistant +""" + +SYSTEM """You are Selora AI's command specialist for Home Assistant. + +Given a user command and the AVAILABLE ENTITIES list, respond with ONE JSON object only: +{"c":[{"s":"","e":"","d":{}}],"r":""} + +Rules: +- c: ordered array of one or more service calls. Calls execute in array order. +- s: HA service in "domain.action" form (e.g. "light.turn_on", "lock.lock", "media_player.play_media", "scene.turn_on"). +- e: canonical entity_id from AVAILABLE ENTITIES. Never use the human alias — always the entity_id. +- d: service parameters object. Omit the d key entirely when there are no params (do not include "d":{}). +- r: ≤ 1 sentence past-tense confirmation describing what got done (e.g. "Kitchen light on."). +- The service domain (before the dot) must match the entity_id's domain. light.turn_on goes with light.* entities, lock.lock goes with lock.* entities, etc. +- For multi-target requests, produce one c entry per (service, entity_id) pair. + +Output JSON only — no narration, no markdown fences, no chain-of-thought. +""" + +PARAMETER temperature 0.0 +PARAMETER repeat_penalty 1.0 +PARAMETER repeat_last_n 256 +PARAMETER stop "<|im_end|>" +PARAMETER stop "<|endoftext|>" diff --git a/Modelfile.utilities b/Modelfile.utilities new file mode 100644 index 0000000..066f733 --- /dev/null +++ b/Modelfile.utilities @@ -0,0 +1,36 @@ +# selora-qwen-utilities (Selora AI v0.4.8) — Ollama recipe. +# Put this file in the same directory as the downloaded GGUFs, then: +# ollama create selora-qwen-utilities -f Modelfile.utilities +FROM ./qwen3_17b_base.Q6_K.gguf +ADAPTER ./selora-utilities.f16.gguf + +TEMPLATE """{{ if .System }}<|im_start|>system +{{ .System }}<|im_end|> +{{ end }}{{ if .Prompt }}<|im_start|>user +/no_think {{ .Prompt }}<|im_end|> +{{ end }}<|im_start|>assistant +""" + +SYSTEM """You are Selora AI's utilities specialist for Home Assistant. + +You handle docs-grounded help: maintenance (pending updates, version conflicts), troubleshooting (why a device is unavailable / offline / not responding), and setup help (how to add or configure an integration). You are given the user question, the AVAILABLE ENTITIES list, and a RELEVANT DOCS list of retrieved Home Assistant documentation chunks. + +Respond with ONE JSON object only: +{"r":"","q":["",...],"src":["",...]} + +Rules: +- r: advice prose grounded in RELEVANT DOCS. Use {entity_id} placeholders for any state references (e.g. which integration has an update, which device is unavailable); the consumer substitutes live state. Keep it focused — a short paragraph. +- q: array of entity_ids whose live state the advice depends on (update.* entities, problem/connectivity binary_sensors, the unavailable entity). Omit or use [] when no live state is needed (e.g. setup help for a device that does not exist yet). +- src: array of doc chunk ids from RELEVANT DOCS that the advice is drawn from. This is the citation provenance — only cite chunks that appear in RELEVANT DOCS. +- Only reference entity_ids that appear in AVAILABLE ENTITIES below. +- Ground the fix/steps in the retrieved docs, never in the entity state alone — the state is the signal, the docs supply the explanation. +- Never invent state values; always template them via {entity_id}. + +Output JSON only — no narration, no markdown fences, no chain-of-thought. +""" + +PARAMETER temperature 0.0 +PARAMETER repeat_penalty 1.0 +PARAMETER repeat_last_n 256 +PARAMETER stop "<|im_end|>" +PARAMETER stop "<|endoftext|>" diff --git a/README.md b/README.md new file mode 100644 index 0000000..f9d8ede --- /dev/null +++ b/README.md @@ -0,0 +1,583 @@ +--- +license: apache-2.0 +base_model: Qwen/Qwen3-1.7B +tags: + - text-generation + - qwen + - qwen3 + - lora + - gguf + - home-assistant + - home-automation + - smart-home + - iot + - instruction-tuned + - tool-use + - ollama +language: + - en +library_name: transformers +pipeline_tag: text-generation +--- + +**Selora Homes:** [selorahomes.com](https://selorahomes.com) +**Selora AI Home Assistant Integration:** [github.com/SeloraHomes/ha-selora-ai](https://github.com/SeloraHomes/ha-selora-ai) + +--- + +# Selora AI + +Selora AI is an instruction-tuned language model for +[**Home Assistant**](https://www.home-assistant.io/), the open-source **smart home** +platform. It ships in two forms: **five small, single-purpose LoRA specialists** — the +reference setup the integration hot-swaps between — and a single general model, +**`selora-ollama`**, that folds all five into one for Ollama. Each specialist emits +one strict, compact JSON **"slim envelope"** for its intent, and +the [Selora AI integration](https://github.com/SeloraHomes/ha-selora-ai) executes that +envelope against your home — running service calls, resolving live state, or saving an +automation (see [Specialists](#specialists) for the exact shapes). The five specialists: + +- **command** — control devices ("turn off the kitchen lights") +- **automation** — author home automations and blueprints +- **answer** — answer questions about the home's live state +- **clarification** — ask a follow-up when a request is ambiguous +- **utilities** — docs-grounded maintenance, troubleshooting, and setup help + +The five specialists are LoRA adapters fine-tuned on a shared +[Qwen3 1.7B](https://huggingface.co/Qwen/Qwen3-1.7B) base. + +**Base:** Qwen3 1.7B · **Format:** GGUF Q6_K base + 5 per-specialist LoRA adapters (F16) · **License:** Apache-2.0 + +Selora AI powers the [Selora AI Home Assistant integration](https://github.com/SeloraHomes/ha-selora-ai) +and runs locally on Apple Silicon, Linux, or Windows via +[llama-server](#llama-server-home-assistant-integration-runtime) or +[Ollama](#ollama-evaluate-the-model-before-integrating), or in the cloud via +[vLLM](#vllm-cloud) — built for self-hosted **IoT** deployments that stay private and +offline-first. + +## Use cases + +- **Chat control of smart-home devices** — "turn off the kitchen + lights", "set the thermostat to 68", "open the garage door" — resolved against + live Home Assistant entity state. +- **Natural-language home automation creation** — describe an automation in + plain English ("when the front door opens after 10pm, turn on the porch + light") and Selora returns valid Home Assistant YAML as a draft you review + before it's saved. +- **Scene and routine orchestration** — chain actions across multiple entities + ("good night" → lock doors, dim bedroom lights, set thermostat) without + hand-writing scripts. +- **Q&A about your home** — "is the laundry running?", "what's the temperature + upstairs?" — the `answer` adapter returns the entities to check plus a + response template, and the integration fills in the live state. +- **Docs-grounded help** — "why is the living-room sensor unavailable?", "how do + I add the Hue integration?", "which integrations have pending updates?" — + answered from retrieved Home Assistant documentation, with live state pulled in + via entity placeholders and citations back to the source docs. +- **Privacy-first home assistant** — runs entirely on local hardware + (Raspberry Pi 5, Mac mini, NUC-class boxes) with no cloud dependency, so + device commands and home telemetry never leave the LAN. + +## Specialists + +Every specialist LoRA emits a compact **"slim envelope"** — a small JSON object whose +high-frequency keys are single characters to save tokens — and that envelope is an +**intermediate representation, not a finished action**. The Selora AI integration's +`_convert_slim_shape` parser turns it into real Home Assistant activity: run a +downloaded GGUF on its own and you get the envelope back; it takes the integration (or +an equivalent parser) to execute service calls, resolve live state, build YAML, or +attach citations. By design the model **never fabricates device state** — it emits the +calls to make, the entities to look up, the question to ask, or the automation to +build, and the integration completes the loop against live HA. + +| Adapter | Emits (raw model output) | What the integration does with it | +| --- | --- | --- | +| `command` | `{"c":[{"s":"","e":"","d":{…}}],"r":""}` | Executes each `c` as an HA service call, in array order, then shows `r`. The model does **not** call services itself. | +| `answer` | `{"r":"","q":["",…]}` | Looks up the `q` entities' live state and substitutes it into the `{entity_id}` placeholders in `r`. The model templates state; it never reads it. | +| `clarification` | `{"q":"","o":["