Skip to content

AI 基础与 Agent 原理

说明

共 15 题,难度 ⭐ ~ ⭐⭐⭐,覆盖 LLM 原理、Prompt Engineering、Agent 架构、Function Calling、幻觉与安全等 AI 基础知识,面向前端工程师理解和使用 AI 技术。

1. 什么是大语言模型(LLM)?它是怎么"理解"和"生成"文本的? ⭐⭐

用通俗的方式解释 LLM 的工作原理。

考察点:LLM 基础

LLM 的本质

大语言模型 = 一个超大的"下一个词预测器"

训练过程:
  互联网文本(万亿 Token)→ 学习语言模式 → 模型参数(数十亿~万亿)

推理过程:
  输入: "今天天气"
  模型: 预测下一个 Token 的概率分布
    → "很" (30%) | "不" (20%) | "真" (15%) | ...
  选择: "很"
  继续: "今天天气很" → "好" (40%) | "热" (25%) | ...
  选择: "好"
  最终: "今天天气很好"

核心: 不是"理解"语义,而是基于统计规律预测下一个 Token
  → 但当模型足够大、训练数据足够多时,涌现出了"类似理解"的能力

关键概念

Token(词元):
  LLM 不以"字"或"词"为单位,而是 Token
  "Hello World" → ["Hello", " World"]  (2 tokens)
  "你好世界" → ["你好", "世界"]  (2-4 tokens,取决于分词器)
  GPT-4: 1 Token ≈ 0.75 个英文单词 ≈ 0.5 个中文字

上下文窗口 (Context Window):
  模型一次能处理的最大 Token 数
  GPT-4: 128K tokens
  Claude: 200K tokens
  → 超过窗口的内容会被截断

参数量:
  GPT-3: 175B (1750 亿)
  GPT-4: 推测 1.8T (1.8 万亿, MoE 架构)
  Llama 3: 8B / 70B / 405B
  → 参数越多 → 能力越强 → 计算成本越高

从预训练到可用

① 预训练 (Pre-training):
   大量文本 → 无监督学习 → 学会语言规律
   → 此时模型只会"补全"文本,不会对话

② 监督微调 (SFT - Supervised Fine-Tuning):
   人工编写 (指令, 回答) 对 → 教模型遵循指令
   → 模型学会了"问答"格式

③ RLHF (基于人类反馈的强化学习):
   人类对模型回答打分 → 训练奖励模型
   → 用奖励模型引导 LLM 输出更好的回答
   → 模型变得更有帮助、更安全、更诚实

④ 对齐 (Alignment):
   确保模型行为符合人类意图和价值观
   → 不输出有害内容
   → 承认不知道而非编造

追问延伸

  • MoE(Mixture of Experts)架构是什么?为什么 GPT-4 用 MoE?
  • 涌现能力(Emergent Abilities)是什么?为什么模型到了一定规模突然变强?
  • 开源模型(Llama / Qwen / DeepSeek)和闭源模型(GPT / Claude)怎么选?

2. Transformer 架构的核心是什么?自注意力机制怎么理解? ⭐⭐⭐

理解现代 AI 模型的基础架构。

考察点:Transformer、Attention

为什么需要 Transformer

在 Transformer 之前:
  RNN/LSTM → 按顺序处理文本(一个词一个词)
  → 长距离依赖困难(句首和句尾的关系难以捕捉)
  → 无法并行计算 → 训练慢

Transformer (2017, "Attention is All You Need"):
  → 并行处理所有 Token
  → 自注意力机制捕捉任意距离的关系
  → 训练速度大幅提升 → 可以用更大的数据集和模型

自注意力机制(Self-Attention)

类比: 阅读理解

  "小明把苹果给了小红,她很开心"

  处理"她"这个词时:
  → 注意力机制会关注"小红"(高权重)
  → 较少关注"苹果"(低权重)
  → 从而理解"她 = 小红"

数学过程(简化):
  每个 Token 生成三个向量:
    Q (Query): "我在找什么?"
    K (Key):   "我是什么?"
    V (Value): "我的信息是什么?"

  注意力分数 = softmax(Q × K^T / √d) × V

  "她" 的 Q 和 "小红" 的 K 的点积最大
  → "小红" 对 "她" 的注意力权重最高
  → "她" 的表示融合了"小红"的信息

Transformer 结构

Encoder-Decoder (原始 Transformer, 用于翻译):
  Encoder: 理解输入 → BERT 使用
  Decoder: 生成输出 → GPT 使用

GPT 系列 (Decoder-Only):
  只有 Decoder → 自回归生成(逐 Token 预测)
  → 适合文本生成

  输入 Token → Embedding → 位置编码

  [ Multi-Head Self-Attention ]  × N 层

  [ Feed-Forward Network ]

  输出概率分布 → 选择下一个 Token

Multi-Head Attention:
  多个"注意力头"并行运行
  → 每个头关注不同的语义关系
  → 头 1 关注语法关系、头 2 关注共指关系、头 3 关注位置关系…
  → 最终拼接在一起

对前端开发者的意义

了解 Transformer 有助于:
  ① 理解 Token 计费(为什么长文本更贵)
  ② 理解上下文窗口限制(为什么需要 RAG)
  ③ 理解流式输出(逐 Token 生成)
  ④ 优化 Prompt(放在末尾的信息注意力更高)
  ⑤ 理解 KV Cache(为什么首 Token 延迟高、后续 Token 快)

追问延伸

  • KV Cache 是什么?为什么能加速推理?
  • 位置编码(Positional Encoding)解决什么问题?RoPE 是什么?
  • Flash Attention 怎么优化注意力计算?

3. Token 和分词器(Tokenizer)是什么?为什么前端需要关注? ⭐⭐

理解 Token 对前端 AI 应用的实际影响。

考察点:Token、成本

什么是分词器

分词器 = 将文本转换为 Token ID 序列的工具

三种分词策略:
  ① 字符级 (Character-level):
     "hello" → ['h', 'e', 'l', 'l', 'o']  (5 tokens)
     → Token 数太多,效率低

  ② 词级 (Word-level):
     "hello world" → ['hello', 'world']  (2 tokens)
     → 词表太大,未知词处理差

  ③ 子词级 (Subword) ← 主流:
     BPE (Byte-Pair Encoding) — GPT 系列使用
     "unhappiness" → ['un', 'happi', 'ness']  (3 tokens)
     → 平衡词表大小和 Token 数量

不同模型的分词差异

同一段文本,不同模型的 Token 数不同:

  "React Server Components 是 React 18 的新特性"

  GPT-4 (cl100k_base):  ~15 tokens
  Claude (claude):       ~12 tokens
  Llama 3:              ~18 tokens

中文分词特点:
  "前端开发" → GPT-4 约 2-3 tokens
  → 中文 token 效率通常低于英文
  → 同等内容,中文消耗的 token 数更多 → 成本更高

前端为什么需要关注 Token

① 成本计算
  GPT-4o: 输入 $2.5/1M tokens, 输出 $10/1M tokens
  一次对话 ~2000 tokens → $0.005 → 每天 1000 次 = $5
  → 前端需要控制每次请求的 token 数

