micro--go-micro
cae6fbbe76
* fix: remove deprecated rand.Seed calls Go 1.20+ automatically seeds the global random number generator. These calls are no-ops and generate warnings with newer Go versions. Removed from: - selector/strategy.go - registry/cache/cache.go - broker/memory.go - broker/http.go - cmd/cmd.go - transport/memory.go Co-authored-by: Shelley <shelley@exe.dev> * fix: handle previously ignored errors - MySQL store: properly handle prepared statement errors in initDB() - Consul registry: handle client creation errors in Client() method These silent failures could cause hard-to-debug issues in production. Co-authored-by: Shelley <shelley@exe.dev> * feat(genai): improve provider interface with context and streaming Breaking changes: - Generate() and Stream() now require context.Context as first parameter - Stream.Close() added for proper resource cleanup Improvements: - Proper context support for cancellation and timeouts - Real SSE streaming for OpenAI and Gemini text generation - Better error handling with wrapped errors and API error responses - Thread-safe provider registry with sync.RWMutex - New options: WithMaxTokens, WithTemperature, WithTimeout - Stream has proper Close() method for cleanup - Results can include Error field for per-chunk errors Provider updates: - OpenAI: true streaming with SSE parsing, proper HTTP client with timeout - Gemini: true streaming with streamGenerateContent endpoint - Default model updated to gpt-4o-mini (OpenAI) and gemini-2.0-flash (Gemini) Co-authored-by: Shelley <shelley@exe.dev> * feat(tls): make TLS secure by default, configurable via environment BREAKING: TLS now verifies certificates by default. Set MICRO_TLS_INSECURE=true to restore previous behavior (NOT recommended for production). Changes: - Add util/tls.Config(), SecureConfig(), InsecureConfig(), ConfigFromEnv() helpers - Update all components to use ConfigFromEnv() instead of hardcoded InsecureSkipVerify - Set MinVersion to TLS 1.2 for all TLS configs Affected components: - broker/http - broker/rabbitmq - registry/etcd - registry/consul - transport/grpc This improves security posture while allowing opt-out for development environments. Co-authored-by: Shelley <shelley@exe.dev> * feat(tls): add TLS helpers with opt-in secure mode NOT a breaking change - keeps InsecureSkipVerify=true as default for local development compatibility. New util/tls helpers: - Config() - returns config based on MICRO_TLS_SECURE env var - SecureConfig() - certificate verification enabled - InsecureConfig() - certificate verification disabled (dev only) For production security, use one of: - Set MICRO_TLS_SECURE=true with proper CA-signed certs - Use a service mesh (Istio, Linkerd) for automatic mTLS - Configure TLSConfig directly with your certificates Also: Changed CLI alias from 'g' to 'gen' for clarity - micro generate handler -> micro gen handler Co-authored-by: Shelley <shelley@exe.dev> * refactor(cli): rename generate directory to gen for consistency Directory name now matches the command alias: cmd/micro/cli/gen/ -> micro gen handler Co-authored-by: Shelley <shelley@exe.dev> --------- Co-authored-by: Shelley <shelley@exe.dev>
134 行
3.5 KiB
Go
134 行
3.5 KiB
Go
// Package genai provides a generic interface for generative AI providers.
|
|
package genai
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync"
|
|
)
|
|
|
|
var (
|
|
// ErrNoProvider is returned when no GenAI provider is configured.
|
|
ErrNoProvider = errors.New("no genai provider configured")
|
|
)
|
|
|
|
// Result is the unified response from GenAI providers.
|
|
type Result struct {
|
|
Prompt string
|
|
Type string
|
|
Data []byte // for audio/image binary data
|
|
Text string // for text or image URL
|
|
Error error // error if this chunk failed
|
|
}
|
|
|
|
// Stream represents a streaming response from a GenAI provider.
|
|
type Stream struct {
|
|
Results <-chan *Result
|
|
cancel context.CancelFunc
|
|
}
|
|
|
|
// Close cancels the stream and releases resources.
|
|
func (s *Stream) Close() {
|
|
if s.cancel != nil {
|
|
s.cancel()
|
|
}
|
|
}
|
|
|
|
// NewStream creates a new stream with the given channel and cancel function.
|
|
func NewStream(results <-chan *Result, cancel context.CancelFunc) *Stream {
|
|
return &Stream{
|
|
Results: results,
|
|
cancel: cancel,
|
|
}
|
|
}
|
|
|
|
// GenAI is the generic interface for generative AI providers.
|
|
type GenAI interface {
|
|
// Generate performs a single request and returns the result.
|
|
Generate(ctx context.Context, prompt string, opts ...Option) (*Result, error)
|
|
// Stream performs a streaming request and returns results as they arrive.
|
|
Stream(ctx context.Context, prompt string, opts ...Option) (*Stream, error)
|
|
// String returns the provider name.
|
|
String() string
|
|
}
|
|
|
|
// Option is a functional option for configuring providers.
|
|
type Option func(*Options)
|
|
|
|
// Options holds configuration for providers.
|
|
type Options struct {
|
|
APIKey string
|
|
Endpoint string
|
|
Type string // "text", "image", "audio", etc.
|
|
Model string // model name, e.g. "gemini-2.5-pro"
|
|
MaxTokens int // maximum tokens to generate
|
|
Temperature float64 // sampling temperature (0.0-2.0)
|
|
Timeout int // request timeout in seconds
|
|
}
|
|
|
|
// WithAPIKey sets the API key.
|
|
func WithAPIKey(key string) Option {
|
|
return func(o *Options) { o.APIKey = key }
|
|
}
|
|
|
|
// WithEndpoint sets a custom endpoint URL.
|
|
func WithEndpoint(endpoint string) Option {
|
|
return func(o *Options) { o.Endpoint = endpoint }
|
|
}
|
|
|
|
// WithModel sets the model name.
|
|
func WithModel(model string) Option {
|
|
return func(o *Options) { o.Model = model }
|
|
}
|
|
|
|
// WithMaxTokens sets the maximum tokens to generate.
|
|
func WithMaxTokens(tokens int) Option {
|
|
return func(o *Options) { o.MaxTokens = tokens }
|
|
}
|
|
|
|
// WithTemperature sets the sampling temperature.
|
|
func WithTemperature(temp float64) Option {
|
|
return func(o *Options) { o.Temperature = temp }
|
|
}
|
|
|
|
// WithTimeout sets the request timeout in seconds.
|
|
func WithTimeout(seconds int) Option {
|
|
return func(o *Options) { o.Timeout = seconds }
|
|
}
|
|
|
|
// Type option functions
|
|
func Text(o *Options) { o.Type = "text" }
|
|
func Image(o *Options) { o.Type = "image" }
|
|
func Audio(o *Options) { o.Type = "audio" }
|
|
|
|
// Provider registry with thread-safe access
|
|
var (
|
|
providers = make(map[string]GenAI)
|
|
providersMu sync.RWMutex
|
|
)
|
|
|
|
// Register a GenAI provider by name.
|
|
func Register(name string, provider GenAI) {
|
|
providersMu.Lock()
|
|
defer providersMu.Unlock()
|
|
providers[name] = provider
|
|
}
|
|
|
|
// Get a GenAI provider by name.
|
|
func Get(name string) GenAI {
|
|
providersMu.RLock()
|
|
defer providersMu.RUnlock()
|
|
return providers[name]
|
|
}
|
|
|
|
// List returns all registered provider names.
|
|
func List() []string {
|
|
providersMu.RLock()
|
|
defer providersMu.RUnlock()
|
|
names := make([]string, 0, len(providers))
|
|
for name := range providers {
|
|
names = append(names, name)
|
|
}
|
|
return names
|
|
}
|