anthropic

package
v1.0.178 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 11, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

Anthropic LLM Integration

This package provides integration with Anthropic's Claude models using the official Anthropic SDK for Go.

Features

  • Official SDK Integration: Uses the official Anthropic SDK v1.4.0
  • Complete API Support: Text generation, multimodal inputs, function calling, streaming
  • Comprehensive Testing: Unit tests, integration tests, and benchmarks
  • Type Safety: Full Go type safety with proper error handling
  • Configurable: Flexible configuration options with sensible defaults

Installation

go get github.com/effective-security/gogentic/pkg/llms/anthropic

Quick Start

Basic Setup
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/effective-security/gogentic/pkg/llms"
    "github.com/effective-security/gogentic/pkg/llms/anthropic"
)

func main() {
    // Initialize the client
    llm, err := anthropic.New(
        anthropic.WithToken("your-api-key"), // or set ANTHROPIC_API_KEY env var
        anthropic.WithModel("claude-3-5-sonnet-20241022"),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Create a simple message
    messages := []llms.MessageContent{
        {
            Role:  llms.ChatMessageTypeHuman,
            Parts: []llms.ContentPart{llms.TextPart("Hello, how are you?")},
        },
    }

    // Generate content
    resp, err := llm.GenerateContent(context.Background(), messages)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(resp.Choices[0].Content)
}
Environment Variable Setup

Set your API key as an environment variable:

export ANTHROPIC_API_KEY="your-api-key-here"

Then you can omit the token from the configuration:

llm, err := anthropic.New(
    anthropic.WithModel("claude-3-5-sonnet-20241022"),
)

Configuration Options

Available Options
// API Configuration
anthropic.WithToken("your-api-key")                    // API key
anthropic.WithModel("claude-3-5-sonnet-20241022")      // Model selection
anthropic.WithBaseURL("https://api.anthropic.com")     // Custom base URL

// HTTP Configuration  
anthropic.WithHTTPClient(&http.Client{})               // Custom HTTP client
anthropic.WithAnthropicBetaHeader("beta-feature-1")    // Beta features
Supported Models
  • claude-3-5-sonnet-20241022 (Latest and most capable)
  • claude-3-5-haiku-20241022 (Fast and cost-effective)
  • claude-3-opus-20240229 (Most powerful for complex tasks)
  • claude-3-sonnet-20240229 (Balanced performance)
  • claude-3-haiku-20240307 (Fastest response times)

Structured JSON outputs (see Structured JSON Outputs) are supported on: claude-opus-4-6, claude-sonnet-4-5, claude-opus-4-5, claude-haiku-4-5.

Advanced Usage

System Messages and Conversation
messages := []llms.MessageContent{
    {
        Role:  llms.ChatMessageTypeSystem,
        Parts: []llms.ContentPart{llms.TextPart("You are a helpful assistant.")},
    },
    {
        Role:  llms.ChatMessageTypeHuman,
        Parts: []llms.ContentPart{llms.TextPart("What's the weather like?")},
    },
    {
        Role:  llms.ChatMessageTypeAI,
        Parts: []llms.ContentPart{llms.TextPart("I'd be happy to help! However, I don't have access to real-time weather data.")},
    },
    {
        Role:  llms.ChatMessageTypeHuman,
        Parts: []llms.ContentPart{llms.TextPart("Can you tell me a joke instead?")},
    },
}

resp, err := llm.GenerateContent(ctx, messages)
Multimodal (Image) Support
// Read an image file
imageData, err := os.ReadFile("image.jpg")
if err != nil {
    log.Fatal(err)
}

messages := []llms.MessageContent{
    {
        Role: llms.ChatMessageTypeHuman,
        Parts: []llms.ContentPart{
            llms.TextPart("What do you see in this image?"),
            llms.BinaryPart("image/jpeg", imageData),
        },
    },
}

resp, err := llm.GenerateContent(ctx, messages)
Streaming Responses
messages := []llms.MessageContent{
    {
        Role:  llms.ChatMessageTypeHuman,
        Parts: []llms.ContentPart{llms.TextPart("Write a short story")},
    },
}

resp, err := llm.GenerateContent(ctx, messages,
    llms.WithStreamingFunc(func(ctx context.Context, chunk []byte) error {
        fmt.Print(string(chunk)) // Print each chunk as it arrives
        return nil
    }),
)
Function/Tool Calling
package main

import (
    "context"
    "reflect"

    "github.com/effective-security/gogentic/pkg/llms"
    "github.com/effective-security/gogentic/pkg/llms/anthropic"
    "github.com/effective-security/gogentic/pkg/schema"
)

// Define function parameters
type WeatherParams struct {
    Location string `json:"location" description:"The city and state, e.g. San Francisco, CA"`
    Unit     string `json:"unit" description:"Temperature unit" enum:"celsius,fahrenheit"`
}

func main() {
    llm, err := anthropic.New(
        anthropic.WithModel("claude-3-5-sonnet-20241022"),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Create schema for function parameters
    schema, err := schema.New(reflect.TypeOf(WeatherParams{}))
    if err != nil {
        log.Fatal(err)
    }

    // Define available functions
    functions := []llms.FunctionDefinition{
        {
            Name:        "get_weather",
            Description: "Get current weather information",
            Parameters:  schema.Parameters,
        },
    }

    messages := []llms.MessageContent{
        {
            Role:  llms.ChatMessageTypeHuman,
            Parts: []llms.ContentPart{llms.TextPart("What's the weather in Tokyo?")},
        },
    }

    // Make the request with functions
    resp, err := llm.GenerateContent(ctx, messages, llms.WithFunctions(functions))
    if err != nil {
        log.Fatal(err)
    }

    // Check if the model wants to call a function
    if len(resp.Choices[0].ToolCalls) > 0 {
        toolCall := resp.Choices[0].ToolCalls[0]
        fmt.Printf("Function call: %s\n", toolCall.FunctionCall.Name)
        fmt.Printf("Arguments: %s\n", toolCall.FunctionCall.Arguments)
        
        // You would implement the actual function call here
        // Then send the result back to continue the conversation
    }
}
Structured JSON Outputs

Claude can generate JSON responses that strictly follow a specified schema using structured outputs. Use llms.WithResponseFormat() with a schema from schema.NewResponseFormat():

package main

import (
    "context"
    "fmt"
    "log"
    "reflect"

    "github.com/effective-security/gogentic/pkg/llms"
    "github.com/effective-security/gogentic/pkg/llms/anthropic"
    "github.com/effective-security/gogentic/pkg/schema"
)

// Define your expected output structure
type InvoiceData struct {
    InvoiceNumber string  `json:"invoice_number" description:"The invoice number"`
    Date          string  `json:"date" description:"Invoice date"`
    TotalAmount   float64 `json:"total_amount" description:"Total amount"`
    CustomerName  string  `json:"customer_name" description:"Customer name"`
}

func main() {
    llm, err := anthropic.New(
        anthropic.WithModel("claude-sonnet-4-5-20241022"), // or claude-opus-4-6 for structured outputs
    )
    if err != nil {
        log.Fatal(err)
    }

    // Create schema from struct
    responseFormat, err := schema.NewResponseFormat(reflect.TypeOf(InvoiceData{}), true)
    if err != nil {
        log.Fatal(err)
    }

    messages := []llms.Message{
        llms.MessageFromTextParts(llms.RoleHuman,
            "Extract invoice data: Invoice #INV-2024-001 dated Jan 15, 2024 for $1,234.56 to John Doe"),
    }

    resp, err := llm.GenerateContent(context.Background(), messages,
        llms.WithResponseFormat(responseFormat),
        llms.WithMaxTokens(1024),
    )
    if err != nil {
        log.Fatal(err)
    }

    // Response is guaranteed to be valid JSON matching the schema
    fmt.Println(resp.Choices[0].Content)
}

Features:

  • Guaranteed valid JSON output
  • Type-safe schema validation
  • No parsing errors
  • Consistent field types
  • All required fields present

Supported models for structured outputs: claude-opus-4-6, claude-sonnet-4-5, claude-opus-4-5, claude-haiku-4-5

Configuration Parameters
resp, err := llm.GenerateContent(ctx, messages,
    llms.WithTemperature(0.7),        // Creativity (0.0-1.0)
    llms.WithMaxTokens(1000),         // Maximum response length
    llms.WithTopP(0.9),               // Nucleus sampling
    llms.WithStopWords([]string{"END"}), // Stop sequences
)

Error Handling

The package provides comprehensive error handling:

resp, err := llm.GenerateContent(ctx, messages)
if err != nil {
    // Errors are wrapped with context information
    if strings.Contains(err.Error(), "authentication_error") {
        log.Fatal("Invalid API key")
    }
    if strings.Contains(err.Error(), "rate_limit_error") {
        log.Fatal("Rate limit exceeded")
    }
    log.Fatal("Other error:", err)
}

Testing

Unit Tests

Run the unit tests:

go test ./pkg/llms/anthropic/ -v -short
Integration Tests

For integration tests with real API calls, set your API key and run:

export ANTHROPIC_API_KEY="your-api-key"
go test ./pkg/llms/anthropic/ -v
Benchmarks

Run performance benchmarks:

go test ./pkg/llms/anthropic/ -bench=. -short

Migration from Custom Client

This package replaces the previous custom Anthropic client implementation with the official SDK. Key changes:

  1. Official SDK: Now uses github.com/anthropics/anthropic-sdk-go
  2. Better Type Safety: Improved type definitions and error handling
  3. Complete API Coverage: Full support for all Anthropic API features
  4. Performance: Better streaming and connection handling
  5. Maintenance: Official support and updates from Anthropic
Migration Guide

If migrating from the old custom client:

  1. Update imports to use the new package
  2. Update function calls to use the new anthropic.New() constructor
  3. API remains largely the same for basic usage
  4. Tool calling syntax updated to use new schema format

Best Practices

1. API Key Security
  • Never hardcode API keys in source code
  • Use environment variables or secure configuration management
  • Rotate keys regularly
2. Error Handling
  • Always check for errors from API calls
  • Implement appropriate retry logic for transient failures
  • Log errors with sufficient context for debugging
3. Rate Limiting
  • Implement backoff strategies for rate limit errors
  • Monitor your usage to stay within limits
  • Consider using multiple API keys for high-volume applications
4. Cost Management
  • Use appropriate models for your use case (Haiku for simple tasks, Sonnet/Opus for complex ones)
  • Set reasonable max_tokens limits
  • Monitor token usage and costs
5. Content Safety
  • Implement content filtering for user inputs
  • Review Anthropic's usage policies
  • Consider implementing safety measures for generated content

Performance Considerations

Model Selection
Model Speed Cost Capability Best For
Claude 3.5 Haiku Fastest Lowest Good Simple tasks, high volume
Claude 3.5 Sonnet Balanced Medium Excellent General purpose
Claude 3 Opus Slower Highest Best Complex reasoning, analysis
Streaming vs Non-Streaming
  • Use streaming for real-time user interfaces
  • Use non-streaming for batch processing
  • Streaming reduces perceived latency
Connection Management
  • Reuse the client instance across requests
  • Configure appropriate timeouts for your use case
  • Consider connection pooling for high-volume applications

Contributing

  1. Ensure all tests pass: go test ./...
  2. Run linting: make lint
  3. Add tests for new functionality
  4. Update documentation for API changes

License

This package is part of the gogentic project. See the main project license for details.

Documentation

Overview

Package anthropic implements the Anthropic (Claude) llms.Model with options for API key, model selection, and custom HTTP client or AWS config when used via Bedrock (see NewBedrock in this package).

Example

mdl, err := anthropic.New(
    anthropic.WithToken(os.Getenv("ANTHROPIC_API_KEY")),
    anthropic.WithModel("claude-3-5-sonnet-20240620"),
)
_ = mdl; _ = err

The models an account can call are listed with NewModelLister, which needs no model name, or with LLM.ListModels.

Example (AdvancedConfiguration)

Example_advancedConfiguration demonstrates various configuration options

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/effective-security/gogentic/pkg/llms"
	"github.com/effective-security/gogentic/pkg/llms/anthropic"
)

func main() {
	llm, err := anthropic.New(
		anthropic.WithModel("claude-3-5-sonnet-20241022"),
		anthropic.WithBaseURL("https://api.anthropic.com"),
		// anthropic.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
		// anthropic.WithAnthropicBetaHeader("beta-feature-1"),
	)
	if err != nil {
		log.Fatal(err)
	}

	messages := []llms.Message{
		llms.MessageFromTextParts(llms.RoleSystem, "You are a creative writer."),
		llms.MessageFromTextParts(llms.RoleHuman, "Write a very short story about a robot learning to paint."),
	}

	resp, err := llm.GenerateContent(context.Background(), messages,
		llms.WithTemperature(0.8),           // Higher creativity
		llms.WithMaxTokens(300),             // Limit response length
		llms.WithTopP(0.9),                  // Nucleus sampling
		llms.WithStopWords([]string{"END"}), // Stop if this sequence appears
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Generated story:\n%s\n", resp.Choices[0].Content)

	// Access generation metadata
	info := resp.Choices[0].Usage
	if info.InputTokens > 0 {
		fmt.Printf("Input tokens used: %v\n", info.InputTokens)
	}
	if info.OutputTokens > 0 {
		fmt.Printf("Output tokens used: %v\n", info.OutputTokens)
	}
	if info.TotalTokens > 0 {
		fmt.Printf("Total tokens used: %v\n", info.TotalTokens)
	}
}
Example (BasicUsage)

Example_basicUsage demonstrates basic text generation

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/effective-security/gogentic/pkg/llms"
	"github.com/effective-security/gogentic/pkg/llms/anthropic"
)

func main() {
	// Initialize the client
	llm, err := anthropic.New(
		anthropic.WithToken("your-api-key"), // or set ANTHROPIC_API_KEY env var
		anthropic.WithModel("claude-3-5-sonnet-20241022"),
	)
	if err != nil {
		log.Fatal(err)
	}

	// Create a simple message
	messages := []llms.Message{
		llms.MessageFromTextParts(llms.RoleHuman, "Hello, how are you?"),
	}

	// Generate content
	resp, err := llm.GenerateContent(context.Background(), messages)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.Choices[0].Content)
}
Example (ConversationWithSystem)