② 上下文窗口管理
  系统 Prompt + 历史消息 + 用户输入 = 总 Token 数
  如果超过上下文窗口 → 早期消息被截断 → 模型"忘记"了前面的对话
  → 前端需要实现对话历史裁剪策略

③ 流式输出体验
  Token 逐个生成 → 前端接收 SSE 流 → 逐字显示
  → 首 Token 延迟(TTFT)影响用户体感
  → 前端需要展示打字动画 / 骨架屏

④ 输入限制
  用户输入的文本需要预估 Token 数
  → 在发送前提示用户"文本过长"
  → 或自动截断/总结

Token 计算工具

typescript
// 前端预估 Token 数(粗略)
function estimateTokens(text: string): number {
  const chineseChars = (text.match(/[\u4e00-\u9fff]/g) || []).length
  const otherChars = text.length - chineseChars
  return Math.ceil(chineseChars * 1.5 + otherChars * 0.25)
}

// 精确计算需要使用对应模型的分词器
// tiktoken (OpenAI): npm install tiktoken
import { encoding_for_model } from 'tiktoken'
const enc = encoding_for_model('gpt-4o')
const tokens = enc.encode('Hello, 你好世界')
console.log(tokens.length) // 精确的 token 数
enc.free()

追问延伸

  • tiktoken 在前端环境怎么用?(WASM 版本)
  • 如何实现对话历史的滑动窗口策略?
  • Token 数和生成速度的关系?(输出越多越慢,因为每个 token 都依赖前面所有 token)

4. Prompt Engineering 的核心技巧?如何写出高质量的 Prompt? ⭐⭐⭐

掌握提示词工程的实用方法。

考察点:Prompt Engineering

Prompt 的基本结构

一个好的 Prompt 通常包含:

┌─────────────────────────────────┐
│  角色设定 (System Prompt)        │  你是一个资深前端工程师
├─────────────────────────────────┤
│  任务描述                        │  请帮我 Review 这段代码
├─────────────────────────────────┤
│  上下文信息                      │  这是一个 React 组件,使用 TypeScript
├─────────────────────────────────┤
│  输入数据                        │  [代码]
├─────────────────────────────────┤
│  输出格式                        │  请用 Markdown 列表输出问题
├─────────────────────────────────┤
│  约束条件                        │  只关注性能问题,忽略样式
└─────────────────────────────────┘

核心技巧

① 角色设定 (Role Prompting)
  ❌ "帮我写代码"
  ✅ "你是一个有 10 年经验的 React 高级工程师,精通 TypeScript 和性能优化"

② 少样本学习 (Few-Shot)
  给模型几个示例,让它模仿格式:

  "将以下错误信息转换为用户友好的提示:
   输入: 'ECONNREFUSED'
   输出: '服务器连接失败,请检查网络后重试'

   输入: '401 Unauthorized'
   输出: '登录已过期,请重新登录'

   输入: 'ETIMEDOUT'
   输出: "

③ 思维链 (Chain-of-Thought, CoT)
  让模型分步推理:

  ❌ "计算这个表达式的结果"
  ✅ "请一步一步地计算这个表达式,展示每一步的推理过程"

  更进一步 — Zero-Shot CoT:
  "Let's think step by step."
  → 简单一句话就能显著提升推理能力

④ 结构化输出
  要求模型按固定格式输出:

  "请用 JSON 格式输出:
   {
     'severity': 'error' | 'warning' | 'info',
     'message': '问题描述',
     'suggestion': '修复建议',
     'line': 行号
   }"

⑤ 限制与约束
  "回答字数不超过 200 字"
  "只使用 React 和 TypeScript,不要使用 class 组件"
  "如果不确定,请说'我不确定'而不是猜测"

高级技巧

⑥ Self-Consistency(自一致性)
  同一个问题让模型回答多次 → 取多数一致的答案
  → 提高复杂推理的准确率

⑦ ReAct (Reason + Act)
  让模型交替进行推理和行动:
  Thought: 我需要查询用户的订单记录
  Action: 调用 getOrders(userId)
  Observation: 返回了 3 条订单
  Thought: 最近一条订单是退货状态...

⑧ Prompt Template(模板化)
  将 Prompt 模板化,动态注入变量:

  const prompt = `
    你是 ${role}。
    请分析以下 ${language} 代码:

    \`\`\`${language}
    ${code}
    \`\`\`

    重点关注: ${focusAreas.join('、')}
    输出格式: ${outputFormat}
  `

System Prompt 设计模式

typescript
const SYSTEM_PROMPT = `你是 DevCraft AI 助手,专注于前端开发。

## 核心能力
- 代码审查和优化建议
- 技术方案设计
- Bug 排查和修复

## 回答规范
1. 优先使用 TypeScript
2. 遵循 React 最佳实践
3. 给出代码示例时注明文件路径
4. 复杂问题分步骤回答

## 限制
- 不回答与编程无关的问题
- 不确定时明确说明,不编造
- 不输出敏感信息(密码、密钥等)

## 输出格式
使用 Markdown,代码块标注语言类型。`

追问延伸

  • Prompt Injection(注入攻击)是什么?如何防御?
  • System Prompt 和 User Prompt 的优先级关系?
  • 如何评估 Prompt 的效果?A/B 测试 Prompt?

5. 模型的 Temperature / Top-P / Max Tokens 等参数是什么? ⭐⭐

理解模型推理参数的含义和调优。

考察点:模型参数

Temperature(温度)

控制输出的随机性:

  temperature = 0:
    → 每次都选概率最高的 Token → 输出最确定/最保守
    → 适合: 代码生成、数据提取、事实问答

  temperature = 0.7 (常用默认值):
    → 适度随机 → 平衡创造性和准确性
    → 适合: 对话、写作

  temperature = 1.5:
    → 高随机性 → 更有创意但可能胡说
    → 适合: 头脑风暴、创意写作

原理:
  预测概率: "好"(40%) "棒"(30%) "冷"(5%) ...
  temp=0: 直接选"好"
  temp=0.7: 大概率选"好"或"棒",偶尔选其他
  temp=1.5: 各种词都有机会被选中

Top-P(核采样)

另一种控制随机性的方式:

  top_p = 0.1:
    → 只从累积概率前 10% 的 Token 中采样
    → 非常保守

  top_p = 0.9:
    → 从累积概率前 90% 的 Token 中采样
    → 适度多样

  例: "今天天气很___"
    "好"(40%) "棒"(30%) "热"(15%) "冷"(10%) "奇"(5%)

    top_p = 0.7:
      → "好"(40%) + "棒"(30%) = 70% ≥ 0.7
      → 只从 "好" 和 "棒" 中选

通常 temperature 和 top_p 选一个调,不建议同时调

其他关键参数

max_tokens:
  模型单次生成的最大 Token 数
  → 设置太小 → 回答被截断
  → 设置太大 → 浪费成本
  → 建议: 根据场景设置(对话 500-1000,长文 2000-4000)

