Hello-Agents 第三章 大语言模型基础 学习笔记
一、语言模型:从"猜词游戏"到"理解语义"
语言模型最根本的任务,其实特别像我们玩"词语接龙":给你前面几个词,让你猜下一个最可能是什么词。早期的模型,比如 N-gram,玩法很机械。它假设一个词的出现,只跟它前面紧挨着的一两个词有关(这叫马尔可夫假设)。比如在"我爱吃___"后面,它根据统计发现"苹果"出现的次数最多,就猜"苹果"。
这种方法简单直接,但问题很大:
- 记性差:只能看眼前一两个词,上下文长了就抓瞎。
- 死板:如果训练数据里没出现过"我爱吃榴莲",它就永远猜不到"榴莲",哪怕这两个词逻辑上完全合理。这就是泛化能力差。
为了解决"死板"的问题,研究者想到了用词向量(Word Embedding)。简单说,就是把每个词变成一个数学向量(一串数字)。神奇的是,在这个数字空间里,意思相近的词(比如"国王"和"女王")位置会靠得很近,甚至能算出"国王 - 男人 + 女人 ≈ 女王"这种关系。模型从此开始"理解"词义了。
但"记性差"的问题还在。于是就有了RNN(循环神经网络),它像人一样有了"短期记忆",能一边读句子一边把前面信息记下来。不过它的记忆会随着句子变长而模糊或爆炸(梯度消失/爆炸问题)。LSTM(长短时记忆网络) 作为RNN的升级版,加入了"门控"机制,像个小秘书一样,决定记住什么、忘记什么,从而记住了更长的信息。
然而,无论是RNN还是LSTM,处理句子都必须是串行的,一个字一个字地读,很慢。直到 Transformer 的出现,才真正引爆了革命。
二、Transformer:让模型"并行"阅读和"全局"思考
Transformer是整个现代大语言模型的基石。它的核心突破是自注意力机制和并行计算。
你可以把自注意力机制想象成:当模型读到句子中的一个词(比如"它")时,它会立刻让这个词和句子里的所有其他词(包括它自己)都"交流"一下,问问:"你们谁跟我关系最密切?谁对我理解自己最有帮助?" 然后根据"交流"的密切程度(计算出的权重),把所有词的信息综合起来,形成对这个词的新理解。这样,任何一个词都能直接获取到整个句子的全局信息,彻底解决了长距离依赖的问题。
正因为这种"全局交流"的特性,Transformer不用像RNN那样必须按顺序处理。它可以把整个句子一起输入,同时计算所有词之间的关系,实现了并行计算,训练速度飞快。
不过,自注意力机制本身不知道词的顺序。为了告诉模型"我爱妈妈"和"妈妈爱我"是不同的,Transformer引入了位置编码,给每个词的位置信息也编码成向量,加在词向量上。
最初的Transformer是编码器-解码器架构,像翻译团队:编码器负责完整理解原文,解码器根据这个理解来生成译文。
三、GPT与Decoder-Only:大道至简,只做"预测"
但OpenAI在搞GPT时,想法更纯粹:既然语言模型的核心就是"预测下一个词",那我们能不能只要解码器,不要编码器?
于是,Decoder-Only架构诞生了。它只保留了解码器部分,工作模式是自回归的:
- 给你一个开头:"今天天气..."
- 它预测下一个词,比如"很"。
- 把"很"加回去,变成"今天天气很",再预测下一个词"好"。
- 如此循环,生成完整句子。
为了保证在预测时不会"作弊"偷看后面的词,它使用了掩码自注意力,在计算时把当前词之后的所有词都遮住。
这种架构极其简洁,却异常强大。它完美契合了生成任务,成为了当今GPT、LLaMA等几乎所有主流大模型的标配。
四、如何与这个"大脑"打交道?
知道了大脑的构造,我们怎么使用它呢?有两个关键环节:
-
提示工程:怎么给模型"下指令"。就像和人沟通,指令越清晰,结果越靠谱。你可以直接问(Zero-shot),也可以给几个例子再让它学(Few-shot),或者引导它一步步推理(Chain-of-Thought)。模型还有一些"旋钮"可以调,比如温度:调低会让输出更确定、保守;调高会让输出更有创意、更多样。
-
分词:模型不认识字,只认识数字(Token)。所以我们需要把文本切成Token序列。直接按"字"或"词"切都有问题。现在主流用的是子词分词,比如BPE算法。它会把常见词(如"学习")保留为一个整体,把生僻词(如"Transformer")拆成有意义的子块(如"Transform"和"er")。这样既能控制词表大小,又能让模型理解新词。
五、模型的强大与局限
大模型的能力遵循缩放定律:一般来说,参数越多、数据越多、算力越大,模型性能就越强。这推动了模型规模的快速膨胀。
但它并非万能,有两大核心局限:
- 幻觉:它会一本正经地胡说八道,生成看似合理但完全错误的内容。这是因为它是根据概率生成文本,而不是访问事实数据库。
- 知识过时:它的知识截止于训练数据收集的那一刻,对之后的新事件一无所知。
因此,在用它构建智能体等应用时,必须设计机制来规避这些问题,比如让它在回答前先去外部知识库检索一下(RAG技术),或者让它调用计算器、搜索引擎等工具来获取实时准确信息。
总结一下
这一章像是拆解了一个魔法黑箱。大语言模型不是凭空出现的魔法,它的演进有清晰的逻辑:从简单的统计(N-gram)到理解语义(词向量),再到拥有记忆(RNN/LSTM),最终通过Transformer实现并行和全局理解的飞跃。而Decoder-Only架构则化繁为简,专注于"预测下一个词"这个核心任务。
理解这些,对我们后续设计智能体至关重要:我们知道怎么给它下指令(提示工程),知道它的输入如何被处理(分词),更清楚它的能力边界在哪里(幻觉、时效性),从而能更好地扬长避短,设计出可靠的系统。
好了,大脑的构造和原理基本清楚了,下一步就是学习如何用它来驱动一个能自主思考、行动的智能体了。
py
# 解决方法:
# 1. 安装依赖 pip install modelscope
# 2. 运行下载脚本
from modelscope import AutoTokenizer, AutoModelForCausalLM
# 这里填写你想存放模型的本地路径,比如 "./Qwen1.5-0.5B-Chat"
local_model = "./my_local_models/Qwen1.5-0.5B-Chat"
# 下载并保存分词器
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-0.5B-Chat", cache_dir=local_model)
tokenizer.save_pretrained(local_model)
# 下载并保存模型
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen1.5-0.5B-Chat", cache_dir=local_model)
model.save_pretrained(local_model)
print("模型下载完成!")
py
# code/chapter3/Qwen.py 调用本地模型
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
# 修改这里:直接指定本地文件夹的路径
model_path = "D:\\MyApp\\hello-agents\\my_local_models\\Qwen1.5-0.5B-Chat"
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using device: {device}")
# 直接从本地加载,不会再联网下载
tokenizer = AutoTokenizer.from_pretrained(model_path, local_files_only=True)
model = AutoModelForCausalLM.from_pretrained(model_path, local_files_only=True).to(
device
)
print("从本地加载模型完成!")
# 准备对话输入
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "你好,请介绍你自己。"},
]
# 使用分词器的模板格式化输入
text = tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)
# 编码输入文本
model_inputs = tokenizer([text], return_tensors="pt").to(device)
print("编码后的输入文本:")
print(model_inputs)
# 使用模型生成回答
# max_new_tokens 控制了模型最多能生成多少个新的Token
generated_ids = model.generate(model_inputs.input_ids, max_new_tokens=512)
# 将生成的 Token ID 截取掉输入部分
# 这样我们只解码模型新生成的部分
generated_ids = [
output_ids[len(input_ids) :]
for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]
# 解码生成的 Token ID
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
print("\n模型的回答:")
print(response)
习题解答
习题1:语言模型演进
1.1
请使用本章提供的迷你语料库(datawhale agent learns, datawhale agent works),计算句子 agent works 在Bigram模型下的概率。
解答 :
语料库为:datawhale agent learns, datawhale agent works(共6个词)。
计算 P(agent):agent 出现2次,总词数6次 => 2/6 ≈ 0.333
计算 P(works | agent):词对 agent works 出现1次,agent 出现2次 => 1/2 = 0.5
句子概率连乘:P(agent works) ≈ P(agent) _ P(works|agent) ≈ 0.333 _ 0.5 = 0.1665
1.2
N-gram模型的核心假设是马尔可夫假设。请解释这个假设的含义,以及N-gram模型存在哪些根本性局限?
解答:
马尔可夫假设含义:假设一个词出现的概率,只与它前面有限个(n-1个)词有关,而不是整个历史。这简化了计算,例如Bigram只依赖前一个词。
根本性局限:
- 数据稀疏性:如果词序列未在训练数据中出现,其概率估计为0,不合理(即使句子本身是合理的)。
- 泛化能力差:模型将词视为孤立符号,无法理解语义相似性。例如,它知道 agent learns 的概率,但无法将此知识泛化到语义相似的 robot learns 上。
1.3
神经网络语言模型(RNN/LSTM)和Transformer分别是如何克服N-gram模型局限的?它们各自的优势是什么?
解答:
神经网络语言模型(RNN/LSTM):
- 如何克服:引入词嵌入,将词表示为连续向量,使语义相似的词向量相近,解决了N-gram的"泛化能力差"问题。RNN/LSTM通过循环结构拥有"记忆",理论上可以处理任意长序列,突破了固定窗口限制。
- 优势:能捕捉语义和一定程度的长期依赖(尤其是LSTM)。
- 遗留问题:RNN/LSTM必须串行处理序列,计算效率低,且实际训练中仍难以处理非常长的依赖关系(梯度消失/爆炸)。
Transformer:
- 如何克服:核心是自注意力机制,允许序列中任意两个词直接"交互",彻底解决了长距离依赖问题。同时,这种计算是并行的,极大提升了训练效率。
- 优势 :
- 强大的长程建模能力:能直接捕捉全局依赖。
- 极高的训练效率:并行计算充分利用硬件。
- 可扩展性:为后续大规模预训练模型奠定了基础。
习题2:Transformer架构
2.1
自注意力机制(Self-Attention)的核心思想是什么?
解答 :
核心思想是让序列中的每个词,都能直接关注到序列中的所有其他词(包括自己),并根据关联程度(注意力权重)动态地聚合这些词的信息,来更新自身的表示。它模拟了人类理解句子时,根据上下文动态聚焦于不同部分的过程。
2.2
为什么Transformer能够并行处理序列,而RNN必须串行处理?位置编码(Positional Encoding)在其中起什么作用?
解答:
并行 vs 串行:RNN的循环结构决定了第t步的计算必须等待第t-1步的隐藏状态,因此是串行的。Transformer的自注意力机制中,所有词的查询、键、值矩阵可以同时计算,注意力权重和输出也可以并行算出,因此可以并行处理整个序列。
位置编码的作用:自注意力机制本身不具备位置信息(打乱词序,注意力计算结果不变)。位置编码为每个词嵌入加上一个代表其绝对和相对位置的向量,从而让模型感知词序,区分"我爱妈妈"和"妈妈爱我"。
2.3
Decoder-Only架构与完整的Encoder-Decoder架构有什么区别?为什么现在主流的大语言模型都采用Decoder-Only架构?
解答:
区别:
- Encoder-Decoder:包含两部分。编码器负责理解整个输入序列,将其编码为上下文表示;解码器基于该表示和已生成的部分,自回归地生成输出序列。适用于翻译、摘要等"理解-生成"任务。
- Decoder-Only:仅保留解码器部分。输入和输出都是文本序列,任务纯粹是自回归地预测下一个词。它将所有输入(包括提示和之前的生成)都视为需要继续的序列。
主流原因:
- 任务统一:将各种任务(问答、创作、代码生成)都转化为"给定上文,预测下文"的统一形式,架构简洁。
- 高效预训练:非常适合在大规模无标注文本上进行下一个词预测的预训练。
- 生成优势:其掩码自注意力机制天然适合自回归生成任务,保证了生成的连贯性。
- 实践成功:GPT系列的成功证明了这种架构在构建通用大语言模型上的强大能力。
习题3:文本分词
文本子词分词算法是大语言模型的一项关键技术,负责将文本转换为模型可处理的 token 序列。那为什么不能直接以"字符"或"单词"作为模型的输入单元?BPE(Byte Pair Encoding)算法解决了什么问题?
解答:
为什么不用字符:字符(如字母、汉字)数量少,无OOV问题,但语义单元太小。模型需要从大量字符组合中学习词义,效率低下,且难以捕捉词级语义。
为什么不用单词:单词作为单元语义明确,但会导致词表爆炸(词汇量巨大),且存在严重的未登录词(OOV)问题(如新词、专业术语、拼写变体)。
BPE算法解决的问题:BPE是一种子词分词算法,它通过折衷方案解决了上述矛盾:
- 平衡词表大小与语义:将常见词保留为完整token(如"agent"),将罕见词拆分为有意义的子词(如"tokenization" -> "token" + "ization")。
- 解决OOV问题:即使遇到新词,也能通过已知子词组合来表示和理解(如"ChatGPT" -> "Chat" + "G" + "PT")。
- 提升效率:在可控的词表大小下,让模型既能处理常见词,又能通过组合应对罕见词。
习题4:实践与分析(模型部署与交互)
4.1
按照本章的指导,在本地部署一个轻量级的开源模型(推荐Qwen3-0.6B),并尝试调整采样参数并观察其对输出的影响。
解答(实践指导与预期观察):
部署步骤:参考3.2.3节,使用 transformers 库加载 Qwen/Qwen1.5-0.5B-Chat(或类似小模型),编写对话生成代码。
调整参数与预期影响:
-
温度(Temperature):
- 温度=0.1:输出确定性高,重复性强,答案保守、准确。
- 温度=0.7:输出平衡,有一定创造性,通顺自然。
- 温度=1.2:输出随机性高,可能更发散、有创意,但也可能不连贯或偏离主题。
-
Top-p(核采样):
- top_p=0.9:从累积概率达90%的候选词中采样,输出多样且合理。
- top_p=0.3:仅从高概率核心词中采样,输出更确定、更可预测。
-
Top-k:
- top_k=50:只从概率最高的50个词中采样,排除长尾低概率词。
- top_k=1:退化为贪心搜索,每次选概率最高的词,输出完全确定但可能单调。
4.2
选择一个具体任务,设计并对比不同的提示策略对输出结果的效果差异。
解答(以"情感分类"任务为例):
任务:判断文本情感(正面/负面/中性)。
提示策略对比:
-
Zero-shot(零样本):
- 提示:"判断以下文本的情感:'这个产品简直太糟糕了。' 情感:"
- 效果:依赖模型已有知识,可能正确,但格式和倾向可能不稳定。
-
Few-shot(少样本,提供3个例子):
- 提示:"文本:服务很好。 情感:正面\n文本:电影很无聊。 情感:负面\n文本:杯子是蓝色的。 情感:中性\n文本:这个产品简直太糟糕了。 情感:"
- 效果:模型通过示例学习了任务格式和分类标准,输出更准确、格式更规范。
-
Chain-of-Thought(思维链):
- 提示:"请逐步分析以下文本的情感。文本:'这个产品简直太糟糕了,完全浪费钱。' 首先,找出表达观点的关键词:'糟糕'、'浪费钱'。这些词通常表达不满。因此,情感倾向是:"
- 效果:引导模型显式推理,对于复杂或隐含情感的文本,能提高分析质量和可信度。
4.3
从性能、成本、可控性、隐私等维度比较闭源模型和开源模型。
解答:
| 维度 | 闭源模型 (如GPT-4, Gemini) | 开源模型 (如LLaMA, Qwen) |
|---|---|---|
| 性能 | 通常领先,尤其在复杂推理、指令遵循和安全性上。 | 第一梯队已接近顶级闭源模型,中等规模模型性能足够应对许多任务。 |
| 成本 | API调用按Token计费,长期使用成本高,但无需硬件投入。 | 一次部署,无限使用。需要自有硬件(或云服务器),初期有投入,长期成本可能更低。 |
| 可控性 | 低。只能通过API交互,无法修改模型内部、调整架构或训练过程。 | 极高。可完全控制模型权重、微调、裁剪、量化,集成到任何系统。 |
| 隐私 | 数据需发送至厂商服务器,存在隐私泄露风险,不适合敏感数据。 | 数据完全本地处理,隐私安全有保障,符合严格合规要求。 |
| 定制化 | 有限,主要依赖提示工程和有限的微调服务。 | 可深度定制,可用领域数据继续训练,打造专属模型。 |
4.4
如果你要构建一个企业级的客服智能体,你会选择哪种类型的模型?需要考虑哪些因素?
解答:
模型类型选择:倾向于选择开源模型。
关键考虑因素:
- 数据隐私与安全:客服涉及用户订单、个人信息等敏感数据,必须本地部署开源模型以确保数据不出域。
- 成本可控:企业级客服请求量大,使用闭源API长期成本不可控。自建开源模型虽然初期有硬件和运维成本,但长期更经济。
- 定制化需求:需要将企业知识库、产品文档、客服话术注入模型,开源模型支持RAG和微调,能更好地适应专业领域。
- 可控性与可靠性:需要保证服务稳定,避免因闭源API服务波动或政策变化影响业务。开源模型自主可控。
- 性能要求:客服任务以信息检索、多轮对话、意图分类为主,当前优秀的开源模型(如Qwen、LLaMA系列)已能很好胜任,不一定需要顶尖但昂贵的闭源模型。
综合建议:选择一款性能足够、中文能力强的开源模型(如Qwen)进行本地化部署,结合RAG接入企业知识库,并通过微调优化对话风格。
习题5:模型幻觉
5.1
请选择其中一种缓解幻觉的方法,说明其工作原理和适用场景。
解答(选择:检索增强生成 - RAG):
工作原理:
- 检索:当用户提问时,系统首先从外部、可信的知识库(如企业文档、维基百科、专业数据库)中检索与问题相关的文档或片段。
- 增强:将检索到的相关文本作为"证据"或"上下文",与用户的原始问题一起拼接,构成一个新的、信息丰富的提示。
- 生成:将增强后的提示输入给大语言模型,要求它基于提供的上下文来生成答案。模型被引导"引用"证据,从而减少凭空编造。
适用场景:
- 需要事实准确性的领域:如客服、技术支持、法律、医疗问答。
- 回答需要最新信息的问题:知识库可以随时更新,弥补模型静态知识的不足。
- 涉及私有或特定领域知识的任务:如企业内部知识查询、产品文档问答。
5.2
调研前沿的研究和论文,是否还有其他的缓解模型幻觉的方法,他们又有哪些改进和优势?
解答(其他方法举例):
推理时自我验证(Self-Checking/Consistency Decoding):
- 方法:让模型生成多个可能的答案或推理路径,然后让模型自己对这些答案进行一致性检查、逻辑验证或重新评分,选择最可信的一个。
- 改进与优势:不依赖外部资源,利用模型自身能力进行纠错。例如,让模型先生成答案,再反问自己"这个答案的依据是什么?"来发现矛盾。
知识图谱增强:
- 方法:将结构化知识图谱与LLM结合。模型生成答案时,可以查询知识图谱中的实体关系和事实,确保答案在逻辑网络中是成立的。
- 改进与优势:比纯文本RAG更具逻辑性和结构性,能更好地处理复杂推理和关系查询,幻觉更少。
强化学习从人类反馈(RLHF)及其扩展:
- 方法:通过人类对模型输出的偏好排序来训练奖励模型,再用强化学习微调LLM,使其输出更符合人类价值观、更真实。
- 改进:如直接偏好优化(DPO),简化了RLHF流程,更稳定高效。宪法AI(CAI)让模型根据一套原则进行自我批判和修正。
- 优势:从模型对齐的源头进行优化,使模型"内在"更倾向于生成真实、有用的内容。
习题6:论文辅助阅读智能体设计
6.1
你会选择哪个模型作为智能体设计时的基座模型?选择时需要考虑哪些因素?
解答:
基座模型选择:会选择开源模型,具体为Qwen系列或LLaMA系列中参数规模适中(如7B-14B)、上下文窗口长(如128K以上)的版本。
考虑因素:
- 上下文长度:处理长论文是核心需求,必须支持超长上下文。
- 学术理解能力:模型在科学文献、代码、逻辑推理上的预训练表现要好。
- 开源与可控性:便于集成RAG、微调等组件,构建完整pipeline。
- 成本与效率:在有限的算力下取得最佳性能平衡。
6.2
如何设计提示词来引导模型更好地理解学术论文?学术论文通常很长,可能超过模型的上下文窗口限制,你会如何解决这个问题?
解答:
提示词设计:
- 赋予角色:"你是一位专业的学术研究助理,擅长深度分析和总结。"
- 结构化指令:明确任务步骤,如"请先总结研究背景、方法、核心结果和结论;然后提取关键词;最后回答以下具体问题..."。
- 要求引用:"请严格基于论文内容回答,必要时指明出自第几章节或图表。"
解决长文本限制:
分层处理与摘要:
- 先用模型或传统方法对论文进行分块(按章节、摘要、引言、方法、结果、讨论)。
- 对每个块生成关键摘要。
- 将摘要集合和用户的具体问题输入模型,进行最终分析。这样只需处理摘要,而非全文。
结合RAG系统:
- 将整篇论文切片并向量化,存入向量数据库。
- 当用户提问时,检索与问题最相关的几个文本片段。
- 将问题+相关片段(而非全文)输入模型生成答案。这是最实用和主流的方法。
6.3
学术研究是严谨的,这意味着我们需要确保智能体生成的信息是准确客观忠于原文的。你认为系统中加入哪些设计能够更好的实现这一需求?
解答:
-
核心:检索增强生成(RAG):这是基石。所有回答必须基于从论文原文中检索出的片段,并在提示中强制要求模型引用来源。
-
事实核查与一致性验证:
- 设计一个验证模块。当智能体生成一个事实性陈述(如"实验准确率为95%")时,自动反向检索原文,确认该数字是否存在及上下文是否一致。
- 对于总结性内容,可以要求模型生成后,再让其以"挑错者"身份重新审视,检查是否有歪曲或添加。
-
不确定性表达:提示模型,如果对某些信息不确定或在原文中找不到明确支持,应如实说明"根据提供内容,未明确提及...",而不是猜测。
-
多轮交互与确认:对于关键结论,智能体可以主动与用户确认:"我理解您的问题是...,根据第X节内容,我总结为...,您是否同意此总结,或需要关注其他部分?"
-
人工审核回路:在关键流程中设置节点,将智能体的输出(如论文总结)提供给用户审阅,用户可提供反馈("这里不准确"),系统利用此反馈进行迭代优化(Reflection范式)。
项目地址:hello-agents