FeatureStore Go SDK

更新时间:
复制 MD 格式

概述

FeatureStore Go SDK 是人工智能平台(PAI)下特征平台(FeatureStore)的 Go 客户端 SDK,提供特征数据的高性能读取和写入。

适用场景

  • 在线推理场景快速获取特征数据

  • 实时特征写入与更新

  • 支持行为数据读取和序列特征拼接

  • 模型特征批量获取

前提条件

在使用 FeatureStore Go SDK 之前,请确保已完成以下准备工作:

* 已创建 FeatureStore 项目(Project)、特征实体(FeatureEntity)、特征视图(FeatureView)和模型特征(ModelFeature),并完成数据同步操作。具体操作,请参见 配置FeatureStore项目

* 已获取阿里云账户的 AccessKey ID 和 AccessKey Secret。具体操作,请参见 创建AccessKey

  • 建议使用本地配置环境变量的方式保存 AccessKey ID 和 AccessKey Secret,配置环境变量

  • FeatureStore Go SDK支持零信任调用,详情请参见:管理访问凭证

快速开始

FeatureStore Go SDK地址见https://github.com/aliyun/aliyun-pai-featurestore-go-sdk

执行以下命令安装 SDK:

go get github.com/aliyun/aliyun-pai-featurestore-go-sdk/v2
import (
    "os"
    featurestore "github.com/aliyun/aliyun-pai-featurestore-go-sdk/v2/featurestore"
)

accessId := os.Getenv("AccessId")
accessKey := os.Getenv("AccessKey")
regionId := "cn-hangzhou"
projectName := "fs_test_ots"

client, err := featurestore.NewFeatureStoreClient(regionId, accessId, accessKey, projectName)

如若从 FeatureDB 读写数据,需配置 FeatureDB 用户名和密码:

username := os.Getenv("FEATUREDB_USERNAME")
password := os.Getenv("FEATUREDB_PASSWORD")
client, err := featurestore.NewFeatureStoreClient(
    regionId, accessId, accessKey, projectName,
    featurestore.WithFeatureDBLogin(username, password),
)

参数介绍

参数名

类型

必填

说明

示例

regionId

String

地域ID

cn-hangzhou

accessId

String

阿里云账号 AccessKey ID

从环境变量获取

accessKey

String

阿里云账号 AccessKey Secret

从环境变量获取

projectName

String

FeatureStore 项目名称

my_project

username

String

FeatureDB 必填

FeatureDB 用户名,仅在线数据源为 FeatureDB 时需配置

featuredb_user

password

String

FeatureDB 必填

FeatureDB 密码,仅在线数据源为 FeatureDB 时需配置

featuredb_password

说明

SDK 默认直连在线数据源(如 FeatureDB),客户端需要在 VPC 环境运行才能连接。本地调试时可使用 WithTestMode() 启用公网访问,但生产环境请勿启用。

// 本地调试使用公网地址
client, err := featurestore.NewFeatureStoreClient(
    regionId, accessId, accessKey, projectName,
    featurestore.WithTestMode(),
    featurestore.WithFeatureDBLogin(username, password),
)

可选配置项

配置项

用途

示例

WithFeatureDBLogin()

FeatureDB 认证信息

featurestore.WithFeatureDBLogin("admin", "pwd")

WithTestMode()

本地调试,使用公网地址

featurestore.WithTestMode()

读取功能

获取 FeatureView 特征数据

通过 FeatureView 获取在线特征数据,支持离线特征、实时特征和序列特征的读取。

接口说明

GetOnlineFeatures(joinIds []interface{}, features []string, alias map[string]string) ([]map[string]interface{}, error)

参数说明

参数名

类型

必填

说明

joinIds

[]interface{}

join_id 值列表,用于查询特征数据

features

[]string

需要返回的特征字段列表,[]string{"*"} 返回全部字段

alias

map[string]string

特征字段别名映射,返回数据时显示别名

示例

project, err := client.GetProject("fs_test_ots")
if err != nil {
    log.Fatal(err)
}

userFeatureView := project.GetFeatureView("user_fea")
if userFeatureView == nil {
    log.Fatal("feature view not exist")
}

