Files
InsightReply/docs/IMPLEMENTATION_PLAN.md
zs 8cf6cb944b
Some checks failed
Extension Build & Release / build (push) Failing after 1m5s
Backend Deploy (Go + Docker) / deploy (push) Failing after 1m40s
Web Console Deploy (Vue 3 + Vite) / deploy (push) Has been cancelled
feat: 部署初版测试
2026-03-02 21:25:21 +08:00

21 KiB
Raw Permalink Blame History

InsightReply 实施计划 (Implementation Plan)

本文档记录了 InsightReply 各模块的具体技术实现方案,是 DEVELOPMENT_PLAN.md(做什么)的落地补充(怎么做)。 功能完善度的产品策略分析见 → PRODUCT_ROADMAP.md


一、数据抓取策略 (Data Acquisition Strategy)

InsightReply 采用 "前端主动感知 + 后端规则引擎" 的双模式来实现数据抓取:

1. 插件端交互式抓取 (User-Driven)

  • 触发场景:用户在 X (Twitter) 上浏览推文时,想针对某条推文生成评论。
  • 实现逻辑Content Script 直接从浏览器 DOM 中提取当前选定推文的作者、正文、互动数 (Like/Reply)。
  • 优点:零延迟,无需后端预先抓取该推文,即看即得。

2. 后端雷达监控抓取 (System-Driven / Radar)

  • 方案选型对比
方案 代表 优点 缺点 月费
付费 SaaS Apify / RapidAPI 即插即用,免维护 按次计费 $30-$100+
自建开源 Nitter + Camoufox 几乎免费 技术门槛高 仅服务器费
  • 最终选型:自建 Nitter 开源方案。
  • Nitter 实例地址https://x.beenglish.eu.org/

二、浏览器插件技术实现 (Extension Architecture)

1. Content Script 与 UI 注入

  • Content Script (src/content/index.ts):监听页面 URL 变化,使用 MutationObserver 实时检测新加载的推文 DOM 节点。
  • Shadow DOM 注入:在推文操作栏注入"Insight"入口按钮。点击后展示主面板,面板挂载在 Shadow DOM 内,确保与 Twitter 原生样式完全隔离。
  • Background Service Worker:作为中转站,处理与后端 Go API 的通信和认证。

2. UI 设计规范 (ui-ux-pro-max)

  • 暗黑毛玻璃风格:主色调 #0A0A0A ~ #171717,浮动面板使用 backdrop-filter: blur()
  • 品牌渐变色:紫蓝渐变 #8B5CF6#3B82F6,用于 CTA 按钮和高亮标签。
  • 字体:优先使用 Inter / Geist / SF Pro 等现代无衬线字体。
  • 微动画:所有状态切换配 ease-in-out 过渡(200ms-300ms)。

3. 技术栈规范

  • Tailwind CSS v4:所有间距、颜色从 Design Tokens 读取,禁止硬编码内联样式。
  • Vue 3 Composition API:高频 UI 元素(Button, Card, Badge)封装为基础组件。
  • cn() 工具函数:基于 clsx + tailwind-merge 统一处理动态 Class 冲突。
  • 轻量化打包:禁止引入完整组件库,采用按需加载。

4. Content Script 性能优化策略 (新增)

在 Twitter 重型 SPA 中,粗暴监听全文档 DOM 变更会产生严重性能问题。

  • 收缩监听范围:将 MutationObserverobserve 目标从 document.body 收缩到 main[role="main"] 或 Timeline 容器。
  • 防抖扫描scanTweets() 加入 requestIdleCallbackdebounce(200ms),避免高频回调。
  • 已处理标记:通过 WeakSet<HTMLElement> 记录已注入按钮的推文节点,避免重复扫描。
  • 多选择器 FallbackTwitter 的 data-testid 属性随时可能变更,已处理推文选择器应支持多层 Fallback
    const TWEET_SELECTORS = [
      'article[data-testid="tweet"]',
      'article[role="article"]',
      'div[data-testid="cellInnerDiv"] article'
    ];
    

三、高可用后台抓取系统 (Industry Radar - Enterprise Architecture)

考虑到系统的稳定性、安全性和反风控 (Anti-Ban),自建 Nitter 之上的抓取系统设计为一套健壮的企业级爬虫架构。

1. 终极反风控与防封禁策略 (Anti-Ban Mechanisms)

