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
File size: 5,013 Bytes
ee34fec 11654f3 | 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 | # 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]
|