package openai_test import ( "context" openai "github.com/sashabaranov/go-openai" "github.com/sashabaranov/go-openai/internal/test/checks" "encoding/json" "fmt" "net/http" "testing" ) // TestAssistant Tests the assistant endpoint of the API using the mocked server. func TestAssistant(t *testing.T) { assistantID := "asst_abc123" assistantName := "Ambrogio" assistantDescription := "Ambrogio is a friendly assistant." assistantInstructions := `You are a personal math tutor. When asked a question, write and run Python code to answer the question.` assistantFileID := "file-wB6RM6wHdA49HfS2DJ9fEyrH" limit := 20 order := "desc" after := "asst_abc122" before := "asst_abc124" client, server, teardown := setupOpenAITestServer() defer teardown() server.RegisterHandler( "/v1/assistants/"+assistantID+"/files/"+assistantFileID, func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { resBytes, _ := json.Marshal(openai.AssistantFile{ ID: assistantFileID, Object: "assistant.file", CreatedAt: 1234567890, AssistantID: assistantID, }) fmt.Fprintln(w, string(resBytes)) } else if r.Method == http.MethodDelete { fmt.Fprintln(w, `{ id: "file-wB6RM6wHdA49HfS2DJ9fEyrH", object: "assistant.file.deleted", deleted: true }`) } }, ) server.RegisterHandler( "/v1/assistants/"+assistantID+"/files", func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { resBytes, _ := json.Marshal(openai.AssistantFilesList{ AssistantFiles: []openai.AssistantFile{ { ID: assistantFileID, Object: "assistant.file", CreatedAt: 1234567890, AssistantID: assistantID, }, }, }) fmt.Fprintln(w, string(resBytes)) } else if r.Method == http.MethodPost { var request openai.AssistantFileRequest err := json.NewDecoder(r.Body).Decode(&request) checks.NoError(t, err, "Decode error") resBytes, _ := json.Marshal(openai.AssistantFile{ ID: request.FileID, Object: "assistant.file", CreatedAt: 1234567890, AssistantID: assistantID, }) fmt.Fprintln(w, string(resBytes)) } }, ) server.RegisterHandler( "/v1/assistants/"+assistantID, func(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: resBytes, _ := json.Marshal(openai.Assistant{ ID: assistantID, Object: "assistant", CreatedAt: 1234567890, Name: &assistantName, Model: openai.GPT4TurboPreview, Description: &assistantDescription, Instructions: &assistantInstructions, }) fmt.Fprintln(w, string(resBytes)) case http.MethodPost: var request openai.Assistant err := json.NewDecoder(r.Body).Decode(&request) checks.NoError(t, err, "Decode error") resBytes, _ := json.Marshal(openai.Assistant{ ID: assistantID, Object: "assistant", CreatedAt: 1234567890, Name: request.Name, Model: request.Model, Description: request.Description, Instructions: request.Instructions, Tools: request.Tools, }) fmt.Fprintln(w, string(resBytes)) case http.MethodDelete: fmt.Fprintln(w, `{ "id": "asst_abc123", "object": "assistant.deleted", "deleted": true }`) } }, ) server.RegisterHandler( "/v1/assistants", func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { var request openai.AssistantRequest err := json.NewDecoder(r.Body).Decode(&request) checks.NoError(t, err, "Decode error") resBytes, _ := json.Marshal(openai.Assistant{ ID: assistantID, Object: "assistant", CreatedAt: 1234567890, Name: request.Name, Model: request.Model, Description: request.Description, Instructions: request.Instructions, Tools: request.Tools, }) fmt.Fprintln(w, string(resBytes)) } else if r.Method == http.MethodGet { resBytes, _ := json.Marshal(openai.AssistantsList{ LastID: &assistantID, FirstID: &assistantID, Assistants: []openai.Assistant{ { ID: assistantID, Object: "assistant", CreatedAt: 1234567890, Name: &assistantName, Model: openai.GPT4TurboPreview, Description: &assistantDescription, Instructions: &assistantInstructions, }, }, }) fmt.Fprintln(w, string(resBytes)) } }, ) ctx := context.Background() t.Run("create_assistant", func(t *testing.T) { _, err := client.CreateAssistant(ctx, openai.AssistantRequest{ Name: &assistantName, Description: &assistantDescription, Model: openai.GPT4TurboPreview, Instructions: &assistantInstructions, }) checks.NoError(t, err, "CreateAssistant error") }) t.Run("retrieve_assistant", func(t *testing.T) { _, err := client.RetrieveAssistant(ctx, assistantID) checks.NoError(t, err, "RetrieveAssistant error") }) t.Run("delete_assistant", func(t *testing.T) { _, err := client.DeleteAssistant(ctx, assistantID) checks.NoError(t, err, "DeleteAssistant error") }) t.Run("list_assistant", func(t *testing.T) { _, err := client.ListAssistants(ctx, &limit, &order, &after, &before) checks.NoError(t, err, "ListAssistants error") }) t.Run("create_assistant_file", func(t *testing.T) { _, err := client.CreateAssistantFile(ctx, assistantID, openai.AssistantFileRequest{ FileID: assistantFileID, }) checks.NoError(t, err, "CreateAssistantFile error") }) t.Run("list_assistant_files", func(t *testing.T) { _, err := client.ListAssistantFiles(ctx, assistantID, &limit, &order, &after, &before) checks.NoError(t, err, "ListAssistantFiles error") }) t.Run("retrieve_assistant_file", func(t *testing.T) { _, err := client.RetrieveAssistantFile(ctx, assistantID, assistantFileID) checks.NoError(t, err, "RetrieveAssistantFile error") }) t.Run("delete_assistant_file", func(t *testing.T) { err := client.DeleteAssistantFile(ctx, assistantID, assistantFileID) checks.NoError(t, err, "DeleteAssistantFile error") }) t.Run("modify_assistant_no_tools", func(t *testing.T) { assistant, err := client.ModifyAssistant(ctx, assistantID, openai.AssistantRequest{ Name: &assistantName, Description: &assistantDescription, Model: openai.GPT4TurboPreview, Instructions: &assistantInstructions, }) checks.NoError(t, err, "ModifyAssistant error") if assistant.Tools != nil { t.Errorf("expected nil got %v", assistant.Tools) } }) t.Run("modify_assistant_with_tools", func(t *testing.T) { assistant, err := client.ModifyAssistant(ctx, assistantID, openai.AssistantRequest{ Name: &assistantName, Description: &assistantDescription, Model: openai.GPT4TurboPreview, Instructions: &assistantInstructions, Tools: []openai.AssistantTool{{Type: openai.AssistantToolTypeFunction}}, }) checks.NoError(t, err, "ModifyAssistant error") if assistant.Tools == nil || len(assistant.Tools) != 1 { t.Errorf("expected a slice got %v", assistant.Tools) } }) t.Run("modify_assistant_empty_tools", func(t *testing.T) { assistant, err := client.ModifyAssistant(ctx, assistantID, openai.AssistantRequest{ Name: &assistantName, Description: &assistantDescription, Model: openai.GPT4TurboPreview, Instructions: &assistantInstructions, Tools: make([]openai.AssistantTool, 0), }) checks.NoError(t, err, "ModifyAssistant error") if assistant.Tools == nil { t.Errorf("expected a slice got %v", assistant.Tools) } }) } func TestAzureAssistant(t *testing.T) { assistantID := "asst_abc123" assistantName := "Ambrogio" assistantDescription := "Ambrogio is a friendly assistant." assistantInstructions := `You are a personal math tutor. When asked a question, write and run Python code to answer the question.` assistantFileID := "file-wB6RM6wHdA49HfS2DJ9fEyrH" limit := 20 order := "desc" after := "asst_abc122" before := "asst_abc124" client, server, teardown := setupAzureTestServer() defer teardown() server.RegisterHandler( "/openai/assistants/"+assistantID+"/files/"+assistantFileID, func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { resBytes, _ := json.Marshal(openai.AssistantFile{ ID: assistantFileID, Object: "assistant.file", CreatedAt: 1234567890, AssistantID: assistantID, }) fmt.Fprintln(w, string(resBytes)) } else if r.Method == http.MethodDelete { fmt.Fprintln(w, `{ id: "file-wB6RM6wHdA49HfS2DJ9fEyrH", object: "assistant.file.deleted", deleted: true }`) } }, ) server.RegisterHandler( "/openai/assistants/"+assistantID+"/files", func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { resBytes, _ := json.Marshal(openai.AssistantFilesList{ AssistantFiles: []openai.AssistantFile{ { ID: assistantFileID, Object: "assistant.file", CreatedAt: 1234567890, AssistantID: assistantID, }, }, }) fmt.Fprintln(w, string(resBytes)) } else if r.Method == http.MethodPost { var request openai.AssistantFileRequest err := json.NewDecoder(r.Body).Decode(&request) checks.NoError(t, err, "Decode error") resBytes, _ := json.Marshal(openai.AssistantFile{ ID: request.FileID, Object: "assistant.file", CreatedAt: 1234567890, AssistantID: assistantID, }) fmt.Fprintln(w, string(resBytes)) } }, ) server.RegisterHandler( "/openai/assistants/"+assistantID, func(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: resBytes, _ := json.Marshal(openai.Assistant{ ID: assistantID, Object: "assistant", CreatedAt: 1234567890, Name: &assistantName, Model: openai.GPT4TurboPreview, Description: &assistantDescription, Instructions: &assistantInstructions, }) fmt.Fprintln(w, string(resBytes)) case http.MethodPost: var request openai.AssistantRequest err := json.NewDecoder(r.Body).Decode(&request) checks.NoError(t, err, "Decode error") resBytes, _ := json.Marshal(openai.Assistant{ ID: assistantID, Object: "assistant", CreatedAt: 1234567890, Name: request.Name, Model: request.Model, Description: request.Description, Instructions: request.Instructions, Tools: request.Tools, }) fmt.Fprintln(w, string(resBytes)) case http.MethodDelete: fmt.Fprintln(w, `{ "id": "asst_abc123", "object": "assistant.deleted", "deleted": true }`) } }, ) server.RegisterHandler( "/openai/assistants", func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { var request openai.AssistantRequest err := json.NewDecoder(r.Body).Decode(&request) checks.NoError(t, err, "Decode error") resBytes, _ := json.Marshal(openai.Assistant{ ID: assistantID, Object: "assistant", CreatedAt: 1234567890, Name: request.Name, Model: request.Model, Description: request.Description, Instructions: request.Instructions, Tools: request.Tools, }) fmt.Fprintln(w, string(resBytes)) } else if r.Method == http.MethodGet { resBytes, _ := json.Marshal(openai.AssistantsList{ LastID: &assistantID, FirstID: &assistantID, Assistants: []openai.Assistant{ { ID: assistantID, Object: "assistant", CreatedAt: 1234567890, Name: &assistantName, Model: openai.GPT4TurboPreview, Description: &assistantDescription, Instructions: &assistantInstructions, }, }, }) fmt.Fprintln(w, string(resBytes)) } }, ) ctx := context.Background() _, err := client.CreateAssistant(ctx, openai.AssistantRequest{ Name: &assistantName, Description: &assistantDescription, Model: openai.GPT4TurboPreview, Instructions: &assistantInstructions, }) checks.NoError(t, err, "CreateAssistant error") _, err = client.RetrieveAssistant(ctx, assistantID) checks.NoError(t, err, "RetrieveAssistant error") _, err = client.ModifyAssistant(ctx, assistantID, openai.AssistantRequest{ Name: &assistantName, Description: &assistantDescription, Model: openai.GPT4TurboPreview, Instructions: &assistantInstructions, }) checks.NoError(t, err, "ModifyAssistant error") _, err = client.DeleteAssistant(ctx, assistantID) checks.NoError(t, err, "DeleteAssistant error") _, err = client.ListAssistants(ctx, &limit, &order, &after, &before) checks.NoError(t, err, "ListAssistants error") _, err = client.CreateAssistantFile(ctx, assistantID, openai.AssistantFileRequest{ FileID: assistantFileID, }) checks.NoError(t, err, "CreateAssistantFile error") _, err = client.ListAssistantFiles(ctx, assistantID, &limit, &order, &after, &before) checks.NoError(t, err, "ListAssistantFiles error") _, err = client.RetrieveAssistantFile(ctx, assistantID, assistantFileID) checks.NoError(t, err, "RetrieveAssistantFile error") err = client.DeleteAssistantFile(ctx, assistantID, assistantFileID) checks.NoError(t, err, "DeleteAssistantFile error") }