features, err := userFeatureView.GetOnlineFeatures(
    []interface{}{"100043186", "100060369"},
    []string{"*"},
    nil,
)
  • 离线/实时FeatureView特征数据示例结果

    [
        {
            "city":"合肥市",
            "follow_cnt":1,
            "gender":"male",
            "user_id":"100043186"
        },
        {
            "city":"",
            "follow_cnt":5,
            "gender":"male",
            "user_id":"100060369"
        }
    ]
  • 序列特征FeatureView特征数据示例结果

    • 假设序列特征读取配置如下

      离线序列特征字段

      事件名称

      序列长度

      在线序列特征名称

      click_seq_50_seq

      click

      50

      click_seq_50_seq

      expr_seq_100_seq

      expr

      100

      expr_seq_100

    • 返回示例结果

      [
        {
          "click_seq_50_seq": "216751275;228787053;220852269;242884721",
          "click_seq_50_seq__event": "click;click;click;click",
          "click_seq_50_seq__event_time": "1699128398;1699128398;1699118623;1699118623",
          "click_seq_50_seq__item_id": "216751275;228787053;220852269;242884721",
          "click_seq_50_seq__playtime": "65.40;72.06;104.69;62.74",
          "click_seq_50_seq__ts": "389018;389018;398793;398793",
          "expr_seq_100": "207474427;216751275;228787053;247136848;270584471;299485479;220852269;242884721;245999124;265863707",
          "expr_seq_100__event": "expr;expr;expr;expr;expr;expr;expr;expr;expr;expr",
          "expr_seq_100__event_time": "1699128398;1699128398;1699128398;1699128398;1699128398;1699128398;1699118623;1699118623;1699118623;1699118623",
          "expr_seq_100__item_id": "207474427;216751275;228787053;247136848;270584471;299485479;220852269;242884721;245999124;265863707",
          "expr_seq_100__playtime": "0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00;0.00",
          "expr_seq_100__ts": "389018;389018;389018;389018;389018;389018;398793;398793;398793;398793",
          "user_id": "186569075"
        },
        {
          "click_seq_50_seq": "201741544;236327912;293320498",
          "click_seq_50_seq__event": "click;click;click",
          "click_seq_50_seq__event_time": "1699178245;1699178245;1699178245",
          "click_seq_50_seq__item_id": "201741544;236327912;293320498",
          "click_seq_50_seq__playtime": "97.41;70.32;135.21",
          "click_seq_50_seq__ts": "339171;339171;339171",
          "expr_seq_100": "201741544;224940066;236327912;240253906;247562151;293320498",
          "expr_seq_100__event": "expr;expr;expr;expr;expr;expr",
          "expr_seq_100__event_time": "1699178245;1699178245;1699178245;1699178245;1699178245;1699178245",
          "expr_seq_100__item_id": "201741544;224940066;236327912;240253906;247562151;293320498",
          "expr_seq_100__playtime": "0.00;0.00;0.00;0.00;0.00;0.00",
          "expr_seq_100__ts": "339171;339171;339171;339171;339171;339171",
          "user_id": "186569870"
        }
      ]

获取 ModelFeature 关联特征

通过 Model 获取关联的所有 FeatureEntity 特征数据,支持上级-下级 Entity 层级关系。

接口说明

// 获取所有根实体及其关联的下级实体特征
GetOnlineFeatures(joinIds map[string][]interface{}) ([]map[string]interface{}, error)

// 获取指定 Entity 及其下级 Entity 特征
GetOnlineFeaturesWithEntity(joinIds map[string][]interface{}, featureEntityName string) ([]map[string]interface{}, error)

参数说明

参数名

类型

必填

说明

joinIds

map[string][]interface{}

join_id 映射,key 为 join_id 名称,value 为值列表

featureEntityName

string

指定获取某个 FeatureEntity 的特征数据

Entity 层级关系

ModelFeature 可关联多个 FeatureEntity,存在上下级嵌套关系:

* 上级 Entity:包含主特征字段 + 关联下级 Entity 的字段

* 下级 Entity:被上级 Entity 引用,包含独立的特征字段

