sapaicore

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jul 8, 2026 License: MIT Imports: 10 Imported by: 0

README

adk-provider-sapaicore

ADK Go v2 model provider for SAP AI Core.

Implements model.LLM so any ADK agent can use GPT, Claude, Gemini, Mistral, or any other model deployed on SAP AI Core without changing agent code.

Install

go get github.com/PedroKlein/adk-provider-sapaicore

Requires Go 1.25+.

Quick Start

The simplest setup uses orchestration mode with auto-discovery (the default):

provider, err := sapaicore.NewProvider(
    sapaicore.WithEndpoint(os.Getenv("AI_CORE_ENDPOINT")),
    sapaicore.WithAuth(
        os.Getenv("AI_CORE_CLIENT_ID"),
        os.Getenv("AI_CORE_CLIENT_SECRET"),
        os.Getenv("AI_CORE_AUTH_URL"),
    ),
)

Then pass the model to any ADK agent:

llm, _ := provider.Model("gpt-4.1")

agent := llmagent.New(llmagent.Config{
    Name:        "my-agent",
    Model:       llm,
    Instruction: "You are a helpful assistant.",
})

r := runner.New(runner.Config{AppName: "my-app", Agent: agent})

for event, err := range r.Run(ctx, userID, sessionID, userMsg) {
    // handle events
}

Any model available on your SAP AI Core instance works by name:

provider.Model("gpt-4.1-mini")
provider.Model("anthropic--claude-4.5-sonnet")
provider.Model("gemini-2.5-flash")
provider.Model("o4-mini")
provider.Model("mistralai--mistral-large-instruct")
provider.Model("deepseek-r1-0528")

Streaming

Streaming works through the standard ADK interface. The provider yields partial text chunks followed by a final aggregated response:

for resp, err := range llm.GenerateContent(ctx, req, true) {
    if resp.Partial {
        fmt.Print(resp.Content.Parts[0].Text) // incremental text
        continue
    }
    // Final response with full text, usage metadata, and finish reason
    fmt.Println(resp.Content.Parts[0].Text)
    fmt.Println(resp.UsageMetadata.PromptTokenCount)
}

Tool Calling

Define tools using standard ADK/genai types. The provider handles the full cycle: function call requests from the model, and function results sent back.

llm, _ := provider.Model("gpt-4.1-mini")

req := &model.LLMRequest{
    Contents: []*genai.Content{
        {Parts: []*genai.Part{{Text: "What's the weather in Berlin?"}}, Role: "user"},
    },
    Config: &genai.GenerateContentConfig{
        Tools: []*genai.Tool{{
            FunctionDeclarations: []*genai.FunctionDeclaration{{
                Name:        "get_weather",
                Description: "Get current weather for a city",
                Parameters:  &genai.Schema{Type: "OBJECT", Properties: map[string]*genai.Schema{
                    "city": {Type: "STRING"},
                }, Required: []string{"city"}},
            }},
        }},
    },
}

// Model returns FunctionCall parts
for resp, _ := range llm.GenerateContent(ctx, req, false) {
    for _, part := range resp.Content.Parts {
        if part.FunctionCall != nil {
            fmt.Printf("Call: %s(%v)\n", part.FunctionCall.Name, part.FunctionCall.Args)
        }
    }
}

Sending tool results back works through the standard content history:

// After executing the tool, send the result back:
contents := []*genai.Content{
    {Parts: []*genai.Part{{Text: "What's the weather?"}}, Role: "user"},
    {Parts: []*genai.Part{{FunctionCall: call}}, Role: "model"},
    {Parts: []*genai.Part{{FunctionResponse: &genai.FunctionResponse{
        ID: call.ID, Name: call.Name,
        Response: map[string]any{"temp": "22°C", "condition": "sunny"},
    }}}, Role: "user"},
}

Multi-modal Input (Images & Files)

Send images or documents alongside text using standard ADK genai.Part types:

// Image from bytes (InlineData)
req := &model.LLMRequest{
    Contents: []*genai.Content{{
        Role: "user",
        Parts: []*genai.Part{
            {Text: "What's in this image?"},
            {InlineData: &genai.Blob{Data: pngBytes, MIMEType: "image/png"}},
        },
    }},
}

// Image from URL (FileData)
req := &model.LLMRequest{
    Contents: []*genai.Content{{
        Role: "user",
        Parts: []*genai.Part{
            {Text: "Describe this image."},
            {FileData: &genai.FileData{
                FileURI:  "https://example.com/photo.jpg",
                MIMEType: "image/jpeg",
            }},
        },
    }},
}

