65 lines
1.9 KiB
Go
65 lines
1.9 KiB
Go
package platformsettings
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"github.com/descrybe/descrybe-v2/apps/api/internal/processing"
|
||
|
|
)
|
||
|
|
|
||
|
|
// DynamicPinecone resolves platform settings on each call so admin changes
|
||
|
|
// apply without restarting the worker. Embeddings use admin AI role
|
||
|
|
// "vectorization" (ResolveAIConfig) with OPENAI_EMBEDDING_* / OPENAI_* env fallback.
|
||
|
|
type DynamicPinecone struct {
|
||
|
|
Settings *Service
|
||
|
|
}
|
||
|
|
|
||
|
|
func (d *DynamicPinecone) Enabled() bool {
|
||
|
|
if d == nil || d.Settings == nil {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
cfg, err := d.Settings.ResolvePinecone(context.Background())
|
||
|
|
return err == nil && cfg.Configured()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (d *DynamicPinecone) SuggestCategory(ctx context.Context, companyID, productText string, candidates []string) (string, error) {
|
||
|
|
if d == nil || d.Settings == nil {
|
||
|
|
return "", errors.New("pinecone not configured")
|
||
|
|
}
|
||
|
|
cfg, err := d.Settings.ResolvePinecone(ctx)
|
||
|
|
if err != nil {
|
||
|
|
return "", err
|
||
|
|
}
|
||
|
|
if !cfg.Configured() {
|
||
|
|
return "", errors.New("pinecone not configured")
|
||
|
|
}
|
||
|
|
cat := processing.NewPineconeCategorizer(cfg.APIKey, cfg.Host, cfg.Namespace)
|
||
|
|
if emb, eerr := d.Settings.ResolveEmbedder(ctx); eerr == nil && emb != nil {
|
||
|
|
cat.Embedder = emb
|
||
|
|
}
|
||
|
|
return cat.SuggestCategory(ctx, companyID, productText, candidates)
|
||
|
|
}
|
||
|
|
|
||
|
|
// ResolveEmbedder builds an OpenAI-compatible Embedder from admin AI role
|
||
|
|
// "vectorization" (DB), falling back to OPENAI_EMBEDDING_* then OPENAI_* env.
|
||
|
|
// Returns (nil, nil) when unset so callers can keep Pinecone text-query mode.
|
||
|
|
func (s *Service) ResolveEmbedder(ctx context.Context) (processing.Embedder, error) {
|
||
|
|
if s == nil {
|
||
|
|
return nil, nil
|
||
|
|
}
|
||
|
|
cfg, err := s.ResolveAIConfig(ctx, AIRoleVectorization)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
if strings.TrimSpace(cfg.APIKey) == "" {
|
||
|
|
return nil, nil
|
||
|
|
}
|
||
|
|
model := strings.TrimSpace(cfg.Model)
|
||
|
|
if model == "" {
|
||
|
|
model = defaultEmbeddingModel
|
||
|
|
}
|
||
|
|
client := processing.NewOpenAIClient(cfg.APIKey, cfg.BaseURL, model, 0, 3)
|
||
|
|
return client, nil
|
||
|
|
}
|