# Synor Compute SDK for Ruby

Access distributed heterogeneous compute at 90% cost reduction.

## Installation

Add to `Gemfile`:

```ruby
gem 'synor_compute'
```

Then run:

```bash
bundle install
```

Or install directly:

```bash
gem install synor_compute
```

## Quick Start

```ruby
require 'synor_compute'

client = SynorCompute::Client.new('your-api-key')

# Matrix multiplication on GPU
a = SynorCompute::Tensor.random([512, 512])
b = SynorCompute::Tensor.random([512, 512])

result = client.matmul(a, b,
  precision: :fp16,
  processor: :gpu
)

if result.success?
  puts "Time: #{result.execution_time_ms}ms"
  puts "Cost: $#{result.cost}"
end
```

## Tensor Operations

```ruby
# Create tensors
zeros = SynorCompute::Tensor.zeros([3, 3])
ones = SynorCompute::Tensor.ones([2, 2])
random = SynorCompute::Tensor.random([10, 10])
randn = SynorCompute::Tensor.randn([100])
eye = SynorCompute::Tensor.eye(3)

# From array
data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
tensor = SynorCompute::Tensor.new(data, shape: [2, 3])

# Operations
reshaped = tensor.reshape([3, 2])
transposed = tensor.transpose

# Math
mean = tensor.mean
sum = tensor.sum
std = tensor.std
```

## Matrix Operations

```ruby
# Matrix multiplication
result = client.matmul(a, b,
  precision: :fp16,
  processor: :gpu,
  strategy: :speed
)

# 2D Convolution
conv = client.conv2d(input, kernel,
  stride: [1, 1],
  padding: [1, 1]
)

# Attention
attention = client.attention(query, key, value,
  num_heads: 8,
  flash: true
)
```

## LLM Inference

```ruby
# Single response
response = client.inference('llama-3-70b', 'Explain quantum computing',
  max_tokens: 512,
  temperature: 0.7
)
puts response.result

# Streaming with block
client.inference_stream('llama-3-70b', 'Write a poem') do |chunk|
  print chunk
end

# Streaming with Enumerator
client.inference_stream('llama-3-70b', 'Write a poem').each do |chunk|
  print chunk
end
```

## Configuration

```ruby
config = SynorCompute::Config.new(
  api_key: 'your-api-key',
  base_url: 'https://api.synor.io/compute/v1',
  default_processor: :gpu,
  default_precision: :fp16,
  timeout: 30,
  debug: true
)

client = SynorCompute::Client.new(config)

# Or with block
SynorCompute.configure do |config|
  config.api_key = 'your-api-key'
  config.default_processor = :gpu
end
```

## Rails Integration

```ruby
# config/initializers/synor_compute.rb
SynorCompute.configure do |config|
  config.api_key = Rails.application.credentials.synor[:api_key]
  config.default_processor = :gpu
end

# In your controller/service
class ComputeService
  def self.client
    @client ||= SynorCompute::Client.new
  end

  def self.compute(a, b)
    client.matmul(a, b)
  end
end
```

## Error Handling

```ruby
begin
  result = client.matmul(a, b)
rescue SynorCompute::ApiError => e
  puts "API Error #{e.status_code}: #{e.message}"
rescue SynorCompute::NetworkError => e
  puts "Network error: #{e.message}"
rescue SynorCompute::Error => e
  puts "Error: #{e.message}"
end
```

## Types

```ruby
# Processor types (symbols)
:cpu, :gpu, :tpu, :npu, :lpu, :fpga, :auto

# Precision (symbols)
:fp64, :fp32, :fp16, :bf16, :int8, :int4

# Job status (symbols)
:pending, :running, :completed, :failed, :cancelled

# Balancing strategy (symbols)
:speed, :cost, :energy, :latency, :balanced
```

## Job Management

```ruby
# Submit async job
job = client.submit_job(:matmul, a: a, b: b)

# Poll for status
status = client.job_status(job.id)

# Wait for completion
result = client.wait_for_job(job.id, timeout: 60)

# Cancel job
client.cancel_job(job.id)
```

## Ruby-Specific Features

### Method Chaining

```ruby
result = client
  .matmul(a, b)
  .tap { |r| puts "Computing..." }
  .then { |r| r.data if r.success? }
```

### Duck Typing

```ruby
# Any object with #to_tensor method works
class MyData
  def to_tensor
    SynorCompute::Tensor.new(@data, shape: @shape)
  end
end

result = client.matmul(MyData.new, b)
```

### Frozen String Literals

The gem is compatible with frozen string literals:

```ruby
# frozen_string_literal: true
require 'synor_compute'
```

## Requirements

- Ruby 3.0+
- faraday gem for HTTP

## Testing

```bash
bundle exec rake test
# or
bundle exec rspec
```

## License

MIT
