本文汇总在 DataBuddy 特征管理全链路(建表 → 训练 → 推理 → 在线发布)中的关键最佳实践,以及最常见的异常类型、错误速查表与排错清单,帮助您规避高频陷阱并快速定位问题。
最佳实践
1. 数据类型治理:写入前统一 cast double
特征工程 SDK 不识别
decimal(p, s) 类型。若特征表中存在 decimal 列,fe.log_model 记录模型时将无法推断模型签名(signature),进而引发在线、离线推理的类型不匹配,甚至 MLmodel 文件中没有 signature 段。做法 :在写入特征表之前,把所有
decimal 列统一 cast("double"),并将该处理沉淀为可复用的工具函数,在所有建表、写入管道中统一调用。时间戳列应保留为时间类型,不要 转为字符串,否则无法用作时间戳键。2. Pipeline 铁律:预处理必须封装进 sklearn.Pipeline
所有预处理(
OneHotEncoder、StandardScaler、自定义变换等)必须 封装进 sklearn.Pipeline,把整条 Pipeline 作为 model 传给 fe.log_model。禁止 在 Pipeline 外部用
pd.get_dummies / 手动 StandardScaler.fit_transform 后再 model.fit(...):外部预处理步骤不会被序列化进 MLmodel,推理时 SDK 从特征表 lookup 出来的是原始 string 列,喂给只认 OHE 后列名的裸模型,轻则报 Feature names unseen at fit time,重则所有样本静默输出训练集均值。from sklearn.pipeline import Pipelinefrom sklearn.compose import ColumnTransformerfrom sklearn.preprocessing import OneHotEncoder, StandardScalerpreprocessor = ColumnTransformer(transformers=[("cat", OneHotEncoder(handle_unknown="ignore"), ["<categorical_feature>"]),("num", StandardScaler(), ["<numeric_feature>"]),])model = Pipeline(steps=[("preprocessor", preprocessor), ("clf", <estimator>)])
3. 模型记录:必须用 fe.log_model 且传 training_set
必须用
fe.log_model 而非 mlflow.<flavor>.log_model:只有前者会把 FeatureSpec 打包进 MLmodel,否则 score_batch 找不到特征来源。必须传
training_set,并开启 infer_input_example=True:模型签名与 input_example 由 SDK 自动推断,是部署在线推理服务的前置条件。不要 再手动
infer_signature(...) 或手动传 input_example=...,否则会与 feature_spec 的原始列错位、污染契约。4. Point-in-time 一致性:显式带上时间戳列
训练时声明了
timestamp_lookup_key 的场景下,score_batch 的输入 df 强烈建议显式带上同名时间戳列 以保证 point-in-time 一致性。若不带,SDK 会自动注入 current_timestamp() 取当前最新可见的特征,等同于用今天的特征预测历史样本,语义不严谨。如需限制回溯时间范围,在
FeatureLookup 中配合 lookback_window(非负 datetime.timedelta)使用,且必须与 timestamp_lookup_key 同时出现。5. 命名规范:统一使用三段式全限定名
引用特征表、注册模型统一使用三段式全限定名
catalog.schema.table / catalog.schema.model_name,避免依赖默认 Catalog 带来的副作用,迁移到不同工作空间时也无需改代码。异常分类
异常类型 | 触发场景 | 处理建议 |
ImportError | 运行环境中的 MLflow 版本低于 SDK 要求 | 安装带 mlflow3 extra 的 SDK,或升级 MLflow 至要求版本 |
EnvironmentError(wedata.common.utils.env_utils) | 必需环境变量未设置(项目 ID、地域、引擎名等) | 在 DataBuddy Notebook 内核中运行,或在本地配置好对应环境变量 |
KeyError | 临时密钥环境变量缺失 | 在 DataBuddy Notebook 内核中运行,或本地配置好对应环境变量 |
ValueError | 业务参数校验失败 | 按错误信息修正参数 |
RuntimeError | 底层云 API、计算资源、连接调用失败 | 查看错误信息中的 request_id,结合 DataBuddy 控制台排查 |
TencentCloudSDKException | 调用云 API 时返回错误(鉴权失败、资源不存在、限流等) | 根据 code / message / request_id 联系平台支持 |
IllegalArgumentException / Exception(PySpark) | Spark SQL 执行失败(DDL、写入、读取) | 排查 Spark 日志与表权限 |
ValueError 常见错误速查
ValueError 多由参数不合法引起,可对照错误信息快速修正:错误信息(节选) | 场景 | 修复方式 |
name must be a non-empty string | 表名、库名传入空字符串 | 检查参数 |
name '...' contains too many segments | 表名段数超过 3 | 使用 catalog.schema.table 三段式或更短形式 |
database_name '...' contains too many segments | 数据库名段数超过 2 | 使用 catalog.schema 二段式或单段名 |
catalog_name '...' conflicts with catalog '...' | 显式 catalog_name 与多段名解析结果不一致 | 二者保持一致,或仅传一种 |
Primary keys have duplicates: [...] | create_table 主键重复 | 去重;复合主键传列表而非字符串 |
Engine type ... is not supported | engine_type 不在受支持的枚举值内 | 使用 EngineTypes.ICEBERG_ENGINE 或 EngineTypes.HIVE_ENGINE |
Invalid write mode '...' | write_table 的 mode 取值非法 | 使用 append 或 overwrite |
Streaming write requires checkpoint_location parameter | 流式写入未传 checkpoint_location | 显式指定 checkpoint 路径 |
table '...' not exists | 读 / 写 / 删 / 打标的表不存在 | 先 create_table 或检查 catalog / database / 表名 |
properties must be a non-empty dictionary | 设置标签时未提供有效 key / value | 传入非空 key、value |
All properties are reserved and cannot be set: [...] | 标签 key 命中系统保留字段(如主键、时间戳键等) | 换一个非保留 key |
Either 'feature_spec' or 'feature_lookups' must be provided, but not both. | create_training_set 同时传或都不传两者 | 二者择一 |
Invalid feature_spec format | feature_spec 不是三段式 | 改成 catalog.schema.spec_name |
FeatureLookup must specify a table_name | FeatureLookup.table_name 为空 | 显式指定表名 |
When table_name '...' is a single-level name, both 'catalog_name' and 'database_name' must be provided. | FeatureLookup 用了单段表名但未补 catalog / database | 改用三段式表名(推荐),或显式传 catalog_name + database_name |
When table_name '...' is a two-level name (schema.table), 'catalog_name' must be provided. | FeatureLookup 用了两段表名但未传 catalog | 补 catalog_name 或改用三段式 |
Unexpected lookback_window value: ... | lookback_window 未配套 timestamp_lookup_key | 同时设置 timestamp_lookup_key |
only non-negative datetime.timedelta allowed. | lookback_window 不是 timedelta 或为负 | 使用非负的 datetime.timedelta(...) |
Setting multiple timestamp lookup keys is not supported. | timestamp_lookup_key 传入多元素列表 | 仅传单列名( str)或单元素列表 |
cloud_secret_id is empty / cloud_secret_key is empty | 临时密钥未注入 | 检查鉴权环境变量 |
RuntimeError 常见错误速查
RuntimeError 多与计算资源、数据源连接或云 API 调用有关,错误信息中通常带 request_id 便于定位:错误信息(节选) | 场景 | 修复方式 |
Failed to delete table '...' | 底层 DROP TABLE 失败 | 查看异常 cause、表锁 / 权限 |
Failed to modify properties for table '...' | 修改表标签失败 | 查看异常 cause |
Failed to list compute resources: no compute resources found | 工作空间无运行中的计算资源组 | 在 DataBuddy 控制台创建 / 启用数据计算资源组 |
Unable to get compute resource basic info | 资源组基础信息缺失 | 联系工作空间管理员 |
Failed to list connections: no connections found | 发布在线表时工作空间无 PostgreSQL 类型连接 | 在控制台创建 PostgreSQL 类型连接 |
Failed to create online table '...' | publish_table 调用创建在线表失败 | 凭 request_id 联系平台支持 |
Failed to drop online table | drop_online_table 失败 | 同上 |
TargetPath.CatalogName 不能为空 | 特定版本 / 环境下 publish_table 缺少在线 Catalog 信息 | 补传 online_catalog_name(具体名称参考所在工作空间已配置的在线 Catalog) |
全链路排错清单
下表按现象 → 根因 → 解决方法整理了从建表到在线发布全链路中最易踩的坑:
现象 | 根因 | 解决方法 |
MLmodel 文件中没有 signature 段 | 特征表存在 decimal(p, s) 列,SDK 类型映射不支持 | 写入前把所有 decimal 列 cast("double") |
log_model 推断 signature 失败 / score_batch 列对不上 | 使用了原生 mlflow.<flavor>.log_model,或手动传了 signature / input_example | 改用 fe.log_model(..., training_set=..., infer_input_example=True) |
ImportError: ... mlflow >= ... | 环境里的 MLflow 版本过低 | 重装带 mlflow3 extra 的 SDK |
EnvironmentError / KeyError | 本地调试缺环境变量 | 在 DataBuddy Notebook 中运行,或本地手动配置对应环境变量 |
When table_name '...' is a single-level name ... | FeatureLookup 用了单段表名但没补 catalog / db | 改三段式表名(推荐),或显式传 catalog_name + database_name |
Unexpected lookback_window value ... | lookback_window 没有配套 timestamp_lookup_key | 同时设置 timestamp_lookup_key |
only non-negative datetime.timedelta allowed. | lookback_window 不是 timedelta 或为负数 | 使用非负的 datetime.timedelta(days=N) |
Failed to list compute resources: no compute resources found | 工作空间无运行中的计算资源组 | 在 DataBuddy 控制台启动一个数据计算资源组 |
Failed to list connections: no connections found | 发布在线表时无 PostgreSQL 连接 | 在控制台先创建 PostgreSQL 类型连接 |
TargetPath.CatalogName 不能为空 | 特定版本 / 环境下 publish_table 缺少在线 Catalog 信息 | 补传 online_catalog_name(名称参考所在工作空间已配置的在线 Catalog) |
Primary keys have duplicates | create_table 主键重复 | 去重;复合主键传列表而非字符串 |
Streaming write requires checkpoint_location parameter | 流式 write_table 未传 checkpoint | 显式传 checkpoint_location |
score_batch 抛 schema 不匹配 | 推理 DataFrame 类型与训练时查出的特征类型不一致(典型: decimal vs double) | 训练前统一 cast,所有特征表存 double |
score_batch 抛 Feature names unseen at fit time,或所有样本预测值完全相同 | 训练时在 Pipeline 外裸调用了 pd.get_dummies / StandardScaler 等预处理,未被序列化进模型 | 用 sklearn.Pipeline + ColumnTransformer + OneHotEncoder(handle_unknown="ignore") 把预处理与模型一起作为 model 传给 fe.log_model |
错误处理建议
在生产化调用中,建议对不同异常类型分别捕获,便于区分参数错误与资源、云 API 错误,并保留
request_id 以便排查:from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKExceptionfrom wedata.common.utils.env_utils import EnvironmentError as WedataEnvErrortry:fe.publish_table(catalog_name="<offline_catalog_name>",schema_name="<offline_schema_name>",table_name="<offline_table_name>",online_db_name="<online_schema_name>",online_table_name="<online_table_name>",)except ValueError as e:# 业务参数错误,直接记录并返回logger.error("invalid params: %s", e)except RuntimeError as e:# 资源 / 云 API 错误,错误信息中的 request_id 可用于联系支持logger.error("publish failed: %s", e)except TencentCloudSDKException as e:logger.error("cloud api error code=%s msg=%s reqid=%s",e.get_code(), e.get_message(), e.get_request_id())except WedataEnvError as e:logger.error("env not ready: %s", e)
提示
如遇文档未覆盖的接口或异常场景,请在工单系统提单,并附上
request_id、SDK 版本与错误堆栈,便于快速定位。常见问题
Q:score_batch 提示找不到 feature_spec.yaml 怎么办?
feature_spec.yaml 是在 fe.log_model 时自动写入的。如果训练时使用的是原生 mlflow.<flavor>.log_model 而非 fe.log_model,则不会写入特征来源信息。请改用 fe.log_model 重新记录模型。Q:发布模型为在线服务时报错存在未发布为在线表的离线特征表?
Q:在线特征数据看起来比离线表落后,是什么原因?
在线特征表的数据来自同步任务,时延取决于同步方式:定时触发 受调度周期限制;持续运行 实时性最高但仍存在任务执行间隔。如对实时性有较高要求,建议在持续运行模式下配置较小的执行间隔,并监控同步任务的运行状态与延迟。