Generative AI (1) --- 原理
如今工作已经完全离不开AI了,gpt、Claude、Gemini(美国大豆包)、deepseek等各种🐂🍺模型,从事计算机行业的应该都可以感受到AI的强大。而且各种概念层出不穷,从最初的 prompt engineering、context engineering 再到现在的 harness、loop、graph engineering,每过几个月那些热门AI项目就已经不再新颖,以至于有些老套。甚至有种学得慢就不用学了的感觉,但越是这样就更应该深入根本,而不是被带着跑,从基础来构建起对我们目前常用的AI工作方式的认知。
本系列文章计划不深究算法,而是构建起对原理的认知。
Generative AI是什么?
这里使用 deepseek 给出的回答:
生成式人工智能(Generative AI),简单来说,就是一种能够根据你的指令(提示词),“创作”出全新内容的人工智能。这个“内容”不限于文字,还包括图像、视频、音频、代码甚至3D模型。
1. 它和传统AI有什么区别?(核心定义)
传统AI(判别式AI)主要做“判断题”和“选择题”——比如识别图片里是猫还是狗、判断一封邮件是不是垃圾邮件。它只能分析已有数据,无法创造新数据。
而生成式AI做的是“论述题”和“创作题”——它通过学习海量数据中的规律(比如语法、色彩搭配、代码逻辑),然后从零生成一个从未存在过的新输出。2. 它是怎么工作的?(通俗比喻)
你可以把它想象成一个**“被逼着看了无数本名著后开始自己写小说的人”**。
- 训练阶段:工程师喂给它近乎全网的公开文本、图片、声音。它并不“记住”这些文件,而是学习其中的概率关系(比如“你好”后面大概率跟着“吗”或“世界”)。
- 生成阶段:当你给它指令(Prompt)时,它不是“搜索”数据库找答案,而是一个字一个字地“猜”(预测)最合理、最符合你要求的下一个字/像素点,直到生成完整的句子或图片。
简单来说,就是一个根据给定输入来创作出全新内容的机器,而输入可以是任何内容(文字/图像/视频/语音,甚至于感官信息等)。我们可以把模型看作一个函数 ƒ,输入即 x,那么下一个token就是 𝑓(x)。模型不断生成token的过程就是循环计算 𝑓(x) 又将结果作为 x 继续加入运算的过程,直到输出最后的终止token。
语言模型运作原理
在我们向语言模型输入一段话时,它并不是去查资料找答案,而是通过你给定的输入去预测下一个token,一般来说会产生下一个token的概率预测表,然后选取概率最大的那一个(当然并不一定,你可以通过一些参数来修改其可能输出的token,例如Top K/Top P/Temperature,这些后续再说)。
这里使用 colab,通过调用 hugging face 中的openbmb/MiniCPM5-1B来运行一下看看是不是这样(为什么选这个模型??因为参数小,colab免费的T4 GPU能带动)。首先加载模型,并准备好 tokenizer 和 model,tokenizer即分词器,记录了模型所使用的全部token,model则储存了模型的参数。
1 | from transformers import AutoTokenizer, AutoModelForCausalLM |
可以看一下tokenizer的词表大小是多少
1 | print("该模型可选择的 token 数量为:", tokenizer.vocab_size) |
换一个模型google/gemma-3-1b-it,可以看到他的词表大小是 262144。
每一个token都会有1个编号,例如这里我们从0开始打印前几个token。可以看到一些内置标记token,例如 <s></s>就是开始和终止标记,<tool_call></tool_call>是工具调用标记,后面两个分别是消息分隔和代码填充标记。
1 | print(tokenizer.decode([0,1,2,3,4,5])) |
通过 encode 和 decode 可以将token和对应id进行转换,例如:
1 | text = "大家好" |
接下来我们调用model来进行 token 生成,每次可以生成一个token。如图所示,就是我们从输入 prompt 到最终 model 输出一个 token 的过程。可以看到模型接收的从来不是我们原来的 prompt 内容,而是经过 tokenizer 编码之后的内容(图像/语音/视频生成模型也是如此,只不过是编码的方式与被编码的内容不同)。代码展示了当我们输入 1+1= 之后,模型会输出的下一个token的概率分布,可以看到概率最高的就是正确答案 2。