机制 说明
请求抖动 (Jitter) 每次请求间加入 1s-5s 强随机延迟,严禁整点并发
熔断降级 (Circuit Breaker) Nitter 连续返回 429/503 时自动暂停 30 分钟
Fallback 节点池 主节点熔断时自动切换到备用 Nitter 实例
指纹轮换 (Fingerprint Rotation) 同步轮换 UA + Sec-Ch-Ua + Accept-Language 等全套 Header
会话隔离 (Session Isolation) 每个采集任务独立 Cookie Jar避免跨任务身份串联

2. 高可用采集架构 (Scraper & Queue)

  • 异步任务队列:基于 Redis 的 Asynq,解耦"触发"与"执行",控制最大并发数。
  • 指数退避重试 (Exponential Backoff):失败后按 1min → 3min → 10min 递增重试间隔。
  • 采集器健壮性
    • goquery 解析找不到元素时记录 Warn返回部分数据绝不 Panic
    • 关键报错时 Dump HTML 快照到日志表,方便排查 Nitter DOM 结构变更。

3. 数据计算与存储层

  • 批量 Upsert:使用 ON CONFLICT DO UPDATE 策略,降低 IO 压力,防止死锁。
  • 热度公式
    heat_score = (Like增量 × 0.4) + (RT增量 × 0.3) + (Reply增量 × 0.3)
    
  • 动态智能抓取频率 (Smart Crawling)
    • 🔥 热度飙升的推文 → 高频队列(每 15 分钟抓一次)
    • 🧊 24 小时无新动态 → 低频队列(每 4 小时抓一次)
    • 极大节省抓取资源,显著降低被封概率。

四、后端安全与认证体系 (新增)

1. JWT 认证方案

