芥末
发布于 2026-03-10 / 0 阅读
0
0

OpenClaw Skill 与 DuckDB 构建自动迭代的电商销售预测系统

大语言模型(Large Language Model,LLM)有丰富的知识,但它默认没有“手脚”。它可以解释天气预报是什么,却不能自己联网查询北京明天的天气;它知道 GitHub Issue 的含义,却不能天然帮你去仓库里查问题;它理解机器学习训练流程,也不会自动连接数据库、拉取数据、训练模型、保存结果。

OpenClaw Skill 解决的是这个“会说但不会做”的问题。Skill 可以理解成写给 AI 的操作手册:什么时候触发、需要什么工具、要执行哪些命令、结果怎么解释,都写在一个 SKILL.md 文件里。OpenClaw 负责加载这些手册,并在用户请求命中时让模型按流程执行。

当 Skill 遇到 RDS DuckDB 分析型实例,事情会变得更有意思。电商平台的行为数据通常非常大,浏览、加购、下单、收藏等事件会按天产生海量记录。如果直接在事务型 MySQL 上做复杂聚合,查询可能拖慢业务库,也可能跑很久。DuckDB 分析型实例负责把“翻账本”的动作变快,OpenClaw Skill 负责把“分析—训练—验证—记录”的动作自动化。

组合起来,就可以做出一个能够持续迭代的电商销售预测系统。

flowchart LR
    U[用户提出预测需求] --> O[OpenClaw]
    O --> S[ecommerce-predictor Skill]
    S --> D[(RDS DuckDB 分析型实例)]
    D --> F[生成时间序列特征]
    F --> M[训练多个预测模型]
    M --> V[用下月真实数据验证]
    V --> H[保存历史版本与指标]
    H --> S

这套系统的重点不是“让 AI 凭感觉预测”,而是把预测工作拆成确定的工程流程:查询数据、构造特征、训练模型、验证误差、记录版本、下次用更多数据重新训练。

OpenClaw Skill:把 AI 能力变成可执行流程

Skill 的本质是一个 Markdown 文件,通常叫 SKILL.md。文件顶部写结构化元信息,正文写操作步骤。

一个最简单的天气查询 Skill 可能只有几行逻辑:

---
name: weather
description: 查询指定城市的天气。Use when: 用户询问天气、气温、降雨情况。
requires:
  bins:
    - curl
---

当用户询问天气时,使用 wttr.in 查询城市天气。

示例:
curl wttr.in/Beijing

拿到结果后,用自然语言总结温度、天气状况和降雨概率。

这不是普通提示词,而是一份可被 OpenClaw 管理、筛选、注入和运行的能力描述。OpenClaw 可以内置多种 Skill,也允许用户自己写新的 Skill。只要把流程讲清楚,AI 就能从“知道这件事”变成“会按步骤做这件事”。

Skill 从文件到运行时的生命周期

一份 SKILL.md 并不会被 OpenClaw 原封不动全部塞进模型上下文。那样做很容易浪费 token,也会让系统提示词变得又长又乱。OpenClaw 采用的是渐进式披露:先只把 Skill 摘要暴露给模型,真正命中后再读取完整正文。

生命周期可以拆成 6 个环节。

flowchart TD
    A[Discovery<br/>扫描 Skill 文件] --> B[Parse<br/>解析 Front Matter]
    B --> C[Filter<br/>检查禁用状态、依赖和系统兼容性]
    C --> D[Inject<br/>把 Skill 摘要注入系统提示词]
    D --> E[Runtime<br/>用户请求命中后读取完整 SKILL.md]
    W[Watch<br/>监听文件变化] --> A
    E --> R[执行命令、查询数据或调用工具]
阶段作用典型产物
Discovery扫描多个 Skill 目录,找到所有 SKILL.md,并按优先级合并Skill[]
Parse读取 YAML 元信息,提取名称、描述、依赖、适用场景SkillEntry
Filter检查用户是否禁用、依赖命令是否存在、系统是否兼容可用的 SkillEntry[]
Inject只把名称和摘要压缩后注入系统提示词SkillSnapshot
Runtime用户请求命中 Skill 后,再读取完整正文并执行命令、脚本、分析结果
Watch监听文件变更,保存后自动让快照失效新版本 SkillSnapshot

