发布于 ,更新于 

AI 入门

背景

在先前部分的题目中,你可能已经或多或少的直接或间接使用了各式各样的ai工具来帮助你解答。不论你是往返于豆包/deepseek/gpt的对话框中,还是直接一步到位掌控了如codex/workbuddy一般的现代集成化agent助手的力量,在这个章节中,我们希望你能够加深对“人工智能”这一存在的了解。会用ai帮你解决问题已经是一件很好的事情,但你更需要了解的是如何合理的使用它并试着去了解它。
附加题可能很难,做不出来也没关系,你只要思考过就行,永远永远都不要放弃思考。

1. 提示词工程

(注:这部分的验证比较困难且主观,请你将你编写的prompt以及相关问题的答案以markdown格式的文件保存即可,我们会进行现场审阅,推荐你标注出各段prompt所对应的题号)
或者:
(如果你完成了第三部分的agent部分,你完全也可以用你自己的agent向我们现场展示你所编写的prompt的效果)

想要召唤一个魔鬼,你必须知道它的名字

1.0 综述:描述清楚你的需求

ai什么都能干,但正因为如此,你不给它下指令,它就永远不知道要干些什么
请看以下的例子:

1
帮我写一个酷酷的个人网站
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
你是一名资深产品设计师和全栈工程师。请帮我从零实现一个具有强烈个人风格的现代个人网站。  

## 项目定位

这是一个面向设计师、开发者和潜在合作方的个人作品集网站,目标是让访客在 10 秒内了解我的身份、擅长领域和代表作品,并愿意继续浏览或联系我。

默认个人信息如下:

- 姓名:puresky

- 身份:独立设计师 / 全栈开发者

- 关键词:数字产品、交互设计、创意技术、实验性视觉

- 风格:克制、锋利、冷静、有科技感,但不要像普通 SaaS 官网


如果缺少具体内容,请生成可信的占位内容,并将其集中管理,方便后续替换。

## 视觉方向

请设计一种具有辨识度的“未来感个人工作室”视觉语言:

- 深色背景为主,使用高对比度的米白色、荧光绿色和少量暖红色作为强调色

- 大面积留白,清晰的网格系统,强烈但克制的排版层级

- 使用超大标题、窄体或等宽字体、细边框和轻微噪点纹理

- 避免模板化渐变、发光圆球、玻璃拟态、堆叠卡片和常见的 AI 生成式审美

- 页面要像一个真实创作者的数字工作室,而不是营销落地页

- 动效应该服务于信息层级和空间感,不要持续晃动或影响阅读

- 支持桌面端、平板和移动端,所有文字不能溢出或互相遮挡


## 页面与功能

实现以下页面:

1. 首页

- 首屏直接展示姓名、身份和一句有态度的个人宣言

- 显示当前状态,例如“Currently available for selected collaborations”

- 提供进入作品集和联系我的入口

- 添加一个具有记忆点但不喧宾夺主的互动元素

2. 作品集页面

- 以编辑感较强的列表或不规则网格展示项目

- 每个项目包含标题、年份、类型、简短说明和视觉预览

- 支持按类别筛选

- 点击项目进入详情页

3. 项目详情页

- 展示项目背景、我的职责、过程、结果和相关图片

- 支持项目之间的前后切换

- 图片应有合理的加载状态和响应式尺寸

4. 关于页面

- 展示个人简介、技能、经历和联系方式

- 内容密度适中,适合快速扫描

5. 联系功能

- 联系表单包含姓名、邮箱、留言

- 前端校验、错误状态、提交中状态和成功状态完整

- 后端使用 Next.js Route Handler 实现接口

- 不配置真实邮件服务时,使用安全的 mock 处理,并明确标注替换位置


## 技术要求

使用以下技术栈:

- Next.js App Router

- TypeScript

- Tailwind CSS

- shadcn/ui,仅在确实有帮助时使用

- Framer Motion,用于页面转场、悬停和滚动动效

- lucide-react 图标

- 使用本地 mock 数据,不依赖外部数据库

- 使用 ESLint 和项目已有的格式化规范

- 优先使用语义化 HTML、可访问的交互控件和键盘可操作的导航


## 交互要求

- 页面加载时有简洁的入场动画

- 页面之间有自然的转场

- 作品列表支持悬停预览或轻微位移反馈

- 导航栏在移动端变成可操作的菜单

- 支持 prefers-reduced-motion

- 所有图标按钮提供 aria-label 或 tooltip

- hover、focus、disabled、loading、error 和 empty 状态完整

- 不要为了展示技术而添加无意义的交互


## 开发流程

请按以下顺序执行:

1. 先检查当前项目结构、依赖和已有代码,保留有价值的现有内容

2. 简要说明你的设计决策和页面信息架构

3. 直接实现完整可运行的网站,不要只提供示例代码

4. 启动开发服务器并确认页面可以访问

5. 检查桌面端和移动端布局

6. 修复明显的视觉问题、控制台错误、类型错误和交互问题

7. 最后说明修改了哪些文件、如何运行项目,以及还需要替换哪些占位内容


## 验收标准

- 首屏具有明确的个人品牌识别度

- 页面不是通用模板的简单拼装

- 移动端没有横向溢出、文字遮挡或按钮错位

- 所有主要导航和交互都可以正常使用

- 项目详情页、筛选、联系表单和移动端菜单可工作

- `npm run build` 或项目对应的构建命令能够成功执行

- 代码结构清晰,组件复用合理,没有不必要的复杂抽象

