Skip to content

Commit

Permalink
feat: support vision
Browse files Browse the repository at this point in the history
  • Loading branch information
liushuangls committed Mar 11, 2024
1 parent cdb5625 commit 1482376
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 1 deletion.
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,68 @@ func main() {
}
```

### Messages Vision example usage:

```go
package main

import (
"errors"
"fmt"

"github.com/liushuangls/go-anthropic"
)

func main() {
client := anthropic.NewClient("your anthropic apikey")

imagePath := "xxx"
imageMediaType := "image/jpeg"
imageFile, err := os.Open(imagePath)
if err != nil {
panic(err)
}
imageData, err := io.ReadAll(imageFile)
if err != nil {
panic(err)
}

resp, err := client.CreateMessages(context.Background(), anthropic.MessagesRequest{
Model: anthropic.ModelClaude3Opus20240229, // only claude 3 model can use vision
Messages: []anthropic.Message{
{
Role: anthropic.RoleUser,
Content: []any{
anthropic.MessageImageContent{
Type: "image",
Source: anthropic.MessageImageContentSource{
Type: "base64",
MediaType: imageMediaType,
Data: imageData,
},
},
anthropic.MessageTextContent{
Type: "text",
Text: "Describe this image.",
},
},
},
},
MaxTokens: 1000,
})
if err != nil {
var e *anthropic.APIError
if errors.As(err, &e) {
fmt.Printf("Messages error, type: %s, message: %s", e.Type, e.Message)
} else {
fmt.Printf("Messages error: %v\n", err)
}
return
}
fmt.Println(resp.Content[0].Text)
}
```

## Acknowledgments
The following project had particular influence on go-anthropic is design.

Expand Down
Binary file added internal/test/sources/ant.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 17 additions & 1 deletion message.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,23 @@ func (m *MessagesRequest) SetTopK(k int) {

type Message struct {
Role string `json:"role"`
Content string `json:"content"`
Content any `json:"content"` // Content can be string, MessageTextContent or MessageImageContent or slice
}

type MessageTextContent struct {
Type string `json:"type"`
Text string `json:"text"`
}

type MessageImageContent struct {
Type string `json:"type"`
Source MessageImageContentSource `json:"source"`
}

type MessageImageContentSource struct {
Type string `json:"type"`
MediaType string `json:"media_type"`
Data any `json:"data"`
}

type MessagesResponse struct {
Expand Down
58 changes: 58 additions & 0 deletions message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package anthropic_test

import (
"context"
"embed"
"encoding/json"
"errors"
"io"
Expand All @@ -15,6 +16,9 @@ import (
"github.com/liushuangls/go-anthropic/internal/test/checks"
)

//go:embed internal/test/sources/*
var sources embed.FS

func TestMessages(t *testing.T) {
server := test.NewTestServer()
server.RegisterHandler("/v1/messages", handleMessagesEndpoint)
Expand Down Expand Up @@ -75,6 +79,60 @@ func TestMessagesTokenError(t *testing.T) {
t.Logf("CreateMessages error: %s", err)
}

func TestMessagesVision(t *testing.T) {
server := test.NewTestServer()
server.RegisterHandler("/v1/messages", handleMessagesEndpoint)

ts := server.AnthropicTestServer()
ts.Start()
defer ts.Close()

baseUrl := ts.URL + "/v1"
client := anthropic.NewClient(
test.GetTestToken(),
anthropic.WithBaseURL(baseUrl),
)

imagePath := "internal/test/sources/ant.jpg"
imageMediaType := "image/jpeg"
imageFile, err := sources.Open(imagePath)
if err != nil {
t.Fatal(err)
}
imageData, err := io.ReadAll(imageFile)
if err != nil {
t.Fatal(err)
}

resp, err := client.CreateMessages(context.Background(), anthropic.MessagesRequest{
Model: anthropic.ModelClaude3Opus20240229,
Messages: []anthropic.Message{
{
Role: anthropic.RoleUser,
Content: []any{
anthropic.MessageImageContent{
Type: "image",
Source: anthropic.MessageImageContentSource{
Type: "base64",
MediaType: imageMediaType,
Data: imageData,
},
},
anthropic.MessageTextContent{
Type: "text",
Text: "Describe this image.",
},
},
},
},
MaxTokens: 1000,
})
if err != nil {
t.Fatal(err)
}
t.Logf("CreateMessages resp: %+v", resp)
}

func handleMessagesEndpoint(w http.ResponseWriter, r *http.Request) {
var err error
var resBytes []byte
Expand Down

0 comments on commit 1482376

Please sign in to comment.