// PDF document (Claude and Gemini only)
req := &model.LLMRequest{
    Contents: []*genai.Content{{
        Role: "user",
        Parts: []*genai.Part{
            {Text: "Summarize this document."},
            {InlineData: &genai.Blob{Data: pdfBytes, MIMEType: "application/pdf"}},
        },
    }},
}

Supported image formats: PNG, JPEG, GIF, WebP. File support varies by model (Claude: PDF; Gemini: PDF, CSV, MP3).

Note: SAP AI Core does not support fetching external URLs. Use InlineData with the file bytes. FileData with HTTP/HTTPS URLs will be rejected by the API with a download error.

Content Filtering

Enable input/output safety filtering with zero configuration:

// Strictest defaults: Azure Content Safety ALLOW_SAFE + prompt_shield on all categories.
provider, _ := sapaicore.NewProvider(ctx,
    sapaicore.WithEndpoint(endpoint),
    sapaicore.WithAuth(clientID, clientSecret, authURL),
    sapaicore.WithFiltering(nil), // nil = sensible defaults
)

Or customize thresholds and providers:

provider, _ := sapaicore.NewProvider(ctx,
    sapaicore.WithEndpoint(endpoint),
    sapaicore.WithAuth(clientID, clientSecret, authURL),
    sapaicore.WithFiltering(&sapaicore.FilteringConfig{
        Input: &sapaicore.InputFilterConfig{
            AzureContentSafety: &sapaicore.AzureContentSafetyConfig{
                Hate:         sapaicore.AzureThresholdAllowSafeLow,
                SelfHarm:     sapaicore.AzureThresholdAllowSafe,
                Sexual:       sapaicore.AzureThresholdAllowSafe,
                Violence:     sapaicore.AzureThresholdAllowSafeLow,
                PromptShield: true,
            },
            LlamaGuard: &sapaicore.LlamaGuardConfig{
                Hate: true,
                ChildExploitation: true,
            },
        },
        Output: &sapaicore.OutputFilterConfig{
            AzureContentSafety: &sapaicore.AzureContentSafetyConfig{
                Hate: sapaicore.AzureThresholdAllowSafe,
            },
        },
    }),
)

Data Masking

Redact PII before messages reach the LLM:

provider, _ := sapaicore.NewProvider(ctx,
    sapaicore.WithEndpoint(endpoint),
    sapaicore.WithAuth(clientID, clientSecret, authURL),
    sapaicore.WithMasking(sapaicore.MaskingConfig{
        Method:   sapaicore.Anonymization,
        Entities: sapaicore.StandardEntities(sapaicore.CommonPIIEntities),
        Allowlist: []string{"SAP", "Joule"},
    }),
)

Custom regex entities:

sapaicore.WithMasking(sapaicore.MaskingConfig{
    Entities: []sapaicore.MaskingEntity{
        sapaicore.StandardEntity(sapaicore.EntityEmail),
        sapaicore.StandardEntity(sapaicore.EntityPhone),
        sapaicore.CustomMaskingEntity(`\b[0-9]{2}-SAP-[0-9]{3}\b`, "REDACTED_ID"),
    },
})

Replacement strategies for standard entities:

sapaicore.WithMasking(sapaicore.MaskingConfig{
    Method: sapaicore.Pseudonymization,
    Entities: []sapaicore.MaskingEntity{
        sapaicore.StandardEntity(sapaicore.EntityEmail),           // DPI default
        sapaicore.FabricatedEntity(sapaicore.EntityPerson),       // realistic fake data
        sapaicore.ConstantEntity(sapaicore.EntityPhone, "PHONE"), // fixed value + incrementing number
    },
})

When using file input with masking, set MaskFileInputMethod:

sapaicore.WithMasking(sapaicore.MaskingConfig{
    Method:              sapaicore.Anonymization,
    Entities:            sapaicore.StandardEntities(sapaicore.CommonPIIEntities),
    MaskFileInputMethod: sapaicore.MaskFileSkip, // or sapaicore.MaskFileAnonymization
})

Translation

Translate input before the LLM or output after generation:

provider, _ := sapaicore.NewProvider(ctx,
    sapaicore.WithEndpoint(endpoint),
    sapaicore.WithAuth(clientID, clientSecret, authURL),
    sapaicore.WithTranslation(sapaicore.TranslationConfig{
        Output: &sapaicore.TranslationOutputConfig{
            TargetLanguage: "de-DE",
        },
    }),
)

Module Fallback

Try the primary model first, fall back to alternatives on failure:

llm, _ := provider.Model("gpt-4.1",
    sapaicore.WithModelFallback("gpt-4.1-mini", "gpt-4.1-nano"),
)

Fallback models inherit all module configurations (filtering, masking, translation).

Prompt Caching

