🔄 复习日 / Review Day — Day 80
📊 NeetCode: 64/150 · SysDesign: 63/40 · Behavioral: 63/40 · Frontend: 37/50 · AI: 31/30
🔥 3-day streak!
今天是复习日!回顾过去4天的内容 (Days 76–79)。
涵盖主题 / Topics covered:
- 🏗️ System Design: AI Chatbot Platform (ChatGPT-scale)
- 💻 Algorithms: Trie (Add/Search Words + Wildcard), Word Search II, Kth Largest in Stream (Heap)
- 🐍 Python Craft: Context Managers, Connection Pooling, Retry with Backoff
- 🤖 AI: AGI Debates, Emerging Architectures, AI News
📝 Quick Quiz — 3 Mini-Reviews
Q1: [🏗️ System Design] — AI Chatbot Platform
Question: In a ChatGPT-scale AI chatbot, why do you need a streaming gateway layer separate from the LLM inference backend — and what problem does it solve for clients?
<details><summary>显示答案 / Show Answer</summary>
LLM inference is slow to start but generates tokens incrementally. Without streaming, clients would wait 10–30s for the full response, causing timeouts and terrible UX.
The streaming gateway (e.g., nginx + SSE or WebSocket proxy) solves this by:
- Forwarding tokens as they're generated — clients start rendering within milliseconds
- Buffering backpressure — if the client is slow (mobile, weak connection), the gateway queues tokens without stalling the GPU inference worker
- Session affinity — routes a user's follow-up message to the same conversation state (message history, system prompt)
Key tradeoff: Stateless HTTP is easier to scale, but SSE/WebSocket connections are stateful. You typically pin a user session to a gateway pod and rely on horizontal scaling at the inference tier.
</details>
Q2: [💻 Algorithms] — Word Search II (Trie + Backtracking)
Question: Word Search II uses a Trie instead of a Set for the word list. In one sentence, explain why the Trie is strictly better than checking if word_so_far in word_set at each DFS step.
<details><summary>显示答案 / Show Answer</summary>
A Trie lets you prune entire DFS branches early: if no word in the list starts with the current prefix, you immediately stop exploring that direction — with a plain set, you'd have no way to know this and would explore all paths regardless.
Concrete example: Grid is 5×5, words = ["abc", "abd"]. With a Trie, once you're at a cell where the current path is "xyz...", you check trie.root.children and find no "x" node → prune immediately. With a set, you'd continue DFS forming "xyzqr..." and only fail at the full word check.
Template reminder:
def findWords(board, words):
trie = Trie()
for w in words: trie.insert(w)
def dfs(node, r, c, path):
if node.word: # found a complete word
res.add(path)
node.word = False # avoid duplicates
tmp, board[r][c] = board[r][c], '#' # mark visited
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] in node.children:
dfs(node.children[board[nr][nc]], nr, nc, path+board[nr][nc])
board[r][c] = tmp # restore
...
Critical optimization: Delete matched words from the Trie (node.word = False) to avoid re-adding duplicates and to enable Trie pruning after a word is found.
</details>
Q3: [🐍 Python Craft] — Retry with Backoff + Connection Pooling
Question: You're building a service that calls an external API. You have both connection pooling and retry with exponential backoff available. A request fails with a ConnectionResetError. In what order should these two mechanisms handle it, and why?
<details><summary>显示答案 / Show Answer</summary>
Order: retry logic wraps the pool, not vice versa.
- Connection pool handles acquiring/releasing connections efficiently (reuse TCP connections, manage pool size). When a
ConnectionResetErrorhappens, the pool should discard that broken connection (not return it to the pool). - Retry with backoff then kicks in at the call-site level: it re-attempts the full operation (which will now request a fresh connection from the pool).
# Correct layering
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=10))
def call_external_api():
with pool.get_connection() as conn: # pool is INSIDE the retry
return conn.request("GET", "/endpoint")
Why not the reverse? If retry logic were inside the pool's connection acquisition, you'd retry getting a pooled connection — which doesn't help if the remote server is actually down. You need to retry the business operation, not just the connection handshake.
Key tenacity patterns:
stop_after_attempt(3)— max retrieswait_exponential(multiplier=1, min=1, max=10)— 1s, 2s, 4s, 8s, 10s...retry=retry_if_exception_type(ConnectionError)— only retry transient errors, NOTValueErroror auth failures
</details>
💡 复习巩固记忆,螺旋式上升。
📅 明天继续新内容!