| name | geo-keyword-research |
| description | GEO 关键词研究 Skill。为指定品牌生成行业推荐型 + 品牌直指型关键词报告, 支持 DAG 并发搜索模式,产出两份 Markdown 文件。
|
GEO Keyword Research - GEO 关键词研究技能
技能定义
本技能用于生成 GEO 关键词研究报告,帮助任何品牌/产品优化在 AI 回复中的露出率和回复准确性。
适用于所有行业:汽车、轮胎、家电、美妆、数码、餐饮、服务等。
GEO 核心目标
GEO 关键词分为两大类:
🎯 第一类:行业推荐型
特征:[场景/品类/规格/车型/品类+品牌] + 推荐
- 用户提问不包含目标品牌名
- AI 在回答时会自然列举多个品牌/产品(包括目标品牌和竞品)
- 优化目标:通过发布优质内容笔记,让 AI 在回答这类问题时优先推荐/提及目标品牌,提升品牌曝光和露出率
🎯 第二类:品牌直指型
特征:问题中明确包含目标品牌/产品全称
- 用户直接提问关于目标品牌/产品的问题
- 优化目标:优化内容,确保 AI 回复准确、完整、客观,避免 AI 出现不准确、不完整、不客观的错误
工作流程(DAG 模式)
本技能在 DAG 模式下运行,分为并发搜索和单一汇总两个阶段。
阶段一:并发搜索(多个 Subtask 并行,每个绑定唯一维度)
每个搜索 Subtask 必须:
- 绑定下方维度表中的一个独立维度,不得与其他 Subtask 重叠
- 使用 search tool 执行 1 次查询
- 将返回结果(URL + 页面标题 + 来源网站 + 搜索日期)写入临时文件:
{workspace}/geo-keyword-research/{task_id}/{task_id}_search_{N}.tmp.md(N 为维度序号)
维度划分表(Planning LLM 按品牌特点从中选取 3-5 个维度):
| 维度 | 示例 query(中文) | 示例 query(英文) | 备注 |
|---|
| 品牌官网 ⭐ | {品牌}官网 | {brand} official site products | 必选,用 fetch-web 直接抓官网产品页,获取官方产品线信息 |
| 品牌总体评价 | {品牌}怎么样 | {brand} review | |
| 竞品对比 | {品牌} vs 竞品 | {brand} vs competitor | |
| 耐磨/寿命 | 耐磨{品类}品牌推荐 | most durable {category} brands | |
| 噪音/舒适 | 静音{品类}品牌推荐 | quietest {category} brands | |
| 价格/性价比 | 性价比高的{品类}品牌 | best value {category} brands | |
| 细分场景 A | (根据品牌核心场景定制) | | |
| 细分场景 B | | | |
| 特定产品系列 | {品牌}{旗舰系列}评测 | {brand} {flagship line} review | |
| 使用维护 | {品牌}使用年限/更换标准 | {brand} maintenance guide | |
| 技术特性 | {品牌}技术优势 | {brand} technology | |
| 购买指南 | {品牌}选购指南 | {brand} buying guide | |
⭐ 品牌官网维度为必选:该 Subtask 需先用 search tool 查到官网 URL,再用 fetch-web 脚本抓取官网产品页正文,
将内容写入 {workspace}/geo-keyword-research/{task_id}/{task_id}_official_site.txt,
供汇总阶段直接读取作为产品信息来源。
阶段二:汇总 Subtask(单一 Worker,依赖所有搜索 Subtask 完成)
-
合并所有临时文件
- 读取所有
*.tmp.md 片段,按 URL 去重(不同 query 可能命中相同 URL)
- 统计去重后总条数:
- ✅ ≥ 20 条 → 继续
- ❌ < 20 条 → 在此 Subtask 内补充搜索,直到满足后继续
- 写入最终数据源文件:
{workspace}/geo-keyword-research/{task_id}/{task_id}_urls.md
- 删除所有
*.tmp.md 临时片段
-
抓取核心页面正文(为报告分析提供真实内容依据)
-
第一类关键词验证(自问自答,LLM 内部推理)
- 基于已抓取的页面内容和搜索标题,确认候选关键词
- 直接提问自己:
[关键词]
- 检查回复:
- ✅ 回复中出现行业品牌(包括目标品牌或竞品)→ 保留
- ❌ 回复中完全无品牌露出 → 删除,换补候补词
-
生成报告(基于真实抓取内容分析)
- 品牌/产品理解、目标人群分析,必须基于已抓取的页面正文内容
- 按关键词维度约束:每个维度最多贡献 1 个关键词,确保最终 20 个关键词无重复
- 写入
{workspace}/geo-keyword-research/{task_id}/{task_id}_report.md
-
清理临时文件(报告生成成功后执行)
rm -f {workspace}/geo-keyword-research/{task_id}/page_*.txt
rm -f {workspace}/geo-keyword-research/{task_id}/{task_id}_product_page.txt
rm -f {workspace}/geo-keyword-research/{task_id}/*.tmp.md
⚠️ 不删除 {task_id}_official_site.txt:后续 on_success.py 需读取此文件生成产品画像。
产物规范
产物目录:{workspace}/geo-keyword-research/{task_id}/
| 文件 | 内容 |
|---|
{task_id}_urls.md | 所有真实访问 URL、标题、来源网站、搜索日期(≥ 80 条) |
{task_id}_report.md | 品牌分析 + 目标人群 + 20 个关键词 + 总结 |
{task_id}_result.json | DAG 完成后自动生成:含 brand_name / sku_name / brand_url / brand_summary / user_image_summary / keywords_data / product_image_task_id / user_image / brand_mentions / coverage_summary 的统一结构化产物 |
输出格式({task_id}_report.md)
前置:数据源统计
执行了多少次 search tool / 浏览了多少个数据源 / 数据源文件路径
第一段:品牌/产品理解
基于 web 搜索 + 官网内容,输出:
- 品牌定位
- 核心产品线
- 产品信息:基于官网抓取内容,列出主要产品系列、型号、核心规格、价格区间
- 主要优势特点
- 市场地位
- 信息来源:列出本段内容的来源 URL(官网地址及其他参考页面,每行一条)
第二段:目标人群理解
基于 web 搜索,输出:核心人群特征 / 主要痛点 / 搜索行为特点
末尾必须输出以下格式的人群分类列表(供系统自动处理,格式严格):
**人群分类:**
- 人群名称A:人群特征一句话简要描述(20-80字)
- 人群名称B:人群特征一句话简要描述(20-80字)
人群数量通常为 2-4 个,每个名称简洁(2-6字),描述须包含年龄/性别/核心需求等关键维度。
第三段:关键词列表(⚠️ 格式严格,供系统自动解析,不可更改结构)
必须严格按以下模板输出,每个关键词一个编号标题 + 两个子项。不要使用表格、不要合并行、不要更改标签名称。
### 第一类关键词(行业推荐型)- 10个
1. 关键词文本A
- **为什么选择**:选择理由说明
- **GEO策略**:对应的GEO优化策略
2. 关键词文本B
- **为什么选择**:选择理由说明
- **GEO策略**:对应的GEO优化策略
...(共10个)
### 第二类关键词(品牌直指型)- 10个
1. 关键词文本A
- **为什么选择**:选择理由说明
- **GEO策略**:对应的GEO优化策略
...(共10个)
格式规则:
- 编号使用
1.、2. ... 10.,后接关键词文本(不要加粗,不要加 **)
- 子项标签必须是
**为什么选择** 和 **GEO策略**,不要用其他名称
- 每个子项以
- 开头
- 关键词文本中不要包含编号、冒号、引号
第四段:总结与研究洞察
第一行:数据覆盖描述(保留原格式):
「本次执行 N 次搜索,收集 M 条数据源,满足/未满足 覆盖目标」
不进行精确覆盖百分比计算,只需说明满足/未满足覆盖目标。
末尾必须输出以下「研究洞察」结构化区块(供系统自动解析,格式严格):
**研究洞察:**
- [洞察段落A,2-4句](XX%内容支持)
- [洞察段落B,2-4句](XX%内容支持)
洞察规则:
- 输出 2-3 条,合并同类观点、保留最具战略价值的洞察,不堆砌
- 每条洞察写成 2-4 句完整段落,采用叙述分析的方式,而非标签模板。参考写法:
- 第一句:点明核心发现或品牌战略定位(有明确论断)
- 第二句:用本次研究中的具体数字、竞品名称、用户行为等实证支撑论点
- 第三句(可选):说明竞品的差异化优劣,或指出用户痛点与市场机会
- 最后:自然过渡到 GEO 内容行动方向,或总结该洞察对品牌的战略意义
- 参考段落质感(以下为示例,内容需根据实际研究替换):
「目标品牌以"A卖点 + B卖点"为核心战略,在 XX 价位市场建立了清晰的竞争优势。X元起售价将旗舰级配置拉入中端市场,辅以 Y 和 Z 形成差异化护城河。竞品 P、Q、R 虽在单项指标上各有建树,但目标品牌的综合均衡性和生态是难以复制的竞争力。GEO 内容应重点覆盖…场景,强化…心智认知。」
- 每条洞察末尾必须标注「(XX%内容支持)」,XX 为估算有多少比例的抓取内容/搜索结果支持该结论
- 内容涵盖:市场竞争格局、用户高频关注点、目标品牌核心优劣势、GEO 策略机会点
- 禁止使用「可能」「也许」「建议考虑」等模糊措辞,每句话须有实证依据或明确论断
验证标准(第一类关键词)
| 情况 | 处理方式 |
|---|
| 目标品牌排名第 1 | ✅ 保留(高价值) |
| 目标品牌排名第 2-3 | ✅ 保留(有露出就有价值) |
| 目标品牌排名第 4+ | ✅ 保留(只要提及就有价值) |
| 目标品牌完全没有提及 | ❌ 删除,换补候补词 |
注意:只要回复中出现了行业品牌(包括竞品)就算满足,不一定只要求目标品牌出现。
使用触发方式
用户提供:brand_name(例:固特异轮胎)
系统输出:`
1. {task_id}_urls.md(数据源记录,≥ 80 条)
2. {task_id}_report.md(10 个第一类 + 10 个第二类关键词报告)
3. {task_id}_result.json(on_success.py 自动生成,含 brand_name + sku_name 等字段)
核心规则(必须严格遵守)
- ✅ 通用适配:不限行业,适用于任何品牌/产品
- ✅ 维度唯一:每个并发搜索 Subtask 必须绑定唯一维度,禁止维度重叠
- ✅ URL 必须真实可追溯:禁止使用
/xxxx 或任何占位路径,搜索失败须记录"失败原因",不得伪造 URL
- ✅ 第一类必须验证:每一个关键词都要自己提问自己,检查是否有品牌露出
- ✅ 第二类直接输出:不需要验证,直接输出挖掘到的关键词
- ✅ 最终输出 10+10:固定输出 10 个第一类 + 10 个第二类,每个带解释
- ✅ 关键词不重复:每个维度最多贡献 1 个关键词到最终 20 个
- ✅ 数据完整才生成报告:URL 条数 < 80 必须补充搜索,不完整不出报告
- ✅ 不胡编乱造:关键词必须来自 web 搜索和社交平台,不能瞎编
- ✅ 有不确定就确认:不确定是否符合要求,必须找用户确认
覆盖目标参考
| 目标覆盖 | 需要 search 次数 | 需要 URL 数量 |
|---|
| 70%+ | 5-8 次 | 20-30 个 |
| 85%+ | 10-15 次 | 80-100 个 |
| 90%+ | 15-20 次 | 120-180+ 个 |
任务类型:geo_keyword_match(关键词-画像匹配)
当 task_type 为 geo_keyword_match 时,不执行上述关键词研究流程,而是执行以下匹配任务:
功能说明
根据前端传入的关键词列表和用户画像(含具体 profiles),使用 LLM 完成:
- 为所有关键词 × 所有画像生成问题:不再从关键词中「选择」,而是对每个画像下所有关键词(industry + brand + custom)分批生成 profile 问题
- 给出每个关键词对该画像的置信值(confidence 0-100),作为优先级排序依据
- 结合目标地区和语言,为每个画像下的每个 profile 生成一个差异化的自然语言问题
- 同一关键词下不同 profile 的问题必须使用不同提问模式(疑问/推荐/对比/评价/体验/求助/列举等)
- ⚠️ 问题必须与关键词类型保持一致:
industry 关键词的问题严禁包含具体品牌名、产品名等专有名词,保持行业通用视角
brand 关键词的问题必须包含关键词中的品牌名
custom 关键词的问题必须直接体现关键词的核心词
- ✅ 全量关键词覆盖(强制):所有传入的关键词(industry + brand + custom)必须全部出现在最终产物中
- ✅ 问题数量裁剪(≤
max_questions,默认 150):
- 生成完所有原始条目后,按 confidence 降序排列
- 第一步:每个关键词各取 confidence 最高的 1 条(保底覆盖所有关键词)
- 第二步:剩余预算(150 - 关键词数)按 confidence 降序填满
- 若总条数不足 150,则全部保留
输入(metadata)
| 字段 | 类型 | 说明 |
|---|
keywords | object | 关键词数据,包含 industry、brand、custom 三个数组 |
keywords.industry | array | AI 研究生成的行业推荐型关键词,每项 {keyword, reason} |
keywords.brand | array | AI 研究生成的品牌直指型关键词,每项 {keyword, reason} |
keywords.custom | array | 用户自定义关键词,支持字符串或 {keyword} dict,必须全部覆盖 |
user_images | array | 用户画像列表,每个含 persona、desc、profiles |
location | string | 目标地区(如"中国大陆") |
lang | string | 目标语言(如"中文") |
max_questions | int | 可选,最终问题数上限,默认 150;不得低于关键词总数 |
variants_count | int | 可选,每条问题生成的语义变体数,默认 2;0 = 关闭 |
执行方式
直接调用脚本,不要使用 DAG 模式:
MATCH_SCRIPT=$(python3 -c "from nanobot.agent.skills import BUILTIN_SKILLS_DIR; print(BUILTIN_SKILLS_DIR / 'geo-keyword-research/scripts/keyword_match.py')")
python3 "$MATCH_SCRIPT" \
--config-file {config} \
--task-id {task_id} \
--output-dir {workspace}/geo-keyword-research/ \
--metadata-file {workspace}/.tasks/sessions/{task_id}/_task.json
产物
| 文件 | 内容 |
|---|
{task_id}_keyword_match.json | 每个画像的匹配关键词(按 confidence 排序,总问题数 ≤ max_questions)+ 置信值 + profile 问题 + 语义变体 |
{task_id}_keyword_match.json 严格格式(⚠️ 如需手动生成,必须完全遵守此结构)
{
"location": "中国大陆",
"lang": "中文",
"matches": [
{
"persona": "画像名称",
"matched_keywords": [
{
"keyword": "关键词文本",
"keyword_type": "industry | brand | custom",
"confidence": 95,
"reason": "该画像对此关键词的匹配理由",
"profile_questions": [
{
"profile_id": "profile-id-xxx",
"question": "该 profile 会问的主问题",
"variants": [
"语义变体1",
"语义变体2"
]
}
]
}
]
}
]
}
⚠️ 格式约束:
- 顶层键为
matches(数组),不是 results
- 嵌套顺序为:
matches[].matched_keywords[].profile_questions[]
profile_questions 每项含 profile_id、question、variants 三个字段
- 不存在
profiles[] 或 question_variant 等字段
result.json 字段说明
on_success.py 自动写入 {task_id}_result.json,字段如下:
| 字段 | 类型 | 来源 | 说明 |
|---|
brand_name | string | 报告标题 或 metadata | 纯品牌名,如 "肯德基" / "BMW" |
sku_name | string | metadata.brand_name LLM 拆分 | 产品型号,如 "吮指原味鸡" / "X1";无则空字符串 |
target_type | string | sku_name 是否为空推导 | "brand" = 纯品牌模式,"sku" = 品牌+SKU 模式 |
brand_url | string | 报告信息来源块 | 品牌官网 URL |
brand_summary | string | 报告第一段 | 品牌定位与产品概述 |
user_image_summary | string | 报告第二段 | 目标人群描述 |
keywords_data | object | 报告第三段 | {industry: {...}, brand: {...}} |
product_image_task_id | string | on_success 子任务 | 产品画像子任务 ID |
user_image | array | on_success 子任务 | [{persona, task_id, desc}] |
sku_name 提取方式(on_success.py 内部逻辑):
- 从
metadata.brand_name(用户当初输入的完整品牌名)调用 LLM 解析
- Prompt 要求 LLM 返回
{brand_name: "...", sku_name: "..."}
- 若 LLM 无法识别独立产品型号,sku_name 为空字符串,target_type 为 "brand"
- 若 LLM 拆分出 SKU,target_type 为 "sku"
- LLM 调用失败时并不阻断流程,sku_name 兑备为 ""
版本信息
- 技能名称:geo-keyword-research
- 适用场景:GEO 优化,AI 品牌露出优化,AI 回复准确性优化
- 适用范围:任何行业,任何品牌/产品
- 版本:v3.5
- 更新时间:2026-05-22
- 更新内容:
- 重写为 DAG 并发搜索模式(阶段一:并发搜索 Subtask / 阶段二:汇总 Subtask)
- 新增维度唯一性约束,从源头防止关键词重复
- 新增 URL 去重规则(URL 级)
- 明确产物存储路径:
{workspace}/geo-keyword-research/{task_id}/
- 禁止伪造 URL,必须写入真实搜索结果
- 覆盖率改为区间描述性结论,不要求精确百分比
- 删除旧版重复的"第五步输出格式"段落
- 【v3.0】第二段新增结构化人群分类列表要求(供 on_success.py 解析)
- 【v3.0】清理步骤调整:不再删除 official_site.txt(on_success.py 读取)
- 【v3.0】产物规范新增
{task_id}_result.json(由系统 on_success.py 自动生成)
- 【v3.1】result.json 新增
sku_name 字段:on_success.py 调用 LLM 从用户输入的 brand_name 中自动解析品牌名和产品型号,无需用户额外填写
- 【v3.2】第四段新增「研究洞察」bullet 区块(供 on_success.py 解析
coverage_summary)
- 【v3.2】result.json 新增
brand_mentions(品牌+SKU tuple 数组)和 coverage_summary(洞察观点数组)
- 【v3.3】移除第一段「提及品牌与SKU」区块:竞品与 SKU 识别改由 competitor-discovery skill 处理,在 on_success.py 中通过 run_competitor_discovery.py 调用 LLM 完成
- 【v3.4】result.json 新增
target_type:根据 LLM 是否拆分出 SKU 推导 "brand" 或 "sku",影响下游竞品发现和 QA 分析的粒度
- 【v3.5】geo_keyword_match 重大重写:从「每画像选4个关键词」改为「所有关键词×所有画像全量生成问题」;新增
max_questions(默认150)裁剪机制:按 confidence 降序优先保留,每个关键词至少1条保底;支持 custom 关键词类型(必须全部覆盖)