module/item.go (276 lines of code) (raw):

package module import ( "errors" "fmt" "strconv" "sync" "github.com/alibaba/pairec/v2/utils" ) type ItemId string type Item struct { Id ItemId `json:"id"` Name string `json:"name,omitempty"` Score float64 RetrieveId string ItemType string Embedding []float64 //Extra interface{} mutex sync.RWMutex Properties map[string]interface{} `json:"properties"` algoScores map[string]float64 RecallScores map[string]float64 } func NewItem(id string) *Item { item := Item{ Id: ItemId(id), Score: 0, Properties: make(map[string]interface{}, 32), } //item.algoScores = make(map[string]float64) return &item } func NewItemWithProperty(id string, properties map[string]interface{}) *Item { item := NewItem(id) for k, v := range properties { item.Properties[k] = v } return item } func (t *Item) GetRecallName() string { return t.RetrieveId } func (t *Item) GetAlgoScores() map[string]float64 { t.mutex.RLock() defer t.mutex.RUnlock() return t.algoScores } func (t *Item) GetAlgoScoreWithNames(names []string) map[string]float64 { ret := make(map[string]float64, len(names)) for _, n := range names { ret[n] = t.algoScores[n] } return ret } func (t *Item) GetAlgoScore(key string) float64 { t.mutex.RLock() defer t.mutex.RUnlock() return t.algoScores[key] } func (t *Item) IncrAlgoScore(name string, score float64) { t.mutex.Lock() defer t.mutex.Unlock() if t.algoScores == nil { t.algoScores = make(map[string]float64) } t.algoScores[name] += score } func (t *Item) CloneAlgoScores() map[string]float64 { t.mutex.RLock() defer t.mutex.RUnlock() algoScores := make(map[string]float64, len(t.algoScores)) for k, v := range t.algoScores { algoScores[k] = v } return algoScores } func (t *Item) AddProperty(key string, value interface{}) { t.mutex.Lock() defer t.mutex.Unlock() t.Properties[key] = value } func (t *Item) GetProperty(key string) interface{} { t.mutex.RLock() defer t.mutex.RUnlock() val, ok := t.Properties[key] if !ok { return nil } return val } func (t *Item) StringProperty(key string) string { t.mutex.RLock() defer t.mutex.RUnlock() val, ok := t.Properties[key] if !ok { return "" } switch value := val.(type) { case string: return value case int: return strconv.Itoa(value) case float64: return strconv.Itoa(int(value)) case int32: return strconv.Itoa(int(value)) case int64: return strconv.Itoa(int(value)) } return "" } func (t *Item) FloatProperty(key string) (float64, error) { t.mutex.RLock() defer t.mutex.RUnlock() val, ok := t.Properties[key] if !ok { return float64(0), errors.New("property key not exist") } switch value := val.(type) { case float64: return value, nil case int: return float64(value), nil case string: f, err := strconv.ParseFloat(value, 64) return f, err default: return float64(0), errors.New("unspport type") } } func (t *Item) IntProperty(key string) (int, error) { t.mutex.RLock() defer t.mutex.RUnlock() val, ok := t.Properties[key] if !ok { return int(0), errors.New("property key not exist") } switch value := val.(type) { case float64: return int(value), nil case int: return value, nil case uint: return int(value), nil case int32: return int(value), nil case int64: return int(value), nil case string: return strconv.Atoi(value) default: return int(0), errors.New("unspport type") } } func (t *Item) AddAlgoScore(name string, score float64) { t.mutex.Lock() defer t.mutex.Unlock() if t.algoScores == nil { t.algoScores = make(map[string]float64) } t.algoScores[name] = score } func (t *Item) AddAlgoScores(scores map[string]float64) { t.mutex.Lock() defer t.mutex.Unlock() if t.algoScores == nil { t.algoScores = make(map[string]float64) } for name, score := range scores { t.algoScores[name] = score } } func (t *Item) FloatExprData(name string) (float64, error) { if name == "current_score" { t.mutex.Lock() defer t.mutex.Unlock() if t.algoScores == nil { t.algoScores = make(map[string]float64) } t.algoScores["recall_score"] = t.Score return t.Score, nil } t.mutex.RLock() defer t.mutex.RUnlock() val, ok := t.algoScores[name] if ok { return val, nil } if val, ok := t.Properties[name]; ok { return utils.ToFloat(val, 0), nil } return float64(0), fmt.Errorf("not found,name:%s", name) } func (t *Item) ExprData() map[string]any { ret := make(map[string]any, len(t.algoScores)+len(t.Properties)) t.mutex.RLock() defer t.mutex.RUnlock() for k, v := range t.algoScores { ret[k] = v } for k, v := range t.Properties { ret[k] = v } return ret } func (t *Item) GetFeatures() map[string]interface{} { t.mutex.Lock() defer t.mutex.Unlock() if t.RetrieveId != "" { if _, ok := t.Properties[t.RetrieveId]; !ok { t.Properties[t.RetrieveId] = t.Score t.Properties["recall_name"] = t.RetrieveId t.Properties["recall_score"] = t.Score } } features := make(map[string]interface{}, len(t.Properties)) for k, v := range t.Properties { features[k] = v } return features } func (t *Item) AddRecallNameFeature() { t.mutex.Lock() defer t.mutex.Unlock() if t.RetrieveId != "" { if _, ok := t.Properties[t.RetrieveId]; !ok { t.Properties[t.RetrieveId] = t.Score t.Properties["recall_name"] = t.RetrieveId t.Properties["recall_score"] = t.Score } } } func (t *Item) GetProperties() map[string]interface{} { t.mutex.RLock() defer t.mutex.RUnlock() return t.Properties } func (t *Item) GetCloneFeatures() map[string]interface{} { t.mutex.Lock() defer t.mutex.Unlock() features := make(map[string]interface{}, len(t.Properties)) for k, v := range t.Properties { features[k] = v } return features } func (t *Item) DeleteProperty(key string) { t.mutex.Lock() defer t.mutex.Unlock() delete(t.Properties, key) } func (t *Item) DeleteProperties(features []string) { t.mutex.Lock() defer t.mutex.Unlock() for _, key := range features { delete(t.Properties, key) } } func (t *Item) AddProperties(properties map[string]interface{}) { t.mutex.Lock() defer t.mutex.Unlock() for key, val := range properties { t.Properties[key] = val } } func (t *Item) DeepClone() *Item { item := NewItemWithProperty(string(t.Id), t.Properties) item.Score = t.Score item.RetrieveId = t.RetrieveId item.ItemType = t.ItemType algoScores := make(map[string]float64, len(t.algoScores)) t.mutex.RLock() for k, v := range t.algoScores { algoScores[k] = v } t.mutex.RUnlock() item.algoScores = algoScores return item }