使用工具调用功能,大幅提升模型实用价值与应用范围

概述

大语言模型(LLM)拥有强大的文本生成和理解能力,但在需要获取外部实时信息或执行特定功能时却存在固有的限制。为了解决这一局限,Amazon Bedrock引入了工具调用(Tool use)功能,通常也被称为函数调用(Function calling),本文章将使用Amazon Bedrock中工具调用这一定义。

工具调用允许模型识别何时需要调用外部工具来完成用户请求,并指明应该使用什么参数。这使得模型能够访问实时数据、查询专有信息库或执行特定操作,从而显著提升其实用价值和应用范围。

您可以使用Amazon Bedrock API为模型提供工具调用的能力,使其生成更加准确、实时且有价值的响应。例如,您可能有一个聊天应用程序,允许用户查询电台播放的最受欢迎的歌曲。要响应这一请求,模型需要一个能够查询并返回歌曲信息的工具。

本例会向模型提供一个工具定义,该工具能够返回特定电台的最受欢迎歌曲。当用户询问相关问题时,模型会分析请求并识别出需要使用该工具。但模型不会直接执行工具调用,而是返回一个调用请求,明确指出需要调用的工具及其所需参数(如电台名称),您的程序会作为模型的Agents来执行工具的调用操作。

您可以根据业务需求灵活实现工具,可以是REST API、数据库查询、Lambda函数或任何其他适合的技术实现。您的程序会将工具调用结果作为新的消息再发送给大模型,最终模型会生成一个完整的响应,为用户提供准确答案。

您可以使用Converse API(Converse或ConverseStream)在Amazon Bedrock中实现工具调用的功能。本文中的示例代码将会展示如何使用Converse API构建一个能够查询电台热门歌曲的应用

使用Converse API实现工具调用

要让模型通过调用工具来完成响应,您需要向模型发送消息以及一个或多个工具的定义。如果模型确定其中某个工具可以帮助生成响应,它会返回一个请求,要求您的程序调用该工具并将结果发送回模型。随后,模型会利用这些结果为原始消息生成响应。

以下步骤展示了如何通过Converse API使用工具。有关示例代码,请参阅“Converse API工具使用示例”。

Converse API工具使用示例:

https://docs.aws.amazon.com/zh_cn/bedrock/latest/userguide/tool-use-examples.html

向模型发送用户消息和工具定义

工具的定义是一个.json模式,您需要在调用Converse操作时通过toolConfig来传递参数。以下是一个工具定义示例,该工具用于获取电台播放的最受欢迎的歌曲。

{
    "tools": [
        {
            "toolSpec": {
                "name": "top_song",
                "description": "Get the most popular song played on a radio station.",
                "inputSchema": {
                    "json": {
                        "type": "object",
                        "properties": {
                            "sign": {
                                "type": "string",
                                "description": "The call sign for the radio station for which you want the most popular song. Example calls signs are WZPZ and WKRP."
                            }
                        },
                        "required": [
                            "sign"
                        ]
                    }
                }
            }
        }
    ]
}

左右滑动查看完整示意

在同一请求中,您还需要通过messages参数传递用户消息。

[
    {
        "role": "user",
        "content": [
            {
                "text": "What is the most popular song on WZPZ?"
            }
        ]
    }
]

左右滑动查看完整示意

模型返回工具调用请求

当您使用消息和工具定义调用Converse API时,模型会根据工具定义来确定是否需要使用该工具来查询信息。例如,如果您的聊天应用用户发送消息“WZPZ电台最受欢迎的歌曲是什么?”,模型会将这条消息和top_song工具定义中的描述进行匹配,并确定该工具可以帮助生成响应。

当模型决定需要使用工具来生成响应时,模型会将返回中的stopReason字段设置为tool_use。模型会识别您需要使用的工具(top_song)及其所需参数(如电台编码WZPZ),并在返回的消息中包含这些信息。您可以使用toolUseId字段在后续调用中标识工具请求。

以下示例展示了模型的响应结果。

{
    "output": {
        "message": {
            "role": "assistant",
            "content": [
                {
                    "toolUse": {
                        "toolUseId": "tooluse_kZJMlvQmRJ6eAyJE5GIl7Q",
                        "name": "top_song",
                        "input": {
                            "sign": "WZPZ"
                        }
                    }
                }
            ]
        }
    },
    "stopReason": "tool_use"
}

左右滑动查看完整示意

应用程序代表模型执行工具请求

应用程序会从模型响应的toolUse字段中获取name值来识别并调用您实现的工具,将工具响应结果和您在上一步中获取的工具请求ID作为参数传递给大模型。

{
    "role": "user",
    "content": [
        {
            "toolResult": {
                "toolUseId": "tooluse_kZJMlvQmRJ6eAyJE5GIl7Q",
                "content": [
                    {
                        "json": {
                            "song": "Elemental Hotel",
                            "artist": "8 Storey Hike"
                        }
                    }
                ]
            }
        }
    ]
}

左右滑动查看完整示意

模型返回最终响应

接下来模型将根据您在请求参数中提供的信息,为原始问题(“WZPZ电台最受欢迎的歌曲是什么?”)生成最终回复。

