Skip to content

Commit 86bd201

Browse files
[azopenaiassistants] Adding in an example that shows how to use the code interpreter (Azure#22819)
* Adding in a specific example that uses the code interpreter and renaming the old file now that we have more than one full file example. * go get -u and updating the example file so it'll render as an entire file, not just a function or segment of code.
1 parent c3e2ab0 commit 86bd201

File tree

4 files changed

+192
-25
lines changed

4 files changed

+192
-25
lines changed
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
//go:build go1.18
2+
// +build go1.18
3+
4+
// Copyright (c) Microsoft Corporation. All rights reserved.
5+
// Licensed under the MIT License. See License.txt in the project root for license information.
6+
7+
package azopenaiassistants_test
8+
9+
import (
10+
"context"
11+
"fmt"
12+
"log"
13+
"os"
14+
"time"
15+
16+
"github.com/Azure/azure-sdk-for-go/sdk/ai/azopenaiassistants"
17+
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
18+
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
19+
)
20+
21+
func Example_assistantsUsingCodeInterpreter() {
22+
azureOpenAIKey := os.Getenv("AOAI_ASSISTANTS_KEY")
23+
24+
// Ex: "https://<your-azure-openai-host>.openai.azure.com"
25+
azureOpenAIEndpoint := os.Getenv("AOAI_ASSISTANTS_ENDPOINT")
26+
27+
if azureOpenAIKey == "" || azureOpenAIEndpoint == "" {
28+
fmt.Fprintf(os.Stderr, "Skipping example, environment variables missing\n")
29+
return
30+
}
31+
32+
keyCredential := azcore.NewKeyCredential(azureOpenAIKey)
33+
34+
client, err := azopenaiassistants.NewClientWithKeyCredential(azureOpenAIEndpoint, keyCredential, nil)
35+
36+
if err != nil {
37+
// TODO: Update the following line with your application specific error handling logic
38+
log.Fatalf("ERROR: %s", err)
39+
}
40+
41+
assistantName := fmt.Sprintf("your-assistant-name-%d", time.Now().UnixNano())
42+
43+
if err != nil {
44+
// TODO: Update the following line with your application specific error handling logic
45+
log.Fatalf("ERROR: %s", err)
46+
}
47+
48+
// First, let's create an assistant.
49+
createAssistantResp, err := client.CreateAssistant(context.Background(), azopenaiassistants.AssistantCreationBody{
50+
Name: &assistantName,
51+
DeploymentName: to.Ptr("gpt-4-1106-preview"),
52+
Instructions: to.Ptr("You are an AI assistant that can write code to help answer math questions."),
53+
Tools: []azopenaiassistants.ToolDefinitionClassification{
54+
&azopenaiassistants.CodeInterpreterToolDefinition{},
55+
// others...
56+
// &azopenaiassistants.FunctionToolDefinition{}
57+
// &azopenaiassistants.RetrievalToolDefinition{}
58+
},
59+
}, nil)
60+
61+
if err != nil {
62+
// TODO: Update the following line with your application specific error handling logic
63+
log.Fatalf("ERROR: %s", err)
64+
}
65+
66+
assistantID := createAssistantResp.ID
67+
68+
// cleanup the assistant after this example. Remove this if you want to re-use the assistant.
69+
defer func() {
70+
_, err := client.DeleteAssistant(context.TODO(), *assistantID, nil)
71+
72+
if err != nil {
73+
// TODO: Update the following line with your application specific error handling logic
74+
log.Fatalf("ERROR: %s", err)
75+
}
76+
}()
77+
78+
// Now we'll create a thread. The thread is where you will add messages, which can later
79+
// be evaluated using a Run. A thread can be re-used by multiple Runs.
80+
createThreadResp, err := client.CreateThread(context.TODO(), azopenaiassistants.AssistantThreadCreationOptions{}, nil)
81+
82+
if err != nil {
83+
// TODO: Update the following line with your application specific error handling logic
84+
log.Fatalf("ERROR: %s", err)
85+
}
86+
87+
threadID := *createThreadResp.ID
88+
89+
// Add a user question to the thread
90+
ourQuestion, err := client.CreateMessage(context.TODO(), threadID, azopenaiassistants.CreateMessageBody{
91+
Content: to.Ptr("I need to solve the equation `3x + 11 = 14`. Can you help me?"),
92+
Role: to.Ptr(azopenaiassistants.MessageRoleUser),
93+
}, nil)
94+
95+
if err != nil {
96+
// TODO: Update the following line with your application specific error handling logic
97+
log.Fatalf("ERROR: %s", err)
98+
}
99+
100+
fmt.Fprintf(os.Stderr, "[USER] I need to solve the equation `3x + 11 = 14`. Can you help me?\n")
101+
102+
// Run the thread and wait (using pollRunEnd) until it completes.
103+
threadRun, err := client.CreateRun(context.TODO(), threadID, azopenaiassistants.CreateRunBody{
104+
AssistantID: assistantID,
105+
}, nil)
106+
107+
if err != nil {
108+
// TODO: Update the following line with your application specific error handling logic
109+
log.Fatalf("ERROR: %s", err)
110+
}
111+
112+
// Wait till the assistant has responded
113+
if err := pollCodeInterpreterEnd(context.TODO(), client, threadID, *threadRun.ID); err != nil {
114+
// TODO: Update the following line with your application specific error handling logic
115+
log.Fatalf("ERROR: %s", err)
116+
}
117+
118+
// retrieve any messages added after we asked our question.
119+
listMessagesPager := client.NewListMessagesPager(threadID, &azopenaiassistants.ListMessagesOptions{
120+
After: ourQuestion.ID,
121+
Order: to.Ptr(azopenaiassistants.ListSortOrderAscending),
122+
})
123+
124+
for listMessagesPager.More() {
125+
page, err := listMessagesPager.NextPage(context.Background())
126+
127+
if err != nil {
128+
// TODO: Update the following line with your application specific error handling logic
129+
log.Fatalf("ERROR: %s", err)
130+
}
131+
132+
for _, threadMessage := range page.Data {
133+
for _, content := range threadMessage.Content {
134+
switch v := content.(type) {
135+
case *azopenaiassistants.MessageTextContent:
136+
fmt.Fprintf(os.Stderr, "[ASSISTANT] %s: Text response: %s\n", *threadMessage.ID, *v.Text.Value)
137+
}
138+
}
139+
}
140+
}
141+
142+
// Output:
143+
}
144+
145+
func pollCodeInterpreterEnd(ctx context.Context, client *azopenaiassistants.Client, threadID string, runID string) error {
146+
for {
147+
lastGetRunResp, err := client.GetRun(context.Background(), threadID, runID, nil)
148+
149+
if err != nil {
150+
return err
151+
}
152+
153+
if *lastGetRunResp.Status != azopenaiassistants.RunStatusQueued && *lastGetRunResp.Status != azopenaiassistants.RunStatusInProgress {
154+
if *lastGetRunResp.Status == azopenaiassistants.RunStatusCompleted {
155+
return nil
156+
}
157+
158+
return fmt.Errorf("run ended but status was not complete: %s", *lastGetRunResp.Status)
159+
}
160+
161+
select {
162+
case <-time.After(500 * time.Millisecond):
163+
case <-ctx.Done():
164+
return ctx.Err()
165+
}
166+
}
167+
}

sdk/ai/azopenaiassistants/example_assistants_test.go renamed to sdk/ai/azopenaiassistants/example_assistants_conversation_loop_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
2121
)
2222

23-
func Example_assistants() {
23+
func Example_assistantsWithConversationLoop() {
2424
azureOpenAIKey := os.Getenv("AOAI_ASSISTANTS_KEY")
2525

2626
// Ex: "https://<your-azure-openai-host>.openai.azure.com"

sdk/ai/azopenaiassistants/go.mod

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,25 @@ module github.com/Azure/azure-sdk-for-go/sdk/ai/azopenaiassistants
33
go 1.18
44

55
require (
6-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2
7-
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1
6+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
7+
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2
88
github.com/Azure/azure-sdk-for-go/sdk/internal v1.6.0
99
github.com/joho/godotenv v1.5.1
1010
github.com/stretchr/testify v1.9.0
1111
)
1212

1313
require (
14-
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
14+
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
1515
github.com/davecgh/go-spew v1.1.1 // indirect
1616
github.com/dnaeon/go-vcr v1.2.0 // indirect
17-
github.com/golang-jwt/jwt/v5 v5.2.0 // indirect
18-
github.com/google/uuid v1.5.0 // indirect
17+
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
18+
github.com/google/uuid v1.6.0 // indirect
1919
github.com/kylelemons/godebug v1.1.0 // indirect
2020
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
2121
github.com/pmezard/go-difflib v1.0.0 // indirect
22-
golang.org/x/crypto v0.21.0 // indirect
23-
golang.org/x/net v0.22.0 // indirect
24-
golang.org/x/sys v0.18.0 // indirect
22+
golang.org/x/crypto v0.22.0 // indirect
23+
golang.org/x/net v0.24.0 // indirect
24+
golang.org/x/sys v0.19.0 // indirect
2525
golang.org/x/text v0.14.0 // indirect
2626
gopkg.in/yaml.v2 v2.4.0 // indirect
2727
gopkg.in/yaml.v3 v3.0.1 // indirect

sdk/ai/azopenaiassistants/go.sum

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 h1:c4k2FIYIh4xtwqrQwV0Ct1v5+ehlNXj5NI/MWVsiTkQ=
2-
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2/go.mod h1:5FDJtLEO/GxwNgUxbwrY3LP0pEoThTQJtk2oysdXHxM=
3-
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
4-
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
1+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
2+
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
3+
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU=
4+
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU=
55
github.com/Azure/azure-sdk-for-go/sdk/internal v1.6.0 h1:sUFnFjzDUie80h24I7mrKtwCKgLY9L8h5Tp2x9+TWqk=
66
github.com/Azure/azure-sdk-for-go/sdk/internal v1.6.0/go.mod h1:52JbnQTp15qg5mRkMBHwp0j0ZFwHJ42Sx3zVV5RE9p0=
7-
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
8-
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
7+
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
8+
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
99
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1010
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1111
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
1212
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
13-
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
14-
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
15-
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
16-
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
13+
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
14+
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
15+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
16+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1717
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
1818
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
1919
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
@@ -25,13 +25,13 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
2525
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2626
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
2727
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
28-
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
29-
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
30-
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
31-
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
28+
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
29+
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
30+
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
31+
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
3232
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
33-
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
34-
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
33+
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
34+
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
3535
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
3636
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
3737
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

0 commit comments

Comments
 (0)