所有 /api/v1 路由(除 /auth/* 外)必须经过 JWT 认证中间件。

  • 技术选型go-chi/jwtauth + HMAC-SHA256 签名。
  • Token 结构
    {
      "sub": "user-uuid",
      "tier": "Pro",
      "exp": 1709164800
    }
    
  • 刷新策略Access Token 有效期 24hRefresh Token 有效期 30d存于 chrome.storage.local

2. Rate Limiting分级限流

Tier 评论生成 监控关键词 监控账号
Free 10 次/天 3 个 3 个
Pro 无限 20 个 20 个
Premium 无限 50 个 50 个
  • 实现方案:基于 Redis 的滑动窗口计数器Key 格式:ratelimit:{user_id}:{action}:{window}
  • 中间件挂载:在 chi Router 中通过 r.Use(RateLimitMiddleware) 全局或分路由挂载。

3. CORS 配置

r.Use(cors.Handler(cors.Options{
    AllowedOrigins:   []string{"chrome-extension://*", "https://x.com", "https://twitter.com"},
    AllowedMethods:   []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
    AllowedHeaders:   []string{"Authorization", "Content-Type"},
    AllowCredentials: true,
    MaxAge:           300,
}))

五、LLM 服务韧性设计 (新增)

1. 调用链路防护

请求 → Timeout Guard (30s) → Circuit Breaker → Retry (max 2) → OpenAI API
  • Timeoutcontext.WithTimeout(ctx, 30*time.Second) 包裹每次 LLM 调用。
  • Circuit Breaker:使用 sony/gobreaker,连续 5 次失败后半开,每 60s 试探一次恢复。
  • 指数退避重试:仅对 5xx / Timeout 重试4xx如 quota exceeded立即失败。

2. 多模型动态路由与 Fallback

系统重构为 多 Provider 支持 (OpenAI / Anthropic / DeepSeek / Gemini),以应对不同用户的专属模型偏好和单一 Provider 宕机时的容灾。同时支持代理接口与自定义模型

路由与配置设计

  1. 环境变量驱动 (ENV):管理员可通过配置 OPENAI_BASE_URL 改写接口地址(完美兼容 Groq、vLLM、Ollama 等任意 OpenAI 兼容代理)。
  2. 可用模型下发:通过 OPENAI_AVAILABLE_MODELS="gpt-4o,gpt-4o-mini" 配置白名单,后端通过 GET /sys/config/llms 统一向前端下发。
  3. 前端交互 (default_llm_model):前端展示为**「可输入的下拉列表 (Combobox)」**,用户既可从系统下发的列表中点选,也支持手动输入任意字符串,实现完全自定义。
  4. 故障转移 (Fallback):当前尝试的 Provider 返回 5xx 时,按兜底顺序切换:Anthropic → OpenAI → Gemini → DeepSeek

统一适配器抽象 建立统一的 LLMProvider 接口,抹平各平台 API 结构差异,内部集成对应 SDK

  • OpenAI (含兼容代理): sashabaranov/go-openai (支持通过 Builder 传入 BaseURL)
  • Anthropic: 直接构造 REST API 请求
  • DeepSeek: 兼容 OpenAI SDK基于 DEEPSEEK_BASE_URL 重连
  • Gemini: google.golang.org/api/generativelanguage/v1beta

3. Token 成本审计

每次 LLM 调用记录 prompt_tokens + completion_tokens,写入 api_usage_logs 表:

INSERT INTO api_usage_logs (user_id, provider, model, prompt_tokens, completion_tokens, cost_usd)
VALUES ($1, $2, $3, $4, $5, $6);

六、Prompt 工程规范 (新增)

1. 策略模板结构

每个评论策略维护独立的 Prompt 模板文件,存放于 server/prompts/ 目录:

server/prompts/
├── system.txt            # 全局 System Prompt
├── cognitive_upgrade.txt  # 认知升级型
├── contrarian.txt         # 反向观点型
├── data_supplement.txt    # 数据补充型
├── empathy.txt            # 共鸣型
└── founder_exp.txt        # 创始人经验型

2. Prompt 结构公式 (必须遵守)

[System Prompt]
- 角色定义:专业社交媒体表达顾问
- 输出约束:字数、语言、格式

[User Prompt]
- 用户身份标签:{identity}
- 目标推文:{tweet_content}
- 策略指令:{strategy_specific_instruction}
- 结构公式Hook + Position + Insight + Brevity
- Few-shot 示例2-3 条高质量参考

[Constraints]
- 不超过 280 字符 (或用户指定长度)
- 语言:与原推文一致,或用户指定
- 语气与身份匹配
- 禁止引号包裹

3. 批量生成规范

API 单次返回 5 种策略 × 2 条备选 = 10 条候选评论

  • 方案 A单次 LLM 调用Prompt 中要求 JSON 数组输出
  • 方案 B5 组并发调用,每组 n=2
  • 推荐方案 A,减少 API 调用次数

七、后端 Go 接口规范

  • 采用 RESTful 标准。
  • 所有接口返回统一 JSON 结构:
    {
      "code": 200,
      "message": "success",
      "data": {}
    }
    
  • 错误码体系:4xxx 为客户端错误,5xxx 为服务端错误。
  • 详细接口文档见 → docs/API.md

八、环境变量与配置管理 (新增)

所有运行时配置统一通过环境变量注入,禁止硬编码

变量名 说明 示例
DATABASE_URL PostgreSQL 连接串 postgres://user:pass@host:5432/db
OPENAI_API_KEY OpenAI API Key sk-...
JWT_SECRET JWT 签名密钥 随机 32+ 字符串
SERVER_PORT 服务端口 8080
CORS_ORIGINS 允许的跨域来源 chrome-extension://*
LOG_LEVEL 日志级别 info / debug / warn
LLM_TIMEOUT_SEC LLM 调用超时秒数 30

模板文件 → server/.env.example


九、验证计划 (Verification Plan)

# 验证项 方法
1 防封控链路 模拟 100 并发请求,验证熔断 + Jitter 能正确拦截
2 HTML 解析容错 模拟账号冻结/推文被删等异常页面,确认不会 Panic
3 Shadow DOM 隔离 在 X 深色/浅色模式下验证插件样式不被污染
4 端到端生成链路 插件点击 → Background → Go API → LLM → 返回结果
5 JWT 认证 (新增) 无 Token / 过期 Token / 非法 Token 拒绝访问
6 Rate Limiting (新增) Free 用户超 10 次/天后返回 429
7 LLM 韧性 (新增) 模拟 OpenAI 超时 / 5xx验证熔断降级 + 重试
8 Graceful Shutdown (新增) 发送 SIGTERM验证在途请求完成后才退出
9 Onboarding 流程 (新增) 首次打开插件触发引导,设置存入 chrome.storage + 后端
10 多条备选评论 (新增) 验证返回 3 条备选Sidebar 卡片式展示正确
11 热度标签 (新增) 在高互动推文旁正确显示 🔥/ 标签
12 效果追踪闭环 (新增) 复制评论 → 24h 后回查 → 互动数据写入 DB

十、用户 Onboarding 实现方案 (新增)

1. 流程设计

首次安装/首次打开插件时,检测 chrome.storage.sync 中是否存在 onboarding_completed 标志。若无,显示 3 步引导:

// background/index.ts
chrome.runtime.onInstalled.addListener(({ reason }) => {
  if (reason === 'install') {
    chrome.storage.sync.set({ onboarding_completed: false });
  }
});

2. 数据存储

字段 存储位置 说明
identity_label chrome.storage.sync + users 身份标签
language_preference chrome.storage.sync + users 偏好语言
tone_preference chrome.storage.sync + user_style_profiles 风格倾向
onboarding_completed chrome.storage.sync 是否已完成引导

3. 与生成链路的集成

用户设置完成后,每次生成评论时自动读取 chrome.storage.sync 中的偏好,附加到 GENERATE_REPLY 消息中:

// 改造 Sidebar.vue 的 generate()
const prefs = await chrome.storage.sync.get(['identity_label', 'language_preference', 'tone_preference']);
chrome.runtime.sendMessage({
  type: 'GENERATE_REPLY',
  payload: {
    tweetContent: props.tweetData.content,
    strategy: 'all',
    identity: prefs.identity_label,
    language: prefs.language_preference,
    tone: prefs.tone_preference
  }
});

十一、前端热度标签实现方案 (新增)

1. 判断逻辑

interface HeatLevel {
  label: string;
  emoji: string;
  className: string;
}

const getHeatLevel = (likes: number, minutesAgo: number): HeatLevel | null => {
  if (likes > 1000 && minutesAgo < 120) {
    return { label: 'Trending', emoji: '🔥', className: 'heat-trending' };
  }
  if (likes > 100 && minutesAgo < 60) {
    return { label: 'Rising', emoji: '⚡', className: 'heat-rising' };
  }
  return null;
};

2. 注入位置

injectInsightButton() 函数中,紧挨 Insight 按钮旁边注入热度标签:

  • 🔥 Trending红色渐变 Badge (background: linear-gradient(135deg, #ef4444, #f97316))
  • Rising黄色渐变 Badge (background: linear-gradient(135deg, #f59e0b, #eab308))

3. 时间计算

从推文 DOM 中的 <time datetime="..."> 元素提取发帖时间,计算与当前时间的差值:

const timeEl = tweetElement.querySelector('time');
const postedAt = new Date(timeEl?.getAttribute('datetime') || '');
const minutesAgo = (Date.now() - postedAt.getTime()) / 60000;

十二、数据飞轮 — 效果追踪与风格学习 (新增)

1. 效果追踪数据流

用户复制评论
    │ copyToClipboard() → 同时记录 hash(reply_text) 到 chrome.storage.local
    ▼
chrome.storage.local:
  tracked_replies: [{
    hash: "a1b2c3",
    text: "Most people miss...",
    strategy: "contrarian",
    copied_at: 1709164800,
    tweet_url: "https://x.com/.../status/..."
  }]
    │
    ▼
Content Script 延迟触发 (当用户访问自己 Profile 页时)
    │ 条件: URL 匹配 x.com/{current_user}
    ▼
扫描用户近期 Tweets/Replies
    │ 对比 tracked_replies 中的 text hash
    ▼
匹配成功 → 提取当前 Likes / Replies 数
    │
    ▼
chrome.runtime.sendMessage → Background → POST /api/v1/replies/{id}/performance
    │
    ▼
写入 reply_performance 表

2. 风格学习 Prompt 注入

user_style_profiles 表有足够数据(≥ 10 条追踪记录)后,生成评论时自动注入风格画像:

[附加上下文 - 个人风格画像]
基于你过去 30 天的高互动评论分析:
- 最有效策略: {top_strategies} (平均互动率 {avg_rate}%)
- 风格特征: {style_description}
- 高频高互动关键词: {keywords}
- 偏好评论长度: {avg_length} 字符

请参考以上风格特征生成评论。

3. 风格特征提取 (后端定时任务)

每周对每个用户的 reply_performance 数据运行一次 LLM 分析:

System: 你是社交媒体互动分析专家。
User: 以下是该用户最近 30 天互动率最高的 10 条评论:
{replies_list}

请总结其写作风格特征, 包括:
1. 最常用的句式结构
2. 高频关键词或短语
3. 语气倾向 (专业/幽默/犀利)
4. 平均有效长度

输出为 JSON 格式。

十三、用户可配置系统设计 (新增)

设计原则:系统不硬编码任何特定产品/领域/策略。所有与用户场景相关的能力均通过用户自定义设置实现,确保对任意行业、任意产品类型的可扩展性。

1. 架构思想:零硬编码 (Zero Hardcoding)

传统做法 (❌):
  Prompt 里写死 "你是一个 AI 创始人,正在推广 SwiftBiu..."

可扩展做法 (✅):
  Prompt 运行时从 user_product_profiles 表 + user_custom_strategies 表
  动态拼装上下文,适用于任何用户、任何产品

2. 产品档案 (Product Profile) 注入机制

当用户配置了产品档案后,生成评论时自动注入以下上下文块:

[产品上下文 — 自动注入,仅当用户已配置产品档案时]
你正在帮助一位 {identity} 撰写社交评论。
该用户正在推广的产品: {product_name} — {tagline}
产品所属领域: {domain}
核心功能: {key_features}
目标用户群: {target_users}
{custom_context}

注意:
- 不要直接提及产品名称或链接 (除非用户使用了"创始人实战型"策略)
- 评论应从 {domain} 领域专家的角度出发,让读者产生"这个人很懂行"的印象
- 引发好奇心 → 点击 Profile → 发现产品,而非硬推

3. 自定义策略运行时

用户自定义的策略模板支持以下模板变量,运行时自动替换:

变量 来源 说明
{tweet_content} 当次请求 目标推文原文
{identity} 用户设置 身份标签
{product_name} 产品档案 产品名称
{domain} 产品档案 所属领域
{key_features} 产品档案 核心功能
{competitors} 产品档案 竞品列表
{language} 用户设置 输出语言
{max_length} 当次请求 最大字符数
{custom_context} 产品档案 自定义上下文

后端处理流程

// service/ai_service.go
func (s *AIService) buildPrompt(req GenerateRequest, profile *ProductProfile, strategies []Strategy) string {
    // 1. 加载 System Prompt
    // 2. 如果有产品档案 → 注入产品上下文块
    // 3. 合并内置策略 + 用户自定义策略
    // 4. 替换所有模板变量
    // 5. 如果有风格画像 (user_style_profiles) → 注入风格上下文
    // 6. 返回最终 Prompt
}

4. 前端推文相关性评分

Content Script 基于产品档案中的 relevance_keywords 对当前浏览的推文做实时相关性判断:

// content/relevance.ts
const scoreRelevance = (tweetText: string, keywords: string[]): number => {
  const text = tweetText.toLowerCase();
  let score = 0;
  for (const kw of keywords) {
    if (text.includes(kw.toLowerCase())) score++;
  }
  return score;
};

// 注入标签
const relevance = scoreRelevance(tweetData.content, userProfile.relevance_keywords);
if (relevance >= 2) {
  // 注入 🎯 "High Relevance" 标签
}

关键词来源chrome.storage.sync 缓存用户的 relevance_keywords(来自产品档案 API定期同步。

5. 前端策略合并展示

Sidebar 策略选择器同时展示系统内置策略和用户自定义策略:

// Sidebar.vue
const allStrategies = computed(() => [
  ...builtinStrategies,                // 系统内置 5 种
  ...userCustomStrategies.value        // 用户自定义 N 种 (从 API 拉取)
]);

自定义策略用不同背景色或 ⚙️ Custom 标签区分,方便用户识别。

6. Prompt 组装顺序

┌─────────────────────────────────────────────┐
│ System Prompt (角色定义 + 输出约束)           │
├─────────────────────────────────────────────┤
│ [可选] 产品上下文 (如果用户配置了产品档案)     │
├─────────────────────────────────────────────┤
│ [可选] 个人风格画像 (如果有 ≥10 条追踪数据)   │
├─────────────────────────────────────────────┤
│ User Prompt:                                 │
│   - 身份标签                                 │
│   - 目标推文                                 │
│   - 策略指令 (内置 or 用户模板,变量已替换)    │
│   - 结构公式: Hook + Position + Insight       │
│   - Few-shot 示例 (系统默认 or 用户自定义)     │
├─────────────────────────────────────────────┤
│ Constraints (字数/语言/格式)                  │
└─────────────────────────────────────────────┘