Tool-Calling bedeutet, dass einem LLM erlaubt wird, bestimmte Funktionen auszulösen (wie „durchsuche meine Dateien“, „führe einen Taschenrechner aus“ oder „rufe eine API auf“), indem es eine strukturierte Anfrage sendet, anstatt die Antwort als Fließtext zu raten. Sie verwenden Tool-Calls, weil sie die Ausgaben zuverlässiger und aktueller machen, und sie dem Modell erlauben echte Aktionen auszuführen (Systeme abfragen, Fakten validieren, Schemas durchsetzen) statt zu halluzinieren.
In diesem Tutorial lernen Sie, wie Sie lokale LLMs über Tool Calling mit Beispielen aus den Bereichen Mathematik, Geschichten, Python-Code und Terminal-Funktionen verwenden. Die Inferenz erfolgt lokal über llama.cpp, llama-server und OpenAI-Endpunkte.
Unser Leitfaden sollte für nahezu jedes Modell einschließlich:
Unser erster Schritt ist, das neueste zu beschaffen llama.cpp auf GitHub hier. Du kannst auch den Build-Anweisungen unten folgen. Ändere -DGGML_CUDA=ON zu -DGGML_CUDA=OFF wenn du keine GPU hast oder nur CPU-Inferenz möchtest. Für Apple Mac / Metal-Geräte, setze -DGGML_CUDA=OFF dann wie gewohnt fort - Metal-Unterstützung ist standardmäßig aktiviert.
In einem neuen Terminal (bei Verwendung von tmux mit STRG+B+D) erstellen wir einige Tools wie das Addieren von 2 Zahlen, das Ausführen von Python-Code, das Ausführen von Linux-Funktionen und vieles mehr:
"required": ["code"],
In diesem Beispiel verwenden wir Devstral 2. Beim Wechsel des Modells stellen Sie sicher, dass Sie die richtigen Sampling-Parameter verwenden. Sie können alle in unseren Anleitungen hier.
Jetzt zeigen wir mehrere Methoden zum Ausführen von Tool-Calling für viele verschiedene Anwendungsfälle unten:
Eine Geschichte schreiben:
Mathematische Operationen:
Generierten Python-Code ausführen
Beliebige Terminal-Funktionen ausführen
🌠 Qwen3-Coder-Next Tool Calling
In einem neuen Terminal erstellen wir einige Tools wie das Addieren von 2 Zahlen, das Ausführen von Python-Code, das Ausführen von Linux-Funktionen und vieles mehr:
Wir verwenden dann die unten stehenden Funktionen, die die Funktionsaufrufe automatisch parsen und für jedes LLM den OpenAI-Endpunkt aufrufen:
Jetzt zeigen wir mehrere Methoden zum Ausführen von Tool-Calling für viele verschiedene Anwendungsfälle unten:
Generierten Python-Code ausführen
Beliebige Terminal-Funktionen ausführen
Wir bestätigen, dass die Datei erstellt wurde — und das wurde sie!
⚡ GLM-4.7-Flash + GLM 4.7 Calling
Zuerst laden wir herunter GLM-4.7 oder GLM-4.7-Flash via etwas Python-Code und starten es dann über llama-server in einem separaten Terminal (zum Beispiel mit tmux). In diesem Beispiel laden wir das große GLM-4.7-Modell herunter:
Wenn Sie es erfolgreich ausgeführt haben, sollten Sie sehen:
Starten Sie es nun über llama-server in einem neuen Terminal. Verwenden Sie tmux, wenn Sie möchten:
Und Sie werden bekommen:
Nun in einem neuen Terminal und beim Ausführen von Python-Code, Erinnerung daran auszuführen Tool Calling Guide Wir verwenden GLM 4.7s optimale Parameter temperature = 0.7 und top_p = 1.0
für weitere Details, können wir dann einige Tool-Aufrufe durchführen:
Zuerst laden wir herunter Devstral 2 via etwas Python-Code und starten es dann über llama-server in einem separaten Terminal (zum Beispiel mit tmux):
Wenn Sie es erfolgreich ausgeführt haben, sollten Sie sehen:
Starten Sie es nun über llama-server in einem neuen Terminal. Verwenden Sie tmux, wenn Sie möchten:
Sie werden untenstehendes sehen, wenn es erfolgreich war:
Wir rufen das Modell dann mit der folgenden Nachricht und mit Devstrals vorgeschlagenen Parametern von nur temperature = 0.15 auf. Erinnerung daran, auszuführen Tool Calling Guide
messages = [{
"role": "user",
Tool-Aufruf zum Ausführen generierten Python-Codes für GLM 4.7
}]
unsloth_inference(messages, temperature = 0.15, top_p = 1.0, top_k = -1, min_p = 0.00)
messages = [{
"role": "user",
"content": [{"type": "text", "text": "Schreibe 'I'm a happy Sloth' in eine Datei und gib sie mir dann wieder aus."}],
}]
messages = unsloth_inference(messages, temperature = 0.15, top_p = 1.0, top_k = -1, min_p = 0.00)
import json, subprocess, random
from typing import Any
def add_number(a: float | str, b: float | str) -> float:
return float(a) + float(b)
def multiply_number(a: float | str, b: float | str) -> float:
return float(a) * float(b)
def substract_number(a: float | str, b: float | str) -> float:
return float(a) - float(b)
def write_a_story() -> str:
return random.choice([
"Vor langer Zeit in einer weit entfernten Galaxie...",
"Es waren zwei Freunde, die Faultiere und Code liebten...",
"Die Welt ging unter, weil jedes Faultier übermenschliche Intelligenz entwickelte...",
"Ohne dass ein Freund es wusste, hatte der andere versehentlich ein Programm geschrieben, das Faultiere evolvieren ließ...",
])
def terminal(command: str) -> str:
if "rm" in command or "sudo" in command or "dd" in command or "chmod" in command:
msg = "Kann Befehle 'rm, sudo, dd, chmod' nicht ausführen, da sie gefährlich sind"
print(msg); return msg
print(f"Führe Terminal-Befehl `{command}` aus")
try:
return str(subprocess.run(command, capture_output = True, text = True, shell = True, check = True).stdout)
except subprocess.CalledProcessError as e:
return f"Befehl fehlgeschlagen: {e.stderr}"
def python(code: str) -> str:
data = {}
exec(code, data)
del data["__builtins__"]
return str(data)
MAP_FN = {
"add_number": add_number,
"multiply_number": multiply_number,
"substract_number": substract_number,
"write_a_story": write_a_story,
"terminal": terminal,
"python": python,
}
tools = [
{
"type": "function",
"function": {
"name": "add_number",
"description": "Addiere zwei Zahlen.",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "Die erste Zahl.",
},
"b": {
"type": "string",
"description": "Die zweite Zahl.",
},
},
"required": ["a", "b"],
},
},
},
{
"type": "function",
"function": {
"name": "multiply_number",
"description": "Multipliziert zwei Zahlen.",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "Die erste Zahl.",
},
"b": {
"type": "string",
"description": "Die zweite Zahl.",
},
},
"required": ["a", "b"],
},
},
},
{
"type": "function",
"function": {
"name": "substract_number",
"description": "Subtrahiert zwei Zahlen.",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "Die erste Zahl.",
},
"b": {
"type": "string",
"description": "Die zweite Zahl.",
},
},
"required": ["a", "b"],
},
},
},
{
"type": "function",
"function": {
"name": "write_a_story",
"description": "Schreibt eine zufällige Geschichte.",
"parameters": {
"type": "object",
"properties": {},
"required": [],
},
},
},
{
"type": "function",
"function": {
"name": "terminal",
"description": "Führt Operationen vom Terminal aus.",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "Der Befehl, den du starten möchtest, z. B. `ls`, `rm`, ...",
},
},
"required": ["command"],
},
},
},
{
"type": "function",
"function": {
"name": "python",
"description": "Rufe einen Python-Interpreter mit etwas Python-Code auf, der ausgeführt wird.",
"parameters": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Der auszuführende Python-Code",
},
},
"required": ["code"],
},
},
},
]
from openai import OpenAI
Wir verwenden dann die folgenden Funktionen (kopieren, einfügen und ausführen), die die Funktionsaufrufe automatisch parsen und den OpenAI-Endpunkt für ein beliebiges Modell aufrufen:
def unsloth_inference(
temperature = 1.0,
temperature = 0.7,
top_p = 0.95,
top_k = 40,
min_p = 0.01,
):
repetition_penalty = 1.0,
openai_client = OpenAI(
base_url = "http://127.0.0.1:8001/v1",
api_key = "sk-no-key-required",
)
model_name = next(iter(openai_client.models.list())).id
print(f"Verwende Modell = {model_name}")
has_tool_calls = True
original_messages_len = len(messages)
while has_tool_calls:
print(f"Aktuelle Nachrichten = {messages}")
response = openai_client.chat.completions.create(
model = model_name,
messages = messages,
temperature = temperature,
temperature = temperature,
tools = tools if tools else None,
tool_choice = "auto" if tools else None,
tool_choice = "auto" if tools else None,
)
tool_calls = response.choices[0].message.tool_calls or []
content = response.choices[0].message.content or ""
tool_calls_dict = [tc.to_dict() for tc in tool_calls] if tool_calls else tool_calls
messages.append({"role": "assistant", "tool_calls": tool_calls_dict, "content": content,})
for tool_call in tool_calls:
fx, args, _id = tool_call.function.name, tool_call.function.arguments, tool_call.id
out = MAP_FN[fx](**json.loads(args))
messages.append({"role": "tool", "tool_call_id": _id, "name": fx, "content": str(out),})
else:
has_tool_calls = False
has_tool_calls = False
messages = [{
"role": "user",
Tool-Aufruf zum Ausführen generierten Python-Codes für GLM 4.7
}]
unsloth_inference(messages, temperature = 1.0, top_p = 0.95, top_k = 40, min_p = 0.00)
messages = [{
"role": "user",
"content": [{"type": "text", "text": "Schreibe 'I'm a happy Sloth' in eine Datei und gib sie mir dann wieder aus."}],
}]
messages = unsloth_inference(messages, temperature = 1.0, top_p = 1.0, top_k = 40, min_p = 0.00)
# !pip install huggingface_hub hf_transfer
import os
os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1"
from huggingface_hub import snapshot_download
snapshot_download(
repo_id = "unsloth/GLM-4.7-GGUF",
local_dir = "unsloth/GLM-4.7-GGUF",
allow_patterns = ["*UD-Q2_K_XL*",], # Für Q2_K_XL
)
./llama.cpp/llama-server \
für das GPU-Offloading, also wie viele Schichten. Versuchen Sie, es anzupassen, wenn Ihre GPU nicht mehr genug Speicher hat. Entfernen Sie es auch, wenn Sie nur CPU-Inferenz haben.
./llama.cpp/llama-server \
--threads -1 \
--alias "unsloth/GLM-4.7" \
--prio 3 \
--min_p 0.01 \
--ctx-size 16384 \
--port 8001 \
--jinja
messages = [{
"role": "user",
"role": "user",
}]
"content": [{"type": "text", "text": "Was ist das heutige Datum plus 3 Tage?"}],
messages = [{
"role": "user",
Tool-Aufruf zum Ausführen generierten Python-Codes für GLM 4.7
}]
"content": [{"type": "text", "text": "Was ist das heutige Datum plus 3 Tage?"}],
import json, subprocess, random
from typing import Any
def add_number(a: float | str, b: float | str) -> float:
return float(a) + float(b)
def multiply_number(a: float | str, b: float | str) -> float:
return float(a) * float(b)
def substract_number(a: float | str, b: float | str) -> float:
return float(a) - float(b)
def write_a_story() -> str:
return random.choice([
"Vor langer Zeit in einer weit entfernten Galaxie...",
"Es waren zwei Freunde, die Faultiere und Code liebten...",
"Die Welt ging unter, weil jedes Faultier übermenschliche Intelligenz entwickelte...",
"Ohne dass ein Freund es wusste, hatte der andere versehentlich ein Programm geschrieben, das Faultiere evolvieren ließ...",
])
def terminal(command: str) -> str:
if "rm" in command or "sudo" in command or "dd" in command or "chmod" in command:
msg = "Kann Befehle 'rm, sudo, dd, chmod' nicht ausführen, da sie gefährlich sind"
print(msg); return msg
print(f"Führe Terminal-Befehl `{command}` aus")
try:
return str(subprocess.run(command, capture_output = True, text = True, shell = True, check = True).stdout)
except subprocess.CalledProcessError as e:
return f"Befehl fehlgeschlagen: {e.stderr}"
def python(code: str) -> str:
data = {}
exec(code, data)
del data["__builtins__"]
return str(data)
MAP_FN = {
"add_number": add_number,
"multiply_number": multiply_number,
"substract_number": substract_number,
"write_a_story": write_a_story,
"terminal": terminal,
"python": python,
}
tools = [
{
"type": "function",
"function": {
"name": "add_number",
"description": "Addiere zwei Zahlen.",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "Die erste Zahl.",
},
"b": {
"type": "string",
"description": "Die zweite Zahl.",
},
},
"required": ["a", "b"],
},
},
},
{
"type": "function",
"function": {
"name": "multiply_number",
"description": "Multipliziert zwei Zahlen.",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "Die erste Zahl.",
},
"b": {
"type": "string",
"description": "Die zweite Zahl.",
},
},
"required": ["a", "b"],
},
},
},
{
"type": "function",
"function": {
"name": "substract_number",
"description": "Subtrahiert zwei Zahlen.",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "Die erste Zahl.",
},
"b": {
"type": "string",
"description": "Die zweite Zahl.",
},
},
"required": ["a", "b"],
},
},
},
{
"type": "function",
"function": {
"name": "write_a_story",
"description": "Schreibt eine zufällige Geschichte.",
"parameters": {
"type": "object",
"properties": {},
"required": [],
},
},
},
{
"type": "function",
"function": {
"name": "terminal",
"description": "Führt Operationen vom Terminal aus.",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "Der Befehl, den du starten möchtest, z. B. `ls`, `rm`, ...",
},
},
"required": ["command"],
},
},
},
{
"type": "function",
"function": {
"name": "python",
"description": "Rufe einen Python-Interpreter mit etwas Python-Code auf, der ausgeführt wird.",
"parameters": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "Der auszuführende Python-Code",
},
},
"required": ["code"],
},
},
},
]
# !pip install huggingface_hub hf_transfer
import os
os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1"
from huggingface_hub import snapshot_download
snapshot_download(
repo_id = "unsloth/Devstral-Small-2-24B-Instruct-2512-GGUF",
local_dir = "unsloth/Devstral-Small-2-24B-Instruct-2512-GGUF",
allow_patterns = ["*UD-Q4_K_XL*", "*mmproj-F16*"], # Für Q4_K_XL
)