{
     "output": {
        "message": {
            "role": "assistant",
            "content": [
                {
                    "text": "The most popular song on WZPZ is Elemental Hotel by 8 Storey Hike."
                }
            ]
        }
    },
    "stopReason": "end_turn"

左右滑动查看完整示意

Converse API工具使用示例

以下Python示例展示了如何实现工具调用。

# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""
Shows how to use tools with the <noloc>Converse</noloc> API and the Cohere Command R model.
"""
import logging
import json
import boto3
from botocore.exceptions import ClientError
class StationNotFoundError(Exception):
    """Raised when a radio station isn't found."""
    pass
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
def get_top_song(call_sign):
    """Returns the most popular song for the requested station.
    Args:
        call_sign (str): The call sign for the station for which you want
        the most popular song.
    Returns:
        response (json): The most popular song and artist.
    """
    song = ""
    artist = ""
    if call_sign == 'WZPZ':
        song = "Elemental Hotel"
        artist = "8 Storey Hike"
    else:
        raise StationNotFoundError(f"Station {call_sign} not found.")
    return song, artist
def generate_text(bedrock_client, model_id, tool_config, input_text):
    """Generates text using the supplied Amazon Bedrock model. If necessary,
    the function handles tool use requests and sends the result to the model.
    Args:
        bedrock_client: The Boto3 Bedrock runtime client.
        model_id (str): The Amazon Bedrock model ID.
        tool_config (dict): The tool configuration.
        input_text (str): The input text.
    Returns:
        Nothing.
    """
    logger.info("Generating text with model %s", model_id)
   # Create the initial message from the user input.
    messages = [{
        "role": "user",
        "content": [{"text": input_text}]
    }]
    response = bedrock_client.converse(
        modelId=model_id,
        messages=messages,
        toolConfig=tool_config
    )
    output_message = response['output']['message']
    messages.append(output_message)
    stop_reason = response['stopReason']
    if stop_reason == 'tool_use':
        # Tool use requested. Call the tool and send the result to the model.
        tool_requests = response['output']['message']['content']
        for tool_request in tool_requests:
            if 'toolUse' in tool_request:
                tool = tool_request['toolUse']
                logger.info("Requesting tool %s. Request: %s",
                            tool['name'], tool['toolUseId'])
                if tool['name'] == 'top_song':
                    tool_result = {}
                    try:
                        song, artist = get_top_song(tool['input']['sign'])
                        tool_result = {
                            "toolUseId": tool['toolUseId'],
                            "content": [{"json": {"song": song, "artist": artist}}]
                        }
                    except StationNotFoundError as err:
                        tool_result = {
                            "toolUseId": tool['toolUseId'],
                            "content": [{"text":  err.args[0]}],
                            "status": 'error'
                        }
                    tool_result_message = {
                        "role": "user",
                        "content": [
                            {
                                "toolResult": tool_result
                            }
                        ]
                    }
                    messages.append(tool_result_message)
                    # Send the tool result to the model.
                    response = bedrock_client.converse(
                        modelId=model_id,
                        messages=messages,
                        toolConfig=tool_config
                    )
                    output_message = response['output']['message']
    # print the final response from the model.
    for content in output_message['content']:
        print(json.dumps(content, indent=4))
def main():
    """
    Entrypoint for tool use example.
    """
    logging.basicConfig(level=logging.INFO,
                        format="%(levelname)s: %(message)s")
    model_id = "cohere.command-r-v1:0"
    input_text = "What is the most popular song on WZPZ?"
    tool_config = {
    "tools": [
        {
            "toolSpec": {
                "name": "top_song",
                "description": "Get the most popular song played on a radio station.",
                "inputSchema": {
                    "json": {
                        "type": "object",
                        "properties": {
                            "sign": {
                                "type": "string",
                                "description": "The call sign for the radio station for which you want the most popular song. Example calls signs are WZPZ, and WKRP."
                            }
                        },
                        "required": [
                            "sign"
                        ]
                    }
                }
            }
        }
    ]
}
    bedrock_client = boto3.client(service_name='bedrock-runtime')
    try:
        print(f"Question: {input_text}")
        generate_text(bedrock_client, model_id, tool_config, input_text)
    except ClientError as err:
        message = err.response['Error']['Message']
        logger.error("A client error occurred: %s", message)
        print(f"A client error occured: {message}")
    else:
        print(
            f"Finished generating text with model {model_id}.")
if __name__ == "__main__":
    main()

左右滑动查看完整示意

有关其他代码示例,请参阅使用Amazon SDK的Amazon Bedrock Runtime代码示例。

使用Amazon SDK的Amazon Bedrock Runtime代码示例:

https://docs.aws.amazon.com/zh_cn/bedrock/latest/userguide/service_code_examples_bedrock-runtime.html

本篇作者

李玉光

北京聚云科技有限公司联合创始人兼首席架构师,前亚马逊云科技合作伙伴大使。拥有十几年的亚马逊云科技云服务开发与架构等经验,协助各类行业客户部署和优化生成式AI应用,显著提升企业的生产力与创新效率。

诚邀您参与「云上探索实验室」,扫描下方二维码,立即体验Amazon Bedrock,开启大模型选型的实战之旅!

星标不迷路,开发更极速!

关注后记得星标「亚马逊云开发者」

听说,点完下面4个按钮

就不会碰到bug了!

点击阅读原文查看博客!获得更详细内容!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值