Enable Anthropic prompt caching (auto-annotates system message and tools with cache_control):

llm, _ := provider.Model("anthropic--claude-4.5-sonnet",
    sapaicore.WithModelPromptCaching(),
)

For 1-hour TTL on supported models (Claude Opus 4.5, Haiku 4.5, Sonnet 4.5):

llm, _ := provider.Model("anthropic--claude-4.5-sonnet",
    sapaicore.WithModelPromptCaching(sapaicore.CacheTTL1h),
)

Module Composition

Modules can be set at provider level (defaults for all models) and overridden per-model:

// Provider-level: all models get filtering + masking.
provider, _ := sapaicore.NewProvider(ctx,
    sapaicore.WithEndpoint(endpoint),
    sapaicore.WithAuth(clientID, clientSecret, authURL),
    sapaicore.WithFiltering(nil),
    sapaicore.WithMasking(sapaicore.MaskingConfig{
        Entities: sapaicore.StandardEntities(sapaicore.CommonPIIEntities),
    }),
)

// This model inherits both filtering and masking.
llm1, _ := provider.Model("gpt-4.1")

// This model replaces filtering with a permissive config, keeps masking.
llm2, _ := provider.Model("gpt-4.1-mini",
    sapaicore.WithModelFiltering(&sapaicore.FilteringConfig{
        Input: &sapaicore.InputFilterConfig{
            AzureContentSafety: &sapaicore.AzureContentSafetyConfig{
                Hate: sapaicore.AzureThresholdAllowAll,
            },
        },
    }),
)

// This model has no filtering at all, keeps masking.
llm3, _ := provider.Model("gpt-4.1-mini", sapaicore.WithoutFiltering())

Composition rules:

  • Same module at both levels → model replaces provider
  • Different modules → both apply
  • Without*() → explicitly removes inherited module

Orchestration modules in foundation-models mode produce an error at Model() time:

// This returns ErrMissingConfig — modules require orchestration mode.
provider, _ := sapaicore.NewProvider(ctx,
    sapaicore.WithEndpoint(endpoint),
    sapaicore.WithAuth(id, secret, url),
    sapaicore.WithDeployments(map[string]string{"gpt-4.1": "d1"}),
    sapaicore.WithFiltering(nil), // ← orchestration module
)
_, err := provider.Model("gpt-4.1") // err: orchestration modules require orchestration mode

Invalid configs also error at Model() time:

  • TranslationConfig with neither Input nor Output set
  • MaskingConfig with empty Entities

Foundation-Models Mode

For per-model deployments (dedicated capacity, custom fine-tunes):

provider, _ := sapaicore.NewProvider(
    sapaicore.WithEndpoint(os.Getenv("AI_CORE_ENDPOINT")),
    sapaicore.WithAuth(clientID, clientSecret, authURL),
    sapaicore.WithDeployments(map[string]string{
        "gpt-4.1":      "d1234abc",
        "gpt-4.1-mini": "d5678def",
    }),
)

llm, _ := provider.Model("gpt-4.1") // routes to deployment d1234abc

Extra Model Parameters

For provider-specific features beyond what ADK exposes:

// Claude extended thinking
llm, _ := provider.Model("anthropic--claude-4.5-sonnet",
    sapaicore.WithModelParams(map[string]any{
        "thinking":   map[string]any{"type": "enabled", "budget_tokens": 16384},
        "max_tokens": 64000,
    }),
)

// Claude 4.6+ native 1M context window
llm, _ := provider.Model("anthropic--claude-4.6-sonnet",
    sapaicore.WithModelParams(map[string]any{
        "max_tokens": 200000,
    }),
)

// OpenAI reasoning effort
llm, _ := provider.Model("o4-mini",
    sapaicore.WithModelParams(map[string]any{
        "reasoning_effort": "high",
    }),
)

// Logprobs
llm, _ := provider.Model("gpt-4.1-mini",
    sapaicore.WithModelParams(map[string]any{
        "logprobs":     true,
        "top_logprobs": 3,
    }),
)

Features