在被赋予任务的时候,你自然会希望要求越具体越好,这就是提示词,你需要准确描述你的任务需求,把交给ai的任务拆分为对方可执行的步骤,并给出你的预期和验收标准

题目一:细化需求

请为以下的四个抽象任务编写细化版的prompt,你可以参考上文中所给出的样式,但我们更希望你能具体问题具体分析(代码需求和日常需求的prompt格式大概也不能盲目通用,对吗?),你可以借助各式各样的工具乃至ai本身来完善你的提示词,请享受这一过程。

1
我需要做一份期末小组汇报的PPT
1
我想让你画一张二次元角色的图片
1
我想让你扮演XXX角色和我聊天
1
2
我想让你帮我开发一款日常app
(至于这个app是拿来干嘛的,没有标准答案,发挥你的想象力吧)

请提交:

  1. 你编写的 Prompt;
  2. AI 根据该 Prompt 生成的回答/产物(可选)。
    另外,如果你觉得无从下手,你也可以先选择继续往下,我们推荐你在完成以下小节后再回头查看你当初的题目一的答案!

1.1 思维链CoT

CoT (chain of thought)思维链通过模拟人类解决问题时的思维过程,通过一系列逻辑推理步骤来引导模型生成答案。其核心在于将复杂问题分解为多个更小、更易于处理的子问题。 通过逐步解决这些子问题,模型能够构建一条逻辑推理的链条,最终得出答案。这种方法不仅提高了模型解决问题的准确性,还增强了其可解释性。
零样本或少样本的CoT是两种典型的CoT代表。
zero-shot CoT:不给示例,只在问题结尾加一句"让我们一步步来思考",靠模型自身的推理能力;
few-shot CoT:先给一道已解决的示例题,让模型照着示例的思路和格式解新题。
CoT 不保证答对,也不等于输出越长越好。真正有价值的是让 AI 展示关键步骤、中间结论和检查过程,这样错了也容易定位。

题目一:编写 zero-shot CoT Prompt

本题不要求你直接解决问题,而是要求你为下面的逻辑问题编写一条 Prompt,使 AI 能够清晰、稳定地完成推理:
小林、小周、小陈分别在18:00、19:00、20:00值班。

已知:

  1. 小林不在18:00值班;
  2. 小周比小陈更早值班;
  3. 小陈不在18:00值班。

请判断三人的值班时间。你的 Prompt 应要求 AI:
• 先整理已知条件;
• 将问题拆分为若干个小步骤;
• 展示关键的中间结论;
• 排除不可能的情况;
• 最后用表格给出答案;
• 对答案进行检查。
请提交:

  1. 你编写的 Prompt;
  2. AI 根据该 Prompt 生成的回答(可选);
  3. 说明你的 Prompt 中哪些内容体现了 CoT。
题目二:编写 few-shot CoT Prompt

请编写一条 few-shot CoT Prompt,让 AI 学会按照固定格式解决类似的逻辑推理题。
你的 Prompt 中必须包含:

  1. 一道已经解决的示例题;
  2. 示例题的条件整理;
  3. 示例题的分步推理;
  4. 示例题的最终答案和检查过程;
  5. 一道新的、结构相似但条件不同的题目。
    要求 AI 对新题也按照以下格式回答:
    已知条件:
    推理步骤:
    中间结论:
    最终答案:
    条件检查:请提交:
  6. 你编写的 Prompt;
  7. AI 根据该 Prompt 生成的回答(可选);
  8. 比较 zero-shot CoT 和 few-shot CoT 在这个任务中的区别。

1.2 检索增强生成 RAG

大模型的知识在训练时就固定了,它可能不知道最新信息、组织内部资料或某个课程的规定,也容易在缺少依据时一本正经地编造。所以有时它才会闹出让某位已故人物死去活来的笑话
RAG(Retrieval-Augmented Generation,检索增强生成)的思路是:AI 回答之前,先从指定的资料库检索相关内容,再带着资料作答,而不是凭空想。
用户问题 ──→ 检索相关资料 ──→ 问题和资料一起交给 AI ──→ 依据资料回答它像是考试时允许 AI 先查阅一份指定的资料,而不是重新训练模型。一个完整的 RAG 系统还要经历资料准备、切分索引、检索、组合上下文、生成、检查资料是否足够等环节,以及一堆恶心的向量计算。但你现在只需要抓住一件事:把"参考资料"和"回答要求"一起放进 Prompt,就是手动版 RAG。
RAG 能减少幻觉但无法杜绝:检索不到、资料过期、资料矛盾、AI 没用对资料,都可能翻车。所以一份合格的 RAG Prompt 至少会规定:只用提供的资料、结论标注依据、资料不足就明说,而不是猜。
再往前走一步是 CoVe(验证链):先让 AI 生成初始回答,再提取关键事实、独立验证、修正错误,最后输出最终回答。RAG(找资料)→ CoT(分步推理)→ CoVe(验证修正)可以串成一条流水线。

题目一:编写一个 RAG 问答 Prompt

下面是一个模拟的“网络部知识库”:
[资料1]《网络部设备借用规定(2026年版)》:
网络部成员借用路由器前需要填写借用登记。普通借用期限不超过7天;周末借用需要得到当周负责人批准。