这条链路里有三个关键对象:

SKILL.md
   ↓ Discovery
Skill[]
   ↓ Parse / Filter
SkillEntry[]
   ↓ Inject
SkillSnapshot
   ↓ Runtime
完整 Skill 正文

这种设计的好处很直接:系统里可以有几十个 Skill,但模型平时只看到每个 Skill 的简短说明;当某个请求确实需要某个 Skill 时,再把完整操作手册拿出来执行。

为什么电商预测需要 DuckDB 分析型实例

电商业务库一般适合在线事务处理(Online Transaction Processing,OLTP),例如写入订单、查询用户最近购买记录、修改库存状态。这类场景强调低延迟、高并发和事务一致性。

销售预测更接近在线分析处理(Online Analytical Processing,OLAP)。它关心的是过去一段时间的整体趋势,比如:

  • 最近 90 天每天有多少 PV(页面浏览量);
  • 每个品类的购买量和转化率怎么变化;
  • 黑色星期五、圣诞节、周末等时间点是否影响购买;
  • 新增数据后,模型误差是否下降。

这类问题经常需要扫描大量历史记录,并按时间、品类、品牌、事件类型做聚合。事务库不是不能查,而是不适合长期承担这种查询压力。

对比项事务型 MySQLDuckDB 分析型实例
主要目标写订单、改状态、查单条记录扫描历史数据、聚合统计、分析趋势
数据组织方式更适合按行读写更适合列式扫描与聚合
典型查询查询某个用户订单统计 7 个月全站 PV、UV、购买量
对业务影响大查询可能占用线上资源分析负载与交易负载隔离
适合任务交易系统报表、特征工程、模型训练数据准备

在电商预测系统中,DuckDB 的位置不是替代业务库,而是承担分析查询。OpenClaw Skill 需要频繁执行聚合 SQL,把原始事件变成模型可用的时间序列特征。如果每次查询都要等几个小时,模型迭代会非常慢;如果分析查询能在秒级返回,训练、验证、调参就可以形成闭环。

数据集与整体任务

示例任务使用公开数据集 eCommerce behavior data from multi category store。数据集中包含多个月的用户行为事件,常见字段包括:

字段含义
event_time事件发生时间
event_type行为类型,例如 viewcartpurchase
product_id商品 ID
category_id品类 ID
category_code品类路径
brand品牌
price价格
user_id用户 ID
user_session会话 ID

预测目标可以按天聚合成时间序列:

指标含义
PV页面浏览量,通常对应 event_type = 'view'
UV独立访客数,通常按 user_id 去重
Purchase购买事件数量
Cart加购事件数量

原始事件表可以先导入 DuckDB 分析型实例,再通过 SQL 生成每日特征。

CREATE TABLE user_events (
    event_time     DATETIME,
    event_type     VARCHAR(32),
    product_id     BIGINT,
    category_id    BIGINT,
    category_code  VARCHAR(255),
    brand          VARCHAR(255),
    price          DOUBLE,
    user_id        BIGINT,
    user_session   VARCHAR(255)
);

导入 CSV 时,可以使用 MySQL 生态工具的 LOAD DATA 能力。实际路径和连接参数需要替换成自己的环境。

LOAD DATA LOCAL INFILE '/data/2019-Oct.csv'
INTO TABLE user_events
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(event_time, event_type, product_id, category_id, category_code, brand, price, user_id, user_session);

生成每日 PV、UV、购买量和加购量的 SQL 可以这样写:

SELECT
    DATE(event_time) AS dt,
    SUM(CASE WHEN event_type = 'view' THEN 1 ELSE 0 END) AS pv,
    COUNT(DISTINCT user_id) AS uv,
    SUM(CASE WHEN event_type = 'purchase' THEN 1 ELSE 0 END) AS purchase_cnt,
    SUM(CASE WHEN event_type = 'cart' THEN 1 ELSE 0 END) AS cart_cnt