Example_conversationWithSystem demonstrates system messages and multi-turn conversation

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/effective-security/gogentic/pkg/llms"
	"github.com/effective-security/gogentic/pkg/llms/anthropic"
)

func main() {
	llm, err := anthropic.New(
		anthropic.WithModel("claude-3-5-sonnet-20241022"),
	)
	if err != nil {
		log.Fatal(err)
	}

	messages := []llms.Message{
		llms.MessageFromTextParts(llms.RoleSystem, "You are a helpful math tutor. Always explain your reasoning step by step."),
		llms.MessageFromTextParts(llms.RoleHuman, "What is 25 * 4?"),
		llms.MessageFromTextParts(llms.RoleAI, "Let me solve this step by step:\n25 × 4 = 100\n\nThis is because 25 × 4 is the same as 25 × 4 = (20 + 5) × 4 = 20 × 4 + 5 × 4 = 80 + 20 = 100."),
		llms.MessageFromTextParts(llms.RoleHuman, "Now what about 25 * 8?"),
	}

	resp, err := llm.GenerateContent(context.Background(), messages)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.Choices[0].Content)
}
Example (DifferentModels)

Example_differentModels demonstrates using different Claude models

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/effective-security/gogentic/pkg/llms"
	"github.com/effective-security/gogentic/pkg/llms/anthropic"
)

