openai-go
openai-go copied to clipboard
Want an example of streaming with tool calling
I got a demo of this working and I would like to merge it if there is interest.
Here's examples/chat-completion-streaming-tool-calling/main.go in my repo, for reference:
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/openai/openai-go"
)
func main() {
client := openai.NewClient()
ctx := context.Background()
question := "What is the weather in New York City? Write a paragraph about it."
print("> ")
println(question)
params := openai.ChatCompletionNewParams{
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage(question),
},
Tools: []openai.ChatCompletionToolParam{
{
Function: openai.FunctionDefinitionParam{
Name: "get_weather",
Description: openai.String("Get weather at the given location"),
Parameters: openai.FunctionParameters{
"type": "object",
"properties": map[string]interface{}{
"location": map[string]string{
"type": "string",
},
},
"required": []string{"location"},
},
},
},
},
Seed: openai.Int(0),
Model: openai.ChatModelGPT4o,
}
// Make initial chat completion request with streaming
stream := client.Chat.Completions.NewStreaming(ctx, params)
acc := openai.ChatCompletionAccumulator{}
// Stream and accumulate the first response
fmt.Println("\nStreaming first response...")
for stream.Next() {
chunk := stream.Current()
acc.AddChunk(chunk)
// Display the content as it arrives
if len(chunk.Choices) > 0 && chunk.Choices[0].Delta.Content != "" {
print(chunk.Choices[0].Delta.Content)
}
// Check if a tool call has finished
if tool, ok := acc.JustFinishedToolCall(); ok {
fmt.Printf("\nTool call detected: %s with arguments %s\n", tool.Name, tool.Arguments)
}
}
println()
if err := stream.Err(); err != nil {
panic(err)
}
// Access the accumulated message and tool calls
var toolCalls []openai.ChatCompletionMessageToolCall
if len(acc.Choices) > 0 {
toolCalls = acc.Choices[0].Message.ToolCalls
}
// Return early if there are no tool calls
if len(toolCalls) == 0 {
fmt.Printf("No function call")
return
}
// If there is a was a function call, continue the conversation
params.Messages = append(params.Messages, acc.Choices[0].Message.ToParam())
for _, toolCall := range toolCalls {
if toolCall.Function.Name == "get_weather" {
// Extract the location from the function call arguments
var args map[string]interface{}
err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args)
if err != nil {
panic(err)
}
location := args["location"].(string)
// Simulate getting weather data
weatherData := getWeather(location)
// Print the weather data
fmt.Printf("Weather in %s: %s\n", location, weatherData)
params.Messages = append(params.Messages, openai.ToolMessage(weatherData, toolCall.ID))
}
}
responseStream := client.Chat.Completions.NewStreaming(ctx, params)
fmt.Println("\nStreaming second response...")
for responseStream.Next() {
evt := responseStream.Current()
if len(evt.Choices) > 0 {
print(evt.Choices[0].Delta.Content)
}
}
println()
if err := responseStream.Err(); err != nil {
panic(err)
}
}
// Mock function to simulate weather data retrieval
func getWeather(location string) string {
// In a real implementation, this function would call a weather API
return "Sunny, 25°C"
}
This example works for me, thanks!