

# 使用工具（函数调用）
<a name="using-tools"></a>

工具可将模型与 API、数据库及代码执行环境等外部功能相连，从而拓展 Amazon Nova 的能力。通过使用工具，Amazon Nova 能够访问实时信息、进行计算并与外部系统交互。

## 了解工具使用工作流程
<a name="tool-workflow"></a>

在 Amazon Nova 中使用工具涉及三个关键阶段：

用户查询与工具定义  
通过提供描述各工具功能与输入要求的 JSON 架构来定义工具。工具配置必须包括有关何时以及如何使用每种工具的详细描述。

工具选择  
用户发送消息时，Amazon Nova 将对消息进行分析，确定是否需要使用工具。这种自动工具选择会检查上下文并决定要调用的工具（如有）。如果 Amazon Nova 确定了合适的工具，就会返回工具名称和必填参数。  
您负责根据模型的请求执行该工具。这意味着需要编写代码来调用工具功能并处理模型提供的输入参数。

返回结果  
工具执行完毕后，以 JSON 或文本 \$1 图像组合的结构化格式，将结果回传给 Amazon Nova。Amazon Nova 可以将工具输出整合到对最终回复中。如果在执行过程中出现错误，请在工具回复中注明这一点，以便 Amazon Nova 可以进行相应调整。

## 创建工具
<a name="create-tool"></a>

通过工具配置定义工具，该配置包含工具数组，以及可选的工具选择参数。每种工具规范必须包括：
+ **名称**：工具的清晰标识符
+ **描述：**工具功能的简要说明
+ **输入架构：**定义必填参数与选填参数的 JSON 架构

**Example 工具配置示例**  

```
tool_config = {
    "tools": [
        {
            "toolSpec": {
                "name": "calculator",
                "description": "A calculator tool that can execute a math equation",
                "inputSchema": {
                    "json": {
                        "type": "object",
                        "properties": {
                            "equation": {
                                "type": "string",
                                "description": "The full equation to evaluate"
                            }
                        },
                        "required": ["equation"]
                    }
                }
            }
        }
    ]
}
```

### 工具定义最佳实践
<a name="tool-best-practices"></a>
+ 确保名称与描述明确传达工具的确切功能；避免使用语义过于相似的工具
+ 在描述中包含关键差异化因素，帮助模型区分相似的工具
+ 为获得最佳性能，将 JSON 架构限制为两层嵌套
+ 使用架构类型（例如 enum、int、float）来限制输入，而不是用纯文本描述结构
+ 使用 JSON 架构表示法标注必填参数与选填参数（例如 "required": ["param1", "param2"]）
+ 提交前使用标准验证器验证 JSON 架构
+ 将长字符串参数置于架构末尾，避免嵌套

### 带约束解码的结构化输出
<a name="structured-output"></a>

Amazon Nova 模型利用约束解码来确保生成的输出具有较高可靠性。此技术使用语法在每个生成步骤限制可能的词元，防止密钥无效，并根据您定义的架构强制使用正确的数据类型。

**Example 结构化输出示例**  

```
tool_config = {
    "tools": [
        {
            "toolSpec": {
                "name": "ProductAnalysis",
                "description": "Analyze product information from text.",
                "inputSchema": {
                    "json": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string",
                                "description": "Product name"
                            },
                            "rating": {
                                "maximum": 5,
                                "description": "Customer rating 1-5",
                                "type": ["number", "null"],
                                "minimum": 1
                            },
                            "features": {
                                "description": "Key product features",
                                "type": "array",
                                "items": {"type": "string"}
                            },
                            "category": {
                                "type": "string",
                                "description": "Product category"
                            },
                            "price": {
                                "type": "number",
                                "description": "Price in USD"
                            }
                        },
                        "required": ["name", "category", "price", "features"]
                    }
                }
            }
        }
    ],
    "toolChoice": {
        "tool": {"name": "ProductAnalysis"}
    }
}
```

### 工具选择选项
<a name="tool-choice-options"></a>

Amazon Nova 支持三个工具选择参数：

Tool  
指定工具将被调用一次，适用于结构化输出使用案例

Any  
至少调用所提供工具中的某一个，适用于 API 选择场景

Auto  
由模型决定是否调用工具以及调用工具的数量（默认行为）

## 调用工具
<a name="call-tool"></a>

Amazon Nova 决定调用工具时，会将工具使用块作为助手消息的一部分返回，且 stopReason 设置为 tool\$1use。工具块包含工具的名称及其输入。

**注意**  
在单个 Python 会话中依次运行以下代码段：调用工具 → 处理工具调用 → 返回工具执行结果。如需再次运行示例，请重启 Python 会话。

**Example 调用工具**  

```
import boto3
import json

# Create Bedrock client
bedrock = boto3.client('bedrock-runtime', region_name='us-east-1')

# Complex calculation that benefits from precise computation
messages = [{
    "role": "user",
    "content": [{
        "text": "Calculate the compound interest on $10,000 invested at 4.75% annual rate for 7 years, compounded quarterly. Use the formula A = P(1 + r/n)^(nt) where P=10000, r=0.0475, n=4, t=7"
    }]
}]

# Define tool configuration with calculator
tool_config = {
    "tools": [{
        "toolSpec": {
            "name": "calculator",
            "description": "Perform mathematical calculations",
            "inputSchema": {
                "json": {
                    "type": "object",
                    "properties": {
                        "expression": {
                            "type": "string",
                            "description": "Mathematical expression to evaluate"
                        }
                    },
                    "required": ["expression"]
                }
            }
        }
    }]
}

# Invoke Model
response = bedrock.converse(
    modelId="us.amazon.nova-2-lite-v1:0",
    messages=messages,
    toolConfig=tool_config
)

# Extract tool use from response
tool = next(
    block["toolUse"]
    for block in response["output"]["message"]["content"]
    if "toolUse" in block
)

print(f"Tool: {tool['name']}")
print(f"Expression: {tool['input']['expression']}")
```

