这是一个基于 Reson Agent 框架的业务开发项目。项目包含:
🚨 硬性规则:没有用户明确指令,绝对不执行 git commit / git push。
默认行为:
正确流程:
git add + git commitgit pushCommit message 格式规范(2026-06-08 用户确认):
Co-Authored-By: Claude ... 行🤖 Generated with [Claude Code](...) 行feat(xxx): ... / fix(xxx): ...)以下目录是 Agent 框架的核心源码,在任何情况下都不得修改:
agent/ # Agent 框架核心代码
├── core/ # 核心运行逻辑
├── tools/ # 内置工具系统
├── llm/ # LLM 调用封装
├── trace/ # 轨迹追踪
├── skill/ # Skill 系统
├── cli/ # 命令行工具
├── utils/ # 工具函数
└── docs/ # 框架文档
如果需要扩展功能,应该:
examples/[your_project]/tools/ 创建自定义工具examples/[your_project]/skills/ 创建自定义 Skillagent/ 目录下的任何文件examples/ # 业务开发主目录
├── my_business/ # 你的业务项目
│ ├── config.py # 业务配置
│ ├── run.py # 运行入口
│ ├── task.prompt # 任务描述
│ ├── tools/ # 自定义工具(可选)
│ ├── skills/ # 自定义 Skill(可选)
│ └── outputs/ # 输出目录
└── [other_examples]/ # 其他业务项目
frontend/ # 前端可视化界面
gateway/ # API 网关
im-server/ # IM 服务器
im-client/ # IM 客户端
knowhub/ # 知识库服务
config/ # 全局配置
这些目录提供基础设施支持,通常不需要修改。如需调整配置,优先在业务项目的 config.py 中覆盖。
frontend/react-template/package-lock.json
2.56.0 → 2.92.2examples/my_business/ (新增)
agent/core 目录结构examples/auto_ad_placement/ (新增)
examples/auto_put_ad_mini/ (新增 — 当前活跃开发)
auto_put_ad 完整体系(无人工干预 → 自主决策 → 自学习反馈)工作目录:
examples/auto_put_ad_mini/业务场景: 微信小程序投流(MARKETING_CARRIER_TYPE_MINI_PROGRAM_WECHAT) 核心目标: 基于 ROI + 跑量(消耗)双维度,自动给出广告粒度的操作决策
本项目是整个自动化投放系统的第一个业务单元:
终极形态(auto_put_ad) 当前阶段(auto_put_ad_mini)
┌──────────────────────┐ ┌───────────────────────┐
│ 受众策略 Agent │ │ │
│ 创意策略 Agent │ │ 数据拉取 → ROI 计算 │
│ 预算策略 Agent │ │ ↓ │
│ ★ 监控调控 Agent ◄───┼────────│ 决策引擎(规则+策略) │
│ 数据分析 Agent │ │ ↓ │
│ 系统运维 Agent │ │ 操作执行(API 调用) │
│ 自学习/反馈环 │ │ │
└──────────────────────┘ └───────────────────────┘
| 决策类型 | 操作 | API 端点 | 触发条件 |
|---|---|---|---|
| 调整出价 | 修改广告 bid_amount | /v3.0/adgroups/update |
ROI 偏离目标、跑量不足/过快 |
| 暂停广告 | 修改 configured_status → DELETED/SUSPEND | /v3.0/adgroups/update |
ROI 过低、长期无消耗、当日预算耗尽 |
⚠️ 当前阶段不包含:创建广告、修改定向、修改创意、调整预算分配。这些属于后续扩展。
Agent 需要拉取并分析以下三个时间粒度的数据:
| 时间粒度 | 用途 | 关键指标 |
|---|---|---|
| 小时级 | 实时监控,快速止损 | 最近 1-3 小时消耗速率、转化成本突变 |
| 日级 | 当天表现评估,出价微调 | 当日 ROI、当日消耗进度、当日转化量 |
| 周级 | 趋势判断,策略调整 | 7 日 ROI 均值、消耗趋势、转化成本波动 |
ROI 高
│
┌────────────┼────────────┐
│ 高ROI低量 │ 高ROI高量 │
│ → 提价放量 │ → 维持/微调 │
消耗少 ──┼────────────┼────────────┤── 消耗多
│ 低ROI低量 │ 低ROI高量 │
│ → 暂停观察 │ → 降价/暂停 │
└────────────┼────────────┘
│
ROI 低
决策逻辑(7 种 action,详见 config.py 和 skills/):
channel_roi_p50,即"动态ROI 7日均值"的中位数),裂变率基于同类人群包均值ROI_LOW_FACTOR=0.75,提价线:BID_UP_ROI_FACTOR=1.05,降价线:BID_DOWN_ROI_FACTOR=0.90ROI = 收入(GMV / 转化价值) ÷ 广告消耗(cost)
# 分时间粒度
hourly_roi = sum(hourly_revenue) / sum(hourly_cost)
daily_roi = daily_revenue / daily_cost
weekly_roi = sum(7d_revenue) / sum(7d_cost)
⚠️ 重要:决策参考使用 动态 ROI (7日均值) 均值,而非单日值
公式定义:
对每一天(需日消耗 ≥ 100 元才参与计算):
T0裂变系数 = T0裂变数(fission0_count) / 首层打开数(open_count)
arpu = 总收入 / 总回流人数
当日裂变收益率 = T0裂变数 × arpu / cost
当日回流倍数 = 总回流人数 / 首层打开数
7日滚动均值(min_periods=3,至少3天合格数据即可计算):
回流倍数_7日均值 = mean(当日回流倍数) over 7天
T0裂变系数_7日均值 = mean(T0裂变系数) over 7天
裂变效率稳定因子 = 回流倍数_7日均值 / T0裂变系数_7日均值
动态 ROI (7日均值) = 当日裂变收益率 × 裂变效率稳定因子
变量含义说明:
两个关键指标:
决策使用规则:
计算层级差异:
| 业务含义 | API 字段 | 说明 |
|---|---|---|
| 广告消耗 | cost |
单位:分 |
| 曝光量 | view_count |
|
| 点击量 | valid_click_count |
|
| 转化量 | conversions_count |
取决于 optimization_goal |
| 转化成本 | cost_per_conversion |
cost / conversions_count |
| 千次曝光成本 | thousand_display_price |
|
| 点击率 | ctr |
|
| 当前出价 | bid_amount(广告属性) |
单位:分 |
| 广告状态 | configured_status / system_status |
examples/auto_put_ad_mini/
├── run.py # 运行入口
├── config.py # 业务配置(ROI 阈值、出价边界等)
├── presets.json # 预设参数
├── prompts/
│ └── system.prompt # Agent 系统 Prompt
├── tools/
│ ├── ad_api.py # 腾讯广告 API 封装(拉数据 + 操作)
│ └── roi_calculator.py # ROI 计算与决策建议生成
├── skills/
│ ├── ad_domain.md # 业务模型:裂变模型、R值、ROI公式
│ ├── platform_rules.md # 平台硬约束:oCPM学习期、调价上限
│ ├── decision_framework.md # 决策框架:角色 + 候选标记 + 年龄策略
│ ├── action_playbook.md # 动作手册:7种action + 权衡原则
│ └── posterior_wisdom.md # 后验经验:学习中断/置信度分级
└── outputs/ # 运行输出
auto_put_ad_mini 是 auto_put_ad 终极体系中 Monitor/调控 Agent 的前身tools/ad_api.py)设计时应考虑复用性,便于后续迁移⚠️ 重要:本项目使用腾讯广告 Marketing API v3.0,与旧版(2.0)有根本性区别!
| 旧版(2.0,已废弃) | 新版(3.0,当前使用) |
|---|---|
| 推广计划(Campaign) | ❌ 已移除 |
| 广告组(AdGroup) | ❌ 业务概念已被"广告"取代 |
| 广告(Ad) | ✅ 广告 — 3.0 顶层单位 |
| 广告创意 | ✅ 动态创意(Dynamic Creative) |
| 业务概念 | API 端点 | 返回字段 | 说明 |
|---|---|---|---|
| 广告(3.0 顶层) | /v3.0/adgroups/add |
adgroup_id |
技术保留旧名,但业务是"广告" |
| 创意 | /v3.0/dynamic_creatives/add |
dynamic_creative_id |
组件化创意 |
/v3.0/adgroups/add)本业务固定参数:
marketing_goal = MARKETING_GOAL_USER_GROWTH(用户增长)marketing_carrier_type:MARKETING_CARRIER_TYPE_MINI_PROGRAM_WECHAT 或 MARKETING_CARRIER_TYPE_WECHAT_OFFICIAL_ACCOUNTbid_mode = BID_MODE_OCPM(oCPM 出价,固定)optimization_goal:OPTIMIZATIONGOAL_PAGE_VIEW 或 OPTIMIZATIONGOAL_CLICKtargeting.custom_audience:自有人群包 ID 数组targeting.age:年龄区间数组,如 [{"min": 25, "max": 35}]time_series:336 位字符串(48段×7天,每段30分钟,"1"=投放)每次执行 Python 脚本前,必须确保使用虚拟环境:
# 检查虚拟环境是否存在
if [ ! -d ".venv" ]; then
python3 -m venv .venv
fi
# 激活虚拟环境
source .venv/bin/activate
# 安装依赖(如需要)
pip3 install -r requirements.txt
pip3 而非 pip 安装依赖.venv/.venv/bin/python3# 在 examples/ 下创建新项目
mkdir -p examples/your_project/{tools,skills,outputs}
cd examples/your_project
# 复制模板文件
cp ../my_business/config.py .
cp ../my_business/run.py .
cp ../my_business/task.prompt .
在业务项目下创建 tools/ 目录:
# examples/your_project/tools/my_tool.py
from agent.tools import tool, ToolResult
@tool(description="我的自定义工具")
async def my_custom_tool(param: str) -> ToolResult:
"""工具功能描述
Args:
param: 参数说明
"""
# 实现逻辑
return ToolResult(output="结果")
在 run.py 中导入:
from tools.my_tool import my_custom_tool
在业务项目下创建 skills/ 目录:
<!-- examples/your_project/skills/my_skill.md -->
---
name: my-skill
description: 我的领域知识
category: custom
---
## 使用场景
- 场景描述
## 指导原则
- 原则说明
业务配置集中在 config.py:
from agent.core.runner import RunConfig, KnowledgeConfig
RUN_CONFIG = RunConfig(
model="qwen/qwen3.5-plus-02-15",
temperature=0.3,
max_iterations=50,
tools=["read_file", "write_file", "your_custom_tool"], # 工具白名单
knowledge=KnowledgeConfig(
enable_injection=False,
enable_completion_extraction=False,
)
)
当协助开发时,Claude 应该:
严格遵守目录约束
agent/ 目录下的文件examples/[project]/ 下优先使用框架能力
agent/README.md 了解框架功能保持项目结构清晰
提供清晰的说明
不要直接修改框架源码
保持业务代码独立
合理使用版本控制
A: 通过以下方式扩展,而不是修改源码:
examples/[project]/tools/examples/[project]/skills/config.py 中的 RunConfigA: 使用框架提供的调试功能:
setup_logging(level="DEBUG").trace/ 目录frontend/react-templateA:
# 如果是 git submodule
git submodule update --remote agent
# 如果是直接克隆
cd agent && git pull origin main
问题描述: 生成的决策报告(Excel/飞书表格)只显示7列基本字段(ad_id、action、dimension、reason、recommended_change_pct、current_bid、recommended_bid),缺少关键业务字段如:
根本原因:
在 tools/ad_decision.py 的 apply_decisions() 函数中,决策DataFrame是直接从LLM输出字典构建的:
df_out = pd.DataFrame(all_decisions) # 只包含决策字段
LLM输出的字典只包含决策相关字段(action、reason等),不包含metrics CSV中的业务字段。如果不合并metrics CSV,输出的Excel/飞书表格就会缺失这些关键信息。
历史记录:
10b0b28)就存在这个bug,从未有合并逻辑正确解决方案:
在 apply_decisions() 函数中,DataFrame创建后立即合并metrics CSV字段:
# ===== 关键修复:合并 metrics CSV 中的字段 =====
try:
df_metrics_full = pd.read_csv(metrics_csv)
# 定义需要合并的字段
merge_cols = [
"ad_id", "account_id", "ad_name", "audience_tier", "create_time", "ad_age_days",
"bid_amount", "yesterday_cost", "yesterday_revenue", "yesterday_roi",
"cost_7d_total", "cost_7d_avg", "revenue_7d_total",
"动态ROI", "动态ROI_7日均值", "cost_30d_total", "cost_30d_avg",
"stable_spend_days_30d", "creative_count", "roi_valid_days"
]
# 仅保留实际存在的列
merge_cols = [c for c in merge_cols if c in df_metrics_full.columns]
df_metrics_merge = df_metrics_full[merge_cols]
# 左连接:保留所有决策,添加metrics字段
df_out = df_out.merge(df_metrics_merge, on="ad_id", how="left", suffixes=("", "_metrics"))
logger.info(f"已从 metrics CSV 合并 {len(merge_cols)} 个字段")
except Exception as e:
logger.warning(f"合并 metrics 字段失败: {e}")
关键位置:
examples/auto_put_ad_mini/tools/ad_decision.pyapply_decisions()(约1324-1345行)df_out = pd.DataFrame(all_decisions) 之后立即执行预防措施:
df_out.drop(columns=["cost_7d_avg"]) 等操作删除业务字段apply_decisions 函数的变更,都必须验证字段合并逻辑是否完整问题描述: 早期成长期(4-7天)的广告收到了LLM的降价(bid_down)或关停(pause)建议,触发兜底检查告警。这些广告应该只允许提价(bid_up)决策。
根本原因:
在 get_ads_for_review() 函数的年龄保护逻辑中,只检查了"是否有提价候选",但没有检查"是否有其他类型的候选":
# ❌ 错误逻辑(不完整)
if not (bid_up_candidate or scale_up_candidate):
# 没有提价候选就跳过,但没检查是否有其他候选
normal_ads_count += 1
continue
这导致如果广告同时满足 roi_low=True 和 bid_up_candidate=False,就会进入LLM评估,LLM可能建议降价或关停。
正确解决方案: 检查是否存在任何非提价类型的候选,如果有则排除:
# ✅ 完整逻辑
elif ad_age <= EARLY_GROWTH_DAYS: # 4-7天
if not (bid_up_candidate or scale_up_candidate):
# 检查是否有其他候选标记
has_any_candidate = roi_low or decay_signal or bid_down_candidate
if has_any_candidate:
normal_ads_count += 1
logger.debug(
f"广告 {row['ad_id']} 处于早期成长期({ad_age}天),"
f"年龄保护:仅允许提价/扩量,其他候选已排除"
f"(roi_low={roi_low}, decay={decay_signal}, bid_down={bid_down_candidate})"
)
age_protected_skip = True
关键位置:
examples/auto_put_ad_mini/tools/ad_decision.pyget_ads_for_review()(约996-1020行)设计原则:
验证方法:
# 运行后检查兜底检查触发次数
grep "兜底检查触发" outputs/decision_log_*.log | wc -l
# 应该输出 0
问题描述:
代码或测试中使用硬编码的日期参数(如 --date 20260415),导致无法使用最新数据。
解决方案:
默认使用"昨天"日期:
from datetime import datetime, timedelta
default_date = (datetime.now() - timedelta(days=1)).strftime("%Y%m%d")
预防措施:
grep -r "20260[0-9]" --include="*.py"验证决策流程完整性:
# 1. 检查metrics CSV列
head -1 outputs/metrics_*.csv | tr ',' '\n' | nl
# 2. 检查决策CSV列(应包含所有metrics字段)
head -1 outputs/reports/decisions_*.csv | tr ',' '\n' | nl
# 3. 对比OUTPUT_COLUMNS定义
grep "OUTPUT_COLUMNS = " tools/report_generator.py -A 20
# 4. 检查Excel文件实际列数
python3 -c "import pandas as pd; print(pd.read_excel('outputs/reports/approval_table_*.xlsx').columns.tolist())"
验证年龄保护逻辑:
# 检查兜底检查触发情况
grep "兜底检查触发" outputs/decision_log_*.log
# 应该输出空(0个触发)
每次修改决策相关代码后,执行以下检查:
cd examples/auto_put_ad_mini && .venv/bin/python3 execute_once.pyhead -1 outputs/metrics_*.csvhead -1 outputs/reports/decisions_*.csvgrep "兜底检查触发" outputs/decision_log_*.log 应为空grep -r "20260[0-9]" --include="*.py" | grep -v ".venv"文档更新:2026-04-20 记录原因:这些问题已反复出现多次,必须明确文档化以防止再次发生
QWEN_API_KEY (通义千问)OPEN_ROUTER_API_KEY (OpenRouter,可选)GEMINI_API_KEY (Gemini,可选)# Python 依赖
pip install -r requirements.txt
# 前端依赖(可选)
cd frontend/react-template
npm install
agent/README.mdexamples/*/agent/docs/最后更新: 2026-04-09 维护者: liulidong