做 GEO 内容最容易踩的坑不是写得差,而是内容"对 AI 不友好"——标题层级乱、实体对不上、分块一塌糊涂,检索系统切片后提不准,自然不被引用。下面用 4 段可运行 Python,把"对 AI 友不友好"量化成发布前体检报告。所有输出均来自真实运行。
import re
def structure_report(text):
h2 = len(re.findall(r'(?m)^##\s', text))
h3 = len(re.findall(r'(?m)^###\s', text))
faq = len(re.findall(r'(?m)^\s*Q:', text))
lists = len(re.findall(r'(?m)^\s*[-*]\s+', text))
paras = [p for p in re.split(r'\n\s*\n', text) if p.strip()]
long_para = [i for i, p in enumerate(paras) if len(p) > 400]
return {
"h2": h2, "h3": h3, "faq": faq, "list_lines": lists,
"long_para_idx": long_para, "pass": h2 >= 2 and faq >= 1 and not long_para,
}
sample = """## Background
### Subsection
- point one
- point two
## Practice
Q: What is GEO?
A: GEO makes content citable by LLMs."""
print(structure_report(sample))真实运行输出:{'h2': 2, 'h3': 1, 'faq': 1, 'list_lines': 2, 'long_para_idx': [], 'pass': True}
检索系统先按 H2 切片再向量化。三条硬线:H2 不少于 2、FAQ 至少 1 对、无超过 400 字段落。没有 H2 整篇切不开,没有 FAQ 没有现成问答对可对齐,超过 400 字段落会被切成含多个主题的脏块、拉低召回。
def anchor_report(text):
BRAND = {"GEO", "RAG", "BM25", "API", "SEO"}
words = re.findall(r'[A-Za-z][A-Za-z0-9\-\.]+', text)
upper = [w for w in words if w.isupper() or w in BRAND]
faq = len(re.findall(r'Q:', text))
has_h2 = bool(re.search(r'(?m)^##\s', text))
score = min(len(set(upper)), 8) + faq * 2 + (3 if has_h2 else 0)
return {"entities": sorted(set(upper)), "faq": faq, "h2": has_h2, "anchor_score": score}
doc = "## GEO Basics\nGEO and RAG improve retrieval.\nQ: What is GEO?\nA: GEO helps LLMs cite your site."
print(anchor_report(doc))真实运行输出:{'entities': ['GEO', 'RAG'], 'faq': 1, 'h2': True, 'anchor_score': 7}
大模型对齐依赖稳定实体锚点。大写实体词(GEO/RAG/BM25/API)是跨分词器稳定的 token,纯形容词零锚点、写了也白写。锚点分 = min(实体数, 8) + FAQ×2 + (有 H2 加 3),上限 8 防堆词刷分。
def chunk(text, window=3, overlap=1):
sents = [s.strip() for s in re.split(r'(?<=[.?!])', text) if s.strip()]
step = max(1, window - overlap)
out = []
for i in range(0, len(sents), step):
g = sents[i:i + window]
if g:
out.append("".join(g))
return out
def eval_overlap(text, overlaps):
results = {}
for ov in overlaps:
chunks = chunk(text, window=3, overlap=ov)
avg_len = sum(len(c) for c in chunks) / len(chunks)
results[ov] = {"chunks": len(chunks), "avg_len": round(avg_len, 1)}
return results
doc = "Do GEO step one submit sitemap. Step two add heading. Step three embed entity. Step four add FAQ. Step five test. Step six update. Step seven analyze. Step eight optimize."
print(eval_overlap(doc, [0, 1, 2]))真实运行输出:{0: {'chunks': 3, 'avg_len': 54.7}, 1: {'chunks': 4, 'avg_len': 55.5}, 2: {'chunks': 8, 'avg_len': 51.1}}
overlap 取 0 切 3 块、取 1 切 4 块、取 2 切 8 块。本例是英文示例,单块均值 51–55;注意块长基准是语料相关的——中文内容单块约 25 字最舒服,英文/中英混排要调高(把基准改到 50 后 overlap=2 的 51.1 即最优)。教学代码里把 25 改成你的语料均值即可,逻辑不用动。
def geo_check(text):
s = structure_report(text)
a = anchor_report(text)
c = eval_overlap(text, [0, 1, 2])
best = min(c, key=lambda o: (abs(c[o]["avg_len"] - 25), -o))
return {
"structure_pass": s["pass"],
"anchor_score": a["anchor_score"],
"best_overlap": best,
"suggest": "publish" if s["pass"] and a["anchor_score"] >= 5 else "revise",
}
article = """## Why GEO
AI citation brings steady exposure to institutional content.
### Three actions
- submit sitemap
- add heading
- embed entity
## Steps
Q: What is GEO?
A: GEO is generative engine optimization, making LLMs cite your content.
Do GEO step one submit sitemap. Step two add heading. Step three embed entity. Step four add FAQ. Step five test. Step six update."""
print(geo_check(article))真实运行输出:{'structure_pass': True, 'anchor_score': 8, 'best_overlap': 2, 'suggest': 'publish'}
把前三步合成一个 geo_check,草稿粘进去跑一次,直接给结构是否达标、锚点分、最优 overlap、发布建议。示例草稿三项全过,建议 publish。注意这版草稿 9 句,跑出来最优 overlap=2——文本长短不同最优值会变,这正是自动搜比拍脑袋准的地方。
Q: 认半角冒号;中文内容若用"问:"需扩展正则,注意代码块内保持 ASCII 以免平台校验拦截。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。