[资料2]《网络部值班安排》:
工作日值班时间为18:00至21:00,周末没有固定值班安排。请为下面的任务编写一条 RAG Prompt:
我想在周六借用一个备用路由器,需要满足什么条件,最多可以借几天?你的 Prompt 应要求 AI:
• 只根据提供的资料回答;
• 找出与问题相关的资料;
• 给出资料编号作为依据;
• 区分资料中明确说明的内容和资料中没有说明的内容;
• 不要补充资料之外的规定。
请提交:

  1. 你编写的 Prompt;
  2. AI 根据该 Prompt 生成的回答(可选);
  3. 说明你的 Prompt 如何体现了 RAG 的思想。
题目二:编写 CoVe 验证链 Prompt

请为下面的场景编写一条 CoVe Prompt:
用户问题:周六可以直接到网络部借用备用路由器吗?

参考资料:
[资料1] 周末借用设备需要得到当周负责人批准。

AI 的初始回答:
周六可以直接到网络部借用备用路由器,借用期限是7天。你的 Prompt 应要求 AI:

  1. 从初始回答中提取需要验证的关键事实;
  2. 为每个事实生成一个验证问题;
  3. 不直接相信初始回答;
  4. 只根据参考资料独立检查这些事实;
  5. 修正初始回答中的错误;
  6. 输出带有资料依据的最终回答。
    请提交:
  7. 你编写的 Prompt;
  8. AI 根据该 Prompt 生成的回答(可选);
  9. 说明 CoVe 如何帮助发现初始回答中的问题。

1.3 注意力引导工程

"注意力引导工程"不是一个定义统一的标准术语,本节指:通过安排 Prompt 的结构、顺序、标记、重点和输出要求,引导 AI 把注意力放在真正重要的信息上。你不是研发ai的人,至少目前不是,你改不了模型内部的注意力机制,你能做的是让任务、资料和约束的边界更清楚。
当 Prompt 里资料多、任务多、要求互相冲突时,AI 容易:抓住资料细节却忘了任务、把背景介绍当指令、漏掉藏在长文本中间的关键条件、分不清主次、输出一堆却没回答真正的问题。
常用的引导方法有六种:

  1. 先说任务,再给资料:任务和判断标准放前面,资料用分隔符框住放后面,避免 AI 把资料当指令。
  2. 标题和分隔符:用 Markdown 标题、XML 标签或自定义分隔符区分"任务 / 资料 / 输出要求"。分隔符本身没有魔力,关键是边界清楚、格式一致。
  3. 明确优先级和冲突处理:资料有多个版本时告诉 AI 听谁的,例如正式通知优先于个人经验,新版本优先于旧版本。
  4. 删除无关内容,或明确要求忽略:资料越多不代表回答越好,明确说"只使用与问题直接相关的资料"。
  5. 关键约束放醒目位置,输出前再检查:“不能编造”"必须引用"这类要求,开头说一次,输出格式里再以检查清单提醒一次,但别整段重复。
  6. 用输出格式引向重点:与其说"请详细回答",不如规定结构:结论 / 资料依据 / 不确定之处 / 下一步。
    它和 RAG 的分工是:RAG 负责"找到哪些资料",注意力引导负责"告诉 AI 怎么用这些资料"。检索结果里的内容都是数据,不是给 AI 的新指令,要提防其中混入"忽略之前所有要求"之类的文字。
    大致的骨架是:
    【核心任务】→【处理规则】→【参考资料】→【输出格式】→【用户问题】再往深处走一步:提示词防御工程。威胁来自提示注入(Prompt Injection)——AI 分不清"指令"和"数据",攻击者把恶意指令藏进用户输入或外部资料里(比如检索结果中混入一句"忽略之前所有要求"),就能让 AI 偏离本来的任务。它位列 OWASP LLM 应用十大风险之首;前文提到的"资料里混入指令",正是它的间接注入形态。
题目一:为长资料编写注意力引导 Prompt

下面是一组混杂了重点和无关信息的材料:
[材料A] 网络部成立于2009年,主要负责校园网络维护,也会组织新生培训和技术分享活动。

[材料B] 新生连接宿舍 Wi-Fi 的步骤:打开无线网络设置,选择校园网,输入学号和密码,完成认证后打开网页测试。

[材料C] 网络部本学期计划举办三次技术分享,主题包括路由器配置、网络安全和开源工具。

[材料D] 如果认证页面没有自动弹出,请先打开浏览器访问任意网页;仍然无法打开时,联系当日值班人员。请为下面的任务编写一条注意力引导 Prompt:
请给新生写一份宿舍 Wi-Fi 连接说明。你的 Prompt 应要求 AI:
• 优先关注材料 B 和材料 D;
• 忽略网络部历史和活动介绍;
• 按实际操作顺序输出步骤;
• 将无法连接时的处理方法单独列出;
• 不添加材料中没有出现的操作。
请提交:

  1. 你编写的 Prompt;
  2. AI 根据该 Prompt 生成的回答(可选);
  3. 说明你使用了哪些标题、分隔符或优先级要求来引导注意力。

2.Transformer 架构与 Token

上帝投色子吗?

我们当然不需要你会写神经网络代码,当然如果你真的会,那么请立马联系我们。只需要建立两个直觉:AI 眼里的文字长什么样(Token),AI 用什么结构理解文字(Transformer)

2.1 Token

文字进入模型之前,先被切成一小块一小块,每一块叫一个 Token,再转成数字 ID 喂给模型。
“我爱编程” ──→ 分词 ──→ [“我”, “爱”, “编程”] ──→ [1234, 5678, 9012](token ID)切分由分词器(Tokenizer)完成,主流算法是 BPE(字节对编码):统计海量文本里哪些字符组合经常一起出现,就把它们合并成一个 token。常见词可能一个词就是 1 个 token,生僻词、拼写错误会被拆成好几个。
所以 token 数不等于字数,不同语言差异很大:

