service/feature/op.go (126 lines of code) (raw):
package feature
import (
"fmt"
"strings"
"github.com/alibaba/pairec/v2/context"
"github.com/alibaba/pairec/v2/module"
)
type FeatureOp interface {
UserTransOp(featureName string, source string, remove bool, normalizer Normalizer, user *module.User, context *context.RecommendContext)
ItemTransOp(featureName string, source string, remove bool, normalizer Normalizer, user *module.User, item *module.Item, context *context.RecommendContext)
}
func NewFeatureOp(t string) FeatureOp {
if t == "raw_feature" {
return RawFeatureOp{}
} else if t == "compose_feature" {
return ComposeFeatureOp{}
} else if t == "delete_feature" {
return DeleteFeatureOp{}
} else if t == "batch_raw_feature" {
return BatchRawFeatureOp{}
} else if t == "new_feature" {
return CreateNewFeatureOp{}
} else if t == "context_feature" {
return ContextFeatureOp{}
}
panic(fmt.Sprintf("not find feature type:%s", t))
}
type featureOp struct {
}
func (op featureOp) getRequestId(context *context.RecommendContext) string {
if nil == context {
return ""
}
return context.RecommendId
}
type RawFeatureOp struct {
featureOp
}
// UserTransOp of RawFeatureOp to Trans user feature
// it create new feature store in user properties
func (op RawFeatureOp) UserTransOp(featureName string, source string, remove bool, normalizer Normalizer, user *module.User, context *context.RecommendContext) {
comms := strings.Split(source, ":")
if len(comms) >= 2 {
value := user.StringProperty(comms[1])
user.AddProperty(featureName, value)
if remove {
user.DeleteProperty(comms[1])
}
}
}
// ItemTransOp of RawFeatureOp to Trans item or user feature
// it create new feature store in item properties
func (op RawFeatureOp) ItemTransOp(featureName string, source string, remove bool, normalizer Normalizer, user *module.User, item *module.Item, context *context.RecommendContext) {
comms := strings.Split(source, ":")
if len(comms) >= 2 {
if comms[0] == SOURCE_USER {
value := user.StringProperty(comms[1])
item.AddProperty(featureName, value)
if remove {
user.DeleteProperty(comms[1])
}
} else {
var newValue interface{}
value := item.StringProperty(comms[1])
newValue = value
if normalizer != nil {
newValue = normalizer.Apply(value)
}
item.AddProperty(featureName, newValue)
if remove {
item.DeleteProperty(comms[1])
}
}
}
}
type ComposeFeatureOp struct {
featureOp
}
func (op ComposeFeatureOp) UserTransOp(featureName string, source string, remove bool, normalizer Normalizer, user *module.User, context *context.RecommendContext) {
vals := strings.Split(source, ",")
var featureValue string
for _, val := range vals {
comms := strings.Split(val, ":")
if len(comms) >= 2 {
value := user.StringProperty(comms[1])
featureValue += "_" + value
if remove {
user.DeleteProperty(comms[1])
}
}
}
user.AddProperty(featureName, featureValue)
}
func (op ComposeFeatureOp) ItemTransOp(featureName string, source string, remove bool, normalizer Normalizer, user *module.User, item *module.Item, context *context.RecommendContext) {
vals := strings.Split(source, ",")
featureValue := featureName
for _, val := range vals {
comms := strings.Split(val, ":")
if len(comms) >= 2 {
if comms[0] == SOURCE_USER {
value := user.StringProperty(comms[1])
// item.AddProperty(featureName, value)
featureValue += "_" + value
} else {
var value string
if comms[1] == "id" {
value = string(item.Id)
} else {
value = item.StringProperty(comms[1])
}
featureValue += "_" + value
if remove {
item.DeleteProperty(comms[1])
}
}
}
}
item.AddProperty(featureName, featureValue)
}
// ContextFeatureOp add context feature to user
type ContextFeatureOp struct {
//featureOp
}
func (op ContextFeatureOp) UserTransOp(featureName string, source string, remove bool, normalizer Normalizer, user *module.User, context *context.RecommendContext) {
contextFeatures := context.GetParameter("features")
if contextFeatures != nil {
if ctxFeatures, ok := contextFeatures.(map[string]any); ok {
user.AddProperties(ctxFeatures)
}
}
}
func (op ContextFeatureOp) ItemTransOp(featureName string, source string, remove bool, normalizer Normalizer, user *module.User, item *module.Item, context *context.RecommendContext) {
}