func main() {
	models := []string{
		"claude-3-5-haiku-20241022",  // Fast and cost-effective
		"claude-3-5-sonnet-20241022", // Balanced performance
		"claude-3-opus-20240229",     // Most capable for complex tasks
	}

	message := "Explain quantum computing in one sentence."

	for _, model := range models {
		llm, err := anthropic.New(
			anthropic.WithModel(model),
		)
		if err != nil {
			log.Printf("Failed to initialize %s: %v", model, err)
			continue
		}

		messages := []llms.Message{
			llms.MessageFromTextParts(llms.RoleHuman, message),
		}

		resp, err := llm.GenerateContent(context.Background(), messages,
			llms.WithMaxTokens(100),
		)
		if err != nil {
			log.Printf("Error with %s: %v", model, err)
			continue
		}

		fmt.Printf("%s: %s\n\n", model, resp.Choices[0].Content)
	}
}
Example (ErrorHandling)

Example_errorHandling demonstrates proper error handling

package main

import (
	"context"
	"fmt"

	"github.com/effective-security/gogentic/pkg/llms"
	"github.com/effective-security/gogentic/pkg/llms/anthropic"
)

func main() {
	// Example with invalid configuration to show error handling
	llm, err := anthropic.New(
		anthropic.WithToken("invalid-token"),
		anthropic.WithModel("claude-3-5-sonnet-20241022"),
	)
	if err != nil {
		fmt.Printf("Configuration error: %v\n", err)
		return
	}

	messages := []llms.Message{
		llms.MessageFromTextParts(llms.RoleHuman, "Hello"),
	}

	resp, err := llm.GenerateContent(context.Background(), messages)
	if err != nil {
		// Handle different types of errors
		switch {
		case contains(err.Error(), "authentication_error"):
			fmt.Println("Authentication failed: check your API key")
		case contains(err.Error(), "rate_limit_error"):
			fmt.Println("Rate limit exceeded: please wait and retry")
		case contains(err.Error(), "invalid_request_error"):
			fmt.Println("Invalid request: check your parameters")
		default:
			fmt.Printf("Other error: %v\n", err)
		}
		return
	}

	fmt.Printf("Success: %s\n", resp.Choices[0].Content)
}

