go-anthropic

Anthropic Claude API wrapper for Go

https://github.com/liushuangls/go-anthropic

Science Score: 44.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (8.2%) to scientific vocabulary

Keywords

ai anthropic claude claude-ai claude-api function-calling go golang llm prompt-caching streaming-api tool-use vision

Keywords from Contributors

agents application multi-agents mesh interpretability sequences generic projection interactive optim
Last synced: 4 months ago · JSON representation ·

Repository

Anthropic Claude API wrapper for Go

Basic Info
  • Host: GitHub
  • Owner: liushuangls
  • License: apache-2.0
  • Language: Go
  • Default Branch: main
  • Homepage:
  • Size: 1.23 MB
Statistics
  • Stars: 148
  • Watchers: 4
  • Forks: 21
  • Open Issues: 9
  • Releases: 43
Topics
ai anthropic claude claude-ai claude-api function-calling go golang llm prompt-caching streaming-api tool-use vision
Created almost 2 years ago · Last pushed 8 months ago
Metadata Files
Readme License Citation

README.md

go-anthropic

Go Reference Go Report Card codecov Sanity check

Anthropic Claude API wrapper for Go (Unofficial).

This package has support for: - Completions - Streaming Completions - Messages - Streaming Messages - Message Batching - Vision and PDFs - Tool use (with computer use) - Prompt Caching - Token Counting

Installation

go get github.com/liushuangls/go-anthropic/v2

Currently, go-anthropic requires Go version 1.21 or greater.

Usage

Messages example usage:

```go package main

import ( "errors" "fmt"

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

)

func main() { client := anthropic.NewClient("your anthropic api key") resp, err := client.CreateMessages(context.Background(), anthropic.MessagesRequest{ Model: anthropic.ModelClaude3Haiku20240307, Messages: []anthropic.Message{ anthropic.NewUserTextMessage("What is your name?"), }, 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].GetText()) } ```

Messages stream example usage:

```go package main

import ( "errors" "fmt"

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

)

func main() { client := anthropic.NewClient("your anthropic api key") resp, err := client.CreateMessagesStream(context.Background(), anthropic.MessagesStreamRequest{ MessagesRequest: anthropic.MessagesRequest{ Model: anthropic.ModelClaude3Haiku20240307, Messages: []anthropic.Message{ anthropic.NewUserTextMessage("What is your name?"), }, MaxTokens: 1000, }, OnContentBlockDelta: func(data anthropic.MessagesEventContentBlockDeltaData) { fmt.Printf("Stream Content: %s\n", data.Delta.Text) }, }) if err != nil { var e *anthropic.APIError if errors.As(err, &e) { fmt.Printf("Messages stream error, type: %s, message: %s", e.Type, e.Message) } else { fmt.Printf("Messages stream error: %v\n", err) } return } fmt.Println(resp.Content[0].GetText()) } ```

Other examples:

Messages Vision example ```go package main import ( "errors" "fmt" "github.com/liushuangls/go-anthropic/v2" ) func main() { client := anthropic.NewClient("your anthropic api key") 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, Messages: []anthropic.Message{ { Role: anthropic.RoleUser, Content: []anthropic.MessageContent{ anthropic.NewImageMessageContent( anthropic.NewMessageContentSource( anthropic.MessagesContentSourceTypeBase64, imageMediaType, imageData, ), ), anthropic.NewTextMessageContent("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].GetText()) } ```
Messages Tool use example ```go package main import ( "context" "fmt" "github.com/liushuangls/go-anthropic/v2" "github.com/liushuangls/go-anthropic/v2/jsonschema" ) func main() { client := anthropic.NewClient( "your anthropic api key", ) request := anthropic.MessagesRequest{ Model: anthropic.ModelClaude3Haiku20240307, Messages: []anthropic.Message{ anthropic.NewUserTextMessage("What is the weather like in San Francisco?"), }, MaxTokens: 1000, Tools: []anthropic.ToolDefinition{ { Name: "get_weather", Description: "Get the current weather in a given location", InputSchema: jsonschema.Definition{ Type: jsonschema.Object, Properties: map[string]jsonschema.Definition{ "location": { Type: jsonschema.String, Description: "The city and state, e.g. San Francisco, CA", }, "unit": { Type: jsonschema.String, Enum: []string{"celsius", "fahrenheit"}, Description: "The unit of temperature, either 'celsius' or 'fahrenheit'", }, }, Required: []string{"location"}, }, }, }, } resp, err := client.CreateMessages(context.Background(), request) if err != nil { panic(err) } request.Messages = append(request.Messages, anthropic.Message{ Role: anthropic.RoleAssistant, Content: resp.Content, }) var toolUse *anthropic.MessageContentToolUse for _, c := range resp.Content { if c.Type == anthropic.MessagesContentTypeToolUse { toolUse = c.MessageContentToolUse } } if toolUse == nil { panic("tool use not found") } request.Messages = append(request.Messages, anthropic.NewToolResultsMessage(toolUse.ID, "65 degrees", false)) resp, err = client.CreateMessages(context.Background(), request) if err != nil { panic(err) } fmt.Printf("Response: %+v\n", resp) } ```
Prompt Caching doc: https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching ```go package main import ( "context" "errors" "fmt" "github.com/liushuangls/go-anthropic/v2" ) func main() { client := anthropic.NewClient( "your anthropic api key", anthropic.WithBetaVersion(anthropic.BetaPromptCaching20240731), ) resp, err := client.CreateMessages( context.Background(), anthropic.MessagesRequest{ Model: anthropic.ModelClaude3Haiku20240307, MultiSystem: []anthropic.MessageSystemPart{ { Type: "text", Text: "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.", }, { Type: "text", Text: "", CacheControl: &anthropic.MessageCacheControl{ Type: anthropic.CacheControlTypeEphemeral, }, }, }, Messages: []anthropic.Message{ anthropic.NewUserTextMessage("Analyze the major themes in Pride and Prejudice.") }, 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.Printf("Usage: %+v\n", resp.Usage) fmt.Println(resp.Content[0].GetText()) } ```
VertexAI example If you are using a Google Credentials file, you can use the following code to create a client: ```go package main import ( "context" "errors" "fmt" "os" "github.com/liushuangls/go-anthropic/v2" "golang.org/x/oauth2/google" ) func main() { credBytes, err := os.ReadFile("") if err != nil { fmt.Println("Error reading file") return } ts, err := google.JWTAccessTokenSourceWithScope(credBytes, "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/cloud-platform.read-only") if err != nil { fmt.Println("Error creating token source") return } // use JWTAccessTokenSourceWithScope token, err := ts.Token() if err != nil { fmt.Println("Error getting token") return } fmt.Println(token.AccessToken) client := anthropic.NewClient(token.AccessToken, anthropic.WithVertexAI("", "")) resp, err := client.CreateMessagesStream(context.Background(), anthropic.MessagesStreamRequest{ MessagesRequest: anthropic.MessagesRequest{ Model: anthropic.ModelClaude3Haiku20240307, Messages: []anthropic.Message{ anthropic.NewUserTextMessage("What is your name?"), }, MaxTokens: 1000, }, OnContentBlockDelta: func(data anthropic.MessagesEventContentBlockDeltaData) { fmt.Printf("Stream Content: %s\n", *data.Delta.Text) }, }) if err != nil { var e *anthropic.APIError if errors.As(err, &e) { fmt.Printf("Messages stream error, type: %s, message: %s", e.Type, e.Message) } else { fmt.Printf("Messages stream error: %v\n", err) } return } fmt.Println(resp.Content[0].GetText()) } ```
Message Batching doc: https://docs.anthropic.com/en/docs/build-with-claude/message-batches ```go package main import ( "context" "errors" "fmt" "os" "github.com/liushuangls/go-anthropic/v2" ) func main() { client := anthropic.NewClient( "your anthropic api key", anthropic.WithBetaVersion(anthropic.BetaMessageBatches20240924), ) resp, err := client.CreateBatch(context.Background(), anthropic.BatchRequest{ Requests: []anthropic.InnerRequests{ { CustomId: myId, Params: anthropic.MessagesRequest{ Model: anthropic.ModelClaude3Haiku20240307, MultiSystem: anthropic.NewMultiSystemMessages( "you are an assistant", "you are snarky", ), MaxTokens: 10, Messages: []anthropic.Message{ anthropic.NewUserTextMessage("What is your name?"), anthropic.NewAssistantTextMessage("My name is Claude."), anthropic.NewUserTextMessage("What is your favorite color?"), }, }, }, }, }, ) 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) retrieveResp, err := client.RetrieveBatch(ctx, resp.Id) 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(retrieveResp) resultResp, err := client.RetrieveBatchResults(ctx, "batch_id_your-batch-here") 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(resultResp) listResp, err := client.ListBatches(ctx, anthropic.ListBatchesRequest{}) 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(listResp) cancelResp, err := client.CancelBatch(ctx, "batch_id_your-batch-here") if err != nil { t.Fatalf("CancelBatch error: %s", err) } fmt.Println(cancelResp) ```
Token Counting example doc: (https://docs.anthropic.com/en/docs/build-with-claude/token-counting)[https://docs.anthropic.com/en/docs/build-with-claude/token-counting] ```go // TODO: add example! ```

Beta features

Anthropic provides several beta features that can be enabled using the following beta version identifiers:

Beta Version Identifier | Code Constant | Description -----------------------------------|---------------------------------|--------------------------------- tools-2024-04-04 | BetaTools20240404 | Initial tools beta tools-2024-05-16 | BetaTools20240516 | Updated tools beta prompt-caching-2024-07-31 | BetaPromptCaching20240731 | Prompt caching beta message-batches-2024-09-24 | BetaMessageBatches20240924 | Message batching beta token-counting-2024-11-01 | BetaTokenCounting20241101 | Token counting beta max-tokens-3-5-sonnet-2024-07-15 | BetaMaxTokens35Sonnet20240715 | Max tokens beta for Sonnet model computer-use-2024-10-22 | BetaComputerUse20241022 | Computer use beta

Supported models

The following models are supported by go-anthropic. These models are also available for use on Google's Vertex AI platform as well.

Model Name | Model String -------------------------------|------------------------------ ModelClaude2Dot0 | "claude-2.0" ModelClaude2Dot1 | "claude-2.1" ModelClaude3Opus20240229 | "claude-3-opus-20240229" ModelClaude3Sonnet20240229 | "claude-3-sonnet-20240229" ModelClaude3Dot5Sonnet20240620 | "claude-3-5-sonnet-20240620" ModelClaude3Dot5Sonnet20241022 | "claude-3-5-sonnet-20241022" ModelClaude3Dot5SonnetLatest | "claude-3-5-sonnet-latest" ModelClaude3Haiku20240307 | "claude-3-haiku-20240307" ModelClaude3Dot5HaikuLatest | "claude-3-5-haiku-latest" ModelClaude3Dot5Haiku20241022 | "claude-3-5-haiku-20241022"

Other Enums

Two exported enums are additionally provided: - RoleUser = "user": Input role type for user messages - RoleAssistant = "assistant": Input role type for assistant/Claude messages

Acknowledgments

The following project had particular influence on go-anthropic's design.

Additionally, we thank anthropic for providing the API and documentation.

License

go-anthropic is licensed under the Apache License, Version 2.0. See LICENSE for the full license text.

Owner

  • Name: Liu Shuang
  • Login: liushuangls
  • Kind: user
  • Location: chengdu, china

Citation (citations_test.go)

package anthropic

import (
	"encoding/json"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestCitationsMessageContent(t *testing.T) {
	// Test creating a text document with citations enabled
	doc := NewTextDocumentMessageContent(
		"The grass is green. The sky is blue.",
		"My Document",
		"This is a trustworthy document.",
		true,
	)

	assert.Equal(t, MessagesContentTypeDocument, doc.Type)
	assert.Equal(t, "My Document", doc.Title)
	assert.Equal(t, "This is a trustworthy document.", doc.Context)
	assert.NotNil(t, doc.DocumentCitations)
	assert.True(t, doc.DocumentCitations.Enabled)
	assert.Equal(t, string(MessagesContentSourceTypeText), string(doc.Source.Type))
	assert.Equal(t, "text/plain", doc.Source.MediaType)
	assert.Equal(t, "The grass is green. The sky is blue.", doc.Source.Data)

	// Test creating a custom content document
	content := []MessageContent{
		{Type: MessagesContentTypeText, Text: strPtr("First chunk")},
		{Type: MessagesContentTypeText, Text: strPtr("Second chunk")},
	}
	customDoc := NewCustomContentDocumentMessageContent(
		content,
		"Custom Document",
		"Document with custom chunks",
		true,
	)

	assert.Equal(t, MessagesContentTypeDocument, customDoc.Type)
	assert.Equal(t, "Custom Document", customDoc.Title)
	assert.Equal(t, "Document with custom chunks", customDoc.Context)
	assert.NotNil(t, customDoc.DocumentCitations)
	assert.True(t, customDoc.DocumentCitations.Enabled)
	assert.Equal(t, string(MessagesContentSourceTypeContent), string(customDoc.Source.Type))
	assert.Equal(t, content, customDoc.Source.Content)

	// Test merging citations delta
	textContent := MessageContent{
		Type: MessagesContentTypeText,
		Text: strPtr("Some text"),
	}

	citation := Citation{
		Type:           CitationTypeCharLocation,
		CitedText:      "The grass is green.",
		DocumentIndex:  0,
		DocumentTitle:  "My Document",
		StartCharIndex: intPtr(0),
		EndCharIndex:   intPtr(20),
	}

	delta := MessageContent{
		Type:     MessagesContentTypeCitationsDelta,
		Citation: &citation,
	}

	textContent.MergeContentDelta(delta)
	assert.Len(t, textContent.Citations, 1)
	assert.Equal(t, citation, textContent.Citations[0])

	// Test JSON marshaling/unmarshaling
	jsonData := `{
                "type": "text",
                "text": "the grass is green",
                "citations": [
                        {
                                "type": "char_location",
                                "cited_text": "The grass is green.",
                                "document_index": 0,
                                "document_title": "My Document",
                                "start_char_index": 0,
                                "end_char_index": 20
                        }
                ]
        }`

	var msgContent MessageContent
	err := json.Unmarshal([]byte(jsonData), &msgContent)
	assert.NoError(t, err)

	// Print the unmarshaled content for debugging
	debugJson, _ := json.MarshalIndent(msgContent, "", "  ")
	t.Logf("Unmarshaled content: %s", string(debugJson))

	assert.Equal(t, MessagesContentTypeText, msgContent.Type)
	assert.Equal(t, "the grass is green", *msgContent.Text)

	// Initialize Citations if nil
	if msgContent.Citations == nil {
		msgContent.Citations = make([]Citation, 0)
	}

	assert.Len(t, msgContent.Citations, 1)
	assert.Equal(t, CitationTypeCharLocation, msgContent.Citations[0].Type)
	assert.Equal(t, "The grass is green.", msgContent.Citations[0].CitedText)
}

func strPtr(s string) *string {
	return &s
}

func intPtr(i int) *int {
	return &i
}

GitHub Events

Total
  • Create event: 42
  • Issues event: 11
  • Release event: 16
  • Watch event: 62
  • Delete event: 22
  • Member event: 1
  • Issue comment event: 56
  • Push event: 40
  • Pull request review comment event: 37
  • Pull request review event: 41
  • Pull request event: 67
  • Fork event: 14
Last Year
  • Create event: 42
  • Issues event: 11
  • Release event: 16
  • Watch event: 62
  • Delete event: 22
  • Member event: 1
  • Issue comment event: 56
  • Push event: 40
  • Pull request review comment event: 37
  • Pull request review event: 41
  • Pull request event: 67
  • Fork event: 14

Committers

Last synced: 7 months ago

All Time
  • Total Commits: 105
  • Total Committers: 11
  • Avg Commits per committer: 9.545
  • Development Distribution Score (DDS): 0.41
Past Year
  • Commits: 64
  • Committers: 11
  • Avg Commits per committer: 5.818
  • Development Distribution Score (DDS): 0.672
Top Committers
Name Email Commits
liushuang l****l@o****m 62
William Matthews w****s@m****m 16
dependabot[bot] 4****] 14
Mike Mann m****n@p****m 3
mrheinen n****n@g****m 2
Ilya Brin 4****n 2
Steve Heyman s****e@r****m 2
shadowpigy 7****y 1
David Ramiro d****d@k****c 1
Chris Hua h****r@g****m 1
mhpenta c****y@g****m 1
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 4 months ago

All Time
  • Total issues: 12
  • Total pull requests: 72
  • Average time to close issues: 25 days
  • Average time to close pull requests: 3 days
  • Total issue authors: 11
  • Total pull request authors: 12
  • Average comments per issue: 1.0
  • Average comments per pull request: 1.18
  • Merged pull requests: 59
  • Bot issues: 0
  • Bot pull requests: 27
Past Year
  • Issues: 10
  • Pull requests: 62
  • Average time to close issues: about 1 month
  • Average time to close pull requests: 3 days
  • Issue authors: 9
  • Pull request authors: 10
  • Average comments per issue: 0.9
  • Average comments per pull request: 1.03
  • Merged pull requests: 50
  • Bot issues: 0
  • Bot pull requests: 27
Top Authors
Issue Authors
  • WillMatthews (2)
  • 1matthewli (1)
  • psykhi (1)
  • chew-z (1)
  • PysomeZh (1)
  • willavos (1)
  • JanRuettinger (1)
  • zieen (1)
  • tonyhb (1)
  • jjhuff (1)
  • josharian (1)
Pull Request Authors
  • dependabot[bot] (32)
  • WillMatthews (31)
  • liushuangls (24)
  • Mrmann87 (6)
  • steveheyman (4)
  • ilyabrin (4)
  • shadowpigy (2)
  • mhpenta (2)
  • davidramiro (2)
  • HaraldNordgren (2)
  • stillmatic (2)
  • zieen (1)
  • mrheinen (1)
Top Labels
Issue Labels
enhancement (2)
Pull Request Labels
dependencies (32) github_actions (19) go (13)

Packages

  • Total packages: 2
  • Total downloads: unknown
  • Total dependent packages: 0
    (may contain duplicates)
  • Total dependent repositories: 0
    (may contain duplicates)
  • Total versions: 45
proxy.golang.org: github.com/liushuangls/go-anthropic/v2
  • Versions: 32
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Dependent packages count: 7.2%
Average: 7.6%
Dependent repos count: 8.1%
Last synced: 4 months ago
proxy.golang.org: github.com/liushuangls/go-anthropic
  • Versions: 13
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Dependent packages count: 8.6%
Average: 9.2%
Dependent repos count: 9.7%
Last synced: 4 months ago

Dependencies

.github/workflows/pr.yml actions
  • actions/checkout v2 composite
  • actions/setup-go v2 composite
  • codecov/codecov-action v4.0.1 composite
go.mod go
go.sum go