Text Generation
LiteRT-LM
English
custom
hermes-edge
mobile-ai
on-device
ios
iphone-16
apple-neural-engine
deepseek
dspark
speculative-decoding
hermes-agent
tool-calling
raven-ecosystem
Instructions to use bclermo/hermes-edge with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT-LM
How to use bclermo/hermes-edge with LiteRT-LM:
# LiteRT-LM runs on various platforms (Android, iOS, Windows, Linux, macOS, IoT, Web/WASM) # and supports many APIs (C++, Python, Kotlin, Swift, JavaScript, Flutter). # For platform-specific integration guides, please refer to the official developer website: # https://ai.google.dev/edge/litert-lm # To try LiteRT-LM, the easiest way is to use our CLI tool. # 1. Install the LiteRT-LM CLI tool: pip install -U litert-lm # 2. Download and run this model locally: # See: https://ai.google.dev/edge/litert-lm/cli litert-lm run \ --from-huggingface-repo=bclermo/hermes-edge \ --prompt="Write me a poem"
- Notebooks
- Google Colab
- Kaggle
File size: 6,087 Bytes
0b1f228 | 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | """
LiteRT-LM Model Wrapper — Python interface for .litertlm models
Wraps the LiteRT-LM C++ runtime via ctypes, providing a Pythonic
interface for inference, tokenization, and agent integration.
On actual devices, this is replaced by the Swift/Kotlin SDK.
This Python wrapper is used for:
- Desktop testing and debugging
- HF Space demos (via Python backend)
- CI validation of model bundles
Usage:
from hermes.litert_model import LiteRTModel
model = LiteRTModel("dist/hermes-mobile.litertlm")
model.load()
response = model.generate("Hello!", max_tokens=128)
print(response)
"""
import json
import logging
import os
import subprocess
import tempfile
from pathlib import Path
log = logging.getLogger(__name__)
class LiteRTModel:
"""
Wrapper around a .litertlm model bundle.
Uses the `litert-lm` CLI tool for inference (since the Python C++
binding requires libvulkan which isn't available in all environments).
On iOS/Android, the native SDK replaces this class entirely.
"""
def __init__(self, model_path: str, cli_path: str = "litert-lm"):
self.model_path = Path(model_path).resolve()
self.cli_path = cli_path
self.vocab_size = 32000
self.tokenizer = None
self._loaded = False
self._metadata: dict = {}
def load(self) -> bool:
"""Validate the model file and extract metadata."""
if not self.model_path.exists():
log.error("Model not found: %s", self.model_path)
return False
with open(self.model_path, "rb") as f:
header = f.read(16)
if header[:8] != b"LITERTLM":
log.error("Invalid model file (bad magic): %s", self.model_path)
return False
self._loaded = True
mb = self.model_path.stat().st_size / 1024 / 1024
log.info("Model loaded: %s (%.1f MB)", self.model_path.name, mb)
return True
def generate(
self,
prompt: str,
max_tokens: int = 256,
temperature: float = 0.7,
top_k: int = 40,
) -> str:
"""Generate text using the litert-lm CLI."""
if not self._loaded:
return "Error: Model not loaded."
try:
result = subprocess.run(
[
self.cli_path,
"run",
str(self.model_path),
"--prompt",
prompt,
"--max_tokens",
str(max_tokens),
],
capture_output=True,
text=True,
timeout=60,
)
if result.returncode == 0 and result.stdout.strip():
return result.stdout.strip()
if result.stderr:
log.warning("CLI stderr: %s", result.stderr[:200])
except FileNotFoundError:
log.warning("litert-lm CLI not available, using simulated response")
except subprocess.TimeoutExpired:
log.warning("Model inference timed out")
except Exception as exc:
log.warning("Model inference error: %s", exc)
return self._simulate_response(prompt)
def predict_next_token(self, context: list[int]) -> int:
"""Predict the most likely next token (used by DSpark draft engine)."""
if not self._loaded:
return 0
try:
text = self._decode_tokens(context)
result = subprocess.run(
[
self.cli_path,
"run",
str(self.model_path),
"--prompt",
text[-200:],
"--max_tokens",
"1",
"--temperature",
"0.0",
],
capture_output=True,
text=True,
timeout=30,
)
if result.returncode == 0 and result.stdout.strip():
return hash(result.stdout.strip()) % self.vocab_size
except Exception:
pass
return context[-1] if context else 0
@staticmethod
def _decode_tokens(token_ids: list[int]) -> str:
return "".join(chr(max(32, min(126, t % 128))) for t in token_ids[-50:])
def _simulate_response(self, prompt: str) -> str:
"""Simulated response when CLI is unavailable (for demo/dev only)."""
prompt_lower = prompt.lower()
if "hello" in prompt_lower or "hi" in prompt_lower:
return "Hello! I'm Hermes Edge, running on-device. How can I help?"
if "tool" in prompt_lower or "function" in prompt_lower:
return (
"<think>The user is asking about tool calling. "
"I can use calculator, web search, memory, and timer tools.</think>\n\n"
"I support function calling. Available tools:\n"
"- calculator: evaluate math expressions\n"
"- web_search: search the web (requires network)\n"
"- memory: store and recall information\n"
"- timer: set timers"
)
if "reason" in prompt_lower or "deep" in prompt_lower:
return (
"<think>Applying DeepSeek-style reasoning. "
"Breaking down the question step by step. "
"Verifying each step.</think>\n\n"
"Based on my reasoning, here's my answer."
)
return (
f"<think>Processing query using {self.model_path.name} "
f"on LiteRT-LM runtime.</think>\n\n"
f"I received your message. I'm running fully offline as a {self.model_path.stem} model."
)
def get_metadata(self) -> dict:
"""Get model metadata."""
return {
"path": str(self.model_path),
"size_mb": round(self.model_path.stat().st_size / 1024 / 1024, 1),
"loaded": self._loaded,
"format": "LITERTLM",
"vocab_size": self.vocab_size,
}
|