FROM user_events
GROUP BY DATE(event_time)
ORDER BY dt;

这一步是后续建模的基础。模型不直接吃原始明细事件,而是吃按天聚合后的时间序列特征。

ecommerce-predictor Skill 应该怎么写

电商预测 Skill 至少需要描述 5 件事:

  1. 如何连接 DuckDB 分析型实例;
  2. 如何从事件表生成训练数据;
  3. 如何构造时间序列特征;
  4. 如何训练多个候选模型并选择效果较好的模型;
  5. 如何保存验证结果,供后续版本对比。

SKILL.md 的元信息可以这样组织:

---
name: ecommerce-predictor
description: "电商用户行为时间序列预测。用于预测 PV、UV、购买量、加购量,并对模型版本进行验证和追踪。Use when: 预测、时间序列、销量预测、电商趋势分析。NOT for: 实时风控、非时序分类问题。"
metadata:
  OpenClaw:
    emoji: "📈"
requires:
  bins:
    - python3
---

正文部分要把执行步骤写清楚,例如:

# ecommerce-predictor

## 目标

连接 RDS DuckDB 分析型实例,读取电商行为数据,按天聚合 PV、UV、Purchase、Cart,
基于历史数据训练时间序列预测模型,并用下一个月的真实数据验证误差。

## 执行流程

1. 检查 Python 环境和依赖。
2. 连接 DuckDB 分析型实例。
3. 查询每日聚合指标。
4. 构造日期、星期、月份、节假日、滞后项、滚动均值等特征。
5. 使用多个模型训练。
6. 使用下月真实数据验证。
7. 记录 MAPE、R²、最佳模型、训练时间范围。
8. 更新 HISTORY.md 和 validation_history.json。

用户调用时,可以用 OpenClaw 的 Skill 命令触发:

/skill ecommerce-predictor 预测下个月的 PV、UV、Purchase、Cart

Skill 的职责不是在一条提示词里“猜答案”,而是让 OpenClaw 进入固定流程:查数据、跑脚本、训练模型、验证结果、写入记录。

“自动进化”不是魔法,而是一个训练闭环

电商预测模型的自动迭代可以拆成四个机制:滚动式训练、自动验证、历史追踪、自动模型选择。

flowchart TD
    A[导入新月份数据] --> B[扩大训练区间]
    B --> C[生成特征]
    C --> D[训练多个候选模型]
    D --> E[用下月真实数据验证]
    E --> F[计算 MAPE / R²]
    F --> G[选择当前版本最佳模型]
    G --> H[写入 validation_history.json]
    H --> A

滚动式训练:训练集随时间向前扩展

滚动式训练的核心做法是:训练起点固定,训练终点逐月向后移动。

# 第 1 轮
train_start = "2019-10-01"
train_end = "2019-11-01"
val_start = "2019-11-01"
val_end = "2019-12-01"

# 第 2 轮
train_start = "2019-10-01"
train_end = "2019-12-01"
val_start = "2019-12-01"
val_end = "2020-01-01"

这样做有几个实际作用:

作用解释
保留历史规律周末、月初月末、促销日等模式会留在训练集中
吸收新数据每导入一个月,新月份数据会进入下一轮训练
便于版本对比每个版本都能明确对应训练区间和验证区间
不依赖人工重跑Skill 可以按固定流程自动执行

但滚动式训练也有代价。历史数据越来越多时,每轮训练都会变慢;如果业务模式发生明显变化,过早的数据还可能拖累模型。数据规模继续扩大后,可以考虑两种改法:

改法适合场景
滑动窗口只保留最近 N 个月数据,适合业务变化快的场景
时间衰减权重保留全部历史,但让近期数据权重更高

自动验证:用未来一个月真实数据检查模型

模型训练完成后,不能只看训练集表现。更合理的做法是把下一个月作为验证集,用真实数据计算预测误差。

常用指标包括 MAPE(Mean Absolute Percentage Error,平均绝对百分比误差)和 R²(决定系数)。

import numpy as np
from sklearn.metrics import r2_score

def mape(y_true, y_pred, eps=1e-8):
    y_true = np.asarray(y_true)
    y_pred = np.asarray(y_pred)
    return np.mean(np.abs((y_true - y_pred) / np.maximum(np.abs(y_true), eps))) * 100

pv_mape = mape(y_true_pv, y_pred_pv)
purchase_mape = mape(y_true_purchase, y_pred_purchase)
pv_r2 = r2_score(y_true_pv, y_pred_pv)

MAPE 越低,代表平均百分比误差越小;R² 越接近 1,代表模型对波动的解释能力越强。

需要注意,MAPE 在真实值接近 0 时会被放大,所以购买量很小的 SKU 或冷门品类不能只看 MAPE,最好同时看 MAE(Mean Absolute Error,平均绝对误差)或 RMSE(Root Mean Squared Error,均方根误差)。

历史追踪:给每次训练留下实验记录

如果每次训练只输出一张预测表,后续很难回答这些问题:

  • 哪个版本的 PV 预测最好?
  • 训练数据变多后,购买量误差有没有下降?
  • 哪次加入了节假日特征?
  • 哪次遇到了异常外部事件?
  • 当前模型是进步了,还是过拟合了?

所以 Skill 需要把每轮结果写进历史文件,例如 validation_history.json

{
  "versions": [
    {
      "version": "v20260309_134100",
      "train_start": "2019-10-01",
      "train_end": "2019-11-01",
      "validation_start": "2019-11-01",
      "validation_end": "2019-12-01",
      "train_days": 31,
      "best_model": "ExponentialSmoothing",
      "pv_mape": 26.92,
      "purchase_mape": 11.39,
      "notes": "baseline, black_friday_error_high"
    },
    {
      "version": "v20260309_152600",
      "train_start": "2019-10-01",
      "train_end": "2019-12-01",
      "validation_start": "2019-12-01",
      "validation_end": "2020-01-01",
      "train_days": 61,
      "best_model": "RandomForest",
      "pv_mape": 8.15,
      "purchase_mape": 23.17,
      "notes": "training_data_doubled"
    }
  ]
}

这相当于一个轻量级 MLOps 记录系统。MLOps 指机器学习工程化运维,关注模型训练、评估、部署、监控和版本管理。这里不需要完整引入 MLflow 之类的平台,也能先把关键实验信息记录下来。

自动模型选择:不同阶段选择不同模型

电商行为数据在不同阶段可能适合不同模型。训练样本少时,线性模型或指数平滑模型可能更稳;数据变多后,树模型可以捕捉更复杂的非线性关系。

可以准备一组候选模型,每次训练后按验证集指标选择。

from sklearn.linear_model import Ridge, Lasso
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor

models = {
    "Ridge": Ridge(alpha=1.0),
    "Lasso": Lasso(alpha=0.01),
    "RandomForest": RandomForestRegressor(
        n_estimators=200,
        max_depth=8,
        random_state=42
    ),
    "GradientBoosting": GradientBoostingRegressor(
        n_estimators=200,
        learning_rate=0.05,
        max_depth=3,
        random_state=42
    )
}

val_results = {}

for name, model in models.items():
    model.fit(X_train, y_train_pv)
    pred = model.predict(X_val)
    val_results[name] = {
        "pv_mape": mape(y_val_pv, pred)
    }

best_model_name = min(
    val_results.keys(),
    key=lambda name: val_results[name]["pv_mape"]
)

如果只按 PV MAPE 选模型,可能会牺牲购买量预测效果。更稳妥的做法是设计综合评分:

score = 0.5 * pv_mape + 0.3 * purchase_mape + 0.2 * cart_mape

权重应该跟业务目标一致。广告投放更关心流量时,PV 权重可以高一些;库存和供应链更关心购买量时,Purchase 权重应该更高。

特征工程:黑五误差为什么会很高

第一次训练只用 2019 年 10 月数据,拿 2019 年 11 月验证,可能会遇到一个典型问题:黑色星期五误差很高。

原因很简单。模型只看到了基础日期特征,没有被告知 11 月 29 日是特殊促销日。对模型来说,那天只是普通星期五。真实世界里,促销活动会显著改变浏览和购买行为,模型却没有对应输入,自然很难预测。

基础特征可能只有这些:

特征含义
day_of_week星期几
day_of_month每月第几天
month月份
is_weekend是否周末
days_since_start距离训练起点的天数

后续版本可以加入更多特征:

特征类型示例作用
节假日特征is_black_fridayis_thanksgivingis_christmas捕捉促销和节日冲击
滞后特征pv_lag_1purchase_lag_7利用昨天、上周同日的数据
滚动统计pv_rolling_7_meancart_rolling_14_mean平滑短期波动
转化特征purchase_cnt / pvcart_cnt / pv表达用户行为链路变化
价格特征平均价格、中位数价格捕捉商品价格结构变化

特征工程往往比模型选择更重要。模型不知道的外部事件,很难靠算法自己猜出来。

从 v1 到 v6:模型迭代结果

在前两个月数据中,第一次预测使用 2019 年 10 月训练,用 2019 年 11 月验证。结果大致如下:

指标数值说明
PV MAPE26.92%页面浏览量平均绝对百分比误差
购买量 MAPE11.39%购买量预测误差
黑五误差45%未显式建模节假日导致误差偏高
训练天数31 天2019-10-01 到 2019-11-01
验证天数30 天2019-11-01 到 2019-12-01
特征数5 个基础时间特征
模型指数平滑基线模型

基线模型的意义不是一次就达到最优,而是建立可比较的起点。后续每导入一个月数据,Skill 会重新聚合数据、训练模型、验证误差并更新历史记录。

版本训练天数最佳模型PV 误差购买量误差主要变化
v1.031 天指数平滑26.92%11.39%基线模型,黑五误差高
v2.061 天RandomForest8.15%23.17%训练数据翻倍
v3.092 天GradientBoosting2.73%42.28%PV 预测达到阶段性最佳
v4.0123 天GradientBoosting2.73%42.28%版本稳定,结果延续
v5.0152 天Ridge29.99%36.99%外部环境变化导致误差上升
v6.0183 天GradientBoosting10.03%12.65%购买量预测明显恢复

这组结果说明两件事。

一方面,随着训练数据从 31 天增加到 183 天,PV 预测从 26.92% 降到 10.03%,误差下降约 62.7%。节假日特征、滞后特征和滚动统计加入后,黑五这类特殊日期不再像基线版本那样难以处理。

另一方面,模型并不是每一轮、每个指标都单调变好。v3.0 的 PV 误差很低,但购买量误差很高;v5.0 遇到外部环境变化后,PV 和购买量都出现明显波动。这很符合真实业务:流量和购买不是同一个目标,突发事件也不一定能从历史数据中推断出来。

如果后续要把它用于库存、补货或营销预算,不能只看一个指标。至少要同时跟踪 PV、UV、Cart、Purchase,并为不同业务目标设置不同模型选择策略。

DuckDB 在闭环里的价值

电商预测 Skill 每轮都需要做大量查询:

  1. 扫描多个月原始行为明细;
  2. 按天聚合 PV、UV、Cart、Purchase;
  3. 计算品类、品牌、价格等统计特征;
  4. 生成训练集和验证集;
  5. 对比不同模型版本的结果。

这些操作都属于分析查询。示例场景中,连接 RDS DuckDB 分析型实例后,数据洞察、迭代验证、策略调整阶段的查询比普通 MySQL 实例快约数百倍。具体倍数会受数据规模、SQL 写法、实例规格和缓存状态影响,但方向很明确:分析负载不应该长期压在交易库上。

flowchart LR
    A[(业务 MySQL<br/>订单与行为写入)] -->|同步/导入| B[(RDS DuckDB<br/>分析型实例)]
    B --> C[聚合 SQL]
    C --> D[特征表]
    D --> E[模型训练]
    E --> F[验证指标]
    F --> G[模型历史记录]

这种架构把交易和分析分开:

模块负责内容
业务 MySQL写入订单、用户行为、交易状态
DuckDB 分析型实例扫描历史数据、聚合统计、生成特征
OpenClaw Skill编排分析流程、执行脚本、保存结果
Python 模型脚本训练模型、计算指标、选择版本
历史记录文件保存每轮训练的参数和效果

上手流程

一个可运行的最小版本可以按这个顺序搭建。

1. 准备 OpenClaw 环境

需要一台可以运行 OpenClaw 的机器,并确保能访问 RDS DuckDB 分析型实例。若 OpenClaw 需要调用云上资源,还需要配置阿里云命令行工具(Command Line Interface,CLI)或对应凭证。

2. 创建 DuckDB 分析型实例

创建实例时,尽量让它和运行 OpenClaw 的云服务器(Elastic Compute Service,ECS)处于同一可用区,并使用同一个专有网络(Virtual Private Cloud,VPC)。这样可以减少网络访问问题和跨区延迟。

创建完成后,需要做三件事:

1. 创建高权限账号或具备导入、查询权限的账号
2. 创建数据库和事件表
3. 在 OpenClaw 所在机器上验证连接

3. 下载并导入电商行为数据

公开数据可以从天池或 Kaggle 获取。解压后按月份导入,例如:

2019-Oct.csv
2019-Nov.csv
2019-Dec.csv
2020-Jan.csv
2020-Feb.csv
2020-Mar.csv
2020-Apr.csv

建议先导入两个月跑通全流程,再逐月追加数据观察模型变化。

4. 安装 Python 依赖

预测脚本通常需要数据库连接库、数据处理库和机器学习库。

pip install pandas numpy scikit-learn pymysql sqlalchemy

如果要使用 XGBoost,还需要额外安装:

pip install xgboost

5. 放置 Skill 文件

ecommerce-predictor/SKILL.md 放到 OpenClaw 可扫描的 Skill 目录里。保存文件后,OpenClaw 的 Watch 机制会监听变更,并在下次对话时重建 Skill 快照。

6. 触发预测

/skill ecommerce-predictor 预测下个月的 PV、UV、Purchase、Cart

一次完整执行后,目录里应该能看到类似文件:

ecommerce-predictor/
├── SKILL.md
├── scripts/
│   ├── build_features.py
│   ├── train.py
│   └── validate.py
├── outputs/
│   ├── forecast_next_month.csv
│   └── validation_report.json
├── HISTORY.md
└── validation_history.json

容易踩的坑

问题表现处理方式
把分析查询直接打到业务库SQL 慢、影响线上交易使用分析型实例承接聚合查询
只保存最终预测结果无法比较版本变化保存训练区间、模型、指标、特征数量
只按 PV 选择模型流量准但购买量不准使用综合指标或按目标分别建模
不处理节假日促销日误差异常高加入节假日、活动日、周末等特征
历史数据无限增长每轮训练越来越慢使用滑动窗口或时间衰减
MAPE 被小真实值放大冷门商品误差看起来很夸张同时观察 MAE、RMSE、样本量
突发事件无法预测外部冲击期间误差升高加入外部变量,或单独标记异常区间
Skill 描述过长系统提示词臃肿摘要只写触发条件和能力边界,细节放正文

OpenClaw Skill 负责把流程标准化,DuckDB 分析型实例负责让历史数据查询足够快。二者结合后,电商预测就不再是一次性的 Notebook 实验,而是一个可以持续运行的闭环:新数据进入,Skill 触发聚合和训练,验证集衡量误差,历史记录沉淀经验,下一轮再基于更多数据重新选择模型。

相关资源:


评论