为什么要单独做一套模块传统 SEO 优化的是搜索引擎排名GEO 优化的是 AI 大模型在回答用户问题时是否提及、如何评价你的品牌。正常用户与智能体的对话 VS GEO 监控维度 对话 GEO 监控目标 准确回答用户问题 探测第三方模型的品牌曝光模型 单一可控模型 通义、DeepSeek、豆包、混元、Kimi、智谱等多引擎提示词 业务导向、可注入知识库 中性助手避免诱导偏向输出 自然语言回复 结构化指标提及率、排名、态度、竞品共现后续动作 会话结束 诊断 → 内容草稿 → 发布向量库 → 基线对比2. 整体架构┌─────────────────────────────────────────────────────────────────┐│ 管理端 ││ 数据看板 │ 探测任务 │ 引擎管理 │ 品牌档案 │ 诊断报告 │ 内容草稿 │└────────────────────────────┬────────────────────────────────────┘│ REST /api/v1/geo/*┌────────────────────────────▼────────────────────────────────────┐│ GeoEngineRunner调度核心 ││ 加载任务 → 遍历品牌×问题×引擎 → 采样探测 → 分析聚合 → 落库 │└──┬──────────┬──────────┬──────────┬──────────┬─────────────────┘│ │ │ │ │▼ ▼ ▼ ▼ ▼probe analyzer metrics diagnoser alert(探测) (分析) (指标) (诊断) (飞书)│ │▼ ▼provider_registry content_generatorcreate_geo_llm publisher → knowledge_document (Chroma)2.1 数据模型关系一次完整的 GEO 业务链路围绕以下核心表展开geo_engines探测引擎配置厂商、model_code、API Key 环境变量名geo_tasks探测任务品牌词、竞品、问题模板、引擎列表、采样次数、告警配置、基线 Rungeo_runs每次执行记录手动 / 定时触发geo_snapshots单次探测快照问题、回答、分析结果、提及指标geo_diagnosesLLM 生成的诊断报告geo_brand_profiles品牌档案定位、差异化、事实边界geo_content_drafts优化内容草稿geo_question_templates场景问题库3. 核心执行流程3.1 流程总览飞书 WebhookGeoDiagnoserMySQLGeoAnalyzer目标大模型probe_engineGeoEngineRunnerAPScheduler飞书 WebhookGeoDiagnoserMySQLGeoAnalyzer目标大模型probe_engineGeoEngineRunnerAPSchedulerloop[sample_count 次采样]loop[品牌 × 问题 × 引擎]run_due_geo_tasks()创建 GeoRun标记 is_runningprobe_engine(engine, prompt)中性 system 用户问题原始回答ProbeResultanalyze(brand, answer, competitors)结构化 JSONaggregate_samples() 多数投票写入 GeoSnapshot更新 Run 状态未提及/负面推荐告警schedule_diagnosis(run_id) 后台任务诊断摘要可选基线回归告警可选3.2 调度入口GEO 任务由 APScheduler 周期性触发backend/app/core/scheduler/init.pyscheduler.add_job(_geo_tasks_job, ‘interval’, minutes5, id‘geo_tasks_runner’)async def _geo_tasks_job():from app.core.geo.engine import run_due_geo_tasksawait run_due_geo_tasks()run_due_geo_tasks() 会清理超过 60 分钟仍处于 running 的僵尸 Run查询 statusactive、未在运行、且 next_run_at now 的任务逐个调用 GeoEngineRunner.run_task(db, task_id, trigger“schedule”)手动执行走 API POST /api/v1/geo/tasks/{task_id}/run通过 asyncio.create_task 在后台跑同一套 run_task 逻辑避免阻塞 HTTP 响应。3.3 三层嵌套循环品牌 × 问题 × 引擎GeoEngineRunner.run_task 是整个模块的「心脏」。其核心逻辑可以概括为backend/app/core/geo/engine.py简化for brand in brands:for item in prompt_items:prompt item[“template”].replace(“{keyword}”, brand)for engine in engines:sample_analyses []for sample_idx in range(sample_count):probe_result await probe_engine(engine, prompt)analysis await self.analyzer.analyze(brand, probe_result.answer, competitors)sample_analyses.append(analysis)aggregated self.analyzer.aggregate_samples(sample_analyses) snapshot GeoSnapshot(..., analysisaggregated, ...) db.add(snapshot) await db.commit() # 逐条提交支持中途取消几个设计要点问题来源任务可配置 question_sourceinline内联模板或 library场景问题库后者支持按 recommend/compare/risk 等分类统计采样次数默认 2 次通过多数投票降低 LLM 随机性逐条 commit每写入一条 snapshot 就提交配合 cancel_requested 标志实现优雅停止引擎可用性检查执行前过滤未配置 API Key 或已禁用的引擎默认问题模板示例DEFAULT_PROMPT_TEMPLATES [“{keyword}怎么样”,“{keyword}靠谱吗”,“推荐几个{keyword}相关的平台”,“网上对{keyword}的评价如何”,]4. 多引擎探测统一 OpenAI 兼容层4.1 厂商注册表所有支持的厂商集中在 provider_registry.py统一管理 base_url、环境变量名与官方文档链接PROVIDER_DEFAULTS {“dashscope”: {“name”: “通义千问”,“base_url”: “https://dashscope.aliyuncs.com/compatible-mode/v1”,“api_key_env”: “geo_dashscope_api_key”,},“deepseek”: {“name”: “DeepSeek”,“base_url”: “https://api.deepseek.com”,“default_model”: “deepseek-v4-flash”,},“doubao”: {“name”: “豆包火山方舟”,“base_url”: “https://ark.cn-beijing.volces.com/api/v3”,},# hunyuan, moonshot, zhipu …}新增厂商的 SOP查厂商 OpenAI 兼容文档确认 base_url 与 model 字段含义在 PROVIDER_DEFAULTS 增加预设配置 .env 中对应的 GEO_*_API_KEY管理端「引擎管理」新增记录4.2 探测 LLMcreate_geo_llm 专门为 GEO 探测创建 LangChain 实例backend/app/core/geo/llm.pydef create_geo_llm(engine: GeoEngine) - ChatOpenAI:defaults get_provider_defaults(engine.provider) or {}base_url engine.base_url or defaults.get(“base_url”, “”)api_key resolve_api_key(settings, engine.api_key_env)kwargs { api_key: api_key, base_url: base_url, model: engine.model_code, temperature: engine.temperature, max_tokens: 2048, timeout: settings.geo_probe_timeout_seconds, } if engine.extra_body: kwargs[extra_body] engine.extra_body # 如混元搜索增强 return ChatOpenAI(**kwargs)分析器使用更便宜的模型默认 qwen-turbo通过 GEO_ANALYZER_PROVIDER / GEO_ANALYZER_MODEL 单独配置。4.3 中性探测提示词探测时必须避免「诱导模型推荐本品牌」因此 probe.py 使用固定中性 system promptNEUTRAL_SYSTEM_PROMPT (“你是一个乐于助人的助手。请根据你的知识如实回答用户问题”“可以列举多个选项并说明各自特点不要刻意回避或偏向任何品牌。”)async def probe_engine(engine: GeoEngine, prompt: str) - ProbeResult:llm create_geo_llm(engine)start time.perf_counter()response await llm.ainvoke([SystemMessage(contentNEUTRAL_SYSTEM_PROMPT),HumanMessage(contentprompt),])elapsed int((time.perf_counter() - start) * 1000)return ProbeResult(promptprompt, answercontent, latency_mselapsed)这是 GEO 测量可信度的关键我们测的是模型在自然状态下的品牌认知而不是 prompt 工程后的结果。LLM 结构化分析器原始回答是非结构化文本需要二次 LLM 调用提取指标。GeoAnalyzer 要求分析模型返回严格 JSON{“brand_mentioned”: true,“mention_rank”: 2,“recommendation”: “recommend”,“competitors_mentioned”: [“竞品A”],“citation_urls”: [“https://…”],“sentiment”: {“category”: “positive”, “score”: 0.6},“summary”: “一句话摘要”,“misunderstanding”: false,“entity_clarity”: “clear”}5.1 多次采样聚合当 sample_count 1 时使用多数投票策略字段 聚合规则brand_mentioned 超过半数采样为 true 则 truemention_rank 取有排名采样的算术平均并四舍五入recommendation 票数最多的态度competitors_mentioned 各采样并集misunderstanding 任一为 true 则 true这种设计在成本与稳定性之间取得平衡比单次探测更可靠又比大量采样更经济。5.2 容错分析器对 JSON 解析失败、LLM 调用异常均有降级处理返回默认的 not_mentioned 结构避免单条失败拖垮整次 Run。指标聚合与数据看板compute_run_metrics 将一批 snapshot 聚合为 Run 级指标供诊断、看板、基线对比复用backend/app/core/geo/metrics.py 输出结构{“total”: 24,“mentioned”: 14,“mention_rate”: 0.5833,“avg_mention_rank”: 2.1,“by_engine”: {“1”: {“total”: 8, “mentioned”: 5, “mention_rate”: 0.625}},“by_category”: {“recommend”: {“total”: 6, “mentioned”: 2, “mention_rate”: 0.333}},“by_recommendation”: {“recommend”: 8, “neutral”: 4, “warn”: 2, “not_mentioned”: 10},“competitor_sov”: {“竞品A”: 12, “竞品B”: 7},“citation_domains”: {“zhihu.com”: 5},“misunderstanding_count”: 1,}看板 API GET /api/v1/geo/dashboard 读取最近 Run 的 snapshot计算趋势与引擎对比若任务设置了 baseline_run_id还会输出优化前后 delta。优化闭环诊断 → 内容 → 发布 → 基线对比GEO 模块不只是需要「监控」也需要完整的优化闭环。7.1 自动诊断探测成功后schedule_diagnosis(run_id) 通过 asyncio.create_task 在后台启动诊断backend/app/core/geo/diagnoser.pydef schedule_diagnosis(run_id: int):asyncio.create_task(run_diagnosis_background(run_id))GeoDiagnoser 将聚合指标、品牌档案、样本摘要拼成 prompt让 LLM 输出summary整体可见度总结root_causes根因列表实体不清、信源缺失、竞品主导等recommendations优化建议FAQ、对比页、证据文档等weaknesses薄弱引擎 / 场景 / 竞品共现misunderstandings品牌被误解的具体案例诊断与探测分析使用同一套便宜模型控制成本。7.2 内容草稿生成GeoContentGenerator 根据诊断建议 品牌档案缺的话再根据优化补充一些生成多篇 Markdown/Html 草稿FAQ、对比页、教程等存入 geo_content_drafts 表等待人工审阅。7.3 发布到企业文档向量库/官网/各大第三方平台可以对接官网如果有 CMS 管理后台那更好生成各种文章审阅通过后GeoPublisher.publish_draft 将内容写入企业文档树GEO/└── {任务名}/├── FAQxxx 怎么样└── 对比xxx vs 竞品发布到企业文档知识库发布时同步调用 sync_document_to_vector写入 Chroma knowledge_document 集合。这意味着 GEO 优化内容最终进入助手可检索的知识库形成「探测 → 补缺 → 再探测」的闭环。7.4 基线对比可将优化前的 Run 设为基线PATCH /api/v1/geo/tasks/{id}/baseline发布内容后重新探测通过 compute_run_metrics 对比提及率变化。若下降超过 regression_threshold默认 0.1触发飞书回归告警。告警体系GeoFeishuAlert 支持三类飞书 Webhook 通知类型 触发条件探测告警 未提及 / 负面推荐且达到 threshold 条数诊断摘要 诊断完成后推送根因与建议 Top 3回归告警 当前 Run 提及率较基线下降 ≥ regression_threshold告警配置挂在任务级 alert_config JSON 字段示例{“enabled”: true,“alert_not_mentioned”: true,“alert_warn”: true,“threshold”: 1,“regression_threshold”: 0.1}Webhook 优先使用 GEO_FEISHU_WEBHOOK_URL可回退到舆情监控的 MONITOR_FEISHU_WEBHOOK_URL。取消与并发控制GEO 探测可能耗时较长品牌数 × 问题数 × 引擎数 × 采样次数 × LLM 延迟需要可靠的并发控制任务级 is_running 标志防止重复执行cancel_requested 循环内 is_cancel_requested() 检查实现手动停止僵尸 Run 清理超过 60 分钟仍为 running 则标记失败手动执行通过 asyncio.create_task 后台化API 立即返回backend/app/core/geo/cancel.pyasync def is_cancel_requested(task_id: int) - bool:async with AsyncSessionLocal() as db:result await db.execute(select(GeoTask.cancel_requested).where(GeoTask.id task_id))return bool(result.scalar_one_or_none())10. 环境配置各引擎 API KeyGEO_DASHSCOPE_API_KEYGEO_DEEPSEEK_API_KEYGEO_DOUBAO_API_KEYGEO_HUNYUAN_API_KEYGEO_MOONSHOT_API_KEYGEO_ZHIPU_API_KEY分析器建议便宜模型GEO_ANALYZER_PROVIDERdashscopeGEO_ANALYZER_MODELqwen-turbo执行参数GEO_PROBE_TIMEOUT_SECONDS60GEO_DEFAULT_SAMPLE_COUNT2GEO_DEFAULT_INTERVAL_MINUTES1440告警GEO_FEISHU_WEBHOOK_URL注意豆包 model_code 需填火山方舟推理接入点 IDep-xxxxDeepSeek 推荐 deepseek-v4-flashdeepseek-chat 已弃用混元可通过 extra_body.enable_enhancement 开启搜索增强11. 核心代码文件仅供参考文件 职责backend/app/core/geo/engine.py 任务调度与执行主循环backend/app/core/geo/probe.py 单引擎探测backend/app/core/geo/analyzer.py 回答结构化分析 采样聚合backend/app/core/geo/llm.py 探测/分析 LLM 工厂backend/app/core/geo/provider_registry.py 厂商预设与可用性检查backend/app/core/geo/metrics.py Run 级指标聚合backend/app/core/geo/diagnoser.py 诊断报告生成backend/app/core/geo/run_brief.py 执行分析报告事实汇总不含建议backend/app/core/geo/content_generator.py 优化内容草稿生成backend/app/core/geo/publisher.py 发布到企业文档 向量库backend/app/core/geo/alert.py 飞书告警backend/app/core/geo/cancel.py 取消控制backend/app/api/v1/geo.py REST API 层backend/app/core/scheduler/init.py 定时任务注册frontend/src/views/admin/geo/* 管理端页面12. 设计经验总结探测与分析分离探测用大模型、分析用便宜模型成本和效果兼顾。中性 prompt 是测量基准GEO 的数据可信度取决于探测时不对品牌做任何引导。OpenAI 兼容层降低接入成本新厂商只需配置 base_url model_code 以及 apiKey无需重写调用逻辑。采样 投票抑制随机性LLM 回答本身有波动多次采样聚合让指标更稳定。闭环比监控更有价值诊断 → 草稿 → 发布向量库 → 基线对比让 GEO 从「看数据」变成「改数据、验效果」。
实现 GEO 监控:从多引擎探测到优化闭环
为什么要单独做一套模块传统 SEO 优化的是搜索引擎排名GEO 优化的是 AI 大模型在回答用户问题时是否提及、如何评价你的品牌。正常用户与智能体的对话 VS GEO 监控维度 对话 GEO 监控目标 准确回答用户问题 探测第三方模型的品牌曝光模型 单一可控模型 通义、DeepSeek、豆包、混元、Kimi、智谱等多引擎提示词 业务导向、可注入知识库 中性助手避免诱导偏向输出 自然语言回复 结构化指标提及率、排名、态度、竞品共现后续动作 会话结束 诊断 → 内容草稿 → 发布向量库 → 基线对比2. 整体架构┌─────────────────────────────────────────────────────────────────┐│ 管理端 ││ 数据看板 │ 探测任务 │ 引擎管理 │ 品牌档案 │ 诊断报告 │ 内容草稿 │└────────────────────────────┬────────────────────────────────────┘│ REST /api/v1/geo/*┌────────────────────────────▼────────────────────────────────────┐│ GeoEngineRunner调度核心 ││ 加载任务 → 遍历品牌×问题×引擎 → 采样探测 → 分析聚合 → 落库 │└──┬──────────┬──────────┬──────────┬──────────┬─────────────────┘│ │ │ │ │▼ ▼ ▼ ▼ ▼probe analyzer metrics diagnoser alert(探测) (分析) (指标) (诊断) (飞书)│ │▼ ▼provider_registry content_generatorcreate_geo_llm publisher → knowledge_document (Chroma)2.1 数据模型关系一次完整的 GEO 业务链路围绕以下核心表展开geo_engines探测引擎配置厂商、model_code、API Key 环境变量名geo_tasks探测任务品牌词、竞品、问题模板、引擎列表、采样次数、告警配置、基线 Rungeo_runs每次执行记录手动 / 定时触发geo_snapshots单次探测快照问题、回答、分析结果、提及指标geo_diagnosesLLM 生成的诊断报告geo_brand_profiles品牌档案定位、差异化、事实边界geo_content_drafts优化内容草稿geo_question_templates场景问题库3. 核心执行流程3.1 流程总览飞书 WebhookGeoDiagnoserMySQLGeoAnalyzer目标大模型probe_engineGeoEngineRunnerAPScheduler飞书 WebhookGeoDiagnoserMySQLGeoAnalyzer目标大模型probe_engineGeoEngineRunnerAPSchedulerloop[sample_count 次采样]loop[品牌 × 问题 × 引擎]run_due_geo_tasks()创建 GeoRun标记 is_runningprobe_engine(engine, prompt)中性 system 用户问题原始回答ProbeResultanalyze(brand, answer, competitors)结构化 JSONaggregate_samples() 多数投票写入 GeoSnapshot更新 Run 状态未提及/负面推荐告警schedule_diagnosis(run_id) 后台任务诊断摘要可选基线回归告警可选3.2 调度入口GEO 任务由 APScheduler 周期性触发backend/app/core/scheduler/init.pyscheduler.add_job(_geo_tasks_job, ‘interval’, minutes5, id‘geo_tasks_runner’)async def _geo_tasks_job():from app.core.geo.engine import run_due_geo_tasksawait run_due_geo_tasks()run_due_geo_tasks() 会清理超过 60 分钟仍处于 running 的僵尸 Run查询 statusactive、未在运行、且 next_run_at now 的任务逐个调用 GeoEngineRunner.run_task(db, task_id, trigger“schedule”)手动执行走 API POST /api/v1/geo/tasks/{task_id}/run通过 asyncio.create_task 在后台跑同一套 run_task 逻辑避免阻塞 HTTP 响应。3.3 三层嵌套循环品牌 × 问题 × 引擎GeoEngineRunner.run_task 是整个模块的「心脏」。其核心逻辑可以概括为backend/app/core/geo/engine.py简化for brand in brands:for item in prompt_items:prompt item[“template”].replace(“{keyword}”, brand)for engine in engines:sample_analyses []for sample_idx in range(sample_count):probe_result await probe_engine(engine, prompt)analysis await self.analyzer.analyze(brand, probe_result.answer, competitors)sample_analyses.append(analysis)aggregated self.analyzer.aggregate_samples(sample_analyses) snapshot GeoSnapshot(..., analysisaggregated, ...) db.add(snapshot) await db.commit() # 逐条提交支持中途取消几个设计要点问题来源任务可配置 question_sourceinline内联模板或 library场景问题库后者支持按 recommend/compare/risk 等分类统计采样次数默认 2 次通过多数投票降低 LLM 随机性逐条 commit每写入一条 snapshot 就提交配合 cancel_requested 标志实现优雅停止引擎可用性检查执行前过滤未配置 API Key 或已禁用的引擎默认问题模板示例DEFAULT_PROMPT_TEMPLATES [“{keyword}怎么样”,“{keyword}靠谱吗”,“推荐几个{keyword}相关的平台”,“网上对{keyword}的评价如何”,]4. 多引擎探测统一 OpenAI 兼容层4.1 厂商注册表所有支持的厂商集中在 provider_registry.py统一管理 base_url、环境变量名与官方文档链接PROVIDER_DEFAULTS {“dashscope”: {“name”: “通义千问”,“base_url”: “https://dashscope.aliyuncs.com/compatible-mode/v1”,“api_key_env”: “geo_dashscope_api_key”,},“deepseek”: {“name”: “DeepSeek”,“base_url”: “https://api.deepseek.com”,“default_model”: “deepseek-v4-flash”,},“doubao”: {“name”: “豆包火山方舟”,“base_url”: “https://ark.cn-beijing.volces.com/api/v3”,},# hunyuan, moonshot, zhipu …}新增厂商的 SOP查厂商 OpenAI 兼容文档确认 base_url 与 model 字段含义在 PROVIDER_DEFAULTS 增加预设配置 .env 中对应的 GEO_*_API_KEY管理端「引擎管理」新增记录4.2 探测 LLMcreate_geo_llm 专门为 GEO 探测创建 LangChain 实例backend/app/core/geo/llm.pydef create_geo_llm(engine: GeoEngine) - ChatOpenAI:defaults get_provider_defaults(engine.provider) or {}base_url engine.base_url or defaults.get(“base_url”, “”)api_key resolve_api_key(settings, engine.api_key_env)kwargs { api_key: api_key, base_url: base_url, model: engine.model_code, temperature: engine.temperature, max_tokens: 2048, timeout: settings.geo_probe_timeout_seconds, } if engine.extra_body: kwargs[extra_body] engine.extra_body # 如混元搜索增强 return ChatOpenAI(**kwargs)分析器使用更便宜的模型默认 qwen-turbo通过 GEO_ANALYZER_PROVIDER / GEO_ANALYZER_MODEL 单独配置。4.3 中性探测提示词探测时必须避免「诱导模型推荐本品牌」因此 probe.py 使用固定中性 system promptNEUTRAL_SYSTEM_PROMPT (“你是一个乐于助人的助手。请根据你的知识如实回答用户问题”“可以列举多个选项并说明各自特点不要刻意回避或偏向任何品牌。”)async def probe_engine(engine: GeoEngine, prompt: str) - ProbeResult:llm create_geo_llm(engine)start time.perf_counter()response await llm.ainvoke([SystemMessage(contentNEUTRAL_SYSTEM_PROMPT),HumanMessage(contentprompt),])elapsed int((time.perf_counter() - start) * 1000)return ProbeResult(promptprompt, answercontent, latency_mselapsed)这是 GEO 测量可信度的关键我们测的是模型在自然状态下的品牌认知而不是 prompt 工程后的结果。LLM 结构化分析器原始回答是非结构化文本需要二次 LLM 调用提取指标。GeoAnalyzer 要求分析模型返回严格 JSON{“brand_mentioned”: true,“mention_rank”: 2,“recommendation”: “recommend”,“competitors_mentioned”: [“竞品A”],“citation_urls”: [“https://…”],“sentiment”: {“category”: “positive”, “score”: 0.6},“summary”: “一句话摘要”,“misunderstanding”: false,“entity_clarity”: “clear”}5.1 多次采样聚合当 sample_count 1 时使用多数投票策略字段 聚合规则brand_mentioned 超过半数采样为 true 则 truemention_rank 取有排名采样的算术平均并四舍五入recommendation 票数最多的态度competitors_mentioned 各采样并集misunderstanding 任一为 true 则 true这种设计在成本与稳定性之间取得平衡比单次探测更可靠又比大量采样更经济。5.2 容错分析器对 JSON 解析失败、LLM 调用异常均有降级处理返回默认的 not_mentioned 结构避免单条失败拖垮整次 Run。指标聚合与数据看板compute_run_metrics 将一批 snapshot 聚合为 Run 级指标供诊断、看板、基线对比复用backend/app/core/geo/metrics.py 输出结构{“total”: 24,“mentioned”: 14,“mention_rate”: 0.5833,“avg_mention_rank”: 2.1,“by_engine”: {“1”: {“total”: 8, “mentioned”: 5, “mention_rate”: 0.625}},“by_category”: {“recommend”: {“total”: 6, “mentioned”: 2, “mention_rate”: 0.333}},“by_recommendation”: {“recommend”: 8, “neutral”: 4, “warn”: 2, “not_mentioned”: 10},“competitor_sov”: {“竞品A”: 12, “竞品B”: 7},“citation_domains”: {“zhihu.com”: 5},“misunderstanding_count”: 1,}看板 API GET /api/v1/geo/dashboard 读取最近 Run 的 snapshot计算趋势与引擎对比若任务设置了 baseline_run_id还会输出优化前后 delta。优化闭环诊断 → 内容 → 发布 → 基线对比GEO 模块不只是需要「监控」也需要完整的优化闭环。7.1 自动诊断探测成功后schedule_diagnosis(run_id) 通过 asyncio.create_task 在后台启动诊断backend/app/core/geo/diagnoser.pydef schedule_diagnosis(run_id: int):asyncio.create_task(run_diagnosis_background(run_id))GeoDiagnoser 将聚合指标、品牌档案、样本摘要拼成 prompt让 LLM 输出summary整体可见度总结root_causes根因列表实体不清、信源缺失、竞品主导等recommendations优化建议FAQ、对比页、证据文档等weaknesses薄弱引擎 / 场景 / 竞品共现misunderstandings品牌被误解的具体案例诊断与探测分析使用同一套便宜模型控制成本。7.2 内容草稿生成GeoContentGenerator 根据诊断建议 品牌档案缺的话再根据优化补充一些生成多篇 Markdown/Html 草稿FAQ、对比页、教程等存入 geo_content_drafts 表等待人工审阅。7.3 发布到企业文档向量库/官网/各大第三方平台可以对接官网如果有 CMS 管理后台那更好生成各种文章审阅通过后GeoPublisher.publish_draft 将内容写入企业文档树GEO/└── {任务名}/├── FAQxxx 怎么样└── 对比xxx vs 竞品发布到企业文档知识库发布时同步调用 sync_document_to_vector写入 Chroma knowledge_document 集合。这意味着 GEO 优化内容最终进入助手可检索的知识库形成「探测 → 补缺 → 再探测」的闭环。7.4 基线对比可将优化前的 Run 设为基线PATCH /api/v1/geo/tasks/{id}/baseline发布内容后重新探测通过 compute_run_metrics 对比提及率变化。若下降超过 regression_threshold默认 0.1触发飞书回归告警。告警体系GeoFeishuAlert 支持三类飞书 Webhook 通知类型 触发条件探测告警 未提及 / 负面推荐且达到 threshold 条数诊断摘要 诊断完成后推送根因与建议 Top 3回归告警 当前 Run 提及率较基线下降 ≥ regression_threshold告警配置挂在任务级 alert_config JSON 字段示例{“enabled”: true,“alert_not_mentioned”: true,“alert_warn”: true,“threshold”: 1,“regression_threshold”: 0.1}Webhook 优先使用 GEO_FEISHU_WEBHOOK_URL可回退到舆情监控的 MONITOR_FEISHU_WEBHOOK_URL。取消与并发控制GEO 探测可能耗时较长品牌数 × 问题数 × 引擎数 × 采样次数 × LLM 延迟需要可靠的并发控制任务级 is_running 标志防止重复执行cancel_requested 循环内 is_cancel_requested() 检查实现手动停止僵尸 Run 清理超过 60 分钟仍为 running 则标记失败手动执行通过 asyncio.create_task 后台化API 立即返回backend/app/core/geo/cancel.pyasync def is_cancel_requested(task_id: int) - bool:async with AsyncSessionLocal() as db:result await db.execute(select(GeoTask.cancel_requested).where(GeoTask.id task_id))return bool(result.scalar_one_or_none())10. 环境配置各引擎 API KeyGEO_DASHSCOPE_API_KEYGEO_DEEPSEEK_API_KEYGEO_DOUBAO_API_KEYGEO_HUNYUAN_API_KEYGEO_MOONSHOT_API_KEYGEO_ZHIPU_API_KEY分析器建议便宜模型GEO_ANALYZER_PROVIDERdashscopeGEO_ANALYZER_MODELqwen-turbo执行参数GEO_PROBE_TIMEOUT_SECONDS60GEO_DEFAULT_SAMPLE_COUNT2GEO_DEFAULT_INTERVAL_MINUTES1440告警GEO_FEISHU_WEBHOOK_URL注意豆包 model_code 需填火山方舟推理接入点 IDep-xxxxDeepSeek 推荐 deepseek-v4-flashdeepseek-chat 已弃用混元可通过 extra_body.enable_enhancement 开启搜索增强11. 核心代码文件仅供参考文件 职责backend/app/core/geo/engine.py 任务调度与执行主循环backend/app/core/geo/probe.py 单引擎探测backend/app/core/geo/analyzer.py 回答结构化分析 采样聚合backend/app/core/geo/llm.py 探测/分析 LLM 工厂backend/app/core/geo/provider_registry.py 厂商预设与可用性检查backend/app/core/geo/metrics.py Run 级指标聚合backend/app/core/geo/diagnoser.py 诊断报告生成backend/app/core/geo/run_brief.py 执行分析报告事实汇总不含建议backend/app/core/geo/content_generator.py 优化内容草稿生成backend/app/core/geo/publisher.py 发布到企业文档 向量库backend/app/core/geo/alert.py 飞书告警backend/app/core/geo/cancel.py 取消控制backend/app/api/v1/geo.py REST API 层backend/app/core/scheduler/init.py 定时任务注册frontend/src/views/admin/geo/* 管理端页面12. 设计经验总结探测与分析分离探测用大模型、分析用便宜模型成本和效果兼顾。中性 prompt 是测量基准GEO 的数据可信度取决于探测时不对品牌做任何引导。OpenAI 兼容层降低接入成本新厂商只需配置 base_url model_code 以及 apiKey无需重写调用逻辑。采样 投票抑制随机性LLM 回答本身有波动多次采样聚合让指标更稳定。闭环比监控更有价值诊断 → 草稿 → 发布向量库 → 基线对比让 GEO 从「看数据」变成「改数据、验效果」。