Supported
Feature Orchestration Foundation Notes
Non-streaming generation
Streaming (SSE) Partial chunks + final aggregated response
Tool calling Function calls and function results
Tool calling (streaming) Deltas assembled into complete calls
Tool choice (auto/none/required) Via ToolConfig.FunctionCallingConfig
System instructions
Multi-turn conversation Full message history
Temperature / TopP / TopK
Seed (deterministic outputs) Best-effort determinism
MaxOutputTokens
StopSequences
FrequencyPenalty / PresencePenalty
Logprobs in response ResponseLogprobs + LogprobsLogprobsResult
JSON response format With schema validation
Extra model params (WithModelParams) Thinking, reasoning_effort, etc.
Server-side timeout/retries - Orchestration only
OAuth2 token caching Auto-refresh before expiry
Auto-discovery - Finds orchestration deployment automatically
Custom HTTP client
Custom headers
Resource groups
Refusal handling ErrorCode="refusal"
BeforeModelCallback (model override) req.Model respected at runtime
Multi-modal input (images) InlineData (bytes) or FileData (HTTPS URL)
File input (PDF, CSV, MP3) InlineData → data URI; model support varies
Content filtering - Azure Content Safety + Llama Guard 3 8B
Data masking (PII) - SAP DPI: anonymization/pseudonymization
Fabricated data masking - FabricatedEntity() / ConstantEntity() strategies
Mask file input - MaskFileInputMethod for file+masking
Translation - SAP Document Translation: input/output
Module fallback - Try model A, fall back to model B
Prompt caching - Anthropic cache_control on system + tools

API Reference

Provider Options
Option Description
WithEndpoint(url) SAP AI Core API base URL (required)
WithAuth(id, secret, authURL) OAuth2 credentials (required)
WithOrchestration() Orchestration mode: auto-discovers deployment (default)
WithDeploymentID(id) Orchestration mode: explicit deployment ID
WithDeployments(map) Foundation-models mode: per-model deployment IDs
WithResourceGroup(group) Resource group (default: "default")
WithHTTPClient(client) Custom *http.Client
WithHeaders(headers) Extra HTTP headers on every request
WithTimeout(seconds) Server-side LLM timeout in seconds (default: 600)
WithMaxRetries(n) Server-side retry count (default: 2)
WithFiltering(cfg) Content filtering (nil = strict defaults). Orchestration only
WithMasking(cfg) PII data masking. Orchestration only
WithTranslation(cfg) Input/output translation. Orchestration only
WithFallback(models...) Model fallback chain. Orchestration only
WithPromptCaching(ttl...) Anthropic prompt caching. Default 5m TTL. Orchestration only
WithStreamOptions(opts) Global stream chunk_size/delimiters. Orchestration only

If none of WithOrchestration, WithDeploymentID, or WithDeployments is specified, orchestration auto-discovery is used. These three options are mutually exclusive.

Model Options
Option Description
WithModelParams(map) Extra params forwarded to the model
WithModelFiltering(cfg) Override provider filtering (nil = strict defaults)
WithoutFiltering() Remove inherited filtering
WithModelMasking(cfg) Override provider masking
WithoutMasking() Remove inherited masking
WithModelTranslation(cfg) Override provider translation
WithoutTranslation() Remove inherited translation
WithModelFallback(models...) Model-level fallback chain
WithModelPromptCaching(ttl...) Enable prompt caching for this model
Errors
sapaicore.ErrMissingConfig      // required option not provided
sapaicore.ErrDeploymentNotFound // model name not in Deployments map (foundation mode only)
sapaicore.ErrDiscovery          // orchestration deployment auto-discovery failed

Credentials

From your SAP AI Core service key (BTP cockpit → Instances → Service Keys):

Option Service Key Field
WithEndpoint serviceurls.AI_API_URL
WithAuth clientID uaa.clientid
WithAuth clientSecret uaa.clientsecret
WithAuth authURL uaa.url + /oauth/token

How It Works

Orchestration mode sends all requests to SAP AI Core's harmonized API:

POST {endpoint}/v2/inference/deployments/{deploymentId}/v2/completion

The model name is embedded in the request body. SAP AI Core routes to the appropriate provider (OpenAI, Anthropic, Google, etc.).

Foundation-models mode sends requests directly to per-model deployments:

POST {endpoint}/v2/inference/deployments/{perModelId}/v1/chat/completions

Dependencies

Two direct dependencies:

  • google.golang.org/adk/v2 - ADK model interface
  • google.golang.org/genai - genai types (Content, Schema, Tool, etc.)

Development

This project uses mise for toolchain management. Run mise install to get the correct Go and tooling versions.

mise install
mise run check  # build + vet + lint + test

Or run individual tasks:

mise run build
mise run lint
mise run test
mise run fix   # auto-fix lint issues (wsl whitespace, gofmt, etc.)
Smoke Tests

Integration tests against a live SAP AI Core instance covering both API modes, streaming, tool calling, extended thinking, and full ADK agent loops.

go test -tags=smoke ./smoketest/ -v -timeout=5m

See smoketest/README.md for credentials setup and the full test catalog.

License

MIT

Documentation

Overview

Package sapaicore implements the ADK Go v2 model.LLM interface for SAP AI Core.