文本 经验换算
英文 1 token ≈ 3~4 个字符,常见单词约 1 token
中文 1 个汉字 ≈ 1~2 个 token

同样的意思,中文通常比英文更费 token,因为主流分词器主要按英文语料训练,对中文切分的效率更低。
想想看:既然中文比英文更费token,那么应当怎样在保证中文对话流的情况下利用这一点合理省钱?
Token 直接决定三件实际的事:
上下文窗口:模型一次最多能处理的 token 数(输入 + 输出),超了就放不下;
计费:API 按输入、输出 token 分别计价,长对话和长资料都是钱;
速度:token 越多,生成越慢。

题目一:数Token

下面是一段真实场景的对话,请估算并实测它的 token 数:
用户:你好,我是大一新生,宿舍连不上校园网了,麻烦帮我看看。
助手:先别急,我们按步骤排查。第一步,确认你连的是不是 Campus-Net-5G 这个 Wi-Fi;第二步,打开浏览器访问任意网页,看认证页面是否弹出。
用户:连上了,但是一直提示"认证失败"。要求:

  1. 先凭经验估算:这段对话大约多少个 token?(提示:中英文分开估)
  2. 再把它丢进任意在线 Token 计数器实测(文末延伸阅读有墙内可用的工具),记录真实数值;
  3. 对比估算和实测,说明差异从哪来;
  4. 如果把"助手"的两句话换成同样意思的英文,token 数是变多还是变少?为什么?
    请提交:你的估算、实测结果、对比分析和结论。
题目二:糖果

这道题改编自文末的 Codex Candy Eval(糖果评测)。原项目会把一道糖果题交给模型,记录输入、输出和推理所消耗的 Token,再根据回答自动判分。
你不需要安装 Codex CLI,也不需要编写或运行 Python、Shell 脚本。本题只要求你阅读下面这段经过删减的真实实现,并使用任意一个网页端 AI 完成实验。
首先阅读模型收到的题目:

1
2
3
4
5
6
7
8
9
10
11
12
不使用任何外部工具回答以下问题:

一个黑色袋子里有三种口味、两种形状的糖果,数量如下:

苹果味 桃子味 西瓜味
圆形 7 9 8
五角星形 7 6 4

不同形状靠手感可以分辨,但不能分辨口味。参赛者需要提前决定摸出
多少颗糖。最少取出多少颗,才能保证手中同时拥有一颗圆形糖和一颗
五角星形糖,并且它们分别是苹果味和桃子味?两种口味与形状的对应
顺序均可。

下面是评测程序的核心片段。不考查 Python 语法,只需根据注释理解数据流:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1. 把上面的题目作为输入发送给模型
proc = run_model(input=CODEX_PROMPT)

# 2. 模型会返回一连串事件,程序从中分别取出回答和 Token 用量
for event in proc.events:
if event.type == "agent_message":
final_text = event.text # 用户最终看到的回答
elif event.type == "turn.completed":
usage = event.usage # 本次调用的用量记录

input_tokens = usage["input_tokens"]
output_tokens = usage["output_tokens"]
reasoning_tokens = usage["reasoning_output_tokens"]

# 3. 本地程序检查回答中是否出现独立的“21”,并据此判定对错
ok = contains_independent_number(final_text, 21)

可以把这段过程理解为:

1
2
3
4
5
6
7
用户题目 + 系统上下文等内容
↓ input tokens
模型处理
↓ output tokens
可见回答 + 不一定展示给用户的推理消耗

本地判分程序检查回答中有没有“21”

原仓库展示了下面两类运行结果(数值来自项目示例图):

模型回答开头 In Tok Out Tok Reason Tok 程序判定
最少要取出 29 个…… 13874 731 456 ×
最少要取出 21 个…… 15272 848 648

注意:Reason Tok 表示模型在推理阶段消耗的 Token,不等于模型向用户展示了一份完整的“内心思考”。不同平台对输出和推理 Token 的统计口径也可能不同,因此不能看到两列就默认把它们相加。
请完成以下任务:

  1. 认清输入与输出:指出代码中什么内容进入了模型,什么内容是模型生成的,什么内容只是本地程序产生的判分结果。解释为什么表中的 In Tok 远多于糖果题本身的字数。
  2. 比较两种理解:如果摸取时完全不能选择形状,计算最坏情况下最多能摸出多少颗仍不满足条件;然后重新读题,说明“不同形状靠手感可以分辨”会怎样改变取糖策略。
  3. 亲手验证 21:证明“取 9 颗圆形糖和 12 颗五角星形糖”一定满足条件,并说明为什么总数为 20 时仍可能失败。由此解释表中 29 被标为错误、21 被标为正确的原因。
  4. 检查评测器OK 是否是模型自己输出的?尝试写一句包含独立数字 21、但实际结论并非 21 的回答。根据代码判断它会被标为对还是错,并说明这种判分方式存在什么漏洞。
  5. 在网页端复现:把上面的糖果题复制到任意网页端 AI 中,记录其回答;如果它回答 29,可以用“题目说形状能靠手感分辨,这一点会改变策略吗?”追问一次。保留两轮完整对话。
  6. 观察可见 Token:使用文末任意在线 Token 工具,分别统计“你发出的题目”和“AI 的可见回答”大约有多少 Token,并标明所选工具或模型。再解释为什么这两个数可能与表中的 In TokOut Tok 不一致。
    请提交:糖果题的计算过程、代码阅读结论、网页端 AI 的两轮对话、Token 实测记录、以及一句你对“模型输出”和“评测结果”区别的总结。

