Local Execution
You're reading the docs for Semantic Router 0.x. Version 1.0 is out: read this page for v1, or the migration guide to upgrade.
Plenty of reasons to run your own LLM instead of calling an API — cost, privacy, compliance. Semantic Router supports local LLMs through llama.cpp.
llama.cpp also runs quantized GGUF models, which shrink memory use enough that even a 13B-parameter model runs with hardware acceleration on an Apple M1 Pro.
Full example
We'll use Mistral-7B-Instruct, quantized to 4-bit to keep the memory footprint small.
Install
For hardware acceleration (BLAS, CUDA, Metal, and so on), see the llama-cpp-python README.
pip install -qU "semantic-router[local]"On Apple silicon, compile with Metal acceleration:
CMAKE_ARGS="-DLLAMA_METAL=on" pip install -qU "semantic-router[local]"Download the model
Mistral 7B Instruct as a 4-bit GGUF is a good balance of quality and consumer-hardware friendliness:
!curl -L "https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.2-GGUF/resolve/main/mistral-7b-instruct-v0.2.Q4_0.gguf?download=true" -o ./mistral-7b-instruct-v0.2.Q4_0.gguf
!ls mistral-7b-instruct-v0.2.Q4_0.ggufDefine the routes
We'll include a dynamic route so the local LLM has some function calling to do:
from datetime import datetime
from zoneinfo import ZoneInfo
from semantic_router import Route
from semantic_router.utils.function_call import get_schema
def get_time(timezone: str) -> str:
"""Finds the current time in a specific timezone.
:param timezone: The timezone to find the current time in, should
be a valid timezone from the IANA Time Zone Database like
"America/New_York" or "Europe/London". Do NOT put the place
name itself like "rome", or "new york", you must provide
the IANA format.
:type timezone: str
:return: The current time in the specified timezone."""
now = datetime.now(ZoneInfo(timezone))
return now.strftime("%H:%M")
time_schema = get_schema(get_time)
time = Route(
name="get_time",
utterances=[
"what is the time in new york city?",
"what is the time in london?",
"I live in Rome, what time is it?",
],
function_schemas=[time_schema],
)
politics = Route(
name="politics",
utterances=[
"isn't politics the best thing ever",
"why don't you tell me about your political opinions",
"don't you just love the president",
"don't you just hate the president",
"they're going to destroy this country!",
"they will save the country!",
],
)
chitchat = Route(
name="chitchat",
utterances=[
"how's the weather today?",
"how are things going?",
"lovely weather today",
"the weather is horrendous",
"let's go to the chippy",
],
)
routes = [politics, chitchat, time]Encoder
To stay fully local we'll use HuggingFaceEncoder, which defaults to sentence-transformers/all-MiniLM-L6-v2:
from semantic_router.encoders import HuggingFaceEncoder
encoder = HuggingFaceEncoder()The llama.cpp LLM
Create a llama_cpp.Llama and wrap it in LlamaCppLLM. Three parameters worth knowing:
n_gpu_layers— how many layers to offload to the GPU.-1for the whole model,0for CPU only.n_ctx— the context window. Capped by the model's own limit (8000 tokens for Mistral-7B-Instruct).verbose— setFalseto quietllama.cpp's output.
The llama-cpp-python API reference covers the rest.
from semantic_router import SemanticRouter
from llama_cpp import Llama
from semantic_router.llms.llamacpp import LlamaCppLLM
enable_gpu = True # offload to GPU (the model must fit in memory)
_llm = Llama(
model_path="./mistral-7b-instruct-v0.2.Q4_0.gguf",
n_gpu_layers=-1 if enable_gpu else 0,
n_ctx=2048,
)
_llm.verbose = False
llm = LlamaCppLLM(name="Mistral-7B-v0.2-Instruct", llm=_llm, max_tokens=None)
router = SemanticRouter(encoder=encoder, routes=routes, llm=llm)Try it
A static route first:
router("how's the weather today?")RouteChoice(name='chitchat', function_call=None, similarity_score=None)Now a time question, which triggers the dynamic route and the local LLM:
out = router("what's the time in New York right now?")
print(out)
get_time(**out.function_call[0])name='get_time' function_call=[{'timezone': 'America/New_York'}] similarity_score=None
'07:50'A couple more:
out = router("what's the time in Rome right now?")
print(out)
get_time(**out.function_call[0])name='get_time' function_call=[{'timezone': 'Europe/Rome'}] similarity_score=None
'13:51'out = router("what's the time in Bangkok right now?")
print(out)
get_time(**out.function_call[0])name='get_time' function_call=[{'timezone': 'Asia/Bangkok'}] similarity_score=None
'18:51'All local, no API calls.
Cleanup
Delete the model when you're done:
rm ./mistral-7b-instruct-v0.2.Q4_0.gguf