// Helper function for error handling example
func contains(s, substr string) bool {
	return len(s) >= len(substr) && s[:len(substr)] == substr
}
Example (MultimodalWithImage)

Example_multimodalWithImage demonstrates image analysis

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/effective-security/gogentic/pkg/llms"
	"github.com/effective-security/gogentic/pkg/llms/anthropic"
)

func main() {
	llm, err := anthropic.New(
		anthropic.WithModel("claude-3-5-sonnet-20241022"),
	)
	if err != nil {
		log.Fatal(err)
	}

	// Read an image file (you would replace this with actual image data)
	imageData, err := os.ReadFile("example.jpg")
	if err != nil {
		// For this example, we'll use a placeholder
		imageData = []byte("placeholder-image-data")
	}

	messages := []llms.Message{
		{
			Role: llms.RoleHuman,
			Parts: []llms.ContentPart{
				llms.TextPart("What do you see in this image? Please describe it in detail."),
				llms.BinaryPart("image/jpeg", imageData),
			},
		},
	}

	resp, err := llm.GenerateContent(context.Background(), messages,
		llms.WithMaxTokens(500),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(resp.Choices[0].Content)
}
Example (StreamingResponse)

Example_streamingResponse demonstrates real-time streaming

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/effective-security/gogentic/pkg/llms"
	"github.com/effective-security/gogentic/pkg/llms/anthropic"
)

