Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions conversation/go/sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ name: Run multi app run template
expected_stdout_lines:
- '== APP - conversation == Input sent: What is dapr?'
Comment thread
filintod marked this conversation as resolved.
Outdated
- '== APP - conversation == Output response: What is dapr?'
- '== APP - conversation == Output response: get weather in San Francisco in celsius'
Comment thread
filintod marked this conversation as resolved.
Outdated
- '== APP - conversation == Tool Call - Name: getWeather - Arguments: '
Comment thread
filintod marked this conversation as resolved.
Outdated
- '== APP - conversation == Tool Execution Output: The weather in San Francisco is 25 degrees Celsius'
Comment thread
filintod marked this conversation as resolved.
Outdated
expected_stderr_lines:
output_match_mode: substring
match_order: none
Expand All @@ -43,6 +46,9 @@ The terminal console output should look similar to this, where:
```text
== APP - conversation == Input sent: What is dapr?
Comment thread
alicejgibbons marked this conversation as resolved.
Outdated
== APP - conversation == Output response: What is dapr?
== APP - conversation == Output response: get weather in San Francisco in celsius
Comment thread
filintod marked this conversation as resolved.
Outdated
== APP - conversation == Tool Call - Name: getWeather - Arguments: location,unit
Comment thread
filintod marked this conversation as resolved.
Outdated
== APP - conversation == Tool Execution Output: The weather in San Francisco is 25 degrees Celsius
Comment thread
filintod marked this conversation as resolved.
Outdated
```

<!-- END_STEP -->
Expand Down
138 changes: 129 additions & 9 deletions conversation/go/sdk/conversation/conversation.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,154 @@ package main

import (
"context"
"encoding/json"
"fmt"
"log"
"strings"

"github.com/invopop/jsonschema"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/structpb"

dapr "github.com/dapr/go-sdk/client"
)

// createMapOfArgsForEcho is a helper to deal with an issue with current echo provider not returning args as a map but a csv
Comment thread
filintod marked this conversation as resolved.
Outdated
func createMapOfArgsForEcho(s string) ([]byte, error) {
m := map[string]any{}
for _, p := range strings.Split(s, ",") {
m[p] = p
}
return json.Marshal(m)
}

// getWeatherInLocation is an example function to use as tool
Comment thread
filintod marked this conversation as resolved.
Outdated
func getWeatherInLocation(request GetDegreesWeatherRequest, defaultValues GetDegreesWeatherRequest) string {
location := request.Location
unit := request.Unit
if location == "location" {
location = defaultValues.Location
}
if unit == "unit" {
unit = defaultValues.Unit
}
return fmt.Sprintf("The weather in %s is 25 degrees %s", location, unit)
}

type GetDegreesWeatherRequest struct {
Location string `json:"location" jsonschema:"title=Location,description=The location to look up the weather for"`
Unit string `json:"unit" jsonschema:"enum=celsius,enum=fahrenheit,description=Unit"`
}

// GenerateFunctionTool helper method to create jsonschema input
func GenerateFunctionTool[T any](name, description string) (*dapr.ConversationToolsAlpha2, error) {
reflector := jsonschema.Reflector{
AllowAdditionalProperties: false,
DoNotReference: true,
}
var v T

schema := reflector.Reflect(v)

schemaBytes, err := schema.MarshalJSON()
if err != nil {
return nil, err
}

var protoStruct structpb.Struct
if err := protojson.Unmarshal(schemaBytes, &protoStruct); err != nil {
return nil, fmt.Errorf("converting jsonschema to proto Struct: %w", err)
}

return (*dapr.ConversationToolsAlpha2)(&dapr.ConversationToolsFunctionAlpha2{
Name: name,
Description: &description,
Parameters: &protoStruct,
}), nil
}

// createUserMessageInput is a helper method to create user messages in expected proto format
func createUserMessageInput(msg string) *dapr.ConversationInputAlpha2 {
return &dapr.ConversationInputAlpha2{
Messages: []*dapr.ConversationMessageAlpha2{
{
ConversationMessageOfUser: &dapr.ConversationMessageOfUserAlpha2{
Content: []*dapr.ConversationMessageContentAlpha2{
{
Text: &msg,
},
},
},
},
},
}
}

