| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- // 投放目标 → 选号策略映射 + 提号 SOP 规则
- // 结构化自《01-资源寻找方法(更新版).docx》STEP06(没有参考账号时,按投放目标反推账号类型)
- // 以及《AI提号需求列表》SOP 提号规则(默认 1.5 倍提号、前 10 篇 80% 风格匹配、优先响应明确数量)。
- // 投放目标 → 账号类型映射。signals 用于从 brief 文本识别投放目标。
- const GOAL_STRATEGIES = {
- seed_conversion: {
- zh: '种草转化',
- signals: ['种草', '转化', '带货', 'ROI', '卖货', '成交', '下单', '电商', '销售', '促转化', '转化率', '转化效果'],
- accountTypes: ['真实测评账号', '垂类KOC', '素人真实体验'],
- tierHint: '偏尾部KOC与素人,重真实体验与转化,不要只看粉丝量',
- note: '重转化时优先真实测评、垂类KOC、素人真实体验;转化链路看 CPE/CPV 与评论区购买意图。'
- },
- brand_exposure: {
- zh: '品牌曝光',
- signals: ['曝光', '品牌', '声量', '认知', '知名度', '破圈', '泛流量', '打爆', '传播', '话题', '热度', '出圈'],
- accountTypes: ['垂类头部腰部KOL', '泛流量账号'],
- tierHint: '偏头部腰部KOL,重覆盖与声量,兼顾垂类可信度',
- note: '重曝光时优先垂类头部腰部KOL与泛流量账号,兼顾专业背书与覆盖。'
- },
- search_drain: {
- zh: '搜索引流',
- signals: ['搜索', '引流', '关键词', '小蓝词', '沉淀', 'SEO', '搜索词', '蓝词', '长尾', '卡位', '收录'],
- accountTypes: ['带关键词账号', '可沉淀内容账号', '小蓝词卡位账号'],
- tierHint: '内容必须带目标搜索关键词、可长期沉淀,卡搜索词/小蓝词',
- note: '搜索引流看重内容能否带目标关键词、能否长期沉淀,优先能卡搜索词/小蓝词的账号。'
- },
- campaign_volume: {
- zh: '活动冲量',
- signals: ['冲量', '活动', '铺量', '同城', '本地', '促销', '大促', '节点', '爆发', '批量', '拉新', '引流到店', '到店'],
- accountTypes: ['铺量素人', '同城本地账号'],
- tierHint: '铺量素人 + 同城本地,重数量与节点节奏',
- note: '活动冲量偏铺量素人与同城本地账号,重数量和节点节奏。'
- }
- };
- // 提号 SOP 规则(喂给 AI 提升选中率的硬规则)
- const SUGGESTION_RULES = [
- {
- id: 'suggest-1.5x',
- title: '默认提号数量 = 需求数量的 1.5 倍以上',
- multiplier: 1.5,
- description: '默认提号数量按需求数量的 1.5 倍以上输出,给客户更充分的选择与替换空间。'
- },
- {
- id: 'style-match-80',
- title: '前 10 篇笔记至少 80% 风格匹配',
- threshold: 0.8,
- description: '候选账号最近 10 篇内容至少 80% 匹配 Brief 调性,否则降级为需复核。'
- },
- {
- id: 'respond-explicit-count',
- title: '优先响应明确数量与平台分布',
- description: 'Brief 明确写了提号数量/平台分布时,严格按数量响应,不自行缩减。'
- }
- ];
- function detectGoal(text) {
- const scores = {};
- for (const [goal, strategy] of Object.entries(GOAL_STRATEGIES)) {
- scores[goal] = strategy.signals.filter(signal => String(text || '').includes(signal)).length;
- }
- let best = 'brand_exposure';
- let bestScore = -1;
- for (const [goal, score] of Object.entries(scores)) {
- if (score > bestScore) {
- best = goal;
- bestScore = score;
- }
- }
- return best;
- }
- function buildGoalStrategy(criteria = {}) {
- const text = [
- criteria.rawText,
- criteria.brand,
- criteria.category,
- ...(criteria.keywords || [])
- ].filter(Boolean).join(' ');
- const goal = detectGoal(text);
- const strategy = GOAL_STRATEGIES[goal] || GOAL_STRATEGIES.brand_exposure;
- const targetCount = Number(criteria.targetCount || 0);
- const suggestionCount = targetCount ? Math.ceil(targetCount * 1.5) : 15;
- return {
- goal,
- goalLabel: strategy.zh,
- accountTypes: strategy.accountTypes,
- tierHint: strategy.tierHint,
- note: strategy.note,
- suggestionCount,
- suggestionRules: SUGGESTION_RULES,
- suggestionNote: targetCount
- ? `Brief 目标 ${targetCount} 位,按 1.5 倍规则建议默认提号 ${suggestionCount} 位以上。`
- : 'Brief 未明确目标人数,建议默认提号 15 位以上供客户选择。'
- };
- }
- module.exports = {
- GOAL_STRATEGIES,
- SUGGESTION_RULES,
- detectGoal,
- buildGoalStrategy
- };
|