mirror of
https://github.com/oobabooga/text-generation-webui.git
synced 2026-03-18 11:24:39 +01:00
160 lines
4.6 KiB
Markdown
160 lines
4.6 KiB
Markdown
## Tool calling in the UI
|
|
|
|
### 1. Load a model with tool-calling support
|
|
|
|
Load a model with tool-calling support from the Model tab.
|
|
|
|
### 2. Select tools
|
|
|
|
In the chat sidebar, check the tools you want the model to use:
|
|
|
|
- `web_search`: Search the web using DuckDuckGo.
|
|
- `fetch_webpage`: Fetch the content of a URL.
|
|
- `calculate`: Evaluate math expressions.
|
|
- `get_datetime`: Get the current date and time.
|
|
- `roll_dice`: Roll dice.
|
|
|
|
### 3. Chat
|
|
|
|
Send a message as usual. When the model decides it needs a tool, it will call it automatically. You will see each tool call and its result in a collapsible accordion inside the chat message.
|
|
|
|
The model may call multiple tools in sequence before giving its final answer.
|
|
|
|
## Writing custom tools
|
|
|
|
Each tool is a single `.py` file in `user_data/tools/`. It needs two things:
|
|
|
|
1. A `tool` dictionary that describes the function (name, description, parameters).
|
|
2. An `execute(arguments)` function that runs it and returns the result.
|
|
|
|
Here is a minimal example (`user_data/tools/get_datetime.py`):
|
|
|
|
```python
|
|
from datetime import datetime
|
|
|
|
tool = {
|
|
"type": "function",
|
|
"function": {
|
|
"name": "get_datetime",
|
|
"description": "Get the current date and time.",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {},
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
def execute(arguments):
|
|
now = datetime.now()
|
|
return {"date": now.strftime("%Y-%m-%d"), "time": now.strftime("%I:%M %p")}
|
|
```
|
|
|
|
An example with parameters (`user_data/tools/roll_dice.py`):
|
|
|
|
```python
|
|
import random
|
|
|
|
tool = {
|
|
"type": "function",
|
|
"function": {
|
|
"name": "roll_dice",
|
|
"description": "Roll one or more dice with the specified number of sides.",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"count": {"type": "integer", "description": "Number of dice to roll.", "default": 1},
|
|
"sides": {"type": "integer", "description": "Number of sides per die.", "default": 20},
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
def execute(arguments):
|
|
count = max(1, min(arguments.get("count", 1), 1000))
|
|
sides = max(2, min(arguments.get("sides", 20), 1000))
|
|
rolls = [random.randint(1, sides) for _ in range(count)]
|
|
return {"rolls": rolls, "total": sum(rolls)}
|
|
```
|
|
|
|
You can open the built-in tools in `user_data/tools/` for more examples.
|
|
|
|
## Tool calling over the API
|
|
|
|
Tool calling over the API follows the [OpenAI API](https://platform.openai.com/docs/guides/function-calling) convention. Define your tools, send them with your messages, and handle tool calls in a loop until the model gives a final answer.
|
|
|
|
```python
|
|
import json
|
|
import requests
|
|
|
|
url = "http://127.0.0.1:5000/v1/chat/completions"
|
|
|
|
tools = [
|
|
{
|
|
"type": "function",
|
|
"function": {
|
|
"name": "get_weather",
|
|
"description": "Get the current weather for a given location.",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"location": {"type": "string", "description": "City name"},
|
|
},
|
|
"required": ["location"]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
|
|
|
|
def execute_tool(name, arguments):
|
|
if name == "get_weather":
|
|
return {"temperature": "14°C", "condition": "partly cloudy"}
|
|
return {"error": f"Unknown tool: {name}"}
|
|
|
|
|
|
messages = [{"role": "user", "content": "What's the weather like in Paris?"}]
|
|
|
|
for _ in range(10):
|
|
response = requests.post(url, json={"messages": messages, "tools": tools}).json()
|
|
choice = response["choices"][0]
|
|
|
|
if choice["finish_reason"] == "tool_calls":
|
|
messages.append({
|
|
"role": "assistant",
|
|
"content": choice["message"]["content"],
|
|
"tool_calls": choice["message"]["tool_calls"],
|
|
})
|
|
|
|
for tool_call in choice["message"]["tool_calls"]:
|
|
name = tool_call["function"]["name"]
|
|
arguments = json.loads(tool_call["function"]["arguments"])
|
|
result = execute_tool(name, arguments)
|
|
print(f"Tool call: {name}({arguments}) => {result}")
|
|
|
|
messages.append({
|
|
"role": "tool",
|
|
"tool_call_id": tool_call["id"],
|
|
"content": json.dumps(result),
|
|
})
|
|
else:
|
|
print(f"\nAssistant: {choice['message']['content']}")
|
|
break
|
|
```
|
|
|
|
## Supported models
|
|
|
|
The following models are supported:
|
|
|
|
- Qwen 3.5
|
|
- GPT-OSS
|
|
- Mistral Small / Devstral
|
|
- DeepSeek V3
|
|
- Kimi-K2
|
|
- MiniMax-M2.5
|
|
- GLM-5
|
|
- Llama 4
|
|
|
|
Other models that output tool calls as JSON (inside XML tags, code blocks, or plain JSON) are also supported through a generic fallback parser.
|