前回、以下の記事を参考にすると、1 回のレスポンス(session.respond(…) の呼び出し)に対して、モデルが“同じツールを複数回呼び出す”こと が可能そうだと分かった。
この記事の実装通りに試してみたところ確かに、ToolCalls が複数同時に呼び出されることが確認できた。(読みやすく整形)
Transcript(entries:
[(Instructions) ,
(Prompt) Send my love to Pikachu and Bulbasaur.
Response Format: <nil>,
(ToolCalls) SendLoveToPokemon: {"name": "Pikachu"}
SendLoveToPokemon: {"name": "Bulbasaur"},
(ToolOutput SendLoveToPokemon) ["Love sent to Pikachu!"],
(ToolOutput SendLoveToPokemon) ["Love sent to Bulbasaur!"],
(Response) Love has been sent to Pikachu and Bulbasaur.
]
)
ポケモン名の取得をツールに分割するととどうなるか試してみた。
import Foundation
import FoundationModels
import Playgrounds
struct GetPokemonListTool: Tool {
let name = "GetPokemonList"
let description = "Get a pokemon name list."
@Generable
struct Arguments {
}
func call(arguments: Arguments) async throws -> [String] {
return ["Pikachu", "Kairyu", "Yadoran", "Pijon"]
}
}
struct SendLoveToPokemonTool: Tool {
let name = "SendLoveToPokemon"
let description = "Send love to a pokemon."
@Generable
struct Arguments {
@Guide(description: "The name of the pokemon to send love to.")
let name: String
}
func call(arguments: Arguments) async throws -> [String] {
return ["Love sent to \(arguments.name)!"]
}
}
#Playground {
let session = LanguageModelSession(tools: [GetPokemonListTool(), SendLoveToPokemonTool()])
let response = try await session.respond(to: "Get a pokemon list and send love to each pokemon.")
print(session.transcript)
}結果は以下の通り。ToolCalls → ToolOutput → ToolCalls → ToolOutput とツールが交互に呼び出されていることを確認できた。
Transcript(entries:
[(Instructions) ,
(Prompt) Get a pokemon list and send love to each pokemon.
Response Format: <nil>,
(Response) null,
(ToolCalls) GetPokemonList: {},
(ToolOutput GetPokemonList) ["Pikachu", "Kairyu", "Yadoran", "Pijon"],
(Response) null,
(ToolCalls) SendLoveToPokemon: {"name": "Yadoran"}
SendLoveToPokemon: {"name": "Kairyu"}
SendLoveToPokemon: {"name": "Pijon"}
SendLoveToPokemon: {"name": "Pikachu"},
(ToolOutput SendLoveToPokemon) ["Love sent to Yadoran!"],
(ToolOutput SendLoveToPokemon) ["Love sent to Kairyu!"],
(ToolOutput SendLoveToPokemon) ["Love sent to Pijon!"],
(ToolOutput SendLoveToPokemon) ["Love sent to Pikachu!"],
(Response) Love has been successfully sent to Yadoran, Kairyu, Pijon, and Pikachu!
]
)
ちなみに、プロンプトの書き方によっては失敗することがあった。(「すべてのポケモンに送る」という指示から、一度に複数へ send love するツールがあることを期待したっぽい?)モデルの反応から失敗原因を探り、期待通りに処理してくれるようプロンプトを調整することが重要。こうした試行錯誤に際しては、やはり#Playground が有能。
Prompt:
Get a pokemon list and send love to the all pokemons.
Response:
The "GetPokemonList" function can provide a list of pokemons, but it doesn't allow sending love to all pokemons at once. The "SendLoveToPokemon" function can only be used for one specific pokemon at a time.
To proceed, I need the names of the pokemons you wish to send love to. Please provide the names.
「Foundation Models:ツール呼び出しを並列/直列に反復させる」への1件のフィードバック