← 2026-06-29 📂 All Days 2026-07-01 →

🏗️ 系统设计 / System Design — Day 78

Topic: Design an AI Chatbot Platform (ChatGPT-scale)

Difficulty: Expert | Phase: Expert


想象你在设计... / Imagine you're designing...

你是 OpenAI 的首席架构师。需要设计一个能同时支持 1000 万并发用户的 AI 对话平台。每个请求都需要调用一个巨大的 LLM,延迟敏感,成本巨高,故障不可接受。

You're the lead architect at OpenAI. Design a platform that serves 10 million concurrent users, each streaming responses from a massive LLM — latency-sensitive, extremely expensive, zero tolerance for failures.


核心挑战 / Core Challenges

  1. LLM 推理极慢 — GPT-4 级别模型,首 token 延迟 500ms-2s
  2. 流式输出 — 用户要看到逐字"打字"效果,不是等全部完成
  3. 有状态会话 — 每轮对话需要历史 context
  4. 成本爆炸 — 每 1M tokens 约 $10-30,乘以 1000 万用户
  5. GPU 是瓶颈 — A100/H100 极贵,利用率必须最大化

架构图 / Architecture Diagram

┌─────────────────────────────────────────────────────────────┐ │ CLIENTS │ │ Web / iOS / Android / API / Plugins │ └────────────────────────┬────────────────────────────────────┘ │ WebSocket / SSE (streaming) ▼ ┌─────────────────────────────────────────────────────────────┐ │ API GATEWAY LAYER │ │ Auth (JWT/OAuth) │ Rate Limiting │ Abuse Detection │ │ (Kong / Nginx + Lua) │ └──────────┬──────────────────────────────┬───────────────────┘ │ │ ▼ ▼ ┌─────────────────────┐ ┌─────────────────────────────┐ │ CONVERSATION SVC │ │ SESSION STORE │ │ - History mgmt │◄─────►│ Redis Cluster │ │ - Context window │ │ (last N turns, TTL 24h) │ │ - Token counting │ └─────────────────────────────┘ └──────────┬──────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ INFERENCE ROUTER │ │ - Model selection (GPT-4o / GPT-4 / GPT-3.5 by cost) │ │ - Load balancing across GPU pods │ │ - Priority queuing (paid > free) │ └──────────┬──────────────────────────┬───────────────────────┘ │ │ ▼ ▼ ┌─────────────────────┐ ┌─────────────────────────────────┐ │ GPU CLUSTER A │ │ GPU CLUSTER B │ │ (A100/H100 pods) │ │ (Spot instances for overflow) │ │ vLLM / TensorRT │ │ vLLM + dynamic batching │ │ KV-Cache enabled │ │ │ └──────────┬──────────┘ └──────────────────────────────────┘ │ ▼ SSE stream ┌─────────────────────────────────────────────────────────────┐ │ STREAMING PROXY │ │ - Chunked transfer (token by token) │ │ - Connection multiplexing │ │ - Backpressure handling │ └──────────┬──────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ STORAGE LAYER │ │ PostgreSQL (conversations) │ S3 (attachments/files) │ │ ElasticSearch (search) │ ClickHouse (analytics) │ └─────────────────────────────────────────────────────────────┘

关键设计决策 / Key Design Decisions

1. 流式传输用 SSE,不用 WebSocket

  • SSE (Server-Sent Events) = 单向流,更简单,CDN 友好
  • WebSocket 是双向的,但 LLM 推理只需要服务端→客户端方向
  • SSE 天然支持断线重连 (Last-Event-ID)

2. vLLM + Continuous Batching

  • 传统推理:一个请求用完 GPU 才处理下一个 → 利用率低
  • Continuous batching:把多个请求的 prefill/decode 阶段交织执行
  • 效果:GPU 利用率从 30% → 80%+,吞吐量提升 3-10x

3. KV Cache 复用

  • 系统 prompt ("You are a helpful assistant") 对所有用户相同
  • Prefix caching:预计算并缓存这部分的 KV cache
  • 节省 ~20% 推理计算量

4. 分层会话存储

热数据 (最近 24h) → Redis (内存,<1ms) 温数据 (最近 30d) → PostgreSQL (SSD,<10ms) 冷数据 (历史) → S3 (对象存储,按需加载)

5. 成本控制:模型分级路由

def route_model(user_tier, message_complexity):
    if user_tier == "free":
        return "gpt-3.5-turbo"   # $0.002/1K tokens
    elif is_simple_query(message_complexity):
        return "gpt-4o-mini"     # $0.015/1K tokens  
    else:
        return "gpt-4o"          # $0.03/1K tokens

为什么这样设计 / Why This Design

决策原因
Inference Router 独立模型升级不影响上游;可做 A/B 测试
Redis 存 session低延迟读取历史,避免每次查 DB
优先队列付费用户等待时间 < 2s;免费用户可接受 5-10s
Spot instancesLLM 推理是无状态的,被抢占只影响当前请求

别踩这个坑 / Common Mistakes

❌ 坑1:把整个对话历史每次都发给 LLM

  • 100 轮对话 × 200 tokens = 20K tokens/请求
  • Context window 满了就崩,成本也爆了
  • ✅ 正确:摘要旧轮次,只保留最近 10-20 轮

❌ 坑2:同步等待 LLM 完成再返回

  • GPT-4 生成 500 字需要 10-30 秒
  • 用户会以为卡死了
  • ✅ 正确:SSE 流式推送,第一个 token < 1s 到达

❌ 坑3:没有限流,被 prompt injection 攻击

  • 攻击者发超长 prompt,把所有 GPU 资源耗尽
  • ✅ 正确:输入 token 上限 + 每用户 RPM/TPM 限流

❌ 坑4:忽略 GPU 内存碎片

  • 不同长度请求的 KV cache 大小不同,导致显存碎片
  • ✅ 正确:vLLM 的 PagedAttention 像操作系统管理物理内存一样管理显存

📚 References


🧒 ELI5

想象你是个超忙的厨师,同时要给一万个客人做饭。每道菜(LLM 推理)需要 30 秒。

  • 分批下锅(Continuous Batching):不等一道菜全熟,多道菜轮流用炉灶
  • 菜单分级(Model Routing):简单的要沙拉用小厨师做,复杂的大餐才用大厨
  • 提前备料(KV Cache):每个菜都用的酱汁提前熬好,不用每次现做
  • 边做边上(SSE Streaming):前菜做好先端上来,不用等整套菜都好

这样 1 万个客人才不会都在等!

💻 算法 / Algorithms — Day 78

**#212 Word Search II** | 🔴 Hard | **Pattern: Tries (3/3)**

🔗 LeetCode #212 | 📹 NeetCode Solution


🧩 前缀树模式 (3/3) — 本系列最终章

Trie Block 总览: Day 74: #208 Implement Trie (Medium) ← 建模板 Day 76: #211 Add and Search Words (Medium) ← 加通配符 . Day 78: #212 Word Search II (Hard) ← TODAY: Trie + DFS

这是 Trie 系列的终极 Boss!把 Trie 嵌入 DFS 回溯,实现在矩阵里同时搜索多个单词。


真实类比 / Real-world Analogy

想象你有一张巨大的字母瓷砖地图,要在地图上找到所有词典里的单词。暴力方法:对每个单词跑一遍 DFS。聪明方法:把词典压进 Trie,DFS 时同时在 Trie 上走 —— 一旦没有前缀匹配,立刻剪枝,不用继续搜下去。

You have a grid of letter tiles. Find all words from a dictionary that can be formed by following adjacent cells. Brute force: run DFS for every word. Smart: load the dictionary into a Trie, walk Trie + grid simultaneously — prune immediately when no prefix matches.


题目 / Problem

board = [
  ['o','a','a','n'],
  ['e','t','a','e'],
  ['i','h','k','r'],
  ['i','f','l','v']
]
words = ["oath","pea","eat","rain"]
Output: ["eat","oath"]

模式映射 / Pattern Mapping

单独用 DFSTrie + DFS
对每个单词 DFS:O(W × M×N×4^L)所有单词共享一次 DFS:O(M×N×4^L)
无法早期剪枝只要 Trie 没有当前前缀,立刻停止
words=10000 时超时words=10000 依然可行

核心洞察:Trie 把"前缀共享"的优势带入了搜索过程。


Python 解法 + 逐步追踪 / Solution + Trace

class TrieNode:
    def __init__(self):
        self.children = {}
        self.word = None  # store full word at end node (not just True)

class Solution:
    def findWords(self, board: list[list[str]], words: list[str]) -> list[str]:
        # Step 1: Build Trie from word list
        root = TrieNode()
        for w in words:
            node = root
            for ch in w:
                if ch not in node.children:
                    node.children[ch] = TrieNode()
                node = node.children[ch]
            node.word = w  # mark end

        rows, cols = len(board), len(board[0])
        result = set()

        def dfs(r, c, node):
            ch = board[r][c]
            if ch not in node.children:
                return  # prune: no prefix match in Trie

            next_node = node.children[ch]

            if next_node.word:
                result.add(next_node.word)
                next_node.word = None  # avoid duplicates

            # Mark visited by overwriting (cheaper than a visited set)
            board[r][c] = '#'

            for dr, dc in [(0,1),(0,-1),(1,0),(-1,0)]:
                nr, nc = r + dr, c + dc
                if 0 <= nr < rows and 0 <= nc < cols and board[nr][nc] != '#':
                    dfs(nr, nc, next_node)

            board[r][c] = ch  # restore

            # Optimization: prune empty Trie nodes (key insight!)
            if not next_node.children:
                del node.children[ch]

        for r in range(rows):
            for c in range(cols):
                dfs(r, c, root)

        return list(result)

追踪示例 / Trace:

从 (1,2)='a' 开始,找 "eat": root → 'e'? 不在 board[1][2]='a' 的邻居里... 从 (1,1)='t' 开始,找 "eat": root 里有 'e'? (1,0)='e' 是邻居 → dfs(1,0,'e') → Trie node 'e' → 邻居 (0,0)='o'? Trie 下一步是 'a', 不匹配 → 邻居 (1,1)='t'? Trie 下一步是 'a', 不匹配 → 邻居 (2,0)='i'? 不匹配 从 (0,1)='a' 开始: root 里有 'e'? (1,1)='t' 邻居... 找到 e→a→t 路径! → found "eat" ✓

复杂度 / Complexity:

  • Time: O(M×N×4^L) where L = max word length (Trie 剪枝大幅减少实际路径)
  • Space: O(N×L) for Trie — N words × avg length L

关键优化 / Key Optimizations

1. 存完整单词,不存布尔值

node.word = w  # better than node.is_end = True

找到时直接加入结果,不需要重建单词。

2. 原地标记已访问

board[r][c] = '#'  # overwrite, not a separate visited set
...
board[r][c] = ch   # restore after DFS

省去 O(M×N) 的 visited 数组。

3. 修剪空 Trie 节点(最关键优化!)

if not next_node.children:
    del node.children[ch]

找到单词后,从 Trie 里删除叶节点。随着更多单词被找到,Trie 越来越小,后续 DFS 剪枝更激进。


举一反三 / Pattern Connections

题目和 Word Search II 的关系
#208 Implement TrieWord Search II 的核心数据结构
#211 Add and Search Words同样 Trie + DFS,但 '.' 通配符换成了矩阵的4方向
#79 Word Search IWord Search II 的简化版:单词 → 多单词
Boggle GameWord Search II 的现实应用

📚 References


🧒 ELI5

想象玩一个字母找词游戏:一张字母格子地图,找出所有词典里能走出来的单词。

笨方法:拿着词典,每个词在地图上走一遍。10000 个词 = 走 10000 遍。

聪明方法:先把词典变成一棵"前缀树"(Trie)。比如 "eat", "east", "easy" 都从 'e'→'a' 开始,在树上共享这两步。

然后在地图上 DFS,同时在 Trie 上走。一走进地图某格,就问 Trie:"这条路有单词吗?" 没有前缀匹配→直接放弃,不用继续往下走。

就像迷宫里,你走到一扇门,门上写"此路绝对没有出口",你就不用进去了!

🗣️ 软技能 / Soft Skills — Day 78

Question: Describe how you've contributed to hiring and growing a team

Category: Leadership | Level: Staff


为什么这道题很重要 / Why This Matters

Staff 工程师的影响力不只来自个人代码,而是来自把团队规模乘以。招人和成长团队是最高 ROI 的投资:一个出色的招聘决策,可以带来 3-5 年的复利回报。面试官问这题,是想确认你从个人贡献者转型到团队构建者了。

A Staff engineer's leverage isn't just their own code — it's multiplying the team. Great hiring decisions compound for 3-5 years. Interviewers ask this to confirm you've shifted from individual contributor to team builder.


STAR 拆解 / STAR Breakdown

Situation(情境)

"我在 X 公司做 Staff 工程师时,团队需要从 4 人扩张到 10 人来支持新产品线。我负责主导技术招聘流程的设计和执行。"
"At X, my team needed to grow from 4 to 10 engineers to support a new product line. I owned designing and running the technical hiring process."

Task(任务)

"我的目标是在 6 个月内招到 6 名高质量工程师,同时维持团队生产力不中断,并确保招进来的人能够在入职后 3 个月内独立上手。"
"My goal: hire 6 quality engineers in 6 months, maintain team output, and ensure new hires were independent contributors within 3 months."

Action(行动)— 具体化!

  1. 定义招聘标准 — 和 EM 一起写了一个"工程师成功画像",明确区分 Must-have vs Nice-to-have,避免面试官各凭直觉打分
  2. 设计面试流程 — 把原来 5 轮随机面试改成结构化 4 轮:系统设计 / 算法 / 行为 / 文化 fit。每轮有评分 rubric
  3. 扩大候选人管道 — 在 2 个行业会议上做了技术分享,直接带来 12 个候选人推荐
  4. 优化候选人体验 — 面试 → offer 时间从 3 周压到 8 天(发现延迟主要来自面试官日程协调)
  5. 新人导师制度 — 给每个新人配了一个 buddy + 写了 30/60/90 天 onboarding checklist

Result(结果)

"6 个月招了 7 人(超额完成),面试到 offer 接受率从 40% → 68%,新人平均 2.5 个月独立上手(vs 行业平均 4-5 个月)。"

❌ 糟糕答案 vs ✅ 优秀答案

❌ 糟糕:

"我参与了很多面试,帮助面试了很多候选人,也帮助 onboard 新同事。"

问题:主语是"很多",没有数字,没有主导权,像打酱油的。

✅ 优秀:

"我发现我们的面试流程缺乏结构,导致面试官评分不一致。我主导重新设计了评分 rubric,面试结果一致性大幅提升,我们对同一候选人的分歧从平均 2.3 分降到 0.7 分(5 分制),offer 接受率从 40% 提到 68%。"
*好在:有问题识别 → 具体行动 → 量化结果。*

Senior/Staff 级别的进阶思路 / Senior/Staff Angle

面试官对 Staff 级别候选人期望更高:

  • 系统化,不只是个案 — 你有没有建立可复用的流程,而不是每次都手工操作?
  • 影响力超越自己团队 — 你的招聘实践有没有被其他团队采纳?
  • 长期视角 — 你有没有想过 2-3 年后团队的技能组合,而不只是当前 headcount?
Junior: "我做了 X 次面试"
Senior: "我设计了面试流程,效率提升了 Y%"
Staff:  "我建立了跨团队可复用的招聘框架,并 mentor 了 3 个面试官"

关键 Takeaways / Key Takeaways

  1. 定义成功画像 — 在招聘前对齐"什么样的人算好",比招完后才发现不合适要便宜得多
  2. 流程胜过直觉 — 结构化面试的预测准确率比非结构化高 2-3 倍(心理学研究结论)
  3. 候选人体验就是品牌 — 被拒的候选人也会谈论公司,快速回复和礼貌对待是最便宜的 employer branding
  4. onboarding 是招聘的延伸 — 入职 90 天的体验决定了这个人能否发挥 100% 的价值

📚 References


🧒 ELI5

组建团队就像打篮球比赛:

  • 你不能只想着今天赢,得想着整个赛季(长期视角)
  • 招错人就像换了一个不适合战术的球员,还没法退换货
  • 好的 onboarding 就是训练营 —— 让新球员快速融入团队打法
  • 面试流程的 rubric 就是裁判规则 —— 没有规则,每个教练都说"我感觉这球员好",结果乱成一锅粥

🤖 AI — Day 78

Topic: The Future — AGI Debates, Emerging Architectures

**Category:** Research | Mode: CONCEPT | Phase: Expert

核心问题:AGI 什么时候到来?/ The Core Question: When Does AGI Arrive?

AGI (Artificial General Intelligence,通用人工智能) = 能在任意认知任务上达到人类水平的 AI。现在的 LLM 很强,但到底离 AGI 有多远?这是 AI 领域最大的争论。

AGI = AI that matches or exceeds human performance on any cognitive task. Current LLMs are impressive — but how far are we, really?


AGI 定义之争 / The Definition War

AGI 没有统一定义,不同人说的 AGI 完全不同:

谁怎么定义 AGI
OpenAI (官方)"能完成大多数经济价值的任务"
Yann LeCun (Meta)"真正理解物理世界,可靠推理" — 认为 LLM 永远达不到
Demis Hassabis (Google DeepMind)"科学发现能力超越人类"
Eliezer Yudkowsky"能自我改进、自我复制的 AI" — 极度担忧

争论本质:是"能用工具的聪明助手"就算 AGI,还是"真正拥有理解力"才算?


当前架构的局限 / Current Architecture Limits

Transformer 很强,但有几个根本性限制:

1. 二次方复杂度问题 (Quadratic Attention)

Context length = N tokens Attention 计算量 = O(N²) N = 100K tokens → 10B 次计算 N = 1M tokens → 1T 次计算 (实际不可行)

2. 无真正"状态记忆"

Transformer 每次推理都是无状态的。"记忆"只是把历史全塞进 context window,本质上是昂贵的查找,不是真正的记忆。

3. 推理 ≠ 理解

LLM 在 benchmark 上强,但遇到分布外问题(out-of-distribution)会犯低级错误。这是 "stochastic parrot" 批评的核心。


新兴架构 / Emerging Architectures

🔷 State Space Models (SSM) — Mamba

Transformer: O(N²) attention
Mamba:       O(N) linear recurrence

关键思路:
  用选择性状态更新 (selective state updates) 替代全量 attention
  每个 token 只更新相关的隐藏状态,忽略无关信息

优势:长序列性能线性增长,推理内存大幅减少

现实:在某些任务上与 Transformer 持平,但多模态和代码任务仍落后

🔷 混合专家模型 (Mixture of Experts, MoE) — 已投入生产

# 概念示例
class MoE(nn.Module):
    def forward(self, x):
        # Router: 每个 token 只激活 top-K 个专家 (e.g., k=2/8)
        expert_weights = self.router(x)  # sparse selection
        outputs = [expert(x) for expert in self.experts]
        return sum(w * o for w, o in zip(expert_weights, outputs))