image

获取特征时,只需传入根实体的 join_id,SDK 会自动根据上级实体的特征值获取下级实体的特征。

不同场景示例

场景1:获取 Model 关联的全部特征

调用 GetOnlineFeatures 传入所有根实体的 join_id,SDK 自动获取 Model 关联的全部特征(包括下级实体)。

model := project.GetModelFeature("model_fv1")
if model == nil {
    t.Fatal("model feature not exist")
}
// 传入所有根实体的 join_id
joinIds := map[string][]interface{}{
    "user_id": {"U001", "U002", "U003"},
    "item_id": {"1001", "1002", "1003"},
}

// 会一并获取所有根实体及其关联下级实体的特征
features, err := model.GetOnlineFeatures(joinIds)

返回示例:

{
  "item_id": "1001",
  "item_title": "智能手表",
  "item_price": 299.00,
  "author_id": "A001",
  "author_name": "张三",
  "author_fans_count": 10000,
  "category_id": "C001",
  "category_name": "电子产品",
  "category_level": 1,
  "user_id": "U001",
  "user_age": 28,
  "user_gender": "male"
}

场景2:获取指定 Entity 侧特征(含下级实体)

调用 GetOnlineFeaturesWithEntity 指定 Entity 名称,获取该 Entity 及其下级实体特征。示例中 item Entity 关联 author、category 两个下级实体,返回 item 侧全部特征。

joinIds := map[string][]interface{}{
    "item_id": {"1001", "1002", "1003"},
}

// 指定获取 item Entity 的特征
// item侧关联下级实体 author、category,一并返回
features, err := model.GetOnlineFeaturesWithEntity(joinIds, "item")

返回示例:

{
  "item_id": "1001",
  "item_title": "智能手表",
  "item_price": 299.00,
  "author_id": "A001",
  "author_name": "张三",
  "author_fans_count": 10000,
  "category_id": "C001",
  "category_name": "电子产品",
  "category_level": 1
}

场景3:获取指定 Entity 侧特征(无下级实体)

调用 GetOnlineFeaturesWithEntity 指定实体名称,获取该实体特征。示例中 author 实体无下级实体,只返回 author 本身的特征字段。

joinIds := map[string][]interface{}{
    "author_id": {"A001", "A002", "A003"},
}

// 指定获取 author Entity 的特征
// author侧无下级实体,只返回 author侧特征
features, err := model.GetOnlineFeaturesWithEntity(joinIds, "author")

返回示例:

{
  "author_id": "A001",
  "author_name": "张三",
  "author_fans_count": 10000
}

ModelFeature 包含序列特征示例

当 ModelFeature 关联序列特征 FeatureView 时,返回数据中会包含序列特征字段:

序列特征对应FeatureEntity一般为user,示例中有两个join_iduser_iditem_id。获取特征的时候需要设置相同的ID数量。

  • 假设序列特征读取配置如下:

    离线序列特征字段

    事件名称

    序列长度

    在线序列特征名称

    click_seq_50_seq

    click

    50

    click_seq_50_seq

    // get ModelFeature by name
    model := project.GetModelFeature("model_with_seq")
    if model == nil {
        t.Fatal("model feature not exist")
    }
    
    joinIds := map[string][]interface{}{
        "user_id": {"186569075", "186569870"},
        "item_id": {"299485479", "207474427"},
    }
    
    // get online features
    features, err := model.GetOnlineFeatures(joinIds)
  • 返回示例结果

    [
      {
        "age": 51,
        "author": 147848300,
        "category": "7",
        "city": "",
        "click_count": 0,
        "click_seq_50_seq": "216751275;228787053;220852269;242884721",
        "click_seq_50_seq__event": "click;click;click;click",
        "click_seq_50_seq__event_time": "1699128398;1699128398;1699118623;1699118623",
        "click_seq_50_seq__item_id": "216751275;228787053;220852269;242884721",
        "click_seq_50_seq__playtime": "65.40;72.06;104.69;62.74",
        "click_seq_50_seq__ts": "391447;391447;401222;401222",
        "duration": 48,
        "follow_cnt": 2,
        "follower_cnt": 0,
        "gender": "female",
        "item_cnt": 0,
        "item_id": 299485479,
        "praise_count": 2,
        "pub_time": 1697885713,
        "register_time": 1696582012,
        "tags": "0",
        "title": "#健身打卡",
        "user_id": "186569075"
      },
      {
        "age": 28,
        "author": 119734983,
        "category": "18",
        "city": "",
        "click_count": 0,
        "click_seq_50_seq": "201741544;236327912;293320498",
        "click_seq_50_seq__event": "click;click;click",
        "click_seq_50_seq__event_time": "1699178245;1699178245;1699178245",
        "click_seq_50_seq__item_id": "201741544;236327912;293320498",
        "click_seq_50_seq__playtime": "97.41;70.32;135.21",
        "click_seq_50_seq__ts": "341600;341600;341600",
        "duration": 15,
        "follow_cnt": 0,
        "follower_cnt": 2,
        "gender": "male",
        "item_cnt": 0,
        "item_id": 207474427,
        "praise_count": 79,
        "pub_time": 1697731285,
        "register_time": 1699135393,
        "tags": "1",
        "title": "#成语故事",
        "user_id": "186569870"
      }
    ]

