Merge pull request #1506 from CyC2018/add-learning-paths
Add learning paths
@@ -8,9 +8,9 @@
|
||||
</div>
|
||||
<br>
|
||||
|
||||
| 算法 | 操作系统 | 网络 |面向对象| 数据库 | Java |系统设计| 工具 | 后记 |
|
||||
| :---: | :----: | :---: | :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| [:pencil2:](#pencil2-算法) | [:computer:](#computer-操作系统) | [:cloud:](#cloud-网络) | [:art:](#art-面向对象) | [:floppy_disk:](#floppy_disk-数据库) |[:coffee:](#coffee-java)| [:bulb:](#bulb-系统设计) |[:wrench:](#wrench-工具)| [:memo:](#memo-后记)|
|
||||
| 学习路线 | 算法 | 操作系统 | 网络 |面向对象| 数据库 | Java |系统设计| 工具 | 后记 |
|
||||
| :---: | :---: | :----: | :---: | :----: | :----: | :----: | :----: | :----: | :----: |
|
||||
| [:rocket:](#rocket-学习路线) | [:pencil2:](#pencil2-算法) | [:computer:](#computer-操作系统) | [:cloud:](#cloud-网络) | [:art:](#art-面向对象) | [:floppy_disk:](#floppy_disk-数据库) |[:coffee:](#coffee-java)| [:bulb:](#bulb-系统设计) |[:wrench:](#wrench-工具)| [:memo:](#memo-后记)|
|
||||
|
||||
<br>
|
||||
|
||||
@@ -20,6 +20,15 @@
|
||||
|
||||
<br>
|
||||
|
||||
## :rocket: 学习路线
|
||||
|
||||
每条路线把笔记按天排好,每天 1~2 小时:读一段笔记,回答几道面试中的真实问题,做一个动手练习;后三条路线每天还有一道算法题。
|
||||
|
||||
- [零基础](https://github.com/CyC2018/CS-Notes/blob/master/notes/学习路线%20-%20零基础.md):没有学过计算机课程时从这里开始,用一次外卖下单讲清程序、操作系统、网络、数据库和数据结构,不需要会编程;
|
||||
- [Java 后端](https://github.com/CyC2018/CS-Notes/blob/master/notes/学习路线%20-%20Java%20后端.md):会 Java 语法以后,系统准备后端面试,依次学 Java、MySQL、Redis、网络、操作系统、Spring、分布式和系统设计;
|
||||
- [大模型应用开发](https://github.com/CyC2018/CS-Notes/blob/master/notes/学习路线%20-%20大模型应用开发.md):准备 RAG、Agent 方向的岗位,从 Transformer 的原理学到 Agent 和工程实践;
|
||||
- [面试冲刺](https://github.com/CyC2018/CS-Notes/blob/master/notes/学习路线%20-%20面试冲刺.md):两三周后就要面试时,每天复习 3 个最常考的知识点。
|
||||
|
||||
## :pencil2: 算法
|
||||
|
||||
- [剑指 Offer 题解](https://github.com/CyC2018/CS-Notes/blob/master/notes/剑指%20Offer%20题解%20-%20目录.md)
|
||||
|
||||
|
After Width: | Height: | Size: 210 KiB |
|
After Width: | Height: | Size: 240 KiB |
|
After Width: | Height: | Size: 202 KiB |
|
After Width: | Height: | Size: 173 KiB |
|
After Width: | Height: | Size: 173 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 162 KiB |
|
After Width: | Height: | Size: 215 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 231 KiB |
|
After Width: | Height: | Size: 198 KiB |
|
After Width: | Height: | Size: 211 KiB |
@@ -0,0 +1,436 @@
|
||||
# 学习路线 - 大模型应用开发
|
||||
<!-- GFM-TOC -->
|
||||
* [学习路线 - 大模型应用开发](#学习路线---大模型应用开发)
|
||||
* [一、说明](#一说明)
|
||||
* [二、开始之前](#二开始之前)
|
||||
* [三、每天的安排](#三每天的安排)
|
||||
* [四、大模型基础](#四大模型基础)
|
||||
* [第 1 天:Token 与 Transformer](#第-1-天token-与-transformer)
|
||||
* [第 2 天:注意力机制](#第-2-天注意力机制)
|
||||
* [第 3 天:生成、KV Cache 与采样](#第-3-天生成kv-cache-与采样)
|
||||
* [第 4 天:训练过程](#第-4-天训练过程)
|
||||
* [第 5 天:微调与量化](#第-5-天微调与量化)
|
||||
* [第 6 天:幻觉与推理模型](#第-6-天幻觉与推理模型)
|
||||
* [五、提示词与上下文](#五提示词与上下文)
|
||||
* [第 7 天:提示词与结构化输出](#第-7-天提示词与结构化输出)
|
||||
* [第 8 天:上下文工程](#第-8-天上下文工程)
|
||||
* [六、检索增强生成](#六检索增强生成)
|
||||
* [第 9 天:RAG 的流程、文档解析与切片](#第-9-天rag-的流程文档解析与切片)
|
||||
* [第 10 天:Embedding 与向量索引](#第-10-天embedding-与向量索引)
|
||||
* [第 11 天:向量数据库、混合检索与重排](#第-11-天向量数据库混合检索与重排)
|
||||
* [第 12 天:Top-K 与查询改写](#第-12-天top-k-与查询改写)
|
||||
* [第 13 天:RAG 的评测与扩展](#第-13-天rag-的评测与扩展)
|
||||
* [七、Agent](#七agent)
|
||||
* [第 14 天:Agent 与工具调用](#第-14-天agent-与工具调用)
|
||||
* [第 15 天:意图识别与规划](#第-15-天意图识别与规划)
|
||||
* [第 16 天:记忆与多轮对话](#第-16-天记忆与多轮对话)
|
||||
* [第 17 天:MCP 与 Skills](#第-17-天mcp-与-skills)
|
||||
* [第 18 天:多 Agent 与 Harness](#第-18-天多-agent-与-harness)
|
||||
* [第 19 天:开发框架、可靠性与评测](#第-19-天开发框架可靠性与评测)
|
||||
* [八、工程实践](#八工程实践)
|
||||
* [第 20 天:流式输出、成本与部署](#第-20-天流式输出成本与部署)
|
||||
* [第 21 天:稳定性与安全](#第-21-天稳定性与安全)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
|
||||
## 一、说明
|
||||
|
||||
适合会一门编程语言(Python 或 Java)、准备大模型应用开发面试的读者,每天约 1~1.5 小时。动手部分需要一个兼容 OpenAI 接口的模型服务(例如 DeepSeek)或本地的 Qwen2.5 小模型;学过 Java 后端路线的读者可以跳过算法题。
|
||||
|
||||
每天先读完阅读范围,再不看笔记回答自测题,答完打开链接核对。选读可以跳过。
|
||||
|
||||
## 二、开始之前
|
||||
|
||||
本路线不讲语法。动手部分大多用 Python,开始前先确认能独立写出下面 5 个程序:
|
||||
|
||||
1. 调用 https://api.github.com/repos/CyC2018/CS-Notes ,解析返回的 JSON,打印 stargazers_count;
|
||||
2. 读取一个 JSON Lines 文件(每行一个订单,含 user_id 和 amount),统计每个用户的订单数和总金额,写入 JSON 文件;
|
||||
3. 把一段长文本切成不超过 200 字的片段,只在句号处切分;
|
||||
4. 用列表保存对话历史,只保留最近 10 条消息;
|
||||
5. 请求超时时重试,最多 3 次,每次等待的时间翻倍。
|
||||
|
||||
写不出来的,先补对应的语法:HTTP 请求与 JSON、文件读写、字符串、列表、异常与循环。用 Java 写同样的程序也可以。
|
||||
|
||||
## 三、每天的安排
|
||||
|
||||
| 天 | 主题 | 阅读 | 算法 |
|
||||
| :-: | --- | --- | --- |
|
||||
| | **大模型基础** | | |
|
||||
| [1](#第-1-天token-与-transformer) | Token 与 Transformer | 大模型应用:Token 与分词~Transformer 结构 | 1. 两数之和 |
|
||||
| [2](#第-2-天注意力机制) | 注意力机制 | 大模型应用:注意力机制 | 15. 三数之和 |
|
||||
| [3](#第-3-天生成kv-cache-与采样) | 生成、KV Cache 与采样 | 大模型应用:自回归生成与 KV Cache~采样参数 | 3. 无重复字符的最长子串 |
|
||||
| [4](#第-4-天训练过程) | 训练过程 | 大模型应用:训练过程 | 206. 反转链表 |
|
||||
| [5](#第-5-天微调与量化) | 微调与量化 | 大模型应用:微调~量化 | 21. 合并两个有序链表 |
|
||||
| [6](#第-6-天幻觉与推理模型) | 幻觉与推理模型 | 大模型应用:幻觉~推理模型 | 141. 环形链表 |
|
||||
| | **提示词与上下文** | | |
|
||||
| [7](#第-7-天提示词与结构化输出) | 提示词与结构化输出 | 大模型应用:提示词~结构化输出 | 146. LRU 缓存 |
|
||||
| [8](#第-8-天上下文工程) | 上下文工程 | 大模型应用:上下文工程 | 20. 有效的括号 |
|
||||
| | **检索增强生成** | | |
|
||||
| [9](#第-9-天rag-的流程文档解析与切片) | RAG 的流程、文档解析与切片 | 大模型应用:RAG 的流程~RAG 的切片 | 33. 搜索旋转排序数组 |
|
||||
| [10](#第-10-天embedding-与向量索引) | Embedding 与向量索引 | 大模型应用:Embedding 与相似度~向量索引 | 215. 数组中的第 K 个最大元素 |
|
||||
| [11](#第-11-天向量数据库混合检索与重排) | 向量数据库、混合检索与重排 | 大模型应用:向量数据库~重排 | 912. 排序数组(手写快速排序) |
|
||||
| [12](#第-12-天top-k-与查询改写) | Top-K 与查询改写 | 大模型应用:Top-K 与阈值~查询改写 | 102. 二叉树的层序遍历 |
|
||||
| [13](#第-13-天rag-的评测与扩展) | RAG 的评测与扩展 | 大模型应用:RAG 的评测与优化~多模态 RAG | 236. 二叉树的最近公共祖先 |
|
||||
| | **Agent** | | |
|
||||
| [14](#第-14-天agent-与工具调用) | Agent 与工具调用 | 大模型应用:Agent 是什么~Agent 与工作流 | 200. 岛屿数量 |
|
||||
| [15](#第-15-天意图识别与规划) | 意图识别与规划 | 大模型应用:意图识别与路由~Agent 的规划 | 46. 全排列 |
|
||||
| [16](#第-16-天记忆与多轮对话) | 记忆与多轮对话 | 大模型应用:Agent 的记忆~多轮对话 | 121. 买卖股票的最佳时机 |
|
||||
| [17](#第-17-天mcp-与-skills) | MCP 与 Skills | 大模型应用:MCP~Skills | 70. 爬楼梯 |
|
||||
| [18](#第-18-天多-agent-与-harness) | 多 Agent 与 Harness | 大模型应用:多 Agent~Harness | 53. 最大子数组和 |
|
||||
| [19](#第-19-天开发框架可靠性与评测) | 开发框架、可靠性与评测 | 大模型应用:开发框架~可靠性与评测 | 5. 最长回文子串 |
|
||||
| | **工程实践** | | |
|
||||
| [20](#第-20-天流式输出成本与部署) | 流式输出、成本与部署 | 大模型应用:流式输出~推理服务部署 | 300. 最长递增子序列 |
|
||||
| [21](#第-21-天稳定性与安全) | 稳定性与安全 | 大模型应用:稳定性~大模型应用的安全 | 25. K 个一组翻转链表 |
|
||||
|
||||
## 四、大模型基础
|
||||
|
||||
### 第 1 天:Token 与 Transformer
|
||||
|
||||
Token 是模型处理文本的单位,也是计费和上下文长度的单位。Transformer 一节先看整体结构,再看参数分布在哪里;混合专家可以略读。
|
||||
|
||||
阅读:《大模型应用》从[Token 与分词](大模型应用.md#token-与分词)读到[Transformer 结构](大模型应用.md#transformer-结构)。
|
||||
|
||||
自测:
|
||||
|
||||
1. Transformer 的结构是怎样的?(见[整体结构](大模型应用.md#1-整体结构))
|
||||
2. 大模型的参数主要分布在哪里?(见[参数都在哪里](大模型应用.md#2-参数都在哪里))
|
||||
3. 什么是 Token?同样的内容,中文和英文的 Token 数一样吗?(见[Token 与分词](大模型应用.md#token-与分词))
|
||||
|
||||
动手:下载 Qwen2.5-7B-Instruct 的 config.json,按[参数都在哪里](大模型应用.md#2-参数都在哪里)一节的方法算出一层中注意力和前馈网络的参数量,再与[附录 A16](大模型应用.md#a16-qwen25-7b-与-qwen3-30b-a3b-的参数量)对照。
|
||||
|
||||
算法(哈希表,简单):[1. 两数之和](https://leetcode.cn/problems/two-sum/),题解见[数组中两个数的和为给定值](Leetcode%20题解%20-%20哈希表.md#1-数组中两个数的和为给定值)。
|
||||
|
||||
### 第 2 天:注意力机制
|
||||
|
||||
注意力是 Transformer 的核心,对着“饿”的例子把 Q、K、V 的计算走一遍。FlashAttention 一节说明了长上下文时计算的瓶颈在哪里。
|
||||
|
||||
阅读:《大模型应用》的[注意力机制](大模型应用.md#注意力机制)。选读:[进阶:注意力机制](大模型应用%20-%20进阶.md#注意力机制)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 注意力的计算公式是什么?为什么要除以 √d?(见[注意力机制](大模型应用.md#注意力机制))
|
||||
2. 多头注意力有什么作用?(见[多头注意力](大模型应用.md#1-多头注意力))
|
||||
3. FlashAttention 解决了什么问题?(见[计算量与 FlashAttention](大模型应用.md#2-计算量与-flashattention))
|
||||
|
||||
动手:用 NumPy 实现单头注意力 softmax(QK<sup>T</sup> / √d) V,输入 3 个 Token、维度为 4 的随机矩阵,打印注意力权重并检查每一行的和是否为 1。
|
||||
|
||||
算法(双指针,中等):[15. 三数之和](https://leetcode.cn/problems/3sum/),题解见[三数之和](Leetcode%20题解%20-%20双指针.md#8-三数之和)。
|
||||
|
||||
### 第 3 天:生成、KV Cache 与采样
|
||||
|
||||
模型每次只生成一个 Token。KV Cache 避免重复计算前面 Token 的 K 和 V,也是推理时显存的主要来源。采样参数决定每一步怎样从概率分布中选出 Token。
|
||||
|
||||
阅读:《大模型应用》从[自回归生成与 KV Cache](大模型应用.md#自回归生成与-kv-cache)读到[采样参数](大模型应用.md#采样参数)。选读:[进阶:自回归生成与 KV Cache](大模型应用%20-%20进阶.md#自回归生成与-kv-cache)。
|
||||
|
||||
自测:
|
||||
|
||||
1. KV Cache 是什么?为什么能加快生成?(见[自回归生成与 KV Cache](大模型应用.md#自回归生成与-kv-cache))
|
||||
2. MHA、MQA 和 GQA 有什么区别?(见[自回归生成与 KV Cache](大模型应用.md#自回归生成与-kv-cache))
|
||||
3. temperature 和 top-p 分别控制什么?(见[采样参数](大模型应用.md#采样参数))
|
||||
|
||||
动手:按[显存:权重与 KV Cache](大模型应用.md#3-显存权重与-kv-cache)一节的方法,算出 Qwen2.5-7B 在 32K 上下文、同时处理 8 个请求时 KV Cache 占用的显存。
|
||||
|
||||
算法(滑动窗口,中等):[3. 无重复字符的最长子串](https://leetcode.cn/problems/longest-substring-without-repeating-characters/),题解见[剑指 Offer 48](48.%20最长不含重复字符的子字符串.md)。
|
||||
|
||||
### 第 4 天:训练过程
|
||||
|
||||
按预训练、监督微调、偏好对齐三个阶段读。PPO、DPO 和 GRPO 的区别是常见的追问,比较时看每种方法需要哪些模型。
|
||||
|
||||
阅读:《大模型应用》的[训练过程](大模型应用.md#训练过程)。选读:[进阶:训练过程](大模型应用%20-%20进阶.md#训练过程)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 大模型的训练分为哪几个阶段?(见[三个阶段](大模型应用.md#1-三个阶段))
|
||||
2. PPO、DPO 和 GRPO 有什么区别?(见[DPO](大模型应用.md#3-dpo)、[GRPO 与三者的选择](大模型应用.md#4-grpo-与三者的选择))
|
||||
3. RLHF 中的奖励模型是怎样训练的?(见[RLHF 与 PPO](大模型应用.md#2-rlhf-与-ppo))
|
||||
|
||||
动手:用 Python 按[DPO](大模型应用.md#3-dpo)一节的公式,对几组给定的 chosen 和 rejected 对数概率计算 DPO 损失,观察 β 取 0.1 和 0.5 时损失的变化。
|
||||
|
||||
算法(链表,简单):[206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/),题解见[链表反转](Leetcode%20题解%20-%20链表.md#2-链表反转)。
|
||||
|
||||
### 第 5 天:微调与量化
|
||||
|
||||
先判断什么时候该微调、什么时候用 RAG 或提示词就够了。LoRA 是最常用的微调方法;量化一节中 GPTQ 与 AWQ 可以略读。
|
||||
|
||||
阅读:《大模型应用》从[微调](大模型应用.md#微调)读到[量化](大模型应用.md#量化)。选读:[进阶:微调](大模型应用%20-%20进阶.md#微调)、[进阶:量化](大模型应用%20-%20进阶.md#量化)。
|
||||
|
||||
自测:
|
||||
|
||||
1. LoRA 的原理是什么?LoRA 和 QLoRA 有什么区别?(见[LoRA](大模型应用.md#3-lora)、[QLoRA 与全参数微调](大模型应用.md#4-qlora-与全参数微调))
|
||||
2. 什么时候用微调,什么时候用 RAG?(见[什么时候微调](大模型应用.md#1-什么时候微调))
|
||||
3. 什么是灾难性遗忘?怎样缓解?(见[灾难性遗忘](大模型应用.md#5-灾难性遗忘))
|
||||
|
||||
动手:按[附录 A17](大模型应用.md#a17-sft-样本的损失掩码)的方法,用 Qwen2.5 的对话模板构造一条 SFT 样本,标出哪些 Token 参与计算损失。
|
||||
|
||||
算法(链表,简单):[21. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/),题解见[归并两个有序的链表](Leetcode%20题解%20-%20链表.md#3-归并两个有序的链表)。
|
||||
|
||||
### 第 6 天:幻觉与推理模型
|
||||
|
||||
幻觉一节按定义、原因、缓解的顺序读,Agent 中的幻觉是调用工具后出现的新问题。推理模型一节很短,说明它和普通模型的区别。
|
||||
|
||||
阅读:《大模型应用》从[幻觉](大模型应用.md#幻觉)读到[推理模型](大模型应用.md#推理模型)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 什么是大模型的幻觉?为什么会产生?(见[什么是幻觉](大模型应用.md#1-什么是幻觉)、[为什么会产生](大模型应用.md#2-为什么会产生))
|
||||
2. 怎样检测和缓解幻觉?(见[检测与缓解](大模型应用.md#3-检测与缓解))
|
||||
3. Agent 调用工具时会出现哪些幻觉?(见[Agent 中的幻觉](大模型应用.md#4-agent-中的幻觉))
|
||||
|
||||
动手:阅读[附录 A19](大模型应用.md#a19-agent-中的工具幻觉),说出模型在什么情况下编造了工具或参数,以及校验是怎样拦住它的。
|
||||
|
||||
算法(链表,简单):[141. 环形链表](https://leetcode.cn/problems/linked-list-cycle/),题解见[判断链表是否存在环](Leetcode%20题解%20-%20双指针.md#6-判断链表是否存在环)。
|
||||
|
||||
综合题:用户问“我们公司的年假有几天”,模型回答了一个错误的天数:可能的原因有哪些?用提示词、RAG、微调分别能解决哪一部分?(见[为什么会产生](大模型应用.md#2-为什么会产生)、[什么时候微调](大模型应用.md#1-什么时候微调)、[检测与缓解](大模型应用.md#3-检测与缓解))
|
||||
|
||||
## 五、提示词与上下文
|
||||
|
||||
### 第 7 天:提示词与结构化输出
|
||||
|
||||
提示词一节讲写法。结构化输出讲怎样让程序可靠地解析模型的回答:约束解码从源头保证格式,解析失败时还要修复和重试。
|
||||
|
||||
阅读:《大模型应用》从[提示词](大模型应用.md#提示词)读到[结构化输出](大模型应用.md#结构化输出)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 怎样写好一个提示词?(见[提示词](大模型应用.md#提示词))
|
||||
2. 怎样让模型稳定地输出合法的 JSON?(见[约束解码](大模型应用.md#1-约束解码)、[输出无法解析时](大模型应用.md#2-输出无法解析时))
|
||||
3. 输出格式正确,内容就一定正确吗?(见[格式正确不等于内容正确](大模型应用.md#3-格式正确不等于内容正确))
|
||||
|
||||
动手:按[附录 A22](大模型应用.md#a22-模型输出-json-的修复校验与重试)的方法,让模型从一段订单描述中抽取 JSON,用 JSON Schema 校验,失败时把错误信息发回模型重试。
|
||||
|
||||
算法(设计,中等):[146. LRU 缓存](https://leetcode.cn/problems/lru-cache/),题解见[LRU](缓存.md#七lru)。
|
||||
|
||||
### 第 8 天:上下文工程
|
||||
|
||||
上下文工程关心每次调用放进什么、按什么顺序放。压缩是重点:什么时候压缩、怎样压缩,以及怎样保证关键事实不丢。
|
||||
|
||||
阅读:《大模型应用》的[上下文工程](大模型应用.md#上下文工程)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 上下文工程和提示词工程有什么区别?(见[上下文工程](大模型应用.md#上下文工程))
|
||||
2. 对话历史太长时怎样压缩?什么时候压缩?(见[压缩的方法与时机](大模型应用.md#3-压缩的方法与时机))
|
||||
3. 压缩后怎样保证关键事实不丢失?(见[压缩后不丢关键事实](大模型应用.md#4-压缩后不丢关键事实))
|
||||
|
||||
动手:按[附录 A4](大模型应用.md#a4-普通摘要与结构化摘要)的方法,对一段 20 轮的客服对话分别做普通摘要和结构化摘要,检查订单号、金额等关键事实是否保留。
|
||||
|
||||
算法(栈和队列,简单):[20. 有效的括号](https://leetcode.cn/problems/valid-parentheses/),题解见[用栈实现括号匹配](Leetcode%20题解%20-%20栈和队列.md#4-用栈实现括号匹配)。
|
||||
|
||||
综合题:一个客服机器人的每次请求都要带上系统提示词、工具定义、用户资料和最近的对话:怎样安排它们的顺序?Token 超出预算时先裁掉什么?(见[放什么、按什么顺序](大模型应用.md#1-放什么按什么顺序)、[Token 预算](大模型应用.md#2-token-预算)、[让前缀缓存命中](大模型应用.md#3-让前缀缓存命中))
|
||||
|
||||
## 六、检索增强生成
|
||||
|
||||
### 第 9 天:RAG 的流程、文档解析与切片
|
||||
|
||||
先看 RAG 的完整流程,再看前两步:文档解析和切片。切片的对比实验说明了不同切法对召回率的影响。
|
||||
|
||||
阅读:《大模型应用》从[RAG 的流程](大模型应用.md#流程)读到[RAG 的切片](大模型应用.md#切片)。
|
||||
|
||||
自测:
|
||||
|
||||
1. RAG 的完整流程是怎样的?(见[RAG 的流程](大模型应用.md#流程))
|
||||
2. 有哪些切片策略?切片大小怎么确定?(见[常用做法](大模型应用.md#2-常用做法)、[怎么确定切片大小](大模型应用.md#4-怎么确定切片大小))
|
||||
3. PDF 为什么难解析?表格怎么处理?(见[PDF 为什么难解析](大模型应用.md#1-pdf-为什么难解析)、[版面分析](大模型应用.md#2-版面分析))
|
||||
|
||||
动手:用 pypdf 提取一份 PDF 的文本,分别按固定长度和按段落切片,比较两种切片的边界是否切断了句子。
|
||||
|
||||
算法(二分查找,中等):[33. 搜索旋转排序数组](https://leetcode.cn/problems/search-in-rotated-sorted-array/)。
|
||||
|
||||
### 第 10 天:Embedding 与向量索引
|
||||
|
||||
Embedding 把文本变成向量,相似度检索靠它完成。向量索引回答数据量大时为什么要用近似检索,重点是 HNSW,IVF 与 PQ 可以略读。
|
||||
|
||||
阅读:《大模型应用》从[Embedding 与相似度](大模型应用.md#embedding-与相似度)读到[向量索引](大模型应用.md#向量索引)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 文本是怎样变成向量的?为什么用余弦相似度?(见[向量与余弦相似度](大模型应用.md#1-向量与余弦相似度))
|
||||
2. HNSW 的原理是什么?(见[HNSW](大模型应用.md#2-hnsw))
|
||||
3. 为什么需要近似最近邻检索?(见[为什么需要近似检索](大模型应用.md#1-为什么需要近似检索))
|
||||
|
||||
动手:用 bge-small-zh 等 Embedding 模型计算几组句子的余弦相似度,参照[附录 A1](大模型应用.md#a1-embedding-相似度与-bm25),找出一组语义相近但字面不同、向量检索优于关键词检索的例子。
|
||||
|
||||
算法(排序与堆,中等):[215. 数组中的第 K 个最大元素](https://leetcode.cn/problems/kth-largest-element-in-an-array/),题解见[Kth Element](Leetcode%20题解%20-%20排序.md#1-kth-element)。
|
||||
|
||||
### 第 11 天:向量数据库、混合检索与重排
|
||||
|
||||
向量数据库除了检索还要处理过滤和更新。混合检索和重排分别弥补向量检索的两个不足:精确的关键词匹配不准,相似度排序不够精细。
|
||||
|
||||
阅读:《大模型应用》从[向量数据库](大模型应用.md#向量数据库)读到[重排](大模型应用.md#重排)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 为什么要把向量检索和关键词检索结合起来?(见[混合检索](大模型应用.md#混合检索))
|
||||
2. 向量检索已经计算了相似度,为什么还要重排?(见[重排](大模型应用.md#重排))
|
||||
3. 向量数据库中的数据怎样更新和删除?(见[更新与删除](大模型应用.md#2-更新与删除))
|
||||
|
||||
动手:写一个函数,按[混合检索](大模型应用.md#混合检索)一节的 RRF 公式把 BM25 和向量检索返回的两个排序列表融合成一个,用几组数据验证结果。
|
||||
|
||||
算法(排序与堆,中等):[912. 排序数组(手写快速排序)](https://leetcode.cn/problems/sort-an-array/),题解见[快速排序](算法%20-%20排序.md#快速排序)。
|
||||
|
||||
### 第 12 天:Top-K 与查询改写
|
||||
|
||||
注意区分召回的 K 和放进提示词的 K。查询改写处理用户的提问与文档措辞不一致的情况。
|
||||
|
||||
阅读:《大模型应用》从[Top-K 与阈值](大模型应用.md#top-k-与阈值)读到[查询改写](大模型应用.md#查询改写)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 召回的 Top-K 和放进提示词的 Top-K 怎么定?(见[Top-K 与阈值](大模型应用.md#top-k-与阈值))
|
||||
2. 相似度阈值怎么设置?(见[相似度阈值](大模型应用.md#4-相似度阈值))
|
||||
3. 为什么要改写用户的查询?有哪些方法?(见[查询改写](大模型应用.md#查询改写))
|
||||
|
||||
动手:阅读[附录 A12](大模型应用.md#a12-切片方式top-k-与相似度阈值),说出切片方式、Top-K 和阈值分别怎样影响召回率和放进提示词的 Token 数。
|
||||
|
||||
算法(二叉树,中等):[102. 二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/),题解见[剑指 Offer 32.2](32.2%20把二叉树打印成多行.md)。
|
||||
|
||||
### 第 13 天:RAG 的评测与扩展
|
||||
|
||||
评测分检索和生成两部分,排查顺序一节把前几天的内容串成了一个排查流程。长上下文、GraphRAG 和多模态 RAG 可以略读。
|
||||
|
||||
阅读:《大模型应用》从[RAG 的评测与优化](大模型应用.md#评测与优化)读到[多模态 RAG](大模型应用.md#多模态-rag)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 怎样评测一个 RAG 系统?(见[检索指标](大模型应用.md#1-检索指标)、[生成指标](大模型应用.md#2-生成指标))
|
||||
2. RAG 回答得不好,按什么顺序排查?(见[排查顺序](大模型应用.md#4-排查顺序))
|
||||
3. 评测集怎样构建?(见[评测集](大模型应用.md#3-评测集))
|
||||
|
||||
动手:为 10 个问题标注相关的文档,用自己的检索结果计算 Recall@5 和 MRR,对照[检索指标](大模型应用.md#1-检索指标)一节核对公式。
|
||||
|
||||
算法(二叉树,中等):[236. 二叉树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/),题解见[二叉树的最近公共祖先](Leetcode%20题解%20-%20树.md#5-二叉树的最近公共祖先)。
|
||||
|
||||
综合题:公司内部的知识库问答上线后,用户反馈经常答非所问:按什么顺序排查?每一步看什么指标?分别可能改哪个环节?(见[排查顺序](大模型应用.md#4-排查顺序)、[检索指标](大模型应用.md#1-检索指标)、[切片](大模型应用.md#切片)、[重排](大模型应用.md#重排))
|
||||
|
||||
## 七、Agent
|
||||
|
||||
### 第 14 天:Agent 与工具调用
|
||||
|
||||
模型只输出文本,工具由应用代码执行,这是理解 Agent 的出发点。Agent 循环一节给出了完整的代码,最后一节说明什么时候不需要 Agent。
|
||||
|
||||
阅读:《大模型应用》从[Agent 是什么](大模型应用.md#agent-是什么)读到[Agent 与工作流](大模型应用.md#agent-与工作流)。
|
||||
|
||||
自测:
|
||||
|
||||
1. Agent 由哪些部分组成?(见[Agent 是什么](大模型应用.md#agent-是什么))
|
||||
2. Function Calling 的原理是什么?(见[工具调用](大模型应用.md#工具调用))
|
||||
3. Agent 和工作流有什么区别?分别适合什么场景?(见[Agent 与工作流](大模型应用.md#agent-与工作流))
|
||||
|
||||
动手:用兼容 OpenAI 接口的模型服务定义一个 query_order 工具(返回模拟的物流信息),按[Agent 循环](大模型应用.md#agent-循环)一节手写循环,完成“订单 1024 到哪了”的问答,打印每一轮的消息。
|
||||
|
||||
算法(回溯与搜索,中等):[200. 岛屿数量](https://leetcode.cn/problems/number-of-islands/),题解见[矩阵中的连通分量数目](Leetcode%20题解%20-%20搜索.md#2-矩阵中的连通分量数目)。
|
||||
|
||||
### 第 15 天:意图识别与规划
|
||||
|
||||
意图识别决定一个请求交给哪个流程处理。规划一节比较 ReAct、先规划后执行等方式,重点是各自适合什么任务。
|
||||
|
||||
阅读:《大模型应用》从[意图识别与路由](大模型应用.md#意图识别与路由)读到[Agent 的规划](大模型应用.md#规划)。
|
||||
|
||||
自测:
|
||||
|
||||
1. ReAct 是什么?为什么用它?(见[ReAct](大模型应用.md#2-react))
|
||||
2. 先规划后执行(Plan-and-Execute)和 ReAct 有什么区别?(见[先规划后执行](大模型应用.md#3-先规划后执行))
|
||||
3. 怎样保证意图识别和路由准确?(见[怎样保证路由准确](大模型应用.md#2-怎样保证路由准确))
|
||||
|
||||
动手:阅读[附录 A6](大模型应用.md#a6-意图路由的三种做法),比较三种路由做法的准确率、延迟和成本,说出各自适合的场景。
|
||||
|
||||
算法(回溯与搜索,中等):[46. 全排列](https://leetcode.cn/problems/permutations/),题解见[排列](Leetcode%20题解%20-%20搜索.md#5-排列)。
|
||||
|
||||
### 第 16 天:记忆与多轮对话
|
||||
|
||||
短期记忆就是放进上下文的对话历史,长期记忆要解决写什么、怎样检索和怎样更新。多轮对话一节处理指代、追问和话题切换。
|
||||
|
||||
阅读:《大模型应用》从[Agent 的记忆](大模型应用.md#记忆)读到[多轮对话](大模型应用.md#多轮对话)。
|
||||
|
||||
自测:
|
||||
|
||||
1. Agent 的短期记忆和长期记忆分别怎样实现?(见[短期记忆](大模型应用.md#1-短期记忆)、[长期记忆的写入](大模型应用.md#2-长期记忆的写入))
|
||||
2. 长期记忆中的信息过时或冲突时怎样处理?(见[更新、冲突与遗忘](大模型应用.md#4-更新冲突与遗忘))
|
||||
3. 多轮对话中的指代和省略怎样处理?(见[指代与省略](大模型应用.md#1-指代与省略))
|
||||
|
||||
动手:按[附录 A5](大模型应用.md#a5-长期记忆的提取与更新)的方法,让模型从对话中提取用户偏好写入长期记忆,用户改口后再更新这条记忆。
|
||||
|
||||
算法(动态规划,简单):[121. 买卖股票的最佳时机](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/),题解见[买卖股票最大的收益](Leetcode%20题解%20-%20贪心思想.md#5-买卖股票最大的收益)。
|
||||
|
||||
### 第 17 天:MCP 与 Skills
|
||||
|
||||
MCP 规定应用怎样接入外部的工具和数据,Skills 规定怎样按需加载完成某类任务的方法,两者常被放在一起比较。
|
||||
|
||||
阅读:《大模型应用》从[MCP](大模型应用.md#mcp)读到[Skills](大模型应用.md#skills)。
|
||||
|
||||
自测:
|
||||
|
||||
1. MCP 是什么?MCP 和 Function Calling 有什么区别?(见[MCP](大模型应用.md#mcp))
|
||||
2. Skill 和 MCP、Tool 有什么区别?(见[Skills](大模型应用.md#skills))
|
||||
|
||||
动手:按[附录 A24](大模型应用.md#a24-mcp-服务端的最小实现)写一个提供 query_order 工具的 MCP 服务端并调用它;再写一个 SKILL.md,描述“按模板写周报”的步骤。
|
||||
|
||||
算法(动态规划,简单):[70. 爬楼梯](https://leetcode.cn/problems/climbing-stairs/),题解见[爬楼梯](Leetcode%20题解%20-%20动态规划.md#1-爬楼梯)。
|
||||
|
||||
### 第 18 天:多 Agent 与 Harness
|
||||
|
||||
多 Agent 一节说明什么时候值得拆成多个 Agent。AI 编程助手和 Harness 讲的是怎样让 Agent 可靠地完成长任务。
|
||||
|
||||
阅读:《大模型应用》从[多 Agent](大模型应用.md#多-agent)读到[Harness](大模型应用.md#harness)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 什么时候需要多个 Agent?有哪些协作方式?(见[为什么要多个 Agent](大模型应用.md#1-为什么要多个-agent)、[协作方式](大模型应用.md#2-协作方式))
|
||||
2. 什么是 Agent Harness?由哪些部分组成?(见[Harness](大模型应用.md#harness))
|
||||
3. 长任务怎样在多次会话之间交接?(见[长任务的交接](大模型应用.md#3-长任务的交接))
|
||||
|
||||
动手:为自己的一个项目写一份给 AI 编程助手看的说明文件(例如 AGENTS.md),写明构建和测试命令、代码规范和提交前要运行的检查,对照[引导与反馈](大模型应用.md#2-引导与反馈)一节检查是否完整。
|
||||
|
||||
算法(动态规划,中等):[53. 最大子数组和](https://leetcode.cn/problems/maximum-subarray/),题解见[子数组最大的和](Leetcode%20题解%20-%20贪心思想.md#10-子数组最大的和)。
|
||||
|
||||
### 第 19 天:开发框架、可靠性与评测
|
||||
|
||||
开发框架一节说明 LangChain、LangGraph 和 Spring AI 各自解决什么问题。可靠性与评测讲工具失败时怎样容错,以及怎样评测一个 Agent。
|
||||
|
||||
阅读:《大模型应用》从[开发框架](大模型应用.md#开发框架)读到[可靠性与评测](大模型应用.md#可靠性与评测)。
|
||||
|
||||
自测:
|
||||
|
||||
1. LangChain 和 LangGraph 有什么区别?为什么用图来编排?(见[为什么用图编排](大模型应用.md#1-为什么用图编排))
|
||||
2. 工具调用失败时怎样容错?(见[容错](大模型应用.md#1-容错))
|
||||
3. 怎样评测一个 Agent?用模型做裁判有哪些偏差?(见[评测](大模型应用.md#2-评测)、[模型裁判的偏差](大模型应用.md#3-模型裁判的偏差))
|
||||
|
||||
动手:按[附录 A8](大模型应用.md#a8-langgraph-的-checkpoint-与人工确认)的方法,在退款节点之前加入人工确认,中断后从 checkpoint 恢复执行。
|
||||
|
||||
算法(动态规划,中等):[5. 最长回文子串](https://leetcode.cn/problems/longest-palindromic-substring/),题解见[最长回文子串](Leetcode%20题解%20-%20字符串.md#10-最长回文子串)。
|
||||
|
||||
综合题:用“订单 1024 到哪了”这个例子,说出客服 Agent 从收到问题到给出回答的完整过程:怎样识别意图、调用哪些工具、对话历史怎样保存、工具超时怎样处理。(见[Agent 循环](大模型应用.md#agent-循环)、[意图识别与路由](大模型应用.md#意图识别与路由)、[记忆](大模型应用.md#记忆)、[容错](大模型应用.md#1-容错))
|
||||
|
||||
## 八、工程实践
|
||||
|
||||
### 第 20 天:流式输出、成本与部署
|
||||
|
||||
流式输出决定用户多快看到第一个字。延迟与成本一节估算了一次 Agent 任务的费用;推理服务部署讲批处理、PagedAttention 和前缀缓存怎样提高吞吐。
|
||||
|
||||
阅读:《大模型应用》从[流式输出](大模型应用.md#流式输出)读到[推理服务部署](大模型应用.md#推理服务部署)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 流式输出是怎样实现的?SSE 的格式是怎样的?(见[SSE 的格式](大模型应用.md#1-sse-的格式))
|
||||
2. 怎样降低一次 Agent 任务的 Token 消耗?(见[让前缀缓存命中](大模型应用.md#3-让前缀缓存命中)、[减少 Token 消耗](大模型应用.md#4-减少-token-消耗))
|
||||
3. PagedAttention 解决了什么问题?(见[PagedAttention](大模型应用.md#4-pagedattention))
|
||||
|
||||
动手:用 curl -N 调用模型服务的流式接口,观察 data: 行的格式和最后的 [DONE],再用代码逐行读取并拼接出完整回答。
|
||||
|
||||
算法(动态规划,中等):[300. 最长递增子序列](https://leetcode.cn/problems/longest-increasing-subsequence/),题解见[最长递增子序列](Leetcode%20题解%20-%20动态规划.md#1-最长递增子序列)。
|
||||
|
||||
### 第 21 天:稳定性与安全
|
||||
|
||||
稳定性一节把超时、重试、限流和熔断用到模型调用上,做法与后端服务一致。安全一节的重点是限制模型能造成的后果。
|
||||
|
||||
阅读:《大模型应用》从[稳定性](大模型应用.md#稳定性)读到[大模型应用的安全](大模型应用.md#安全)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 调用模型接口时怎样设置超时和重试?(见[超时](大模型应用.md#1-超时)、[重试与指数退避](大模型应用.md#2-重试与指数退避))
|
||||
2. 流式输出中途断开怎么办?(见[流式输出中途断开](大模型应用.md#4-流式输出中途断开))
|
||||
3. 怎样防御提示词注入?(见[大模型应用的安全](大模型应用.md#安全))
|
||||
|
||||
算法(链表,困难):[25. K 个一组翻转链表](https://leetcode.cn/problems/reverse-nodes-in-k-group/),题解见[K 个一组翻转链表](Leetcode%20题解%20-%20链表.md#11-k-个一组翻转链表)。
|
||||
|
||||
综合题:设计一个企业内部的智能客服:用户的问题怎样分流到知识库问答和工具调用?怎样评测效果?怎样控制延迟和成本?出现提示词注入时怎样限制损失?(见[意图识别与路由](大模型应用.md#意图识别与路由)、[评测与优化](大模型应用.md#评测与优化)、[延迟与成本](大模型应用.md#延迟与成本)、[安全](大模型应用.md#安全))
|
||||
@@ -0,0 +1,266 @@
|
||||
# 学习路线 - 面试冲刺
|
||||
<!-- GFM-TOC -->
|
||||
* [学习路线 - 面试冲刺](#学习路线---面试冲刺)
|
||||
* [一、说明](#一说明)
|
||||
* [二、每天的安排](#二每天的安排)
|
||||
* [三、Java](#三java)
|
||||
* [第 1 天:集合](#第-1-天集合)
|
||||
* [第 2 天:线程池、锁与 volatile](#第-2-天线程池锁与-volatile)
|
||||
* [第 3 天:CAS、锁升级与 ThreadLocal](#第-3-天cas锁升级与-threadlocal)
|
||||
* [第 4 天:JVM](#第-4-天jvm)
|
||||
* [四、MySQL](#四mysql)
|
||||
* [第 5 天:索引](#第-5-天索引)
|
||||
* [第 6 天:事务、MVCC 与锁](#第-6-天事务mvcc-与锁)
|
||||
* [第 7 天:SQL 优化、日志与分库分表](#第-7-天sql-优化日志与分库分表)
|
||||
* [五、Redis 与缓存](#五redis-与缓存)
|
||||
* [第 8 天:Redis](#第-8-天redis)
|
||||
* [第 9 天:缓存问题与 Redis 集群](#第-9-天缓存问题与-redis-集群)
|
||||
* [六、网络与操作系统](#六网络与操作系统)
|
||||
* [第 10 天:TCP 与 HTTPS](#第-10-天tcp-与-https)
|
||||
* [第 11 天:进程、死锁与 I/O 多路复用](#第-11-天进程死锁与-io-多路复用)
|
||||
* [七、框架、分布式与大模型](#七框架分布式与大模型)
|
||||
* [第 12 天:Spring 与设计模式](#第-12-天spring-与设计模式)
|
||||
* [第 13 天:分布式锁、消息队列与秒杀](#第-13-天分布式锁消息队列与秒杀)
|
||||
* [第 14 天:大模型应用](#第-14-天大模型应用)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
|
||||
## 一、说明
|
||||
|
||||
适合两三周内就要面试、已经学过这些内容的读者,每天 1.5~2 小时,覆盖约 40 个核心考点,最后 1 天是大模型应用。应聘大模型应用岗位的读者,用[大模型应用开发](学习路线%20-%20大模型应用开发.md)每天的自测题复习。
|
||||
|
||||
每天先不看笔记,把 3 个自测题各口述 1~2 分钟,答得不完整的再读链接的小节;然后做两道算法题,每题限时 30 分钟。
|
||||
|
||||
## 二、每天的安排
|
||||
|
||||
| 天 | 主题 | 阅读 | 算法 |
|
||||
| :-: | --- | --- | --- |
|
||||
| | **Java** | | |
|
||||
| [1](#第-1-天集合) | 集合 | HashMap、ConcurrentHashMap、与 ArrayList 的比较 | 1. 两数之和、56. 合并区间 |
|
||||
| [2](#第-2-天线程池锁与-volatile) | 线程池、锁与 volatile | ThreadPoolExecutor、synchronized 与 ReentrantLock 的比较、内存模型三大特性、volatile | 88. 合并两个有序数组、15. 三数之和 |
|
||||
| [3](#第-3-天cas锁升级与-threadlocal) | CAS、锁升级与 ThreadLocal | 非阻塞同步、锁升级的过程、线程本地存储(Thread Local Storage) | 3. 无重复字符的最长子串、206. 反转链表 |
|
||||
| [4](#第-4-天jvm) | JVM | 运行时数据区域、判断一个对象是否可被回收、垃圾收集算法、CMS 收集器、G1 收集器、内存溢出与内存泄漏 | 21. 合并两个有序链表、141. 环形链表 |
|
||||
| | **MySQL** | | |
|
||||
| [5](#第-5-天索引) | 索引 | B+ Tree 原理、MySQL 索引、索引优化、索引失效 | 92. 反转链表 II、146. LRU 缓存 |
|
||||
| [6](#第-6-天事务mvcc-与锁) | 事务、MVCC 与锁 | 并发一致性问题、隔离级别、多版本并发控制、封锁类型、Next-Key Locks | 20. 有效的括号、33. 搜索旋转排序数组 |
|
||||
| [7](#第-7-天sql-优化日志与分库分表) | SQL 优化、日志与分库分表 | 查询性能优化、MySQL 的日志、分库分表 | 215. 数组中的第 K 个最大元素、912. 排序数组(手写快速排序) |
|
||||
| | **Redis 与缓存** | | |
|
||||
| [8](#第-8-天redis) | Redis | Redis 的数据类型、Redis 的数据结构、Redis 持久化、单线程为什么快 | 102. 二叉树的层序遍历、103. 二叉树的锯齿形层序遍历 |
|
||||
| [9](#第-9-天缓存问题与-redis-集群) | 缓存问题与 Redis 集群 | 缓存问题、Sentinel、Redis 分片 | 236. 二叉树的最近公共祖先、200. 岛屿数量 |
|
||||
| | **网络与操作系统** | | |
|
||||
| [10](#第-10-天tcp-与-https) | TCP 与 HTTPS | UDP 和 TCP 的特点、TCP 的三次握手、TCP 的四次挥手、TCP 可靠传输、HTTPS | 46. 全排列、121. 买卖股票的最佳时机 |
|
||||
| [11](#第-11-天进程死锁与-io-多路复用) | 进程、死锁与 I/O 多路复用 | 进程与线程的区别、协程、必要条件、死锁预防、I/O 复用 | 53. 最大子数组和、5. 最长回文子串 |
|
||||
| | **框架、分布式与大模型** | | |
|
||||
| [12](#第-12-天spring-与设计模式) | Spring 与设计模式 | AOP、Bean 的生命周期、循环依赖、事务失效、设计模式前言、实现 | 300. 最长递增子序列、1143. 最长公共子序列 |
|
||||
| [13](#第-13-天分布式锁消息队列与秒杀) | 分布式锁、消息队列与秒杀 | 分布式锁、消息队列的可靠性、秒杀系统、限流、降级与熔断 | 42. 接雨水、25. K 个一组翻转链表 |
|
||||
| [14](#第-14-天大模型应用) | 大模型应用 | RAG 的流程、Agent 是什么、工具调用、MCP | 23. 合并 K 个升序链表、72. 编辑距离 |
|
||||
|
||||
## 三、Java
|
||||
|
||||
### 第 1 天:集合
|
||||
|
||||
必学:[HashMap](Java%20容器.md#hashmap)、[ConcurrentHashMap](Java%20容器.md#concurrenthashmap)、[与 ArrayList 的比较](Java%20容器.md#2-与-arraylist-的比较)。
|
||||
|
||||
自测:
|
||||
|
||||
1. HashMap 的 put() 过程是怎样的?什么时候扩容、什么时候转成红黑树?(见[put 操作](Java%20容器.md#3-put-操作)、[扩容-基本原理](Java%20容器.md#5-扩容-基本原理)、[链表转红黑树](Java%20容器.md#8-链表转红黑树))
|
||||
2. ConcurrentHashMap 怎样保证线程安全?JDK 1.7 和 1.8 有什么区别?(见[JDK 1.8 的改动](Java%20容器.md#3-jdk-18-的改动))
|
||||
3. ArrayList 和 LinkedList 有什么区别?(见[与 ArrayList 的比较](Java%20容器.md#2-与-arraylist-的比较))
|
||||
|
||||
算法(哈希表,简单):[1. 两数之和](https://leetcode.cn/problems/two-sum/),题解见[数组中两个数的和为给定值](Leetcode%20题解%20-%20哈希表.md#1-数组中两个数的和为给定值)。
|
||||
|
||||
算法(数组,中等):[56. 合并区间](https://leetcode.cn/problems/merge-intervals/),题解见[合并区间](Leetcode%20题解%20-%20数组与矩阵.md#13-合并区间)。
|
||||
|
||||
### 第 2 天:线程池、锁与 volatile
|
||||
|
||||
必学:[ThreadPoolExecutor](Java%20并发.md#threadpoolexecutor)、[synchronized 与 ReentrantLock 的比较](Java%20并发.md#比较)、[内存模型三大特性](Java%20并发.md#内存模型三大特性)、[volatile](Java%20并发.md#volatile)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 线程池的核心参数有哪些?提交任务后是怎样执行的?(见[ThreadPoolExecutor](Java%20并发.md#threadpoolexecutor))
|
||||
2. synchronized 和 ReentrantLock 有什么区别?(见[synchronized 与 ReentrantLock 的比较](Java%20并发.md#比较))
|
||||
3. volatile 能保证什么,不能保证什么?(见[volatile](Java%20并发.md#volatile))
|
||||
|
||||
算法(双指针,简单):[88. 合并两个有序数组](https://leetcode.cn/problems/merge-sorted-array/),题解见[归并两个有序数组](Leetcode%20题解%20-%20双指针.md#5-归并两个有序数组)。
|
||||
|
||||
算法(双指针,中等):[15. 三数之和](https://leetcode.cn/problems/3sum/),题解见[三数之和](Leetcode%20题解%20-%20双指针.md#8-三数之和)。
|
||||
|
||||
### 第 3 天:CAS、锁升级与 ThreadLocal
|
||||
|
||||
必学:[非阻塞同步](Java%20并发.md#非阻塞同步)、[锁升级的过程](Java%20并发.md#锁升级的过程)、[线程本地存储(Thread Local Storage)](Java%20并发.md#2-线程本地存储thread-local-storage)。
|
||||
|
||||
自测:
|
||||
|
||||
1. CAS 的原理是什么?ABA 问题怎么解决?(见[CAS](Java%20并发.md#1-cas)、[ABA](Java%20并发.md#3-aba))
|
||||
2. synchronized 的锁升级过程是怎样的?(见[锁升级的过程](Java%20并发.md#锁升级的过程))
|
||||
3. ThreadLocal 为什么可能导致内存泄漏?(见[线程本地存储(Thread Local Storage)](Java%20并发.md#2-线程本地存储thread-local-storage))
|
||||
|
||||
算法(滑动窗口,中等):[3. 无重复字符的最长子串](https://leetcode.cn/problems/longest-substring-without-repeating-characters/),题解见[剑指 Offer 48](48.%20最长不含重复字符的子字符串.md)。
|
||||
|
||||
算法(链表,简单):[206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/),题解见[链表反转](Leetcode%20题解%20-%20链表.md#2-链表反转)。
|
||||
|
||||
### 第 4 天:JVM
|
||||
|
||||
必学:[运行时数据区域](Java%20虚拟机.md#一运行时数据区域)、[判断一个对象是否可被回收](Java%20虚拟机.md#判断一个对象是否可被回收)、[垃圾收集算法](Java%20虚拟机.md#垃圾收集算法)、[CMS 收集器](Java%20虚拟机.md#6-cms-收集器)、[G1 收集器](Java%20虚拟机.md#7-g1-收集器)、[内存溢出与内存泄漏](Java%20虚拟机.md#内存溢出与内存泄漏)。
|
||||
|
||||
自测:
|
||||
|
||||
1. JVM 的内存区域有哪些?(见[运行时数据区域](Java%20虚拟机.md#一运行时数据区域))
|
||||
2. CMS 和 G1 有什么区别?(见[G1 收集器](Java%20虚拟机.md#7-g1-收集器))
|
||||
3. 线上出现 OOM 怎样排查?(见[内存溢出与内存泄漏](Java%20虚拟机.md#内存溢出与内存泄漏))
|
||||
|
||||
算法(链表,简单):[21. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/),题解见[归并两个有序的链表](Leetcode%20题解%20-%20链表.md#3-归并两个有序的链表)。
|
||||
|
||||
算法(链表,简单):[141. 环形链表](https://leetcode.cn/problems/linked-list-cycle/),题解见[判断链表是否存在环](Leetcode%20题解%20-%20双指针.md#6-判断链表是否存在环)。
|
||||
|
||||
## 四、MySQL
|
||||
|
||||
### 第 5 天:索引
|
||||
|
||||
必学:[B+ Tree 原理](MySQL.md#b-tree-原理)、[MySQL 索引](MySQL.md#mysql-索引)、[索引优化](MySQL.md#索引优化)、[索引失效](MySQL.md#索引失效)。
|
||||
|
||||
自测:
|
||||
|
||||
1. MySQL 为什么用 B+ 树做索引?(见[B+ Tree 原理](MySQL.md#b-tree-原理))
|
||||
2. 什么是聚簇索引、回表和覆盖索引?(见[B+Tree 索引](MySQL.md#1-btree-索引)、[覆盖索引](MySQL.md#5-覆盖索引))
|
||||
3. 联合索引的最左前缀是什么?哪些情况下索引会失效?(见[多列索引](MySQL.md#2-多列索引)、[索引失效](MySQL.md#索引失效))
|
||||
|
||||
算法(链表,中等):[92. 反转链表 II](https://leetcode.cn/problems/reverse-linked-list-ii/)。
|
||||
|
||||
算法(设计,中等):[146. LRU 缓存](https://leetcode.cn/problems/lru-cache/),题解见[LRU](缓存.md#七lru)。
|
||||
|
||||
### 第 6 天:事务、MVCC 与锁
|
||||
|
||||
必学:[并发一致性问题](数据库系统原理.md#二并发一致性问题)、[隔离级别](数据库系统原理.md#四隔离级别)、[多版本并发控制](数据库系统原理.md#五多版本并发控制)、[封锁类型](数据库系统原理.md#封锁类型)、[Next-Key Locks](数据库系统原理.md#六next-key-locks)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 四种隔离级别分别解决了脏读、不可重复读、幻读中的哪些?(见[隔离级别](数据库系统原理.md#四隔离级别))
|
||||
2. MVCC 的原理是什么?(见[ReadView](数据库系统原理.md#readview))
|
||||
3. InnoDB 在可重复读级别下怎样避免幻读?(见[Next-Key Locks](数据库系统原理.md#next-key-locks))
|
||||
|
||||
算法(栈和队列,简单):[20. 有效的括号](https://leetcode.cn/problems/valid-parentheses/),题解见[用栈实现括号匹配](Leetcode%20题解%20-%20栈和队列.md#4-用栈实现括号匹配)。
|
||||
|
||||
算法(二分查找,中等):[33. 搜索旋转排序数组](https://leetcode.cn/problems/search-in-rotated-sorted-array/)。
|
||||
|
||||
### 第 7 天:SQL 优化、日志与分库分表
|
||||
|
||||
必学:[查询性能优化](MySQL.md#二查询性能优化)、[MySQL 的日志](MySQL.md#七日志)、[分库分表](MySQL.md#五切分)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 线上出现慢 SQL,怎样排查和优化?(见[慢查询的定位与优化](MySQL.md#慢查询的定位与优化))
|
||||
2. redo log、undo log 和 binlog 有什么区别?为什么需要两阶段提交?(见[MySQL 的日志](MySQL.md#七日志)、[两阶段提交](MySQL.md#两阶段提交))
|
||||
3. 分库分表之后会遇到哪些问题?(见[Sharding 存在的问题](MySQL.md#sharding-存在的问题))
|
||||
|
||||
算法(排序与堆,中等):[215. 数组中的第 K 个最大元素](https://leetcode.cn/problems/kth-largest-element-in-an-array/),题解见[Kth Element](Leetcode%20题解%20-%20排序.md#1-kth-element)。
|
||||
|
||||
算法(排序与堆,中等):[912. 排序数组(手写快速排序)](https://leetcode.cn/problems/sort-an-array/),题解见[快速排序](算法%20-%20排序.md#快速排序)。
|
||||
|
||||
综合题:订单表有 2000 万行,按用户查询最近的订单很慢,同时下单高峰期还出现了死锁:分别怎样分析和解决?(见[使用 Explain 进行分析](MySQL.md#使用-explain-进行分析)、[索引优化](MySQL.md#索引优化)、[MySQL 死锁](计算机操作系统%20-%20死锁.md#2-mysql-死锁))
|
||||
|
||||
## 五、Redis 与缓存
|
||||
|
||||
### 第 8 天:Redis
|
||||
|
||||
必学:[Redis 的数据类型](Redis.md#二数据类型)、[Redis 的数据结构](Redis.md#四数据结构)、[Redis 持久化](Redis.md#八持久化)、[单线程为什么快](Redis.md#单线程为什么快)。
|
||||
|
||||
自测:
|
||||
|
||||
1. Redis 有哪些数据类型?ZSET 的底层为什么用跳表?(见[Redis 的数据类型](Redis.md#二数据类型)、[跳跃表](Redis.md#跳跃表))
|
||||
2. RDB 和 AOF 有什么区别?(见[Redis 持久化](Redis.md#八持久化))
|
||||
3. Redis 为什么快?(见[单线程为什么快](Redis.md#单线程为什么快))
|
||||
|
||||
算法(二叉树,中等):[102. 二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/),题解见[剑指 Offer 32.2](32.2%20把二叉树打印成多行.md)。
|
||||
|
||||
算法(二叉树,中等):[103. 二叉树的锯齿形层序遍历](https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/),题解见[剑指 Offer 32.3](32.3%20按之字形顺序打印二叉树.md)。
|
||||
|
||||
### 第 9 天:缓存问题与 Redis 集群
|
||||
|
||||
必学:[缓存问题](缓存.md#四缓存问题)、[Sentinel](Redis.md#十二sentinel)、[Redis 分片](Redis.md#十三分片)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 缓存穿透、击穿和雪崩有什么区别?分别怎样解决?(见[缓存问题](缓存.md#四缓存问题))
|
||||
2. 怎样保证缓存与数据库的一致性?(见[缓存一致性](缓存.md#缓存一致性))
|
||||
3. 哨兵和 Redis Cluster 分别解决什么问题?(见[Sentinel](Redis.md#十二sentinel)、[Redis Cluster](Redis.md#redis-cluster))
|
||||
|
||||
算法(二叉树,中等):[236. 二叉树的最近公共祖先](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/),题解见[二叉树的最近公共祖先](Leetcode%20题解%20-%20树.md#5-二叉树的最近公共祖先)。
|
||||
|
||||
算法(回溯与搜索,中等):[200. 岛屿数量](https://leetcode.cn/problems/number-of-islands/),题解见[矩阵中的连通分量数目](Leetcode%20题解%20-%20搜索.md#2-矩阵中的连通分量数目)。
|
||||
|
||||
## 六、网络与操作系统
|
||||
|
||||
### 第 10 天:TCP 与 HTTPS
|
||||
|
||||
必学:[UDP 和 TCP 的特点](计算机网络%20-%20传输层.md#udp-和-tcp-的特点)、[TCP 的三次握手](计算机网络%20-%20传输层.md#tcp-的三次握手)、[TCP 的四次挥手](计算机网络%20-%20传输层.md#tcp-的四次挥手)、[TCP 可靠传输](计算机网络%20-%20传输层.md#tcp-可靠传输)、[HTTPS](HTTP.md#六https)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 三次握手和四次挥手的过程是怎样的?为什么 TIME_WAIT 要等 2MSL?(见[三次握手的原因](计算机网络%20-%20传输层.md#三次握手的原因)、[TIME_WAIT](计算机网络%20-%20传输层.md#time_wait))
|
||||
2. TCP 和 UDP 有什么区别?TCP 怎样保证可靠传输?(见[UDP 和 TCP 的特点](计算机网络%20-%20传输层.md#udp-和-tcp-的特点)、[TCP 可靠传输](计算机网络%20-%20传输层.md#tcp-可靠传输))
|
||||
3. HTTPS 的握手过程是怎样的?(见[TLS 握手](HTTP.md#tls-握手))
|
||||
|
||||
算法(回溯与搜索,中等):[46. 全排列](https://leetcode.cn/problems/permutations/),题解见[排列](Leetcode%20题解%20-%20搜索.md#5-排列)。
|
||||
|
||||
算法(动态规划,简单):[121. 买卖股票的最佳时机](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/),题解见[买卖股票最大的收益](Leetcode%20题解%20-%20贪心思想.md#5-买卖股票最大的收益)。
|
||||
|
||||
### 第 11 天:进程、死锁与 I/O 多路复用
|
||||
|
||||
必学:[进程与线程的区别](计算机操作系统%20-%20进程管理.md#3-区别)、[协程](计算机操作系统%20-%20进程管理.md#5-协程)、[必要条件](计算机操作系统%20-%20死锁.md#必要条件)、[死锁预防](计算机操作系统%20-%20死锁.md#死锁预防)、[I/O 复用](Socket.md#二io-复用)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 进程、线程和协程有什么区别?(见[进程与线程的区别](计算机操作系统%20-%20进程管理.md#3-区别)、[协程](计算机操作系统%20-%20进程管理.md#5-协程))
|
||||
2. 死锁的必要条件是什么?怎样避免?(见[必要条件](计算机操作系统%20-%20死锁.md#必要条件)、[死锁预防](计算机操作系统%20-%20死锁.md#死锁预防))
|
||||
3. select、poll 和 epoll 有什么区别?(见[select、poll 与 epoll 的比较](Socket.md#比较))
|
||||
|
||||
算法(动态规划,中等):[53. 最大子数组和](https://leetcode.cn/problems/maximum-subarray/),题解见[子数组最大的和](Leetcode%20题解%20-%20贪心思想.md#10-子数组最大的和)。
|
||||
|
||||
算法(动态规划,中等):[5. 最长回文子串](https://leetcode.cn/problems/longest-palindromic-substring/),题解见[最长回文子串](Leetcode%20题解%20-%20字符串.md#10-最长回文子串)。
|
||||
|
||||
## 七、框架、分布式与大模型
|
||||
|
||||
### 第 12 天:Spring 与设计模式
|
||||
|
||||
必学:[AOP](Spring.md#二aop)、[Bean 的生命周期](Spring.md#bean-的生命周期)、[循环依赖](Spring.md#循环依赖)、[事务失效](Spring.md#事务失效)、[设计模式前言](设计模式%20-%20目录.md#一前言)、[单例](设计模式%20%20-%20单例.md#实现)。
|
||||
|
||||
自测:
|
||||
|
||||
1. AOP 的原理是什么?JDK 动态代理和 CGLIB 有什么区别?(见[动态代理](Spring.md#动态代理))
|
||||
2. Spring 怎样解决循环依赖?(见[循环依赖](Spring.md#循环依赖))
|
||||
3. 单例模式有哪几种写法?项目中还用过哪些设计模式?(见[实现](设计模式%20%20-%20单例.md#实现)、[设计模式前言](设计模式%20-%20目录.md#一前言))
|
||||
|
||||
算法(动态规划,中等):[300. 最长递增子序列](https://leetcode.cn/problems/longest-increasing-subsequence/),题解见[最长递增子序列](Leetcode%20题解%20-%20动态规划.md#1-最长递增子序列)。
|
||||
|
||||
算法(动态规划,中等):[1143. 最长公共子序列](https://leetcode.cn/problems/longest-common-subsequence/),题解见[最长公共子序列](Leetcode%20题解%20-%20动态规划.md#1-最长公共子序列)。
|
||||
|
||||
### 第 13 天:分布式锁、消息队列与秒杀
|
||||
|
||||
必学:[分布式锁](分布式.md#一分布式锁)、[消息队列的可靠性](消息队列.md#三可靠性)、[秒杀系统](系统设计基础.md#六秒杀系统)、[限流、降级与熔断](系统设计基础.md#限流降级与熔断)。
|
||||
|
||||
自测:
|
||||
|
||||
1. 用 Redis 怎样实现分布式锁?有哪些问题?(见[Redis 的 SET NX 指令](分布式.md#redis-的-set-nx-指令))
|
||||
2. 怎样保证消息不丢失、不重复消费?(见[消息队列的可靠性](消息队列.md#三可靠性)、[接收端的可靠性](消息队列.md#接收端的可靠性))
|
||||
3. 秒杀系统怎样防止超卖?(见[防止超卖的几种做法](系统设计基础.md#防止超卖的几种做法))
|
||||
|
||||
算法(双指针,困难):[42. 接雨水](https://leetcode.cn/problems/trapping-rain-water/),题解见[接雨水](Leetcode%20题解%20-%20双指针.md#9-接雨水)。
|
||||
|
||||
算法(链表,困难):[25. K 个一组翻转链表](https://leetcode.cn/problems/reverse-nodes-in-k-group/),题解见[K 个一组翻转链表](Leetcode%20题解%20-%20链表.md#11-k-个一组翻转链表)。
|
||||
|
||||
综合题:设计一个秒杀系统:从页面、网关、服务、缓存、消息队列到数据库,每一层分别做什么来扛住流量、防止超卖?出现故障时怎样降级?(见[秒杀系统](系统设计基础.md#六秒杀系统)、[限流、降级与熔断](系统设计基础.md#限流降级与熔断)、[消息队列的可靠性](消息队列.md#三可靠性))
|
||||
|
||||
### 第 14 天:大模型应用
|
||||
|
||||
必学:[RAG 的流程](大模型应用.md#流程)、[Agent 是什么](大模型应用.md#agent-是什么)、[工具调用](大模型应用.md#工具调用)、[MCP](大模型应用.md#mcp)。
|
||||
|
||||
自测:
|
||||
|
||||
1. RAG 的流程是怎样的?(见[RAG 的流程](大模型应用.md#流程))
|
||||
2. Agent 由哪些部分组成?Function Calling 的原理是什么?(见[Agent 是什么](大模型应用.md#agent-是什么)、[工具调用](大模型应用.md#工具调用))
|
||||
3. MCP 和 Function Calling 有什么区别?(见[MCP](大模型应用.md#mcp))
|
||||
|
||||
算法(链表,困难):[23. 合并 K 个升序链表](https://leetcode.cn/problems/merge-k-sorted-lists/),题解见[合并 K 个有序链表](Leetcode%20题解%20-%20链表.md#13-合并-k-个有序链表)。
|
||||
|
||||
算法(动态规划,困难):[72. 编辑距离](https://leetcode.cn/problems/edit-distance/),题解见[编辑距离](Leetcode%20题解%20-%20动态规划.md#2-编辑距离)。
|
||||
@@ -1,12 +1,14 @@
|
||||
# 计算机操作系统
|
||||
|
||||
标为“选读”的篇目在面试中很少问到,时间有限时可以跳过。
|
||||
|
||||
- [概述](计算机操作系统%20-%20概述.md)
|
||||
- [进程管理](计算机操作系统%20-%20进程管理.md)
|
||||
- [进程管理 - 进阶](计算机操作系统%20-%20进程管理%20-%20进阶.md)
|
||||
- [死锁](计算机操作系统%20-%20死锁.md)
|
||||
- [内存管理](计算机操作系统%20-%20内存管理.md)
|
||||
- [设备管理](计算机操作系统%20-%20设备管理.md)
|
||||
- [链接](计算机操作系统%20-%20链接.md)
|
||||
- [设备管理](计算机操作系统%20-%20设备管理.md)(选读)
|
||||
- [链接](计算机操作系统%20-%20链接.md)(选读)
|
||||
|
||||
## 参考资料
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# 计算机网络
|
||||
|
||||
标为“选读”的篇目在面试中很少问到,时间有限时可以跳过。
|
||||
|
||||
- [概述](计算机网络%20-%20概述.md)
|
||||
- [物理层](计算机网络%20-%20物理层.md)
|
||||
- [物理层](计算机网络%20-%20物理层.md)(选读)
|
||||
- [链路层](计算机网络%20-%20链路层.md)
|
||||
- [网络层](计算机网络%20-%20网络层.md)
|
||||
- [传输层](计算机网络%20-%20传输层.md)
|
||||
|
||||