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 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 \ model.litertlm \ --prompt="Write me a poem"
- Notebooks
- Google Colab
- Kaggle
| """ | |
| Hermes Agent-Style Tool Calling Format | |
| Implements the NousResearch Hermes function-calling protocol: | |
| - Tool definitions in <tools> XML block in system message | |
| - Model emits <tool_call>{"name": "...", "arguments": {...}}</tool_call> | |
| - Results return as <tool_response>{"name": "...", "content": ...}</tool_response> | |
| - Supports multi-turn recursive tool calling | |
| Compatible with LiteRT-LM constrained decoding anchors. | |
| Usage: | |
| tools = [ | |
| ToolDef(name="calculator", description="Math calculator", | |
| parameters={"type": "object", "properties": {"expr": {"type": "string"}}}) | |
| ] | |
| formatter = HermesToolFormatter(tools) | |
| prompt = formatter.build_tool_prompt("What's 2+2?") | |
| """ | |
| import json | |
| import logging | |
| from collections.abc import Callable | |
| from dataclasses import dataclass, field | |
| log = logging.getLogger(__name__) | |
| class ToolDef: | |
| name: str | |
| description: str | |
| parameters: dict | None = None | |
| class ToolResult: | |
| name: str | |
| content: str | |
| success: bool = True | |
| TOOL_CALL_START = "<tool_call>" | |
| TOOL_CALL_END = "</tool_call>" | |
| TOOL_RESPONSE_START = "<tool_response>" | |
| TOOL_RESPONSE_END = "</tool_response>" | |
| class HermesToolFormatter: | |
| """Builds prompts and parses responses in Hermes function-calling format.""" | |
| def __init__(self, tools: list[ToolDef] | None = None): | |
| self.tools = tools or [] | |
| def set_tools(self, tools: list[ToolDef]) -> None: | |
| self.tools = tools | |
| def build_tools_block(self) -> str: | |
| """Build the <tools> XML block for the system message.""" | |
| if not self.tools: | |
| return "" | |
| lines = ["<tools>"] | |
| for tool in self.tools: | |
| entry = { | |
| "type": "function", | |
| "function": { | |
| "name": tool.name, | |
| "description": tool.description, | |
| }, | |
| } | |
| if tool.parameters: | |
| entry["function"]["parameters"] = tool.parameters | |
| lines.append(json.dumps(entry)) | |
| lines.append("</tools>") | |
| return "\n".join(lines) | |
| def build_system_message(self, base_system: str = "") -> str: | |
| """Build the full system message with tool definitions.""" | |
| parts = [base_system] if base_system else [] | |
| tools_block = self.build_tools_block() | |
| if tools_block: | |
| parts.append(tools_block) | |
| return "\n\n".join(parts) if parts else "You are a helpful AI assistant." | |
| def build_tool_prompt( | |
| self, | |
| user_input: str, | |
| system_override: str | None = None, | |
| context: str | None = None, | |
| ) -> str: | |
| """Build a full ChatML prompt with tool definitions in the system message.""" | |
| system = system_override or self.build_system_message( | |
| "You are Hermes Edge, an on-device AI agent. Use tools when needed." | |
| ) | |
| messages = [{"role": "system", "content": system}] | |
| if context: | |
| messages.append({"role": "user", "content": context}) | |
| messages.append({"role": "user", "content": user_input}) | |
| return self._format_chatml(messages) | |
| def parse_tool_calls(self, text: str) -> list[dict]: | |
| """Parse <tool_call>...</tool_call> blocks from model output.""" | |
| import re | |
| pattern = re.compile( | |
| re.escape(TOOL_CALL_START) + r"(.*?)" + re.escape(TOOL_CALL_END), re.DOTALL | |
| ) | |
| calls = [] | |
| for match in pattern.finditer(text): | |
| try: | |
| parsed = json.loads(match.group(1).strip()) | |
| calls.append(parsed) | |
| except json.JSONDecodeError: | |
| log.warning("Failed to parse tool call: %s", match.group(1)) | |
| return calls | |
| def format_tool_result(self, name: str, content: str) -> str: | |
| """Format a tool result for feeding back into the prompt.""" | |
| payload = json.dumps({"name": name, "content": content}) | |
| return f"{TOOL_RESPONSE_START}{payload}{TOOL_RESPONSE_END}" | |
| def _format_chatml(messages: list[dict]) -> str: | |
| im_start = "<|im_start|>" | |
| im_end = "<|im_end|>" | |
| parts = [] | |
| for msg in messages: | |
| parts.append(f"{im_start}{msg['role']}\n{msg['content']}{im_end}\n") | |
| parts.append(f"{im_start}assistant\n") | |
| return "".join(parts) | |
| class ToolRegistry: | |
| """Registry of executable tools that the agent can call.""" | |
| def __init__(self): | |
| self._tools: dict[str, tuple[ToolDef, Callable]] = {} | |
| def register( | |
| self, | |
| name: str, | |
| description: str, | |
| func: Callable, | |
| parameters: dict | None = None, | |
| ) -> ToolDef: | |
| tool = ToolDef(name=name, description=description, parameters=parameters) | |
| self._tools[name] = (tool, func) | |
| return tool | |
| def get_defs(self) -> list[ToolDef]: | |
| return [t for t, _ in self._tools.values()] | |
| def execute(self, name: str, arguments: dict | None = None) -> ToolResult: | |
| if name not in self._tools: | |
| return ToolResult(name=name, content=f"Unknown tool: {name}", success=False) | |
| _, func = self._tools[name] | |
| try: | |
| if arguments: | |
| result = func(**arguments) | |
| else: | |
| result = func() | |
| return ToolResult(name=name, content=str(result), success=True) | |
| except Exception as exc: | |
| log.error("Tool %s failed: %s", name, exc) | |
| return ToolResult(name=name, content=str(exc), success=False) | |