stop:
  遇到特定字符串时停止生成
  → stop: ["\n\n", "---"]
  → 控制输出结构

frequency_penalty (0~2):
  惩罚已出现的 Token → 减少重复
  → 0: 不惩罚
  → 1: 中等惩罚
  → 适合: 避免模型陷入重复循环

presence_penalty (0~2):
  惩罚已出现的主题 → 鼓励谈论新内容
  → 适合: 发散性对话、创意写作

seed:
  固定随机种子 → 相同输入得到(接近)相同输出
  → 适合: 可复现的测试和评估

不同场景的推荐参数

场景temperaturetop_pmax_tokens
代码生成0 ~ 0.20.12000
代码审查0 ~ 0.30.21000
对话聊天0.70.9500
创意写作1.0 ~ 1.50.952000
数据提取00.1500
翻译0.30.32000

追问延伸

  • logprobs 参数是什么?怎么用它做置信度分析?
  • 如何通过参数控制 JSON 输出的格式?(response_format: { type: 'json_object' }
  • Streaming 模式下参数有什么影响?(不影响生成质量,只影响传输方式)

6. 什么是 AI Agent?和普通 LLM 调用有什么区别? ⭐⭐⭐

理解 Agent 的核心概念和架构。

考察点:Agent 架构

Agent vs 普通 LLM 调用

普通 LLM 调用:
  用户问 → LLM 答 → 结束
  单轮对话,无法使用工具,无法记忆

AI Agent:
  用户问 → Agent 思考 → 使用工具 → 观察结果 → 继续思考 → ... → 最终回答
  多步推理,能调用工具,有记忆

类比:
  普通 LLM = 一个很有知识的人(只能用脑子想)
  AI Agent = 一个很有知识的人 + 电脑 + 搜索引擎 + 计算器 + ...(能使用工具)

Agent 的核心组件

┌──────────────────────────────────────────┐
│                AI Agent                   │
├──────────────────────────────────────────┤
│                                          │
│  ┌────────────┐  ┌────────────────────┐  │
│  │  LLM 大脑   │  │  记忆 (Memory)     │  │
│  │  推理/决策   │  │  短期: 对话历史     │  │
│  │            │  │  长期: 向量数据库   │  │
│  └─────┬──────┘  └────────────────────┘  │
│        │                                  │
│  ┌─────┴──────────────────────────────┐  │
│  │        工具 (Tools)                 │  │
│  │  搜索  | 代码执行 | API调用 | 文件   │  │
│  └────────────────────────────────────┘  │
│                                          │
│  ┌────────────────────────────────────┐  │
│  │     规划 (Planning)                 │  │
│  │  任务分解 → 步骤执行 → 结果综合     │  │
│  └────────────────────────────────────┘  │
└──────────────────────────────────────────┘

Agent 执行流程

用户: "帮我查看今天的天气,并推荐合适的穿搭"

Agent 思考链:
  ① Thought: 我需要先获取今天的天气信息
  ② Action: 调用 weather_api(location="北京")
  ③ Observation: 温度 25°C,晴,微风
  ④ Thought: 天气温暖,我可以推荐轻薄穿搭了
  ⑤ Action: 生成穿搭建议
  ⑥ Output: "今天北京 25°C 晴天,建议穿轻薄T恤+薄外套..."

主流 Agent 框架

框架开发者特点适用场景
LangChainLangChain全功能链式调用复杂 Agent 应用
LangGraphLangChain图结构工作流多步骤有状态 Agent
Vercel AI SDKVercel前端友好、流式 UI前端 AI 应用
CrewAICrewAI多 Agent 协作团队式任务处理
AutoGenMicrosoft多 Agent 对话研究和实验
DifyDify.AI低代码快速原型

追问延伸

  • 单 Agent 和多 Agent 系统有什么区别?什么时候需要多 Agent?
  • Agent 的"幻觉"怎么办?如何让 Agent 承认"不知道"?
  • Agent 的可观测性(Observability)怎么做?(LangSmith / LangFuse)

7. ReAct 模式是什么?和 CoT 有什么区别? ⭐⭐

理解 Agent 的核心推理模式。

考察点:推理模式

Chain-of-Thought (CoT)

CoT = 思维链:让模型分步推理

例: "一个商店有 5 个苹果,卖了 3 个,又进了 2 个,还剩几个?"

不用 CoT:
  → "4 个"(直接回答,可能出错)

用 CoT:
  → 步骤 1: 初始有 5 个苹果
  → 步骤 2: 卖了 3 个,剩下 5-3=2 个
  → 步骤 3: 又进了 2 个,现在有 2+2=4 个
  → 答案: 4 个 ✅

CoT 的局限:
  只能用"脑子想" → 无法获取实时信息 → 无法执行操作

ReAct = Reasoning + Acting

ReAct = 交替进行推理(Thought)和行动(Action)

Thought → Action → Observation → Thought → Action → ... → Answer

例: "GPT-4 是什么时候发布的?发布后 OpenAI 的股价涨了多少?"

ReAct 过程:
  Thought: 我需要查找 GPT-4 的发布时间
  Action: search("GPT-4 release date")
  Observation: GPT-4 于 2023年3月14日发布

  Thought: 现在我需要查找 OpenAI 发布 GPT-4 后的股价变化
  Action: search("OpenAI stock price after GPT-4")
  Observation: OpenAI 是非上市公司,没有公开股价

  Thought: OpenAI 没有股价。我应该诚实告知用户
  Answer: GPT-4 于 2023年3月14日发布。但 OpenAI 是非上市公司,
          没有公开的股票价格。如果您想了解微软(OpenAI 的主要投资方)
          的股价变化,我可以帮您查找。

CoT vs ReAct

维度CoTReAct
推理✅ 分步推理✅ 分步推理
行动❌ 无法调用工具✅ 可以调用工具
外部信息❌ 只用训练知识✅ 实时获取信息
准确性🟡 依赖训练数据✅ 可验证事实
适用场景数学推理、逻辑分析Agent、问答、任务执行

代码实现(简化)

typescript
async function reactLoop(query: string, tools: Tool[], llm: LLM) {
  const messages = [
    { role: 'system', content: REACT_SYSTEM_PROMPT },
    { role: 'user', content: query },
  ]

  for (let i = 0; i < MAX_ITERATIONS; i++) {
    const response = await llm.chat(messages)

    if (response.includes('Final Answer:')) {
      return extractFinalAnswer(response)
    }

    const { thought, action, actionInput } = parseReActResponse(response)

    const tool = tools.find(t => t.name === action)
    const observation = await tool.execute(actionInput)

    messages.push(
      { role: 'assistant', content: response },
      { role: 'user', content: `Observation: ${observation}` }
    )
  }

  return 'Agent 达到最大迭代次数,无法完成任务'
}

追问延伸

  • Plan-and-Execute 模式和 ReAct 有什么区别?(先规划所有步骤 vs 边想边做)
  • Reflexion 模式是什么?(Agent 反思自己的错误并改进)
  • 多步推理中如何处理工具调用失败?

8. 什么是 Function Calling?前端如何使用? ⭐⭐⭐

掌握 LLM 调用外部函数的机制。

考察点:Function Calling、工具调用

Function Calling 是什么

Function Calling = LLM 决定要调用哪个函数 + 生成参数

普通对话:
  用户: "北京今天天气怎么样?"
  LLM: "我无法获取实时天气信息。"  ← 没有能力

Function Calling:
  用户: "北京今天天气怎么样?"
  LLM: {
    "function": "get_weather",      ← LLM 选择了工具
    "arguments": { "city": "北京" }  ← LLM 生成了参数
  }
  应用: 调用真实的天气 API → 返回结果给 LLM
  LLM: "北京今天 25°C,晴天,适合外出。"  ← 基于真实数据回答

注意: LLM 不执行函数!只是决定调用什么 + 生成参数
      实际执行由应用层(前端/后端)完成

OpenAI Function Calling

typescript
import OpenAI from 'openai'

const openai = new OpenAI()

const tools = [
  {
    type: 'function' as const,
    function: {
      name: 'get_weather',
      description: '获取指定城市的实时天气',
      parameters: {
        type: 'object',
        properties: {
          city: { type: 'string', description: '城市名称' },
          unit: {
            type: 'string',
            enum: ['celsius', 'fahrenheit'],
            description: '温度单位',
          },
        },
        required: ['city'],
      },
    },
  },
  {
    type: 'function' as const,
    function: {
      name: 'search_products',
      description: '搜索商品',
      parameters: {
        type: 'object',
        properties: {
          query: { type: 'string', description: '搜索关键词' },
          max_price: { type: 'number', description: '最高价格' },
        },
        required: ['query'],
      },
    },
  },
]

const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: '北京天气怎么样?' }],
  tools,
  tool_choice: 'auto',
})

