service/recall/recall.go (116 lines of code) (raw):
package recall
import (
"encoding/json"
"fmt"
"github.com/alibaba/pairec/v2/context"
"github.com/alibaba/pairec/v2/log"
"github.com/alibaba/pairec/v2/module"
"github.com/alibaba/pairec/v2/persist/cache"
"github.com/alibaba/pairec/v2/recconf"
"github.com/alibaba/pairec/v2/utils"
)
type Recall interface {
GetCandidateItems(user *module.User, context *context.RecommendContext) []*module.Item
}
var recalls = make(map[string]Recall)
var recallSigns = make(map[string]string)
func RegisterRecall(name string, recall Recall) {
recalls[name] = recall
}
func GetRecall(name string) (Recall, error) {
recall, ok := recalls[name]
if !ok {
return nil, fmt.Errorf("recall:not found, recall name:%s", name)
}
if recall == nil {
return nil, fmt.Errorf("recall is nil, recall name:%s", name)
}
return recall, nil
}
func Load(config *recconf.RecommendConfig) {
for _, conf := range config.RecallConfs {
if _, ok := recalls[conf.Name]; ok {
sign, _ := json.Marshal(&conf)
if utils.Md5(string(sign)) == recallSigns[conf.Name] {
continue
}
}
var recall Recall
if conf.RecallType == "UserCollaborativeFilterRecall" {
recall = NewUserCollaborativeFilterRecall(conf)
} else if conf.RecallType == "UserTopicRecall" {
recall = NewUserTopicRecall(conf)
} else if conf.RecallType == "VectorRecall" {
recall = NewVectorRecall(conf)
} else if conf.RecallType == "UserCustomRecall" {
recall = NewUserCustomRecall(conf)
} else if conf.RecallType == "HologresVectorRecall" {
recall = NewHologresVectorRecall(conf)
} else if conf.RecallType == "HologresVectorRecallV2" {
recall = NewHologresVectorRecallV2(conf)
} else if conf.RecallType == "ItemCollaborativeFilterRecall" {
recall = NewItemCollaborativeFilterRecall(conf)
} else if conf.RecallType == "UserGroupHotRecall" {
recall = NewUserGroupHotRecall(conf)
} else if conf.RecallType == "UserGlobalHotRecall" {
recall = NewUserGlobalHotRecall(conf)
} else if conf.RecallType == "I2IVectorRecall" {
recall = NewI2IVectorRecall(conf)
} else if conf.RecallType == "ColdStartRecall" {
recall = NewColdStartRecall(conf)
} else if conf.RecallType == "MilvusVectorRecall" {
//recall = NewMilvusVectorRecall(conf)
} else if conf.RecallType == "BeRecall" {
recall = NewBeRecall(conf)
} else if conf.RecallType == "RealTimeU2IRecall" {
recall = NewRealTimeU2IRecall(conf)
} else if conf.RecallType == "OnlineHologresVectorRecall" {
recall = NewOnlineHologresVectorRecall(conf)
} else if conf.RecallType == "GraphRecall" {
recall = NewGraphRecall(conf)
} else if conf.RecallType == "MockRecall" {
recall = NewMockRecall(conf)
} else if conf.RecallType == "OpenSearchRecall" {
recall = NewOpenSearchRecall(conf)
} else if conf.RecallType == "OnlineVectorRecall" {
recall = NewOnlineVectorRecall(conf)
}
if recall == nil {
panic(fmt.Sprintf("recall empty, name:%s", conf.Name))
}
RegisterRecall(conf.Name, recall)
sign, _ := json.Marshal(&conf)
recallSigns[conf.Name] = utils.Md5(string(sign))
}
}
type BaseRecall struct {
modelName string
cache cache.Cache
cachePrefix string
cacheTime int
itemType string
recallCount int
recallAlgo string
}
func NewBaseRecall(config recconf.RecallConfig) *BaseRecall {
recall := &BaseRecall{
modelName: config.Name,
itemType: config.ItemType,
recallCount: config.RecallCount,
recallAlgo: config.RecallAlgo,
}
if len(config.CacheAdapter) > 0 {
cache, err := cache.NewCache(config.CacheAdapter,
config.CacheConfig)
if err != nil {
log.Error(fmt.Sprintf("error=%v", err))
} else {
recall.cache = cache
recall.cachePrefix = config.CachePrefix
recall.cacheTime = 1800
if config.CacheTime > 0 {
recall.cacheTime = config.CacheTime
}
}
}
return recall
}