Chào các bạn, tôi là một kỹ sư backend đã làm việc với Go và AI APIs được 4 năm. Hôm nay tôi muốn chia sẻ những kinh nghiệm thực chiến về việc chọn framework để xây dựng hệ thống AI API production-ready với Go.
Tại sao nên dùng Go cho AI API Development
Go sinh ra để xử lý concurrent requests cực kỳ hiệu quả. Với goroutines, bạn có thể handle hàng nghìn concurrent connections chỉ với vài MB RAM. Điều này đặc biệt quan trọng khi làm việc với AI APIs vì:
- AI inference thường có độ trễ cao (1-5 giây)
- Cần batch requests để tối ưu chi phí
- Streaming responses yêu cầu connection management chặt chẽ
- Rate limiting và retry logic phức tạp
So sánh các Framework phổ biến
1. go-openai - Thư viện chuyên biệt
Đây là lựa chọn phổ biến nhất với hơn 8k stars. Tuy nhiên, nó được thiết kế cho OpenAI API gốc, nên cần custom implementation để tích hợp HolySheep AI.
2. AI SDKs - Frameworkagnostic
Các SDK đa nền tảng cho phép switch providers dễ dàng. Nhưng đôi kí overhead không cần thiết cho production.
3. Custom Implementation - Linh hoạt tối đa
Cách tiếp cận tôi recommend cho production systems: tự build abstraction layer.
Code mẫu: HolySheep AI Client cho Go
package aiclient
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
type HolySheepClient struct {
apiKey string
baseURL string
httpClient *http.Client
maxRetries int
}
type ChatMessage struct {
Role string json:"role"
Content string json:"content"
}
type ChatRequest struct {
Model string json:"model"
Messages []ChatMessage json:"messages"
Temperature float64 json:"temperature,omitempty"
MaxTokens int json:"max_tokens,omitempty"
Stream bool json:"stream,omitempty"
}
type ChatResponse struct {
ID string json:"id"
Model string json:"model"
Choices []Choice json:"choices"
Usage Usage json:"usage"
}
type Choice struct {
Message ChatMessage json:"message"
FinishReason string json:"finish_reason"
}
type Usage struct {
PromptTokens int json:"prompt_tokens"
CompletionTokens int json:"completion_tokens"
TotalTokens int json:"total_tokens"
}
func NewHolySheepClient(apiKey string) *HolySheepClient {
return &HolySheepClient{
apiKey: apiKey,
baseURL: "https://api.holysheep.ai/v1",
httpClient: &http.Client{
Timeout: 60 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
},
},
maxRetries: 3,
}
}
func (c *HolySheepClient) Chat(ctx context.Context, req ChatRequest) (*ChatResponse, error) {
url := fmt.Sprintf("%s/chat/completions", c.baseURL)
jsonData, err := json.Marshal(req)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey))
var lastErr error
for attempt := 0; attempt <= c.maxRetries; attempt++ {
resp, err := c.httpClient.Do(httpReq)
if err != nil {
lastErr = err
time.Sleep(time.Duration(attempt+1) * 500 * time.Millisecond)
continue
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response: %w", err)
}
var chatResp ChatResponse
if err := json.Unmarshal(body, &chatResp); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
return &chatResp, nil
}
if resp.StatusCode == 429 || resp.StatusCode >= 500 {
lastErr = fmt.Errorf("rate limited or server error: %d", resp.StatusCode)
time.Sleep(time.Duration(attempt+1) * time.Second)
continue
}
return nil, fmt.Errorf("API error: status %d", resp.StatusCode)
}
return nil, fmt.Errorf("max retries exceeded: %w", lastErr)
}
Streaming Implementation với Server-Sent Events
package aiclient
import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
type StreamHandler func(delta string) error
func (c *HolySheepClient) ChatStream(ctx context.Context, req ChatRequest, handler StreamHandler) error {
req.Stream = true
url := fmt.Sprintf("%s/chat/completions", c.baseURL)
jsonData, err := json.Marshal(req)
if err != nil {
return fmt.Errorf("failed to marshal request: %w", err)
}
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, strings.NewReader(string(jsonData)))
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey))
resp, err := c.httpClient.Do(httpReq)
if err != nil {
return fmt.Errorf("failed to send request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("API error %d: %s", resp.StatusCode, string(body))
}
scanner := bufio.NewScanner(resp.Body)
scanner.Split(scanLinesWithCRLF