This guide explains all the configuration options available in the go-tabbyapi client library. Understanding these options will help you optimize the client for your specific use case.
The tabby.NewClient() function accepts multiple configuration options using the functional options pattern:
client := tabby.NewClient(
tabby.WithBaseURL("http://localhost:8080"),
tabby.WithAPIKey("your-api-key"),
tabby.WithTimeout(30*time.Second),
// Add more options as needed
)Let's explore each configuration option in detail:
Sets the base URL for the TabbyAPI server:
tabby.WithBaseURL("http://localhost:8080")- Default:
"http://localhost:8080" - Purpose: Specifies the endpoint where the TabbyAPI server is running
- Format: Should include protocol (http/https) and host, with optional port
- Examples:
- Local server:
"http://localhost:8080" - Remote server:
"https://tabby-api.example.com" - Custom port:
"http://localhost:9000"
- Local server:
Note: Do not include API version or endpoint paths in the base URL. The library automatically appends them.
Sets the timeout duration for all API requests:
tabby.WithTimeout(30*time.Second)- Default:
30*time.Second - Purpose: Controls how long to wait for API responses before timing out
- Considerations:
- Set shorter timeouts for quick operations like health checks
- Set longer timeouts for model loading or large generation requests
- For streaming operations, this timeout applies to establishing the connection, not the entire stream duration
Example with different timeouts:
// Quick operations
quickClient := tabby.NewClient(
tabby.WithBaseURL("http://localhost:8080"),
tabby.WithTimeout(5*time.Second),
)
// Long-running operations
longRunningClient := tabby.NewClient(
tabby.WithBaseURL("http://localhost:8080"),
tabby.WithTimeout(2*time.Minute),
)Provides a custom HTTP client for making API requests:
customClient := &http.Client{
// Custom configuration
}
tabby.WithHTTPClient(customClient)- Default: Standard HTTP client with 30-second timeout
- Purpose: Allows advanced HTTP configuration such as:
- Custom transport settings
- Connection pooling
- Proxy configuration
- TLS settings
- Custom redirect policy
Example with advanced configuration:
transport := &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: 90 * time.Second,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
},
DisableCompression: false,
Proxy: http.ProxyFromEnvironment,
}
customClient := &http.Client{
Transport: transport,
Timeout: 60 * time.Second,
}
client := tabby.NewClient(
tabby.WithBaseURL("http://localhost:8080"),
tabby.WithHTTPClient(customClient),
)Sets the API key for standard authentication:
tabby.WithAPIKey("your-api-key")- Default: No authentication
- Purpose: Authenticates requests using the X-API-Key header
- Permissions: Typically provides read and write permissions but not administrative access
- Usage: Standard choice for most applications
Sets the admin key for administrative operations:
tabby.WithAdminKey("your-admin-key")- Default: No authentication
- Purpose: Authenticates requests using the X-Admin-Key header
- Permissions: Provides full administrative access, including model management
- Usage: Use only when administrative operations are required
Sets a bearer token for OAuth or JWT authentication:
tabby.WithBearerToken("your-bearer-token")- Default: No authentication
- Purpose: Authenticates requests using the Authorization header with Bearer scheme
- Permissions: Depends on the token's claims and server configuration
- Usage: Useful when integrating with OAuth/JWT systems
Note: Only use one authentication method at a time. If multiple are provided, the last one specified will take precedence.
Sets the retry policy for failed requests:
tabby.WithRetryPolicy(tabby.DefaultRetryPolicy())- Default: No retry policy
- Purpose: Automatically retries failed requests based on configurable conditions
- Implementation: Uses the
RetryPolicyinterface with these methods:ShouldRetry(resp *http.Response, err error) bool: Determines if a request should be retriedRetryDelay(attempts int) time.Duration: Returns the delay before the next retryMaxRetries() int: Returns the maximum number of retry attempts
The library provides a default retry policy that can be used:
tabby.WithRetryPolicy(tabby.DefaultRetryPolicy())The default policy provides:
- Maximum of 3 retry attempts
- Exponential backoff with jitter:
- 1st retry: ~100ms
- 2nd retry: ~1.2s
- 3rd retry: ~2.3s
- Retries on:
- Any network or connection error
- Any HTTP status code >= 500 (server errors)
For more control, you can create a custom retry policy:
customPolicy := &tabby.SimpleRetryPolicy{
MaxRetryCount: 5, // Try up to 5 times
// Exponential backoff with jitter
RetryDelayFunc: func(attempts int) time.Duration {
baseDelay := time.Duration(1<<uint(attempts-1)) * time.Second // 1s, 2s, 4s, 8s, 16s
jitter := time.Duration(rand.Int63n(int64(500 * time.Millisecond)))
return baseDelay + jitter
},
// Retry conditions
RetryableFunc: func(resp *http.Response, err error) bool {
// Retry on network errors
if err != nil {
return true
}
// Retry on server errors (5xx) and rate limiting (429)
statusCode := resp.StatusCode
return statusCode >= 500 || statusCode == 429
},
}
client := tabby.NewClient(
tabby.WithBaseURL("http://localhost:8080"),
tabby.WithAPIKey("your-api-key"),
tabby.WithRetryPolicy(customPolicy),
)Here's a comprehensive example showing all configuration options together:
package main
import (
"crypto/tls"
"math/rand"
"net"
"net/http"
"time"
"github.com/pixelsquared/go-tabbyapi/tabby"
)
func main() {
// Seed the random number generator (for jitter in retry policy)
rand.Seed(time.Now().UnixNano())
// Create a custom transport
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
},
}
// Create a custom HTTP client
httpClient := &http.Client{
Transport: transport,
Timeout: 60 * time.Second,
}
// Create a custom retry policy
retryPolicy := &tabby.SimpleRetryPolicy{
MaxRetryCount: 5,
RetryDelayFunc: func(attempts int) time.Duration {
baseDelay := time.Duration(1<<uint(attempts-1)) * time.Second
jitter := time.Duration(rand.Int63n(int64(500 * time.Millisecond)))
return baseDelay + jitter
},
RetryableFunc: func(resp *http.Response, err error) bool {
if err != nil {
return true
}
statusCode := resp.StatusCode
return statusCode >= 500 || statusCode == 429
},
}
// Create the TabbyAPI client with all configuration options
client := tabby.NewClient(
// Core options
tabby.WithBaseURL("https://tabby-api.example.com"),
tabby.WithHTTPClient(httpClient),
// Authentication option (choose one)
tabby.WithAPIKey("your-api-key"),
// OR tabby.WithAdminKey("your-admin-key"),
// OR tabby.WithBearerToken("your-bearer-token"),
// Retry policy
tabby.WithRetryPolicy(retryPolicy),
)
defer client.Close()
// Use the client to interact with TabbyAPI
// ...
}Once configured, the client provides access to all TabbyAPI services:
// Create the client
client := tabby.NewClient(/* options */)
// Access services
completions := client.Completions() // CompletionsService
chat := client.Chat() // ChatService
models := client.Models() // ModelsService
embeddings := client.Embeddings() // EmbeddingsService
lora := client.Lora() // LoraService
templates := client.Templates() // TemplatesService
tokens := client.Tokens() // TokensService
sampling := client.Sampling() // SamplingService
health := client.Health() // HealthService
auth := client.Auth() // AuthService- Set appropriate timeouts based on operation type:
- Health checks: 5-10 seconds
- Text generation: 30-60 seconds
- Model loading: 2-5 minutes
- Embedding generation: 10-30 seconds
// Different clients for different operation types
healthClient := tabby.NewClient(
tabby.WithBaseURL(baseURL),
tabby.WithAPIKey(apiKey),
tabby.WithTimeout(5*time.Second),
)
generationClient := tabby.NewClient(
tabby.WithBaseURL(baseURL),
tabby.WithAPIKey(apiKey),
tabby.WithTimeout(60*time.Second),
)
adminClient := tabby.NewClient(
tabby.WithBaseURL(baseURL),
tabby.WithAdminKey(adminKey),
tabby.WithTimeout(5*time.Minute),
)- Use the least privileged authentication required for your operations:
- Regular operations (completions, chat, embeddings): Use API key
- Administrative operations (model management): Use admin key
- Never mix admin and non-admin operations in the same client instance
// Client for standard operations
standardClient := tabby.NewClient(
tabby.WithBaseURL(baseURL),
tabby.WithAPIKey(apiKey),
)
// Separate client for admin operations
adminClient := tabby.NewClient(
tabby.WithBaseURL(baseURL),
tabby.WithAdminKey(adminKey),
)-
Use retries for transient errors only:
- Network issues
- Server errors (5xx)
- Rate limiting (429)
- Do not retry client errors (4xx) except for rate limiting
-
Implement exponential backoff to avoid overwhelming the server:
baseDelay := time.Duration(1<<uint(attempts-1)) * time.Second // 1s, 2s, 4s, 8s...
-
Add jitter to prevent retry storms:
jitter := time.Duration(rand.Int63n(int64(500 * time.Millisecond))) delay := baseDelay + jitter
-
Increase MaxIdleConnsPerHost for high-throughput applications:
transport.MaxIdleConnsPerHost = 100
-
Set reasonable connection timeouts:
transport.IdleConnTimeout = 90 * time.Second
-
Enable HTTP/2 for better performance:
transport.ForceAttemptHTTP2 = true
client := tabby.NewClient(
tabby.WithBaseURL(os.Getenv("TABBY_API_URL")),
tabby.WithAPIKey(os.Getenv("TABBY_API_KEY")),
tabby.WithTimeout(60*time.Second),
tabby.WithRetryPolicy(tabby.DefaultRetryPolicy()),
)client := tabby.NewClient(
tabby.WithBaseURL("http://localhost:8080"),
// Often no authentication needed in development
tabby.WithTimeout(30*time.Second),
// No retry policy for faster debugging
)// Create a test server
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Mock responses here
}))
defer testServer.Close()
// Configure client to use test server
client := tabby.NewClient(
tabby.WithBaseURL(testServer.URL),
tabby.WithTimeout(5*time.Second),
)For different operation types, consider creating specialized clients:
type TabbyClients struct {
Standard *tabby.Client // For regular operations
Admin *tabby.Client // For admin operations
Streaming *tabby.Client // For streaming operations with longer timeouts
}
func NewTabbyClients(config Config) *TabbyClients {
standard := tabby.NewClient(
tabby.WithBaseURL(config.BaseURL),
tabby.WithAPIKey(config.APIKey),
tabby.WithTimeout(30*time.Second),
tabby.WithRetryPolicy(tabby.DefaultRetryPolicy()),
)
admin := tabby.NewClient(
tabby.WithBaseURL(config.BaseURL),
tabby.WithAdminKey(config.AdminKey),
tabby.WithTimeout(2*time.Minute),
tabby.WithRetryPolicy(createAdminRetryPolicy()),
)
streaming := tabby.NewClient(
tabby.WithBaseURL(config.BaseURL),
tabby.WithAPIKey(config.APIKey),
tabby.WithTimeout(5*time.Minute),
// No retry policy for streaming
)
return &TabbyClients{
Standard: standard,
Admin: admin,
Streaming: streaming,
}
}
// Remember to close all clients
func (c *TabbyClients) Close() {
c.Standard.Close()
c.Admin.Close()
c.Streaming.Close()
}Properly configuring your TabbyAPI client can significantly impact the performance, reliability, and security of your application. Choose configuration options that match your specific requirements, and remember to always close your client when you're done using it to release resources.
For more detailed information about using the configured client, refer to the other documentation pages: