从「无差别撒钱」到「每一分补贴都有 ROI 可查」
promo-mind 是一个可本地运行的营销券决策样例:读取用户画像,生成结构化券策略,基于历史样本模拟增量 GMV 与净 ROI,再按预算进入自动审批、人工审核或多人会签。整个流程由 LangGraph 编排,并使用 SQLite checkpoint 支持跨进程查询与恢复。
当前项目使用固定种子的模拟画像和券历史,执行节点也只写入“模拟执行”状态,不会连接真实营销平台或发放优惠券。
- 快速开始:安装、运行、人工审批、LLM 配置与常见错误
- 架构说明:模块边界、运行时数据流、checkpoint 与扩展点
- 项目背景:业务问题、数据可信度分级与参考资料
- 贡献指南:开发环境、质量门禁与代码规范
| 能力 | 当前实现 |
|---|---|
| 用户画像 | DataProvider Protocol + 固定种子的 MockDataProvider |
| 策略生成 | 默认离线 ScriptedStrategyAgent;可选 OpenAI 兼容的 CouponStrategyAgent |
| ROI 模拟 | 确定性 SimulatedROICalculator + 按券类型注册的成本 kernel |
| 审批 | <= 5,000 元自动通过,<= 50,000 元人工审核,更高预算两人会签 |
| 工作流 | 画像 → 策略 → ROI → 审批 → 模拟执行 |
| 持久化 | LangGraph SQLite checkpoint;支持 run / resume / inspect |
| 评估 | 11 个 YAML 场景、确定性评分基线与 CI 回归门禁 |
设计原则是只把开放式策略生成交给可选 LLM。画像读取、ROI 计算、审批路由和状态持久化保持确定性,便于测试、审计和替换。
要求 Python 3.12+。以下命令从本目录 promo-mind/ 执行:
python -m venv .venv
source .venv/bin/activate
python -m pip install -e .
promo-mind --version
promo-mind run \
--user-id user_0002 \
--goal "提升本月复购率" \
--thread-id demo-auto默认使用离线、确定性的 ScriptedStrategyAgent。user_0002 在默认配置下会自动审批并输出 JSON;关键字段包括:
{
"thread_id": "demo-auto",
"status": "executed",
"interrupts": [],
"state": {
"profile": {},
"strategy": {},
"prediction": {},
"approval": {},
"trace": []
}
}默认 checkpoint 数据库为 .promo-mind/checkpoints.sqlite3。thread_id 是持久化主键;再次用同一数据库运行同名 thread 会被拒绝,以避免覆盖历史决策。
固定模拟数据中的 user_0005 在默认阈值下会停在人工审批:
promo-mind run \
--user-id user_0005 \
--goal "新客首单转化" \
--thread-id demo-review
promo-mind inspect demo-review
promo-mind resume demo-review \
--action approve \
--reviewer operator@example.com中断时顶层 status 为 pending_approval,审批完成后为 executed;改用 --action reject 会得到 rejected,且不会进入模拟执行节点。多人会签要求在同一次 resume 中重复传入两个不同的 --reviewer。
LLM 模式只通过 PROMO_MIND_* 环境变量配置。仓库不硬编码模型名,也不自动读取 .env 或 TOML 配置文件。
export PROMO_MIND_STRATEGY_BACKEND=llm
export PROMO_MIND_LLM_API_KEY="<由密钥管理系统注入>"
export PROMO_MIND_LLM_MODEL="<服务商支持的模型名>"
# 使用非默认 OpenAI 兼容端点时设置:
# export PROMO_MIND_LLM_BASE_URL="https://provider.example/v1"
# export PROMO_MIND_LLM_TIMEOUT_SECONDS=30
# export PROMO_MIND_LLM_PARSE_MAX_RETRIES=1
promo-mind run \
--user-id user_0002 \
--goal "提升本月复购率" \
--thread-id demo-llmPROMO_MIND_LLM_API_KEY 和 PROMO_MIND_LLM_MODEL 在 llm 模式下均为必填。模型返回空文本、非法 JSON、schema 不匹配或错误用户分群时,应用按 PROMO_MIND_LLM_PARSE_MAX_RETRIES 重试,耗尽后回退到 ScriptedStrategyAgent。网络、超时、认证和限流错误不会回退,也不会被应用层重试。
完整环境变量说明见快速开始:运行配置。
在已安装项目依赖的 Python 3.12+ 环境中,从 promo-mind/ 目录运行:
bash scripts/demo.sh脚本会依次演示三个典型用户的离线策略生成、人工审批中断与 approve 恢复,以及全部 Eval 场景评分。录制方法和 VHS Tape 示例见 Demo 录制指南。
当前 CLI 的真实命令面如下:
promo-mind run --user-id <id> [--goal <text>] [--thread-id <id>] [--database <path>]
promo-mind resume <thread-id> --action <approve|reject> --reviewer <id>... [--database <path>]
promo-mind inspect <thread-id> [--database <path>]
promo-mind --version
--database 的优先级高于 PROMO_MIND_CHECKPOINT_DB_PATH。使用非默认数据库时,run、inspect 和 resume 必须指向同一文件。当前帮助界面把 --reviewer 显示为可选,但审批领域模型实际要求至少一位非空审批人。
from promo_mind.core.roi import SimulatedROICalculator
from promo_mind.domain.models import CouponStrategy, CouponType
strategy = CouponStrategy(
coupon_type=CouponType.THRESHOLD_REDUCTION,
face_value=10.0,
threshold=80.0,
target_segment="churn_risk",
estimated_redemption_rate=0.24,
)
prediction = SimulatedROICalculator().simulate_roi(strategy, "churn_risk")
print(prediction.model_dump())
# {
# 'strategy_id': 'strategy_612e8be32cd2',
# 'estimated_incremental_gmv': 17958.03,
# 'net_roi': 4.7558,
# 'budget_required': 3120.0,
# }这些数值来自当前固定模拟数据和默认参数,不代表真实业务收益。
安装开发依赖后,按以下顺序运行质量门禁:
python -m pip install -e ".[dev]"
python -m ruff check promo_mind tests eval
python -m mypy promo_mind tests eval
python -m pytest
python -m eval.score --assert-baseline项目要求 Python 3.12+、Pydantic v2 和 mypy strict。更多开发约定见 CONTRIBUTING.md。
- 用户画像、历史券效果和 ROI 都是可复现模拟数据,不是线上数据或因果实验结果。
execute只生成模拟执行消息,不调用投放平台。- LLM 端点必须兼容当前使用的 Chat Completions JSON 请求形式。
- SQLite 适合本地演示和单机恢复;生产部署需要重新评估并发、权限、密钥与数据治理。