2.2 Transformer

2017 年 Google 发表论文《Attention Is All You Need》,提出 Transformer 架构,如今几乎所有大模型(GPT、Claude、DeepSeek 等)都是它的后代。核心思想是:处理每个词时,都能按相关性"看到"上下文里的所有其他词,这个机制叫自注意力(Self-Attention)。
打个比方:读"小明把蛋糕给了小红,她说了谢谢",AI 要知道"她"指谁,得回头去看"小红"。自注意力做的就是:处理"她"时,对句子里每个词算一个相关度,再按相关度加权融合它们的含义,相关度最高的词影响最大。
实现上,每个 token 会扮演三个角色:查询(Query,我要找什么)、键(Key,我是什么)、值(Value,我的内容)。相关度由 Query 与所有 Key 的匹配程度决定,再按相关度加权汇总所有 Value。为了捕捉不同层面的关系,模型会用多头注意力并行运行多组这样的计算,比如有的头关注"谁指代谁",有的头关注语法结构。另外,因为注意力本身不区分先后顺序,模型还会用位置编码给每个 token 标上位置。
原始 Transformer 分编码器(读入)和解码器(生成)两部分,解码时用掩码遮住未来,防止"偷看答案"。现代大模型普遍只用解码器部分:逐个预测下一个 token,把刚生成的 token 再喂回自己,像接龙一样把整段话写出来。

附加题:能工智人

大模型生成文本的本质,是根据当前可见的 token 预测下一个 token。Transformer 并不是简单地把前文平均混在一起,而是通过自注意力计算:当前位置应该重点参考前文的哪些位置。
本题放开工具限制:你可以使用 AI、计算器、在线 Tokenizer、电子表格或其他资料,但不要求使用需要特殊网络条件的网站/app。你必须提交自己的计算过程,并注明工具帮你完成了什么;只有 AI 给出的最终答案、没有推导记录,不能算作完成。

热身:上下文会改变预测

分别补全下面两句话,每处只填一个你认为最可能出现的字或词,并简要说明你参考了哪些上下文:
今天天气真____

小明推开窗,看见外面乌云密布,风刮得树枝乱晃。他缩回脑袋,叹了口气:"今天天气真____“再让任意 AI 分别补全,对比它与你的选择。不要只回答"上下文变长了”,还要指出新增的哪些 token 改变了预测。

主体:手算一次简化的自注意力

下面用一个经过教学简化的单层、单头注意力,处理这段已经被切好的 token:
小明 / 把 / 蛋糕 / 给 / 小红 / 她模型接下来要预测第 7 个 token。为理解最后一个 token"她"与前文的关系,每个 token 都会产生三个向量:
• Query(Q):当前位置正在寻找什么;
• Key(K):每个位置可以用什么特征与 Query 匹配;
• Value(V):匹配后,真正汇总进当前位置的信息。
本题把真实模型中成百上千维的向量压缩成二维,并人为赋予了便于观察的含义。真实模型中的维度通常不能直接解释为"男性"或"女性",数据也不会像下表这样整齐。

位置 token Q K V
1 小明 (1, 0) (1, 0) (1, 0)
2 (0, 0) (0, 0) (0, 0)
3 蛋糕 (0, 1) (0, 1) (0, 0)
4 (1, 0) (0, 0) (0, 0)
5 小红 (0, 1) (2, 1) (0, 1)
6 (1, 1) (1, 1) (0, 0)
任务一:画出因果掩码

画一个 6×6 的表格:行表示"正在处理的位置",列表示"想要查看的位置"。能查看填 ,不能查看填 ×
规则:第 1 个位置只能查看位置 1;第 2 个位置可以查看位置 1、2;以此类推。然后回答:

  1. 处理位置 4 的"给"时,可以看到哪些 token?
  2. 假设第 7 个 token 最终生成了"说",处理位置 6 的"她"时能提前看到它吗?
  3. 如果取消因果掩码,训练时可能发生什么"偷看答案"的问题?
任务二:计算"她"应该关注谁

只计算位置 6 的注意力。取 Q她 = (1, 1),它与每个位置的 K 做点积:
分数 = Q她 · K = Q的第1项 × K的第1项 + Q的第2项 × K的第2项示例:Q她 · K小明 = 1×1 + 1×0 = 1
请计算剩余 5 个分数,并填入下表。真实 Transformer 会对分数进行缩放、掩码和 Softmax;为避免本题变成指数运算练习,下表已经给出将分数除以 √2、再经过 Softmax 后的近似权重。各项保留两位小数后原本合计为 0.99,表中把 0.01 的舍入差补到了最后一项,使权重之和保持为 1。

被关注的 token 点积分数 注意力权重
小明 1 0.11
0.05
蛋糕 0.11
0.05
小红 0.45
0.23

检查:所有注意力权重相加应当等于 1。权重越大,表示该位置的 V 对"她"的新表示影响越大。
接着计算注意力输出:

1
2
H她 = 0.11×V小明 + 0.05×V把 + 0.11×V蛋糕
+ 0.05×V给 + 0.45×V小红 + 0.23×V她

向量要分两列计算。例如第一列是:

1
0.11×1 + 0.05×0 + 0.11×0 + 0.05×0 + 0.45×0 + 0.23×0

请算出完整的 H她 = (____, ____),并回答:

  1. 哪个 token 的注意力权重最高?
  2. 根据 V 的加权结果,"她"更多地汇总了"小明"还是"小红"的信息?
  3. 为什么"点积分数最高"和"最终汇总的信息最多"有关,但不能直接画等号?提示:中间还有 Softmax,真正被加权的是 V,而不是 K。
任务三:从隐藏表示到下一个 token

说明:注意力输出还不是文字。真实模型会继续经过残差连接、前馈网络、归一化和许多 Transformer 层,最后由输出层把隐藏表示映射成整个词表中每个 token 的分数(logit)。本题把中间步骤全部省略,直接用刚算出的 H她 做一次简化输出映射:

候选 token 输出向量 W 分数 H她 · W
(0, 2)
(2, 0)
(0, 1)
(0.5, 0)

计算四个候选 token 的分数并回答:

  1. 如果模型总选择分数最高的 token,下一个 token 是什么?
  2. 实际生成时,模型为什么不一定每次都选择最高分?请查找并解释 temperature 或采样的作用。
  3. 新 token 生成后,模型要继续生成第 8 个 token,输入会发生什么变化?因果掩码的可见范围又会怎样变化?

请提交:

  1. 热身中的两次预测、依据,以及与 AI 输出的对比;
  2. 完整的 6×6 因果掩码表;
  3. 任务一,任务二,任务三的各部分答案
  4. 150~300 字总结:自注意力怎样让当前位置有选择地使用上下文?它又怎样与逐 token 生成配合?
  5. 工具使用说明:列出使用的工具、用途,以及你如何核对工具给出的结果。

3.Agent简述

据说会使用火的动物只有人类

前两章主要是在聊天界面里使用 AI。这一章换一种方式:用 Python 调用模型,并从零搭出一个最小 Agent。
可以先把大模型理解成一个函数:输入消息,得到回答。它不会自动记住上一次调用,也不会自己执行外部操作。我们将依次给它加入单次调用、循环、对话历史和 System Prompt。step01step03 均为必做题,请分别保存,方便比较每一步新增了什么。
本章统一使用OpenAI 兼容接口,不要求安装 Codex CLI。调用 API 可能产生费用,请设置合理的余额和调用次数,不要把 API Key 提交到公开仓库!

3.0 获取你的api key

出于这样那样的原因,我们就不让你自行破费使用ai服务了
目前国内有着许许多多的免费api额度服务,本题以阿里云百炼为例。如果你还没有阿里云账号,请先注册并完成实名认证,再按下面的步骤获取 API Key:

  1. 登录 百炼控制台,按页面提示开通百炼服务,并确认当前账号有可用的模型额度;
  2. 进入 API-KEY 管理
  3. 点击 创建我的 API-KEY(部分页面显示为“创建 API Key”);
  4. 创建后立即复制完整 Key,它不会再次完整显示;
  5. 把 Key 粘贴到 .env,不要写进 .py 文件、公开仓库、聊天记录或截图。
    建议为本系列题目单独创建一个 Key,并在阿里云控制台关注额度或设置用量限制。若 Key 可能已泄露,立即到控制台禁用、删除并重新创建。官方说明见 阿里云百炼:获取 API Key

3.1 准备环境

请新建 requirements.txt,内容如下:

1
2
openai>=1.0.0  
python-dotenv>=1.0.0

在终端进入代码所在目录,然后安装依赖:

1
pip install -r requirements.txt

再新建 .env

1
2
3
DASHSCOPE_API_KEY=在这里填写你的_API_Key  
DASHSCOPE_MODEL=qwen3.7-plus
DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1

(选模型的话就在“用量&费用”这一栏选一个有免费额度的大语言模型即可,这里推荐你选正式版模型,比如示例中的qwen3.7-plus)

建议同时新建 .gitignore,至少写入一行 .env。如果 API Key 曾经出现在公开网页、截图或 Git 提交中,应立即去开放平台撤销并重新生成。
本章会反复用到下面这个接口。Step 01 会提供代码填空骨架,之后的 Step 02~04 再由你在已补完的代码上继续修改:

1
2
3
4
client.chat.completions.create(  
model=模型名,
messages=消息列表,
)

messages 是一个“列表套字典”的结构。常见 rolesystemuserassistant;模型生成的文本通常位于返回结果的 choices[0].message.content

3.2 Step 01:完成一次模型调用

这一步改为代码填空。请把下面的内容保存为 step01.py,再将 ___1______8___ 替换为正确内容。不要删除空输入检查,也不要把真实 API Key 直接写入源码。

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

import os

from dotenv import load_dotenv
from openai import OpenAI


def main() -> None:
load_dotenv()

api_key = os.getenv(___1___)
model = os.getenv("DASHSCOPE_MODEL", ___2___)
base_url = os.getenv("DASHSCOPE_BASE_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1")

if not api_key:
raise RuntimeError("没有找到 DASHSCOPE_API_KEY,请检查 .env 文件")

client = OpenAI(api_key=___3___, base_url=base_url)

prompt = input("你:")
if ___4___:
print("输入不能为空")
return

messages = [
{"role": ___5___, "content": prompt},
]

response = client.chat.completions.create(
model=___6___,
messages=___7___,
)
answer = response.___8___
print(f"AI:{answer}")


if __name__ == "__main__":

main()