GPT-4 据报道是 MoE 架构(8 个专家,每次激活 2 个)。总参数量大,但每次推理只用 1/4 的参数 → 参数量大 + 计算量小。

🔷 Test-Time Compute Scaling — 最新趋势

与其在训练时用更多算力(更大模型),不如在推理时动态增加思考时间:

简单问题: 直接回答 (1x compute)
难题:     CoT + Self-verify + Multiple attempts (10x compute)
超难题:   MCTS 搜索 + Reflection loops (100x compute)

这就是 OpenAI o1/o3、DeepSeek-R1 背后的思路:推理时 scaling,不只是训练时 scaling。


AGI 时间线的不同派系 / AGI Timeline Camps

乐观派 (OpenAI, Anthropic 部分人):
  "2-5 年内出现初级 AGI"
  依据:scaling law 还在起效,o1/o3 推理能力跃升

悲观派 (部分学术界):
  "当前架构有根本性限制,需要新范式"
  依据:LLM 缺乏 grounding, 世界模型, 持久记忆

中立派 (大多数研究者):
  "定义不清楚,无法讨论时间线"
  依据:每次 AGI 被"快要实现"时,定义就往后挪

Yann LeCun 独立派:
  "Transformer 永远达不到真正 AGI"
  主张:世界模型 + 能量模型 (Energy-Based Models) 才是出路
  他的 JEPA 架构是这个方向的尝试

你应该关注什么 / What You Should Watch

作为工程师,这些是近期最值得关注的:

  1. 推理时 scaling — o3/DeepSeek-R1 类模型在复杂任务上的进展
  2. 多模态 + 具身 AI — 能感知和操控物理世界的 AI(机器人方向)
  3. 内存与持久学习 — 超越 context window 的长期记忆机制
  4. 能效提升 — 同等能力用更少算力(量化、蒸馏、稀疏激活)

简单 Python 代码演示 / Python Demo

演示 Test-Time Compute 的核心思路:多次尝试 + 自我验证:

import anthropic  # pip install anthropic

def solve_with_test_time_compute(problem: str, n_attempts: int = 3) -> str:
    """
    Simple test-time compute: try N times, verify each, return best
    In practice: o1 uses MCTS + internal reward model, much more complex
    """
    client = anthropic.Anthropic()
    attempts = []

    for i in range(n_attempts):
        # Each attempt uses CoT
        response = client.messages.create(
            model="claude-opus-4-5",
            max_tokens=1024,
            messages=[{
                "role": "user",
                "content": f"Think step by step: {problem}"
            }]
        )
        attempts.append(response.content[0].text)

    # Self-verification: ask model to pick best answer
    verify_prompt = f"These are {n_attempts} solutions. Which is most likely correct?\n"
    for i, a in enumerate(attempts):
        verify_prompt += f"\nSolution {i+1}: {a[:200]}..."

    verdict = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=256,
        messages=[{"role": "user", "content": verify_prompt}]
    )
    return verdict.content[0].text

📚 References


🧒 ELI5

AGI 的争论就像争论"什么时候能造出会真正思考的机器"。

现在的 AI(LLM)就像一个读了所有书的人,记性超好,能写作文,但:

  • 没有真正理解物理世界(不知道"把球推下去,球会滚")
  • 没有长期记忆(每次对话都是第一次见面)
  • 遇到没见过的题目容易乱答

新架构(Mamba、MoE、Test-Time Scaling)就像给这个人加上了:

  • 更高效的大脑(Mamba:不用每次把所有记忆翻一遍)
  • 专科专家团队(MoE:遇到数学题找数学专家,遇到写作题找写作专家)
  • 多想一会儿的能力(Test-Time Compute:难题多思考几步再回答)

AGI 什么时候来?聪明人们争论了几十年,结论只有一个:定义不同,答案不同。 🤷

Attention Heatmap

When the model processes it, it attends most strongly to animal.

Theanimaldidntcrossthestreetbecauseitwastootired
it →