Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
304 lines (273 loc) · 50.7 KB
/
Copy pathindex.html
File metadata and controls
304 lines (273 loc) · 50.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>小P的猫舍 - 爱玩毛线爱贴贴</title><meta name="author" content="LittlePyx"><meta name="copyright" content="LittlePyx"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="小P的学习、研究、生活记录">
<meta property="og:type" content="website">
<meta property="og:title" content="小P的猫舍">
<meta property="og:url" content="https://littlepyx.github.io/index.html">
<meta property="og:site_name" content="小P的猫舍">
<meta property="og:description" content="小P的学习、研究、生活记录">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://littlepyx.github.io/img/kamuyi.jpg">
<meta property="article:author" content="LittlePyx">
<meta property="article:tag" content="博客、技术、记录">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://littlepyx.github.io/img/kamuyi.jpg"><script type="application/ld+json">{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "小P的猫舍",
"url": "https://littlepyx.github.io/"
}</script><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://littlepyx.github.io/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css"><script>
(() => {
const saveToLocal = {
set: (key, value, ttl) => {
if (!ttl) return
const expiry = Date.now() + ttl * 86400000
localStorage.setItem(key, JSON.stringify({ value, expiry }))
},
get: key => {
const itemStr = localStorage.getItem(key)
if (!itemStr) return undefined
const { value, expiry } = JSON.parse(itemStr)
if (Date.now() > expiry) {
localStorage.removeItem(key)
return undefined
}
return value
}
}
window.btf = {
saveToLocal,
getScript: (url, attr = {}) => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val))
script.onload = script.onreadystatechange = () => {
if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve()
}
script.onerror = reject
document.head.appendChild(script)
}),
getCSS: (url, id) => new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) link.id = id
link.onload = link.onreadystatechange = () => {
if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve()
}
link.onerror = reject
document.head.appendChild(link)
}),
addGlobalFn: (key, fn, name = false, parent = window) => {
if (!false && key.startsWith('pjax')) return
const globalFn = parent.globalFn || {}
globalFn[key] = globalFn[key] || {}
globalFn[key][name || Object.keys(globalFn[key]).length] = fn
parent.globalFn = globalFn
}
}
const activateDarkMode = () => {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
const activateLightMode = () => {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
}
}
btf.activateDarkMode = activateDarkMode
btf.activateLightMode = activateLightMode
const theme = saveToLocal.get('theme')
theme === 'dark' ? activateDarkMode() : theme === 'light' ? activateLightMode() : null
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide')
}
const detectApple = () => {
if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) {
document.documentElement.classList.add('apple')
}
}
detectApple()
})()
</script><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: {"path":"/search.xml","preload":false,"top_n_per_article":2,"unescape":true,"languages":{"hits_empty":"未找到符合您查询的内容:${query}","hits_stats":"共找到 ${hits} 篇文章"}},
translate: undefined,
highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false,"highlightFullpage":false,"highlightMacStyle":false},
copy: {
success: '复制成功',
error: '复制失败',
noSupport: '浏览器不支持'
},
relativeDate: {
homepage: false,
post: false
},
runtime: '',
dateSuffix: {
just: '刚刚',
min: '分钟前',
hour: '小时前',
day: '天前',
month: '个月前'
},
copyright: undefined,
lightbox: 'null',
Snackbar: undefined,
infinitegrid: {
js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid/dist/infinitegrid.min.js',
buttonText: '加载更多'
},
isPhotoFigcaption: false,
islazyloadPlugin: false,
isAnchor: false,
percent: {
toc: true,
rightside: false,
},
autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: '小P的猫舍',
isHighlightShrink: false,
isToc: false,
pageType: 'home'
}</script><link rel="stylesheet" href="/css/custom.css"><link rel="stylesheet" href="/vendor/katex/katex.min.css"><link rel="stylesheet" href="/css/happy-llm.css"><meta name="generator" content="Hexo 5.4.2"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img text-center"><img src="/img/kamuyi.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/ loading='lazy'></div><div class="site-data text-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">18</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">43</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">4</div></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/algorithm/"><i class="fa-fw fas fa-code"></i><span> 算法笔记</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-user"></i><span> 关于</span></a></div></div></div></div><div class="page" id="body-wrap"><header class="full_page" id="page-header" style="background-image: url(/img/archive.webp);"><nav id="nav"><span id="blog-info"><a class="nav-site-title" href="/"><span class="site-name">小P的猫舍</span></a></span><div id="menus"><div id="search-button"><span class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></span></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/algorithm/"><i class="fa-fw fas fa-code"></i><span> 算法笔记</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-user"></i><span> 关于</span></a></div></div><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav><div id="site-info"><h1 id="site-title">小P的猫舍</h1><div id="site-subtitle"><span id="subtitle"></span></div><div id="site_social_icons"><a class="social-icon" href="https://github.com/LittlePyx" target="_blank" title="GitHub"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:627875273@qq.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a><a class="social-icon" href="/algorithm/" target="_blank" title="算法笔记"><i class="fas fa-code"></i></a></div></div><div id="scroll-down"><i class="fas fa-angle-down scroll-down-effects"></i></div></header><main class="layout" id="content-inner"><div class="recent-posts nc" id="recent-posts"><div class="recent-post-items"><div class="recent-post-item"><div class="post_cover left"><a href="/2026/11/02/happy-llm-08-agentic-rl/" title="Agentic RL:GRPO、OPD 与工具轨迹训练"><img class="post-bg" src="/img/happy-llm-agentic-rl-natgeo-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Agentic RL:GRPO、OPD 与工具轨迹训练" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/11/02/happy-llm-08-agentic-rl/" title="Agentic RL:GRPO、OPD 与工具轨迹训练">Agentic RL:GRPO、OPD 与工具轨迹训练</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-11-02T02:10:00.000Z" title="发表于 2026-11-02 10:10:00">2026-11-02</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/AI-Agent/">AI Agent</a></span></div><div class="content">封面:珠峰营地附近的山峰倒影 · 摄影 Jansen Wong / National Geographic My Shot 第七章把模型接到了检索和工具环境中,参数仍然可以保持不变。本章进一步讨论:保存模型实际走过的轨迹,用结果或教师反馈判断哪些动作值得鼓励,再通过梯度更新模型。环境执行循环和参数更新循环由此连接起来。 本篇对应 Happy-LLM 第八章的固定快照,覆盖 GRPO、OPD、Search-R1 与 ReTool。沿用第四章的策略、概率比和参考模型概念,补清多轮轨迹中的信号来源、token 归属和实现约定。计算器和检查脚本使用人工数据,没有运行远程训练或报告模型效果。 1. 先把一次交互写成训练样本 1.1 状态、动作、观察与奖励 对自回归模型,给定历史 hth_tht,下一个 token 是动作 ata_tat,策略为 πθ(at∣ht)\pi_\theta(a_t\mid h_t)πθ(at∣ht)。若生成了一段工具请求,应用解析并执行它,再把环境观察 ooo 加入后续历史。 内容 来源 在训练中的角色 问题和系统约束 数据集或应用 初...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/2026/11/02/happy-llm-07-evaluation-rag-agent/" title="大模型应用:评测、RAG 与 Agent 的工程闭环"><img class="post-bg" src="/img/happy-llm-applications-natgeo-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="大模型应用:评测、RAG 与 Agent 的工程闭环" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/11/02/happy-llm-07-evaluation-rag-agent/" title="大模型应用:评测、RAG 与 Agent 的工程闭环">大模型应用:评测、RAG 与 Agent 的工程闭环</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-11-02T02:00:00.000Z" title="发表于 2026-11-02 10:00:00">2026-11-02</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/AI-Agent/">AI Agent</a></span></div><div class="content">封面:雨后波浪谷的倒影 · 摄影 Nicholas Roemmelt / National Geographic Traveler Photo Contest 模型可以生成答案,但应用还要解决三个问题:答案怎样验收,需要的资料从哪里来,以及模型提出的操作怎样真正执行。评测、RAG 和 Agent 分别处理这些问题,它们最终要在同一个系统里配合。 本篇对应 Happy-LLM 第七章。先确定任务和指标,再构建检索与执行链路,最后用失败样本定位问题。文中的小型案例均为教学构造。 1. 先定义任务成功,再比较模型 1.1 模型能力与系统能力 以“查询设备故障原因,并在需要时创建维修工单”为例,完整任务可能包括识别设备、检索手册、根据证据判断故障、补问缺失信息和调用工单接口。模型回答看起来合理,只覆盖其中一部分。 层次 评测对象 可观察结果 模型 在给定输入下生成什么 答案正确性、格式、指令遵循 检索 能否找到所需证据 相关文档是否进入候选、排序是否靠前 执行 工具是否按预期运行 参数合法性、返回状态、实际状态变化 端到端 用户目标是否完成 成功率、成本、延迟...</div></div></div><div class="recent-post-item"><div class="post_cover left"><a href="/2026/10/12/happy-llm-04-training-and-alignment/" title="大语言模型:规模、训练阶段与工程取舍"><img class="post-bg" src="/img/happy-llm-training-natgeo-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="大语言模型:规模、训练阶段与工程取舍" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/10/12/happy-llm-04-training-and-alignment/" title="大语言模型:规模、训练阶段与工程取舍">大语言模型:规模、训练阶段与工程取舍</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-10-12T02:00:00.000Z" title="发表于 2026-10-12 10:00:00">2026-10-12</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/AI-Agent/">AI Agent</a></span></div><div class="content">封面:安第斯山脉 Llullaillaco 火山上空的星轨 · 摄影 Maria Stenzel / National Geographic Image Collection 第三章解释了模型怎样预测 token。这一章进一步讨论:同样采用下一 token 预测,为什么训练规模、语料和后续训练不同,会得到使用体验差异很大的模型?从一个基础模型到能稳定回答指令、调用工具的模型,中间还需要哪些工作? 本篇对应 Happy-LLM 第四章。先确定训练阶段分别优化什么,再讨论算力、数据与显存如何约束训练,最后回到能力评估和应用选择。 1. 从语言建模到指令模型 1.1 “大”体现在哪些方面 LLM 仍是语言模型:给定上下文,输出词表上的条件概率分布。以自回归模型为例: pθ(x1:T)=∏t=1Tpθ(xt∣x<t).p_\theta(x_{1:T})=\prod_{t=1}^{T}p_\theta(x_t\mid x_{<t}). pθ(x1:T)=t=1∏Tpθ(xt∣x<t). 扩大模型并没有改变这条概率分解。变化主要是参数量、训练 token 数、...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/2026/09/21/happy-llm-03-pretrained-language-models/" title="预训练语言模型:训练目标、架构与任务适配"><img class="post-bg" src="/img/happy-llm-plm-natgeo-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="预训练语言模型:训练目标、架构与任务适配" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/09/21/happy-llm-03-pretrained-language-models/" title="预训练语言模型:训练目标、架构与任务适配">预训练语言模型:训练目标、架构与任务适配</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-09-21T02:00:00.000Z" title="发表于 2026-09-21 10:00:00">2026-09-21</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/AI-Agent/">AI Agent</a></span></div><div class="content">封面:冰岛群山与潮水中的倒影 · 摄影 Ramiro Torrents / National Geographic Your Shot 第二章解释了 Transformer 怎样计算一个位置的表示。使用同样的注意力和前馈层,模型却可以做不同的事:根据左右文补词、根据前缀续写,或读取一段文本后生成另一段文本。差别来自位置之间能否互相读取、训练时要求预测什么,以及最后使用哪一种输出。 本篇对应 Happy-LLM 第三章。先把训练目标与网络架构分开,再看 BERT 怎样学习双向表示、T5 怎样生成目标序列、GPT 怎样续写,最后讨论这些设计如何影响训练数据、显存和任务适配。 1. 预训练在学习什么 1.1 从文本中构造监督信号 第一章已经介绍:模型把 token ID 映射成输入向量,再计算上下文表示,最终通过输出层得到预测分布。预训练要做的,是在大量样本上调整这些共享参数,使预测更准确。 例如,把“请 检查 电源”中的“电源”遮住,原来的“电源”就是标签;把“请 检查”作为前缀,“电源”就是下一个 token 的标签。两种任务都能直接从原文生成训练样本,这就是自监督学习。 对一个...</div></div></div><div class="recent-post-item"><div class="post_cover left"><a href="/2026/09/12/happy-llm-02-transformer-engineering/" title="Transformer:注意力、网络结构与自回归推理"><img class="post-bg" src="/img/happy-llm-transformer-natgeo-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Transformer:注意力、网络结构与自回归推理" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/09/12/happy-llm-02-transformer-engineering/" title="Transformer:注意力、网络结构与自回归推理">Transformer:注意力、网络结构与自回归推理</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-09-12T02:10:00.000Z" title="发表于 2026-09-12 10:10:00">2026-09-12</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/AI-Agent/">AI Agent</a></span></div><div class="content">封面:犹他州 Owachomo 天然石桥与银河 · 摄影 Jim Richardson / National Geographic 一段文本经过 tokenizer 和 embedding 查表,得到一个形状为 [B,T,D][B,T,D][B,T,D] 的张量。BBB 是批量大小,TTT 是 token 数,DDD 是每个位置的表示维度。此时每个向量仍来自固定查表;同一个 token 在不同句子里的基础表示相同。 Transformer 的主要工作,是逐层让这些表示结合上下文,再将它们映射为任务需要的输出。理解它既要看单次注意力怎样计算,也要看注意力与其他子层如何组成网络,以及训练、生成时的信息范围如何变化。 本篇对应 Happy-LLM 第二章,以稠密 Transformer 为主,并延伸到自回归推理与缓存。 贯穿全文的数据结构输入是 token ID;embedding 将它变为逐位置向量;注意力混合位置之间的信息;前馈层变换每个位置的特征;堆叠后的表示再通过输出层产生标签或词表分布。 1. 输入表示与位置 1.1 token ID 如何进入网络 令输入 ID 张量为 I...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/2026/09/12/happy-llm-01-nlp-for-agent/" title="NLP 基础:文本编码、表示学习与语言模型"><img class="post-bg" src="/img/happy-llm-nlp-natgeo-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="NLP 基础:文本编码、表示学习与语言模型" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/09/12/happy-llm-01-nlp-for-agent/" title="NLP 基础:文本编码、表示学习与语言模型">NLP 基础:文本编码、表示学习与语言模型</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-09-12T02:00:00.000Z" title="发表于 2026-09-12 10:00:00">2026-09-12</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/AI-Agent/">AI Agent</a></span></div><div class="content">封面:冰岛冰川河流入海 · 摄影 Andro Loria / National Geographic Your Shot 同一句“设备无法联网”,可以作为搜索查询、故障类别的输入,也可以成为一段回答的开头。文字没有变,计算机需要完成的运算却不同:有时比较文档,有时预测标签,有时估计接下来可能出现的 token。 这些任务共用一些基础:把文本编码为离散符号,为符号建立数值表示,再利用上下文完成预测。编码保留了什么信息、表示丢掉了什么信息、训练目标奖励什么行为,会一直影响到最终结果。 本篇以 Happy-LLM 第一章 为起点,补充文本编码、表示学习与检索之间的联系。 文本处理中的四个层次字符与 token 决定输入单元;向量表示让符号可以参与计算;语言模型学习上下文中的概率关系;分类、检索和生成把这些能力用于不同输出。 1. 文本进入模型之前:字符、token 与词表 1.1 字符编码与模型编码是两回事 文本文件首先是一串字节。UTF-8 等字符编码规定字节怎样对应 Unicode 字符;tokenizer 则规定这段文本怎样对应模型词表中的 token ID。UTF-8 解码正...</div></div></div><div class="recent-post-item"><div class="post_cover left"><a href="/2026/09/08/composing-programs-chapter-1-to-4-roadmap/" title="从函数到分布式系统:Composing Programs 第一至第四章总路线图"><img class="post-bg" src="/img/composing-programs-higher-order-functions-nature-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="从函数到分布式系统:Composing Programs 第一至第四章总路线图" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/09/08/composing-programs-chapter-1-to-4-roadmap/" title="从函数到分布式系统:Composing Programs 第一至第四章总路线图">从函数到分布式系统:Composing Programs 第一至第四章总路线图</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-09-08T02:00:00.000Z" title="发表于 2026-09-08 10:00:00">2026-09-08</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/Computer-Science/">Computer Science</a></span></div><div class="content"> 这四章围绕程序的组织方式逐步展开:怎样组合函数、管理数据和状态、解释代码,以及协调多个任务。 这些内容通过抽象联系起来。函数封装计算步骤,数据接口隔离内部表示,解释器实现语言规则,执行框架负责调度与协作。调用者通过接口使用这些能力,实现细节则由各自的模块负责。 PROGRAMMING ABSTRACTION 从函数组合到多机协作 按章节梳理知识,再沿着变化、状态和契约回看它们的联系。 1. 先看全局:四章分别扩大了哪一层边界 CHAPTER 01 行为抽象 把函数当作值,组合新的计算规则 CHAPTER 02 数据与对象 通过接口使用数据,隔离内部表示的变化 CHAPTER 03 程序与语义 把源码变成数据,再由运行时赋予含义 CHAPTER 04 数据流与系统 把计算推迟、拆分,并交给多个执行单元 各章的重点和用途如下: 章节 主要概念 设计用途 第一章 一等函数、高阶函数与闭包 传递和组合行为,复用...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/2026/09/02/composing-programs-parallel-mapreduce/" title="计算如何同时展开:并发、并行、MapReduce 与共享状态"><img class="post-bg" src="/img/composing-programs-parallel-mapreduce-nature-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="计算如何同时展开:并发、并行、MapReduce 与共享状态" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/09/02/composing-programs-parallel-mapreduce/" title="计算如何同时展开:并发、并行、MapReduce 与共享状态">计算如何同时展开:并发、并行、MapReduce 与共享状态</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-09-02T05:00:00.000Z" title="发表于 2026-09-02 13:00:00">2026-09-02</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/Computer-Science/">Computer Science</a></span></div><div class="content">前三篇逐步解决了数据怎样按需流动、计算目标怎样声明,以及不同机器怎样通过消息可靠协作。最后还剩一个性能问题:当任务之间可以独立推进时,怎样让它们同时执行,并且不破坏结果正确性? 本篇整合教材 4.7 Distributed Data Processing 与 4.8 Parallel Computing,沿着下面的顺序展开: 本篇主线 先保证模型和正确性,再谈扩展速度 01 · MODEL识别等待还是计算区分并发、并行、分布式与 Python 执行模型 02 · SAFETY约束共享可变状态理解 race,再选择 lock、queue 或分区所有权 03 · SCALE拆分、聚合并测量MapReduce、数据倾斜与真实加速比 1. Concurrency、Parallelism 与 Distribution 回答不同问题 这三个词经常被混用,但它们关注的不是同一件事。 概念 核心问题 是否要求同一时刻执行 是否要求多台机器 Concurrency(并发) 多个任务怎样在同一段时间内推进 不要求 不要...</div></div></div><div class="recent-post-item"><div class="post_cover left"><a href="/2026/09/02/composing-programs-distributed-reliability/" title="机器之间如何协作:消息、协议与分布式失败"><img class="post-bg" src="/img/composing-programs-distributed-reliability-nature-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="机器之间如何协作:消息、协议与分布式失败" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/09/02/composing-programs-distributed-reliability/" title="机器之间如何协作:消息、协议与分布式失败">机器之间如何协作:消息、协议与分布式失败</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-09-02T04:00:00.000Z" title="发表于 2026-09-02 12:00:00">2026-09-02</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/Computer-Science/">Computer Science</a></span></div><div class="content">前两篇都可以在单个进程中完成:Iterator 让数据按需流动,声明式系统负责选择执行过程。当数据、服务和计算节点分布在不同机器上时,程序需要面对一个新的事实:机器之间没有共同的函数栈和内存,只能通过网络发送消息。 本篇受教材 4.6 Distributed Computing 启发,但不把重点放在网络历史或拓扑分类,而是回答工程中更直接的问题: 本篇主线 可靠性来自一组相互配合的边界 01 · 边界调用变成消息双方不再共享内存和调用栈 02 · 不确定超时不等于未执行响应丢失会让结果进入未知状态 03 · 恢复Retry + Idempotency允许重传,同时吸收重复业务效果 04 · 解释状态 + Observability让失败可以恢复、关联和定位 1. 远程调用不是“慢一点的函数调用” 本地调用: 1result = execute_task(task) 调用者与函数通常位于同一进程。参数通过内存传递,返回值直接回到当前调用栈;如果函数抛出异常,调用者也能在同一运行时中接住它。 远程调用看起来可...</div></div></div><div class="recent-post-item"><div class="post_cover right"><a href="/2026/09/02/composing-programs-declarative-unification/" title="从“怎样执行”到“满足什么”:SQL、逻辑规则与 Unification"><img class="post-bg" src="/img/composing-programs-declarative-unification-nature-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="从“怎样执行”到“满足什么”:SQL、逻辑规则与 Unification" loading='lazy'></a></div><div class="recent-post-info"><a class="article-title" href="/2026/09/02/composing-programs-declarative-unification/" title="从“怎样执行”到“满足什么”:SQL、逻辑规则与 Unification">从“怎样执行”到“满足什么”:SQL、逻辑规则与 Unification</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time datetime="2026-09-02T03:00:00.000Z" title="发表于 2026-09-02 11:00:00">2026-09-02</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/">Notes</a><i class="fas fa-angle-right article-meta-link"></i><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Notes/Computer-Science/">Computer Science</a></span></div><div class="content">上一篇用 Iterator 和 Generator 把大量数据组织成按需流动的 Pipeline。不过,那条管道仍然由程序员规定了每一个执行步骤:先读取,再过滤,然后转换和聚合。 这一次继续向上抽象:程序只描述结果必须满足什么条件,执行系统自己决定怎样得到结果。 本文把教材 4.3 Declarative Programming、4.4 Logic Programming 和 4.5 Unification 重新组织成一条递进路线: 本篇主线 抽象逐层提高,但执行成本没有消失 01 · 表达从步骤转向结果条件程序不再手写每一次遍历与判断 02 · 关系SQL、Fact 与 Rule用关系描述已有事实和推导规则 03 · 求解Unification + Search建立变量绑定,再寻找成立的证明路径 1. 声明式编程隐藏的是执行过程,不是计算本身 假设任务执行记录保存在 task_runs 表中: task_id service status duration_ms t-17 search faile...</div></div></div></div><nav id="pagination"><div class="pagination"><span class="page-number current">1</span><a class="page-number" href="/page/2/#content-inner">2</a><a class="page-number" href="/page/3/#content-inner">3</a><a class="extend next" rel="next" href="/page/2/#content-inner"><i class="fas fa-chevron-right fa-fw"></i></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info text-center"><div class="avatar-img"><img src="/img/kamuyi.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/ loading='lazy'></div><div class="author-info-name">LittlePyx</div><div class="author-info-description">小P的学习、研究、生活记录</div><div class="site-data"><a href="/archives/"><div class="headline">文章</div><div class="length-num">18</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">43</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">4</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/littlepyx"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons"><a class="social-icon" href="https://github.com/LittlePyx" target="_blank" title="GitHub"><i class="fab fa-github"></i></a><a class="social-icon" href="mailto:627875273@qq.com" target="_blank" title="Email"><i class="fas fa-envelope"></i></a><a class="social-icon" href="/algorithm/" target="_blank" title="算法笔记"><i class="fas fa-code"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content"><strong>教育经历</strong><br>
本科:杭州电子科技大学<br>
研究生:电子科技大学<br><br>
<strong>研究方向</strong><br>
AI Agent 开发、计算成像、深度学习、光学<br><br>
新增:代码随想录算法刷题笔记整理中,按题型与算法模板归纳。
</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2026/09/12/happy-llm-02-transformer-engineering/" title="Transformer:注意力、网络结构与自回归推理"><img src="/img/happy-llm-transformer-natgeo-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Transformer:注意力、网络结构与自回归推理"/ loading='lazy'></a><div class="content"><a class="title" href="/2026/09/12/happy-llm-02-transformer-engineering/" title="Transformer:注意力、网络结构与自回归推理">Transformer:注意力、网络结构与自回归推理</a><time datetime="2026-09-12T02:10:00.000Z" title="发表于 2026-09-12 10:10:00">2026-09-12</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2026/09/12/happy-llm-01-nlp-for-agent/" title="NLP 基础:文本编码、表示学习与语言模型"><img src="/img/happy-llm-nlp-natgeo-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="NLP 基础:文本编码、表示学习与语言模型"/ loading='lazy'></a><div class="content"><a class="title" href="/2026/09/12/happy-llm-01-nlp-for-agent/" title="NLP 基础:文本编码、表示学习与语言模型">NLP 基础:文本编码、表示学习与语言模型</a><time datetime="2026-09-12T02:00:00.000Z" title="发表于 2026-09-12 10:00:00">2026-09-12</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2026/09/08/composing-programs-chapter-1-to-4-roadmap/" title="从函数到分布式系统:Composing Programs 第一至第四章总路线图"><img src="/img/composing-programs-higher-order-functions-nature-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="从函数到分布式系统:Composing Programs 第一至第四章总路线图"/ loading='lazy'></a><div class="content"><a class="title" href="/2026/09/08/composing-programs-chapter-1-to-4-roadmap/" title="从函数到分布式系统:Composing Programs 第一至第四章总路线图">从函数到分布式系统:Composing Programs 第一至第四章总路线图</a><time datetime="2026-09-08T02:00:00.000Z" title="发表于 2026-09-08 10:00:00">2026-09-08</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2026/09/02/composing-programs-parallel-mapreduce/" title="计算如何同时展开:并发、并行、MapReduce 与共享状态"><img src="/img/composing-programs-parallel-mapreduce-nature-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="计算如何同时展开:并发、并行、MapReduce 与共享状态"/ loading='lazy'></a><div class="content"><a class="title" href="/2026/09/02/composing-programs-parallel-mapreduce/" title="计算如何同时展开:并发、并行、MapReduce 与共享状态">计算如何同时展开:并发、并行、MapReduce 与共享状态</a><time datetime="2026-09-02T05:00:00.000Z" title="发表于 2026-09-02 13:00:00">2026-09-02</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2026/09/02/composing-programs-distributed-reliability/" title="机器之间如何协作:消息、协议与分布式失败"><img src="/img/composing-programs-distributed-reliability-nature-cover.jpg" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="机器之间如何协作:消息、协议与分布式失败"/ loading='lazy'></a><div class="content"><a class="title" href="/2026/09/02/composing-programs-distributed-reliability/" title="机器之间如何协作:消息、协议与分布式失败">机器之间如何协作:消息、协议与分布式失败</a><time datetime="2026-09-02T04:00:00.000Z" title="发表于 2026-09-02 12:00:00">2026-09-02</time></div></div></div></div><div class="card-widget card-categories"><div class="item-headline">
<i class="fas fa-folder-open"></i>
<span>分类</span>
</div>
<ul class="card-category-list" id="aside-cat-list">
<li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Notes/"><span class="card-category-list-name">Notes</span><span class="card-category-list-count">17</span></a><ul class="card-category-list child"><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Notes/AI-Agent/"><span class="card-category-list-name">AI Agent</span><span class="card-category-list-count">2</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Notes/Computer-Science/"><span class="card-category-list-name">Computer Science</span><span class="card-category-list-count">13</span></a></li></ul></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Tutorial/"><span class="card-category-list-name">Tutorial</span><span class="card-category-list-count">1</span></a></li>
</ul></div><div class="card-widget card-tags"><div class="item-headline"><i class="fas fa-tags"></i><span>标签</span></div><div class="card-tag-cloud"><a href="/tags/AST/" style="font-size: 1.1em; color: #999">AST</a> <a href="/tags/Parallelism/" style="font-size: 1.1em; color: #999">Parallelism</a> <a href="/tags/Attention/" style="font-size: 1.1em; color: #999">Attention</a> <a href="/tags/Theory/" style="font-size: 1.23em; color: #999ea6">Theory</a> <a href="/tags/Inference/" style="font-size: 1.1em; color: #999">Inference</a> <a href="/tags/Transformer/" style="font-size: 1.1em; color: #999">Transformer</a> <a href="/tags/NLP/" style="font-size: 1.1em; color: #999">NLP</a> <a href="/tags/MapReduce/" style="font-size: 1.1em; color: #999">MapReduce</a> <a href="/tags/Generic-Operations/" style="font-size: 1.1em; color: #999">Generic Operations</a> <a href="/tags/Higher-Order-Functions/" style="font-size: 1.1em; color: #999">Higher-Order Functions</a> <a href="/tags/Embedding/" style="font-size: 1.1em; color: #999">Embedding</a> <a href="/tags/Error-Handling/" style="font-size: 1.1em; color: #999">Error Handling</a> <a href="/tags/Information/" style="font-size: 1.1em; color: #999">Information</a> <a href="/tags/Happy-LLM/" style="font-size: 1.23em; color: #999ea6">Happy-LLM</a> <a href="/tags/Interpreter/" style="font-size: 1.37em; color: #99a4b2">Interpreter</a> <a href="/tags/SQL/" style="font-size: 1.1em; color: #999">SQL</a> <a href="/tags/Python-Object-Model/" style="font-size: 1.1em; color: #999">Python Object Model</a> <a href="/tags/Data-Structures/" style="font-size: 1.1em; color: #999">Data Structures</a> <a href="/tags/Programming-Abstraction/" style="font-size: 1.1em; color: #999">Programming Abstraction</a> <a href="/tags/Software-Engineering/" style="font-size: 1.1em; color: #999">Software Engineering</a> <a href="/tags/Distributed-Systems/" style="font-size: 1.1em; color: #999">Distributed Systems</a> <a href="/tags/Data-Pipeline/" style="font-size: 1.1em; color: #999">Data Pipeline</a> <a href="/tags/Functional-Programming/" style="font-size: 1.1em; color: #999">Functional Programming</a> <a href="/tags/RAG/" style="font-size: 1.1em; color: #999">RAG</a> <a href="/tags/Parsing/" style="font-size: 1.1em; color: #999">Parsing</a> <a href="/tags/Protocol/" style="font-size: 1.1em; color: #999">Protocol</a> <a href="/tags/Declarative-Programming/" style="font-size: 1.1em; color: #999">Declarative Programming</a> <a href="/tags/Unification/" style="font-size: 1.1em; color: #999">Unification</a> <a href="/tags/Technology/" style="font-size: 1.1em; color: #999">Technology</a> <a href="/tags/Concurrency/" style="font-size: 1.1em; color: #999">Concurrency</a> <a href="/tags/Logic-Programming/" style="font-size: 1.1em; color: #999">Logic Programming</a> <a href="/tags/Optics/" style="font-size: 1.1em; color: #999">Optics</a> <a href="/tags/Iterator/" style="font-size: 1.1em; color: #999">Iterator</a> <a href="/tags/Evaluation/" style="font-size: 1.1em; color: #999">Evaluation</a> <a href="/tags/Python/" style="font-size: 1.5em; color: #99a9bf">Python</a> <a href="/tags/Composing-Programs/" style="font-size: 1.5em; color: #99a9bf">Composing Programs</a> <a href="/tags/Mutable-State/" style="font-size: 1.1em; color: #999">Mutable State</a> <a href="/tags/Closure/" style="font-size: 1.1em; color: #999">Closure</a> <a href="/tags/Data-Abstraction/" style="font-size: 1.1em; color: #999">Data Abstraction</a> <a href="/tags/Generator/" style="font-size: 1.1em; color: #999">Generator</a></div></div><div class="card-widget card-archives">
<div class="item-headline">
<i class="fas fa-archive"></i>
<span>归档</span>
</div>
<ul class="card-archive-list">
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/09/">
<span class="card-archive-list-date">
九月 2026
</span>
<span class="card-archive-list-count">7</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/08/">
<span class="card-archive-list-date">
八月 2026
</span>
<span class="card-archive-list-count">7</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/07/">
<span class="card-archive-list-date">
七月 2026
</span>
<span class="card-archive-list-count">1</span>
</a>
</li>
<li class="card-archive-list-item">
<a class="card-archive-list-link" href="/archives/2026/01/">
<span class="card-archive-list-date">
一月 2026
</span>
<span class="card-archive-list-count">3</span>
</a>
</li>
</ul>
</div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>网站信息</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">文章数目 :</div><div class="item-count">18</div></div><div class="webinfo-item"><div class="item-name">最后更新时间 :</div><div class="item-count" id="last-push-date" data-lastPushDate="2026-09-16T08:15:04.743Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer"><div class="footer-other"><div class="footer-copyright"><span class="copyright">©2025 - 2026 By LittlePyx</span><span class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo 5.4.2</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly 5.4.2</a></span></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="日间和夜间模式切换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><div class="js-pjax"><script>window.typedJSFn = {
init: str => {
window.typed = new Typed('#subtitle', Object.assign({
strings: str,
startDelay: 300,
typeSpeed: 150,
loop: true,
backSpeed: 50,
}, null))
},
run: subtitleType => {
if (true) {
if (typeof Typed === 'function') {
subtitleType()
} else {
btf.getScript('https://cdn.jsdelivr.net/npm/typed.js/dist/typed.umd.min.js').then(subtitleType)
}
} else {
subtitleType()
}
},
processSubtitle: (content, extraContents = []) => {
if (true) {
const sub = ["爱玩毛线","喵喵喵","爱学习"].slice()
if (extraContents.length > 0) {
sub.unshift(...extraContents)
}
if (typeof content === 'string') {
sub.unshift(content)
} else if (Array.isArray(content)) {
sub.unshift(...content)
}
sub.length > 0 && typedJSFn.init(sub)
} else {
document.getElementById('subtitle').textContent = typeof content === 'string' ? content :
(Array.isArray(content) && content.length > 0 ? content[0] : '')
}
}
}
btf.addGlobalFn('pjaxSendOnce', () => { typed.destroy() }, 'typedDestroy')
</script><script>function subtitleType () {
typedJSFn.processSubtitle(["爱玩毛线","喵喵喵","爱学习"])
}
typedJSFn.run(subtitleType)</script><script>(() => {
const runMermaid = ele => {
window.loadMermaid = true
const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'neutral'
ele.forEach((item, index) => {
const mermaidSrc = item.firstElementChild
const mermaidThemeConfig = `%%{init:{ 'theme':'${theme}'}}%%\n`
const mermaidID = `mermaid-${index}`
const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent
const renderFn = mermaid.render(mermaidID, mermaidDefinition)
const renderMermaid = svg => {
mermaidSrc.insertAdjacentHTML('afterend', svg)
}
// mermaid v9 and v10 compatibility
typeof renderFn === 'string' ? renderMermaid(renderFn) : renderFn.then(({ svg }) => renderMermaid(svg))
})
}
const codeToMermaid = () => {
const codeMermaidEle = document.querySelectorAll('pre > code.mermaid')
if (codeMermaidEle.length === 0) return
codeMermaidEle.forEach(ele => {
const preEle = document.createElement('pre')
preEle.className = 'mermaid-src'
preEle.hidden = true
preEle.textContent = ele.textContent
const newEle = document.createElement('div')
newEle.className = 'mermaid-wrap'
newEle.appendChild(preEle)
ele.parentNode.replaceWith(newEle)
})
}
const loadMermaid = () => {
if (false) codeToMermaid()
const $mermaid = document.querySelectorAll('#article-container .mermaid-wrap')
if ($mermaid.length === 0) return
const runMermaidFn = () => runMermaid($mermaid)
btf.addGlobalFn('themeChange', runMermaidFn, 'mermaid')
window.loadMermaid ? runMermaidFn() : btf.getScript('https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js').then(runMermaidFn)
}
btf.addGlobalFn('encrypt', loadMermaid, 'mermaid')
window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid)
})()</script></div><script src="/js/mermaid-polish.js" defer></script><script src="/js/article-experience.js" defer></script><script src="/js/happy-llm.js" defer></script><script id="canvas_nest" defer="defer" color="0, 122, 204" opacity="0.6" zIndex="-1" count="60" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-nest.min.js"></script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="text-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span> 数据加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章、算法笔记..." type="text"/></div></div><hr/><div id="local-search-results"></div><div id="local-search-stats-wrap"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js"></script></div></div></body></html>