填空提示:

  1. ___1___.env 中保存 API Key 的变量名,注意它是一个字符串;
  2. ___2___:没有配置 DASHSCOPE_MODEL 时使用的默认模型名(当然你自己选了模型的话就填你选的那个模型的代号);
  3. ___3___:上面已经读取出的 API Key 变量;
  4. ___4___:当 prompt 去掉首尾空白后为空时,条件应当成立;
  5. ___5___:用户消息对应的 role 字符串;
  6. ___6___:上面保存模型名的变量;
  7. ___7___:刚刚构造出的消息列表;
  8. ___8___:从响应的第一个 choice 中依次取得 messagecontent。可以回看 3.1 最后一段。
    补完后,先逐项解释这条数据路径:
1
2
.env -> api_key/model/base_url -> OpenAI 客户端
用户输入 -> messages -> 模型响应 -> choices[0].message.content -> 终端输出

要求:

  1. API Key 必须从环境变量读取,不能直接写在代码中。
  2. 当用户没有输入任何内容时,不应向 API 发送请求。
  3. 至少测试“你好,请用一句话介绍你自己”和“今天天气怎么样”。解释模型为什么通常无法直接报告你所在地的实时天气。
    请提交:补完后的 step01.py、八个填空的答案及简短说明、两次运行记录,以及你对实时天气回答的解释。

3.3 Step 02:加入循环

请复制 step01.pystep02.py,在其基础上让程序能够连续对话。此时暂时不要保存历史消息,每一轮仍只把用户当前输入发给模型。
示例伪代码:

1
2
3
4
5
6
7
8
完成与 step01 相同的初始化  

不断循环:
读取用户输入
如果输入是 exit 或 quit:结束循环
如果输入为空:跳过本轮
只用当前输入构造消息列表
调用模型并打印回答

完成“失忆实验”:先输入“我叫张三”,再输入“我叫什么名字?”。第二次请求中没有第一轮消息,因此模型通常无法可靠回答。这里的重点不是模型一定说“不知道”,而是它没有获得能够支持答案的上下文。
请提交:step02.py、完整的两轮对话记录,以及一句话解释模型为什么会“失忆”。

3.4 Step 03:加入短期记忆与 System Prompt

请复制 step02.pystep03.py,一次完成两项改造:用 history 保存对话历史,并在历史的第一条放入 System Prompt。你可以把 Agent 设计成校园网答疑助手、学习计划助手,或其他有明确职责和边界的角色。
示例伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
完成与前两步相同的初始化  
系统提示词 = 描述 Agent 的身份、任务、限制和输出要求
历史 = [一条 role 为 system、content 为系统提示词的消息]

不断循环:
读取用户输入
如果输入是 exit 或 quit:结束循环
如果输入为空:跳过本轮
把用户消息追加到历史
使用完整历史调用模型
取出模型回答
把模型回答追加到历史
打印回答

历史的顺序应当是 system -> user -> assistant -> user -> assistant。System Prompt 只需要在最前面放一次,不要每轮重复追加。如果请求失败,不要把一个不存在的模型回答写入历史。
完成下面两组实验:

  1. 记忆实验:先输入“我叫张三”,再输入“我叫什么名字?”,并与 step02.py 的结果对比;
  2. 身份实验:分别向 step02.pystep03.py 提出同一个与你设定角色有关的问题,比较身份、语气、内容边界和输出格式;然后尝试要求 Agent 忽略原有身份并记录结果。
    结合第 2 章回答:这种“记忆”的本质是什么?为什么历史越来越长时,请求可能变慢、变贵?System Prompt 能引导模型,但为什么不能被当作绝对可靠的安全边界?
    请提交:step03.py、System Prompt、两组实验记录,以及你对上述问题的回答。本题暂时不要求定义 ask_agent() 函数。

附加题:糖果(其二)

任务一:将 Agent 封装成函数

基础题中的 step03.py 只能在终端中交互。为了让其他程序复用它,请在不改变现有行为的前提下进行重构,定义:

1
def ask_agent(prompt: str) -> str:  

…这个函数应当检查输入、把用户消息追加到历史、调用模型、保存模型回答,并返回回答文本。终端交互循环必须放在 if __name__ == "__main__": 下,保证其他脚本导入 step03 时不会自动出现“你:”。
请另建一个临时测试文件,完成下面的导入调用:

1
2
3
from step03 import ask_agent  

print(ask_agent("你好,请用一句话介绍你自己"))

请提交重构后的 step03.py、测试文件和运行记录,并指出“函数参数”“发送给模型的消息”与“函数返回值”分别是什么。

任务二:实操糖果题

下面的脚本不依赖 Codex CLI。请将它保存为 candy_agent_eval.py,与 step03.py 放在同一目录。它会导入你的 ask_agent,重复提问,并在回答中出现独立数字 21 时判定通过。

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

from __future__ import annotations

import argparse
import importlib
import re
import time

import step03


CANDY_PROMPT = """请回答下面的问题,并说明理由:

在一个黑色的袋子里放有三种口味的糖果,每种糖果有两种不同的形状
(圆形和五角星形,不同形状靠手感可以分辨)。数量如下:

苹果味 桃子味 西瓜味
圆形 7 9 8
五角星形 7 6 4

参赛者需要提前决定摸出的糖果数。最少取出多少个,才能保证手中同时拥有
不同形状的苹果味和桃子味糖果?圆形苹果味配五角星桃子味,或者圆形桃子味
配五角星苹果味,均满足要求。
"""

