大数跨境

纯代码小白也可以手搓一个GEO工具

纯代码小白也可以手搓一个GEO工具 AI效率圈A
2026-08-29
2
导读:我做了一个 GEO 工具,前后折腾了近半个月,1 个人,从立项到 81MB NSIS 安装包出包。


我做了一个 GEO 工具,前后折腾了近半个月,1 个人,从立项到 81MB NSIS 安装包出包。

跑通之后第一次 monitor:6 个 AI 引擎 1024 次查询,86 次提到我——跨引擎 AI 提及率 8.32%

这个数现在看不算高。但我第一次跑的时候是 0%。部署内容、优化结构、跑通 6 引擎监测这一套跑下来,从 0 到 8.32% 的过程,踩过的坑比代码多。

我把 30 天的完整过程整理成分节内容放在最后,本篇文章是骨架导览。


什么是 GEO

一句话:让 AI 在回答里提到你

以前做 SEO,是让百度谷歌搜得到你。现在大家买东西前不打开百度了——直接问豆包、问 Kimi。AI 答完就完事,你网站连出场机会都没有。

GEO(Generative Engine Optimization)就是让 AI 引擎在回答用户问题时,愿意把你的网站 / 品牌作为引用源写进答案。

国内外都已经有人接单做这个。工具侧目前最完整的方案是 Otterly.AI / Profound 这类,但都不接国内 6 引擎(豆包、DeepSeek、通义、文心、Kimi、腾讯元宝),所以我自己写了一个。


工具的技术骨架

整个工具分四层:





    
    
    
    
1
2
3
4
5
6
7
8
9
┌─────────────────────────────────┐
│  桌面端 Tauri 2(WebView2)     │  ← 用户能本地跑
├─────────────────────────────────┤
│  前端 Next.js 14 standalone     │  ← 8 大模块 UI
├─────────────────────────────────┤
│  后端 Python FastAPI             │  ← 6 引擎 LLM + 数据
├─────────────────────────────────┤
│  LLM 6 引擎 + 监测 + 部署       │  ← 数据来源
└─────────────────────────────────┘

下面分别讲每层做什么、怎么搭。


第一层:Tauri 桌面端壳

为什么选 Tauri 不选 Electron:Tauri 包大小只有 81MB(Electron 通常 200MB+),启动 < 1 秒,内存 30-50MB,且复用系统 WebView2(用户已经装了 Edge 就有)。

桌面端做的是sidecar 模式——Tauri 主进程启动后,自动拉起 backend (Python exe) 和 frontend (Next standalone),分别监听 :8000 和 :3001,然后 Tauri 窗口加载 http://localhost:3001

Sidecar 启动代码大约 100 行 Rust,核心逻辑:





    
    
    
    
1
2
3
4
5
6
let mut backend_cmd = Command::new(&backend_path);
backend_cmd
    .env("GEO_MINIMAX_MODEL", "MiniMax-Text-01")
    .env("GEO_PORT", "8000")
    .env("GEO_NO_BROWSER", "1");
let backend = backend_cmd.spawn()?;

踩坑提示:sidecar 启动失败时 Tauri 窗口会显示"localhost 拒绝连接"——但用户不知道为什么。要给一个错误兜底 UI。


第二层:Next.js 前端

8 大模块:

模块
URL
作用
概览
/dashboard
4 KPI + 6 引擎状态 + 趋势
监控中心
/monitors
触发监测 + 看历史
GEO 工具
/tools
6 个白帽工具
内容工场
/content
5 步写作流
客户管理
/clients
多客户
账户中心
/account
API&集成 + 订阅
通知中心
/notifications
系统通知
设置
/settings
5 主题切换

关键技术决策

  • output: "standalone": 让 Next.js 打包出一个 86MB 的自包含 Node 服务(不用 next start 全套)
  • 5 套主题用 CSS 变量切换: data-theme="midnight" 改一组 CSS 变量,不重载
  • 客户端组件必须抽离: useState / useEffect 必须在 "use client" 文件里,server component 里用 hook 会编译失败
  • 跨页 deep-link: tools 生成结果 → content 预填表单,靠 sessionStorage 传值




    
    
    
    