const toolCall = response.choices[0].message.tool_calls?.[0]
if (toolCall) {
  const args = JSON.parse(toolCall.function.arguments)
  // { city: "北京" }

  const weatherData = await getWeatherAPI(args.city)

  const finalResponse = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages: [
      { role: 'user', content: '北京天气怎么样?' },
      response.choices[0].message,
      {
        role: 'tool',
        tool_call_id: toolCall.id,
        content: JSON.stringify(weatherData),
      },
    ],
  })

  console.log(finalResponse.choices[0].message.content)
  // "北京今天25°C,晴天,微风..."
}

并行 Function Calling

GPT-4o 支持一次调用多个函数:

用户: "帮我查北京和上海的天气"

LLM 返回:
  tool_calls: [
    { function: "get_weather", arguments: { city: "北京" } },
    { function: "get_weather", arguments: { city: "上海" } },
  ]

应用层: Promise.all 并行调用两个 API → 结果返回给 LLM

前端中的 Function Calling

typescript
// Vercel AI SDK — 前端友好的 Function Calling
import { generateText, tool } from 'ai'
import { openai } from '@ai-sdk/openai'
import { z } from 'zod'

const result = await generateText({
  model: openai('gpt-4o'),
  prompt: '北京天气怎么样?',
  tools: {
    getWeather: tool({
      description: '获取城市天气',
      parameters: z.object({
        city: z.string().describe('城市名称'),
      }),
      execute: async ({ city }) => {
        const data = await fetch(`/api/weather?city=${city}`)
        return data.json()
      },
    }),
  },
})

追问延伸

  • tool_choice: 'auto'tool_choice: 'required' 的区别?
  • Function Calling 的参数校验失败怎么处理?(重试 / 结构化输出)
  • 如何防止 LLM 调用不该调用的函数?(权限控制 / 函数白名单)

9. LLM 的幻觉(Hallucination)问题?如何缓解? ⭐⭐

理解幻觉问题的成因和解决方案。

考察点:AI 安全

什么是幻觉

幻觉 = 模型生成看似合理但事实上错误/虚构的内容

类型:
  ① 事实性幻觉: "爱因斯坦发明了电话"(错误的事实)
  ② 忠实性幻觉: 回答与输入矛盾(摘要时添加原文没有的信息)
  ③ 编造来源: "根据 2024 年 Nature 论文..."(不存在的论文)
  ④ 自信地胡说: 用非常确定的语气说完全错误的内容

为什么会产生幻觉:
  - LLM 是概率模型,本质是"看起来像"正确答案
  - 训练数据中的错误/矛盾信息
  - 对训练数据之外的知识(截止日期后的事件)一无所知
  - 模型倾向于"有答案"而非说"不知道"

缓解策略

① RAG (Retrieval-Augmented Generation)
  检索相关知识 → 作为上下文注入 Prompt → 基于事实回答
  → 最有效的缓解幻觉的方法

② Prompt 设计
  "如果你不确定答案,请说'我不确定'而不是猜测"
  "请在回答中标注信息来源"
  "只基于以下提供的内容回答,不要使用你的训练知识"

③ 降低 Temperature
  temperature = 0 → 最确定的输出 → 减少随机生成

④ 事实核查
  让模型先回答,再让另一个 Prompt 检查回答的准确性
  "请检查以下回答中是否有事实错误: [回答]"

⑤ 引用来源
  要求模型在回答中标注引用:
  "回答时请使用 [1][2] 标注来源,并在末尾列出参考资料"

⑥ Grounding(接地)
  将回答限制在提供的文档/数据中:
  "只根据以下文档内容回答用户问题,如果文档中没有答案,说'文档中未提及'"

前端如何处理幻觉

typescript
// ① 在 UI 中添加免责声明
<div className="ai-disclaimer">
  AI 生成的内容可能存在错误,请注意甄别
</div>

// ② 让用户反馈
<button onClick={() => reportInaccuracy(messageId)}>
  这个回答不准确
</button>

// ③ 显示信息来源
{answer.sources?.map(source => (
  <a href={source.url} key={source.id}>
    [{source.index}] {source.title}
  </a>
))}

// ④ 置信度展示
{answer.confidence < 0.7 && (
  <span className="low-confidence">
    ⚠️ 此回答置信度较低,建议人工确认
  </span>
)}

追问延伸

  • Constitutional AI 是什么?Claude 如何用它减少有害输出?
  • 如何用 LLM 做"自我检查"?(Self-Consistency / Self-Critique)
  • 幻觉检测工具有哪些?(RAGAS / TruLens)

10. 如何评估 LLM 应用的效果?评估指标有哪些? ⭐⭐

建立 AI 应用的评估体系。

考察点:模型评估

为什么需要评估

场景: 你改了一个 Prompt → 效果变好了还是变差了?

没有评估:
  "感觉好像变好了"  ← 主观判断,不可靠

有评估:
  "准确率从 72% 提升到 85%,延迟从 2s 降到 1.5s"  ← 客观数据

评估维度

┌──────────────────────────────────────────┐
│  质量指标                                 │
│  准确率 / 相关性 / 完整性 / 一致性        │
├──────────────────────────────────────────┤
│  安全指标                                 │
│  幻觉率 / 有害输出率 / 隐私泄露          │
├──────────────────────────────────────────┤
│  性能指标                                 │
│  延迟 / 吞吐量 / Token 消耗 / 成本       │
├──────────────────────────────────────────┤
│  用户指标                                 │
│  满意度 / 点赞率 / 重试率 / 留存率       │
└──────────────────────────────────────────┘

