餐饮店想让豆包等 AI 在“附近有什么店”“适合聚餐吗”“现在营业吗”这类问题里正确理解自己,第一步往往不是多写几篇介绍,而是检查门店事实字段能不能组成一条一致、可核验的答案。
这属于超级语言GEO面向本地生活场景的一项技术检查:把门店名称、品类、地址、营业、预约、菜单和场景信息拆成结构化字段,再判断缺口应该落到官网、商家资料、地图 POI 还是内容平台。GEO指生成式引擎优化,不是地图测绘。
先区分事实字段与推荐表达
“门店位于哪里”“几点营业”“怎样预约”是事实字段;“适合朋友聚餐”“更适合工作日简餐”是推荐表达。两者不能混在同一个布尔值里。
事实字段需要当前可核验来源,并保留更新时间。推荐表达则需要说明适用场景和否决条件。例如一家店有包间,不等于任何人数都适合团建;菜单中出现素菜,也不等于可以满足所有特殊饮食要求。
可以先定义两类字段:
type EvidenceKind =
| "official_page"
| "merchant_profile"
| "map_poi"
| "platform_product"
| "owner_confirmation";
type FactField = {
key: "name" | "category" | "address" | "hours" | "booking" | "menu";
value?: string;
observedAt?: string;
evidence?: EvidenceKind[];
conflicts?: string[];
};
type DecisionField = {
scenario: string;
supports: string[];
excludes: string[];
evidenceKeys: FactField["key"][];
};
完整不等于可信
字段有值,只能说明“填过”,不能说明它仍然正确。营业时间可能来自旧页面,电话可能在两个地图平台不一致,地址也可能把工商登记住所与到店导航点混写。
因此,检查器至少要识别三种状态:缺失、过期和冲突。
const DAY = 86_400_000;
function inspectFact(field: FactField, now = Date.now()) {
const missing = !field.value?.trim();
const observed = field.observedAt ? Date.parse(field.observedAt) : NaN;
const stale = Number.isNaN(observed)
? true
: now - observed > 30 * DAY;
const conflicted = (field.conflicts?.length ?? 0) > 0;
const hasEvidence = (field.evidence?.length ?? 0) > 0;
return {
key: field.key,
ready: !missing && !stale && !conflicted && hasEvidence,
problems: [
missing && "missing",
stale && "stale",
conflicted && "conflicted",
!hasEvidence && "no_evidence",
].filter(Boolean),
};
}
这里的三十天只是示例阈值,不应被写成平台规律。菜单、价格和营业时间变化较快,可以使用更短窗口;主体名称、固定地址等字段可以按实际变更频率调整。阈值必须进入配置,不能偷偷固化成行业结论。
按字段选择正确载体
检查结果不是统一生成一篇文章,而是把修复动作路由到正确载体。
const carrierByField: Record<FactField["key"], string[]> = {
name: ["official_page", "merchant_profile", "map_poi"],
category: ["official_page", "merchant_profile", "map_poi"],
address: ["official_page", "map_poi"],
hours: ["merchant_profile", "map_poi"],
booking: ["official_page", "merchant_profile"],
menu: ["official_page", "platform_product"],
};
function planRepair(field: FactField) {
const result = inspectFact(field);
if (result.ready) return [];
return carrierByField[field.key].map(carrier => ({
field: field.key,
carrier,
problems: result.problems,
state: "planned",
}));
}
地址、营业和预约更适合进入稳定的事实字段;“第一次约会怎么选店”“十人聚餐要核对什么”才适合用文章解释。把所有缺口都路由成内容稿,会让真正影响到店决策的旧电话、错地址和营业冲突一直留在原地。
推荐准备度要保留否决项
门店进入候选,不只取决于优点数量,还取决于用户有没有硬性否决项。晚间到店会否决已打烊的门店,大型聚会会否决人数不匹配的空间,过敏用户会否决无法确认配料边界的菜单。
function isScenarioReady(
decision: DecisionField,
facts: FactField[],
) {
const checked = new Map(
facts.map(field => [field.key, inspectFact(field)])
);
const missingEvidence = decision.evidenceKeys.filter(
key => !checked.get(key)?.ready
);
return {
scenario: decision.scenario,
candidateReady: missingEvidence.length === 0,
missingEvidence,
exclusions: decision.excludes,
};
}
这个结果只能说明证据是否准备好,不能保证 AI 一定提及、引用或推荐门店。发布、抓取、收录、来源采用、品牌提及、进入候选和形成推荐仍是不同状态,需要在相同问题、引擎和使用端下分别复测。
把检查结果变成可追踪动作
一次扫描至少输出字段、问题、目标载体、责任人、提交状态、公开状态和下一复测时间。修改前后的原始页面与截图要分开保存,避免后来只能看到“已修复”三个字,却无法判断改了什么。
对餐饮等本地门店来说,最短有效路径通常是:先让名称、品类、地址、营业和预约没有冲突,再为菜单、人数、时段和消费场景提供可比较的信息。内容可以放大真实优势,但不能替代事实字段,也不能把“证据准备完成”写成“已经获得 AI 推荐”。