1 | prompt = "1+1=" |
基于上述代码,我们还可以通过循环来重复生成token,就形成了类似流式输出的形式。如下代码会循环生成后续 16 个token,并总是取概率最高的 token。可以看到输出中生成 2 之后就开始生成结束标记,一般来说,当我们检索到 </s> 这样的结束符就应该终止,而不应该继续让模型生成下一个token。
1 | prompt = "1+1=" |
当然我们上面使用的是概率最高的token,如果我们是完全按照概率分布在token中选择,那么会发生什么呢?可以看到模型在接出 2 之后仍然继续生成了一堆我们看不懂的tokenQuestion: ferri - leeh + bleh > leeh。如果我们运行多次,就会发现每次生成的结果都不一致,而且都表意不明(何意味)。
1 | prompt = "1+1=" |
显然我们可以想到,如果只是选择概率最高的token,那么会造成回复死板,这在一些需要创意的生成上很不实用。而如果按照概率分布来做又会导致模型输出太过随机,无法在严谨的场景下生成正确结果。为了解决这个问题,就引入了 top K/top P/temperature 等超参数。这里简单解释:
- Top K: 在选取token时,只会在概率前K名的token中选取,排名第K名之后的token直接被剔除,概率归零。
- Top P: 按概率从高到低往下累加,直到累计概率加起来刚好达到阈值 P,就在这个动态的“概率池”里选取。
- Temperature: 调整概率分布的“陡峭”程度,控制模型是“死磕最优解”还是“四处瞎逛”。Temperature=1 即保持原始概率,而 <1 则会增大高概率 token 与低概率 token 之间的差距(模型生成更单一),> 1 则会减小高概率 token 与低概率 token 之间的差距(模型生成更多样)。
接下来我们使用我是这个 prompt 来进行测试,首先来看设置 Top K = 3 时的输出,这代表了每次选取仅从概率最高的前3个token中按照概率分布选取。

