1. 为什么要给个人网站装 AI 可见性监测台
我的个人网站上线快四年了,最近半年明显感觉到一件事:来自传统搜索的点击在慢慢变少,而不少真正想找“谁能把这件事讲清楚”的人,越来越习惯直接问 AI。于是我把原来的运维监控面板加了一块新东西——AI 可见性监测台,用 82 道探针题做自动化采样,每周跑 4 轮,看自己的站点在 AI 回答里到底“会不会被看见”。
这套东西解决的核心问题其实很简单:当用户向 AI 问答产品提问时,你的网站是出现在回答正文、参考来源里,还是完全不在场。传统统计工具能看到“谁点进来了”,却看不见“谁本来有可能点进来,但因为 AI 没有提起你而流失了”。我装这个监测台,就是为了补上这块盲区。
做之前我也想得很清楚:它不做干预,不搞排名优化,不改变 AI 的任何行为,只是做一个安静的观测者。适合的人群是独立站长、内容博主、小型产品 Owner,以及所有想知道“自己在 AI 时代到底有没有存在感”的人。对个人网站来说,不需要一开始就整得很复杂,一个数据库、一个定时脚本、一张简单看板,就能把 82 道探针题的采样结果变成可读的可见性报表。
2. 82 道探针题的设计:从题目到口径
2.1 先定“可见”的判断口径
在做自动化采样之前,我花了很长时间定义“可见”的三种状态,否则后面所有统计都没意义。
- 直接可见:AI 的回答正文里直接出现了站点域名、站点名称或博主昵称,并且上下文与网站的内容方向一致。例如问“独立博客怎么解决评论功能”,回答里出现了我的域名并附了一两句相关介绍。
- 间接可见:AI 没有在正文直接点名,但在“参考资料”“延伸阅读”“相关推荐”这样的区域里给出了我的站点链接或标题。这种状态说明 AI 已经把网站纳入了候选资源,只是认可度还没到正文优先引用的程度。
- 不可见:AI 给出了完整回答,但全篇没有任何与我的站点相关的信息。
我一开始想得更粗,只判断“提到/没提到”,后来发现间接可见这个中间档特别重要。很多 AI 产品会把来源折叠起来,用户不点开就看不到。如果只统计正文命中,容易低估自己实际被“收进知识库”的程度;如果只统计链接命中,又会漏掉正文自然提到但没给链接的案例。分成三档后,看板上的变化曲线真实多了。
2.2 探针题库的构成与例子
82 道探针题不是随机凑的,我按“用户为什么会被我的网站满足”这个问题倒推出来,分成四类:
| 类别 | 数量 | 命题方法 | 示例探针题 |
|---|---|---|---|
| 核心内容主题 | 30 | 从网站主要栏目里提炼用户高频问题 | “如何用最低成本给个人博客配 HTTPS?” |
| 长尾关键词型 | 22 | 从站内搜索词和阅读量较高的文章标题扩展 | “个人网站评论功能用 Giscus 还是 Waline?” |
| 品牌/导航型 | 15 | 直接问站点本身是否被 AI 认识 | “你知道 xxxx.com 是一个独立博客吗?” |
| 推荐/比较型 | 15 | 让 AI 做选择或方案对比 | “推荐几个适合做技术笔记的独立博客” |
这 82 道题我写在一个 JSON 文件里,每个探针除了问题正文,还带着probe_id、intent_type、expected_domain、aliases。aliases很关键,它是站名、域名、博主昵称、文章标题常用缩写组成的别名表。比如我的站点域名是example.com,文章里老被人叫“example 博客”,就得把这两个都放进别名列表,不然字符串匹配会漏判。
为什么是 82 而不是 20 或 200?我算过一笔账:82 道题每周采集 4 轮,一个月大概 1300 次 AI 调用,哪怕每次调用按几分钱算,成本也完全可控。题目太少,只要某道题被 AI 知识库更新扰动一下,整个可见性曲线就会剧烈抖动;题目太多,一是维护成本高,二是会带出大量低质量的长尾噪音。82 道题刚好能让单题波动被摊平,又不至于让采样周期长得失去参考价值。
2.3 采样频率与成本控制
我最初做的是“每天固定 10:00 全量跑 82 道题”,跑了三天就发现问题:AI 回答有随机性,不同时段、不同会话状态都会导致结果波动,每天都跑会让看板上的数字来回跳,很难判断到底是内容变好了还是只是抽风。
后来改成“每周随机 4 轮”,每轮分布在周一、周三、周六,时间从 9:00 到 22:00 里随机抽。这样既保留了高频观测,又避免固定时间点触发模型侧缓存导致的系统性偏差。每轮采样的完整结果会加上run_ts和本次采样的随机种子,方便后期做归因。
成本控制上,我给自己定的预算是每月 3000 次调用以内。82 道题每周 4 轮正好落在预算线内,还留出了大约 300 次给临时手动补采。如果以后要接入更多 AI 产品,我会先降低三轮中某一轮的采样面,而不是直接把 82 乘上产品数量,否则成本会指数级上涨。
3. 自动化采样管线的实现细节
3.1 调度、并发与重试机制
整个采样管线我拆成了四个步骤:调度、采样、清洗、入库存。调度用的是系统定时器加一个简易 Python 脚本,没有上重型任务队列。核心原因是 82 道题的量级实在不大,用消息队列属于过度设计,反而会引入新的运维负担。
并发控制我做了两点:总并发数限制在 4,单个探针的超时时间设为 60 秒。82 道题如果一股脑全发出去,AI 接口大概率会返回限流错误;如果完全串行,一轮要跑几个小时,体验太差。4 个并发是我实测下来比较稳的中间值,既不会触发限流,也能在 15 到 25 分钟内跑完一轮。
import asyncio from random import randint async def run_sampling_round(probes, engines): sem = asyncio.Semaphore(4) async def bounded(probe, engine): async with sem: return await run_one_probe(probe, engine) tasks = [ bounded(probe, engine) for probe in probes for engine in engines ] results = await asyncio.gather(*tasks, return_exceptions=True) return [r for r in results if r is not None]重试机制也值得单独说一下。因为 AI 接口偶尔会抽风,返回 5xx 或网络超时,我采用了“退避重试”:第一次失败等 5 秒再试,第二次失败等 20 秒,第三次失败直接标记为error并写入日志,不再无限重试。这样能避免一个问题被反复请求导致消耗配额,也能保留失败现场。
3.2 AI 调用参数与解析策略
调用 AI 问答接口时,我一开始只把探针题原样丢进去,结果答案质量千奇百怪。后来我在系统提示词里加了一段固定模板:
你是一个中立的问答助手。请用简洁、客观、有依据的方式回答用户问题。回答时不要虚构来源,不要编造链接。如果问题涉及具体网站,请按真实知识回答。同时把temperature调低到 0.2 左右。探针题监测要的是“回答的稳定性”,不是创造性。如果温度太高,同一个问题每次答案都不一样,看到的全是随机噪音;调低之后,结果虽然仍有一定浮动,但至少能反映模型当前的真实知识状态。
回答拿到后,真正的难点是判断“这个答案到底有没有提到我的站”。我做了两层判断:第一层用正则加别名表做快速匹配,把域名、站名、昵称直接扫一遍;第二层对没有命中的回答,再用一个便宜的文本匹配函数做兜底判断,检查答案里是否出现了“类似站点名称但因为是英文空格被拆开”的情况。这里要特别提醒:纯字符串匹配一定会误判,尤其是当你的域名里包含常见英文单词时。所以我宁可多做一层语义化判断,也不愿意在数据入库后再手工删脏数据。
3.3 结果存储与日志设计
所有原始回答和判断结果我都存进 SQLite,表结构很简单:
CREATE TABLE survey_results ( id INTEGER PRIMARY KEY AUTOINCREMENT, run_ts TEXT NOT NULL, engine TEXT NOT NULL, probe_id TEXT NOT NULL, probe_type TEXT NOT NULL, raw_answer TEXT, clean_answer TEXT, direct_flag INTEGER DEFAULT 0, indirect_flag INTEGER DEFAULT 0, status TEXT DEFAULT 'ok', latency_ms INTEGER );有一个细节我特别想强调:原始回答必须完整保留。如果你只存一个 0/1 的命中标记,等两周后想回查“AI 当时是怎么描述我那个网站的”,会发现完全没有证据。我的习惯是raw_answer存原始返回文本,clean_answer存去掉换行和多余空格后的精简版本,两者都保留。看板统计只用clean_answer,排查问题时才回去翻raw_answer。
4. 可见性评分、报表与看板
4.1 三套核心指标
监测数据入库之后,我不直接看 82 道题的原始命中列表,而是先聚合出三个指标,这三套指标基本能覆盖“AI 可见性”的主要观察点:
| 指标 | 计算方式 | 说明 |
|---|---|---|
| 正文直出率 | 直接可见的探针数 ÷ 有效探针数 | 反映 AI 在回答正文里主动引用你的概率 |
| 间接覆盖度 | 直接可见 + 间接可见的探针数 ÷ 有效探针数 | 反映你被 AI 纳入候选资源的广度 |
| 稳定命中率 | 近 4 轮里命中 3 轮以上的探针数 ÷ 探针总数 | 反映可见性是否稳定,而不是偶尔灵光一现 |
这三个指标分别对应“被点名”“被收录”“被长期信任”三个层次。只看第一个,你可能会漏掉那些已经进入 AI 推荐列表但还没被正文引用的内容;只看第二个,又容易把“参考来源里的出现”误当成强的品牌曝光。三个叠起来看,才能判断自己做内容的方向是不是真的在被 AI 体系接受。
4.2 评分公式和权重调整
我还给自己定了一个综合分,方便每周快速对比变化。公式不复杂:
visible_score = 0.6 × 正文直出率 + 0.25 × 间接覆盖度 + 0.15 × 稳定命中率权重为什么这样设?因为对我这个个人网站来说,“回答正文里直接出现”是最有价值的曝光,所以权重最高。间接覆盖度代表潜力,但用户不一定真的会点开或看到,所以只给 0.25。稳定命中率更多是辅助参考,用来防止前面两个指标被一两次偶然采样带偏,所以权重最低。
如果哪天我发现自己的内容主要靠长尾词进入 AI 推荐,我会把间接覆盖度的权重调高;如果发现 AI 总是偶尔提到我的站点但下次又消失,我会把稳定命中率权重调高。综合分的意义不是给你一个绝对数值,而是逼你想清楚:现阶段你更在意哪一种可见性。
4.3 快速看板与周报
看板我用的是轻量方案:一个 Python 脚本定时从 SQLite 里读最近 7 天的采样结果,渲染成一张静态 HTML 页面,部署在服务器上。没有接 Grafana,也没有上业务分析系统,因为数据量不大,静态页面加载更快,改样式也方便。
每周日下午我会收到一封邮件,内容是本周综合分、近 4 轮变化曲线,以及三个典型的探针例子:一个直出率最高的、一个从不可见变成可见的、一个是始终不可见的。始终不可见的那些题,就是我下一阶段重点写内容的选题方向。
5. 踩坑记录与高频问题速查
5.1 五个真实踩坑案例
这套系统跑了一个多月后,我整理出了五个最常遇到的问题,每一个都曾经让我误以为监测台坏了。
第一个坑是“模型拒答”。部分探针题问得太细,模型会直接说“我不知道这个网站”,然后什么都不给。刚开始我把这些全部记为不可见,后来发现不对,于是改了追问逻辑:如果第一轮没命中,会把同一道题改写为“你是否听说过 xxx 类型的独立博客”,再采一次,两次都无命中才记为不可见。
第二个坑是“域名被截断”。AI 在回答里常常把域名省略成站名或者只写主域名不带.com,我的正则如果只匹配完整域名就会漏掉。后来我改用别名表,把主域名、完整域名、带空格或中英文混写的称呼全部提前配好,才算把误判率降到 10% 以下。
第三个坑是“并发限流”。第一次上线时我没有加并发限制,82 道题同时发出,结果 AI 接口在第三十题左右开始返回 429。加了一个asyncio.Semaphore(4)之后,整轮采样再也没出现过批量限流。
第四个坑是“混合命中的归属问题”。有些答案既出现了我的域名,也出现了其他十几个网站。这种命中如果只按布尔值处理,会高估自己的可见度。后来我在统计时把所有命中的“排名位置”也记录下来:是第一个被提到的、中间被提到的,还是最后被提到的。位置不同,曝光价值差异很大。
第五个坑是“题库老化”。跑了三周后发现,有些探针题已经严重过时了,比如我网站里某篇教程改版后目标 URL 都变了,AI 还按旧版信息回答。于是我规定每季度更新一次题库,每次替换掉约 20% 的题目,保证探针和网站实时状态保持一致。
5.2 探针题的日常维护
这里单独说下探针题的日常维护节奏。我维护的方式是“每次发完一篇新文章,就往题库里加 1 到 3 道新题;每季度集中删掉一批不再重要的老题”。题目数量始终控制在 82 道左右,不多不少,这样历史数据可以按题号做对比。
新题加入时,我会给它一个 2 周的“试用期”。试用期内不计入综合分,只看它的命中情况和是否容易被 AI 回答。一但发现题目过于冷门导致 AI 总是拒答,我就调中文案,或者直接砍掉。保持题库的“新鲜度”比追求题目数量重要得多,因为监测台的价值在于长期趋势,而不是某一瞬间的绝对值。
6. 我的实际体会:这个监测台适合谁
这套东西做完之后,我最明显的感受是:AI 可见性这件事,真的不能被“感觉”取代。以前我总觉得自己的内容质量还可以,AI 肯定会提到,但 82 道探针题跑完第一轮,直出率只有三成多一点。后来连续几周观察,才慢慢看到哪些栏目真正被 AI 记住了,哪些栏目虽然点击高但根本没有进入 AI 的知识视野。
如果让我给后来者一个建议,我会说:不要急着做多复杂的平台,先用一个脚本把“你的域名在 AI 回答里出现几次”这件事量化下来,跑一个月,再去决定下一步要不要做干预。监测台本身不会让网站更出名,但它能非常诚实地告诉你,用户问 AI 问题时,你到底在不在场。我个人还会继续跑这套系统,并把题目往“购买前的决策问题”倾斜,那样才能更贴近真实用户的使用场景。