Audio-to-Audio
Moshi
English
speech-to-speech
full-duplex
function-calling
tool-use
voice-agent
realtime
personaplex
low-latency
Instructions to use abhinavpgagi/personaplex-tool-calling with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Moshi
How to use abhinavpgagi/personaplex-tool-calling with Moshi:
# pip install moshi # Run the interactive web server python -m moshi.server --hf-repo "abhinavpgagi/personaplex-tool-calling" # Then open https://localhost:8998 in your browser
# pip install moshi import torch from moshi.models import loaders # Load checkpoint info from HuggingFace checkpoint = loaders.CheckpointInfo.from_hf_repo("abhinavpgagi/personaplex-tool-calling") # Load the Mimi audio codec mimi = checkpoint.get_mimi(device="cuda") mimi.set_num_codebooks(8) # Encode audio (24kHz, mono) wav = torch.randn(1, 1, 24000 * 10) # [batch, channels, samples] with torch.no_grad(): codes = mimi.encode(wav.cuda()) decoded = mimi.decode(codes) - Notebooks
- Google Colab
- Kaggle
| # SPDX-FileCopyrightText: Copyright (c) 2026 Abhinav Kalvacherla | |
| # SPDX-License-Identifier: Apache-2.0 | |
| """ | |
| Generic HTTP executor for client-supplied function/API definitions. | |
| A function definition (supplied per-session, see session_config.py) is a dict: | |
| { | |
| "name": "get_weather", # required — tool name | |
| "description": "Current weather for a lat/lon.", | |
| "endpoint": "https://api.open-meteo.com/v1/forecast", # required — may contain {placeholders} | |
| "method": "GET", # GET|POST|PUT|PATCH|DELETE (default GET) | |
| "param_location": "query", # query|body|path (default: query for GET, body otherwise) | |
| "param_locations": {"id": "path"}, # optional per-parameter override | |
| "headers": {"X-Api-Key": "..."}, # optional static request headers | |
| "static_params": {"current_weather": true}, # optional server-merged constants | |
| "parameters": { ...JSON schema... } # OpenAI tool parameters schema | |
| } | |
| `build_openai_tools` turns the {name, description, parameters} parts into the | |
| OpenAI `tools` array given to the LLM. `execute_function` takes the LLM-extracted | |
| args, builds the HTTP request per the spec, and returns the response text. | |
| Security: the server makes requests to client-supplied URLs (an SSRF surface). | |
| `_enforce_allowlist` restricts hosts and blocks private/loopback/link-local IPs. | |
| """ | |
| from __future__ import annotations | |
| import ipaddress | |
| import logging | |
| import os | |
| import socket | |
| from urllib.parse import urlparse | |
| import httpx | |
| logger = logging.getLogger(__name__) | |
| MAX_RESPONSE_CHARS = 1500 | |
| HTTP_TIMEOUT = 4.0 # below rag_timeout; the retriever's wait_for is the hard ceiling | |
| def build_openai_tools(functions: list[dict]) -> list[dict]: | |
| """Map declarative function defs → OpenAI `tools` array for the LLM.""" | |
| tools = [] | |
| for f in functions: | |
| tools.append({ | |
| "type": "function", | |
| "function": { | |
| "name": f["name"], | |
| "description": f.get("description", ""), | |
| "parameters": f.get("parameters") or {"type": "object", "properties": {}}, | |
| }, | |
| }) | |
| return tools | |
| def _default_location(spec: dict) -> str: | |
| return "query" if str(spec.get("method", "GET")).upper() == "GET" else "body" | |
| def _split_args(spec: dict, args: dict) -> tuple[str, dict, dict | None]: | |
| """Route merged args into URL path / query / body per the spec.""" | |
| loc = spec.get("param_location") or _default_location(spec) | |
| per = spec.get("param_locations") or {} | |
| merged = {**(spec.get("static_params") or {}), **(args or {})} | |
| url = spec["endpoint"] | |
| query: dict = {} | |
| body: dict = {} | |
| for k, v in merged.items(): | |
| placeholder = "{%s}" % k | |
| where = per.get(k, "path" if placeholder in url else loc) | |
| if where == "path": | |
| url = url.replace(placeholder, str(v)) | |
| elif where == "body": | |
| body[k] = v | |
| else: | |
| query[k] = v | |
| return url, query, (body or None) | |
| def _enforce_allowlist(url: str, cfg) -> None: | |
| """Reject disallowed hosts and any host resolving to a non-public IP (SSRF guard).""" | |
| parsed = urlparse(url) | |
| if parsed.scheme not in ("http", "https"): | |
| raise PermissionError(f"scheme {parsed.scheme!r} not allowed") | |
| host = parsed.hostname or "" | |
| server_allow = {h for h in (os.environ.get("MOSHI_TOOL_ALLOWED_HOSTS") or "").split(",") if h} | |
| sess_allow = set(getattr(cfg, "allowed_hosts", None) or []) | |
| if server_allow and sess_allow: | |
| allow = server_allow & sess_allow | |
| else: | |
| allow = server_allow or sess_allow | |
| if allow and host not in allow: | |
| raise PermissionError(f"host {host!r} not in allowlist") | |
| # Block private / loopback / link-local / reserved targets regardless of allowlist. | |
| try: | |
| infos = socket.getaddrinfo(host, None) | |
| except socket.gaierror as exc: | |
| raise PermissionError(f"cannot resolve host {host!r}: {exc}") from exc | |
| for info in infos: | |
| ip = ipaddress.ip_address(info[4][0]) | |
| if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved or ip.is_multicast: | |
| raise PermissionError(f"host {host!r} resolves to non-public IP {ip}") | |
| async def execute_function(spec: dict, args: dict, cfg) -> str: | |
| """Build and make the HTTP call described by `spec` with `args`; return response text.""" | |
| _enforce_allowlist(spec["endpoint"], cfg) | |
| method = str(spec.get("method", "GET")).upper() | |
| url, query, body = _split_args(spec, args) | |
| headers = spec.get("headers") or {} | |
| logger.info("[http] %s %s params=%s body=%s", method, url, query, body) | |
| async with httpx.AsyncClient(timeout=HTTP_TIMEOUT, follow_redirects=False) as client: | |
| resp = await client.request(method, url, params=query or None, json=body, headers=headers) | |
| resp.raise_for_status() | |
| text = resp.text | |
| return text[:MAX_RESPONSE_CHARS] | |