规模化的 GEO 内容:如何在不损害品牌的情况下获得人工智能搜索排名
您的有机搜索流量正在下降,而这并不是因为您的搜索引擎优化变差了。根据 SparkToro 的数据,现在约有 60% 的谷歌查询以零点击告终--用户从人工智能生成的摘要中获得答案,而不是点击进入你的页面。Perplexity、ChatGPT Search、谷歌人工智能概述--这些都不是未来的威胁。它们已经在吞噬你的流量。
生成式引擎优化(GEO)是您反击的方式。传统搜索引擎优化针对排名算法(关键词、反向链接、页面速度)进行优化,而 GEO 则针对人工智能模型进行优化,这些模型通过从多个来源获取信息来撰写答案。目标是:调整内容结构,让人工智能搜索引擎在回答时引用您的品牌。
问题在于,GEO 所需的内容规模是大多数营销团队无法手动制作的。人工智能模型并不依赖单一来源,它们会综合数十个来源。要想持续显示,你需要覆盖数百个长尾查询,每个查询都针对用户可能向人工智能助手提出的特定问题。
显而易见的捷径--让 LLM 批量生成文章--会带来更严重的问题。让 GPT-4 制作 50 篇文章,你会得到 50 篇充满捏造的统计数据、重复的措辞和你的品牌从未提出过的主张的文章。这不是 GEO。这是人工智能垃圾内容,上面还印着你的品牌名称。
解决方法是将每一次生成调用都建立在经过验证的源文件基础上--真实的产品规格、经过批准的品牌信息以及 LLM 借鉴而非编造的实际数据。本教程将介绍一个基于以下三个组件的生产流水线:
- OpenClaw--一个开源的人工智能 Agents 框架,用于协调工作流程并连接 Telegram、WhatsApp 和 Slack 等消息平台。
- Milvus--处理知识存储、语义重复数据删除和 RAG 检索的向量数据库
- LLMs(GPT-4o、Claude、Gemini)--生成和评估引擎
最后,您将拥有一个工作系统,它能将品牌文档摄入 Milvus 支持的知识库,将种子主题扩展为长尾查询,进行语义重复,并批量生成具有内置质量评分功能的文章。
注:这是一个为实际营销工作流程构建的工作系统,但代码只是一个起点。您需要根据自己的使用情况调整提示、评分阈值和知识库结构。
管道如何解决数量 × 质量问题
| 组件 | 作用 |
|---|---|
| OpenClaw | Agents 协调、消息集成(Lark、Telegram、WhatsApp) |
| Milvus | 知识存储、语义重复数据删除、RAG 检索 |
| LLMs (GPT-4o、Claude、Gemini) | 查询扩展、文章生成、质量评分 |
| 嵌入模型 | 将文本转化为 Milvus 的向量(OpenAI,默认为 1536 维度) |
管道分两个阶段运行。第 0 阶段将源材料输入知识库。第 1 阶段从中生成文章。
下面是第 1 阶段发生的情况:
- 用户通过 Lark、Telegram 或 WhatsApp 发送信息。OpenClaw 收到信息后会将其发送给 GEO 生成技能。
- 该技能使用 LLM(真实用户向人工智能搜索引擎提出的具体问题)将用户的主题扩展为长尾搜索查询。
- 每个查询都会被嵌入,并与 Milvus 进行语义重复检查。与现有内容过于相似(余弦相似度大于 0.85)的查询会被删除。
- 存活的查询会同时触发两个 Milvus Collections 中的 RAG 检索:知识库(品牌文档)和文章档案(以前生成的内容)。这种双重检索方式使输出内容始终以真实源材料为基础。
- LLM 利用检索到的上下文生成每篇文章,然后根据 GEO 质量标准进行评分。
- 完成后的文章会写回 Milvus,为下一批内容充实演绎和 RAG 池。
GEO 技能定义还包含优化规则:以直接回答为引导、使用结构化格式、明确引用来源并包含原创分析。人工智能搜索引擎会根据结构对内容进行解析,并优先处理无来源的声明,因此每条规则都与特定的检索行为相对应。
生成分批进行。第一轮交由客户审核。一旦方向得到确认,管道就会扩展到全面生产。
为什么知识层是 GEO 与人工智能垃圾邮件的区别?
知识层是该管道与 "只是提示 ChatGPT "的区别所在。如果没有知识层,LLM 的输出看起来光鲜亮丽,但却说不出任何可验证的内容--而人工智能搜索引擎越来越善于发现这一点。Milvus 是为这一管道提供动力的向量数据库,它在这里带来了几项重要的功能:
语义重复数据删除可以捕捉关键词所忽略的内容。关键词匹配将 "Milvus 性能基准 "和 "Milvus 与其他向量数据库相比如何?"视为不相关的查询。向量相似性识别出它们问的是同一个问题,因此管道会跳过重复的问题,而不是浪费一次生成调用。
双 Collections RAG 将来源和输出分开。 geo_knowledge 存储摄入的品牌文档。geo_articles 存储生成的内容。每个生成查询都会同时访问这两个集合--知识库会保持事实的准确性,而文章档案则会保持整个批次的基调一致。这两个 Collections 是独立维护的,因此更新源材料绝不会影响现有文章。
随规模扩大而改进的反馈回路。每篇生成的文章都会立即写回 Milvus。下一批文章将拥有更大的重复数据池和更丰富的 RAG 上下文。随着时间的推移,质量会不断提高。
多种部署选项,满足不同需求。
Milvus Lite:Milvus 的轻量级版本,只需一行代码即可在笔记本电脑上运行,无需 Docker。非常适合原型开发,本教程只需要它。
MilvusStandalone 和 Milvus Distributed:用于生产的可扩展性更强的版本。
Zilliz Cloud是零烦恼的托管 Milvus。您完全不必担心技术设置和维护。提供免费层。
本教程使用 Milvus Lite - 无需创建账户,无需安装pip install pymilvus 以外的其他程序,一切都在本地运行,因此您可以在承诺任何事情之前尝试完整的管道。
部署的不同之处在于 URI:
MILVUS_URI = "./geo_milvus.db" # Local dev (Milvus Lite, no Docker needed)
MILVUS_URI = "https://xxx.zillizcloud.com" # Production (Zilliz Cloud)
client = MilvusClient(uri=MILVUS_URI)
逐步教程
整个管道打包为 OpenClaw Skill - 一个包含SKILL.MD 指令文件和代码执行的目录。
skills/geo-generator/
├── SKILL.md # Skill definition (instructions + metadata)
├── index.js # OpenClaw tool registration, bridges to Python
├── requirements.txt
└── src/
├── config.py # Configuration (Milvus/LLM connection)
├── llm_client.py # LLM wrapper (embedding + chat)
├── milvus_store.py # Milvus operations (article + knowledge collections)
├── ingest.py # Knowledge ingestion (documents + web pages)
├── expander.py # Step 1: LLM expands long-tail queries
├── dedup.py # Step 2: Milvus semantic deduplication
├── generator.py # Step 3: Article generation + GEO scoring
├── main.py # Main pipeline entry point
└── templates/
└── geo_template.md # GEO article prompt template
第1步:定义OpenClaw技能
SKILL.md 定义OpenClaw技能,告诉OpenClaw这个技能能做什么以及如何调用它。它公开了两个工具:geo_ingest ,用于向知识库提供信息;geo_generate ,用于批量生成文章。它还包含GEO优化规则,这些规则决定了LLM生成的内容。
---
name: geo-generator
description: Batch generate GEO-optimized articles using Milvus vector database and LLM, with knowledge base ingestion
version: 1.1.0
user-invocable: true
disable-model-invocation: false
command-dispatch: tool
command-tool: geo_generate
command-arg-mode: raw
metadata: {"openclaw":{"emoji":"📝","primaryEnv":"OPENAI_API_KEY","requires":{"bins":["python3"],"env":["OPENAI_API_KEY"],"os":["darwin","linux"]}}}
---
# GEO Article Batch Generator
## What it does
Batch generates GEO (Generative Engine Optimization) articles optimized for AI search engines (Perplexity, ChatGPT Search, Google AI Overview). Uses Milvus for semantic deduplication, knowledge retrieval, and knowledge base storage. LLM for content generation.
Tools
geo_ingest — Feed the knowledge base
Before generating articles, users can ingest authoritative source materials to improve accuracy:
- Local files: Markdown, TXT, PDF documents
- Web URLs: Fetches page content automatically
Examples:
- “Ingest these Milvus docs into the knowledge base: https://milvus.io/docs/overview.md”
- “Add these files to the GEO knowledge base: /path/to/doc1.md /path/to/doc2.pdf”
geo_generate — Batch generate articles
When the user sends a message like "Generate 20 GEO articles about Milvus vector database":
- Parse intent — Extract: topic keyword, target count, optional language/tone
- Expand long-tail questions — Call LLM to generate N long-tail search queries around the topic
- Deduplicate via Milvus — Embed each query, search Milvus for similar existing content, drop duplicates (similarity > 0.85)
- Batch generate — For each surviving query, retrieve context from BOTH knowledge base and previously generated articles, then call LLM with GEO template
- Store & export — Write each article back into Milvus (for future dedup) and save to output files
- Report progress — Send progress updates and final summary back to the chat
Recommended workflow
- First ingest authoritative documents/URLs about the topic
- Then generate articles — the knowledge base ensures factual accuracy
GEO Optimization Rules
Every generated article MUST include:
- A direct, concise answer in the first paragraph (AI engines extract this)
- At least 2 citations or data points with sources
- Structured headings (H2/H3), bullet lists, or tables
- A unique perspective or original analysis
- Schema-friendly metadata (title, description, keywords)
Output format
For each article, return:
- Title
- Meta description
- Full article body (Markdown)
- Target long-tail query
- GEO score (0-100, self-evaluated)
Guardrails
- Never fabricate citations or statistics — use data from the knowledge base
- If Milvus is unreachable, report the error honestly
- Respect the user’s specified count — do not over-generate
- All progress updates should include current/total count
步骤 2:注册工具并连接到 Python
OpenClaw在Node.js上运行,但GEO流水线使用的是Python语言。index.js 将两者连接起来–它将每个工具注册到OpenClaw,并委托相应的Python脚本执行。
function _runPython(script, args, config) {
return new Promise((resolve) => {
const child = execFile("python3", [script, ...args], {
maxBuffer: 10 * 1024 * 1024,
env: { ...process.env, ...config?.env },
}, (error, stdout) => {
// Parse JSON result and return to chat
});
child.stdout?.on("data", (chunk) => process.stdout.write(chunk));
});
}
// Tool 1: Ingest documents/URLs into knowledge base
async function geo_ingest(params, config) {
const args = [];
if (params.files?.length) args.push(“–files”, …params.files);
if (params.urls?.length) args.push(“–urls”, …params.urls);
return _runPython(INGEST_SCRIPT, args, config);
}
// Tool 2: Batch generate GEO articles
async function geo_generate(params, config) {
return _runPython(MAIN_SCRIPT, [
“–topic”, params.topic,
“–count”, String(params.count || 20),
“–output”, params.output || DEFAULT_OUTPUT,
], config);
}
第三步:摄取源材料
在生成任何内容之前,你需要一个知识库。ingest.py 抓取网页或读取本地文档,将文本分块、嵌入并写入 Milvus 中的geo_knowledge Collections。这样才能使生成的内容基于真实信息,而不是 LLM 的幻觉。
def ingest_sources(files=None, urls=None):
llm = get_llm_client()
milvus = get_milvus_client()
ensure_knowledge_collection(milvus)
<span class="hljs-keyword">for</span> url <span class="hljs-keyword">in</span> urls:
text = extract_from_url(url) <span class="hljs-comment"># Fetch and extract text</span>
chunks = chunk_text(text) <span class="hljs-comment"># Split into 800-char chunks with overlap</span>
embeddings = get_embeddings_batch(llm, chunks)
records = [
{<span class="hljs-string">"embedding"</span>: emb, <span class="hljs-string">"content"</span>: chunk,
<span class="hljs-string">"source"</span>: url, <span class="hljs-string">"source_type"</span>: <span class="hljs-string">"url"</span>, <span class="hljs-string">"chunk_index"</span>: i}
<span class="hljs-keyword">for</span> i, (chunk, emb) <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(<span class="hljs-built_in">zip</span>(chunks, embeddings))
]
insert_knowledge(milvus, records)
第 4 步:扩展长尾查询
给定一个类似于 "Milvus 向量数据库 "的主题,LLM 会生成一组具体、真实的搜索查询,也就是真实用户在人工智能搜索引擎中输入的问题。提示涵盖不同的意图类型:信息、比较、如何操作、解决问题和常见问题。
SYSTEM_PROMPT = """\
You are an SEO/GEO keyword research expert. Generate long-tail search queries.
Requirements:
1. Each query = a specific question a real user might ask
2. Cover different intents: informational, comparison, how-to, problem-solving, FAQ
3. One query per line, no numbering
"""
def expand_queries(client, topic, count):
user_prompt = f"Topic: {topic}\nPlease generate {count} long-tail search queries."
result = chat(client, SYSTEM_PROMPT, user_prompt)
queries = [q.strip() for q in result.strip().splitlines() if q.strip()]
return queries[:count]
第五步:通过 Milvus 进行重复搜索
这就是向量搜索的优势所在。每个扩展查询都会嵌入geo_knowledge 和geo_articles Collections 并与之比较。如果余弦相似度超过 0.85,则说明该查询与系统中已有的内容在语义上重复,因此会被丢弃,从而防止管道生成五篇略有不同但都回答了相同问题的文章。
def deduplicate_queries(llm_client, milvus_client, queries):
embeddings = get_embeddings_batch(llm_client, queries)
unique = []
for query, emb in zip(queries, embeddings):
if is_duplicate(milvus_client, emb, threshold=0.85):
print(f" [Dedup] Skipping duplicate: {query}")
continue
unique.append((query, emb))
return unique
步骤 6:使用双源 RAG 生成文章
对于每个存活的查询,生成器都会从 Milvus 的两个 Collections 中检索上下文:从geo_knowledge 中检索权威的源材料,从geo_articles 中检索以前生成的文章。这种双重检索可保持内容的事实基础(知识库)和内部一致性(文章历史)。
def get_context(client, embedding, top_k=3):
context_parts = []
<span class="hljs-comment"># 1. Knowledge base (authoritative sources)</span>
<span class="hljs-keyword">for</span> hit <span class="hljs-keyword">in</span> search_knowledge(client, embedding, top_k):
source = hit[<span class="hljs-string">"entity"</span>][<span class="hljs-string">"source"</span>]
context_parts.append(<span class="hljs-string">f"### Source Material (from: <span class="hljs-subst">{source}</span>):\n<span class="hljs-subst">{hit[<span class="hljs-string">'entity'</span>][<span class="hljs-string">'content'</span>][:<span class="hljs-number">800</span>]}</span>"</span>)
<span class="hljs-comment"># 2. Previously generated articles</span>
<span class="hljs-keyword">for</span> hit <span class="hljs-keyword">in</span> search_similar(client, embedding, top_k):
context_parts.append(<span class="hljs-string">f"### Related Article: <span class="hljs-subst">{hit[<span class="hljs-string">'entity'</span>][<span class="hljs-string">'title'</span>]}</span>\n<span class="hljs-subst">{hit[<span class="hljs-string">'entity'</span>][<span class="hljs-string">'content'</span>][:<span class="hljs-number">500</span>]}</span>"</span>)
<span class="hljs-keyword">return</span> <span class="hljs-string">"\n\n"</span>.join(context_parts)
这两个 Collections 使用相同的嵌入维度(1536),但存储不同的元数据,因为它们的作用不同:geo_knowledge 追踪每个块的来源(用于来源归属),而geo_articles 则存储原始查询和 GEO 分数(用于 dedup 匹配和质量过滤)。
def generate_one(llm_client, milvus_client, query, embedding):
context = get_context(milvus_client, embedding) # Dual-source RAG
template = _load_template() # GEO template
user_prompt = template.replace("{query}", query).replace("{context}", context)
raw = chat(llm_client, <span class="hljs-string">"You are a senior GEO content writer..."</span>, user_prompt)
article = _parse_article(raw)
article[<span class="hljs-string">"geo_score"</span>] = _score_article(llm_client, article[<span class="hljs-string">"content"</span>]) <span class="hljs-comment"># Self-evaluate</span>
insert_article(milvus_client, article) <span class="hljs-comment"># Write back for future dedup & RAG</span>
<span class="hljs-keyword">return</span> article
Milvus 数据模型
下面是从头开始创建的每个 Collections 的外观:
# geo_knowledge — Source material for RAG retrieval
schema.add_field("embedding", DataType.FLOAT_VECTOR, dim=1536)
schema.add_field("content", DataType.VARCHAR, max_length=65535)
schema.add_field("source", DataType.VARCHAR, max_length=1024) # URL or file path
schema.add_field("source_type", DataType.VARCHAR, max_length=32) # "file" or "url"
# geo_articles — Generated articles for dedup + RAG
schema.add_field(“embedding”, DataType.FLOAT_VECTOR, dim=1536)
schema.add_field(“query”, DataType.VARCHAR, max_length=512)
schema.add_field(“title”, DataType.VARCHAR, max_length=512)
schema.add_field(“content”, DataType.VARCHAR, max_length=65535)
schema.add_field(“geo_score”, DataType.INT64)
运行管道
将skills/geo-generator/ 目录放入 OpenClaw 技能文件夹,或将压缩文件发送给 Lark,让 OpenClaw 安装。你需要配置你的OPENAI_API_KEY 。
然后,通过聊天信息与管道进行交互:
例 1:将源 URL 录入知识库,然后生成文章。
例 2:上传一本书(《呼啸山庄》),然后生成 3 篇 GEO 文章并导出到云雀文档。
将此管道用于生产
本教程中的所有内容都是在 Milvus Lite 上运行的,也就是说,它是在你的笔记本电脑上运行的,当你的笔记本电脑停止运行时,它也会停止运行。对于真正的 GEO 管道来说,这还不够。你需要在开会时生成文章。你希望在下周二同事进行批处理时,知识库还能可用。
此时,有两种解决方案。
使用 Standalone 或 Distributed 模式自行托管 Milvus。你的工程团队在服务器上安装完整版本--一台专用计算机,可以是物理计算机,也可以从 AWS 等云提供商处租用。它功能强大,能让你完全控制部署,但确实需要一个专门的工程团队来设置、维护和扩展。
使用 Zilliz Cloud。Zilliz Cloud 是完全托管的 Milvus,在其基础上具有更先进的企业级功能,由同一团队构建。
操作和维护零烦恼。
提供免费层级。 免费层包括 5GB 的存储空间--足够摄取《呼啸山庄》的全部内容 360 次或 360 本图书。对于较大的工作负载,还提供 30 天的免费试用。
总是第一时间获得新功能。当 Milvus 发布改进功能时,Zilliz Cloud 会自动获取,无需等待团队安排升级。
MILVUS_URI = "https://xxx.zillizcloud.com" # That's the only change.
client = MilvusClient(uri=MILVUS_URI)
注册 Zilliz Cloud,体验一下吧。
当 GEO 内容生成适得其反时
GEO 内容生成的效果取决于其背后的知识库。在以下几种情况下,这种方法弊大于利:
没有权威的原始资料。没有坚实的知识基础,LLM 只能依赖训练数据。输出结果充其量是通用的,最差也是幻觉。RAG步骤的全部意义在于将生成建立在经过验证的信息基础之上--跳过这一步,你就只是在进行额外步骤的提示工程。
宣传不存在的东西。如果产品与描述不符,那就不是 GEO,而是错误信息。自我评分步骤会发现一些质量问题,但它无法验证知识库中不存在矛盾的说法。
您的受众纯粹是人类。GEO 优化(结构化标题、第一段直接回答、引用密度)是为人工智能的可发现性而设计的。如果您纯粹是为人类读者撰写文章,就会感觉公式化。了解您的目标受众。
关于删除阈值的说明。管道会丢弃余弦相似度超过 0.85 的查询。如果有太多近似重复的查询通过,请降低阈值。如果管道丢弃了看起来确实不同的查询,则应提高阈值。0.85 是一个合理的起点,但正确的值取决于你的主题有多狭窄。
结论
GEO 就像十年前的搜索引擎优化--足够早,正确的基础架构能为你带来真正的优势。本教程建立了一个管道,可以生成人工智能搜索引擎实际引用的文章,以品牌自身的源材料为基础,而不是以法学硕士的幻觉为基础。该堆栈由OpenClaw负责协调,Milvus负责知识存储和RAG检索,LLMs 负责生成和评分。
完整的源代码可在github.com/nicepkg/openclaw 获取。
如果您正在构建 GEO 战略,并需要基础架构的支持,请加入 Milvus Slack 社区:
- 加入Milvus Slack 社区,了解其他团队如何使用向量搜索内容、推断和 RAG。
- 预约 20 分钟的免费 Milvus Office Hours 会议,与团队一起讨论您的使用案例。
- 如果您想跳过基础架构设置,Zilliz Cloud(Milvus 托管)有一个免费层级--只需更改一个 URI,您就可以投入生产。
营销团队开始探索 GEO 时会遇到的几个问题:
我的搜索引擎优化流量正在下降。GEO是否可以取代SEO?GEO 并没有取代 SEO,而是将其扩展到了一个新的渠道。传统的搜索引擎优化仍然是通过用户点击页面来获取流量。GEO 针对的是用户在不访问网站的情况下直接从人工智能(Perplexity、ChatGPT Search、Google AI Overview)获得答案的日益增长的查询份额。如果您在分析中看到零点击率攀升,这就是 GEO 旨在夺回的流量--不是通过点击,而是通过人工智能生成的答案中的品牌引用。
GEO 内容与普通人工智能生成的内容有何不同?大多数人工智能生成的内容都是泛泛而谈--LLM 从训练数据中提取并生成听起来合理的内容,但这些内容并不基于您品牌的实际事实、主张或数据。而 GEO 内容则以经过验证的源材料知识库为基础,采用 RAG(检索增强生成)技术。不同之处体现在产出上:具体的产品细节而不是模糊的概括,真实的数字而不是捏造的统计数字,以及数十篇文章中一致的品牌声音。
我需要多少篇文章才能让 GEO 起作用?没有一个神奇的数字,但逻辑是简单明了的:人工智能模型从多个来源合成每个答案。您的优质内容覆盖的长尾查询越多,您的品牌出现的频率就越高。从围绕核心主题撰写 20-30 篇文章开始,衡量哪些文章被引用(检查您的人工智能提及率和推荐流量),然后再扩大规模。
人工智能搜索引擎不会惩罚大量生成的内容吗?如果是低质量内容,它们会的。人工智能搜索引擎越来越善于检测无来源的声明、重复使用的措辞以及不增加原创价值的内容。这正是该管道包括一个知识库作为基础和一个自我评分步骤作为质量控制的原因。我们的目标不是生成更多内容,而是生成对人工智能模型真正有用的内容。
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