func main() {
	llm, err := anthropic.New(
		anthropic.WithModel("claude-3-5-sonnet-20241022"),
	)
	if err != nil {
		log.Fatal(err)
	}

	messages := []llms.Message{
		llms.MessageFromTextParts(llms.RoleHuman, "Write a short poem about programming"),
	}

	fmt.Print("Streaming response: ")
	resp, err := llm.GenerateContent(context.Background(), messages,
		llms.WithStreamingFunc(func(ctx context.Context, chunk []byte) error {
			fmt.Print(string(chunk)) // Print each chunk as it arrives
			return nil
		}),
		llms.WithMaxTokens(200),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("\n\nFinal response: %s\n", resp.Choices[0].Content)
}
Example (ToolCalling)

Example_toolCalling demonstrates tool/function calling

package main

import (
	"context"
	"fmt"
	"log"
	"reflect"

	"github.com/effective-security/gogentic/pkg/llms"
	"github.com/effective-security/gogentic/pkg/llms/anthropic"
	"github.com/effective-security/gogentic/pkg/schema"
)

func main() {
	llm, err := anthropic.New(
		anthropic.WithModel("claude-3-5-sonnet-20241022"),
	)
	if err != nil {
		log.Fatal(err)
	}

	// Define function parameters
	type WeatherParams struct {
		Location string `json:"location" description:"The city and state, e.g. San Francisco, CA"`
		Unit     string `json:"unit" description:"Temperature unit" enum:"celsius,fahrenheit"`
	}

	// Create schema for function parameters
	schema, err := schema.New(reflect.TypeOf(WeatherParams{}))
	if err != nil {
		log.Fatal(err)
	}

	// Define available functions
	tools := []llms.Tool{
		{
			Type: "function",
			Function: &llms.FunctionDefinition{
				Name:        "get_weather",
				Description: "Get current weather information for a location",
				Parameters:  schema.Parameters,
			},
		},
	}

	messages := []llms.Message{
		llms.MessageFromTextParts(llms.RoleHuman, "What's the weather like in Tokyo, Japan?"),
	}

	// Make the request with functions
	resp, err := llm.GenerateContent(context.Background(), messages,
		llms.WithTools(tools),
	)
	if err != nil {
		log.Fatal(err)
	}

	// Check if the model wants to call a function
	if len(resp.Choices[0].ToolCalls) > 0 {
		toolCall := resp.Choices[0].ToolCalls[0]
		fmt.Printf("Function call requested:\n")
		fmt.Printf("  Function: %s\n", toolCall.FunctionCall.Name)
		fmt.Printf("  Arguments: %s\n", toolCall.FunctionCall.Arguments)

		// Simulate function execution (you would implement the actual function here)
		functionResult := "Temperature: 22°C, Condition: Partly cloudy, Humidity: 65%"

		// Continue the conversation with the function result
		messages = append(messages, llms.Message{
			Role: llms.RoleAI,
			Parts: []llms.ContentPart{
				llms.ToolCall{
					ID:           toolCall.ID,
					FunctionCall: toolCall.FunctionCall,
				},
			},
		})

		messages = append(messages, llms.Message{
			Role: llms.RoleTool,
			Parts: []llms.ContentPart{
				llms.ToolCallResponse{
					ToolCallID: toolCall.ID,
					Content:    functionResult,
				},
			},
		})

		// Get the final response
		finalResp, err := llm.GenerateContent(context.Background(), messages)
		if err != nil {
			log.Fatal(err)
		}

		fmt.Printf("Final response: %s\n", finalResp.Choices[0].Content)
	} else {
		fmt.Printf("Direct response: %s\n", resp.Choices[0].Content)
	}
}

Index

Examples

Constants

View Source
const (
	RoleUser      = "user"
	RoleAssistant = "assistant"
	RoleSystem    = "system"

	// DefaultMaxTokens is the max_tokens sent when a call sets none. It is
	// the 8192-token output limit of Claude 3.5 Sonnet, so that model and
	// every later one accept it. Claude 3 Haiku and Opus, which are
	// deprecated, stop at 4096 tokens and reject it: pass llms.WithMaxTokens
	// for them.
	DefaultMaxTokens = 8 * 1024

	// DefaultBaseURL is the endpoint of the Anthropic API.
	DefaultBaseURL = "https://api.anthropic.com"
)
View Source
const (
	TokenEnvVarName = "ANTHROPIC_API_KEY" //nolint:gosec
)

Variables

View Source
var (
	ErrEmptyResponse            = errors.New("anthropic: no response")
	ErrMissingToken             = errors.New("anthropic: missing API key, set it in the ANTHROPIC_API_KEY environment variable")
	ErrUnexpectedResponseLength = errors.New("anthropic: unexpected length of response")
	ErrInvalidContentType       = errors.New("anthropic: invalid content type")
	ErrUnsupportedMessageType   = errors.New("anthropic: unsupported message type")
	ErrUnsupportedContentType   = errors.New("anthropic: unsupported content type")
)

Functions

func GenerateMessagesContent added in v0.10.58

func GenerateMessagesContent(ctx context.Context, o *LLM, messages []llms.Message, opts *llms.CallOptions) (*llms.ContentResponse, error)

GenerateMessagesContent generates content using the Anthropic API with processed messages.

This function handles the core logic for generating content, including:

  • Message processing and conversion to Anthropic format
  • Tool definition handling
  • Parameter setup (temperature, max tokens, etc.)
  • Streaming and non-streaming responses

The function processes input messages to separate system prompts from conversation messages, converts tools to the Anthropic format, and handles both streaming and non-streaming responses.

func GenerateStreamingContent added in v0.10.58

func GenerateStreamingContent(ctx context.Context, o *LLM, params anthropic.MessageNewParams, streamingFunc func(context.Context, []byte) error, requestOpts ...option.RequestOption) (*llms.ContentResponse, error)

GenerateStreamingContent handles streaming responses from the Anthropic API.

This function establishes a streaming connection to the Anthropic API and processes real-time response chunks. It handles:

  • Text content streaming (delta updates)
  • Tool call streaming (partial JSON assembly)
  • Usage statistics collection
  • Error handling for streaming failures

The streaming function is called for each text chunk received, allowing for real-time display or processing of the generated content.

func HandleAIMessage added in v0.10.58

func HandleAIMessage(msg llms.Message) (anthropic.MessageParam, error)

HandleAIMessage converts AI assistant messages to Anthropic assistant message format.

This function handles AI/assistant messages and converts them to the Anthropic assistant message format. It supports:

  • Text responses from the assistant
  • Tool calls with function names and JSON arguments
  • Mixed content (text + tool calls)

Tool call arguments are validated as proper JSON before conversion.

func HandleHumanMessage added in v0.10.58

func HandleHumanMessage(msg llms.Message) (anthropic.MessageParam, error)

HandleHumanMessage converts human messages to Anthropic user message format.

This function handles human/user messages and converts them to the Anthropic user message format. It supports:

  • Text content
  • Image content (PNG, JPEG, GIF, WebP)
  • Base64 encoding for binary content
  • Multiple content parts in a single message

Images are automatically base64-encoded and formatted for the Anthropic API.

func HandleSystemMessage added in v0.10.58

func HandleSystemMessage(msg llms.Message) (string, error)

HandleSystemMessage extracts text content from system messages.

System messages in Anthropic are handled separately from conversation messages and are passed as a distinct system parameter. This function validates that the system message contains only text content and returns it as a string.

func HandleToolMessage added in v0.10.58

func HandleToolMessage(msg llms.Message) (anthropic.MessageParam, error)

HandleToolMessage converts tool response messages to Anthropic user message format.

This function handles tool call response messages and converts them to the Anthropic user message format with tool result content. Tool responses in Anthropic are sent as user messages containing tool result blocks.

The function validates that the message contains only tool call response content and formats it appropriately for the API.

func NewModelLister added in v1.0.173

func NewModelLister(opts ...Option) (llms.ModelLister, error)

NewModelLister returns a client that lists the models of an Anthropic account. It takes the options of New, and needs a token but no model name. The Bedrock endpoint has no model list: with WithAWSConfig it returns llms.ErrModelListNotSupported.

func ProcessMessages added in v0.10.58

func ProcessMessages(messages []llms.Message) ([]anthropic.MessageParam, string, error)

ProcessMessages converts generic message content to Anthropic SDK message parameters.

This function processes an array of message content and converts them to the format expected by the Anthropic API. It handles:

  • System message extraction (returned as separate system prompt)
  • Human message conversion (text and image content)
  • AI message conversion (text and tool calls)
  • Tool message conversion (tool call responses)
  • Error handling for unsupported message types

Returns the converted messages, extracted system prompt, and any error encountered.

func ToTools added in v0.10.58

func ToTools(tools []llms.Tool, model string) ([]anthropic.ToolUnionParam, error)

ToTools converts LLM tool definitions to Anthropic SDK tool parameters.

This function transforms the generic llms.Tool format into the specific anthropic.ToolUnionParam format required by the Anthropic SDK. It handles:

  • Function definition conversion
  • JSON schema property mapping from orderedmap to regular map
  • Required parameter specification
  • Tool description formatting
  • Model-aware web_fetch: legacy models (e.g. claude-sonnet-4-0) get WebFetchTool20250910Param, newer models get WebFetchTool20260209Param.

Returns nil if no tools are provided, which is handled gracefully by the API. Returns an error wrapping llms.ErrMissingFunctionDefinition for a tool other than web_search that has no function definition. A function without Parameters takes an empty object.

Types

type LLM

type LLM struct {
	Client  *anthropic.Client
	Options *Options
}

func New

func New(opts ...Option) (*LLM, error)

New creates a new Anthropic LLM client using the official Anthropic SDK.

This function initializes an Anthropic client with the provided options. If no token is provided via options, it will attempt to read the API key from the ANTHROPIC_API_KEY environment variable.

Required configuration:

  • API token (via WithToken option or ANTHROPIC_API_KEY env var)
  • Model (via WithModel option)

Example usage:

llm, err := anthropic.New(
    anthropic.WithToken("your-api-key"),
    anthropic.WithModel("claude-3-5-sonnet-20241022"),
)
if err != nil {
    log.Fatal(err)
}

// Generate content
resp, err := llm.GenerateContent(ctx, messages)

func NewBedrock added in v0.16.114

func NewBedrock(opts ...Option) (*LLM, error)

func (*LLM) GenerateContent

func (o *LLM) GenerateContent(ctx context.Context, messages []llms.Message, options ...llms.CallOption) (*llms.ContentResponse, error)

GenerateContent implements the Model interface.

This method generates content using the Anthropic API. It supports:

  • Text and image inputs (multimodal)
  • Tool/function calling
  • Streaming responses
  • Custom parameters (temperature, max tokens, etc.)

Example usage:

messages := []llms.MessageContent{
    {
        Role: llms.ChatMessageTypeHuman,
        Parts: []llms.ContentPart{llms.TextPart("Hello, how are you?")},
    },
}

resp, err := llm.GenerateContent(ctx, messages,
    llms.WithTemperature(0.7),
    llms.WithMaxTokens(1000),
)

func (*LLM) GetName added in v0.10.61

func (o *LLM) GetName() string

GetName implements the Model interface.

func (*LLM) GetProviderType added in v0.10.54

func (o *LLM) GetProviderType() llms.ProviderType

GetProviderType implements the Model interface.

func (*LLM) Infer added in v0.21.160

Infer uses the existing Anthropic SDK client with lossless schemas, thinking passthrough and no retries.

func (*LLM) ListModels added in v1.0.173

func (o *LLM) ListModels(ctx context.Context) ([]llms.ModelInfo, error)

ListModels implements llms.ModelLister. It returns the models of the account in every lifecycle stage, newest first, each with the model line as its Family and the effort levels the API reports for it.

A client built with NewBedrock returns llms.ErrModelListNotSupported: the Bedrock runtime endpoint has no model list.

func (*LLM) ValidateInference added in v0.21.160

func (o *LLM) ValidateInference(r llms.InferenceRequest) error

ValidateInference rejects nonportable Anthropic request controls.

type Option

type Option func(*Options)

func WithAWSConfig added in v0.19.148

func WithAWSConfig(cfg *aws.Config) Option

WithAWSConfig passes the AWS config to the client.

func WithAnthropicBetaHeader

func WithAnthropicBetaHeader(value string) Option

WithAnthropicBetaHeader adds the Anthropic Beta header to support extended options.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseUrl passes the Anthropic base URL to the client. If not set, the default base URL is used.

func WithEffortPolicy added in v1.0.173

func WithEffortPolicy(policy llms.EffortPolicy) Option

WithEffortPolicy sets the reasoning effort used when a call requests none, and the highest effort any call may use. Each call still sends the nearest level its model accepts. Legacy GenerateContent only; the portable Infer path is unaffected.

func WithHTTPClient

func WithHTTPClient(client option.HTTPClient) Option

WithHTTPClient allows setting a custom HTTP client. If not set, the default value is http.DefaultClient.

func WithModel

func WithModel(model string) Option

WithModel passes the Anthropic model to the client.

func WithToken

func WithToken(token string) Option

WithToken passes the Anthropic API token to the client. If not set, the token is read from the ANTHROPIC_API_KEY environment variable.

type Options added in v0.10.58

type Options struct {
	Token      string
	Model      string
	BaseURL    string
	HttpClient option.HTTPClient

	// If supplied, the 'anthropic-beta' header will be added to the request with the given value.
	AnthropicBetaHeader string

	// AWSCfg is used with Bedrock
	AWSCfg *aws.Config

	// Effort is the reasoning effort default and ceiling for every call.
	Effort llms.EffortPolicy
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址