func main() {
client, err := dapr.NewClient()
if err != nil {
panic(err)
}

input := dapr.ConversationInput{
Content: "What is dapr?",
// Role: nil, // Optional
// ScrubPII: nil, // Optional
inputMsg := "What is dapr?"
conversationComponent := "echo"

request := dapr.ConversationRequestAlpha2{
Name: conversationComponent,
Inputs: []*dapr.ConversationInputAlpha2{createUserMessageInput(inputMsg)},
}

fmt.Println("Input sent:", inputMsg)

resp, err := client.ConverseAlpha2(context.Background(), request)
if err != nil {
log.Fatalf("err: %v", err)
}

fmt.Println("Input sent:", input.Content)
fmt.Println("Output response:", resp.Outputs[0].Choices[0].Message.Content)

var conversationComponent = "echo"
tool, err := GenerateFunctionTool[GetDegreesWeatherRequest]("getWeather", "get weather from a location in the given unit")
if err != nil {
log.Fatalf("err: %v", err)
}

request := dapr.NewConversationRequest(conversationComponent, []dapr.ConversationInput{input})
weatherMessage := "get weather in San Francisco in celsius"
Comment thread
filintod marked this conversation as resolved.
Outdated
requestWithTool := dapr.ConversationRequestAlpha2{
Name: conversationComponent,
Inputs: []*dapr.ConversationInputAlpha2{createUserMessageInput(weatherMessage)},
Tools: []*dapr.ConversationToolsAlpha2{tool},
}

resp, err := client.ConverseAlpha1(context.Background(), request)
resp, err = client.ConverseAlpha2(context.Background(), requestWithTool)
if err != nil {
log.Fatalf("err: %v", err)
}

fmt.Println("Output response:", resp.Outputs[0].Result)
fmt.Println("Output response:", resp.Outputs[0].Choices[0].Message.Content)
for _, toolCalls := range resp.Outputs[0].Choices[0].Message.ToolCalls {
fmt.Printf("Tool Call - Name: %s - Arguments: %v\n", toolCalls.ToolTypes.Name, toolCalls.ToolTypes.Arguments)
Comment thread
filintod marked this conversation as resolved.
Outdated

// parse the arguments and execute tool
args := []byte(toolCalls.ToolTypes.Arguments)
if conversationComponent == "echo" {
Comment thread
alicejgibbons marked this conversation as resolved.
// echo does not return a compliant tools argument, it should return json object with keys being the argument names
Comment thread
filintod marked this conversation as resolved.
Outdated
args, err = createMapOfArgsForEcho(toolCalls.ToolTypes.Arguments)
if err != nil {
log.Fatalf("err: %v", err)
}
}

// find the tool (only one in this case) and execute
for _, toolInfo := range requestWithTool.Tools {
if toolInfo.Name == toolCalls.ToolTypes.Name && toolInfo.Name == "getWeather" {
var reqArgs GetDegreesWeatherRequest
if err = json.Unmarshal(args, &reqArgs); err != nil {
log.Fatalf("err: %v", err)
}
// execute tool
toolExecutionOutput := getWeatherInLocation(reqArgs, GetDegreesWeatherRequest{Location: "San Francisco", Unit: "Celsius"})
fmt.Printf("Tool Execution Output: %s\n", toolExecutionOutput)
Comment thread
filintod marked this conversation as resolved.
Outdated
}
}
}
}
10 changes: 9 additions & 1 deletion conversation/go/sdk/conversation/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@ toolchain go1.24.5

require github.com/dapr/go-sdk v1.13.0-rc.1

// TODO: remove when PR https://github.com/dapr/go-sdk/pull/766 is merged
replace github.com/dapr/go-sdk => github.com/mikeee/dapr_go-sdk v1.13.0-rc.1.0.20250911101203-c6cb090061af
Comment thread
filintod marked this conversation as resolved.
Outdated

require (
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/dapr/dapr v1.16.0-rc.3 // indirect
github.com/dapr/kit v0.15.4 // indirect
github.com/dapr/kit v0.16.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/invopop/jsonschema v0.13.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
go.opentelemetry.io/otel v1.36.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sys v0.33.0 // indirect
Expand Down
19 changes: 15 additions & 4 deletions conversation/go/sdk/conversation/go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/dapr/dapr v1.16.0-rc.3 h1:D99V20GOhb+bZXH1PngME+wgzIZCcBFOvmaP7DOZxGo=
github.com/dapr/dapr v1.16.0-rc.3/go.mod h1:uyKnxMohSg87LSFzZ/oyuiGSo0+qkzeR0eXncPyIV9c=
github.com/dapr/go-sdk v1.13.0-rc.1 h1:GKvTl38EhxQ3VHuQngMMm8hEaAVHn9gu63CI2HTbI+U=
github.com/dapr/go-sdk v1.13.0-rc.1/go.mod h1:Klfst183A5pb2YZ0KHUCRwdeQuL8RFKX649ILW9K3h4=
github.com/dapr/kit v0.15.4 h1:29DezCR22OuZhXX4yPEc+lqcOf/PNaeAuIEx9nGv394=
github.com/dapr/kit v0.15.4/go.mod h1:HwFsBKEbcyLanWlDZE7u/jnaDCD/tU+n3pkFNUctQNw=
github.com/dapr/kit v0.16.0 h1:I2sMBzndw5XTjsaH0J/hbKK6WNbuT0AHxIY5M9OhzGI=
github.com/dapr/kit v0.16.0/go.mod h1:40ZWs5P6xfYf7O59XgwqZkIyDldTIXlhTQhGop8QoSM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
Expand All @@ -16,10 +18,19 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mikeee/dapr_go-sdk v1.13.0-rc.1.0.20250911101203-c6cb090061af h1:Fr/lhl9RS2/vYPjZ4QS+5NjXyzTjku9uj0Pv0yAoLM4=
github.com/mikeee/dapr_go-sdk v1.13.0-rc.1.0.20250911101203-c6cb090061af/go.mod h1:IJ7Fs9QnkQHeLBkjOBA+cLMV+z/EVeAUyEmvp36ji3A=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
Expand Down