"github.com/volcengine/ark-runtime-go/arkruntime"
"github.com/volcengine/ark-runtime-go/arkruntime/model/chat"
client := arkruntime.NewClientWithApiKey(
os.Getenv("ARK_API_KEY"),
arkruntime.WithBaseUrl("https://ark.cn-beijing.volces.com/api/v3"),
fmt.Println("----- function call multiple rounds request -----")
ctx := context.Background()
// Step 1: send the conversation and available functions to the model
req := &chat.ChatCompletionRequest{
Model: "doubao-seed-2-1-pro-260915", // Replace with Model ID
Messages: []chat.ChatCompletionRequestMessage{
systemMessage("你是 AI 人工智能助手"),
userMessage("上海的天气怎么样?"),
Tools: []chat.ChatCompletionTool{
Type: chat.ToolTypeFunction,
Function: chat.FunctionObject{
Name: "get_current_weather",
Description: chat.NewOptString("Get the current weather in a given location"),
Parameters: functionParameters(map[string]interface{}{
"properties": map[string]interface{}{
"location": map[string]interface{}{
"description": "The city and state, e.g. Beijing",
"unit": map[string]interface{}{
"description": "枚举值有celsius、fahrenheit",
resp, err := client.CreateChatCompletion(ctx, req)
fmt.Printf("chat error: %v\n", err)
// extend conversation with assistant's reply
req.Messages = append(req.Messages, assistantToolCallMessage(resp.Choices[0].Message))
// Step 2: check if the model wanted to call a function.
// The model can choose to call one or more functions; if so,
// the content will be a stringified JSON object adhering to
// your custom schema (note: the model may hallucinate parameters).
for _, toolCall := range resp.Choices[0].Message.ToolCalls {
fmt.Println("calling function")
fmt.Println(" id:", toolCall.ID)
fmt.Println(" name:", toolCall.Function.Name)
fmt.Println(" argument:", toolCall.Function.Arguments)
functionResponse, err := CallAvailableFunctions(toolCall.Function.Name, toolCall.Function.Arguments)
functionResponse = err.Error()
// extend conversation with function response
req.Messages = append(req.Messages,
toolMessage(toolCall.ID, functionResponse),
// get a new response from the model where it can see the function response
secondResp, err := client.CreateChatCompletion(ctx, req)
fmt.Printf("second chat error: %v\n", err)
fmt.Println("conversation", MustMarshal(req.Messages))
fmt.Println("new message", MustMarshal(secondResp.Choices[0].Message))
func CallAvailableFunctions(name, arguments string) (string, error) {
if name == "get_current_weather" {
Location string `json:"location"`
Unit string `json:"unit"`
if err := json.Unmarshal([]byte(arguments), ¶ms); err != nil {
return "", fmt.Errorf("failed to parse function call name=%s arguments=%s", name, arguments)
return GetCurrentWeather(params.Location, params.Unit), nil
return "", fmt.Errorf("got unavailable function name=%s arguments=%s", name, arguments)
// GetCurrentWeather get the current weather in a given location.
// Example dummy function hard coded to return the same weather.
// In production, this could be your backend API or an external API
func GetCurrentWeather(location, unit string) string {
switch strings.ToLower(location) {
return `{"location": "Beijing", "temperature": "10", "unit": unit}`
return `{"location": "Beijing", "temperature": "10", "unit": unit}`
return `{"location": "Shanghai", "temperature": "23", "unit": unit}`
return `{"location": "Shanghai", "temperature": "23", "unit": unit}`
return fmt.Sprintf(`{"location": %s, "temperature": "unknown"}`, location)
func MustMarshal(v interface{}) string {
func systemMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestSystemMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestSystemMessage{
Role: chat.ChatCompletionRequestSystemMessageRoleSystem,
Content: chat.NewStringChatCompletionMessageContent(content),
func toolMessage(toolCallID, content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestToolMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestToolMessage{
Role: chat.ChatCompletionRequestToolMessageRoleTool,
ToolCallID: chat.NewOptNilString(toolCallID),
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
func userMessage(content string) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestUserMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestUserMessage{
Role: chat.ChatCompletionRequestUserMessageRoleUser,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(content)),
func functionParameters(value map[string]interface{}) chat.OptFunctionObjectParameters {
encoded, err := json.Marshal(value)
var parameters chat.FunctionObjectParameters
if err := json.Unmarshal(encoded, ¶meters); err != nil {
return chat.NewOptFunctionObjectParameters(parameters)
func assistantToolCallMessage(message chat.ChatCompletionResponseMessage) chat.ChatCompletionRequestMessage {
return chat.ChatCompletionRequestMessage{
OneOf: chat.NewChatCompletionRequestAssistantMessageChatCompletionRequestMessageSum(
chat.ChatCompletionRequestAssistantMessage{
Role: chat.ChatCompletionRequestAssistantMessageRoleAssistant,
Content: chat.NewOptNilChatCompletionMessageContent(chat.NewStringChatCompletionMessageContent(message.Content)),
ToolCalls: toRequestToolCalls(message.ToolCalls),
func toRequestToolCalls(
toolCalls []chat.ChatCompletionMessageToolCall,
) []chat.ChatCompletionRequestMessageToolCall {
requestToolCalls := make([]chat.ChatCompletionRequestMessageToolCall, 0, len(toolCalls))
for _, toolCall := range toolCalls {
requestToolCalls = append(requestToolCalls, chat.ChatCompletionRequestMessageToolCall{
ID: chat.NewOptNilString(toolCall.ID),
Function: chat.ChatCompletionRequestMessageToolCallFunction{
Name: toolCall.Function.Name,
Arguments: chat.NewOptString(toolCall.Function.Arguments),