It bridges Google's Agent Development Kit with SAP AI Core's inference API, supporting two modes of operation:

  • Orchestration: a single deployment handles all models via the SAP AI Core harmonized API. Supports extended thinking, response format, tool calling, server-side timeout/retry, content filtering, data masking, translation, model fallback, and prompt caching.

  • Foundation-models: per-model deployment IDs with a direct OpenAI-compatible chat completions API.

Quick Start

provider, err := sapaicore.NewProvider(
    sapaicore.WithEndpoint("https://api.ai.prod.us-east-1.aws.ml.hana.ondemand.com"),
    sapaicore.WithAuth(clientID, clientSecret, authURL),
    sapaicore.WithOrchestration(), // auto-discovers deployment
)
if err != nil {
    log.Fatal(err)
}

llm, err := provider.Model("gpt-4.1")

Both streaming and non-streaming generation are supported via the standard ADK model.LLM interface.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrMissingConfig      = errors.New("sapaicore: missing required configuration")
	ErrDeploymentNotFound = errors.New("sapaicore: deployment not found for model")
	ErrDiscovery          = errors.New("sapaicore: orchestration deployment discovery")
)

CommonPIIEntities covers the most frequently masked PII types: person names, organizations, email, phone, and addresses.

Functions

This section is empty.

Types

type AzureContentSafetyConfig added in v0.3.0

type AzureContentSafetyConfig struct {
	Hate     AzureThreshold
	SelfHarm AzureThreshold
	Sexual   AzureThreshold
	Violence AzureThreshold

	// PromptShield enables jailbreak/prompt-injection detection (input only).
	PromptShield bool
}

type AzureThreshold added in v0.3.0

type AzureThreshold int

AzureThreshold controls Azure Content Safety sensitivity. Values map to SAP AI Core API thresholds (0/2/4/6): lower = stricter.

const (
	AzureThresholdAllowSafe          AzureThreshold = 0
	AzureThresholdAllowSafeLow       AzureThreshold = 2
	AzureThresholdAllowSafeLowMedium AzureThreshold = 4
	AzureThresholdAllowAll           AzureThreshold = 6
)

type CacheTTL added in v0.3.0

type CacheTTL string

CacheTTL controls the time-to-live for prompt cache entries.

const (
	CacheTTL5m CacheTTL = "5m"
	CacheTTL1h CacheTTL = "1h" // Only supported on select Anthropic models.
)

type CustomEntity added in v0.3.0

type CustomEntity struct {
	Regex       string
	Replacement string
}

type DPIEntity added in v0.3.0

type DPIEntity string
const (
	EntityPerson            DPIEntity = "profile-person"
	EntityOrg               DPIEntity = "profile-org"
	EntityUniversity        DPIEntity = "profile-university"
	EntityLocation          DPIEntity = "profile-location"
	EntityEmail             DPIEntity = "profile-email"
	EntityPhone             DPIEntity = "profile-phone"
	EntityAddress           DPIEntity = "profile-address"
	EntitySAPIDsInternal    DPIEntity = "profile-sapids-internal"
	EntitySAPIDsPublic      DPIEntity = "profile-sapids-public"
	EntityURL               DPIEntity = "profile-url"
	EntityUsernamePassword  DPIEntity = "profile-username-password"
	EntityNationalID        DPIEntity = "profile-nationalid"
	EntityIBAN              DPIEntity = "profile-iban"
	EntitySSN               DPIEntity = "profile-ssn"
	EntityCreditCard        DPIEntity = "profile-credit-card-number"
	EntityPassport          DPIEntity = "profile-passport"
	EntityDriverLicense     DPIEntity = "profile-driverlicense"
	EntityNationality       DPIEntity = "profile-nationality"
	EntityReligiousGroup    DPIEntity = "profile-religious-group"
	EntityPoliticalGroup    DPIEntity = "profile-political-group"
	EntityPronounsGender    DPIEntity = "profile-pronouns-gender"
	EntityEthnicity         DPIEntity = "profile-ethnicity"
	EntityGender            DPIEntity = "profile-gender"
	EntitySexualOrientation DPIEntity = "profile-sexual-orientation"
	EntityTradeUnion        DPIEntity = "profile-trade-union"
	EntitySensitiveData     DPIEntity = "profile-sensitive-data"
)

type FilteringConfig added in v0.3.0

type FilteringConfig struct {
	Input  *InputFilterConfig
	Output *OutputFilterConfig
}

FilteringConfig configures content filtering. Orchestration-mode only.

type InputFilterConfig added in v0.3.0

type InputFilterConfig struct {
	AzureContentSafety *AzureContentSafetyConfig
	LlamaGuard         *LlamaGuardConfig
}

type LlamaGuardConfig added in v0.3.0

