作为一个前端er如何了解LLM(大语言模型)

LLM是如何工作的?

用一句话总结,LLM就是一个"超级猜词机器"。它通过海量文本数据训练,学习语言规律,然后通过概率计算,预测下一个单词。让我们按照处理流程来详细了解LLM的工作原理。

整体流程图

下面我们先通过流程图来看一下它的工作流程。

graph TD A[输入文本] --> B(Token化处理) B --> C{词表示} C -->|传统方法| C1[One-Hot编码] C -->|现代方法| C2[动态Embedding] C2 --> D[+位置编码] D --> E[Transformer块] E --> F[自注意力机制] F --> G[计算词间关联权重] G --> H[多头注意力拼接] H --> I[前馈神经网络] I --> J[LayerNorm] J --> K{是否最后一层?} K -->|否| E K -->|是| L[输出概率分布] L --> M[温度采样] M --> N[生成最终Token] N --> O[输出文本] style C1 fill:#f9f,stroke:#333,stroke-width:2px style C2 fill:#8f8,stroke:#333,stroke-width:2px subgraph 核心迭代 E-->F-->G-->H-->I-->J-->K end subgraph 开发者可控参数 B -.-> P[最大Token数] M -.-> Q[温度值] L -.-> R[Top-p采样] end

有了以上的流程图,我们再分步解析

1. 输入处理:Token化

Token:文字的 "最小零件"

Token是理解大模型的重要概念。是一段文本被切分成的 最小单位 ,比如我们通过openai的分词器 就可以把"ChatGPT is cool!" 这段文字切分为5个token 分别是["Chat", "GPT", "is", "cool", "!"]

上下文窗口(Context Window)

各大厂商的竞争中,有一个很重要的指标就是上下文窗口的大小。这里的上下文窗口,指的就是大模型可以处理 Token 数量,上下文越大,能处理的 Token 越多。能处理的 Token 越多,大模型对信息的理解就越充分,生成的内容就越接近我们需要的结果。

下面是 gpt-4o-mini 的上下文窗口处理的 Token 情况(摘自 Open AI 官网)。

同时,token也关系到如何计费。token越多,收费越多

2. 词表示(Word Representation)

传统方法:One-Hot编码(早期方案)

One-Hot编码是最基础的词表示方法,将每个词表示为一个只有一个1,其余都是0的向量。这种方法简单直观,但无法表达词与词之间的关系。

举个例子,假设我们的词表里只有5个词:[猫, 小猫, 狗, 跑, 睡觉],那么每个词都会被编码成一个5维向量:

javascript 复制代码
// 词表大小为5的One-Hot编码示例
const vocabulary = {
  "猫":    [1, 0, 0, 0, 0],
  "小猫":  [0, 1, 0, 0, 0],
  "狗":    [0, 0, 1, 0, 0],
  "跑":    [0, 0, 0, 1, 0],
  "睡觉":  [0, 0, 0, 0, 1]
};

// 虽然"猫"和"小猫"在语义上很接近
// 但它们的One-Hot编码完全不同,无法体现出它们的相似性
const cat = vocabulary["猫"];     // [1, 0, 0, 0, 0]
const kitten = vocabulary["小猫"]; // [0, 1, 0, 0, 0]

// 计算相似度会得到0,说明One-Hot编码无法捕捉词义关系
const similarity = cosineSimilarity(cat, kitten); // 结果为0

这个例子展示了One-Hot编码的主要缺点:

  1. 向量维度随词表大小线性增长(实际词表可能有几万到几十万个词)
  2. 所有词之间的距离都相等,无法表达词义的相近程度
  3. 无法进行有意义的向量运算(如类比推理)

现代方法:动态Embedding

Embedding是将字符转换为高维向量(一串数字)过程。这种方法不仅能表示词的含义,还能捕捉词之间的关系。

举个例子,假设我们使用300维的向量来表示每个词,那么"猫"这个词可能被表示为:

javascript 复制代码
// 猫的词向量(简化示例,实际是300维)
const cat = [0.2, -0.5, 0.8, 0.1, -0.3, ...]; // 300个数字

// 小猫的词向量
const kitten = [0.18, -0.48, 0.79, 0.12, -0.28, ...]; // 与"猫"的向量非常接近

// 计算相似度(余弦相似度)
const similarity = cosineSimilarity(cat, kitten); // 结果接近1,表示语义相近

这种表示方法相比One-Hot编码(假设词表大小为50000,就需要50000维向量)有两个明显优势:

  1. 维度更低(通常是50~1000维),计算效率更高
  2. 可以通过向量运算发现词之间的语义关系,比如"猫"和"小猫"的向量距离很近,而"猫"和"狗"的向量距离较远。

位置编码

为了让模型理解词在句子中的位置信息,需要给每个词的Embedding加入位置信息。

3. Transformer核心处理

自注意力机制(Self-Attention)

它的核心机制就是让模型处理每个词时,会"注意"其他词的重要性。

比如句子"他打了球,然后它破了",模型会关联"它"和"球",而不是"他"。

可以把它想象成代码中的依赖分析

typescript 复制代码
// 伪代码示例:计算词间关联
function selfAttention(tokens) {
  const scores = tokens.map(token => 
    tokens.map(other => similarity(token, other))
  );
  return weightedSum(scores);
}

多头注意力机制

通过多个不同的注意力头,模型可以同时关注不同角度的信息,比如语法关系、语义关系等。

前馈神经网络和LayerNorm

经过注意力层后,每个token都会通过一个前馈神经网络进行进一步处理,并通过LayerNorm进行归一化,保持数值稳定。

4. 输出生成

概率分布

模型会为每个可能的下一个词计算概率。比如输入"今天天气真",模型会计算"好"的概率是80%,"糟糕"的概率是20%,依此类推。

