Files
sglang/sgl-router/bindings/golang/README.md
T
2025-11-16 10:12:10 -08:00

553 lines
14 KiB
Markdown

# SGLang Go gRPC SDK
A high-level Go SDK for interacting with SGLang gRPC API, designed with an OpenAI-style API for familiarity and ease of use.
**Location**: `sgl-router/bindings/golang/`
## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Basic Usage](#basic-usage)
- [Streaming Usage](#streaming-usage)
- [Examples](#examples)
- [Configuration](#configuration)
- [API Reference](#api-reference)
- [Testing](#testing)
- [Unit Tests](#unit-tests)
- [Integration Tests](#integration-tests)
- [Benchmarks](#benchmarks)
- [Documentation](#documentation)
- [Development](#development)
- [Troubleshooting](#troubleshooting)
- [License](#license)
## Features
- **OpenAI-style API**: Familiar interface similar to OpenAI Go SDK
- **Streaming Support**: Real-time streaming chat completions
- **Non-streaming Support**: Simple request/response API
- **Tool Calling**: Support for function calling and tool use
- **Type-safe**: Full Go type definitions for requests and responses
- **Comprehensive Testing**: 18+ unit and integration tests
- **Thread-safe**: All public methods are safe for concurrent use
- **Well-documented**: Full API documentation with examples
## Installation
```bash
go get github.com/sglang/sglang-go-grpc-sdk
```
### Build Requirements
- Go 1.21 or later
- Rust toolchain (for building the FFI library)
- Python 3.x (for Python bindings in Rust FFI)
- Tokio runtime for async operations
## Quick Start
### Basic Usage (Non-streaming)
```go
package main
import (
"context"
"fmt"
"log"
"github.com/sglang/sglang-go-grpc-sdk"
)
func main() {
// Create client
client, err := sglang.NewClient(sglang.ClientConfig{
Endpoint: "grpc://localhost:20000",
TokenizerPath: "/path/to/tokenizer",
})
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Create completion
resp, err := client.CreateChatCompletion(context.Background(), sglang.ChatCompletionRequest{
Model: "default",
Messages: []sglang.ChatMessage{
{Role: "user", Content: "Hello!"},
},
Stream: false,
})
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Choices[0].Message.Content)
fmt.Printf("Usage: Prompt=%d, Completion=%d, Total=%d\n",
resp.Usage.PromptTokens,
resp.Usage.CompletionTokens,
resp.Usage.TotalTokens)
}
```
### Streaming Usage
```go
package main
import (
"context"
"fmt"
"io"
"log"
"github.com/sglang/sglang-go-grpc-sdk"
)
func main() {
// Create client
client, err := sglang.NewClient(sglang.ClientConfig{
Endpoint: "grpc://localhost:20000",
TokenizerPath: "/path/to/tokenizer",
})
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Create streaming completion
ctx := context.Background()
stream, err := client.CreateChatCompletionStream(ctx, sglang.ChatCompletionRequest{
Model: "default",
Messages: []sglang.ChatMessage{
{Role: "user", Content: "Tell me a story"},
},
Stream: true,
MaxCompletionTokens: intPtr(500),
})
if err != nil {
log.Fatal(err)
}
defer stream.Close()
// Read streaming response
for {
chunk, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
for _, choice := range chunk.Choices {
if choice.Delta.Content != "" {
fmt.Print(choice.Delta.Content)
}
}
}
fmt.Println() // newline
}
// Helper functions for optional pointer fields
func intPtr(i int) *int {
return &i
}
func float32Ptr(f float32) *float32 {
return &f
}
```
## Examples
The SDK includes several examples in the `examples/` directory:
- **simple**: Basic non-streaming chat completion example
- **streaming**: Real-time streaming with performance metrics
### Running Examples
```bash
# Run simple example
cd bindings/golang/examples/simple
bash run.sh
# Run streaming example
cd bindings/golang/examples/streaming
bash run.sh
# Or use Makefile from bindings/golang directory
cd bindings/golang
make run-simple
make run-streaming
```
Examples automatically detect the server endpoint and tokenizer path via environment variables or defaults.
## Configuration
### Environment Variables
- `SGL_GRPC_ENDPOINT`: gRPC server endpoint (default: `grpc://localhost:20000`)
- `SGL_TOKENIZER_PATH`: Path to tokenizer directory (required)
- `CARGO_BUILD_DIR`: Rust build output directory (auto-detected if not set)
### ClientConfig
```go
type ClientConfig struct {
// Endpoint is the gRPC endpoint URL (e.g., "grpc://localhost:20000")
// Required field. Must include the scheme (grpc://) and port number.
Endpoint string
// TokenizerPath is the path to the tokenizer directory containing
// tokenizer configuration files (e.g., tokenizer.json, vocab.json)
// Required field.
TokenizerPath string
}
```
## API Reference
### Client Methods
```go
type Client struct {
// Thread-safe client for SGLang gRPC API
}
// Creates a new client with the given configuration
func NewClient(config ClientConfig) (*Client, error)
// Closes the client and releases all resources
func (c *Client) Close() error
// Creates a non-streaming chat completion
func (c *Client) CreateChatCompletion(ctx context.Context, req ChatCompletionRequest) (*ChatCompletionResponse, error)
// Creates a streaming chat completion
func (c *Client) CreateChatCompletionStream(ctx context.Context, req ChatCompletionRequest) (*ChatCompletionStream, error)
```
### Request Types
- `ChatCompletionRequest`: Main request type for chat completions
- Model, Messages, Stream, Temperature, TopP, MaxCompletionTokens, Tools, etc.
- `ChatMessage`: Individual message in a conversation
- Role, Content
- `Tool`: Tool/function definition for function calling
- Type, Function (name, description, parameters)
### Response Types
- `ChatCompletionResponse`: Non-streaming response
- ID, Model, Created, Choices, Usage
- `ChatCompletionStreamResponse`: Streaming response chunk
- Same structure as above but for incremental updates
- `Message`: Complete message with content and tool calls
- `ToolCall`: Tool call information with function and arguments
- `Usage`: Token usage statistics
- PromptTokens, CompletionTokens, TotalTokens
## Testing
The SDK includes comprehensive testing infrastructure with both unit and integration tests.
### Unit Tests
Unit tests are located in `client_test.go` and test individual components without requiring a server.
#### Running Unit Tests
```bash
# Run all unit tests
go test ./...
# Run with verbose output
go test -v ./...
# Run specific test
go test -run TestClientConfig
# Run tests with race detector (detects concurrency issues)
go test -race ./...
# Run with coverage analysis
go test -cover ./...
# Generate detailed coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
```
#### Unit Test Coverage
- **Configuration validation** (`TestClientConfig`) - Validates ClientConfig requirements
- **Type structures** - Verifying all struct types work correctly
- **Response handling** - Testing response parsing and validation
- **Concurrent operations** (`TestConcurrentClientOperations`) - Thread-safety verification
- **Benchmarks** (`BenchmarkChatCompletionRequest`) - Performance measurement
**Test Files**:
- `client_test.go` - 10 unit tests covering core functionality
- Tests cover: config validation, message types, request validation, close operations, response types, streaming, tools, concurrency, and context cancellation
### Integration Tests
Integration tests require a running SGLang server and test the full client-server interaction.
#### Prerequisites
1. Start an SGLang server:
```bash
# Using Python (requires sglang package installed)
python -m sglang.launch_server --model-path meta-llama/Llama-2-7b-hf
# Or using pre-built Docker image
docker run -p 20000:20000 lmsys/sglang:latest
# Or build your own
sglang launch_server --model-path <model_path>
```
2. Set required environment variables:
```bash
# Set the gRPC endpoint (default: grpc://localhost:20000)
export SGL_GRPC_ENDPOINT=grpc://localhost:20000
# Set the tokenizer path (required)
export SGL_TOKENIZER_PATH=/path/to/tokenizer
```
#### Running Integration Tests
```bash
# Run all integration tests
go test -tags=integration ./...
# Run specific integration test
go test -tags=integration -run TestIntegrationNonStreamingCompletion
# Run with verbose output
go test -tags=integration -v ./...
# Run with race detector
go test -tags=integration -race ./...
```
#### Integration Test Coverage
**Test File**: `integration_test.go` - 4 integration tests
- `TestIntegrationNonStreamingCompletion` - Basic non-streaming request/response
- `TestIntegrationStreamingCompletion` - Streaming response handling
- `TestIntegrationConcurrentRequests` - Multiple simultaneous requests
- `TestIntegrationContextCancellation` - Context timeout and cancellation
### Benchmarks
Measure performance of SDK operations:
```bash
# Run all benchmarks
go test -bench=. -benchmem ./...
# Run specific benchmark
go test -bench=BenchmarkChatCompletionRequest -benchmem
# Run for longer duration
go test -bench=. -benchtime=10s ./...
```
Current benchmarks:
- `BenchmarkChatCompletionRequest` - Measures request creation performance
### CI/CD Integration
Add to your GitHub Actions workflow:
```yaml
- name: Run Go tests
run: |
go test -race -cover ./...
- name: Run integration tests (on main branch)
if: github.ref == 'refs/heads/main'
env:
SGL_GRPC_ENDPOINT: grpc://localhost:20000
SGL_TOKENIZER_PATH: /path/to/tokenizer
run: go test -tags=integration ./...
```
## Documentation
### Code Documentation
All public types and functions include comprehensive documentation:
1. **Package-level documentation** in `client.go` with usage examples
2. **Type documentation** for all structs with field descriptions
3. **Function documentation** with:
- Purpose and behavior description
- Parameter documentation with types and constraints
- Return value documentation
- Error cases and handling
- Safety notes (for FFI functions)
- Usage examples
### Key Documented Components
- `Client` - Main client with thread-safety notes
- `ClientConfig` - Configuration requirements and validation rules
- `ChatCompletionRequest` - Request structure with field descriptions
- `ChatCompletionResponse` - Response structure and usage
- `ChatCompletionStreamResponse` - Streaming response format
- `Usage` - Token usage information structure
- `Tool`, `Function`, `ToolCall` - Tool call structures
### Viewing Documentation
Generate and view HTML documentation:
```bash
# Install godoc (if not already installed)
go install golang.org/x/tools/cmd/godoc@latest
# Generate and serve documentation
godoc -http=:6060
# Visit: http://localhost:6060/pkg/github.com/sglang/sglang-go-grpc-sdk/
```
## Development
### Building
```bash
cd bindings/golang
# Build the Go bindings (compiles Rust FFI library)
make build
# Clean build
make clean && make build
```
### Code Quality
Ensure code quality before committing:
```bash
# Run Go vet (check for potential bugs)
go vet ./...
# Format code
go fmt ./...
# Run all tests with race detection
go test -race ./...
```
### Project Structure
```
bindings/golang/
├── client.go # Main client implementation
├── client_test.go # Unit tests
├── integration_test.go # Integration tests
├── README.md # This file
├── Makefile # Build automation
├── Cargo.toml # Rust FFI dependencies
├── examples/ # Example programs
│ ├── simple/ # Non-streaming example
│ └── streaming/ # Streaming example
├── src/ # Rust FFI source
│ ├── client.rs # Client FFI
│ ├── stream.rs # Stream handling
│ ├── grpc_converter.rs # Response conversion
│ └── ...
└── internal/ # Internal packages
└── ffi/ # FFI bindings
```
## Troubleshooting
### Connection Errors
**Error**: `connection refused` or `failed to dial`
**Solution**:
1. Ensure SGLang server is running: `python -m sglang.launch_server`
2. Check endpoint: `echo $SGL_GRPC_ENDPOINT`
3. Verify port is not blocked: `nc -zv localhost 20000`
### Tokenizer Not Found
**Error**: `tokenizer path not found` or `tokenizer configuration missing`
**Solution**:
1. Set `SGL_TOKENIZER_PATH` environment variable
2. Verify path contains required files: `ls $SGL_TOKENIZER_PATH`
3. Files should include: `tokenizer.json`, `vocab.json`, `config.json`
### Build Failures
**Error**: `library 'sglang_router_rs' not found`
**Solution**:
1. Rebuild Rust library: `cd sgl-router/bindings/golang && make build`
2. Or manually with cargo: `cd sgl-router/bindings/golang && cargo build --release`
3. Set `CARGO_BUILD_DIR` if using non-standard build location
4. Ensure Rust toolchain is installed: `rustup toolchain list`
### Tests Hanging
**Error**: Tests seem to hang indefinitely
**Solution**:
1. Use timeout for hanging tests: `timeout 30s go test ./...`
2. Run with verbose output to see which test hangs: `go test -v ./...`
3. Ensure server is responsive: `grpcurl -plaintext localhost:20000 list`
### Memory Issues
**Error**: Out of memory during tests
**Solution**:
```bash
# Run with memory limit for long-running tests
GODEBUG=madvdontneed=1 go test -timeout 5m ./...
# Monitor memory during tests
watch -n1 'ps aux | grep test'
```
## Contributing
When adding new features:
1. Add comprehensive documentation to public types/functions
2. Include usage examples for complex APIs
3. Add unit tests covering happy path and error cases
4. Add integration tests if server interaction required
5. Ensure code passes `go vet` and `go test -race`
6. Update this README if adding new features
## License
See LICENSE file for details.
---
**Need Help?**
- Check examples in `examples/` directory
- Run tests to see working code: `go test -v ./...`
- Review function documentation: `godoc` or inline comments
- Check troubleshooting section above