type LlamaGuardConfig struct {
	ViolentCrimes         bool
	NonViolentCrimes      bool
	SexCrimes             bool
	ChildExploitation     bool
	Defamation            bool
	SpecializedAdvice     bool
	Privacy               bool
	IntellectualProperty  bool
	IndiscriminateWeapons bool
	Hate                  bool
	SelfHarm              bool
	SexualContent         bool
	Elections             bool
	CodeInterpreterAbuse  bool
}

LlamaGuardConfig enables Llama Guard 3 8B categories.

type MaskFileInputMethod added in v0.4.0

type MaskFileInputMethod string

MaskFileInputMethod controls how file inputs interact with masking. Required when file parts are present and masking is configured.

const (
	MaskFileAnonymization MaskFileInputMethod = "anonymization"
	MaskFileSkip          MaskFileInputMethod = "skip"
)

type MaskingConfig added in v0.3.0

type MaskingConfig struct {
	// Method defaults to [Anonymization] if empty.
	Method MaskingMethod

	// Entities to mask. Use [StandardEntities]([CommonPIIEntities]) for quick setup.
	Entities []MaskingEntity

	// Allowlist contains strings that should never be masked even if they match.
	Allowlist []string

	// MaskGroundingInput controls whether grounding module input is also masked.
	MaskGroundingInput bool

	// MaskFileInputMethod controls how file inputs are handled by masking.
	// Required when file content blocks are present in the request.
	MaskFileInputMethod MaskFileInputMethod
}

MaskingConfig configures data masking. Orchestration-mode only.

type MaskingEntity added in v0.3.0

type MaskingEntity struct {
	// contains filtered or unexported fields
}

MaskingEntity is either a standard DPIEntity or a CustomEntity.

func ConstantEntity added in v0.4.0

func ConstantEntity(entity DPIEntity, replacement string) MaskingEntity

ConstantEntity replaces matches with a fixed value followed by an incrementing number.

func CustomMaskingEntity added in v0.3.0

func CustomMaskingEntity(regex, replacement string) MaskingEntity

func FabricatedEntity added in v0.4.0

func FabricatedEntity(entity DPIEntity) MaskingEntity

FabricatedEntity replaces matches with realistic fake data appropriate to the entity type.

func StandardEntities added in v0.3.0

func StandardEntities(entities []DPIEntity) []MaskingEntity

func StandardEntity added in v0.3.0

func StandardEntity(entity DPIEntity) MaskingEntity

type MaskingMethod added in v0.3.0

type MaskingMethod string
const (
	Anonymization    MaskingMethod = "anonymization"
	Pseudonymization MaskingMethod = "pseudonymization"
)

type ModelOption

type ModelOption func(*modelConfig)

ModelOption configures a specific model instance returned by Provider.Model.

func WithModelFallback added in v0.3.0

func WithModelFallback(models ...string) ModelOption

func WithModelFiltering added in v0.3.0

func WithModelFiltering(cfg *FilteringConfig) ModelOption

WithModelFiltering overrides provider-level filtering for this model. Pass nil for the same defaults as WithFiltering.

func WithModelMasking added in v0.3.0

func WithModelMasking(cfg MaskingConfig) ModelOption

WithModelMasking overrides provider-level masking for this model.

func WithModelParams

func WithModelParams(params map[string]any) ModelOption

WithModelParams adds extra parameters forwarded directly to the model. In orchestration mode these go into model.params (e.g. thinking, reasoning_effort). In foundation-models mode these are merged into the top-level request body.

If a key conflicts with a field set via [genai.GenerateContentConfig] (e.g. "seed", "top_k", "logprobs"), the WithModelParams value takes precedence. This allows overriding any first-class parameter when needed.

Example
package main

import (
	"context"
	"fmt"
	"log"

	sapaicore "github.com/PedroKlein/adk-provider-sapaicore"
)

