Skip to content

Commit 24fec6a

Browse files
committed
Updated tests
1 parent d6c202b commit 24fec6a

File tree

4 files changed

+79
-3
lines changed

4 files changed

+79
-3
lines changed

pkg/openai/chat.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,14 @@ func (c *Client) Chat(ctx context.Context, messages []*schema.Message, opts ...O
104104
// Return all choices
105105
var result []*schema.Content
106106
for _, choice := range response.Choices {
107-
if choice.Message == nil || choice.Message.Content == nil {
107+
// A choice must have a message, content and/or tool calls
108+
if choice.Message == nil || choice.Message.Content == nil && len(choice.Message.ToolCalls) == 0 {
109+
continue
110+
}
111+
for _, tool := range choice.Message.ToolCalls {
112+
result = append(result, schema.ToolUse(tool))
113+
}
114+
if choice.Message.Content == nil {
108115
continue
109116
}
110117
switch v := choice.Message.Content.(type) {

pkg/openai/chat_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ func Test_chat_003(t *testing.T) {
6565
assert.NotNil(client)
6666

6767
message := schema.NewMessage("user", "What is in this image")
68-
// .AppendImageUrl("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg")
68+
image, err := schema.ImageUrl("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", "auto")
69+
assert.NoError(err)
70+
assert.NotNil(message.Add(image))
6971
response, err := client.Chat(context.Background(), []*schema.Message{message}, openai.OptModel("gpt-4-vision-preview"))
7072
assert.NoError(err)
7173
assert.NotNil(response)

pkg/openai/schema/message.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"io"
77
"net/http"
8+
"net/url"
89
"os"
910
"reflect"
1011
"strings"
@@ -31,6 +32,9 @@ type Message struct {
3132
// object or an array of content objects
3233
Content any `json:"content,omitempty"`
3334

35+
// Any tool calls
36+
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
37+
3438
// Time the message was created, in unix seconds
3539
Created int64 `json:"created,omitempty"`
3640
}
@@ -72,8 +76,12 @@ type Content struct {
7276
Type string `json:"type" writer:",width:4"`
7377
Text string `json:"text,omitempty" writer:",width:60,wrap"`
7478
Source *contentSource `json:"source,omitempty"`
79+
Url *contentImage `json:"image_url,omitempty"`
80+
81+
// Tool Function Call
7582
toolUse
7683

84+
// Tool Result
7785
ToolId string `json:"tool_use_id,omitempty"`
7886
Result string `json:"content,omitempty"`
7987
}
@@ -85,6 +93,25 @@ type contentSource struct {
8593
Data string `json:"data,omitempty"`
8694
}
8795

96+
// Image Source
97+
type contentImage struct {
98+
Url string `json:"url,omitempty"`
99+
Detail string `json:"detail,omitempty"`
100+
}
101+
102+
// Tool Call
103+
type ToolCall struct {
104+
Id string `json:"id,omitempty"`
105+
Type string `json:"type,omitempty"`
106+
Function ToolFunction `json:"function,omitempty"`
107+
}
108+
109+
// Tool Function and Arguments
110+
type ToolFunction struct {
111+
Name string `json:"name,omitempty"`
112+
Arguments string `json:"arguments,omitempty"`
113+
}
114+
88115
// Tool call
89116
type toolUse struct {
90117
Name string `json:"name,omitempty"`
@@ -148,6 +175,46 @@ func ImageData(path string) (*Content, error) {
148175
return Image(r)
149176
}
150177

178+
// Return a new content object of type image, from a Url
179+
func ImageUrl(v, detail string) (*Content, error) {
180+
url, err := url.Parse(v)
181+
if err != nil {
182+
return nil, err
183+
}
184+
if url.Scheme != "https" {
185+
return nil, ErrBadParameter.With("ImageUrl: not an https url")
186+
}
187+
return &Content{
188+
Type: "image_url",
189+
Url: &contentImage{
190+
Url: url.String(),
191+
Detail: detail,
192+
},
193+
}, nil
194+
}
195+
196+
// Return tool usage
197+
func ToolUse(t ToolCall) *Content {
198+
var input map[string]any
199+
200+
// Decode the arguments
201+
if t.Function.Arguments != "" {
202+
if err := json.Unmarshal([]byte(t.Function.Arguments), &input); err != nil {
203+
return nil
204+
}
205+
}
206+
207+
// Return the content
208+
return &Content{
209+
Type: t.Type,
210+
Id: t.Id,
211+
toolUse: toolUse{
212+
Name: t.Function.Name,
213+
Input: input,
214+
},
215+
}
216+
}
217+
151218
// Return a tool result
152219
func ToolResult(id string, result string) *Content {
153220
return &Content{Type: "tool_result", ToolId: id, Result: result}

pkg/openai/schema/tool.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type Tool struct {
1818
Name string `json:"name"`
1919
Description string `json:"description"`
2020
Type string `json:"type,omitempty"`
21-
Parameters *toolParameters `json:"input_schema,omitempty"`
21+
Parameters *toolParameters `json:"parameters,omitempty"`
2222
}
2323

2424
// Tool function parameters

0 commit comments

Comments
 (0)