// Package synor provides a Go SDK for Synor Compute. // // Access distributed heterogeneous compute resources (CPU, GPU, TPU, NPU, LPU) // for AI/ML workloads at 90% cost reduction compared to traditional cloud. // // Example: // // client := synor.NewClient("your-api-key") // result, err := client.MatMul(ctx, a, b, synor.FP16) package synor import ( "bytes" "context" "encoding/base64" "encoding/json" "fmt" "io" "net/http" "time" ) // Version of the SDK. const Version = "0.1.0" // DefaultEndpoint is the default API endpoint. const DefaultEndpoint = "https://compute.synor.cc/api/v1" // ProcessorType represents supported processor types. type ProcessorType string const ( CPU ProcessorType = "cpu" GPU ProcessorType = "gpu" TPU ProcessorType = "tpu" NPU ProcessorType = "npu" LPU ProcessorType = "lpu" FPGA ProcessorType = "fpga" WASM ProcessorType = "wasm" WebGPU ProcessorType = "webgpu" ) // Precision represents computation precision levels. type Precision string const ( FP64 Precision = "fp64" FP32 Precision = "fp32" FP16 Precision = "fp16" BF16 Precision = "bf16" INT8 Precision = "int8" INT4 Precision = "int4" ) // BalancingStrategy represents job scheduling strategies. type BalancingStrategy string const ( Speed BalancingStrategy = "speed" Cost BalancingStrategy = "cost" Energy BalancingStrategy = "energy" Latency BalancingStrategy = "latency" Balanced BalancingStrategy = "balanced" ) // JobStatus represents job states. type JobStatus string const ( Pending JobStatus = "pending" Queued JobStatus = "queued" Running JobStatus = "running" Completed JobStatus = "completed" Failed JobStatus = "failed" Cancelled JobStatus = "cancelled" ) // Config holds client configuration. type Config struct { APIKey string Endpoint string Strategy BalancingStrategy Precision Precision Timeout time.Duration Debug bool } // DefaultConfig returns a default configuration. func DefaultConfig(apiKey string) Config { return Config{ APIKey: apiKey, Endpoint: DefaultEndpoint, Strategy: Balanced, Precision: FP32, Timeout: 30 * time.Second, Debug: false, } } // Client is the main Synor Compute client. type Client struct { config Config httpClient *http.Client } // NewClient creates a new client with the given API key. func NewClient(apiKey string) *Client { return NewClientWithConfig(DefaultConfig(apiKey)) } // NewClientWithConfig creates a new client with custom configuration. func NewClientWithConfig(config Config) *Client { return &Client{ config: config, httpClient: &http.Client{ Timeout: config.Timeout, }, } } // JobResult represents the result of a job. type JobResult struct { JobID string `json:"job_id"` Status JobStatus `json:"status"` Data interface{} `json:"data,omitempty"` Error string `json:"error,omitempty"` Metrics *JobMetrics `json:"metrics,omitempty"` } // JobMetrics contains execution metrics. type JobMetrics struct { ExecutionTimeMs float64 `json:"execution_time_ms"` QueueTimeMs float64 `json:"queue_time_ms"` ProcessorType ProcessorType `json:"processor_type"` ProcessorID string `json:"processor_id"` FLOPS float64 `json:"flops"` MemoryBytes int64 `json:"memory_bytes"` CostMicro int64 `json:"cost_micro"` EnergyMJ float64 `json:"energy_mj"` } // Tensor represents a multi-dimensional array. type Tensor struct { Data []float32 `json:"data"` Shape []int `json:"shape"` DType Precision `json:"dtype"` } // NewTensor creates a new tensor from data and shape. func NewTensor(data []float32, shape []int, dtype Precision) *Tensor { return &Tensor{ Data: data, Shape: shape, DType: dtype, } } // Zeros creates a tensor of zeros. func Zeros(shape []int, dtype Precision) *Tensor { size := 1 for _, dim := range shape { size *= dim } return &Tensor{ Data: make([]float32, size), Shape: shape, DType: dtype, } } // Serialize converts tensor to transmission format. func (t *Tensor) Serialize() map[string]interface{} { buf := new(bytes.Buffer) for _, v := range t.Data { var b [4]byte *(*float32)((&b[0])) = v buf.Write(b[:]) } return map[string]interface{}{ "data": base64.StdEncoding.EncodeToString(buf.Bytes()), "shape": t.Shape, "dtype": t.DType, } } // MatMul performs matrix multiplication. func (c *Client) MatMul(ctx context.Context, a, b *Tensor, precision Precision) (*JobResult, error) { job, err := c.SubmitJob(ctx, "matmul", map[string]interface{}{ "a": a.Serialize(), "b": b.Serialize(), "precision": precision, }) if err != nil { return nil, err } return job.Wait(ctx) } // Inference runs model inference. func (c *Client) Inference(ctx context.Context, model, input string, maxTokens int) (*JobResult, error) { job, err := c.SubmitJob(ctx, "inference", map[string]interface{}{ "model": model, "input": input, "max_tokens": maxTokens, "strategy": c.config.Strategy, }) if err != nil { return nil, err } return job.Wait(ctx) } // Job represents a submitted compute job. type Job struct { ID string client *Client status JobStatus } // SubmitJob submits a new compute job. func (c *Client) SubmitJob(ctx context.Context, operation string, params map[string]interface{}) (*Job, error) { body := map[string]interface{}{ "operation": operation, "params": params, "strategy": c.config.Strategy, } var resp struct { JobID string `json:"job_id"` } if err := c.request(ctx, "POST", "/jobs", body, &resp); err != nil { return nil, err } return &Job{ ID: resp.JobID, client: c, status: Pending, }, nil } // Wait waits for the job to complete. func (j *Job) Wait(ctx context.Context) (*JobResult, error) { ticker := time.NewTicker(500 * time.Millisecond) defer ticker.Stop() for { select { case <-ctx.Done(): return nil, ctx.Err() case <-ticker.C: result, err := j.client.GetJobStatus(ctx, j.ID) if err != nil { return nil, err } if result.Status == Completed || result.Status == Failed || result.Status == Cancelled { return result, nil } } } } // GetJobStatus gets the status of a job. func (c *Client) GetJobStatus(ctx context.Context, jobID string) (*JobResult, error) { var result JobResult if err := c.request(ctx, "GET", "/jobs/"+jobID, nil, &result); err != nil { return nil, err } return &result, nil } // CancelJob cancels a running job. func (c *Client) CancelJob(ctx context.Context, jobID string) error { return c.request(ctx, "DELETE", "/jobs/"+jobID, nil, nil) } // PricingInfo contains pricing information. type PricingInfo struct { ProcessorType ProcessorType `json:"processor_type"` SpotPrice float64 `json:"spot_price"` AvgPrice24h float64 `json:"avg_price_24h"` AWSEquivalent float64 `json:"aws_equivalent"` SavingsPercent float64 `json:"savings_percent"` } // GetPricing gets current pricing for all processor types. func (c *Client) GetPricing(ctx context.Context) ([]PricingInfo, error) { var resp struct { Pricing []PricingInfo `json:"pricing"` } if err := c.request(ctx, "GET", "/pricing", nil, &resp); err != nil { return nil, err } return resp.Pricing, nil } func (c *Client) request(ctx context.Context, method, path string, body interface{}, result interface{}) error { url := c.config.Endpoint + path var bodyReader io.Reader if body != nil { bodyBytes, err := json.Marshal(body) if err != nil { return fmt.Errorf("failed to marshal request: %w", err) } bodyReader = bytes.NewReader(bodyBytes) } req, err := http.NewRequestWithContext(ctx, method, url, bodyReader) if err != nil { return fmt.Errorf("failed to create request: %w", err) } req.Header.Set("Authorization", "Bearer "+c.config.APIKey) req.Header.Set("Content-Type", "application/json") resp, err := c.httpClient.Do(req) if err != nil { return fmt.Errorf("request failed: %w", err) } defer resp.Body.Close() if resp.StatusCode >= 400 { var errResp struct { Message string `json:"message"` } json.NewDecoder(resp.Body).Decode(&errResp) return &SynorError{ Message: errResp.Message, StatusCode: resp.StatusCode, } } if result != nil { if err := json.NewDecoder(resp.Body).Decode(result); err != nil { return fmt.Errorf("failed to decode response: %w", err) } } return nil } // SynorError represents an API error. type SynorError struct { Message string StatusCode int } func (e *SynorError) Error() string { return fmt.Sprintf("synor: %s (status %d)", e.Message, e.StatusCode) }