自动化评估方法

① LLM-as-Judge(用 LLM 评估 LLM)
  让一个强模型(GPT-4)评估弱模型的回答:

  "请评估以下回答的质量:
   问题: {question}
   参考答案: {reference}
   模型回答: {response}

   评分标准 (1-5):
   - 准确性: 信息是否正确
   - 完整性: 是否回答了所有要点
   - 相关性: 是否紧扣问题

   请输出 JSON: { accuracy: N, completeness: N, relevance: N }"

② 传统 NLP 指标
  BLEU / ROUGE → 和参考答案的文本重合度
  → 适合翻译、摘要
  → 不太适合开放式问答

③ RAG 特定指标 (RAGAS)
  - Faithfulness: 回答是否忠实于检索到的文档
  - Answer Relevancy: 回答是否相关
  - Context Precision: 检索的文档是否精准
  - Context Recall: 是否检索到了所有相关文档

评估流程

typescript
// 构建评估数据集
const evalDataset = [
  {
    query: '什么是闭包?',
    expectedAnswer: '闭包是指函数可以记住并访问其词法作用域...',
    category: 'javascript',
  },
  // ... 100+ 测试用例
]

// 运行评估
async function evaluate(dataset, promptTemplate) {
  const results = []

  for (const item of dataset) {
    const response = await llm.chat(promptTemplate(item.query))
    const score = await llmJudge(item.query, item.expectedAnswer, response)
    results.push({ ...item, response, score })
  }

  return {
    avgAccuracy: avg(results.map(r => r.score.accuracy)),
    avgCompleteness: avg(results.map(r => r.score.completeness)),
    avgRelevance: avg(results.map(r => r.score.relevance)),
    totalCost: results.reduce((s, r) => s + r.tokenCost, 0),
    avgLatency: avg(results.map(r => r.latency)),
  }
}

// 对比不同 Prompt 版本
const v1 = await evaluate(dataset, promptV1)
const v2 = await evaluate(dataset, promptV2)
console.table({ v1, v2 })

评估工具

工具类型特点
LangSmith全链路追踪 + 评估 + 数据集管理
RAGASRAG 评估专注 RAG 质量指标
PromptfooPrompt 评估CLI 工具,对比 Prompt 版本
Braintrust平台评估 + 实验管理
自建灵活适合特定业务需求

追问延伸

  • 评估数据集怎么构建?需要多少测试用例?
  • LLM-as-Judge 的偏见怎么处理?(位置偏见、冗长偏见)
  • 如何实现 Prompt 的 A/B 测试?线上评估怎么做?

11. 什么是模型微调(Fine-Tuning)?什么时候需要微调?前端工程师需要了解什么? ⭐⭐⭐

理解微调的场景、方法与局限性。

考察点:微调技术

微调 vs Prompt Engineering

Prompt Engineering(调提示词):
  ✅ 零成本启动,即改即用
  ✅ 不需要训练数据
  ✅ 灵活切换任务
  ❌ 占用上下文窗口(Few-Shot 示例吃 Token)
  ❌ 复杂指令 LLM 不一定能稳定遵循

Fine-Tuning(微调):
  ✅ 模型内化了你的"规则",不占上下文窗口
  ✅ 输出格式更稳定、风格更一致
  ✅ 可以降低推理成本(用小模型替代大模型)
  ❌ 需要高质量训练数据(通常 100-10000 条)
  ❌ 有训练成本和时间
  ❌ 模型知识不会更新(知识截止于训练数据)

决策流程:
  需求 → 先试 Prompt Engineering
       → 效果不够 → 试 RAG(检索增强)
       → 还不够 → 考虑 Fine-Tuning
       → 极端场景 → 从头预训练(99% 不需要)

微调的主流方法

┌────────────────────────────────────────────────────┐
│          全参数微调 (Full Fine-Tuning)               │
│  修改模型所有参数 → 效果最好 → 成本最高             │
│  适合: 大公司、特定垂直领域                          │
├────────────────────────────────────────────────────┤
│          LoRA (Low-Rank Adaptation)                  │
│  冻结原模型,只训练低秩矩阵 → 效果好 → 成本低       │
│  参数量: 原模型的 0.1% ~ 1%                          │
│  适合: 绝大多数微调场景(推荐首选)                  │
├────────────────────────────────────────────────────┤
│          QLoRA                                       │
│  LoRA + 4bit 量化 → 单卡 24GB 即可微调 7B 模型      │
│  适合: 资源受限、个人开发者                          │
├────────────────────────────────────────────────────┤
│          Prefix Tuning / P-Tuning                    │
│  在输入前添加可训练的"虚拟 Token"                    │
│  参数量极小 → 但效果通常不如 LoRA                    │
└────────────────────────────────────────────────────┘

微调数据格式

jsonl
// OpenAI 微调数据格式(JSONL)
{"messages": [
  {"role": "system", "content": "你是一个前端代码审查助手,输出格式为 JSON"},
  {"role": "user", "content": "审查这段代码:\nconst x = document.getElementById('app');\nx.innerHTML = userInput;"},
  {"role": "assistant", "content": "{\"issues\": [{\"severity\": \"critical\", \"type\": \"xss\", \"line\": 2, \"message\": \"直接将用户输入赋值给 innerHTML 存在 XSS 风险\", \"fix\": \"使用 textContent 或 DOMPurify 净化\"}]}"}
]}
{"messages": [
  {"role": "system", "content": "你是一个前端代码审查助手,输出格式为 JSON"},
  {"role": "user", "content": "审查这段代码:\nawait fetch('/api/data')"},
  {"role": "assistant", "content": "{\"issues\": [{\"severity\": \"warning\", \"type\": \"error-handling\", \"line\": 1, \"message\": \"fetch 请求缺少错误处理\", \"fix\": \"添加 try-catch 或 .catch() 处理网络错误\"}]}"}
]}

前端工程师需要知道的

typescript
// OpenAI Fine-Tuning API 示例
import OpenAI from 'openai'

const openai = new OpenAI()

const fineTune = await openai.fineTuning.jobs.create({
  training_file: 'file-abc123',  // 上传的 JSONL 文件 ID
  model: 'gpt-4o-mini-2024-07-18',
  hyperparameters: {
    n_epochs: 3,       // 训练轮数
    batch_size: 'auto',
    learning_rate_multiplier: 'auto',
  },
  suffix: 'code-reviewer',  // 模型名后缀
})

// 使用微调后的模型(和普通调用完全一样)
const response = await openai.chat.completions.create({
  model: 'ft:gpt-4o-mini-2024-07-18:my-org:code-reviewer:abc123',
  messages: [
    { role: 'system', content: '你是一个前端代码审查助手,输出格式为 JSON' },
    { role: 'user', content: '审查这段代码:\n...' },
  ],
})

什么时候微调

