Cookie の設定を選択する

当社は、当社のサイトおよびサービスを提供するために必要な必須 Cookie および類似のツールを使用しています。当社は、パフォーマンス Cookie を使用して匿名の統計情報を収集することで、お客様が当社のサイトをどのように利用しているかを把握し、改善に役立てています。必須 Cookie は無効化できませんが、[カスタマイズ] または [拒否] をクリックしてパフォーマンス Cookie を拒否することはできます。

お客様が同意した場合、AWS および承認された第三者は、Cookie を使用して便利なサイト機能を提供したり、お客様の選択を記憶したり、関連する広告を含む関連コンテンツを表示したりします。すべての必須ではない Cookie を受け入れるか拒否するには、[受け入れる] または [拒否] をクリックしてください。より詳細な選択を行うには、[カスタマイズ] をクリックしてください。

Amazon Bedrock の AI モデルをカスタムツールまたは API に接続する方法を説明するツール使用デモ。

フォーカスモード
Amazon Bedrock の AI モデルをカスタムツールまたは API に接続する方法を説明するツール使用デモ。 - Amazon Bedrock

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

次のコード例は、アプリケーション、生成 AI モデル、接続されたツールまたは API 間の一般的なインタラクションを構築し、AI と外部世界のインタラクションを仲介する方法を示しています。外部気象 API を AI モデルに接続する例を使用して、ユーザー入力に基づいてリアルタイムの気象情報を提供します。

.NET
SDK for .NET
注記

GitHub には、その他のリソースもあります。AWS コード例リポジトリ で全く同じ例を見つけて、設定と実行の方法を確認してください。

シナリオフローのプライマリ実行。このシナリオでは、ユーザー、Amazon Bedrock Converse API、および気象ツール間の会話を調整します。