### 处理工具调用
<a name="process-tool-calls"></a>

从消息中提取工具名称与参数，然后调用该工具：

```
def calculate(expression):
    """Evaluate mathematical expression"""
    print(f"Calculating: {expression}")
    P = 10000
    r = 0.0475
    n = 4
    t = 7
    result = P * (1 + r/n) ** (n*t)
    return result

stop_reason = response["stopReason"]

if stop_reason == "tool_use":
    if tool["name"] == "calculator":
        result = calculate(tool["input"]["expression"])
```

### 返回工具执行结果
<a name="return-tool-results"></a>

使用 ToolResultBlock 架构返回工具执行结果：

```
messages.append(response["output"]["message"])

# Add the tool result
messages.append({
    "role": "user",
    "content": [{
        "toolResult": {
            "toolUseId": tool['toolUseId'],
            "content": [{"json": {"result": result}}],
            "status": "success"
        }
    }]
})

# Send the tool result to the model
response = bedrock.converse(
    modelId="us.amazon.nova-2-lite-v1:0",
    messages=messages,
    toolConfig=tool_config
)

# Extract and display final response
final_text = next(
    block["text"]
    for block in response["output"]["message"]["content"]
    if "text" in block
)

print(f"\nFinal Response:\n{final_text}")
```

### 错误处理
<a name="tool-error-handling"></a>

将错误信息回传到 Amazon Nova，以便对请求进行修改并重试：

```
tool_result_message = {
    "role": "user",
    "content": [
        {
            "toolResult": {
                "toolUseId": tool["toolUseId"],
                "content": [{"text": "A validation exception occurred on field: sample.field"}],
                "status": "error"
            }
        }
    ]
}
```

### 安全注意事项
<a name="tool-security"></a>
+ 在调用工具之前，请确认工具是否存在
+ 确保输入的格式正确
+ 在执行工具之前，请确认是否有适当的权限
+ 基于会话详情进行处理，禁止 Amazon Nova 在工具调用中注入用户信息
+ 注意：LLM 可能会虚构工具调用，务必在执行前进行校验

## 内置系统工具
<a name="builtin-tools"></a>

Amazon Nova 2.0 模型包含完全托管的内置工具，无需自定义实现。通过 Converse API 中的简易开关即可启用这些工具。

### 代码解释器
<a name="code-interpreter"></a>

通过代码解释器，Nova 可以在隔离的沙盒环境中安全地执行 Python 代码。此工具专为数学计算、逻辑运算和迭代算法而设计。

**注意**  
代码解释器在 IAD、PDX 和 NRT AWS 区域中可用。为确保请求路由至支持的区域，请使用全局 CRIS。使用 Bedrock API 密钥时，需要手动将 `InvokeTool` 权限添加到策略定义。默认 Bedrock 角色不允许 `InvokeTool` 操作。

通过指定 systemTool 参数启用代码解释器：

```
import boto3
import json

bedrock = boto3.client('bedrock-runtime', region_name='us-east-1')

tool_config = {
    "tools": [{
        "systemTool": {
            "name": "nova_code_interpreter"
        }
    }]
}

response = bedrock.converse(
    modelId="us.amazon.nova-2-lite-v1:0",
    messages=[{
        "role": "user",
        "content": [{
            "text": "What is the average of 10, 24, 2, 3, 43, 52, 13, 68, 6, 7, 902, 82"
        }]
    }],
    toolConfig=tool_config,
    inferenceConfig={"maxTokens": 10000, "temperature": 0}
)

# Pretty print the response
for block in response["output"]["message"]["content"]:
    if "toolUse" in block:
        print("=== Tool Use ===")
        print(f"Tool: {block['toolUse']['name']}")
        print(f"Code:\n{block['toolUse']['input']['snippet']}\n")
    
    elif "toolResult" in block:
        print("=== Tool Result ===")
        result = block['toolResult']['content'][0]['json']
        print(f"Output: {result['stdOut']}")
        if result['stdErr']:
            print(f"Error: {result['stdErr']}")
        print(f"Exit Code: {result['exitCode']}\n")
    
    elif "text" in block:
        print("=== Final Answer ===")
        print(block["text"])
```

该解释器在沙盒中运行代码，并以标准架构的形式返回结果：

```
{
    "stdOut": "String",
    "stdErr": "String",
    "exitCode": "int",
    "isError": "boolean"
}
```

### Web Grounding
<a name="web-grounding-tool"></a>

通过 Web Grounding 功能，Amazon Nova 能够访问互联网中的实时信息，从而提供最新的回复并减少幻觉。通过指定 nova\$1grounding 系统工具来启用：

```
tool_config = {
    "tools": [{
        "systemTool": {"name": "nova_grounding"}
    }]
}
```

有关 Web Grounding 的详细信息，请参阅 [Web Grounding](web-grounding.md)。

### 模型上下文协议（MCP）
<a name="mcp-protocol"></a>

模型上下文协议（MCP）是一种开放标准，支持在数据来源和人工智能驱动的工具之间建立安全的双向连接。可运行 MCP 服务器，让 Amazon Nova 自动通过客户端网桥发现其工具，而不必为每个 API 或服务编写自定义适配器。

连接后，Amazon Nova 会像其他任何外部集成一样对待 MCP 工具：决定何时调用、发送所需的参数以及将结果纳入其回复中。通过内置的 MCPClient，搭配 Amazon Nova 与 Strands 使用可简化操作，该客户端能自动管理发现、连接与结果映射。