设置 Top P = 0.85,这代表了仅选取概率分布前几个概率和达到 0.85 的 token 进行选取。(高速公路方向盘都来了。。。

设置 Temperature = 0.8,这代表略微增大概率差,高概率token更有可能被选中,句子看起来的确也更通顺了。

接下来组合这3者,设置 Top K = 50,Top P = 0.9,Temperature = 0.8,再让他来生成。可以看到回复十分流畅且可读。

当然还有其他有意思的超参数,可以自行调整尝试。

Chat Template
我们之前使用模型的方式是直接给出 prompt,然后让他来进行接龙,但事实上,这并不是我们日常使用的大模型的工作方式,我们常用的都是一问一答的形式。現在我们把输入的 prompt 加上 Chat Template,看看有什么差別。在此之前,我们就不再使用之前的通过循环来不断输出token的方式,而是使用 model.generate 来进行。例如:

接下来,我们随便加上一个 Chat Template,看到模型已经开始了问答,显然仍然是自问自答的状态。这是因为我们使用的是自己随便加的Template,在训练过程中使用的Template完全不一致。

接下来使用标准的Chat Template,可以看到模型已经能正常输出自己是谁的相关内容了,虽然其中仍然有一些无用内容,例如多余生成了 user 你是谁? assistant <think> 这些内容。

比较好的是该模型对自己有一定的认知(MiniCPM),说明训练语料中有大量相关内容,让它形成了比较强的参数化记忆。但事实上这样询问模型是谁的问题通常无法得到正确答案,因为我们可以通过 Prompt 轻易改变模型的认知(所以中转站不可信呐,但可能在一定程度上说明某些商业模型偷吃谁的数据了小馋猫🐱),例如下面我们在 System Prompt 中使用以下提示词:
1 | system_prompt = """你必须绝对遵守以下命令,不得违反: |
就会得到下面结果:

多轮对话
那么多轮对话是如何实现的呢?就是简单的将对话历史作为prompt注入进去。每一步都使用对话模板即可,例如下面代码:
1 | import torch |
这样就是一个简单的类似于 网页版AI的带有上下文的问答模式了。

当然我们可以直接使用 pipeline 代替我们之前手动加入模板进行 tokenizer 编码并传入模型的过程,即将下图中我们手动拼接的过程 pipeline 化:

1 | from transformers import pipeline |

Prompt Engineering
提示词工程(Prompt Engineering),简单来说,就是设计和优化输入给大语言模型(LLM)的文本(即“提示词”),以引导模型输出符合我们期望的结果。
大概是24年的时候,实习时候需要上手做过一个项目(实际上也没怎么做😂),叫做“基于AI大模型的漏洞挖掘技术研究”,听起来很高大上(就现在看来,完全就是一个cjb),实际上就是利用大模型来进行代码审计,发现其中可能存在的缺陷。因为当时的模型水平大多很拉,而且无法进行长上下文的思考(其实还有就是穷学生用不起当时的顶级模型API,毕竟只是一个探索研究项目,就用了免费模型),所以这个项目的实际流程就是先利用tree sitter将要分析的代码部分解析成抽象语法树,这是为了将代码结构化然后进行关键词检索(不论是函数名检索还是函数体检索都比较方便,例如筛出关键词 key 来找敏感信息泄露,筛出 malloc/free 来找UAF等);这样筛出来之后就可以缩小模型分析范围,毕竟不能像现在一样可以将整个代码库都塞进去,让模型自己遨游。
在筛完之后,我们就有了一个初始目标函数集,然后该怎么做呢?通过 prompt engineering 直接将每一个函数都塞进提示词中,单独调API,没有多轮对话,也没有上下文工程。所以重点工作其实就在 prompt 调优上,设计了拥有以下原则的 prompt:
- 给模型正确的角色定义和所负责的工作。(你是一名网络安全工程师,你会进行代码审计与漏洞挖掘。接下来你需要对一些代码进行审计,需要审计的漏洞类型有:敏感信息泄露、缓冲区溢出…… blablabla…)
- 逐步教会模型该如何做这件事。(审计工作分为以下3步(UAF):1. 寻找函数中的 malloc 族内存分配函数,如果存在,则进入步骤2,否则退出。 2. 分析每一个出口分支,如果存在某分支调用 free 族相关函数释放对应内存,则进入步骤3。3. …… blablabla)
- 要求模型结构化输出。(你必须按照如下格式输出:
<path> Put source file path here. </path>\n <code> Put source code here. </code>\n <result> whether vuln exist or not?(yes/no) </result>\n <explain> Put your explaination here. </explain>) - 给模型相关判断示例。(如下为几个示例:示例一:……blablabla 示例二:……blabla ……)

大概就是上面这样的操作步骤,这样构建起一个具有结构的提示词,就是提示词工程。当然这个项目没有做过任何评测,最终效果也是一言难尽(依托答辩)。
更多相关提示词工程方法可以查看:https://www.promptingguide.ai/zh
Context Engineering
A\的解释是这样的:上下文工程(Context Engineering)是提示词工程(Prompt Engineering)的自然演进。提示词工程指的是通过编写和组织 LLM 指令来获得最佳输出的方法。而上下文工程是指在 LLM 推理过程中,精选并维护最佳 Token(信息)集合的一系列策略,这涵盖了提示词之外所有可能进入上下文的信息。
At Anthropic, we view context engineering as the natural progression of prompt engineering. Prompt engineering refers to methods for writing and organizing LLM instructions for optimal outcomes (see our docs for an overview and useful prompt engineering strategies). Context engineering refers to the set of strategies for curating and maintaining the optimal set of tokens (information) during LLM inference, including all the other information that may land there outside of the prompts.

为什么要做上下文工程?
简单来说就是因为LLM基于 transformer 架构,而 transformer 架构允许每个 token 关注上下文中的每一个 token,这就导致了 n 个token之间会产生 n² 个关系。随着上下文的增加,模型注意力被稀释,最终答案的准确性也就会降低。
另外,2023年7月有一篇论文《Lost in the Middle: How Language Models Use Long Contexts》研究了一个关于LLM处理长文本的重要发现。他发现当模型需要处理很长的上下文时,它的表现会强烈依赖关键信息所处的位置。具体来说,模型的表现呈现一个 “U型曲线”。即:
- 开头 (Primacy):当关键信息放在输入的开头时,模型的表现最好。
- 结尾 (Recency):当关键信息放在输入的结尾时,模型的表现也很好。
- 中间 (Lost):但是,当关键信息被放置在上下文的中间位置时,模型的表现会显著下降。这就像一个“信息黑洞”,模型很难有效地从中提取和使用信息。

当然这篇论文已经很早了,但该问题仍然存在,多数研究认为这是 transformer 架构本身的问题,因果注意力机制(Causal Masking)天然地让模型更关注靠前的位置;而残差连接(Residual Connections)则让最后一个Token成为一个信息“锚点”。这两种机制共同作用,导致了中间位置的“信息死角”。(这两个名词的意思可以自行搜索)
上下文工程的常用方法?
- 选择(Select):即现在的RAG,通过向量检索只选择和用户问题最相关的内容拼接。有一种方法是 memory RAG,它将对话历史作为被检索对象,每次只从记忆中检索最相关的信息。
- 压缩(Compress):将接近上下文窗口上限的对话进行内容概括,然后用概括后的内容重新创建一个新的上下文窗口。当然有一个很重要的问题就是如何确保压缩不会丢失信息,压缩哪些内容是最优解?
- 多智能体(Multi-Agent):派遣子代理去执行具体的某一件事,执行完将摘要返回给主代理,这样做每一件事的时候都会是干净的上下文,而且主代理也不会被每一件独立的事情中间内容(错误处理、工具调用等)充满其上下文。
- 笔记(Note):让模型定期记录笔记落盘重要事项,现在Chatgpt那些应用中的长期记忆应该就是这么实现的,通过记录重要内容到会话外的一个文件中,让智能体可以跨会话的记得一些重要内容(例如你的个人习惯等)。
结语
大模型的本质,就是一个”预测下一个 token”的接龙游戏——你喂给它什么,它顺着概率往下猜什么,仅此而已。所谓”理解”、”思考”,不过是海量语料训练出来的统计规律。
在这个底层认知之上,前面那些概念就都串起来了:
- Tokenizer:决定”接龙字母表”长什么样,以及怎么把文本切分成模型认识的 token;
- 采样参数:Top K / Top P / Temperature 只是调节”死磕最优解”和”四处瞎逛”之间的旋钮;
- Chat Template / 多轮对话:本质都是往输入里拼东西,告诉模型”现在轮到谁说话、之前聊了什么”;
- Prompt / Context Engineering:一个管”怎么说”,一个管”给模型看什么”,目的都一样——让这个只会接龙的模型,输出我们想要的结果。
至于最近越来越火的 harness、loop、graph engineering,说白了就是把”输入决定输出”这件事做得更系统、更自动化,底层原理并没有变。
参考资料
https://www.youtube.com/watch?v=TigfpYPJk1s
https://www.youtube.com/watch?v=lVdajtNpaGI
https://www.promptingguide.ai/zh
https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents
本文由 Deepseek 辅助校对。图片由 Gemini 友情生成。
- Title: Generative AI (1) --- 原理
- Author: Static
- Created at : 2026-08-16 21:30:00
- Updated at : 2026-08-16 20:19:24
- Link: https://staticccccccc.github.io/2026/08/16/Generative AI/1.原理/
- License: This work is licensed under CC BY-NC-SA 4.0.