场景推荐方案理由
让 AI 回答公司内部知识RAG知识会更新,微调无法实时更新
输出必须严格遵循特定 JSON 格式Fine-Tuning微调后格式稳定性远超 Prompt
模仿特定写作风格Fine-Tuning风格是隐性知识,Prompt 难以完整描述
用小模型替代大模型降本Fine-Tuning微调后 4o-mini 可接近 4o 效果
简单问答 / 翻译 / 摘要Prompt通用任务 Prompt 足够

追问延伸

  • LoRA 的数学原理是什么?为什么低秩分解有效?
  • 微调数据量多少合适?数据质量和数量哪个更重要?
  • 如何评估微调效果?过拟合怎么检测和避免?

12. 什么是向量数据库(Vector Database)?在 AI 应用中起什么作用? ⭐⭐

理解向量数据库在 RAG 和语义搜索中的核心地位。

考察点:向量存储与相似性搜索

为什么需要向量数据库

传统搜索 vs 语义搜索:

用户搜索: "JS 闭包"
  关键词搜索: 只能匹配包含 "JS" 和 "闭包" 的文档
  语义搜索:   能匹配 "JavaScript closure"、"函数作用域链"、
              "变量被内部函数引用" 等语义相关的内容

核心思路:
  文本 → Embedding 模型 → 向量 [0.12, -0.34, 0.56, ...]  (1536维)
  相似的语义 → 相近的向量 → 向量距离小

Embedding 原理

文本转向量:
  "React Hooks"    → [0.12, -0.34, 0.56, ..., 0.78]  // 1536维向量
  "React 钩子函数"  → [0.11, -0.33, 0.55, ..., 0.77]  // 相似!距离近
  "Vue 响应式"      → [0.45, 0.12, -0.67, ..., 0.23]  // 不同!距离远

常用 Embedding 模型:
  ┌──────────────────────────────────────────┐
  │ 模型                   │ 维度  │ 特点    │
  ├──────────────────────────────────────────┤
  │ text-embedding-3-small │ 1536  │ 性价比高│
  │ text-embedding-3-large │ 3072  │ 精度最高│
  │ BGE-M3 (开源)         │ 1024  │ 多语言  │
  │ Jina Embeddings v3    │ 1024  │ 多语言  │
  └──────────────────────────────────────────┘

相似度计算:
  余弦相似度 (Cosine Similarity):
    cos(A, B) = (A · B) / (|A| × |B|)
    值域 [-1, 1],越接近 1 越相似

  欧氏距离 (Euclidean Distance):
    d = √(Σ(ai - bi)²)
    值越小越相似

向量数据库选型

┌──────────────────────────────────────────────────────┐
│ 数据库          │ 类型       │ 特点                    │
├──────────────────────────────────────────────────────┤
│ Pinecone        │ 云服务     │ 全托管,开箱即用         │
│ Weaviate        │ 开源/云    │ 支持混合搜索,GraphQL API│
│ Qdrant          │ 开源/云    │ Rust 实现,性能优秀      │
│ Milvus          │ 开源       │ 大规模,适合企业级       │
│ Chroma          │ 开源       │ 轻量,适合原型开发       │
│ pgvector        │ PG 扩展   │ 直接在 PostgreSQL 中用   │
│ Supabase Vector │ 云服务     │ 基于 pgvector,前端友好  │
└──────────────────────────────────────────────────────┘

前端接入示例

typescript
// 使用 Supabase Vector(前端友好的方案)
import { createClient } from '@supabase/supabase-js'
import OpenAI from 'openai'

const supabase = createClient(SUPABASE_URL, SUPABASE_KEY)
const openai = new OpenAI()

// 1. 文档入库(通常在后端/脚本中执行)
async function indexDocument(content: string, metadata: Record<string, unknown>) {
  const embeddingResponse = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: content,
  })
  const embedding = embeddingResponse.data[0].embedding

  await supabase.from('documents').insert({
    content,
    metadata,
    embedding,
  })
}

// 2. 语义搜索
async function semanticSearch(query: string, topK = 5) {
  const embeddingResponse = await openai.embeddings.create({
    model: 'text-embedding-3-small',
    input: query,
  })
  const queryEmbedding = embeddingResponse.data[0].embedding

  const { data } = await supabase.rpc('match_documents', {
    query_embedding: queryEmbedding,
    match_threshold: 0.7,
    match_count: topK,
  })

  return data
}

// 3. RAG: 搜索 + 生成
async function ragAnswer(question: string) {
  const docs = await semanticSearch(question)
  const context = docs.map(d => d.content).join('\n\n')

  const response = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages: [
      {
        role: 'system',
        content: `基于以下参考文档回答用户问题。如果文档中没有相关信息,请说明。\n\n${context}`,
      },
      { role: 'user', content: question },
    ],
  })

  return {
    answer: response.choices[0].message.content,
    sources: docs.map(d => d.metadata),
  }
}

向量数据库在 AI 应用中的位置

┌──────────────────────────────────────────────────────┐
│                  RAG 架构全景                         │
│                                                      │
│  用户提问                                             │
│    ↓                                                 │
│  Query Embedding → 向量数据库 → Top-K 相似文档       │
│                                       ↓              │
│                              Context + Question      │
│                                       ↓              │
│                                   LLM 生成            │
│                                       ↓              │
│                                   回答 + 引用         │
│                                                      │
│  离线流程(数据准备):                                 │
│  文档 → 分块(Chunking) → Embedding → 存入向量数据库  │
└──────────────────────────────────────────────────────┘

追问延伸

  • 文档分块(Chunking)有哪些策略?chunk_size 怎么选?
  • 混合搜索(Hybrid Search)是什么?关键词 + 语义如何结合?
  • 向量数据库的索引算法(HNSW / IVF / PQ)区别是什么?

13. 什么是多模态大模型(Multimodal LLM)?前端如何接入多模态能力? ⭐⭐

理解多模态模型的原理和前端集成方式。

考察点:多模态技术

什么是多模态

单模态:
  文本 → LLM → 文本

多模态:
  文本   ┐
  图像   ├→ 多模态 LLM → 文本 / 图像 / 音频 / 视频
  音频   ┤
  视频   ┘

代表模型:
  GPT-4o:      文本 + 图像 + 音频 → 文本 + 音频
  Claude 3.5:  文本 + 图像 → 文本
  Gemini 2.0:  文本 + 图像 + 音频 + 视频 → 文本 + 图像 + 音频

图像理解(Vision)

typescript
// OpenAI Vision API
const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [
    {
      role: 'user',
      content: [
        { type: 'text', text: '这个 UI 设计有什么可以改进的地方?' },
        {
          type: 'image_url',
          image_url: {
            url: 'data:image/png;base64,iVBOR...', // Base64 或 URL
            detail: 'high', // low | high | auto
          },
        },
      ],
    },
  ],
  max_tokens: 1000,
})

前端图像上传与分析