写入功能

将特征数据实时写入 FeatureDB 数据源,支持实时特征和序列特征的写入。

适用场景

  • 实时更新用户特征(如在线特征更新)

  • 写入用户行为序列数据(点击、播放等事件)

  • 实时特征数据的部分字段更新(不影响其他字段)

说明

目前写入接口仅支持在线数据源为 FeatureDB 的实时特征视图和行为序列特征视图,需配置 FeatureDB 用户名和密码。

实时特征写入

整行更新

project, err := client.GetProject("test_pro1")
if err != nil {
    log.Fatal(err)
}

featureView := project.GetFeatureView("user_feature_view")
if featureView == nil {
    t.Fatal("feature view not exist")
}

// 构造写入数据
writeData := make([]map[string]interface{}, 0)
record := map[string]interface{}{
    "user_id":  "user_001",
    "name":     "张三",
    "age":      28,
    "city":     "北京",
}
writeData := append(writeData, record)
// 写入数据
featureView.WriteFeatures(writeData)

// 强制刷新(确保数据完成写入)
featureView.WriteFlush()

方法

参数

必填

说明

WriteFeatures

[]map[string]interface{}

批量写入数据

WriteFlush

-

确保数据完成写入(调用后不能再写入)

部分字段更新

默认整行替换,部分字段更新需指定 InsertMode:

import "github.com/aliyun/aliyun-pai-featurestore-go-sdk/v2/constants"

record = map[string]interface{}{
    "user_id":  "user_001",
    "name":     "李四",
}
writeData := append(writeData, record)
featureView.WriteFeaturesWithInsertMode(writeData, constants.Partial_Field_Write)
// 强制刷新(确保数据完成写入)
featureView.WriteFlush()

序列特征写入

序列特征写入用于实时记录用户行为事件(点击、播放、购买等),支持在线推理场景的行为序列特征构建。

示例

sequenceFeatureView := project.GetFeatureView("sequence")
if sequenceFeatureView == nil {
    t.Fatal("sequence featureview not found")
}

// 构造序列数据
sequenceWriteData := make([]map[string]interface{}, 0)
for i := 0; i < 10; i++ {
    data := make(map[string]interface{})
    data["request_id"] = int64(901850344 + i)
    data["user_id"] = fmt.Sprintf("%d", 1000+i+1)
    data["page"] = "home"
    data["net_type"] = "wifi"
    data["day_h"] = 17
    data["week_day"] = 6
    data["event_unix_time"] = time.Now().Unix()
    data["item_id"] = fmt.Sprintf("22346678%d", i)
    data["event"] = "click"
    data["playtime"] = 54.7296554003366 + float64(i)
    sequenceWriteData = append(sequenceWriteData, data)
}

err = sequenceFeatureView.WriteFeatures(sequenceWriteData)
if err != nil {
    t.Fatal(err)
}
sequenceFeatureView.WriteFlush()

相关文档