func main() {
	provider, err := sapaicore.NewProvider(context.Background(),
		sapaicore.WithEndpoint("https://api.ai.prod.us-east-1.aws.ml.hana.ondemand.com"),
		sapaicore.WithAuth("client-id", "client-secret", "https://auth.example.com/oauth/token"),
		sapaicore.WithDeploymentID("d1234abc"),
	)
	if err != nil {
		log.Fatal(err)
	}

	// Enable extended thinking for Claude models.
	llm, err := provider.Model("anthropic--claude-4.5-sonnet",
		sapaicore.WithModelParams(map[string]any{
			"thinking":   map[string]any{"type": "enabled", "budget_tokens": 16384},
			"max_tokens": 64000,
		}),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(llm.Name())
}
Output:
anthropic--claude-4.5-sonnet

func WithModelPromptCaching added in v0.3.0

func WithModelPromptCaching(ttl ...CacheTTL) ModelOption

func WithModelTranslation added in v0.3.0

func WithModelTranslation(cfg TranslationConfig) ModelOption

WithModelTranslation overrides provider-level translation for this model.

func WithoutFiltering added in v0.3.0

func WithoutFiltering() ModelOption

func WithoutMasking added in v0.3.0

func WithoutMasking() ModelOption

func WithoutTranslation added in v0.3.0

func WithoutTranslation() ModelOption

type Option

type Option func(*providerConfig)

Option configures a Provider.

func WithAuth

func WithAuth(clientID, clientSecret, authURL string) Option

WithAuth sets the OAuth2 client credentials. authURL is the token endpoint, e.g. "https://xxx.authentication.xxx.hana.ondemand.com/oauth/token".

func WithDeploymentID

func WithDeploymentID(id string) Option

WithDeploymentID enables orchestration mode using a specific deployment ID.

func WithDeployments

func WithDeployments(deployments map[string]string) Option

WithDeployments enables foundation-models mode with per-model deployment IDs.

func WithEndpoint

func WithEndpoint(endpoint string) Option

func WithFallback added in v0.3.0

func WithFallback(models ...string) Option

WithFallback configures model fallback. The service tries the primary model first, then each fallback in order. Fallback models inherit all module configs. Orchestration-mode only.

func WithFiltering added in v0.3.0

func WithFiltering(cfg *FilteringConfig) Option

WithFiltering enables content filtering. Orchestration-mode only.

Pass nil for sensible defaults: Azure Content Safety ALLOW_SAFE on all categories with prompt_shield, applied to both input and output.

func WithHTTPClient

func WithHTTPClient(client *http.Client) Option

func WithHeaders

func WithHeaders(headers http.Header) Option

func WithMasking added in v0.3.0

func WithMasking(cfg MaskingConfig) Option

WithMasking enables PII redaction before messages reach the LLM. Orchestration-mode only. Method defaults to Anonymization if empty.

func WithMaxRetries

func WithMaxRetries(n int) Option

WithMaxRetries sets the server-side retry count for LLM requests. Default is 2 retries.

func WithOrchestration

func WithOrchestration() Option

WithOrchestration enables orchestration mode by automatically discovering the orchestration deployment. It queries the SAP AI Core deployments API at provider creation time to find the running orchestration deployment.

func WithPromptCaching added in v0.3.0

func WithPromptCaching(ttl ...CacheTTL) Option

WithPromptCaching adds cache_control annotations to the system message and tool definitions. Orchestration-mode only. Non-Anthropic models ignore the annotation. Default TTL is 5m. Pass CacheTTL1h for 1-hour caching on supported models.

func WithResourceGroup

func WithResourceGroup(group string) Option
Example
package main

import (
	"context"
	"fmt"
	"log"

	sapaicore "github.com/PedroKlein/adk-provider-sapaicore"
)

func main() {
	provider, err := sapaicore.NewProvider(context.Background(),
		sapaicore.WithEndpoint("https://api.ai.prod.us-east-1.aws.ml.hana.ondemand.com"),
		sapaicore.WithAuth("client-id", "client-secret", "https://auth.example.com/oauth/token"),
		sapaicore.WithDeploymentID("d1234abc"),
		sapaicore.WithResourceGroup("my-team-rg"),
	)
	if err != nil {
		log.Fatal(err)
	}

	llm, err := provider.Model("gpt-4.1")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(llm.Name())
}
Output:
gpt-4.1

func WithStreamOptions added in v0.3.0

func WithStreamOptions(opts StreamOptions) Option

func WithTimeout

func WithTimeout(seconds int) Option

WithTimeout sets the server-side LLM request timeout in seconds. Default is 600 seconds.

func WithTranslation added in v0.3.0

func WithTranslation(cfg TranslationConfig) Option

WithTranslation enables input/output translation. Orchestration-mode only.

type OutputFilterConfig added in v0.3.0

type OutputFilterConfig struct {
	AzureContentSafety *AzureContentSafetyConfig
	LlamaGuard         *LlamaGuardConfig

	// Overlap sets the number of characters from previous chunks sent as additional
	// context to the filtering service during streaming. Only relevant when streaming.
	Overlap int
}

type Provider

type Provider struct {
	// contains filtered or unexported fields
}

Provider creates model.LLM instances backed by SAP AI Core deployments.

func NewProvider

func NewProvider(ctx context.Context, opts ...Option) (*Provider, error)

NewProvider validates the given options and returns a ready-to-use Provider. It returns ErrMissingConfig if required options are absent.

If no mode is specified, orchestration auto-discovery is used by default. NewProvider makes an HTTP call to discover the orchestration deployment ID when auto-discovery is active.

ctx is used for any HTTP calls made during provider initialization (e.g. orchestration deployment discovery). It does not affect subsequent Model() or GenerateContent() calls.

Example (FoundationModels)
package main

import (
	"context"
	"fmt"
	"log"

	sapaicore "github.com/PedroKlein/adk-provider-sapaicore"
)

func main() {
	provider, err := sapaicore.NewProvider(context.Background(),
		sapaicore.WithEndpoint("https://api.ai.prod.us-east-1.aws.ml.hana.ondemand.com"),
		sapaicore.WithAuth("client-id", "client-secret", "https://auth.example.com/oauth/token"),
		sapaicore.WithDeployments(map[string]string{
			"gpt-4.1":      "d1234abc",
			"gpt-4.1-mini": "d5678def",
		}),
	)
	if err != nil {
		log.Fatal(err)
	}

	llm, err := provider.Model("gpt-4.1")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(llm.Name())
}
Output:
gpt-4.1
Example (Orchestration)
package main

import (
	"context"
	"fmt"
	"log"

	sapaicore "github.com/PedroKlein/adk-provider-sapaicore"
)

func main() {
	provider, err := sapaicore.NewProvider(context.Background(),
		sapaicore.WithEndpoint("https://api.ai.prod.us-east-1.aws.ml.hana.ondemand.com"),
		sapaicore.WithAuth("client-id", "client-secret", "https://auth.example.com/oauth/token"),
		sapaicore.WithDeploymentID("d1234abc"), // or use WithOrchestration() for auto-discovery
	)
	if err != nil {
		log.Fatal(err)
	}

	llm, err := provider.Model("gpt-4.1")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(llm.Name())
}
Output:
gpt-4.1

func (*Provider) Model

func (p *Provider) Model(name string, opts ...ModelOption) (model.LLM, error)

Model returns a model.LLM for the given model name.

In orchestration mode, name is any SAP AI Core model identifier (e.g. "gpt-4.1", "anthropic--claude-4.5-sonnet").

In foundation-models mode, name must exist in the map provided to WithDeployments. Returns ErrDeploymentNotFound if the name is not registered.

type StreamOptions added in v0.3.0

type StreamOptions struct {
	// ChunkSize is the minimum characters per chunk that post-LLM modules operate on.
	ChunkSize int
	// Delimiters to split text into chunks. Required when translation is active with streaming.
	Delimiters []string
}

StreamOptions configures global streaming behavior for orchestration modules.

type TranslationConfig added in v0.3.0

type TranslationConfig struct {
	Input  *TranslationInputConfig
	Output *TranslationOutputConfig
}

TranslationConfig configures translation. Orchestration-mode only. At least one of Input or Output must be set.

type TranslationInputConfig added in v0.3.0

type TranslationInputConfig struct {
	// SourceLanguage (e.g. "de-DE"). Empty means auto-detect.
	SourceLanguage string
	// TargetLanguage (e.g. "en-US"). Required.
	TargetLanguage string
}

type TranslationOutputConfig added in v0.3.0

type TranslationOutputConfig struct {
	// SourceLanguage of the LLM output. Empty means auto-detect.
	SourceLanguage string
	// TargetLanguage for the translated output (e.g. "fr-FR"). Required.
	TargetLanguage string
}

Directories

Path Synopsis
internal
auth
Package auth manages OAuth2 client-credentials tokens with thread-safe caching.
Package auth manages OAuth2 client-credentials tokens with thread-safe caching.
convert
Package convert transforms between Google genai types and OpenAI-compatible wire types.
Package convert transforms between Google genai types and OpenAI-compatible wire types.
foundation
Package foundation implements the SAP AI Core foundation-models mode strategy.
Package foundation implements the SAP AI Core foundation-models mode strategy.
openai
Package openai defines wire types for the OpenAI-compatible chat completions format used by both SAP AI Core API modes.
Package openai defines wire types for the OpenAI-compatible chat completions format used by both SAP AI Core API modes.
orchestration
Package orchestration implements the SAP AI Core orchestration mode strategy.
Package orchestration implements the SAP AI Core orchestration mode strategy.
request
Package request provides shared HTTP execution for SAP AI Core inference requests.
Package request provides shared HTTP execution for SAP AI Core inference requests.
stream
Package stream handles Server-Sent Events parsing and incremental aggregation of streaming chat completion responses.
Package stream handles Server-Sent Events parsing and incremental aggregation of streaming chat completion responses.
Package smoketest provides integration tests against a live SAP AI Core instance.
Package smoketest provides integration tests against a live SAP AI Core instance.

Jump to

Keyboard shortcuts

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