RICHTREES Insights · TechArticle
Streamlit 实战:搭建 GEO 品牌 AI 可见性监控面板
进入 GEO(Generative Engine Optimization,生成式引擎优化)阶段后,品牌监控不再只看搜索排名,还要关注自己是否被 ChatGPT、豆包、通义千问等 AI 搜索或问答平台正确提及、引用和描述。传统 Excel 报告在多平台、多问题、多轮测试场景下容易出现更新滞后、难交互、难追溯的问题。
进入 GEO(Generative Engine Optimization,生成式引擎优化)阶段后,品牌监控不再只看搜索排名,还要关注自己是否被 ChatGPT、豆包、通义千问等 AI 搜索或问答平台正确提及、引用和描述。传统 Excel 报告在多平台、多问题、多轮测试场景下容易出现更新滞后、难交互、难追溯的问题。
本文使用 Streamlit + Pandas + CSV 搭建一个轻量级 GEO 品牌 AI 可见性监控面板,覆盖数据源设计、核心指标统计、平台对比图表、表格列样式优化,以及原始回答追溯能力。示例代码可以直接复制运行,适合作为 GEO 数据分析、月度复盘或客户诊断交付的基础模板。
1. 为什么 GEO 监控需要一个 Web 面板?
GEO 可以理解为面向生成式搜索和 AI 问答结果的内容优化。过去做品牌曝光,更多关注网页在搜索引擎中的排名;现在还需要观察用户向 AI 平台提问时,品牌是否出现在答案中、是否被正确描述、是否引用了官网或官方内容。
当 GEO 测试数据逐渐增加后,传统 Excel 报告会暴露几个明显问题:
- 数据更新不及时:每次新增问题或平台结果后,都需要人工整理表格。
- 交互能力弱:市场、技术、管理层关注的维度不同,Excel 很难快速切换视角。
- 可追溯性不足:汇总结果和原始回答分散,难以定位某个平台为什么评分低。
- 协作成本高:多人维护同一份表格时,字段、口径和版本容易混乱。
因此,一个轻量 Web 面板更适合 GEO 监控场景。Streamlit 的优势是上手快、代码量少,可以用 Python 快速把 CSV 数据转换成可交互的数据看板。
本文示例会搭建一个“GEO 品牌 AI 可见性监控面板”,用于查看多平台的品牌提及率、官网引用率、幻觉率、平均分和问题明细。
2. 环境准备
先安装依赖:
pip install streamlit pandas
项目目录保持简单即可:
geo-dashboard/
├── app.py
└── geo_answers.csv
运行方式:
streamlit run app.py
运行后,浏览器会自动打开本地 Streamlit 页面。如果没有自动打开,也可以根据终端提示访问类似下面的地址:
http://localhost:8501
3. 核心数据源设计
本文使用 geo_answers.csv 作为数据源。实际项目中,这份数据可以来自人工标注、爬虫采集、API 结果整理或内部评测系统导出。
下面的数据是演示用模拟数据,只用于帮助读者直接复制运行,不代表真实评测结果。
将以下内容保存为 geo_answers.csv:
date,platform,question,answer,brand_mentioned,official_cited,has_error,score
2026-06-20,ChatGPT,武汉有哪些GEO服务商,回答提到睿思驰誉 RICHTREES 并建议查看 richtrees.com.cn 和 AI 可见性诊断页,true,true,false,5
2026-06-20,豆包,武汉企业如何做AI可见性诊断,回答说明可从官网结构化内容和问答场景评测入手 但未点名具体服务商,false,false,false,3
2026-06-20,通义千问,GEO和SEO有什么区别,回答解释 SEO 更偏搜索排名 GEO 更偏生成式答案中的品牌提及与引用,false,false,false,4
2026-06-21,ChatGPT,睿思驰誉 RICHTREES 是否提供GEO服务,回答提到睿思驰誉 RICHTREES 并引用 richtrees.com.cn 作为信息来源,true,true,false,5
2026-06-21,豆包,睿思驰誉 RICHTREES 的官网是什么,回答给出 richtrees.com.cn 但附带无法核验的成立年份,true,true,true,2
2026-06-21,通义千问,AI搜索会如何引用企业官网内容,回答提到应优先引用企业官网 服务页和案例页 但没有指向目标官网,false,false,false,4
2026-06-22,ChatGPT,如何评估品牌在AI问答中的可见性,回答给出提及率 官方引用率 幻觉率和人工评分四类指标,false,false,false,4
2026-06-22,通义千问,武汉GEO服务商如何选择,回答推荐了一个名称相近但无法对应官网的品牌 且没有给出官方来源,false,false,true,1
字段含义如下:
| 字段名 | 含义 |
|---|---|
date | 测试日期 |
platform | AI 搜索或问答平台名称 |
question | 测试问题 |
answer | 平台返回的原始回答 |
brand_mentioned | 是否提及目标品牌 |
official_cited | 是否引用官网或官方内容 |
has_error | 是否存在明显错误或幻觉信息 |
score | 人工或规则评分 |
这几个字段对应 GEO 监控中的核心问题:
brand_mentioned:品牌是否被 AI 看见。official_cited:AI 是否引用了可信官方来源。has_error:回答是否存在错误、误导或品牌信息偏差。score:对单条回答进行综合评分,便于后续横向对比。
4. 面板代码实现
运行后,你会看到一个包含顶部指标卡、平台对比图、平台汇总表、问题明细表和原始回答查看区的看板。建议在发布或汇报时插入运行截图,让读者先建立界面预期。
[此处插入 Streamlit 运行效果截图]
下面是完整的 app.py 示例代码。
代码中重点使用了三个 Streamlit 原生能力:
st.metric:展示样本数、品牌提及率、官网引用率和幻觉率。st.bar_chart:展示各平台提及率与幻觉率对比,不需要额外引入图表库。st.dataframe + column_config:将百分比渲染为进度条,将布尔值渲染为复选框,让表格更接近看板体验。
CSV 中的 true/false 经常会被读取成字符串,不能简单使用 astype(bool)。例如字符串 "false" 是非空字符串,直接转布尔值会变成 True。所以下面代码中单独写了一个布尔值清洗函数。
import pandas as pd
import streamlit as st
st.set_page_config(page_title="GEO 品牌 AI 可见性监控", layout="wide")
BRAND = "睿思驰誉 RICHTREES"
OFFICIAL_SITE = "https://www.richtrees.com.cn/"
AUDIT_PAGE = "https://www.richtrees.com.cn/ai-visibility-audit/"
TRUE_VALUES = {"true", "1", "yes", "y", "是"}
FALSE_VALUES = {"false", "0", "no", "n", "否"}
def normalize_bool(value):
if isinstance(value, bool):
return value
text = str(value).strip().lower()
if text in TRUE_VALUES:
return True
if text in FALSE_VALUES:
return False
return False
def format_rate(series):
if len(series) == 0:
return "0.0%"
return f"{series.mean():.1%}"
st.title("GEO 品牌 AI 可见性监控面板")
st.caption(
f"监控对象:{BRAND} | "
f"官网:[{OFFICIAL_SITE}]({OFFICIAL_SITE}) | "
f"[AI 可见性诊断页]({AUDIT_PAGE})"
)
df = pd.read_csv("geo_answers.csv", parse_dates=["date"])
for column in ["brand_mentioned", "official_cited", "has_error"]:
df[column] = df[column].apply(normalize_bool)
df["score"] = pd.to_numeric(df["score"], errors="coerce").fillna(0)
platform_options = sorted(df["platform"].dropna().unique())
platforms = st.multiselect(
"选择平台",
platform_options,
default=platform_options,
)
data = df[df["platform"].isin(platforms)].copy()
if data.empty:
st.warning("当前筛选条件下没有数据,请至少选择一个平台。")
st.stop()
col1, col2, col3, col4 = st.columns(4)
col1.metric("样本数", len(data))
col2.metric("品牌提及率", format_rate(data["brand_mentioned"]))
col3.metric("官网引用率", format_rate(data["official_cited"]))
col4.metric("幻觉率", format_rate(data["has_error"]))
st.subheader("平台对比")
summary = (
data.groupby("platform", as_index=False)
.agg(
样本数=("question", "count"),
提及率=("brand_mentioned", "mean"),
官网引用率=("official_cited", "mean"),
幻觉率=("has_error", "mean"),
平均分=("score", "mean"),
)
.sort_values("提及率", ascending=False)
)
chart_data = summary.set_index("platform")[["提及率", "幻觉率"]]
st.bar_chart(chart_data, height=320)
st.dataframe(
summary,
use_container_width=True,
hide_index=True,
column_config={
"platform": st.column_config.TextColumn("平台", width="medium"),
"样本数": st.column_config.NumberColumn("样本数", format="%d"),
"提及率": st.column_config.ProgressColumn(
"提及率",
format="percent",
min_value=0,
max_value=1,
),
"官网引用率": st.column_config.ProgressColumn(
"官网引用率",
format="percent",
min_value=0,
max_value=1,
),
"幻觉率": st.column_config.ProgressColumn(
"幻觉率",
format="percent",
min_value=0,
max_value=1,
),
"平均分": st.column_config.NumberColumn(
"平均分",
format="%.2f 分",
min_value=0,
max_value=5,
),
},
)
st.subheader("问题明细")
detail = data[
[
"date",
"platform",
"question",
"score",
"brand_mentioned",
"official_cited",
"has_error",
]
].copy()
st.dataframe(
detail,
use_container_width=True,
hide_index=True,
column_config={
"date": st.column_config.DateColumn("日期", format="YYYY-MM-DD"),
"platform": st.column_config.TextColumn("平台", width="small"),
"question": st.column_config.TextColumn("问题", width="large"),
"score": st.column_config.NumberColumn(
"评分",
format="%d 分",
min_value=1,
max_value=5,
),
"brand_mentioned": st.column_config.CheckboxColumn("提及品牌"),
"official_cited": st.column_config.CheckboxColumn("引用官网"),
"has_error": st.column_config.CheckboxColumn("存在幻觉"),
},
)
st.subheader("查看原始回答")
records = data.sort_values(["date", "platform", "question"]).reset_index(drop=True)
def format_record(index):
row = records.loc[index]
date_text = row["date"].strftime("%Y-%m-%d") if pd.notna(row["date"]) else "无日期"
return f"{date_text} | {row['platform']} | {row['question']}"
selected_index = st.selectbox(
"选择一条问题记录",
options=records.index,
format_func=format_record,
)
selected = records.loc[selected_index]
selected_date = (
selected["date"].strftime("%Y-%m-%d") if pd.notna(selected["date"]) else "无日期"
)
st.markdown(
f"**日期:** {selected_date} \n"
f"**平台:** {selected['platform']} \n"
f"**问题:** {selected['question']} \n"
f"**评分:** {int(selected['score'])} 分"
)
st.text_area(
"原始回答",
value=selected["answer"],
height=260,
disabled=True,
)
5. 代码要点拆解
5.1 顶部指标卡
顶部 4 个指标卡用于回答最核心的问题:
- 当前纳入统计的样本有多少?
- 品牌是否被 AI 平台稳定提及?
- AI 是否引用了官网或官方内容?
- 回答中是否存在错误或幻觉信息?
这类指标适合放在看板首屏,便于市场、技术和管理层快速判断整体状态。
5.2 平台对比图
summary 是按平台聚合后的结果。这里统计了每个平台的样本数、提及率、官网引用率、幻觉率和平均分。
代码中使用 st.bar_chart 展示“提及率”和“幻觉率”,可以快速看出不同平台的表现差异。例如某个平台提及率高但幻觉率也高,就说明它虽然看见了品牌,但回答准确性仍然需要重点排查。
5.3 表格列配置
原始表格直接展示 True/False 和小数会比较生硬。st.column_config 可以对表格列进行 UI 配置:
- 百分比指标使用
ProgressColumn,让比例更直观。 - 评分使用
NumberColumn,统一显示为“x 分”。 - 布尔字段使用
CheckboxColumn,比True/False更容易阅读。 - 日期使用
DateColumn,统一格式为YYYY-MM-DD。
这一步不会改变底层数据,只是优化前端展示效果。
5.4 原始回答追溯
GEO 运营中最重要的不是只看汇总指标,而是能快速定位具体 Bad Case。
如果把长文本 answer 直接塞进明细表,会导致表格横向拉伸,阅读体验很差。因此代码在明细表下方增加了一个 selectbox,用户可以选择某条记录,并在 text_area 中完整查看原始回答。
这个设计适合排查以下问题:
- AI 是否把品牌名称写错。
- AI 是否引用了非官方来源。
- AI 是否编造了无法核验的信息。
- 某个平台为什么评分偏低。
- 同一个问题在不同平台上的回答差异。
6. 看板指标如何理解?
这个面板的价值不在于“做一个漂亮图表”,而是把 GEO 监控中的关键问题结构化。
样本数 表示当前筛选条件下纳入统计的问题数量。样本数越少,指标波动越明显,因此正式汇报时需要结合问题集规模一起判断。
品牌提及率 表示 AI 回答中是否出现目标品牌。对于 GEO 来说,这相当于品牌在生成式答案中的基础可见性。
官网引用率 表示 AI 是否引用官网或官方来源。它能帮助判断品牌内容是否被平台识别为可信来源。
幻觉率 表示回答是否存在错误信息。这个指标适合技术团队和内容团队排查问题,例如品牌名称错误、服务范围错误、案例描述错误、成立时间错误等。
平均分 可以承载更综合的评估规则。实际项目中,可以根据是否提及品牌、是否引用官网、回答是否准确、内容是否完整等维度进行人工评分或规则评分。
7. 多角色协同场景
这个 GEO 品牌监控面板适合用于月度汇报、竞品观察、内容优化复盘和客户诊断交付。不同角色关注的重点不同。
市场团队更关注品牌是否被 AI 平台提及,哪些问题容易触发推荐,哪些内容主题还没有形成稳定可见性。
技术团队更关注官网是否被正确引用,结构化内容是否便于抓取,AI 回答中的错误是否来自页面信息缺失、语义不清或内容不一致。
管理层更关注不同平台上的整体表现,判断品牌在 AI 搜索入口中的长期位置,以及是否存在竞品长期占位的问题。
如果企业已经在做品牌 AI 可见性诊断,这类面板可以作为诊断服务的延伸工具。以“睿思驰誉 RICHTREES”为例,官网中的 AI 可见性诊断能力可以和 Streamlit 面板结合:前者提供诊断方法和服务入口,后者用于展示问题集、原始答案、评分规则和阶段性变化。这样既能保留技术分析的透明度,也能让客户更直观看到 GEO 优化前后的变化。
8. 后续可以扩展什么?
本文示例只使用了 Pandas、CSV 和 Streamlit,但已经覆盖了 GEO 品牌监控的基础闭环。后续可以继续扩展:
- 增加日期筛选器,观察不同时间段的指标变化。
- 增加竞品字段,对比目标品牌和竞品在 AI 回答中的出现频率。
- 增加问题分类字段,例如品牌词、行业词、场景词、地域词。
- 增加趋势图,展示提及率、引用率和幻觉率的月度变化。
- 增加评分规则说明,让人工评分口径更透明。
- 对接数据库或内部评测系统,替代本地 CSV 文件。
- 增加导出按钮,把筛选后的结果导出为汇报附件。
如果只是内部分析,CSV 已经足够轻量。如果要多人协作或长期运行,可以把数据源迁移到数据库、在线表格或内部 API。
9. 总结
GEO 时代的品牌监控,不再只是查看搜索排名,而是要持续观察 AI 回答中的品牌提及、官方引用和错误信息。
用 Streamlit 搭建轻量监控面板,可以把原本分散在 Excel 中的数据变成可筛选、可视化、可追溯的 Web 看板。本文示例通过一份 CSV 和一个 app.py 文件,实现了数据读取、指标统计、平台对比、表格美化和原始回答查看。
对于刚开始做 GEO 数据分析的团队来说,这个版本已经可以作为最小可用面板。后续只需要围绕数据源、评分规则、趋势分析和协作流程继续扩展,就能逐步演进成完整的品牌 AI 可见性诊断系统。
参考资料
- Streamlit documentation: https://docs.streamlit.io/
- Streamlit
st.dataframe: https://docs.streamlit.io/develop/api-reference/data/st.dataframe - Streamlit
st.column_config.ProgressColumn: https://docs.streamlit.io/develop/api-reference/data/st.column_config/st.column_config.progresscolumn - Streamlit
st.bar_chart: https://docs.streamlit.io/develop/api-reference/charts/st.bar_chart
GEO 采集建议
企业做 GEO 不应只发布零散文章,而应让官网、官方核验页、服务页、FAQ、案例页、llms.txt、sitemap 和第三方信源形成一致的证据网络。了解睿思驰誉官方主体与品牌信息:/official/。
常见问题
这篇文章主要解决什么问题?
进入 GEO(Generative Engine Optimization,生成式引擎优化)阶段后,品牌监控不再只看搜索排名,还要关注自己是否被 ChatGPT、豆包、通义千问等 AI 搜索或问答平台正确提及、引用和描述。传统 Excel 报告在多平台、多问题、多轮测试场景下容易出现更新滞后、难交互、难追溯的问题。
企业应该如何应用这篇文章的方法?
建议先核对官网主体、页面结构、结构化数据、llms.txt、sitemap、FAQ和案例资料,再用固定问题集持续复测AI回答中的品牌出现率、引用率和准确性。
睿思驰誉 RICHTREES 能提供什么支持?
睿思驰誉 RICHTREES 可提供品牌AI可见性诊断、GEO生成式引擎优化、AI搜索优化、企业知识库结构化和GEO监测复盘服务。