ANSWER_PATTERN = re.compile(r"(?<!\d)21(?!\d)")


def preview(text: str, limit: int = 100) -> str:
one_line = " ".join(text.split())
return one_line if len(one_line) <= limit else one_line[: limit - 3] + "..."


def run_once() -> tuple[str, bool, float]:
# 重新加载模块,使每轮评测都从空白对话历史开始。
agent_module = importlib.reload(step03)
start = time.perf_counter()
answer = agent_module.ask_agent(CANDY_PROMPT)
elapsed = time.perf_counter() - start
passed = bool(ANSWER_PATTERN.search(answer))
return answer, passed, elapsed


def main() -> None:
parser = argparse.ArgumentParser(description="使用 step03 Agent 自动测试糖果题")
parser.add_argument("-n", "--tests", type=int, default=3, help="测试次数")
args = parser.parse_args()
if args.tests < 1:
parser.error("测试次数必须大于 0")

correct = 0
for index in range(1, args.tests + 1):
try:
answer, passed, elapsed = run_once()
correct += int(passed)
mark = "PASS" if passed else "FAIL"
print(f"[{index}/{args.tests}] {mark} {elapsed:.1f}s {preview(answer)}")
except Exception as exc:
print(f"[{index}/{args.tests}] ERROR {type(exc).__name__}: {exc}")

print(f"\n正确次数:{correct}/{args.tests}")
print(f"正确率:{correct / args.tests:.1%}")


if __name__ == "__main__":
main()

运行一次或多次测试:

1
2
python candy_agent_eval.py  
python candy_agent_eval.py --tests 5

请提交评测输出,并至少完整保留一条模型回答。这个脚本只检查回答里是否出现独立的 21,所以“判为 PASS”不等于推理一定正确,例如模型也可能写出“答案不是 21”。请检查完整回答,并分析判分规则可能出现的误判,以及你的 Agent 为什么答对或答错。

4.延伸阅读

(如果你发现有一些链接打不开或者看不懂,问ai,不要问我们,我们也打不开)


CoT:思维链与 Prompt 优化
以下资料用于进一步理解 CoT、任务分解和 Prompt 优化。建议先阅读官方文档,再阅读技术文章中的案例。

  1. 阿里云百炼:文生文 Prompt 指南
    阿里云官方文档,介绍如何构建清晰的 Prompt,并包含“引导模型思考”和思维链的示例。
  2. DeepSeek 官方:Prompt Library
    DeepSeek 官方提示词库,可以观察不同任务中如何描述角色、任务、限制条件和输出格式。
  3. 腾讯云开发者社区:DeepSeek 提示词工程完全指南
    结合 DeepSeek 和复杂任务案例,介绍任务拆解、角色设定、输出格式和 Prompt 迭代。
  4. CSDN:提示词工程——思维链(Chain of Thoughts, CoT)
    专门介绍 CoT、zero-shot CoT 和 few-shot CoT,适合用来复习本节中的基本概念和示例。

RAG:检索增强生成

  1. 阿里云百炼:知识库
    阿里云官方文档,介绍知识库如何利用 RAG 为大模型补充私有数据和最新信息。
  2. 腾讯云:知识引擎原子能力
    腾讯云官方文档,可用于了解知识检索、文档处理和问答应用中的相关能力。

注意力引导工程:资料组织与 Prompt 结构
本节中的分隔符、资料组织、任务优先级和输出格式,可以结合以下资料继续练习:

  1. HiddenLayer:Prompt Injection Attacks on LLMs
    提示注入的攻击原理与"三明治防御"等缓解策略的经典分析。
  2. Evidently AI:What is Prompt Injection? Example Attacks, Defenses and Testing
    提示注入入门指南,包含直接/间接注入的完整示例与多层防御思路。

Transformer 与 Token

  1. 《Attention Is All You Need》(Transformer 原始论文)
    2017 年 Google 提出 Transformer 架构的原始论文,现代大模型的基石。
  2. 菜鸟工具:在线 Token 计算器
    国内可直接访问,粘贴文本即可估算 token 数、字符数、单词数和费用,附换算公式,适合题目一的实测。
  3. Token 用量价格计算器
    支持 Claude、GPT、Gemini、DeepSeek 等主流模型,按输入/输出/缓存分别计费,可换算人民币,适合算 API 成本账(GitHub Pages 托管,国内通常可访问)。
  4. DeepSeek 官方:Token 用量计算文档
    官方提供中英文 token 换算比例与离线 tokenizer 下载,最贴近你实际要调用的模型。
  5. Codex Candy Eval:糖果题 Token 与推理用量评测
    题目二的原始项目。它展示了如何把题目送入模型、读取输入/输出/推理 Token,并用本地规则自动判分;阅读时也要留意“答案是否正确”和“判分规则是否可靠”是两个不同的问题。

Agent 与 Python 调用模型

  1. DeepSeek 官方:API 文档
    本章所用模型接口的官方入口,可查询 API Key、模型名称、费用和常见错误。
  2. DeepSeek 官方:对话补全 API
    可查阅 messages、model、temperature 等请求字段,以及 choices 和 token 用量等响应字段。
  3. python-dotenv(PyPI)
    .env 配置加载库的官方页面,含全部用法。
  4. OpenAI Python SDK(PyPI)
    OpenAI 兼容接口的官方客户端,DeepSeek 等国内模型可直接复用。

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @NEUP 2026 创建,使用 Stellaris 作为主题。

Hexo 强力驱动