温度采样

在生成内容时,我们通过温度(Temperature)参数来控制输出的随机性(0~1或更高):

  • 低温度(如0.2):输出保守、确定性高(适合代码生成)
  • 高温度(如0.8):输出更随机、有创意(适合写故事)

示例:

typescript 复制代码
// 低温度 → 输出更集中 → 输出 "2"
model.generate("1+1=", { temperature: 0.2 });   // 输出 "2"

// 高温度 → 可能输出 "2, 或者11?开玩笑的,是2啦!(这都是概率性的结果)"
model.generate("1+1=", { temperature: 0.8 }); // 可能是 "2" 也可能是 "11"

Top-p采样

除了温度之外,Top-p采样也是一个重要的控制参数,它决定了模型在选择下一个词时会考虑概率总和达到p的候选词。

假设模型预测下一个词时, 的概率是0.6,很好的概率是 0.2,非常好的概率是0.1。如果我们设置p=0.8,那么模型只会从很好这两个词中选择(因为它们的概率和为0.8),而不会考虑非常好。这种方法可以帮助模型在保持输出质量的同时,避免生成一些低概率(可能不太合适)的词

如何与大模型沟通

我们站在用户视角,写好提示词只需要掌握一个公式:

提示词 = 定义角色 + 背景信息 + 任务目标 + 输出要求

  1. 定义角色:明确告诉AI它应该扮演什么角色,比如'你是一个资深的前端开发工程师'。这样可以让AI从特定的专业角度思考问题。
  2. 背景信息:提供必要的上下文信息,如项目背景、技术栈、已有代码等。这些信息能帮助AI更准确地理解问题场景。
  3. 任务目标:清晰地描述你想要完成什么,可以是具体的编码任务、代码优化、问题诊断等。目标越明确,AI的回答就越精准。
  4. 输出要求:指定期望的输出格式、代码风格、注释要求等。这能确保AI的回答符合你的具体需求,比如'请用TypeScript实现,并添加详细注释'。

提示工程

零样本提示(Zero-shot Prompting)

零样本提示是最基础的提示方法,直接告诉模型要做什么,不需要提供示例。

prompt = 优化下面的代码性能: 直接让模型优化代码

javascript 复制代码
function fibonacci(n) {
  if (n <= 1) return n;
  return fibonacci(n-1) + fibonacci(n-2);
}`;

少样本提示(Few-shot Prompting)

通过提供一些示例来引导模型,让它理解任务模式。

通过示例引导模型进行代码注释 prompt = 请按照下面的示例格式为代码添加注释: function add(a, b) { // 接收两个数字参数 return a + b; // 返回它们的和 }

javascript 复制代码
// 需要注释的代码:
function multiply(x, y) {
  return x * y;
}`;

思维链(Chain-of-Thought)

引导模型一步步思考问题,适合复杂的编程任务。

引导模型逐步思考代码重构 prompt = `请一步步思考如何重构这段代码 思考步骤:

  1. 首先,分析代码的主要功能
  2. 找出代码中的重复模式
  3. 考虑使用现代JavaScript特性
  4. 提出重构方案
  5. 实现重构后的代码;
javascript 复制代码
function processData(data) {
  let result = [];
  for(let i = 0; i < data.length; i++) {
    if(data[i].type === 'A') {
      result.push(data[i].value * 2);
    } else if(data[i].type === 'B') {
      result.push(data[i].value * 3);
    }
  }
  return result;
}

角色扮演(Role Playing)

让模型扮演特定角色,比如代码审查者、性能优化专家等。

让模型扮演代码审查者 prompt = `你是一个经验丰富的前端代码审查者,请审查下面的React组件代码,重点关注:

  1. 性能优化
  2. 最佳实践
  3. 潜在的内存泄漏
  4. 代码可维护性
tsx 复制代码
function UserList({ users }) {
  const [selectedUser, setSelectedUser] = useState(null);
  
  useEffect(() => {
    const handler = () => console.log('window resized');
    window.addEventListener('resize', handler);
  }, []);

  return (
    <div>
      {users.map(user => (
        <div onClick={() => setSelectedUser(user)}>
          {user.name}
        </div>
      ))}
    </div>
  );
}`;

这里只提到了基本的几项提示技术,算是抛砖引玉。我们可以通过提示工程指南

参考

相关推荐
黄智勇18 分钟前
xlsx-handlebars 一个用于处理 XLSX 文件 Handlebars 模板的 Rust 库,支持多平台使
前端
brzhang1 小时前
为什么 OpenAI 不让 LLM 生成 UI?深度解析 OpenAI Apps SDK 背后的新一代交互范式
前端·后端·架构
brzhang2 小时前
OpenAI Apps SDK ,一个好的 App,不是让用户知道它该怎么用,而是让用户自然地知道自己在做什么。
前端·后端·架构
井柏然3 小时前
前端工程化—实战npm包深入理解 external 及实例唯一性
前端·javascript·前端工程化
IT_陈寒3 小时前
Redis 高性能缓存设计:7个核心优化策略让你的QPS提升300%
前端·人工智能·后端
井柏然4 小时前
从 npm 包实战深入理解 external 及实例唯一性
前端·javascript·前端工程化
羊锦磊4 小时前
[ vue 前端框架 ] 基本用法和vue.cli脚手架搭建
前端·vue.js·前端框架
brzhang4 小时前
高通把Arduino买了,你的“小破板”要变“AI核弹”了?
前端·后端·架构
她说..4 小时前
通过git拉取前端项目
java·前端·git·vscode·拉取代码
智能化咨询4 小时前
玩转ClaudeCode:通过Chrome DevTools MCP实现高级调试与反反爬策略
前端·chrome·chrome devtools