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:
+213
@@ -0,0 +1,213 @@
|
||||
package glm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"tm/pkg/logger"
|
||||
)
|
||||
|
||||
// SDK provides a high-level interface for the GLM service
|
||||
type SDK struct {
|
||||
service GLMService
|
||||
client *Client
|
||||
config *Config
|
||||
}
|
||||
|
||||
// New creates a new GLM SDK with the provided configuration and logger
|
||||
func New(config *Config, logger logger.Logger) (*SDK, error) {
|
||||
if config == nil {
|
||||
config = DefaultConfig()
|
||||
}
|
||||
|
||||
client, err := NewClient(config, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
service := NewService(client)
|
||||
|
||||
return &SDK{
|
||||
service: service,
|
||||
client: client,
|
||||
config: config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ChatCompletion performs a chat completion request
|
||||
func (s *SDK) ChatCompletion(ctx context.Context, req *ChatCompletionRequest) (*ChatCompletionResponse, error) {
|
||||
return s.service.ChatCompletion(ctx, req)
|
||||
}
|
||||
|
||||
// StreamChatCompletion performs a streaming chat completion request
|
||||
func (s *SDK) StreamChatCompletion(ctx context.Context, req *ChatCompletionRequest, onChunk func(*StreamChatCompletionResponse) error) error {
|
||||
return s.service.StreamChatCompletion(ctx, req, onChunk)
|
||||
}
|
||||
|
||||
// ListModels lists available models
|
||||
func (s *SDK) ListModels(ctx context.Context) (*ModelsResponse, error) {
|
||||
return s.service.ListModels(ctx)
|
||||
}
|
||||
|
||||
// Health checks if the GLM service is available
|
||||
func (s *SDK) Health(ctx context.Context) error {
|
||||
return s.service.Health(ctx)
|
||||
}
|
||||
|
||||
// QuickChat is a convenience method for simple chat interactions
|
||||
func (s *SDK) QuickChat(ctx context.Context, userMessage string) (string, error) {
|
||||
req := &ChatCompletionRequest{
|
||||
Model: s.config.DefaultModel,
|
||||
Messages: []Message{
|
||||
{
|
||||
Role: MessageRoleUser,
|
||||
Content: userMessage,
|
||||
},
|
||||
},
|
||||
MaxTokens: s.config.DefaultMaxTokens,
|
||||
TopP: s.config.DefaultTopP,
|
||||
Temperature: s.config.DefaultTemperature,
|
||||
FrequencyPenalty: s.config.DefaultFrequencyPenalty,
|
||||
PresencePenalty: s.config.DefaultPresencePenalty,
|
||||
}
|
||||
|
||||
if s.config.EnableThinking {
|
||||
req.Thinking = &Thinking{Type: "true"}
|
||||
}
|
||||
|
||||
resp, err := s.ChatCompletion(ctx, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(resp.Choices) == 0 {
|
||||
return "", ErrInvalidResponse("no choices returned")
|
||||
}
|
||||
|
||||
return resp.Choices[0].Message.Content, nil
|
||||
}
|
||||
|
||||
// QuickChatWithSystem is a convenience method for chat with system prompt
|
||||
func (s *SDK) QuickChatWithSystem(ctx context.Context, systemPrompt, userMessage string) (string, error) {
|
||||
req := &ChatCompletionRequest{
|
||||
Model: s.config.DefaultModel,
|
||||
Messages: []Message{
|
||||
{
|
||||
Role: MessageRoleSystem,
|
||||
Content: systemPrompt,
|
||||
},
|
||||
{
|
||||
Role: MessageRoleUser,
|
||||
Content: userMessage,
|
||||
},
|
||||
},
|
||||
MaxTokens: s.config.DefaultMaxTokens,
|
||||
TopP: s.config.DefaultTopP,
|
||||
Temperature: s.config.DefaultTemperature,
|
||||
FrequencyPenalty: s.config.DefaultFrequencyPenalty,
|
||||
PresencePenalty: s.config.DefaultPresencePenalty,
|
||||
}
|
||||
|
||||
if s.config.EnableThinking {
|
||||
req.Thinking = &Thinking{Type: "true"}
|
||||
}
|
||||
|
||||
resp, err := s.ChatCompletion(ctx, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(resp.Choices) == 0 {
|
||||
return "", ErrInvalidResponse("no choices returned")
|
||||
}
|
||||
|
||||
return resp.Choices[0].Message.Content, nil
|
||||
}
|
||||
|
||||
// TranslateOptions represents options for translation
|
||||
type TranslateOptions struct {
|
||||
Model string `json:"model,omitempty"`
|
||||
MaxTokens int `json:"max_tokens,omitempty"`
|
||||
Temperature float64 `json:"temperature,omitempty"`
|
||||
FrequencyPenalty float64 `json:"frequency_penalty,omitempty"`
|
||||
PresencePenalty float64 `json:"presence_penalty,omitempty"`
|
||||
TopP float64 `json:"top_p,omitempty"`
|
||||
EnableThinking *bool `json:"enable_thinking,omitempty"`
|
||||
}
|
||||
|
||||
// Translate is a convenience method for translation tasks using dynamic configuration parameters optimized for translation
|
||||
func (s *SDK) Translate(ctx context.Context, text, fromLang, toLang string) (string, error) {
|
||||
systemPrompt := "You are a high-precision translator specializing in professional tender documents. Always respond with only the translated text — no explanations, notes, or markdown formatting."
|
||||
|
||||
userMessage := fmt.Sprintf("Translate the following text from %s to %s accurately and professionally:\n\"%s\"", fromLang, toLang, text)
|
||||
|
||||
// Build request with custom options or defaults
|
||||
req := &ChatCompletionRequest{
|
||||
Model: s.config.TranslationOptions.Model,
|
||||
Messages: []Message{
|
||||
{
|
||||
Role: MessageRoleSystem,
|
||||
Content: systemPrompt,
|
||||
},
|
||||
{
|
||||
Role: MessageRoleUser,
|
||||
Content: userMessage,
|
||||
},
|
||||
},
|
||||
MaxTokens: s.config.TranslationOptions.MaxTokens,
|
||||
TopP: s.config.TranslationOptions.TopP,
|
||||
Temperature: s.config.TranslationOptions.Temperature,
|
||||
FrequencyPenalty: s.config.TranslationOptions.FrequencyPenalty,
|
||||
PresencePenalty: s.config.TranslationOptions.PresencePenalty,
|
||||
}
|
||||
|
||||
resp, err := s.ChatCompletion(ctx, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(resp.Choices) == 0 {
|
||||
return "", ErrInvalidResponse("no choices returned")
|
||||
}
|
||||
|
||||
return resp.Choices[0].Message.Content, nil
|
||||
}
|
||||
|
||||
// StreamQuickChat is a convenience method for streaming chat interactions
|
||||
func (s *SDK) StreamQuickChat(ctx context.Context, userMessage string, onChunk func(string) error) error {
|
||||
req := &ChatCompletionRequest{
|
||||
Model: s.config.DefaultModel,
|
||||
Messages: []Message{
|
||||
{
|
||||
Role: MessageRoleUser,
|
||||
Content: userMessage,
|
||||
},
|
||||
},
|
||||
MaxTokens: s.config.DefaultMaxTokens,
|
||||
TopP: s.config.DefaultTopP,
|
||||
Temperature: s.config.DefaultTemperature,
|
||||
FrequencyPenalty: s.config.DefaultFrequencyPenalty,
|
||||
PresencePenalty: s.config.DefaultPresencePenalty,
|
||||
Stream: true,
|
||||
}
|
||||
|
||||
if s.config.EnableThinking {
|
||||
req.Thinking = &Thinking{Type: "true"}
|
||||
}
|
||||
|
||||
return s.StreamChatCompletion(ctx, req, func(chunk *StreamChatCompletionResponse) error {
|
||||
if len(chunk.Choices) > 0 && chunk.Choices[0].Delta.Content != "" {
|
||||
return onChunk(chunk.Choices[0].Delta.Content)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// GetService returns the underlying service for advanced usage
|
||||
func (s *SDK) GetService() GLMService {
|
||||
return s.service
|
||||
}
|
||||
|
||||
// GetConfig returns the current configuration
|
||||
func (s *SDK) GetConfig() *Config {
|
||||
return s.config
|
||||
}
|
||||
Reference in New Issue
Block a user