fix: propagate LLM timeout to AI Core client
CI / test (pull_request) Successful in 15s
CI / review (/anthropic/v1, anthropic--claude-4.6-sonnet, sonnet, anthropic, SONNET_REVIEW_TOKEN) (pull_request) Successful in 32s
CI / review (/openai/v1, gpt-5, security, openai, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m58s
CI / review (/openai/v1, gpt-5, gpt, openai, GPT_REVIEW_TOKEN) (pull_request) Successful in 2m16s
CI / test (pull_request) Successful in 15s
CI / review (/anthropic/v1, anthropic--claude-4.6-sonnet, sonnet, anthropic, SONNET_REVIEW_TOKEN) (pull_request) Successful in 32s
CI / review (/openai/v1, gpt-5, security, openai, SECURITY_REVIEW.md, SECURITY_REVIEW_TOKEN) (pull_request) Successful in 1m58s
CI / review (/openai/v1, gpt-5, gpt, openai, GPT_REVIEW_TOKEN) (pull_request) Successful in 2m16s
Address review feedback: MAJOR: - AICoreClient now defaults to 5min timeout (matching Client) - Add AICoreClient.WithTimeout() for explicit timeout control - Client.WithAICore() inherits parent client's timeout - Client.WithTimeout() propagates to aicore client if set MINOR: - Extract AICoreOpenAIAPIVersion constant for the hardcoded api-version - Tighten IsAnthropicModel to only match 'anthropic--' prefix (SAP AI Core always uses this prefix for Anthropic models) NIT: - Use fmt.Sprintf for token generation in tests (robust for >9 calls) - Add error checking in TestAICoreClient_TokenExpiry - Add tests for WithTimeout propagation
This commit is contained in:
+21
-9
@@ -13,6 +13,10 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// AICoreOpenAIAPIVersion is the API version used for OpenAI models through AI Core.
|
||||
// Update this when SAP AI Core releases a new stable version.
|
||||
const AICoreOpenAIAPIVersion = "2024-12-01-preview"
|
||||
|
||||
// AICoreConfig holds SAP AI Core authentication and connection settings.
|
||||
type AICoreConfig struct {
|
||||
ClientID string
|
||||
@@ -40,14 +44,22 @@ type deployment struct {
|
||||
}
|
||||
|
||||
// NewAICoreClient creates a new AI Core client with the given configuration.
|
||||
// The client uses a default 5-minute timeout; use WithTimeout to customize.
|
||||
func NewAICoreClient(cfg AICoreConfig) *AICoreClient {
|
||||
return &AICoreClient{
|
||||
config: cfg,
|
||||
http: &http.Client{Timeout: 30 * time.Second},
|
||||
http: &http.Client{Timeout: 5 * time.Minute},
|
||||
deployments: make(map[string]deployment),
|
||||
}
|
||||
}
|
||||
|
||||
// WithTimeout sets the HTTP request timeout for AI Core calls.
|
||||
// This should be called during construction, before concurrent use.
|
||||
func (c *AICoreClient) WithTimeout(d time.Duration) *AICoreClient {
|
||||
c.http.Timeout = d
|
||||
return c
|
||||
}
|
||||
|
||||
// getToken returns a valid OAuth token, refreshing if necessary.
|
||||
func (c *AICoreClient) getToken(ctx context.Context) (string, error) {
|
||||
c.mu.RLock()
|
||||
@@ -154,7 +166,6 @@ func (c *AICoreClient) getDeploymentURL(ctx context.Context, model string) (stri
|
||||
}
|
||||
|
||||
func (c *AICoreClient) fetchDeployments(ctx context.Context, token string) error {
|
||||
|
||||
deployURL := strings.TrimRight(c.config.APIURL, "/") + "/v2/lm/deployments"
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, deployURL, nil)
|
||||
if err != nil {
|
||||
@@ -180,10 +191,10 @@ func (c *AICoreClient) fetchDeployments(ctx context.Context, token string) error
|
||||
|
||||
var deployResp struct {
|
||||
Resources []struct {
|
||||
ID string `json:"id"`
|
||||
DeploymentURL string `json:"deploymentUrl"`
|
||||
Status string `json:"status"`
|
||||
Details struct {
|
||||
ID string `json:"id"`
|
||||
DeploymentURL string `json:"deploymentUrl"`
|
||||
Status string `json:"status"`
|
||||
Details struct {
|
||||
Resources struct {
|
||||
BackendDetails struct {
|
||||
Model struct {
|
||||
@@ -326,8 +337,8 @@ func (c *AICoreClient) CompleteOpenAI(ctx context.Context, model string, message
|
||||
return "", fmt.Errorf("marshal request: %w", err)
|
||||
}
|
||||
|
||||
// AI Core uses /chat/completions?api-version=2024-12-01-preview for OpenAI models
|
||||
chatURL := strings.TrimRight(deployURL, "/") + "/chat/completions?api-version=2024-12-01-preview"
|
||||
// AI Core uses /chat/completions?api-version=<version> for OpenAI models
|
||||
chatURL := strings.TrimRight(deployURL, "/") + "/chat/completions?api-version=" + AICoreOpenAIAPIVersion
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, chatURL, bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("create request: %w", err)
|
||||
@@ -363,6 +374,7 @@ func (c *AICoreClient) CompleteOpenAI(ctx context.Context, model string, message
|
||||
}
|
||||
|
||||
// IsAnthropicModel returns true if the model name indicates an Anthropic model.
|
||||
// SAP AI Core uses "anthropic--" prefix for Anthropic models (e.g., "anthropic--claude-3-5-sonnet").
|
||||
func IsAnthropicModel(model string) bool {
|
||||
return strings.HasPrefix(model, "anthropic--") || strings.Contains(model, "claude")
|
||||
return strings.HasPrefix(model, "anthropic--")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user