PAI-Rec 引擎诊断与配置校验
本 Skill 为阿里云 PAI-Rec(可编程推荐系统)引擎提供全面的诊断和校验能力,包括接口排查和配置分析。
场景说明
PAI-Rec 是阿里云的可编程推荐系统,提供智能推荐能力。本 Skill 帮助用户:
- 诊断 PAI-Rec 引擎接口问题:当引擎 API 返回错误或意外结果时,通过 EAS 服务日志和引擎配置追踪请求以定位根因。
- 校验引擎配置:在部署前分析引擎配置文件是否存在潜在问题、不一致或错误配置。
架构:PAI-EAS 服务 + PAI-Rec 引擎 + 引擎配置管理
关键组件
- PAI-EAS 服务:托管推荐引擎的弹性算法服务
- PAI-Rec 引擎:处理请求的推荐引擎
- 引擎配置:定义引擎行为的配置文件
- 服务日志:含请求追踪的 EAS 服务日志
安装
前置检查:需要 Aliyun CLI >= 3.3.3
运行aliyun version确认 >= 3.3.3。若未安装或版本过低,
运行curl -fsSL https://aliyuncli.alicdn.com/setup.sh | bash安装 / 更新,
或见references/cli-installation-guide.md获取安装说明。
前置检查:需要更新 Aliyun CLI 插件
[必须] 运行aliyun configure set --auto-plugin-install true启用插件自动安装。
[必须] 运行aliyun plugin update确保已有插件始终为最新版本。
鉴权
前置检查:需要阿里云凭证
安全规则:
- 绝不读取、回显或打印 AK/SK 值(例如echo $ALIBABA_CLOUD_ACCESS_KEY_ID是禁止的)
- 绝不要求用户在对话或命令行中直接输入 AK/SK
- 绝不使用字面凭证值运行aliyun configure set
- 只使用aliyun configure list检查凭证状态
```bash
aliyun configure list
```
检查输出中是否有有效 profile(AK、STS 或 OAuth 身份)。
如果不存在有效 profile,就此停止。
1. 从阿里云控制台获取凭证
2. 在本会话之外配置凭证(通过终端中的aliyun configure或 shell profile 中的环境变量)
3. 待aliyun configure list显示有效 profile 后再返回并重试
RAM 策略
[必须] 权限失败处理: 当任何命令或 API 调用在执行过程中因权限错误失败时,遵循以下流程:
1. 阅读references/ram-policies.md获取本 Skill 所需的完整权限列表
2. 使用ram-permission-diagnoseskill 引导用户申请必要权限
3. 暂停并等待用户确认所需权限已授予
本 Skill 所需的详细 RAM 策略见 references/ram-policies.md。
参数确认
重要:参数确认 —— 执行任何命令或 API 调用前,
所有用户可自定义的参数(例如 RegionId、服务名、实例 ID、
环境名、配置名等)都必须与用户确认。
未经用户明确批准,不要假设或使用默认值。
必需参数
| 参数名 | 必填 / 可选 | 说明 | 默认值 |
|---|---|---|---|
service-name | 必填 | PAI-EAS 服务名 | 无 |
cluster-id | 必填 | EAS 集群 / 地域 ID | 无 |
instance-id | 必填 | PAI-Rec 实例 ID | 无 |
request-id | 必填(诊断用) | 引擎 API 响应中的请求 ID | 无 |
config-name | 可选 | 引擎配置名 | 无 |
environment | 可选 | 引擎环境(Prod/Pre) | 无 |
engine-config-id | 可选 | 特定引擎配置版本 ID | 无 |
region | 可选 | 阿里云地域 | 无 |
可观测性(每条 aliyun 命令都必须遵守)
加载本 Skill 时,为整个会话生成一次随机 session ID(32 字符小写十六进制字符串)。在下方用作 {session-id}。
规则:每条调用云 API 的 aliyun CLI 命令都必须包含 --user-agent 标志。
本地工具命令(如 configure、plugin、version)不支持该标志,应排除。
--user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-rec-diagnosis/{session-id}
示例(假设 session-id 为 a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6):
aliyun eas describe-service --cluster-id cn-hangzhou --service-name my_service --user-agent AlibabaCloud-Agent-Skills/alibabacloud-pai-rec-diagnosis/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
在任何 aliyun API 命令调用上,都不要跳过、改变格式或省略 --user-agent。
核心工作流
[必须] 分配每会话工作目录 —— 所有临时工件
(原始配置转储、日志转储、脱敏输出)必须写在唯一的
每会话目录下,以避免并行 Skill 调用之间的并发覆盖。在
工作流开始时、任何产生工件的 CLI 调用之前运行以下命令,并在整个会话中复用$WORKDIR。
将完整模板作为位置参数传入(在 BSD/macOS 和
GNU/Linuxmktemp上都可用);不要使用-t prefix,它会回退到$TMPDIR
(例如 macOS 上的/var/folders),甚至在沙箱 shell 中可能失败。
```bash
export WORKDIR=$(mktemp -d /tmp/pairec-diag-XXXXXX)
```
下方显示的所有文件路径($WORKDIR/engine_configs_list.json等)都位于
此目录内,不得替换为硬编码的/tmp/...路径。
[必须] 只使用下方定义的工作流。 不要发明额外
步骤(例如实例资源检查、网络探测),也不要用人工分析替代已定义的工作流步骤。
工作流 1:PAI-Rec 引擎接口诊断
此工作流帮助诊断 PAI-Rec 引擎 API 返回错误或意外结果时的问题。
输入示例:
服务名:embedding_recall
API 响应:
{
"code": 299,
"msg": "items size not enough",
"request_id": "941b4e14-d1c5-489f-a184-b2b17f8b4fdb",
"size": 0,
"experiment_id": "",
"items": []
}
#### 步骤 1:获取 EAS 服务信息
获取服务详情以找到 EAS 服务 ID 和配置:
aliyun eas describe-service \
--cluster-id <cluster-id> \
--service-name <service-name>
要提取的内容:
Resource:EAS 服务资源 ID(例如eas-r-1v4qb1yan3qmnjwxqe)ServiceConfig.envs:包含以下内容的环境变量:REGION:地域INSTANCE_ID:PAI-Rec 实例 IDCONFIG_NAME:引擎配置名PAIREC_ENVIRONMENT:环境(product/prepub)
#### 步骤 2:从 API 响应提取请求 ID
解析 API 响应 JSON 获取 request_id 字段。这将用于搜索服务日志。
#### 步骤 3:查询 EAS 服务日志
用请求 ID 作为搜索服务日志的唯一过滤条件。搜索 PAI-Rec 业务日志时不要传 --start-time / --end-time:
aliyun eas describe-service-log \
--cluster-id <cluster-id> \
--service-name <service-name> \
--keyword <request-id> \
--page-size 500
[关键] --keyword <request-id> 是强制的——禁止本地后处理:
- 你必须传
--keyword <request-id>(服务端过滤,对完整request_id精确大小写敏感匹配)。API 只返回匹配关键词的日志行。 - 你不得省略
--keyword然后本地过滤(例如通过head、grep、python3、jq或任何脚本管道)。 - 你不得在没有
--keyword的情况下多次调用describe-service-log,希望通过扫描完整日志流找到相关行。 - 如果带
--keyword的调用返回空结果,报告未找到匹配日志——不要回退到获取未过滤日志。 --page-size500 在单页捕获整个追踪;一个请求的匹配条目通常 < 30。
❌ 错误(获取所有日志,本地过滤——禁止):
```bash
aliyun eas describe-service-log --cluster-id cn-beijing --service-name embedding_recall | head -300
aliyun eas describe-service-log --cluster-id cn-beijing --service-name embedding_recall | grep "request_id"
```
✅ 正确(服务端关键词过滤——必需):
```bash
aliyun eas describe-service-log --cluster-id cn-beijing --service-name embedding_recall --keyword 0c6cbd91-5618-4705-8e08-9126bf4600f7 --page-size 500
```
[关键] 时间范围会静默丢弃业务日志:
- 仅
--keyword(无时间范围)时,CLI 返回匹配 request_id 的完整 PAI-Rec 应用追踪(controller.go/feed.go/recall.go/rank_service.go等)。 - 加
--start-time/--end-time——即使窗口覆盖真实时间戳——也会静默丢弃业务日志,只返回基础设施噪音(/bin/sh心跳、502 Bad Gateway重试、postgres.go dbstat)。 - 仅对无
--keyword的宽泛扫描使用时间范围,格式为yyyy-MM-dd HH:mm:ssUTC(无T/ 无Z);ISO-8601 形式如2025-04-28T00:00:00Z会被拒绝并报InvalidParameter。
#### 步骤 4:列出引擎配置
映射环境并列出匹配配置:
环境映射:
product→Prodprepub→Pre
aliyun pairecservice list-engine-configs \
--instance-id <instance-id> \
--environment <Prod|Pre> \
--status Released \
--name <config-name> > "$WORKDIR/engine_configs_list.json" 2>&1
[必须] 始终传 --name <config-name> 做服务端过滤:
<config-name> 已从步骤 1 得知(ServiceConfig.envs.CONFIG_NAME);将其作为 --name 转发。省略它会返回整个实例的配置清单(常数百个无关条目),强制客户端过滤,浪费 token,并有触及 CLI 默认分页导致目标行被静默丢弃的风险。--name 是服务端的精确匹配过滤;不要用 grep / jq select 后处理替代。同一规则适用于本 Skill 中每次 list-engine-configs 调用(包括工作流 2 步骤 1)。
要提取的内容:
- 找到
Status: Released的配置 - 获取
EngineConfigId和Version
#### 步骤 5:获取引擎配置详情
aliyun pairecservice get-engine-config \
--instance-id <instance-id> \
--engine-config-id <engine-config-id> > "$WORKDIR/raw_engine_config.json" 2>&1
[必须] 展示前脱敏 —— 配置可能含明文密码或
访问密钥。打印到终端前始终通过脱敏器管道;只有脱敏输出
(凭据替换为 *REDACTED*)才应出现在那里。原始文件
$WORKDIR/raw_engine_config.json 可直接传给 scripts/validate.py(它不打印凭据值)。
python3 scripts/sanitize_config.py "$WORKDIR/raw_engine_config.json"
要提取的内容:
ConfigValue:实际引擎配置(JSON/YAML)
#### 步骤 5.5(可选):静态配置健全性检查
对检索到的 ConfigValue 运行 scripts/validate.py 以排除结构性 /
引用错误。见 references/config-validation.md。
printf '%s' "$CONFIG_VALUE" | python3 scripts/validate.py --stdin
何时运行:当日志指向某配置元素,或首次诊断该配置时。
何时跳过:当日志显示非配置根因(缺少 scene_id、上游 5xx)时。
[不得] 不要替换或重复 validate.py(与工作流 2 § 步骤 3 相同限制)。
[必须] 范围规则: 发现仅在绑定到当前 request_id 的日志证据时才进入最终诊断。
#### 步骤 5a(条件性):检索实验配置
条件: API 响应中 experiment_id 非空(例如 "ER14_L21_L26#EG21_L38#EG38#E44_GL36_GL37")。
解析: 从字符串提取 EG{id}(实验组)和 E{id}(实验)数字 ID。忽略 ER、L、GL 前缀——它们不携带配置。
对每个 EG{id}:
aliyun pairecservice get-experiment-group \
--instance-id <instance-id> \
--experiment-group-id <id> > "$WORKDIR/experiment_group_<id>.json" 2>&1
对每个 E{id}:
aliyun pairecservice get-experiment \
--instance-id <instance-id> \
--experiment-id <id> > "$WORKDIR/experiment_<id>.json" 2>&1
**要提取的内容:** `Config` 字段——包含覆盖参数(例如 `default.RecallNames`、`rankconf`、`filterNames`、`default.SortNames`),它们取代基础引擎配置。
**覆盖优先级(低 → 高):** 基础引擎配置 < ExperimentGroup.Config < Experiment.Config。在步骤 6 应用以理解实际运行时行为。
**校验实验配置** 相对基础配置(引用存在性检查):
python3 scripts/validate.py "$WORKDIR/raw_engine_config.json" \
--experiment-config "$WORKDIR/experiment_group_<id>.json" \
--experiment-config "$WORKDIR/experiment_<id>.json"
#### 步骤 6:综合分析
一起分析以下组件:
1. **API 响应**:错误码、消息和返回数据
2. **服务日志**:request_id 的追踪日志,显示处理流程
3. **引擎配置**:可能影响行为的设置
4. **实验覆盖**(若 `experiment_id` 非空):有效配置 = 基础配置叠加实验参数
**要检查的常见问题:**
- 配置不匹配(例如召回设置、过滤规则)
- 实验覆盖(例如实验从基础配置改变了 `RecallNames` / `rankconf`)
- 资源限制(例如条目不足、超时设置)
- 数据源问题(例如表访问、特征可用性)
- 环境不一致(例如 prepub 环境用了 prod 配置)
**[必须] 仅证据报告规则:**
交付给用户的最终诊断**必须**严格基于 EAS 服务日志和引擎配置直接显示的内容。应用以下约束:
- **只报告观察到的。** 引用证明每个论断的确切日志行(文件:行号、级别、消息)和确切配置片段。
- **陈述从日志证据到 API 响应的直接因果链**,就此打住。
- **不要添加**以下任何内容,除非用户明确要求:
- 日志 / 配置中不可见的推测性根因(例如"客户端可能发了错误的 X")
- 修复建议或补救步骤
- 条件性"如果 X 则 Y"场景
- 无关的最佳实践建议(安全、兜底设计、命名等)
- 对日志 / 配置未覆盖的上游系统、客户端代码或数据源的猜测
- **如果证据不足以得出结论**,明确说明需要什么额外数据(特定日志行、其他配置版本、其他环境),而非猜测。
- **建议仅限主动请求。** 仅在用户在后续明确要求时才提供修复 / 建议。
---
### 工作流 2:PAI-Rec 引擎配置校验
此工作流校验引擎配置是否存在潜在问题。
**输入:** 配置名和环境(Prod/Pre)
#### 步骤 1:列出配置版本
如果用户未提供 `engine-config-id`,列出可用版本:
aliyun pairecservice list-engine-configs \
--instance-id <instance-id> \
--environment <Prod|Pre> \
--name <config-name>
**向用户展示:**
- `Version`:版本号
- `Status`:配置状态(Released/Draft/Archived)
- `GmtCreateTime`:创建时间戳
- `EngineConfigId`:版本 ID
请用户选择版本或提供 `engine-config-id`。
#### 步骤 2:获取配置详情
aliyun pairecservice get-engine-config \
--instance-id <instance-id> \
--engine-config-id <engine-config-id> > "$WORKDIR/raw_engine_config.json" 2>&1
**[必须] 展示前脱敏** —— 打印到终端前始终脱敏:
python3 scripts/sanitize_config.py "$WORKDIR/raw_engine_config.json"
#### 步骤 3:运行 Schema + 规则校验
**[必须]** 将提取的 `ConfigValue` JSON 喂给 `scripts/validate.py`。该脚本
强制执行 JSON Schema(`references/schema.json`)+ 引用一致性规则,通过时退出
状态 0,失败时 1。
从保存的 JSON 文件(推荐)
python3 scripts/validate.py "$WORKDIR/raw_engine_config.json"
或通过 stdin 直接管道 ConfigValue
printf '%s' "$CONFIG_VALUE" | python3 scripts/validate.py --stdin
需要 `jsonschema`(`pip install jsonschema`);若缺失,脚本回退到
仅规则校验而不做 Schema 检查。
**[不得] 不要替换或重复 `validate.py`:**
- 不要跳过它;不要用 Python / jq / grep / 任何其他工具手写等价检查——该脚本是权威校验器。
- 脚本运行后不要重新实现、重新检查或"双重确认"任何规则;逐字信任其输出,包括干净的 `0 error(s), 0 warning(s)` 运行。
- 如果脚本无法运行(缺少 Python、依赖问题等),修复环境并重跑——不要回退到手动检查。
- 脚本范围之外的检查仍允许(见步骤 4)。
**脚本检查内容(摘要):**
1. **结构** —— JSON 良构性、必填字段、类型(`RecallConfs`、
`FilterConfs`、`SortConfs`、`AlgoConfs`、`SceneConfs`、`RankConf`、
`FeatureConfs`、`UserFeatureConfs`、`DebugConfs`、`FeatureLogConfs`、
`CallBackConfs`、`PipelineConfs` 等)
2. **枚举值** —— `RecallType` / `FilterType` / `SortType` /
`DebugConfs.OutputType` / `GeneralRankConfs.ActionConfs[].ActionType`
3. **引用一致性** —— `SceneConfs.RecallNames` → `RecallConfs`;
`FilterNames` → `FilterConfs`;`SortNames` → `SortConfs`;
`RankConf.RankAlgoList` → `AlgoConfs`;任何 `DaoConf.AdapterType` +
`*Name` → 对应 `*Confs`(Hologres / Redis / MySQL / TableStore /
FeatureStore / …)
4. **业务规则**
- `User2ItemExposureFilter` 配 `WriteLog=true` + FeatureStore adapter:必须设置
`TimeInterval > 0`
- `accumulator` 模式下的 `PriorityAdjustCountFilter`:`Count` 必须严格
递增(用 `Type="fix"` 实现每次召回独立上限)
- `PipelineConfs.*.Name` 必须全局唯一
- `DebugConfs.Rate` 必须是 `[0, 100]` 内的整数
5. **重复名称检测** 在 `RecallConfs`、`FilterConfs`、`SortConfs`、
`AlgoConfs` 内
详细用法、退出码、示例输出和完整规则列表见
[references/config-validation.md](references/config-validation.md)。
#### 步骤 4:基于证据的报告
**[必须] 报告必需的第一行:** 逐字引用 `validate.py` 的 stdout
——要么 `Validation passed: configuration is well-formed`,要么
`Validation finished: N error(s), M warning(s)`。缺少这确切一行的报告
无效;从步骤 3 重新开始。
**人工检查仅允许** 用于 `validate.py` 范围之外的关注点:环境 / 地域 /
模型签名不匹配、跨版本差异、`RankScore` 变量与模型输出字段之间的
命名冲突,以及脚本自身要求人工判断的任何 `[WARNING]` 的根因读取。
除非能将它们绑定到这些范围外关注点之一,否则不要添加脚本未报告的发现。
**报告结构:**
- ✅ 检查通过 —— 引用 `validate.py` 的 `0 error(s), 0 warning(s)` 行
- ⚠️ 警告 —— 复制脚本的每条 `[WARNING] <path>: <message>`,
加上人工检查中的任何范围外不一致
- ❌ 错误 —— 复制脚本的每条 `[ERROR] <path>: <message>`
- 缺失证据说明 —— 仅当列出 ≥1 条 ⚠️ 警告时:说明什么额外数据会将该警告升级为确认错误。0 警告时,省略此节;不要用通用范围外免责声明(跨版本差异、远程连通性、地域 / 端点一致性)填充它——那些是证据-only 规则禁止的主动最佳实践建议。
不要添加推测性修复或最佳实践题外话;仅在用户明确要求时提供建议。
---
成功验证方法
详细验证步骤见 references/verification-method.md。
快速验证:
- 诊断工作流:
- 服务信息成功检索
- 找到含 request_id 的日志
- 配置正确加载
- 根因已识别
- 校验工作流:
- 配置成功检索
- 所有校验检查已执行
- 问题清晰报告
- 建议已提供(如适用)
清理
本 Skill 执行只读阿里云 API 调用(不创建远程资源)。临时工件
进入 /tmp 下的每会话本地 $WORKDIR(见核心工作流前言)。本 Skill 不自动删除 $WORKDIR
——操作系统级临时策略会回收它(macOS 定期清理 /tmp;大多数
Linux 发行版在重启时或通过 systemd-tmpfiles 清理)。要更快释放磁盘空间,
在工作流外手动运行 rm -rf /tmp/pairec-diag-*。
最佳实践
- 日志查询——仅关键词,无时间范围,无本地过滤:对于请求级诊断,向
aliyun eas describe-service-log传--keyword <request_id>并保持--start-time/--end-time未设置。绝不省略--keyword然后本地后处理(例如| head、| grep、| python3)——这破坏了服务端过滤,浪费 token,并可能漏掉第一页之外的日志。将关键词与时间范围组合会因 CLI 怪癖过滤掉业务日志(见工作流 1 步骤 3)。仅对宽泛的非请求扫描使用时间范围,且只用yyyy-MM-dd HH:mm:ssUTC 格式(无T/ 无Z)。 - 信任
validate.py:对于工作流 2,将scripts/validate.py视为其目录中规则的唯一事实来源。不要跳过它手写检查,也不要在干净运行后手动重新校验其规则。人工检查保留给其范围之外的关注点(环境 / 地域 / 模型签名、跨版本差异、RankScore与模型输出命名)。 - 环境意识:始终验证配置匹配目标环境(Prod vs Pre);问题持续时与已知良好版本对比。
- 日志保留:EAS 服务日志保留期有限;问题出现后及时诊断。
- 仅证据结论:将每个陈述建立在具体日志行或配置片段上。遵循系统化工作流,而非仅从错误消息跳到结论。不要推测,不要提议修复,也不要主动提供最佳实践建议,除非用户明确要求。如果证据不足,说明缺什么而非推断。
参考链接
| 参考文档 | 说明 |
|---|---|
| RAM 策略 | PAI-Rec 和 EAS API 所需的 RAM 权限 |
| 相关命令 | 完整 CLI 命令参考 |
| 验证方法 | 详细验证流程 |
| CLI 安装指南 | 阿里云 CLI 安装说明 |
| 配置示例 | 示例引擎配置和常见模式 |
| 配置校验 | scripts/validate.py 用法、退出码、规则目录 |
| 故障排查指南 | 常见问题与解决方案 |
| 配置脱敏 | LLM 分析前的凭据脱敏 |
阿里云skills
◯ 评论 0