Function Tools函数工具(Tool Calling)
Build agentic workflows with OpenAI-compatible tool calling — entirely on-device. Both the Foundry Local and ORT engines support the OpenAI tools + tool_choice interface.使用 OpenAI 兼容的工具调用接口构建 Agentic 工作流——完全在设备上运行。Foundry Local 和 ORT 引擎均支持 OpenAI tools + tool_choice 接口。
How It Works工作原理
| Engine引擎 | Strategy策略 |
|---|---|
| Foundry Local | Tools forwarded natively via the standard OpenAI tools parameter. Response may carry native tool_calls or functools[...] format — both normalised automatically.工具定义通过标准 OpenAI tools 参数原生转发。响应可能携带原生 tool_calls 字段或 functools[...] 格式——两种格式均自动归一化。 |
| ORT | Tools serialised as JSON Schema inside the system prompt. Model replies with a <tool_call>{...}</tool_call> block; parse_tool_call() extracts and validates it.工具以 JSON Schema 形式注入系统提示词。模型以 <tool_call>{...}</tool_call> 块回复,parse_tool_call() 负责提取和验证。 |
Both engines return the same ChatResponse structure — your application code is engine-agnostic.两个引擎返回相同的 ChatResponse 结构——你的应用代码与引擎无关。
Supported Output Formats (auto-detected)支持的输出格式(自动检测)
| Format格式 | Example示例 |
|---|---|
<tool_call> block | <tool_call>{"name": "get_weather", "arguments": {"city": "Paris"}}</tool_call> |
| Phi-3 native | <|function_calls|>{...}<|/function_calls|> |
| Mistral-style | <functioncall>{...}</functioncall> |
| Markdown code block | ```json {...} ``` |
| OpenAI-legacy wrapper | {"function_call": {"name": ..., "arguments": ...}} |
| Bare JSON | {"name": "...", "arguments": {...}} |
Example: Two-turn Tool-Calling Agent示例:两轮工具调用 Agent
This example demonstrates a complete tool-calling workflow: the model decides to call a function, your code executes it, then the model generates a final response using the tool result.此示例演示完整的工具调用工作流:模型决定调用函数,你的代码执行该函数,然后模型使用工具返回的结果生成最终响应。
Step 1: Start the server第 1 步:启动服务
bash
obeaver serve Phi-4-mini
Step 2: Python client with tool calling第 2 步:Python 客户端调用工具
python
from openai import OpenAI
import json
client = OpenAI(base_url="http://127.0.0.1:18000/v1", api_key="unused")
# Define tools
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
messages = [{"role": "user", "content": "What is the weather in Tokyo?"}]
# Turn 1 — model decides to call a tool
resp = client.chat.completions.create(
model="Phi-4-mini",
messages=messages,
tools=tools
)
choice = resp.choices[0]
if choice.finish_reason == "tool_calls":
tool_call = choice.message.tool_calls[0]
args = json.loads(tool_call.function.arguments)
# Execute your function (replace with real implementation)
weather_result = {"city": args["city"], "temperature": "18°C", "condition": "Sunny"}
# Turn 2 — send tool result back to model
messages += [
choice.message,
{"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(weather_result)},
]
final = client.chat.completions.create(
model="Phi-4-mini",
messages=messages
)
print(final.choices[0].message.content)
curl Examplescurl 示例
Foundry Local
bash
obeaver serve Phi-4-mini
curl -s http://127.0.0.1:18000/v1/chat/completions \
-H "Content-Type: application/json" \
-d @tests/tool_foundrylocal_request.json
ORT
bash
obeaver serve --engine ort ./models/Qwen3-0.6B_ONNX_INT4_CPU
curl -s http://127.0.0.1:18000/v1/chat/completions \
-H "Content-Type: application/json" \
-d @tests/tool_ort_request.json
Tool-Calling Internals工具调用内部实现
| Component组件 | Role作用 |
|---|---|
ToolCall | Dataclass: id, name, arguments → .to_openai_dict()数据类:id、name、arguments → .to_openai_dict() |
ChatResponse | Unified engine response: content, tool_calls, finish_reason引擎统一响应结构:content、tool_calls、finish_reason |
inject_tools_into_messages() | Appends JSON Schema tool definitions to system prompt (ORT path)将 JSON Schema 工具定义追加到系统提示词(ORT 路径) |
parse_tool_call() | Extracts ToolCall from raw model output; handles 6 format variants从模型原始输出中提取 ToolCall;处理 6 种格式变体 |
build_tool_result_message() | Builds the role: tool message for turn-2 follow-up构建第二轮对话中发回的 role: tool 消息 |
Data Flow数据流
text
User request + tools
→ inject_tools_into_messages() [ORT] / pass tools natively [Foundry]
→ Engine generates response
→ parse_tool_call() extracts ToolCall
→ Application executes the function
→ build_tool_result_message() creates turn-2 message
→ Engine generates final response with tool result context