1
2
3
4
5
// tools/page.tsx
const handleApply = (result, step) => {
  sessionStorage.setItem("workflow-input", JSON.stringify(result));
  window.location.href = `/content?step=${step}`;
};

踩坑提示:SWC 编译报错行号不可信——报 line 100,实际错在 line 50,类型不匹配引发。保持数组对象类型一致。


第三层:Python FastAPI 后端

为什么 Python:爬虫、内容改写、SEO 审计都是 Python 生态,重写不划算。

后端分 4 块:

  1. API 路由/api/clients/*
    /api/monitors/*/api/tools/*
  2. 服务层(monitor_service、analytics、automation)
  3. LLM 适配层(每个引擎一个文件,统一接口)
  4. 数据库(SQLite + SQLAlchemy + Alembic)

6 引擎的接入用可插拔设计:





    
    
    
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# app/llm/base.py
class LLMBackend(ABC):
    @abstractmethod
    async def query(self, prompt: str, **kwargs) -> str:
        raise NotImplementedError

# 每个引擎一个文件
class OllamaBackend(LLMBackend): ...
class DoubaoBackend(LLMBackend): ...
class TongyiBackend(LLMBackend): ...

# 注册表
BACKENDS = {
    "ollama": OllamaBackend,
    "doubao": DoubaoBackend,
    # ...
}

没配 API key 就用 ollama 本地默认qwen3.5:4b),零成本跑通。要切换 6 引擎,只在 .env 里加 key。

数据库用 SQLite 单文件,跟用户电脑走。dogfood 阶段 42 篇文章 + 几万个 mention 完全够用,不需要 PostgreSQL。

踩坑提示:Python 的 tz-aware vs tz-naive 是经典坑——datetime.utcnow() 是 naive,datetime.now() + DB 存的是 aware,比较前必须 replace(tzinfo=None)


第四层:6 引擎 LLM 集成

每个引擎有自己 API 格式,但做 3 件事:

  1. 接受关键词 + 品牌名
  2. 真实调用引擎搜索
  3. 解析回答里是否提到品牌

比如 ollama 本地:





    
    
    
    
1
2
3
4
5
6
7
async def query(self, prompt: str, **kwargs) -> str:
    r = await client.post(
        f"{self.base_url}/api/generate",
        json={"model": "qwen3.5:4b", "prompt": prompt, "stream": False},
        timeout=60,
    )
    return r.json()["response"]

豆包走 OpenAI 兼容 API,本质是同样的 chat completion。

判断"是否提到" 有两种策略:

  • 简单匹配:if brand in response_text
  • LLM 判定:让另一个 LLM 读回答 + 品牌名 + 判定结果

我用的是混合——简单匹配 + LLM 二判。LLM 输出的"判定"比较准,但慢。

6 引擎分布(我跑的真实数据):

  • minimax 内置兜底:256 次命中
  • ollama 本地:228 次
  • dashscope / deepseek / hunyuan:各 150 次左右
  • 商业 4 引擎(豆包/Kimi/文心/腾讯元宝)接口 key 

第五层:6 个白帽工具

/tools 页面提供 6 个工具,每个 3 秒内出可验证结果:

工具
输出
标准来源
GEO 评分
8 维度打分卡
Princeton GEO + Google 质量指南
Princeton 改写
应用 GEO 8 规则后的内容
Princeton 公开方法
llms.txt
AI 爬虫可读的站点说明
llmstxt.org
Schema.org
JSON-LD 结构化数据
schema.org 官方
FAQ
关键词对应问答
谷歌 PAA
S.A.S
70/20/10 行业内容
自家方法论

每个工具统一模式:





    
    
    
    
1
2
3
4
5
6
@router.post("/score")
async def score(payload: ScoreRequest, db: Session = Depends(get_db)):
    prompt = build_score_prompt(payload.content, payload.brand)
    raw = await llm_registry.query("ollama", prompt)
    parsed = parse_score_json(raw)  # 容错解析
    return ScoreResponse(scores=parsed, overall=sum(s.score for s in parsed) / 8)

跨工具工作流





    
    
    
    
1
2
3
4
5
6
7
8
9
用户输入弱内容
 ↓ GEO 评分(找最弱维度)
 ↓ Princeton 改写(应用 8 规则)
 ↓ Schema.org(生成 JSON-LD)
 ↓ llms.txt(生成站点级文件)
 ↓ FAQ(生成问答段落)
 ↓ S.A.S(生成扩展内容)
 ↓ 发布到 xxx.cn
 ↓ 触发 monitor 验证

这是 GEO 工具的"价值放大器"——单点工具 + 工作流 = 真实业务闭环。


打包:从 0 到 81MB 安装包

最后讲打包——这是最折腾的一步。

后端打包(PyInstaller frozen exe 46MB):





    
    
    
    
1
pyinstaller pyinstaller.spec --clean --noconfirm

pyinstaller.spec 关键配置——datas 必须用绝对路径





    
    
    
    
1
2
3
4
5
6
7
8
9
10
import os
PROJECT_ROOT = os.path.dirname(os.path.abspath(SPEC))
a = Analysis(
    [os.path.join(PROJECT_ROOT, 'geo_backend_launcher.py')],
    pathex=[PROJECT_ROOT],
    datas=[
        (os.path.join(PROJECT_ROOT, 'alembic'), 'alembic'),
        (os.path.join(PROJECT_ROOT, 'alembic.ini'), '.'),
    ],
)

这里我踩过后才暴露的坑——spec 用相对路径时,PyInstaller 是相对 cwd 而不是 spec 位置解析。第一次打包跑通,30 天后重打就报 alembic.ini not found,因为 cwd 换了。

NSIS 安装包(最终 81MB):

Tauri bundler 要下载 NSIS 工具(nsis-3.11.zip + nsis_tauri_utils.dll),GitHub Releases 在国内不稳。我的解法:





    
    
    
    
1
TAURI_BUNDLER_TOOLS_GITHUB_MIRROR=http://127.0.0.1:18765/

本地起一个 mirror server,所有路径都返回正确的文件,tauri-bundler 完全不知道。dll 用国内镜像 ghfast.top 下载。

junction + glob 不跟随binaries/node 是 junction(指向真实目录),tauri 的 glob ** 不跟随 symlink——直接报 path not found。解法是 robocopy 复制真实目录 + 用目录映射代替 ** glob。


真实 dogfood 数据

跑通工具后,拿自己新建的网站当小白鼠

指标
第 42 次(基线)
第 43 次(部署后)
提及
82 / 1024
86 / 1034
提及率
8.01%
8.32%
状态
completed
completed

绝对 +0.31pp,相对 +3.9%。

这中间有个坑值得讲——我第一次跑出 19.5% 提及率时差点拿出去吹。后来发现 19.5% 是单引擎(minimax)视角,跨 6 引擎平均只有 8.32%。

教训:跨引擎平均比单引擎数字更接近真实市场。别拿"最好看的数字"说话

工具能跑、6 引擎全跑通、81MB 安装包出来。还在用自己的网站dogfooding, 能否变现要看后续真实数据情况,这是我现在面对的现实。

但工具是入口,不是终点。下一步:给 5 个潜在客户做GEO 体检,看谁愿意继续。


课程 9 集目录

主题
踩坑密度
00
课程总览(学习路径建议)
01
立项与技术选型(Tauri vs Electron 决策)
02
环境搭建与中文路径踩坑
(junction + pnpm shim)
⭐⭐⭐
03
Next.js 前端架构(8 模块 + 5 主题)
⭐⭐⭐
04
Python 后端与 6 引擎接入
⭐⭐⭐
05
工具集开发 GEO 6 件套
⭐⭐
06
PyInstaller 打包踩坑
(alembic / frozen exe)
⭐⭐⭐
07
Tauri 桌面端封装(sidecar + 5 主题)
⭐⭐⭐
08
NSIS 安装包打包
(mirror server 突破 GitHub 超时)
⭐⭐⭐⭐
09
dogfood 验证与反思

全课程 9.4 万字,每集含:

  • 我为什么这么做
  • 我做错了哪些决策
  • 真实代码片段(可直接复制)
  • 我现在会怎么改

怎么领

【声明】内容源于网络
0
0
AI效率圈A
1234
内容 0
粉丝 0
AI效率圈A 1234
总阅读0
粉丝0
内容0