Add GLM SDK Implementation
- Introduced a new GLM SDK for interacting with the GLM (Zhipu AI) API, designed for chat completions and text generation tasks. - Implemented core components including Client, Service, and SDK layers following Clean Architecture principles. - Added configuration management, error handling, and structured logging for improved usability and maintainability. - Included comprehensive documentation and usage examples to facilitate integration and understanding of the SDK's functionality. - Enhanced the API with features such as chat completion, streaming responses, and model management, ensuring robust interaction with the GLM service.
This commit is contained in:
@@ -0,0 +1,280 @@
|
||||
# GLM SDK Usage Guide
|
||||
|
||||
## Matching the Provided Curl Request
|
||||
|
||||
The SDK can replicate the exact curl request provided:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"tm/pkg/glm"
|
||||
"tm/pkg/logger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
config := &glm.Config{
|
||||
BaseURL: "https://api.z.ai",
|
||||
APIKey: "4e267ac7897f4a789cacb3dbee15f312.coJtK3397qFv16x5",
|
||||
}
|
||||
|
||||
logger := logger.NewLogger()
|
||||
sdk, err := glm.New(config, logger)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
req := &glm.ChatCompletionRequest{
|
||||
Model: "glm-4.5",
|
||||
Messages: []glm.Message{
|
||||
{
|
||||
Role: glm.MessageRoleSystem,
|
||||
Content: "You are a high-precision translator specializing in professional tender documents. Always respond with only the translated English text — no explanations, notes, or markdown formatting.",
|
||||
},
|
||||
{
|
||||
Role: glm.MessageRoleUser,
|
||||
Content: "Translate the following text from Swedish to English accurately and professionally:\n\"IT-stöd för projekt- och portföljstyrning\"",
|
||||
},
|
||||
},
|
||||
Thinking: &glm.Thinking{
|
||||
Type: "false",
|
||||
},
|
||||
MaxTokens: 4096,
|
||||
TopP: 1,
|
||||
FrequencyPenalty: 0,
|
||||
PresencePenalty: 0,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
resp, err := sdk.ChatCompletion(ctx, req)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if len(resp.Choices) > 0 {
|
||||
fmt.Println(resp.Choices[0].Message.Content)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Using the Translate Convenience Method
|
||||
|
||||
For the specific translation use case:
|
||||
|
||||
```go
|
||||
translated, err := sdk.Translate(ctx, "IT-stöd för projekt- och portföljstyrning", "Swedish", "English")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(translated) // Output: "IT support for project and portfolio management"
|
||||
```
|
||||
|
||||
### Custom Translation Options
|
||||
|
||||
For more control over translation parameters:
|
||||
|
||||
```go
|
||||
opts := &glm.TranslateOptions{
|
||||
Model: "glm-4.5",
|
||||
MaxTokens: 1024,
|
||||
Temperature: 0.1, // Very low for consistent translations
|
||||
FrequencyPenalty: 0.2,
|
||||
PresencePenalty: 0.2,
|
||||
EnableThinking: &[]bool{false}[0],
|
||||
}
|
||||
|
||||
translated, err := sdk.TranslateWithOptions(ctx, "IT-stöd för projekt- och portföljstyrning", "Swedish", "English", opts)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(translated)
|
||||
```
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### GLM SDK Configuration
|
||||
|
||||
```go
|
||||
config := &glm.Config{
|
||||
BaseURL: "https://api.z.ai",
|
||||
APIKey: "your-api-key",
|
||||
Timeout: 300 * time.Second,
|
||||
RetryAttempts: 3,
|
||||
RetryDelay: 2 * time.Second,
|
||||
EnableLogging: true,
|
||||
DefaultModel: "glm-4.5",
|
||||
DefaultMaxTokens: 4096,
|
||||
DefaultTopP: 1.0,
|
||||
DefaultTemperature: 0.7,
|
||||
DefaultFrequencyPenalty: 0.0,
|
||||
DefaultPresencePenalty: 0.0,
|
||||
EnableStreaming: false,
|
||||
EnableThinking: false,
|
||||
|
||||
// Translation-specific configuration
|
||||
TranslationMaxTokens: 2048,
|
||||
TranslationTemperature: 0.3,
|
||||
TranslationFrequencyPenalty: 0.1,
|
||||
TranslationPresencePenalty: 0.1,
|
||||
TranslationEnableThinking: false,
|
||||
}
|
||||
```
|
||||
|
||||
### Bootstrap Configuration (Application Level)
|
||||
|
||||
Configure translation parameters via environment variables in your application bootstrap:
|
||||
|
||||
```go
|
||||
// cmd/worker/bootstrap/config.go
|
||||
type GLMConfig struct {
|
||||
// ... basic GLM settings ...
|
||||
|
||||
// Translation options configured via environment variables
|
||||
TranslateOptions TranslateOptions
|
||||
}
|
||||
|
||||
type TranslateOptions struct {
|
||||
MaxTokens int `env:"GLM_TRANSLATE_MAX_TOKENS" default:"2048"`
|
||||
Temperature float64 `env:"GLM_TRANSLATE_TEMPERATURE" default:"0.3"`
|
||||
FrequencyPenalty float64 `env:"GLM_TRANSLATE_FREQUENCY_PENALTY" default:"0.1"`
|
||||
PresencePenalty float64 `env:"GLM_TRANSLATE_PRESENCE_PENALTY" default:"0.1"`
|
||||
EnableThinking bool `env:"GLM_TRANSLATE_ENABLE_THINKING" default:"false"`
|
||||
}
|
||||
```
|
||||
|
||||
Set these environment variables to customize translation behavior:
|
||||
|
||||
```bash
|
||||
export GLM_TRANSLATE_MAX_TOKENS=1024
|
||||
export GLM_TRANSLATE_TEMPERATURE=0.2
|
||||
export GLM_TRANSLATE_FREQUENCY_PENALTY=0.2
|
||||
export GLM_TRANSLATE_PRESENCE_PENALTY=0.2
|
||||
export GLM_TRANSLATE_ENABLE_THINKING=false
|
||||
```
|
||||
|
||||
## Error Handling Examples
|
||||
|
||||
```go
|
||||
resp, err := sdk.ChatCompletion(ctx, req)
|
||||
if err != nil {
|
||||
var glmErr *glm.Error
|
||||
if errors.As(err, &glmErr) {
|
||||
switch glmErr.Code {
|
||||
case glm.ErrCodeAuthentication:
|
||||
log.Printf("Authentication failed: %s", glmErr.Message)
|
||||
// Handle authentication error (e.g., refresh token)
|
||||
case glm.ErrCodeRateLimit:
|
||||
log.Printf("Rate limit exceeded: %s", glmErr.Message)
|
||||
// Implement backoff strategy
|
||||
case glm.ErrCodeInvalidRequest:
|
||||
log.Printf("Invalid request: %s", glmErr.Message)
|
||||
// Fix request parameters
|
||||
case glm.ErrCodeServerError:
|
||||
log.Printf("Server error: %s", glmErr.Message)
|
||||
// Retry or alert administrators
|
||||
default:
|
||||
log.Printf("Unknown error: %s", glmErr.Error())
|
||||
}
|
||||
} else {
|
||||
log.Printf("Non-GLM error: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
## Streaming with Progress Tracking
|
||||
|
||||
```go
|
||||
var fullResponse strings.Builder
|
||||
|
||||
err := sdk.StreamChatCompletion(ctx, req, func(chunk *glm.StreamChatCompletionResponse) error {
|
||||
if len(chunk.Choices) > 0 {
|
||||
content := chunk.Choices[0].Delta.Content
|
||||
fmt.Print(content) // Print as it comes
|
||||
fullResponse.WriteString(content)
|
||||
}
|
||||
|
||||
// Check for completion
|
||||
if len(chunk.Choices) > 0 && chunk.Choices[0].FinishReason != nil {
|
||||
fmt.Printf("\n\nFinished with reason: %s\n", *chunk.Choices[0].FinishReason)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Complete response: %s\n", fullResponse.String())
|
||||
```
|
||||
|
||||
## Integration with Tender Management System
|
||||
|
||||
```go
|
||||
// In your service layer
|
||||
type TranslationService struct {
|
||||
glmSDK *glm.SDK
|
||||
logger logger.Logger
|
||||
}
|
||||
|
||||
func NewTranslationService(glmSDK *glm.SDK, logger logger.Logger) *TranslationService {
|
||||
return &TranslationService{
|
||||
glmSDK: glmSDK,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *TranslationService) TranslateTenderDocument(ctx context.Context, text, sourceLang, targetLang string) (string, error) {
|
||||
s.logger.Info("Translating tender document", map[string]interface{}{
|
||||
"text_length": len(text),
|
||||
"source_lang": sourceLang,
|
||||
"target_lang": targetLang,
|
||||
})
|
||||
|
||||
translated, err := s.glmSDK.Translate(ctx, text, sourceLang, targetLang)
|
||||
if err != nil {
|
||||
s.logger.Error("Translation failed", map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
})
|
||||
return "", err
|
||||
}
|
||||
|
||||
s.logger.Info("Translation completed", map[string]interface{}{
|
||||
"translated_length": len(translated),
|
||||
})
|
||||
|
||||
return translated, nil
|
||||
}
|
||||
```
|
||||
|
||||
## Health Monitoring
|
||||
|
||||
```go
|
||||
// Check service health
|
||||
err := sdk.Health(ctx)
|
||||
if err != nil {
|
||||
log.Printf("GLM service is unhealthy: %v", err)
|
||||
// Alert monitoring system
|
||||
} else {
|
||||
log.Println("GLM service is healthy")
|
||||
}
|
||||
```
|
||||
|
||||
## Model Management
|
||||
|
||||
```go
|
||||
// List available models
|
||||
models, err := sdk.ListModels(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println("Available models:")
|
||||
for _, model := range models.Data {
|
||||
fmt.Printf("- %s (owned by %s)\n", model.ID, model.OwnedBy)
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user