using Amazon; using Amazon.BedrockRuntime; using Amazon.BedrockRuntime.Model; using Amazon.Runtime.Documents; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; namespace ConverseToolScenario; public static class ConverseToolScenario { /* Before running this .NET code example, set up your development environment, including your credentials. This demo illustrates a tool use scenario using Amazon Bedrock's Converse API and a weather tool. The script interacts with a foundation model on Amazon Bedrock to provide weather information based on user input. It uses the Open-Meteo API (https://open-meteo.com) to retrieve current weather data for a given location. */ public static BedrockActionsWrapper _bedrockActionsWrapper = null!; public static WeatherTool _weatherTool = null!; public static bool _interactive = true; // Change this string to use a different model with Converse API. private static string model_id = "amazon.nova-lite-v1:0"; private static string system_prompt = @" You are a weather assistant that provides current weather data for user-specified locations using only the Weather_Tool, which expects latitude and longitude. Infer the coordinates from the location yourself. If the user specifies a state, country, or region, infer the locations of cities within that state. If the user provides coordinates, infer the approximate location and refer to it in your response. To use the tool, you strictly apply the provided tool specification. - Explain your step-by-step process, and give brief updates before each step. - Only use the Weather_Tool for data. Never guess or make up information. - Repeat the tool use for subsequent requests if necessary. - If the tool errors, apologize, explain weather is unavailable, and suggest other options. - Report temperatures in °C (°F) and wind in km/h (mph). Keep weather reports concise. Sparingly use emojis where appropriate. - Only respond to weather queries. Remind off-topic users of your purpose. - Never claim to search online, access external data, or use tools besides Weather_Tool. - Complete the entire process until you have all required data before sending the complete response. " ; private static string default_prompt = "What is the weather like in Seattle?"; // The maximum number of recursive calls allowed in the tool use function. // This helps prevent infinite loops and potential performance issues. private static int max_recursions = 5; public static async Task Main(string[] args) { // Set up dependency injection for the Amazon service. using var host = Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => logging.AddFilter("System", LogLevel.Error) .AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace)) .ConfigureServices((_, services) => services.AddHttpClient() .AddSingleton<IAmazonBedrockRuntime>(_ => new AmazonBedrockRuntimeClient(RegionEndpoint.USEast1)) // Specify a region that has access to the chosen model. .AddTransient<BedrockActionsWrapper>() .AddTransient<WeatherTool>() .RemoveAll<IHttpMessageHandlerBuilderFilter>() ) .Build(); ServicesSetup(host); try { await RunConversationAsync(); } catch (Exception ex) { Console.WriteLine(new string('-', 80)); Console.WriteLine($"There was a problem running the scenario: {ex.Message}"); Console.WriteLine(new string('-', 80)); } finally { Console.WriteLine( "Amazon Bedrock Converse API with Tool Use Feature Scenario is complete."); Console.WriteLine(new string('-', 80)); } } /// <summary> /// Populate the services for use within the console application. /// </summary> /// <param name="host">The services host.</param> private static void ServicesSetup(IHost host) { _bedrockActionsWrapper = host.Services.GetRequiredService<BedrockActionsWrapper>(); _weatherTool = host.Services.GetRequiredService<WeatherTool>(); } /// <summary> /// Starts the conversation with the user and handles the interaction with Bedrock. /// </summary> /// <returns>The conversation array.</returns> public static async Task<List<Message>> RunConversationAsync() { // Print the greeting and a short user guide PrintHeader(); // Start with an empty conversation var conversation = new List<Message>(); // Get the first user input var userInput = await GetUserInputAsync(); while (userInput != null) { // Create a new message with the user input and append it to the conversation var message = new Message { Role = ConversationRole.User, Content = new List<ContentBlock> { new ContentBlock { Text = userInput } } }; conversation.Add(message); // Send the conversation to Amazon Bedrock var bedrockResponse = await SendConversationToBedrock(conversation); // Recursively handle the model's response until the model has returned its final response or the recursion counter has reached 0 await ProcessModelResponseAsync(bedrockResponse, conversation, max_recursions); // Repeat the loop until the user decides to exit the application userInput = await GetUserInputAsync(); } PrintFooter(); return conversation; } /// <summary> /// Sends the conversation, the system prompt, and the tool spec to Amazon Bedrock, and returns the response. /// </summary> /// <param name="conversation">The conversation history including the next message to send.</param> /// <returns>The response from Amazon Bedrock.</returns> private static async Task<ConverseResponse> SendConversationToBedrock(List<Message> conversation) { Console.WriteLine("\tCalling Bedrock..."); // Send the conversation, system prompt, and tool configuration, and return the response return await _bedrockActionsWrapper.SendConverseRequestAsync(model_id, system_prompt, conversation, _weatherTool.GetToolSpec()); } /// <summary> /// Processes the response received via Amazon Bedrock and performs the necessary actions based on the stop reason. /// </summary> /// <param name="modelResponse">The model's response returned via Amazon Bedrock.</param> /// <param name="conversation">The conversation history.</param> /// <param name="maxRecursion">The maximum number of recursive calls allowed.</param> private static async Task ProcessModelResponseAsync(ConverseResponse modelResponse, List<Message> conversation, int maxRecursion) { if (maxRecursion <= 0) { // Stop the process, the number of recursive calls could indicate an infinite loop Console.WriteLine("\tWarning: Maximum number of recursions reached. Please try again."); } // Append the model's response to the ongoing conversation conversation.Add(modelResponse.Output.Message); if (modelResponse.StopReason == "tool_use") { // If the stop reason is "tool_use", forward everything to the tool use handler await HandleToolUseAsync(modelResponse.Output, conversation, maxRecursion - 1); } if (modelResponse.StopReason == "end_turn") { // If the stop reason is "end_turn", print the model's response text, and finish the process PrintModelResponse(modelResponse.Output.Message.Content[0].Text); if (!_interactive) { default_prompt = "x"; } } } /// <summary> /// Handles the tool use case by invoking the specified tool and sending the tool's response back to Bedrock. /// The tool response is appended to the conversation, and the conversation is sent back to Amazon Bedrock for further processing. /// </summary> /// <param name="modelResponse">The model's response containing the tool use request.</param> /// <param name="conversation">The conversation history.</param> /// <param name="maxRecursion">The maximum number of recursive calls allowed.</param> public static async Task HandleToolUseAsync(ConverseOutput modelResponse, List<Message> conversation, int maxRecursion) { // Initialize an empty list of tool results var toolResults = new List<ContentBlock>(); // The model's response can consist of multiple content blocks foreach (var contentBlock in modelResponse.Message.Content) { if (!String.IsNullOrEmpty(contentBlock.Text)) { // If the content block contains text, print it to the console PrintModelResponse(contentBlock.Text); } if (contentBlock.ToolUse != null) { // If the content block is a tool use request, forward it to the tool var toolResponse = await InvokeTool(contentBlock.ToolUse); // Add the tool use ID and the tool's response to the list of results toolResults.Add(new ContentBlock { ToolResult = new ToolResultBlock() { ToolUseId = toolResponse.ToolUseId, Content = new List<ToolResultContentBlock>() { new ToolResultContentBlock { Json = toolResponse.Content } } } }); } } // Embed the tool results in a new user message var message = new Message() { Role = ConversationRole.User, Content = toolResults }; // Append the new message to the ongoing conversation conversation.Add(message); // Send the conversation to Amazon Bedrock var response = await SendConversationToBedrock(conversation); // Recursively handle the model's response until the model has returned its final response or the recursion counter has reached 0 await ProcessModelResponseAsync(response, conversation, maxRecursion); } /// <summary> /// Invokes the specified tool with the given payload and returns the tool's response. /// If the requested tool does not exist, an error message is returned. /// </summary> /// <param name="payload">The payload containing the tool name and input data.</param> /// <returns>The tool's response or an error message.</returns> public static async Task<ToolResponse> InvokeTool(ToolUseBlock payload) { var toolName = payload.Name; if (toolName == "Weather_Tool") { var inputData = payload.Input.AsDictionary(); PrintToolUse(toolName, inputData); // Invoke the weather tool with the input data provided var weatherResponse = await _weatherTool.FetchWeatherDataAsync(inputData["latitude"].ToString(), inputData["longitude"].ToString()); return new ToolResponse { ToolUseId = payload.ToolUseId, Content = weatherResponse }; } else { var errorMessage = $"\tThe requested tool with name '{toolName}' does not exist."; return new ToolResponse { ToolUseId = payload.ToolUseId, Content = new { error = true, message = errorMessage } }; } } /// <summary> /// Prompts the user for input and returns the user's response. /// Returns null if the user enters 'x' to exit. /// </summary> /// <param name="prompt">The prompt to display to the user.</param> /// <returns>The user's input or null if the user chooses to exit.</returns> private static async Task<string?> GetUserInputAsync(string prompt = "\tYour weather info request:") { var userInput = default_prompt; if (_interactive) { Console.WriteLine(new string('*', 80)); Console.WriteLine($"{prompt} (x to exit): \n\t"); userInput = Console.ReadLine(); } if (string.IsNullOrWhiteSpace(userInput)) { prompt = "\tPlease enter your weather info request, e.g. the name of a city"; return await GetUserInputAsync(prompt); } if (userInput.ToLowerInvariant() == "x") { return null; } return userInput; } /// <summary> /// Logs the welcome message and usage guide for the tool use demo. /// </summary> public static void PrintHeader() { Console.WriteLine(@" ================================================= Welcome to the Amazon Bedrock Tool Use demo! ================================================= This assistant provides current weather information for user-specified locations. You can ask for weather details by providing the location name or coordinates. Weather information will be provided using a custom Tool and open-meteo API. Example queries: - What's the weather like in New York? - Current weather for latitude 40.70, longitude -74.01 - Is it warmer in Rome or Barcelona today? To exit the program, simply type 'x' and press Enter. P.S.: You're not limited to single locations, or even to using English! Have fun and experiment with the app! "); } /// <summary> /// Logs the footer information for the tool use demo. /// </summary> public static void PrintFooter() { Console.WriteLine(@" ================================================= Thank you for checking out the Amazon Bedrock Tool Use demo. We hope you learned something new, or got some inspiration for your own apps today! For more Bedrock examples in different programming languages, have a look at: https://docs.aws.amazon.com/bedrock/latest/userguide/service_code_examples.html ================================================= "); } /// <summary> /// Logs information about the tool use. /// </summary> /// <param name="toolName">The name of the tool being used.</param> /// <param name="inputData">The input data for the tool.</param> public static void PrintToolUse(string toolName, Dictionary<string, Document> inputData) { Console.WriteLine($"\n\tInvoking tool: {toolName} with input: {inputData["latitude"].ToString()}, {inputData["longitude"].ToString()}...\n"); } /// <summary> /// Logs the model's response. /// </summary> /// <param name="message">The model's response message.</param> public static void PrintModelResponse(string message) { Console.WriteLine("\tThe model's response:\n"); Console.WriteLine(message); Console.WriteLine(); } }

デモで使用される気象ツール。このファイルは、ツール仕様を定義し、Open-Meteo API から を使用して気象データを取得するロジックを実装します。

using Amazon.BedrockRuntime.Model; using Amazon.Runtime.Documents; using Microsoft.Extensions.Logging; namespace ConverseToolScenario; /// <summary> /// Weather tool that will be invoked when requested by the Bedrock response. /// </summary> public class WeatherTool { private readonly ILogger<WeatherTool> _logger; private readonly IHttpClientFactory _httpClientFactory; public WeatherTool(ILogger<WeatherTool> logger, IHttpClientFactory httpClientFactory) { _logger = logger; _httpClientFactory = httpClientFactory; } /// <summary> /// Returns the JSON Schema specification for the Weather tool. The tool specification /// defines the input schema and describes the tool's functionality. /// For more information, see https://json-schema.org/understanding-json-schema/reference. /// </summary> /// <returns>The tool specification for the Weather tool.</returns> public ToolSpecification GetToolSpec() { ToolSpecification toolSpecification = new ToolSpecification(); toolSpecification.Name = "Weather_Tool"; toolSpecification.Description = "Get the current weather for a given location, based on its WGS84 coordinates."; Document toolSpecDocument = Document.FromObject( new { type = "object", properties = new { latitude = new { type = "string", description = "Geographical WGS84 latitude of the location." }, longitude = new { type = "string", description = "Geographical WGS84 longitude of the location." } }, required = new[] { "latitude", "longitude" } }); toolSpecification.InputSchema = new ToolInputSchema() { Json = toolSpecDocument }; return toolSpecification; } /// <summary> /// Fetches weather data for the given latitude and longitude using the Open-Meteo API. /// Returns the weather data or an error message if the request fails. /// </summary> /// <param name="latitude">The latitude of the location.</param> /// <param name="longitude">The longitude of the location.</param> /// <returns>The weather data or an error message.</returns> public async Task<Document> FetchWeatherDataAsync(string latitude, string longitude) { string endpoint = "https://api.open-meteo.com/v1/forecast"; try { var httpClient = _httpClientFactory.CreateClient(); var response = await httpClient.GetAsync($"{endpoint}?latitude={latitude}&longitude={longitude}&current_weather=True"); response.EnsureSuccessStatusCode(); var weatherData = await response.Content.ReadAsStringAsync(); Document weatherDocument = Document.FromObject( new { weather_data = weatherData }); return weatherDocument; } catch (HttpRequestException e) { _logger.LogError(e, "Error fetching weather data: {Message}", e.Message); throw; } catch (Exception e) { _logger.LogError(e, "Unexpected error fetching weather data: {Message}", e.Message); throw; } } }

ツール設定を使用した Converse API アクション。

/// <summary> /// Wrapper class for interacting with the Amazon Bedrock Converse API. /// </summary> public class BedrockActionsWrapper { private readonly IAmazonBedrockRuntime _bedrockClient; private readonly ILogger<BedrockActionsWrapper> _logger; /// <summary> /// Initializes a new instance of the <see cref="BedrockActionsWrapper"/> class. /// </summary> /// <param name="bedrockClient">The Bedrock Converse API client.</param> /// <param name="logger">The logger instance.</param> public BedrockActionsWrapper(IAmazonBedrockRuntime bedrockClient, ILogger<BedrockActionsWrapper> logger) { _bedrockClient = bedrockClient; _logger = logger; } /// <summary> /// Sends a Converse request to the Amazon Bedrock Converse API. /// </summary> /// <param name="modelId">The Bedrock Model Id.</param> /// <param name="systemPrompt">A system prompt instruction.</param> /// <param name="conversation">The array of messages in the conversation.</param> /// <param name="toolSpec">The specification for a tool.</param> /// <returns>The response of the model.</returns> public async Task<ConverseResponse> SendConverseRequestAsync(string modelId, string systemPrompt, List<Message> conversation, ToolSpecification toolSpec) { try { var request = new ConverseRequest() { ModelId = modelId, System = new List<SystemContentBlock>() { new SystemContentBlock() { Text = systemPrompt } }, Messages = conversation, ToolConfig = new ToolConfiguration() { Tools = new List<Tool>() { new Tool() { ToolSpec = toolSpec } } } }; var response = await _bedrockClient.ConverseAsync(request); return response; } catch (ModelNotReadyException ex) { _logger.LogError(ex, "Model not ready, please wait and try again."); throw; } catch (AmazonBedrockRuntimeException ex) { _logger.LogError(ex, "Error occurred while sending Converse request."); throw; } } }
  • API の詳細については、「AWS SDK for .NET API リファレンス」の「Converse」を参照してください。

Java
SDK for Java 2.x
注記

GitHub には、その他のリソースもあります。AWS コード例リポジトリ で全く同じ例を見つけて、設定と実行の方法を確認してください。

シナリオフローのプライマリ実行。このシナリオでは、ユーザー、Amazon Bedrock Converse API、および気象ツール間の会話を調整します。

/* This demo illustrates a tool use scenario using Amazon Bedrock's Converse API and a weather tool. The program interacts with a foundation model on Amazon Bedrock to provide weather information based on user input. It uses the Open-Meteo API (https://open-meteo.com) to retrieve current weather data for a given location. */ public class BedrockScenario { public static final String DASHES = new String(new char[80]).replace("\0", "-"); private static String modelId = "amazon.nova-lite-v1:0"; private static String defaultPrompt = "What is the weather like in Seattle?"; private static WeatherTool weatherTool = new WeatherTool(); // The maximum number of recursive calls allowed in the tool use function. // This helps prevent infinite loops and potential performance issues. private static int maxRecursions = 5; static BedrockActions bedrockActions = new BedrockActions(); public static boolean interactive = true; private static final String systemPrompt = """ You are a weather assistant that provides current weather data for user-specified locations using only the Weather_Tool, which expects latitude and longitude. Infer the coordinates from the location yourself. If the user provides coordinates, infer the approximate location and refer to it in your response. To use the tool, you strictly apply the provided tool specification. - Explain your step-by-step process, and give brief updates before each step. - Only use the Weather_Tool for data. Never guess or make up information. - Repeat the tool use for subsequent requests if necessary. - If the tool errors, apologize, explain weather is unavailable, and suggest other options. - Report temperatures in °C (°F) and wind in km/h (mph). Keep weather reports concise. Sparingly use emojis where appropriate. - Only respond to weather queries. Remind off-topic users of your purpose. - Never claim to search online, access external data, or use tools besides Weather_Tool. - Complete the entire process until you have all required data before sending the complete response. """; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println(""" ================================================= Welcome to the Amazon Bedrock Tool Use demo! ================================================= This assistant provides current weather information for user-specified locations. You can ask for weather details by providing the location name or coordinates. Example queries: - What's the weather like in New York? - Current weather for latitude 40.70, longitude -74.01 - Is it warmer in Rome or Barcelona today? To exit the program, simply type 'x' and press Enter. P.S.: You're not limited to single locations, or even to using English! Have fun and experiment with the app! """); System.out.println(DASHES); try { runConversation(scanner); } catch (Exception ex) { System.out.println("There was a problem running the scenario: " + ex.getMessage()); } waitForInputToContinue(scanner); System.out.println(DASHES); System.out.println("Amazon Bedrock Converse API with Tool Use Feature Scenario is complete."); System.out.println(DASHES); } /** * Starts the conversation with the user and handles the interaction with Bedrock. */ private static List<Message> runConversation(Scanner scanner) { List<Message> conversation = new ArrayList<>(); // Get the first user input String userInput = getUserInput("Your weather info request:", scanner); System.out.println(userInput); while (userInput != null) { ContentBlock block = ContentBlock.builder() .text(userInput) .build(); List<ContentBlock> blockList = new ArrayList<>(); blockList.add(block); Message message = Message.builder() .role(ConversationRole.USER) .content(blockList) .build(); conversation.add(message); // Send the conversation to Amazon Bedrock. ConverseResponse bedrockResponse = sendConversationToBedrock(conversation); // Recursively handle the model's response until the model has returned its final response or the recursion counter has reached 0. processModelResponse(bedrockResponse, conversation, maxRecursions); // Repeat the loop until the user decides to exit the application. userInput = getUserInput("Your weather info request:", scanner); } printFooter(); return conversation; } /** * Processes the response from the model and updates the conversation accordingly. * * @param modelResponse the response from the model * @param conversation the ongoing conversation * @param maxRecursion the maximum number of recursions allowed */ private static void processModelResponse(ConverseResponse modelResponse, List<Message> conversation, int maxRecursion) { if (maxRecursion <= 0) { // Stop the process, the number of recursive calls could indicate an infinite loop System.out.println("\tWarning: Maximum number of recursions reached. Please try again."); } // Append the model's response to the ongoing conversation conversation.add(modelResponse.output().message()); String modelResponseVal = modelResponse.stopReasonAsString(); if (modelResponseVal.compareTo("tool_use") == 0) { // If the stop reason is "tool_use", forward everything to the tool use handler handleToolUse(modelResponse.output(), conversation, maxRecursion - 1); } if (modelResponseVal.compareTo("end_turn") == 0) { // If the stop reason is "end_turn", print the model's response text, and finish the process PrintModelResponse(modelResponse.output().message().content().get(0).text()); if (!interactive) { defaultPrompt = "x"; } } } /** * Handles the use of a tool by the model in a conversation. * * @param modelResponse the response from the model, which may include a tool use request * @param conversation the current conversation, which will be updated with the tool use results * @param maxRecursion the maximum number of recursive calls allowed to handle the model's response */ private static void handleToolUse(ConverseOutput modelResponse, List<Message> conversation, int maxRecursion) { List<ContentBlock> toolResults = new ArrayList<>(); // The model's response can consist of multiple content blocks for (ContentBlock contentBlock : modelResponse.message().content()) { if (contentBlock.text() != null && !contentBlock.text().isEmpty()) { // If the content block contains text, print it to the console PrintModelResponse(contentBlock.text()); } if (contentBlock.toolUse() != null) { ToolResponse toolResponse = invokeTool(contentBlock.toolUse()); // Add the tool use ID and the tool's response to the list of results List<ToolResultContentBlock> contentBlockList = new ArrayList<>(); ToolResultContentBlock block = ToolResultContentBlock.builder() .json(toolResponse.getContent()) .build(); contentBlockList.add(block); ToolResultBlock toolResultBlock = ToolResultBlock.builder() .toolUseId(toolResponse.getToolUseId()) .content(contentBlockList) .build(); ContentBlock contentBlock1 = ContentBlock.builder() .toolResult(toolResultBlock) .build(); toolResults.add(contentBlock1); } } // Embed the tool results in a new user message Message message = Message.builder() .role(ConversationRole.USER) .content(toolResults) .build(); // Append the new message to the ongoing conversation //conversation.add(message); conversation.add(message); // Send the conversation to Amazon Bedrock var response = sendConversationToBedrock(conversation); // Recursively handle the model's response until the model has returned its final response or the recursion counter has reached 0 processModelResponse(response, conversation, maxRecursion); } // Invokes the specified tool with the given payload and returns the tool's response. // If the requested tool does not exist, an error message is returned. private static ToolResponse invokeTool(ToolUseBlock payload) { String toolName = payload.name(); if (Objects.equals(toolName, "Weather_Tool")) { Map<String, Document> inputData = payload.input().asMap(); printToolUse(toolName, inputData); // Invoke the weather tool with the input data provided Document weatherResponse = weatherTool.fetchWeatherData(inputData.get("latitude").toString(), inputData.get("longitude").toString()); ToolResponse toolResponse = new ToolResponse(); toolResponse.setContent(weatherResponse); toolResponse.setToolUseId(payload.toolUseId()); return toolResponse; } else { String errorMessage = "The requested tool with name " + toolName + " does not exist."; System.out.println(errorMessage); return null; } } public static void printToolUse(String toolName, Map<String, Document> inputData) { System.out.println("Invoking tool: " + toolName + " with input: " + inputData.get("latitude").toString() + ", " + inputData.get("longitude").toString() + "..."); } private static void PrintModelResponse(String message) { System.out.println("\tThe model's response:\n"); System.out.println(message); System.out.println(""); } private static ConverseResponse sendConversationToBedrock(List<Message> conversation) { System.out.println("Calling Bedrock..."); try { return bedrockActions.sendConverseRequestAsync(modelId, systemPrompt, conversation, weatherTool.getToolSpec()); } catch (ModelNotReadyException ex) { System.err.println("Model is not ready. Please try again later: " + ex.getMessage()); throw ex; } catch (BedrockRuntimeException ex) { System.err.println("Bedrock service error: " + ex.getMessage()); throw ex; } catch (RuntimeException ex) { System.err.println("Unexpected error occurred: " + ex.getMessage()); throw ex; } } private static ConverseResponse sendConversationToBedrockwithSpec(List<Message> conversation, ToolSpecification toolSpec) { System.out.println("Calling Bedrock..."); // Send the conversation, system prompt, and tool configuration, and return the response return bedrockActions.sendConverseRequestAsync(modelId, systemPrompt, conversation, toolSpec); } public static String getUserInput(String prompt, Scanner scanner) { String userInput = defaultPrompt; if (interactive) { System.out.println("*".repeat(80)); System.out.println(prompt + " (x to exit): \n\t"); userInput = scanner.nextLine(); } if (userInput == null || userInput.trim().isEmpty()) { return getUserInput("\tPlease enter your weather info request, e.g., the name of a city", scanner); } if (userInput.equalsIgnoreCase("x")) { return null; } return userInput; } private static void waitForInputToContinue(Scanner scanner) { while (true) { System.out.println(""); System.out.println("Enter 'c' followed by <ENTER> to continue:"); String input = scanner.nextLine(); if (input.trim().equalsIgnoreCase("c")) { System.out.println("Continuing with the program..."); System.out.println(""); break; } else { // Handle invalid input. System.out.println("Invalid input. Please try again."); } } } public static void printFooter() { System.out.println(""" ================================================= Thank you for checking out the Amazon Bedrock Tool Use demo. We hope you learned something new, or got some inspiration for your own apps today! For more Bedrock examples in different programming languages, have a look at: https://docs.aws.amazon.com/bedrock/latest/userguide/service_code_examples.html ================================================= """); } }

デモで使用される気象ツール。このファイルは、ツール仕様を定義し、Open-Meteo API から を使用して気象データを取得するロジックを実装します。

public class WeatherTool { private static final Logger logger = LoggerFactory.getLogger(WeatherTool.class); private static java.net.http.HttpClient httpClient = null; /** * Returns the JSON Schema specification for the Weather tool. The tool specification * defines the input schema and describes the tool's functionality. * For more information, see https://json-schema.org/understanding-json-schema/reference. * * @return The tool specification for the Weather tool. */ public ToolSpecification getToolSpec() { Map<String, Document> latitudeMap = new HashMap<>(); latitudeMap.put("type", Document.fromString("string")); latitudeMap.put("description", Document.fromString("Geographical WGS84 latitude of the location.")); // Create the nested "longitude" object Map<String, Document> longitudeMap = new HashMap<>(); longitudeMap.put("type", Document.fromString("string")); longitudeMap.put("description", Document.fromString("Geographical WGS84 longitude of the location.")); // Create the "properties" object Map<String, Document> propertiesMap = new HashMap<>(); propertiesMap.put("latitude", Document.fromMap(latitudeMap)); propertiesMap.put("longitude", Document.fromMap(longitudeMap)); // Create the "required" array List<Document> requiredList = new ArrayList<>(); requiredList.add(Document.fromString("latitude")); requiredList.add(Document.fromString("longitude")); // Create the root object Map<String, Document> rootMap = new HashMap<>(); rootMap.put("type", Document.fromString("object")); rootMap.put("properties", Document.fromMap(propertiesMap)); rootMap.put("required", Document.fromList(requiredList)); // Now create the Document representing the JSON schema Document document = Document.fromMap(rootMap); ToolSpecification specification = ToolSpecification.builder() .name("Weather_Tool") .description("Get the current weather for a given location, based on its WGS84 coordinates.") .inputSchema(ToolInputSchema.builder() .json(document) .build()) .build(); return specification; } /** * Fetches weather data for the given latitude and longitude. * * @param latitude the latitude coordinate * @param longitude the longitude coordinate * @return a {@link CompletableFuture} containing the weather data as a JSON string */ public Document fetchWeatherData(String latitude, String longitude) { HttpClient httpClient = HttpClient.newHttpClient(); // Ensure no extra double quotes latitude = latitude.replace("\"", ""); longitude = longitude.replace("\"", ""); String endpoint = "https://api.open-meteo.com/v1/forecast"; String url = String.format("%s?latitude=%s&longitude=%s&current_weather=True", endpoint, latitude, longitude); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .build(); try { HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { String weatherJson = response.body(); System.out.println(weatherJson); ObjectMapper objectMapper = new ObjectMapper(); Map<String, Object> rawMap = objectMapper.readValue(weatherJson, new TypeReference<Map<String, Object>>() {}); Map<String, Document> documentMap = convertToDocumentMap(rawMap); Document weatherDocument = Document.fromMap(documentMap); System.out.println(weatherDocument); return weatherDocument; } else { throw new RuntimeException("Error fetching weather data: " + response.statusCode()); } } catch (Exception e) { System.out.println("Error fetching weather data: " + e.getMessage()); throw new RuntimeException("Error fetching weather data", e); } } private static Map<String, Document> convertToDocumentMap(Map<String, Object> inputMap) { Map<String, Document> result = new HashMap<>(); for (Map.Entry<String, Object> entry : inputMap.entrySet()) { result.put(entry.getKey(), convertToDocument(entry.getValue())); } return result; } // Convert different types of Objects to Document private static Document convertToDocument(Object value) { if (value instanceof Map) { return Document.fromMap(convertToDocumentMap((Map<String, Object>) value)); } else if (value instanceof Integer) { return Document.fromNumber(SdkNumber.fromInteger((Integer) value)); } else if (value instanceof Double) { // return Document.fromNumber(SdkNumber.fromDouble((Double) value)); } else if (value instanceof Boolean) { return Document.fromBoolean((Boolean) value); } else if (value instanceof String) { return Document.fromString((String) value); } return Document.fromNull(); // Handle null values safely } }

ツール設定を使用した Converse API アクション。

/** * Sends an asynchronous converse request to the AI model. * * @param modelId the unique identifier of the AI model to be used for the converse request * @param systemPrompt the system prompt to be included in the converse request * @param conversation a list of messages representing the conversation history * @param toolSpec the specification of the tool to be used in the converse request * @return the converse response received from the AI model */ public ConverseResponse sendConverseRequestAsync(String modelId, String systemPrompt, List<Message> conversation, ToolSpecification toolSpec) { List<Tool> toolList = new ArrayList<>(); Tool tool = Tool.builder() .toolSpec(toolSpec) .build(); toolList.add(tool); ToolConfiguration configuration = ToolConfiguration.builder() .tools(toolList) .build(); SystemContentBlock block = SystemContentBlock.builder() .text(systemPrompt) .build(); ConverseRequest request = ConverseRequest.builder() .modelId(modelId) .system(block) .messages(conversation) .toolConfig(configuration) .build(); try { ConverseResponse response = getClient().converse(request).join(); return response; } catch (ModelNotReadyException ex) { throw new RuntimeException("Model is not ready: " + ex.getMessage(), ex); } catch (BedrockRuntimeException ex) { throw new RuntimeException("Failed to converse with Bedrock model: " + ex.getMessage(), ex); } }
  • API の詳細については、「AWS SDK for Java 2.x API リファレンス」の「Converse」を参照してください。

JavaScript
SDK for JavaScript (v3)
注記

GitHub には、その他のリソースもあります。AWS コード例リポジトリ で全く同じ例を見つけて、設定と実行の方法を確認してください。

シナリオフローのプライマリ実行。このシナリオでは、ユーザー、Amazon Bedrock Converse API、および気象ツール間の会話を調整します。

/* Before running this JavaScript code example, set up your development environment, including your credentials. This demo illustrates a tool use scenario using Amazon Bedrock's Converse API and a weather tool. The script interacts with a foundation model on Amazon Bedrock to provide weather information based on user input. It uses the Open-Meteo API (https://open-meteo.com) to retrieve current weather data for a given location.*/ import { Scenario, ScenarioAction, ScenarioInput, ScenarioOutput, } from "@aws-doc-sdk-examples/lib/scenario/index.js"; import { BedrockRuntimeClient, ConverseCommand, } from "@aws-sdk/client-bedrock-runtime"; import { parseArgs } from "node:util"; import { fileURLToPath } from "node:url"; import { dirname } from "node:path"; const __filename = fileURLToPath(import.meta.url); import data from "./questions.json" with { type: "json" }; import toolConfig from "./tool_config.json" with { type: "json" }; const systemPrompt = [ { text: "You are a weather assistant that provides current weather data for user-specified locations using only\n" + "the Weather_Tool, which expects latitude and longitude. Infer the coordinates from the location yourself.\n" + "If the user provides coordinates, infer the approximate location and refer to it in your response.\n" + "To use the tool, you strictly apply the provided tool specification.\n" + "If the user specifies a state, country, or region, infer the locations of cities within that state.\n" + "\n" + "- Explain your step-by-step process, and give brief updates before each step.\n" + "- Only use the Weather_Tool for data. Never guess or make up information. \n" + "- Repeat the tool use for subsequent requests if necessary.\n" + "- If the tool errors, apologize, explain weather is unavailable, and suggest other options.\n" + "- Report temperatures in °C (°F) and wind in km/h (mph). Keep weather reports concise. Sparingly use\n" + " emojis where appropriate.\n" + "- Only respond to weather queries. Remind off-topic users of your purpose. \n" + "- Never claim to search online, access external data, or use tools besides Weather_Tool.\n" + "- Complete the entire process until you have all required data before sending the complete response.", }, ]; const tools_config = toolConfig; /// Starts the conversation with the user and handles the interaction with Bedrock. async function askQuestion(userMessage) { // The maximum number of recursive calls allowed in the tool use function. // This helps prevent infinite loops and potential performance issues. const max_recursions = 5; const messages = [ { role: "user", content: [{ text: userMessage }], }, ]; try { const response = await SendConversationtoBedrock(messages); await ProcessModelResponseAsync(response, messages, max_recursions); } catch (error) { console.log("error ", error); } } // Sends the conversation, the system prompt, and the tool spec to Amazon Bedrock, and returns the response. // param "messages" - The conversation history including the next message to send. // return - The response from Amazon Bedrock. async function SendConversationtoBedrock(messages) { const bedRockRuntimeClient = new BedrockRuntimeClient({ region: "us-east-1", }); try { const modelId = "amazon.nova-lite-v1:0"; const response = await bedRockRuntimeClient.send( new ConverseCommand({ modelId: modelId, messages: messages, system: systemPrompt, toolConfig: tools_config, }), ); return response; } catch (caught) { if (caught.name === "ModelNotReady") { console.log( "`${caught.name}` - Model not ready, please wait and try again.", ); throw caught; } if (caught.name === "BedrockRuntimeException") { console.log( '`${caught.name}` - "Error occurred while sending Converse request.', ); throw caught; } } } // Processes the response received via Amazon Bedrock and performs the necessary actions based on the stop reason. // param "response" - The model's response returned via Amazon Bedrock. // param "messages" - The conversation history. // param "max_recursions" - The maximum number of recursive calls allowed. async function ProcessModelResponseAsync(response, messages, max_recursions) { if (max_recursions <= 0) { await HandleToolUseAsync(response, messages); } if (response.stopReason === "tool_use") { await HandleToolUseAsync(response, messages, max_recursions - 1); } if (response.stopReason === "end_turn") { const messageToPrint = response.output.message.content[0].text; console.log(messageToPrint.replace(/<[^>]+>/g, "")); } } // Handles the tool use case by invoking the specified tool and sending the tool's response back to Bedrock. // The tool response is appended to the conversation, and the conversation is sent back to Amazon Bedrock for further processing. // param "response" - the model's response containing the tool use request. // param "messages" - the conversation history. // param "max_recursions" - The maximum number of recursive calls allowed. async function HandleToolUseAsync(response, messages, max_recursions) { const toolResultFinal = []; try { const output_message = response.output.message; messages.push(output_message); const toolRequests = output_message.content; const toolMessage = toolRequests[0].text; console.log(toolMessage.replace(/<[^>]+>/g, "")); for (const toolRequest of toolRequests) { if (Object.hasOwn(toolRequest, "toolUse")) { const toolUse = toolRequest.toolUse; const latitude = toolUse.input.latitude; const longitude = toolUse.input.longitude; const toolUseID = toolUse.toolUseId; console.log( `Requesting tool ${toolUse.name}, Tool use id ${toolUseID}`, ); if (toolUse.name === "Weather_Tool") { try { const current_weather = await callWeatherTool( longitude, latitude, ).then((current_weather) => current_weather); const currentWeather = current_weather; const toolResult = { toolResult: { toolUseId: toolUseID, content: [{ json: currentWeather }], }, }; toolResultFinal.push(toolResult); } catch (err) { console.log("An error occurred. ", err); } } } } const toolResultMessage = { role: "user", content: toolResultFinal, }; messages.push(toolResultMessage); // Send the conversation to Amazon Bedrock await ProcessModelResponseAsync( await SendConversationtoBedrock(messages), messages, ); } catch (error) { console.log("An error occurred. ", error); } } // Call the Weathertool. // param = longitude of location // param = latitude of location async function callWeatherTool(longitude, latitude) { // Open-Meteo API endpoint const apiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current_weather=true`; // Fetch the weather data. return fetch(apiUrl) .then((response) => { return response.json().then((current_weather) => { return current_weather; }); }) .catch((error) => { console.error("Error fetching weather data:", error); }); } /** * Used repeatedly to have the user press enter. * @type {ScenarioInput} */ const pressEnter = new ScenarioInput("continue", "Press Enter to continue", { type: "input", }); const greet = new ScenarioOutput( "greet", "Welcome to the Amazon Bedrock Tool Use demo! \n" + "This assistant provides current weather information for user-specified locations. " + "You can ask for weather details by providing the location name or coordinates." + "Weather information will be provided using a custom Tool and open-meteo API." + "For the purposes of this example, we'll use in order the questions in ./questions.json :\n" + "What's the weather like in Seattle? " + "What's the best kind of cat? " + "Where is the warmest city in Washington State right now? " + "What's the warmest city in California right now?\n" + "To exit the program, simply type 'x' and press Enter.\n" + "Have fun and experiment with the app by editing the questions in ./questions.json! " + "P.S.: You're not limited to single locations, or even to using English! ", { header: true }, ); const displayAskQuestion1 = new ScenarioOutput( "displayAskQuestion1", "Press enter to ask question number 1 (default is 'What's the weather like in Seattle?')", ); const askQuestion1 = new ScenarioAction( "askQuestion1", async (/** @type {State} */ state) => { const userMessage1 = data.questions["question-1"]; await askQuestion(userMessage1); }, ); const displayAskQuestion2 = new ScenarioOutput( "displayAskQuestion2", "Press enter to ask question number 2 (default is 'What's the best kind of cat?')", ); const askQuestion2 = new ScenarioAction( "askQuestion2", async (/** @type {State} */ state) => { const userMessage2 = data.questions["question-2"]; await askQuestion(userMessage2); }, ); const displayAskQuestion3 = new ScenarioOutput( "displayAskQuestion3", "Press enter to ask question number 3 (default is 'Where is the warmest city in Washington State right now?')", ); const askQuestion3 = new ScenarioAction( "askQuestion3", async (/** @type {State} */ state) => { const userMessage3 = data.questions["question-3"]; await askQuestion(userMessage3); }, ); const displayAskQuestion4 = new ScenarioOutput( "displayAskQuestion4", "Press enter to ask question number 4 (default is 'What's the warmest city in California right now?')", ); const askQuestion4 = new ScenarioAction( "askQuestion4", async (/** @type {State} */ state) => { const userMessage4 = data.questions["question-4"]; await askQuestion(userMessage4); }, ); const goodbye = new ScenarioOutput( "goodbye", "Thank you for checking out the Amazon Bedrock Tool Use demo. We hope you\n" + "learned something new, or got some inspiration for your own apps today!\n" + "For more Bedrock examples in different programming languages, have a look at:\n" + "https://docs.aws.amazon.com/bedrock/latest/userguide/service_code_examples.html", ); const myScenario = new Scenario("Converse Tool Scenario", [ greet, pressEnter, displayAskQuestion1, askQuestion1, pressEnter, displayAskQuestion2, askQuestion2, pressEnter, displayAskQuestion3, askQuestion3, pressEnter, displayAskQuestion4, askQuestion4, pressEnter, goodbye, ]); /** @type {{ stepHandlerOptions: StepHandlerOptions }} */ export const main = async (stepHandlerOptions) => { await myScenario.run(stepHandlerOptions); }; // Invoke main function if this file was run directly. if (process.argv[1] === fileURLToPath(import.meta.url)) { const { values } = parseArgs({ options: { yes: { type: "boolean", short: "y", }, }, }); main({ confirmAll: values.yes }); }
  • API の詳細については、「AWS SDK for JavaScript API リファレンス」の「Converse」を参照してください。

SDK for .NET
注記

GitHub には、その他のリソースもあります。AWS コード例リポジトリ で全く同じ例を見つけて、設定と実行の方法を確認してください。

シナリオフローのプライマリ実行。このシナリオでは、ユーザー、Amazon Bedrock Converse API、および気象ツール間の会話を調整します。

using Amazon; using Amazon.BedrockRuntime; using Amazon.BedrockRuntime.Model; using Amazon.Runtime.Documents; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; namespace ConverseToolScenario; public static class ConverseToolScenario { /* Before running this .NET code example, set up your development environment, including your credentials. This demo illustrates a tool use scenario using Amazon Bedrock's Converse API and a weather tool. The script interacts with a foundation model on Amazon Bedrock to provide weather information based on user input. It uses the Open-Meteo API (https://open-meteo.com) to retrieve current weather data for a given location. */ public static BedrockActionsWrapper _bedrockActionsWrapper = null!; public static WeatherTool _weatherTool = null!; public static bool _interactive = true; // Change this string to use a different model with Converse API. private static string model_id = "amazon.nova-lite-v1:0"; private static string system_prompt = @" You are a weather assistant that provides current weather data for user-specified locations using only the Weather_Tool, which expects latitude and longitude. Infer the coordinates from the location yourself. If the user specifies a state, country, or region, infer the locations of cities within that state. If the user provides coordinates, infer the approximate location and refer to it in your response. To use the tool, you strictly apply the provided tool specification. - Explain your step-by-step process, and give brief updates before each step. - Only use the Weather_Tool for data. Never guess or make up information. - Repeat the tool use for subsequent requests if necessary. - If the tool errors, apologize, explain weather is unavailable, and suggest other options. - Report temperatures in °C (°F) and wind in km/h (mph). Keep weather reports concise. Sparingly use emojis where appropriate. - Only respond to weather queries. Remind off-topic users of your purpose. - Never claim to search online, access external data, or use tools besides Weather_Tool. - Complete the entire process until you have all required data before sending the complete response. " ; private static string default_prompt = "What is the weather like in Seattle?"; // The maximum number of recursive calls allowed in the tool use function. // This helps prevent infinite loops and potential performance issues. private static int max_recursions = 5; public static async Task Main(string[] args) { // Set up dependency injection for the Amazon service. using var host = Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => logging.AddFilter("System", LogLevel.Error) .AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace)) .ConfigureServices((_, services) => services.AddHttpClient() .AddSingleton<IAmazonBedrockRuntime>(_ => new AmazonBedrockRuntimeClient(RegionEndpoint.USEast1)) // Specify a region that has access to the chosen model. .AddTransient<BedrockActionsWrapper>() .AddTransient<WeatherTool>() .RemoveAll<IHttpMessageHandlerBuilderFilter>() ) .Build(); ServicesSetup(host); try { await RunConversationAsync(); } catch (Exception ex) { Console.WriteLine(new string('-', 80)); Console.WriteLine($"There was a problem running the scenario: {ex.Message}"); Console.WriteLine(new string('-', 80)); } finally { Console.WriteLine( "Amazon Bedrock Converse API with Tool Use Feature Scenario is complete."); Console.WriteLine(new string('-', 80)); } } /// <summary> /// Populate the services for use within the console application. /// </summary> /// <param name="host">The services host.</param> private static void ServicesSetup(IHost host) { _bedrockActionsWrapper = host.Services.GetRequiredService<BedrockActionsWrapper>(); _weatherTool = host.Services.GetRequiredService<WeatherTool>(); } /// <summary> /// Starts the conversation with the user and handles the interaction with Bedrock. /// </summary> /// <returns>The conversation array.</returns> public static async Task<List<Message>> RunConversationAsync() { // Print the greeting and a short user guide PrintHeader(); // Start with an empty conversation var conversation = new List<Message>(); // Get the first user input var userInput = await GetUserInputAsync(); while (userInput != null) { // Create a new message with the user input and append it to the conversation var message = new Message { Role = ConversationRole.User, Content = new List<ContentBlock> { new ContentBlock { Text = userInput } } }; conversation.Add(message); // Send the conversation to Amazon Bedrock var bedrockResponse = await SendConversationToBedrock(conversation); // Recursively handle the model's response until the model has returned its final response or the recursion counter has reached 0 await ProcessModelResponseAsync(bedrockResponse, conversation, max_recursions); // Repeat the loop until the user decides to exit the application userInput = await GetUserInputAsync(); } PrintFooter(); return conversation; } /// <summary> /// Sends the conversation, the system prompt, and the tool spec to Amazon Bedrock, and returns the response. /// </summary> /// <param name="conversation">The conversation history including the next message to send.</param> /// <returns>The response from Amazon Bedrock.</returns> private static async Task<ConverseResponse> SendConversationToBedrock(List<Message> conversation) { Console.WriteLine("\tCalling Bedrock..."); // Send the conversation, system prompt, and tool configuration, and return the response return await _bedrockActionsWrapper.SendConverseRequestAsync(model_id, system_prompt, conversation, _weatherTool.GetToolSpec()); } /// <summary> /// Processes the response received via Amazon Bedrock and performs the necessary actions based on the stop reason. /// </summary> /// <param name="modelResponse">The model's response returned via Amazon Bedrock.</param> /// <param name="conversation">The conversation history.</param> /// <param name="maxRecursion">The maximum number of recursive calls allowed.</param> private static async Task ProcessModelResponseAsync(ConverseResponse modelResponse, List<Message> conversation, int maxRecursion) { if (maxRecursion <= 0) { // Stop the process, the number of recursive calls could indicate an infinite loop Console.WriteLine("\tWarning: Maximum number of recursions reached. Please try again."); } // Append the model's response to the ongoing conversation conversation.Add(modelResponse.Output.Message); if (modelResponse.StopReason == "tool_use") { // If the stop reason is "tool_use", forward everything to the tool use handler await HandleToolUseAsync(modelResponse.Output, conversation, maxRecursion - 1); } if (modelResponse.StopReason == "end_turn") { // If the stop reason is "end_turn", print the model's response text, and finish the process PrintModelResponse(modelResponse.Output.Message.Content[0].Text); if (!_interactive) { default_prompt = "x"; } } } /// <summary> /// Handles the tool use case by invoking the specified tool and sending the tool's response back to Bedrock. /// The tool response is appended to the conversation, and the conversation is sent back to Amazon Bedrock for further processing. /// </summary> /// <param name="modelResponse">The model's response containing the tool use request.</param> /// <param name="conversation">The conversation history.</param> /// <param name="maxRecursion">The maximum number of recursive calls allowed.</param> public static async Task HandleToolUseAsync(ConverseOutput modelResponse, List<Message> conversation, int maxRecursion) { // Initialize an empty list of tool results var toolResults = new List<ContentBlock>(); // The model's response can consist of multiple content blocks foreach (var contentBlock in modelResponse.Message.Content) { if (!String.IsNullOrEmpty(contentBlock.Text)) { // If the content block contains text, print it to the console PrintModelResponse(contentBlock.Text); } if (contentBlock.ToolUse != null) { // If the content block is a tool use request, forward it to the tool var toolResponse = await InvokeTool(contentBlock.ToolUse); // Add the tool use ID and the tool's response to the list of results toolResults.Add(new ContentBlock { ToolResult = new ToolResultBlock() { ToolUseId = toolResponse.ToolUseId, Content = new List<ToolResultContentBlock>() { new ToolResultContentBlock { Json = toolResponse.Content } } } }); } } // Embed the tool results in a new user message var message = new Message() { Role = ConversationRole.User, Content = toolResults }; // Append the new message to the ongoing conversation conversation.Add(message); // Send the conversation to Amazon Bedrock var response = await SendConversationToBedrock(conversation); // Recursively handle the model's response until the model has returned its final response or the recursion counter has reached 0 await ProcessModelResponseAsync(response, conversation, maxRecursion); } /// <summary> /// Invokes the specified tool with the given payload and returns the tool's response. /// If the requested tool does not exist, an error message is returned. /// </summary> /// <param name="payload">The payload containing the tool name and input data.</param> /// <returns>The tool's response or an error message.</returns> public static async Task<ToolResponse> InvokeTool(ToolUseBlock payload) { var toolName = payload.Name; if (toolName == "Weather_Tool") { var inputData = payload.Input.AsDictionary(); PrintToolUse(toolName, inputData); // Invoke the weather tool with the input data provided var weatherResponse = await _weatherTool.FetchWeatherDataAsync(inputData["latitude"].ToString(), inputData["longitude"].ToString()); return new ToolResponse { ToolUseId = payload.ToolUseId, Content = weatherResponse }; } else { var errorMessage = $"\tThe requested tool with name '{toolName}' does not exist."; return new ToolResponse { ToolUseId = payload.ToolUseId, Content = new { error = true, message = errorMessage } }; } } /// <summary> /// Prompts the user for input and returns the user's response. /// Returns null if the user enters 'x' to exit. /// </summary> /// <param name="prompt">The prompt to display to the user.</param> /// <returns>The user's input or null if the user chooses to exit.</returns> private static async Task<string?> GetUserInputAsync(string prompt = "\tYour weather info request:") { var userInput = default_prompt; if (_interactive) { Console.WriteLine(new string('*', 80)); Console.WriteLine($"{prompt} (x to exit): \n\t"); userInput = Console.ReadLine(); } if (string.IsNullOrWhiteSpace(userInput)) { prompt = "\tPlease enter your weather info request, e.g. the name of a city"; return await GetUserInputAsync(prompt); } if (userInput.ToLowerInvariant() == "x") { return null; } return userInput; } /// <summary> /// Logs the welcome message and usage guide for the tool use demo. /// </summary> public static void PrintHeader() { Console.WriteLine(@" ================================================= Welcome to the Amazon Bedrock Tool Use demo! ================================================= This assistant provides current weather information for user-specified locations. You can ask for weather details by providing the location name or coordinates. Weather information will be provided using a custom Tool and open-meteo API. Example queries: - What's the weather like in New York? - Current weather for latitude 40.70, longitude -74.01 - Is it warmer in Rome or Barcelona today? To exit the program, simply type 'x' and press Enter. P.S.: You're not limited to single locations, or even to using English! Have fun and experiment with the app! "); } /// <summary> /// Logs the footer information for the tool use demo. /// </summary> public static void PrintFooter() { Console.WriteLine(@" ================================================= Thank you for checking out the Amazon Bedrock Tool Use demo. We hope you learned something new, or got some inspiration for your own apps today! For more Bedrock examples in different programming languages, have a look at: https://docs.aws.amazon.com/bedrock/latest/userguide/service_code_examples.html ================================================= "); } /// <summary> /// Logs information about the tool use. /// </summary> /// <param name="toolName">The name of the tool being used.</param> /// <param name="inputData">The input data for the tool.</param> public static void PrintToolUse(string toolName, Dictionary<string, Document> inputData) { Console.WriteLine($"\n\tInvoking tool: {toolName} with input: {inputData["latitude"].ToString()}, {inputData["longitude"].ToString()}...\n"); } /// <summary> /// Logs the model's response. /// </summary> /// <param name="message">The model's response message.</param> public static void PrintModelResponse(string message) { Console.WriteLine("\tThe model's response:\n"); Console.WriteLine(message); Console.WriteLine(); } }

デモで使用される気象ツール。このファイルは、ツール仕様を定義し、Open-Meteo API から を使用して気象データを取得するロジックを実装します。

using Amazon.BedrockRuntime.Model; using Amazon.Runtime.Documents; using Microsoft.Extensions.Logging; namespace ConverseToolScenario; /// <summary> /// Weather tool that will be invoked when requested by the Bedrock response. /// </summary> public class WeatherTool { private readonly ILogger<WeatherTool> _logger; private readonly IHttpClientFactory _httpClientFactory; public WeatherTool(ILogger<WeatherTool> logger, IHttpClientFactory httpClientFactory) { _logger = logger; _httpClientFactory = httpClientFactory; } /// <summary> /// Returns the JSON Schema specification for the Weather tool. The tool specification /// defines the input schema and describes the tool's functionality. /// For more information, see https://json-schema.org/understanding-json-schema/reference. /// </summary> /// <returns>The tool specification for the Weather tool.</returns> public ToolSpecification GetToolSpec() { ToolSpecification toolSpecification = new ToolSpecification(); toolSpecification.Name = "Weather_Tool"; toolSpecification.Description = "Get the current weather for a given location, based on its WGS84 coordinates."; Document toolSpecDocument = Document.FromObject( new { type = "object", properties = new { latitude = new { type = "string", description = "Geographical WGS84 latitude of the location." }, longitude = new { type = "string", description = "Geographical WGS84 longitude of the location." } }, required = new[] { "latitude", "longitude" } }); toolSpecification.InputSchema = new ToolInputSchema() { Json = toolSpecDocument }; return toolSpecification; } /// <summary> /// Fetches weather data for the given latitude and longitude using the Open-Meteo API. /// Returns the weather data or an error message if the request fails. /// </summary> /// <param name="latitude">The latitude of the location.</param> /// <param name="longitude">The longitude of the location.</param> /// <returns>The weather data or an error message.</returns> public async Task<Document> FetchWeatherDataAsync(string latitude, string longitude) { string endpoint = "https://api.open-meteo.com/v1/forecast"; try { var httpClient = _httpClientFactory.CreateClient(); var response = await httpClient.GetAsync($"{endpoint}?latitude={latitude}&longitude={longitude}&current_weather=True"); response.EnsureSuccessStatusCode(); var weatherData = await response.Content.ReadAsStringAsync(); Document weatherDocument = Document.FromObject( new { weather_data = weatherData }); return weatherDocument; } catch (HttpRequestException e) { _logger.LogError(e, "Error fetching weather data: {Message}", e.Message); throw; } catch (Exception e) { _logger.LogError(e, "Unexpected error fetching weather data: {Message}", e.Message); throw; } } }

ツール設定を使用した Converse API アクション。

/// <summary> /// Wrapper class for interacting with the Amazon Bedrock Converse API. /// </summary> public class BedrockActionsWrapper { private readonly IAmazonBedrockRuntime _bedrockClient; private readonly ILogger<BedrockActionsWrapper> _logger; /// <summary> /// Initializes a new instance of the <see cref="BedrockActionsWrapper"/> class. /// </summary> /// <param name="bedrockClient">The Bedrock Converse API client.</param> /// <param name="logger">The logger instance.</param> public BedrockActionsWrapper(IAmazonBedrockRuntime bedrockClient, ILogger<BedrockActionsWrapper> logger) { _bedrockClient = bedrockClient; _logger = logger; } /// <summary> /// Sends a Converse request to the Amazon Bedrock Converse API. /// </summary> /// <param name="modelId">The Bedrock Model Id.</param> /// <param name="systemPrompt">A system prompt instruction.</param> /// <param name="conversation">The array of messages in the conversation.</param> /// <param name="toolSpec">The specification for a tool.</param> /// <returns>The response of the model.</returns> public async Task<ConverseResponse> SendConverseRequestAsync(string modelId, string systemPrompt, List<Message> conversation, ToolSpecification toolSpec) { try { var request = new ConverseRequest() { ModelId = modelId, System = new List<SystemContentBlock>() { new SystemContentBlock() { Text = systemPrompt } }, Messages = conversation, ToolConfig = new ToolConfiguration() { Tools = new List<Tool>() { new Tool() { ToolSpec = toolSpec } } } }; var response = await _bedrockClient.ConverseAsync(request); return response; } catch (ModelNotReadyException ex) { _logger.LogError(ex, "Model not ready, please wait and try again."); throw; } catch (AmazonBedrockRuntimeException ex) { _logger.LogError(ex, "Error occurred while sending Converse request."); throw; } } }
  • API の詳細については、「AWS SDK for .NET API リファレンス」の「Converse」を参照してください。

AWS SDK 開発者ガイドとコード例の完全なリストについては、「」を参照してくださいAWS SDK での Amazon Bedrock の使用。このトピックには、使用開始方法に関する情報と、以前の SDK バージョンの詳細も含まれています。

プライバシーサイト規約Cookie の設定
© 2025, Amazon Web Services, Inc. or its affiliates.All rights reserved.