typescript
// React 组件:图像分析
function ImageAnalyzer() {
  const [result, setResult] = useState<string>('')
  const [loading, setLoading] = useState(false)

  async function handleImageUpload(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0]
    if (!file) return

    setLoading(true)

    const base64 = await fileToBase64(file)

    const res = await fetch('/api/analyze-image', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        image: base64,
        prompt: '分析这个 UI 截图,指出设计问题和改进建议',
      }),
    })

    const data = await res.json()
    setResult(data.analysis)
    setLoading(false)
  }

  return (
    <div>
      <input type="file" accept="image/*" onChange={handleImageUpload} />
      {loading && <p>分析中...</p>}
      {result && <div className="analysis">{result}</div>}
    </div>
  )
}

function fileToBase64(file: File): Promise<string> {
  return new Promise((resolve) => {
    const reader = new FileReader()
    reader.onload = () => resolve(reader.result as string)
    reader.readAsDataURL(file)
  })
}

语音交互

typescript
// 实时语音对话(OpenAI Realtime API / WebRTC)
const pc = new RTCPeerConnection()

// 获取麦克风音频
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
pc.addTrack(stream.getTracks()[0])

// 接收 AI 音频
const audioEl = document.createElement('audio')
audioEl.autoplay = true
pc.ontrack = (e) => {
  audioEl.srcObject = e.streams[0]
}

// 连接 OpenAI Realtime
const offer = await pc.createOffer()
await pc.setLocalDescription(offer)

const sdpResponse = await fetch('https://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${OPENAI_API_KEY}`,
    'Content-Type': 'application/sdp',
  },
  body: offer.sdp,
})

const answer: RTCSessionDescriptionInit = {
  type: 'answer',
  sdp: await sdpResponse.text(),
}
await pc.setRemoteDescription(answer)

多模态应用场景

前端相关的多模态场景:
  ┌─────────────────────────────────────────────────────┐
  │ 场景              │ 输入      │ 输出   │ 技术点     │
  ├─────────────────────────────────────────────────────┤
  │ UI 审查           │ 截图      │ 文本   │ Vision API │
  │ 设计稿转代码      │ 设计图    │ 代码   │ Vision+生成│
  │ 图表数据提取      │ 图表截图  │ JSON   │ Vision API │
  │ 无障碍 alt 生成   │ 图片      │ 文本   │ Vision API │
  │ 语音助手          │ 音频      │ 音频   │ Realtime   │
  │ 视频内容分析      │ 视频帧    │ 文本   │ 抽帧+Vision│
  │ OCR 识别          │ 文档图片  │ 文本   │ Vision API │
  └─────────────────────────────────────────────────────┘

追问延伸

  • 图像 Token 怎么计算?detail: high vs low 的成本差异?
  • 前端如何实现实时语音对话?WebRTC vs WebSocket 方案对比?
  • 多模态模型的"幻觉"和文本模型有什么不同?

14. AI 应用的工程化实践有哪些?前端如何构建生产级 AI 应用? ⭐⭐⭐

从原型到生产,AI 应用的工程化全流程。

考察点:AI 工程化

原型 vs 生产

原型(Demo):
  调一下 API → 拿到结果 → 展示
  耗时: 1-2 天

生产级应用:
  ┌──────────────────────────────────────────┐
  │  错误处理   │ API 限流   │ 流式传输     │
  │  成本控制   │ 日志追踪   │ 缓存策略     │
  │  Prompt 管理│ A/B 测试   │ 安全防护     │
  │  监控告警   │ 降级方案   │ 多模型路由   │
  └──────────────────────────────────────────┘
  耗时: 数月

这就是"AI 工程化"要解决的问题

前端 AI 应用架构

┌────────────────────────────────────────────────────────┐
│  Frontend                                              │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐              │
│  │ Chat UI  │ │ Streaming│ │ State    │              │
│  │ Component│ │ Handler  │ │ Manager  │              │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘              │
│       └─────────────┼───────────┘                     │
│                     ↓                                  │
├────────────────────────────────────────────────────────┤
│  API Layer (BFF / Edge Function)                       │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐              │
│  │ Rate     │ │ Auth &   │ │ Request  │              │
│  │ Limiter  │ │ API Key  │ │ Logger   │              │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘              │
│       └─────────────┼───────────┘                     │
│                     ↓                                  │
├────────────────────────────────────────────────────────┤
│  AI Service Layer                                      │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐              │
│  │ Prompt   │ │ Model    │ │ Response │              │
│  │ Template │ │ Router   │ │ Cache    │              │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘              │
│       └─────────────┼───────────┘                     │
│                     ↓                                  │
├────────────────────────────────────────────────────────┤
│  LLM Providers                                         │
│  OpenAI  │  Anthropic  │  本地模型  │  备用模型       │
└────────────────────────────────────────────────────────┘

关键工程化实践

typescript
// 1. 多模型路由与降级
class ModelRouter {
  private models = [
    { name: 'gpt-4o', provider: 'openai', priority: 1 },
    { name: 'claude-3.5-sonnet', provider: 'anthropic', priority: 2 },
    { name: 'deepseek-chat', provider: 'deepseek', priority: 3 },
  ]

  async chat(messages: Message[]): Promise<string> {
    for (const model of this.models) {
      try {
        return await this.callModel(model, messages)
      } catch (e) {
        console.warn(`${model.name} failed, trying next...`, e)
      }
    }
    throw new Error('All models failed')
  }

  private async callModel(model: ModelConfig, messages: Message[]) {
    const controller = new AbortController()
    const timeout = setTimeout(() => controller.abort(), 30_000)

    try {
      return await providers[model.provider].chat({
        model: model.name,
        messages,
        signal: controller.signal,
      })
    } finally {
      clearTimeout(timeout)
    }
  }
}

// 2. 语义缓存(避免重复调用)
class SemanticCache {
  async get(query: string): Promise<string | null> {
    const embedding = await getEmbedding(query)
    const cached = await vectorDB.search(embedding, { threshold: 0.95 })

    if (cached.length > 0) {
      return cached[0].response
    }
    return null
  }

  async set(query: string, response: string): Promise<void> {
    const embedding = await getEmbedding(query)
    await vectorDB.insert({ query, response, embedding })
  }
}

// 3. Prompt 版本管理
const prompts = {
  'code-review': {
    v1: { template: '...', model: 'gpt-4o-mini' },
    v2: { template: '...', model: 'gpt-4o' },
    active: 'v2',
  },
}

// 4. 成本追踪
function trackCost(model: string, usage: TokenUsage) {
  const pricing: Record<string, { input: number; output: number }> = {
    'gpt-4o': { input: 2.5 / 1_000_000, output: 10 / 1_000_000 },
    'gpt-4o-mini': { input: 0.15 / 1_000_000, output: 0.6 / 1_000_000 },
    'claude-3.5-sonnet': { input: 3 / 1_000_000, output: 15 / 1_000_000 },
  }

  const cost =
    usage.prompt_tokens * pricing[model].input +
    usage.completion_tokens * pricing[model].output

  metrics.record('ai_cost', cost, { model })
}

可观测性

typescript
// LangSmith 追踪集成
import { Client } from 'langsmith'
import { traceable } from 'langsmith/traceable'

