工具箱含四份结构模板(产品事实/供应商/供货关系/证书,YAML 与 Airtable 两版)、一份校验规则、三条提示词(资料抽取/一致性对账/产品页生成)、三个确定性脚本(单位换算/发布前泄露自查/事实层与线上对账)、60 词工业泵中英术语表、资产处理规范和三份检查清单。最小可用集只需产品事实模板 + 抽取提示词 + 上新清单三件。
产品事实层工具箱:结构模板、提示词与校验脚本
这是模块十四的收口。前面六篇讲的是为什么这样想,这一篇是照着抄的东西。
正文六篇一律不放长代码,所有实现件都收在这里。这样安排的好处是:你不认同某条思路可以不用对应的件,也不影响其它部分;反过来,你换成 Notion、Airtable 甚至 Excel,思路一样成立,只是把下面的 YAML 换成表格字段。
最小可用集:如果只想先跑起来,取三件就够——产品事实模板、抽取提示词、上新清单。
一、目录结构与密级边界
项目根/
├── src/data/facts/ # ✅ 可公开,进构建
│ ├── products.yaml # 产品事实(型号 / 参数 / 认证)
│ ├── certificates.yaml # 证书(编号 / 机构 / 有效期)
│ └── glossary.yaml # 中英术语表
│
├── internal/ # ⛔ 绝不进构建,不进公开仓库
│ ├── suppliers.yaml # 供应商档案
│ └── sourcing.yaml # 供货关系(成本 / MOQ / 交期)
│
└── scripts/
├── convert-units.mjs # 单位换算
├── check-leaks.mjs # 发布前泄露自查
└── reconcile.mjs # 事实层 ↔ 线上对账
两条铁规矩:
internal/加进.gitignore(或放独立私有仓库)。src/下任何文件不得引用它internal/从第一天起就不进公开仓库。已经进过的话,改当前版本没用,历史里还在——只能重写历史或换仓库,并假设已泄露
为什么按目录分而不是按字段分:让“能不能公开”变成一个由文件位置就能回答的问题。理由见两种死法。
二、模板一:产品事实(products.yaml)
每个数值型字段带值 + 单位 + 工况 + 出处 + 可信度五样,理由见什么才算一条产品事实。
- id: CP-100-SS316 # 永不复用、永不修改
model: "CP-100"
variant: "SS316 casing"
category: centrifugal # 关联到品类维度
slug: "cp-100-ss316" # 可改,与 id 分离
status: active # active | eol | sample_only | planned
eol_replacement: null # status=eol 时填替代型号 id
specs:
- key: max_flow
label: "Max Flow Rate"
value: 120
unit: "m3/h"
condition: "2900 rpm, clean water, 20°C" # 必填,数值型字段无此项不允许发布
confidence: supplier_doc # verified | supplier_doc | verbal | estimated
source:
doc: "CP100-datasheet-v3.pdf"
page: 2
received: 2026-05-11
- key: casing_material
label: "Casing Material"
value: "SS316"
unit: null # 非数值型,unit 与 condition 可为 null
condition: null
confidence: supplier_doc
source: { doc: "CP100-datasheet-v3.pdf", page: 1, received: 2026-05-11 }
certs: [CERT-CE-0031]
images:
- file: "centrifugal-pump-cp-100-ss316-front.webp"
alt: "CP-100 SS316 centrifugal pump, front view"
rights: supplier_granted_written # 见第八节
datasheet_public: "/downloads/cp-100-datasheet-en.pdf"
updated_at: 2026-08-06
Airtable / Notion 版字段(同一套结构,换成表格):
| 表 | 字段 |
|---|---|
| Products | ID、Model、Variant、Category、Slug、Status、EOL Replacement、Updated At |
| Specs | Product(关联)、Key、Label、Value、Unit、Condition、Confidence(单选)、Source Doc、Source Page、Received |
| Certificates | Cert ID、Type、Number、Issuer、Issued、Expires、Scan File |
| Images | Product(关联)、File、Alt、Rights(单选) |
Specs 单独一张表是关键——一个产品有多条参数,每条都要带自己的工况和出处。塞进主表的多行文本里就没法校验也没法对账了。
三、模板二~四:证书、供应商、供货关系
certificates.yaml(可公开,但有效期要盯)
- id: CERT-CE-0031
type: "CE" # CE | ATEX | UL | ISO9001 | NSF | FDA ...
number: "CE-2024-88712"
issuer: "TÜV SÜD"
scope: "CP-100 series, EU Machinery Directive 2006/42/EC"
issued: 2024-03-15
expires: 2027-03-14 # 必填。到期前 60 天触发提醒
scan: "internal/certs/ce-2024-88712.pdf" # 扫描件放内部,页面只显示编号
internal/suppliers.yaml(⛔ 内部)
- id: SUP-0007
name: "XX 泵业有限公司"
location: "浙江温州"
contact: { person: "王工", wechat: "...", email: "..." }
qualifications: ["ISO 9001:2015", "ISO 14001"]
capabilities: ["SS316 铸造", "双相钢铸造", "ISO 9906 Grade 2 水力测试"]
payment_terms: "30% 定金 + 70% 见提单"
notes: "打样快,批量交期不稳" # 主观笔记,只在内部
capabilities 值得注意:厂名不能公开,但能力描述可以改写后公开——“我们对接的产线具备 SS316 与双相钢铸造能力”。这就是藏关系不藏能力的具体做法。
internal/sourcing.yaml(⛔ 内部,一个产品对多家)
- product: CP-100-SS316
supplier: SUP-0007
role: primary # primary | backup | sampling
cost: { amount: 3200, currency: CNY, ex_works: true }
moq: 5
lead_time_days: 25
price_valid_until: 2026-09-30 # 必填。过期自动标为待更新
updated_at: 2026-08-06
- product: CP-100-SS316
supplier: SUP-0012
role: backup
cost: { amount: 3050, currency: CNY, ex_works: true }
moq: 10
lead_time_days: 30
price_valid_until: 2026-08-31
updated_at: 2026-07-20
备供和打样的字段可以留空——按角色的实际需要填,不要求每家都填满。
四、校验规则:让脏数据过不了构建
这是 AI 写入的护栏。放在 Astro 的内容配置旁,构建时自动跑;不用 Astro 的话,单独写个 validate.mjs 在提交前跑,效果一样。
// scripts/facts-schema.mjs
import { z } from 'zod';
const CONFIDENCE = ['verified', 'supplier_doc', 'verbal', 'estimated'];
const UNITS = ['m3/h', 'L/min', 'm', 'bar', 'kW', 'rpm', 'mm', '°C', 'cP', '%', null];
const source = z.object({
doc: z.string().min(1),
page: z.number().int().positive(),
received: z.coerce.date(),
});
const spec = z.object({
key: z.string().regex(/^[a-z0-9_]+$/),
label: z.string().min(1),
value: z.union([z.number(), z.string()]),
unit: z.enum(UNITS).nullable(),
condition: z.string().nullable(),
confidence: z.enum(CONFIDENCE),
source: source,
}).refine(
// 规则一:数值型字段必须有工况
(s) => typeof s.value !== 'number' || (s.condition && s.condition.length > 0),
{ message: '数值型参数必须填写 condition(工况条件)' }
).refine(
// 规则二:数值型字段必须有单位(百分比与无量纲除外,用 '%' 或显式 null 声明)
(s) => typeof s.value !== 'number' || s.unit !== undefined,
{ message: '数值型参数必须声明 unit' }
);
export const productSchema = z.object({
id: z.string().regex(/^[A-Z0-9-]+$/),
model: z.string().min(1),
variant: z.string().nullable(),
category: z.string().min(1),
slug: z.string().regex(/^[a-z0-9-]+$/),
status: z.enum(['active', 'eol', 'sample_only', 'planned']),
eol_replacement: z.string().nullable(),
specs: z.array(spec).min(1),
certs: z.array(z.string()).default([]),
images: z.array(z.object({
file: z.string(),
alt: z.string().min(10), // 规则三:alt 不允许敷衍
rights: z.enum(['own', 'supplier_granted_written', 'rendered']),
})).default([]),
updated_at: z.coerce.date(),
}).refine(
// 规则四:停产必须指明替代型号(可以是品类,但不能空着)
(p) => p.status !== 'eol' || !!p.eol_replacement,
{ message: 'status=eol 必须填 eol_replacement' }
);
四条规则各自防的事:
| 规则 | 防的是 |
|---|---|
| 数值必须有工况 | 「120 m³/h」这种没有意义的数进入事实层 |
| 可信度是枚举 | AI 随手填一个自由文本,导致措辞模板匹配不上 |
| alt 至少 10 字符 | 批量生成时 alt 被填成 “product image” |
| 停产必须有替代 | 下线时没有 301 目标,权重直接丢掉 |
还要单独跑一个悬空引用检查:certs 里的每个 id 在 certificates.yaml 里存在、sourcing.yaml 里的 product / supplier 都存在、eol_replacement 指向的型号存在。
五、提示词一:资料抽取
用途:把供应商的 PDF / Excel / 微信截图变成结构化条目。核心是三条硬要求,理由见AI 的边界。
你是产品资料录入助手。下面是供应商提供的原始资料。
把其中的产品事实抽取成 JSON,严格遵守以下规则:
【铁律,违反任何一条都算任务失败】
1. 只抽取原文中明确出现的值。禁止推测、禁止按同类产品补全、禁止取行业典型值。
2. 原文没有的字段,一律输出 null,并把字段名加入 missing 数组。
输出 null 是正确行为,编一个合理的值是严重错误。
3. 每个值必须回填 source(文件名 + 页码)和 quote(原文片段,10-40 字,原样照抄)。
无法给出 quote 的值,说明你不是抄来的 —— 把它改成 null。
【单位与换算】
- 单位原样保留,不要换算。换算由脚本完成。
- 原文单位不明确时,unit 填 null 并在 warnings 里说明。
【工况】
- 数值型参数必须找到对应的工况条件(转速 / 介质 / 温度等)。
- 原文没有交代工况的数值,condition 填 null,并加入 warnings。
【可信度】
- 正式规格书 / 检测报告 → supplier_doc
- 微信、邮件正文里的口头数字 → verbal
- 不要输出 verified(那需要我们自己实测)
输出 JSON:
{
"product": { "model": "", "variant": "", "specs": [...] },
"missing": ["字段名"],
"warnings": ["说明"],
"conflicts": []
}
【冲突】
若同一字段在资料中出现两个不同值,两个都放进 conflicts,不要自己选一个。
原始资料:
---
{{PASTE_SUPPLIER_DOC}}
---
配套的第二轮:审校者回查
抽完之后换一个角色再跑一遍,这一步能捞回相当一部分错误:
你现在是审校者,不是录入者。
下面是原始资料和一份已抽取的 JSON。逐字段核对,对每个字段输出:
- verified:JSON 的值与原文一致,并指出在原文哪一处
- mismatch:不一致,给出原文的正确值
- not_found:原文中找不到依据(这类字段必须改成 null)
不要润色、不要补全、不要评价资料质量。只做核对。
原始资料:{{DOC}}
待核对 JSON:{{JSON}}
六、提示词二:产品页生成(禁数字)
核心机制是占位符:模型只准输出 {{...}},不准输出数值,最后由脚本回填。
任务:为下面这个型号写一个英文产品页正文,面向欧美 B2B 工业买家。
【最重要的规则:禁止输出任何数字】
所有参数值、认证编号、日期、价格一律使用占位符,例如 {{max_flow}}、{{casing_material}}。
可用占位符清单如下,只能用这些:
{{AVAILABLE_PLACEHOLDERS}}
你输出的正文里如果出现任何具体数值(如 "120 m³/h"),本次任务作废。
需要提到某个数但清单里没有对应占位符时,改写句子避开它,并在末尾 notes 里说明。
【措辞受可信度约束】
- confidence=verified 的参数:可写 "delivers"、"tested at"
- confidence=supplier_doc 的参数:只能写 "rated at"、"per manufacturer specification"、"nominal"
- confidence=verbal / estimated 的参数:不会出现在占位符清单里,不要提及
本型号各参数的可信度:{{CONFIDENCE_MAP}}
【页面写作规格(来自关键词注册表)】
URL:{{URL}}
H1 与 Title 必须包含:{{PKW}}
H2 中自然出现:{{SKW}}
严禁出现的词:{{NKW}}
【要写的部分】
1. 开场段(80–120 词):这个型号解决什么问题,什么工况下选它
2. 为什么选它(100–150 词):从工程角度讲结构带来的实际好处
3. 典型应用(60–100 词):具体行业与场景,不要泛泛而谈
4. FAQ 三条:每条 ### 提问,第一句给结论。数值一律用占位符
【语气】
专业、直接、给工程师读。禁止 "world-class"、"leading"、"best quality" 这类空词。
美式英语。只输出正文,不要 frontmatter。
回填与校验(这一步是纯代码,不经模型):
// 回填占位符;任何未匹配的占位符都让流程失败
function fillPlaceholders(draft, specMap) {
const missing = [];
const filled = draft.replace(/\{\{(\w+)\}\}/g, (_, key) => {
const spec = specMap[key];
if (!spec) { missing.push(key); return `{{${key}}}`; }
return spec.unit ? `${spec.value} ${spec.unit}` : `${spec.value}`;
});
if (missing.length) {
throw new Error(`未匹配的占位符:${missing.join(', ')}`);
}
// 反向检查:正文里不该出现"裸数字 + 单位"的组合
const leaked = filled.match(/\d+(\.\d+)?\s?(m3\/h|GPM|bar|PSI|kW|rpm)/g) || [];
const expected = Object.values(specMap).map(s => `${s.value} ${s.unit}`);
const suspicious = leaked.filter(x => !expected.includes(x));
if (suspicious.length) {
throw new Error(`正文出现来源不明的数值:${suspicious.join(', ')}`);
}
return filled;
}
最后那个反向检查是兜底:万一模型无视规则直接写了数字,这里会拦住。宁可构建失败,也不要发布一个来源不明的数字。
七、三个确定性脚本
7.1 单位换算
原则:有唯一正确答案的运算不交给模型。
// scripts/convert-units.mjs
const FACTORS = {
'm3/h→GPM': 4.40287, 'L/min→GPM': 0.264172,
'm→ft': 3.28084, 'bar→PSI': 14.5038,
'kW→HP': 1.34102, 'mm→in': 0.0393701,
};
export function convert(value, from, to, digits = 1) {
if (from === '°C' && to === '°F') return +(value * 9 / 5 + 32).toFixed(digits);
const f = FACTORS[`${from}→${to}`];
if (!f) throw new Error(`未定义的换算:${from} → ${to}`);
return +(value * f).toFixed(digits);
}
公制存原值,英制在生成页面时现算——不要把换算结果也存进事实层,否则改一个值要记得改两处,又回到分叉的老路。
7.2 发布前泄露自查
在最终产物里搜内部标识,命中就让发布失败。
// scripts/check-leaks.mjs
import { readdir, readFile } from 'fs/promises';
import { join } from 'path';
import yaml from 'js-yaml';
const DIST = 'dist';
const EXT = ['.html', '.js', '.json', '.xml', '.txt', '.css'];
// 黑名单从内部文件动态生成,避免手工维护
const suppliers = yaml.load(await readFile('internal/suppliers.yaml', 'utf8'));
const NEEDLES = [
...suppliers.map(s => s.name),
...suppliers.map(s => s.id),
...suppliers.flatMap(s => [s.location, s.contact?.email, s.contact?.wechat]),
'ex_works', 'price_valid_until', 'lead_time_days', 'moq',
].filter(Boolean);
async function* walk(dir) {
for (const e of await readdir(dir, { withFileTypes: true })) {
const p = join(dir, e.name);
if (e.isDirectory()) yield* walk(p);
else if (EXT.some(x => e.name.endsWith(x))) yield p;
}
}
const hits = [];
for await (const file of walk(DIST)) {
const text = await readFile(file, 'utf8');
for (const n of NEEDLES) if (text.includes(n)) hits.push({ file, needle: n });
}
if (hits.length) {
console.error('❌ 构建产物中发现内部信息:');
for (const h of hits) console.error(` ${h.file} ← "${h.needle}"`);
process.exit(1);
}
console.log(`✅ 已扫描构建产物,未发现内部信息(${NEEDLES.length} 个标识)`);
关键设计:黑名单从内部文件动态生成。新增一家供应商不需要记得来更新脚本——这就是不让正确行为依赖记性。
放进构建流程:astro build && node scripts/check-leaks.mjs,并在 CI 里跑。
7.3 事实层 ↔ 线上对账
检出四种错配:
// scripts/reconcile.mjs —— 输出报告,不自动改任何东西
const issues = [];
for (const p of products) {
const page = pages.find(x => x.slug === p.slug);
if (p.status === 'active' && !page)
issues.push({ level: 'warn', type: '漏发', id: p.id });
if (p.status === 'eol' && page && !page.hasNoticeAndRedirect)
issues.push({ level: 'warn', type: '该下线', id: p.id });
if (page) for (const s of p.specs) {
if (!page.text.includes(`${s.value}`))
issues.push({ level: 'error', type: '参数不一致', id: p.id, key: s.key });
}
for (const certId of p.certs) {
const c = certs.find(x => x.id === certId);
if (c && new Date(c.expires) < new Date() && page)
issues.push({ level: 'error', type: '证书已过期仍在宣称', id: p.id, cert: certId });
if (c && daysUntil(c.expires) < 60)
issues.push({ level: 'warn', type: '证书即将到期', id: p.id, cert: certId });
}
}
「证书已过期仍在宣称」是唯一应该当天处理的一类。
八、中英术语表起步版
术语表属于事实层:未登记的词报错,不让模型临场翻译。下面是工业泵方向的起步版,换品类照这个格式替换即可。
# src/data/facts/glossary.yaml
# 结构类
离心泵: { en: "centrifugal pump" }
磁力泵: { en: "magnetic drive pump", alt_forbidden: ["magnetic pump"] }
齿轮泵: { en: "gear pump" }
螺杆泵: { en: "screw pump" }
自吸泵: { en: "self-priming pump" }
潜水泵: { en: "submersible pump" }
计量泵: { en: "metering pump", alt_forbidden: ["dosing pump"] }
卧式: { en: "horizontal" }
立式: { en: "vertical" }
单级: { en: "single-stage" }
多级: { en: "multistage" }
# 部件类
机封: { en: "mechanical seal", alt_forbidden: ["shaft seal", "sealing device"] }
填料密封: { en: "packing seal" }
叶轮: { en: "impeller" }
泵壳: { en: "casing", alt_forbidden: ["pump shell", "housing"] }
轴: { en: "shaft" }
联轴器: { en: "coupling" }
底座: { en: "base plate" }
口环: { en: "wear ring" }
# 材质类
铸铁: { en: "cast iron" }
不锈钢 304: { en: "SS304", alt_forbidden: ["stainless steel 304", "SUS304"] }
不锈钢 316: { en: "SS316", alt_forbidden: ["stainless steel 316", "SUS316"] }
双相钢: { en: "duplex stainless steel" }
哈氏合金: { en: "Hastelloy" }
氟塑料: { en: "PVDF" }
碳化硅: { en: "silicon carbide (SiC)" }
# 参数类
流量: { en: "flow rate" }
扬程: { en: "head" }
功率: { en: "power" }
效率: { en: "efficiency" }
转速: { en: "rotational speed" }
汽蚀余量: { en: "NPSH" }
黏度: { en: "viscosity" }
介质温度: { en: "media temperature" }
工作压力: { en: "operating pressure" }
防护等级: { en: "IP rating" }
绝缘等级: { en: "insulation class" }
能效等级: { en: "IE efficiency class" }
# 标准与认证
出厂测试: { en: "factory acceptance test (FAT)" }
水力性能测试: { en: "hydraulic performance test per ISO 9906" }
防爆: { en: "explosion-proof (ATEX)" }
食品级: { en: "food-grade" }
卫生级: { en: "sanitary / hygienic design" }
alt_forbidden 是明确禁用的其它译法。同一个概念只允许一种英文写法——理由不是文风统一,是避免把一个词的信号拆成三份弱信号。
九、资产处理规范
图片
文件名:品类-型号-变体-视图.webp
✅ centrifugal-pump-cp-100-ss316-front.webp
❌ IMG_20260511_143022.webp
❌ 温州XX泵业-CP100.webp ← 文件名里带厂名,等于泄露
处理顺序:重命名 → 转 WebP 压缩 → 生成多尺寸 → 清除 EXIF → 写 alt
清 EXIF 不能跳过:供应商拍的照片里可能带 GPS 位置。一行命令的事:
exiftool -all= -overwrite_original *.webp
alt 写法:型号 + 关键特征 + 视图,一句话讲清画面。不堆关键词。
✅ alt="CP-100 SS316 centrifugal pump, front view showing suction flange"
❌ alt="pump, centrifugal pump, stainless steel pump, industrial pump China"
授权(rights 字段的三个值):
| 值 | 含义 | 能不能用 |
|---|---|---|
own |
自己拍的 / 自己渲染的 | ✅ 随便用 |
supplier_granted_written |
供应商书面确认可用 | ✅ 可用,保留确认记录 |
rendered |
按尺寸图自己做的 3D / 线稿 | ✅ 可用 |
不在这三类里的图,不进事实层。去掉别家的水印不等于取得授权,只是让侵权变得不明显。拿授权其实很简单,微信问一句“这些图我可以用在自己网站上吗,麻烦回复确认一下”,截图存档。
规格书 PDF
内外两版:
| 版本 | 内容 | 位置 |
|---|---|---|
| 内部版 | 供应商原件,带 logo 与工厂信息 | internal/datasheets/ |
| 公开版 | 去掉供应商 logo 与工厂信息,换成自己的 | public/downloads/ |
公开版记得改 PDF 属性里的作者字段——原件的属性里常常直接写着工厂名,这是最容易漏的一条泄露路径。
exiftool -Author="Your Company" -Creator="Your Company" -Producer= cp-100-datasheet-en.pdf
留邮箱换 PDF 的话,接询盘表单那套流程即可。
十、三份清单
10.1 新产品上新清单
【入库】
□ 供应商资料齐全(规格书 / 图片 / 认证扫描件)
□ 图片与规格书的使用授权已书面确认
□ 跑抽取提示词 → 得到 JSON + missing + warnings + conflicts
□ 跑审校者回查 → mismatch 与 not_found 全部处理
□ 每个数值型参数有工况条件
□ 每个值有出处(文件名 + 页码 + 日期)
□ 可信度按实际来源标注,没有伪造 verified
□ conflicts 已人工裁决(或拆成两个型号)
【关键词登记】← 最容易跳过,跳过就等着自己抢自己
□ 主关键词已在注册表登记,无归属冲突
□ URL 已确定且未与已有页面重复
□ 负面边界词已列出
【发布】
□ 校验通过(schema + 悬空引用)
□ 页面正文无来源不明的数值(回填反向检查通过)
□ 措辞与可信度匹配(supplier_doc 没写成 delivers)
□ 图片已重命名 / 压缩 / 清 EXIF / 写 alt
□ 规格书公开版已去除供应商信息、改过 PDF 属性
□ 内链回品类页 + 相关场景页
□ 结构化数据已生成
□ 泄露自查脚本通过
10.2 维护日历(按腐烂速度排,不做每月全量)
| 触发条件 | 动作 |
|---|---|
| 证书到期前 60 天 | 找供应商要新证书;到期日当天页面上的宣称必须撤下 |
| 报价有效期到 | 标为待更新;未更新前不对外报价 |
| 供应商发来新版规格书 | 按出处字段定位受影响的参数,重新抽取核对 |
| 每季度 | 问主供一次:还在产吗、参数有变吗 |
| 每季度 | 跑一次完整对账,处理四类错配 |
| 供应商通知停产 | 走下线流程(下面这份) |
10.3 停产下线清单
□ 事实层里 status 改为 eol,填上 eol_replacement
□ 页面加停产标注(别让客户询价之后才知道)
□ 页面上给出替代型号并链接过去
□ 配置 301 → 替代型号页;无替代则跳品类页
□ 从 sitemap 移除(但页面本身保留)
□ 检查站内还有哪些页面链向它,改成指向替代型号
□ 不要删除页面,不要删除事实层记录
最后两条是重点:页面积累的排名和外链是资产,记录删了就再也检不出“站上有页面但产品已不存在”这类错配。
十一、怎么开始
不要一次全建。按这个顺序,每一步都能单独产生价值:
| 步骤 | 做什么 | 产出 |
|---|---|---|
| 1 | 挑 3 个主力型号,按模板一填完整(含工况、出处、可信度) | 你会立刻发现有多少参数其实来源不明 |
| 2 | 跑一遍抽取提示词处理下一个新型号 | 验证流程能不能省时间 |
| 3 | 加上校验规则 | 从此脏数据进不来 |
| 4 | 把内部数据挪进 internal/,接上泄露自查 |
关掉最贵的那个风险 |
| 5 | 接上页面生成(占位符 + 回填) | 上新从半天变成十分钟 |
| 6 | 接上对账脚本与维护日历 | 半年后它还准 |
第 1 步就有价值,哪怕后面几步一直没做。因为那三个型号会告诉你一件事:你现在对外发布的参数里,有多少是你其实说不清来源的。
十二、扩展:真实问题挖掘(配合第 72 篇)
事实层解决“页面上的数字从哪来”,这一节解决“除了数字还该写什么”。用法见从 Reddit 挖真实用户问题。
12.1 聚类提示词
下面是一批来自技术论坛 / 客户询盘的原始提问文本。
你的任务是归纳提问,不是解答。
【绝对禁止】
- 不要回答任何技术问题
- 不要判断某个说法对不对
- 不要改写成营销文案
任何技术结论一律放进 to_verify,不要给出答案。
【输出 JSON】
{
"clusters": [
{
"topic": "用一句话概括这一类在纠结什么",
"type": "terminology | question | tradeoff | complaint",
"frequency": 出现次数,
"sources": ["来源标识"],
"raw_phrasings": ["原文照抄的片段,保留他们的用词"],
"their_terms": ["他们使用的术语,标出和我们说法不同的"],
"implied_conditions": ["提问中隐含的工况,全部视为待核实"],
"classification_confidence": "high | low"
}
],
"to_verify": [
{ "claim": "论坛里出现的技术说法", "source": "哪来的", "how_to_verify": "该问谁 / 查哪个标准" }
]
}
【四分法定义】
terminology:只是叫法不同 → 改术语表,不产出内容
question:有明确答案、答完即止
tradeoff:没有唯一答案,取决于工况取舍(最有价值)
complaint:踩坑、被坑、验货问题
拿不准是 question 还是 tradeoff 的,classification_confidence 填 low。
原始文本:
---
{{PASTE_RAW_POSTS}}
---
12.2 四分法归类与去处对照
| type | 去处 | 产出内容? |
|---|---|---|
terminology |
改 glossary.yaml,全站替换 |
❌ 不产出 |
question |
型号页 FAQ 模块 | ✅ 一问一答 |
tradeoff |
独立技术资源页 | ✅ 有立场的对比 |
complaint |
选型陷阱 / 验货要点 / 信任页 | ✅ 清单式 |
12.3 待观察清单(频次未达门槛)
# content-queue/observing.yaml
# 门槛:独立来源 ≥ 3 才进写作队列
- topic: "磁力泵在含固介质里的轴承寿命"
type: tradeoff
frequency: 2
sources: ["reddit:r/AskEngineers", "inquiry:2026-06-18"]
first_seen: 2026-06-18
status: observing # observing | queued | written | dropped
note: "再出现一次就写"
status: dropped 是必须保留的一个值——明确判断为个例并放弃,比让它永远挂在待办里好。
12.4 待核实清单
论坛说法进不了事实层,只能进这里(理由见什么才算一条产品事实):
# content-queue/to-verify.yaml
- claim: "CP-100 介质温度上限 120°C"
confidence: verbal # 论坛陌生人说的,最低档
source: "reddit:r/AskEngineers, 2026-07-02"
how_to_verify:
- 向主供索取温度-材质对应表
- 查密封件材质标准耐温
status: open # open | verified | rejected
resolved_value: null # 核实后填入,然后才允许进 products.yaml
只有 status: verified 的条目才能变成事实层里的一条参数,并且要按正常规则带上工况、可信度和出处。
12.5 效果验证记录
三个信号,手工记就够(做法见第 72 篇):
□ GSC 该页面是否出现未登记过的长尾 query?(写完 2–6 周后看)
□ 把原始问题丢进 ChatGPT / Perplexity,是否引用本站?(记日期与结果)
□ 是否收到引用了本页内容的询盘?(最强信号,人工留意)
第二个信号后来有了正式做法:固定问题集 + 固定引擎 + 季度频率,结果回写进注册表。见GEO 审计升级。
十三、对外接口:fact_refs
事实层不只被页面模板读,还被GEO 意图注册表读。那张表里每条对外答案都要声明自己用了哪些事实:
# GEO 意图注册表中的一条
id: Q-017
canonical_answer: "The CP-100 handles fluids up to 80°C continuously,
or 95°C intermittently with PTFE-lined bearings."
fact_refs:
- cp-100.temp_max_continuous
- cp-100.temp_max_intermittent
引用格式就是点号路径:<product_id>.<field>,工况变体加后缀(temp_max_continuous)。不需要新增字段,事实层的现有结构直接当地址空间用。
这条引用关系换来三件事:
| 能力 | 没有 fact_refs 时怎么做 |
有了之后 |
|---|---|---|
| 供应商换版后的影响面 | 靠记性翻页面 | 查一次:哪些答案引了这个字段 |
| 数字一致性对账 | 人工核对 | 脚本扫全站答案 × 事实层,不一致即 error |
| 过期传导 | 事实层标了过期,页面照旧 | 过期字段的所有下游答案一起标红 |
校验规则加一条:fact_refs 里的路径必须在事实层存在,悬空即报错。这和第四节里“参数必须有出处”是同一类检查——只是方向相反,那条查上游,这条查下游。
反过来的约束也成立:答案里出现的每个数字都必须有对应的 fact_refs。没有的话,说明这个数字是模型编的,或者是从某封邮件里抄来但从未登记的——两种都是第 68 篇划的红线。
对账脚本在GEO 意图注册表工具箱,它复用本篇 7.x 节的事实层加载逻辑,不重复实现。
相关文章
模块十四(思路)
- 事实与表达分离:为什么产品资料要单独存一层
- 什么才算一条产品事实:工况、可信度与出处
- 供应商与产品的关系怎么想:多对多、角色与腐烂速度分层
- AI 的边界划在哪:以「错了能不能被发现」为唯一标准
- 从供应商资料到网站产品页:这条链上的顺序为什么不能换
- 事实层的两种死法:漏出去,和放过期
模块十五(内容素材来源)
上下游
- 中央关键词注册表设计 —— 需求侧的另一半
- SKU 详情页的七个模块 —— 页面长什么样
- HTML 表格规范 —— 参数表怎么渲染
- 全系列 AI Skills 工具箱 —— 前 65 篇的收口
- GEO 意图注册表工具箱 —— 消费
fact_refs的那一侧
RELATED / 相关推荐
接着读这些
按同一分类、系列与标签为你挑选。
GEO 意图注册表工具箱:模板、校验、提示词与起步问题集
GEO 意图注册表六篇正文的收口。正文只讲思路、不放长代码,所有实现件集中在这里——注册表模板(YAML 与 Airtable 两版)、校验规则、三条提示词、意图卡与四象限脚本、复述渲染组件、llms.txt 生成器、工业 B2B 起步问题集 40 问,以及存量站的四轮迁移清单。
全系列 AI Skills 工具箱汇总:Prompt 合集与使用指南
65 篇内容的收口。这篇把十二个 Skill 的说明书、脚本清单、以及贯穿全系列的执行顺序整理成一份可以直接照着用的索引,并给出三种落地路径——从零建站、已有站点改造、只用 Skills 工具箱。
事实与表达分离:为什么产品资料要单独存一层
改一个参数要翻好几个页面,根源是事实和表达混在一起了。这篇讲怎么把"型号存在吗、参数多少、谁能供"这类事实单独存成一层,让页面、报价单、询盘回复全部从它派生——以及一个能立刻看清你有没有真的建立事实源的判断标准。