const ragAnswer = traceable(
  async function ragAnswer(question: string) {
    const docs = await traceable(semanticSearch, { name: 'retrieval' })(question)
    const answer = await traceable(llmGenerate, { name: 'generation' })({
      question,
      context: docs,
    })
    return answer
  },
  { name: 'rag-pipeline', tags: ['production'] }
)

// 前端错误上报
window.addEventListener('unhandledrejection', (event) => {
  if (event.reason?.message?.includes('rate_limit')) {
    showToast('AI 服务繁忙,请稍后重试')
    metrics.increment('ai_rate_limit')
  }
})

生产 Checklist

□ 错误处理: API 超时/限流/模型不可用的降级方案
□ 流式传输: SSE/ReadableStream 实现打字机效果
□ 安全防护: API Key 不暴露前端,输入过滤,输出检查
□ 成本控制: Token 限制、缓存、模型路由、预算告警
□ 可观测性: 请求日志、延迟追踪、成本统计、错误率
□ Prompt 管理: 版本控制、A/B 测试、模板引擎
□ 用户体验: 加载状态、取消请求、重试机制、反馈收集
□ 合规: 数据隐私、内容审核、用户协议

追问延伸

  • 如何实现 AI 应用的 A/B 测试?(Prompt / 模型 / 参数)
  • 语义缓存的命中率怎么提升?向量相似度阈值怎么调?
  • 如何预估 AI 应用的成本?用量突增怎么控制?

15. AI 技术的发展趋势是什么?前端工程师如何规划 AI 学习路线? ⭐⭐

把握 AI 发展方向,制定个人学习计划。

考察点:AI 趋势与前端融合

2024-2025 AI 关键趋势

┌──────────────────────────────────────────────────────────┐
│  趋势 1: Agent 从概念到产品                              │
│                                                          │
│  2023: "用 Prompt 调 API"                                │
│  2024: "Agent 能用工具、做规划、有记忆"                   │
│  2025: "多 Agent 协作、自主完成复杂工作流"                │
│                                                          │
│  代表: Claude Computer Use / OpenAI Operator              │
│       Devin / Cursor / Windsurf / v0                     │
├──────────────────────────────────────────────────────────┤
│  趋势 2: 小模型崛起                                      │
│                                                          │
│  大模型并不总是最优选:                                    │
│  Phi-3 (3.8B) / Llama 3.2 (1B-3B) / Qwen2.5 (0.5B-72B)│
│  → 端侧推理 → 手机/浏览器本地运行 → 隐私保护            │
│                                                          │
│  WebLLM / Transformers.js → 浏览器端运行 LLM             │
├──────────────────────────────────────────────────────────┤
│  趋势 3: 多模态成为标配                                  │
│                                                          │
│  GPT-4o: 原生多模态(文本+图像+音频)                    │
│  实时语音对话: OpenAI Realtime API                       │
│  视频理解: Gemini 2.0                                    │
│  → 前端需要处理更多媒体类型的 AI 交互                    │
├──────────────────────────────────────────────────────────┤
│  趋势 4: AI Native 应用                                  │
│                                                          │
│  不是"给现有应用加 AI",而是"围绕 AI 重新设计产品"       │
│  传统: 搜索框 → 结果列表                                 │
│  AI Native: 对话 → 直接给答案 + 操作                     │
│                                                          │
│  例: Perplexity (搜索) / Cursor (编程) / v0 (UI生成)     │
├──────────────────────────────────────────────────────────┤
│  趋势 5: AI 开发工具标准化                               │
│                                                          │
│  Vercel AI SDK → 统一的前端 AI 开发体验                  │
│  LangChain / LlamaIndex → 标准化 RAG / Agent 框架       │
│  MCP (Model Context Protocol) → 标准化工具接入           │
│  OpenAI Agents SDK → 标准化 Agent 开发                   │
└──────────────────────────────────────────────────────────┘

前端 × AI 技能矩阵

Level 1: AI 应用使用者(1-2 周)
  ☑ 使用 ChatGPT / Claude / Cursor 辅助编程
  ☑ 理解 Prompt Engineering 基础
  ☑ 了解 LLM 的能力边界

Level 2: AI 功能集成者(1-3 月)
  ☑ 调用 OpenAI / Claude API
  ☑ 实现流式输出(SSE / ReadableStream)
  ☑ 使用 Vercel AI SDK 构建 Chat UI
  ☑ 理解 Token / 成本 / 上下文窗口

Level 3: AI 应用开发者(3-6 月)
  ☑ 构建 RAG 应用(向量数据库 + 检索 + 生成)
  ☑ 实现 Agent(Function Calling + 工具编排)
  ☑ AI 应用工程化(缓存/降级/监控/成本控制)
  ☑ 使用 LangChain / LlamaIndex 等框架

Level 4: AI 产品架构师(6-12 月)
  ☑ 设计多 Agent 协作系统
  ☑ MCP 服务端开发与集成
  ☑ 微调模型用于特定场景
  ☑ 端侧 AI 推理(WebLLM / ONNX Runtime Web)
  ☑ AI 产品的评估与迭代体系

浏览器端 AI 推理

typescript
// 使用 Transformers.js 在浏览器中运行模型
import { pipeline } from '@huggingface/transformers'

// 情感分析
const classifier = await pipeline('sentiment-analysis')
const result = await classifier('I love React!')
// [{ label: 'POSITIVE', score: 0.9998 }]

// 文本嵌入
const embedder = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2')
const embedding = await embedder('React Hooks 教程')
// Float32Array(384) [0.012, -0.034, ...]

// WebLLM: 浏览器中运行完整 LLM
import { CreateMLCEngine } from '@mlc-ai/web-llm'

const engine = await CreateMLCEngine('Llama-3.2-1B-Instruct-q4f16_1-MLC')
const reply = await engine.chat.completions.create({
  messages: [{ role: 'user', content: '什么是闭包?' }],
})

推荐学习资源

入门:
  📚 《Building LLM Apps》— Vercel AI SDK 实战
  🎥  Andrej Karpathy YouTube — LLM 原理讲解
  📝  Prompt Engineering Guide (promptingguide.ai)

进阶:
  📚  LangChain / LangGraph 官方文档
  📚  Anthropic Cookbook — Claude 最佳实践
  🔧  LangSmith — AI 应用调试和评估
  🔧  Vercel AI SDK 文档

前沿:
  📝  Lilian Weng 博客 — AI Agent 综述
  📝  Anthropic Research Blog
  📝  OpenAI Research Blog
  🏗️  MCP 官方文档 (modelcontextprotocol.io)

实战项目建议:
  1. AI 聊天机器人(流式 + 历史 + Markdown 渲染)
  2. 文档问答系统(RAG: 向量检索 + 生成)
  3. AI 代码助手(Function Calling + 代码执行)
  4. 多 Agent 工作流(规划 → 执行 → 审查)

追问延伸

  • 端侧 AI(WebLLM / Transformers.js)的性能瓶颈是什么?
  • AI 会取代前端工程师吗?前端在 AI 时代的不可替代性是什么?
  • 如何评估一个 AI 技术是否值得投入学习?

用心学习,用代码说话 💻