程序员学 AI(二):LLM 到底是什么?程序员应该知道的大模型基础概念
《程序员的 AI 工程入门》系列第 2 篇
本文定位:不深入复杂数学,从程序员角度理解 LLM 的基本原理,并亲手实现一个最简单的 Language Model。
上一篇,我们先建立了一张现代 AI Application 的整体地图:

用户任务
↓
Context
↓
LLM
↓
Tools
↓
Result
↓
回到 Context
这一篇,我们把其中最核心的一块单独拆出来:
LLM
我们主要回答几个问题:
- LLM 到底是什么?
- 它为什么能回答问题、写代码?
- 所谓“生成”到底是怎么发生的?
- 今天经常说的“推理模型”,和生成是什么关系?
- GPT、Claude、Gemini、DeepSeek、Qwen 又是什么?
- 我们能不能自己写一个最简单的 Language Model?
- 为什么模型会 Java,却不知道你项目里的 UserService.java?
一、LLM 到底是什么?
LLM 是:
Large Language Model
中文通常翻译成:
大语言模型。
如果站在程序员使用 AI 的角度,可以先给它一个简单定义:
LLM 是一种经过大规模数据训练得到的模型,它能够根据输入的信息理解上下文、进行一定程度的推理,并生成后续内容。
可以先把它画成:
输入一组信息
↓
LLM
↓
理解 / 推理 / 生成
↓
得到结果
例如输入:
请解释一下 Java HashMap 的底层原理。
模型可以输出:
HashMap 底层主要由数组、链表和红黑树组成……
输入:
public User getUser(Long id) {
return userMapper.selectById(id);
}
然后告诉模型:
分析一下这段代码可能存在的问题。
模型也可能给你:
1. selectById(id) 可能返回 null。
2. 调用方如果默认 User 一定存在,可能出现空指针。
3. 可以根据业务场景增加异常处理。
所以对于程序员来说,LLM 最值得关注的地方不是它的名字。
而是:
我们第一次获得了一种可以直接处理自然语言、代码、日志、SQL、JSON 等信息的通用模型能力。

二、程序员可以先把 LLM 理解成“超级自动补全”
如果一上来就讲:
Transformer
Attention
Token
Embedding
神经网络
很容易把问题讲复杂。
对于程序员来说,有一个更容易建立直觉的入口:
自动补全。
例如你在 IDEA 里输入:
System.out.pr
IDE 很可能提示:
System.out.println()
再比如:
List<String> list = new Array
IDE 可能猜测你接下来想写:
new ArrayList<>()
它是在根据:
前面已经出现的内容
判断:
后面最可能出现什么
LLM 当然远比 IDE 自动补全复杂。
但是理解它最基础的生成机制,可以从这里开始。
假设当前已经有:
HashMap 底层主要由数组、
模型会判断:
接下来最可能出现什么?
可以把结果极度简化成:
链表 48%
红黑树 17%
哈希表 9%
集合 3%
其他 …
模型选择:
链表
于是已有内容变成:
HashMap 底层主要由数组、链表
然后再次判断:
下一个是什么?
可能生成:
和
再继续:
红黑树
最后得到:
HashMap 底层主要由数组、链表和红黑树组成。
这就是一个非常重要的基本思想:
根据前面的内容,预测并生成后续内容。

三、LLM 真正是怎么生成一句话的?
当然,真实 LLM 并不是简单地:
查一张“下一个词概率表”
但如果暂时隐藏复杂的神经网络计算,可以把整个生成过程理解成:
用户输入
↓
拆成 Token
↓
模型读取当前 Context
↓
计算下一 Token 的概率
↓
选择一个 Token
↓
把 Token 加到已有内容
↓
再次计算
↓
不断循环
↓
形成完整结果
这里先只理解三个概念:
Token
Model
Generation
就够了。

四、模型根据什么决定“下一个 Token”?
这里才真正涉及:
Model
也就是:
模型
LLM 并不是一堆:
if
else
switch
组成的规则系统。
例如我们没有写:
if (question.contains("HashMap")) {
return "数组、链表、红黑树";
}
模型依然可能回答 HashMap。
为什么?
因为在模型真正被使用之前,还有一个非常重要的阶段:
Training
也就是:
训练。
训练过程可以极度简化成:
大量文本和代码
↓
让模型不断预测后续内容
↓
预测错误
↓
调整内部参数
↓
继续预测
↓
继续调整
↓
重复很多很多次
训练结束以后,就得到:
训练好的模型参数
以后我们向模型提问时,并不是重新训练它。
而是:
输入
↓
使用已经训练好的参数进行计算
↓
得到下一个 Token 的概率

五、模型参数是什么?
程序员第一次看到:
模型有多少参数
经常容易和 Java 方法参数混在一起。
例如:
public User getUser(Long id)
这里的:
id
是方法参数。
但模型参数不是这个意思。
可以先把模型参数理解成:
模型通过训练学到的大量内部数值。
例如只是为了示意:
w1 = 0.38492
w2 = -0.29381
w3 = 1.28491
w4 = 0.00391
…
真正的大模型内部当然复杂得多。
这些参数共同影响模型:
如何理解当前输入
哪些信息之间有关联
接下来应该生成什么
这里非常容易产生一个误解:
模型参数 = 知识数据库
其实不是。
模型内部并不是简单存着:
HashMap = 数组 + 链表 + 红黑树
Spring Boot = Java 框架
Redis = 内存数据库
然后回答问题时执行:
SELECT answer
FROM model_knowledge
WHERE question = ?
不是这样的。
更准确的理解是:
大量语言规律、代码模式、概念关系和知识,以复杂的形式编码进了模型参数。

六、为什么模型会 Java?
现在这个问题就比较容易理解了。
训练阶段,模型会接触大量:
自然语言
代码
技术文档
代码解释
软件工程内容
模型不断学习:
前面的内容
↓
后面通常会出现什么
例如看到:
for (int i = 0;
后面经常会出现:
i < list.size();
i++
看到:
@RestController
可能经常和:
Spring
@GetMapping
@PostMapping
@RequestMapping
HTTP
Controller
一起出现。
看到:
Map<String, User>
可能和:
HashMap
put
get
key
value
形成关系。
训练规模足够大之后,模型逐渐形成非常复杂的:
语言模式
代码模式
概念关系
知识关联
所以它开始表现出:
Java 理解能力
Python 能力
SQL 能力
代码生成能力
这就是所谓:
模型能力。
七、今天的 LLM 不只是“自动补全”
讲到这里,还需要特别说明一件事。
如果只说:
LLM 就是超级自动补全。
其实也不够准确。
它只是一个非常适合入门理解的比喻。
今天的大模型已经表现出了非常强的:
理解
推理
规划
代码分析
问题拆解
工具选择
能力。
例如你问:
一个商品原价 100 元。
先涨价 20%,
然后再打八折。
最后是多少钱?
模型需要得到:
100 × 1.2 = 120
120 × 0.8 = 96
最终回答:
96 元
再比如程序员问:
Spring Boot 服务突然很卡。
CPU 不高。
内存不高。
部分 SQL 接口超时。
SSH 也开始卡顿。
应该怎么排查?
这时候模型需要综合:
CPU
内存
磁盘 IO
数据库
慢 SQL
网络
线程
连接池
系统负载
再给出一个合理的排查顺序。
这种能力通常叫:
Reasoning
也就是:
推理能力。
八、生成和推理是什么关系?
现在经常会看到:
推理模型
Reasoning Model
于是很容易产生一个疑问:
以前是生成式 AI,现在是不是已经进入“推理 AI”,生成已经过时了?
不是。
Generation 仍然是 LLM 非常核心的输出机制。
最终模型依然需要不断:
生成 Token
才能形成:
回答
代码
JSON
Tool Call
所以:
生成
和:
推理
并不是新旧替代关系。
可以这样理解:
生成
=
模型把结果输出出来的基本方式
推理
=
模型解决复杂问题时表现出的能力
一个推理能力很强的模型,最终依然需要:
Token
↓
Token
↓
Token
↓
组成结果
所以今天更准确的理解是:
LLM
│
┌─────────┴─────────┐
│ │
生成能力 推理能力
│ │
└─────────┬─────────┘
↓
输出结果
现代 LLM 已经不只是:
给一句话
↓
续写一句话
越来越多模型能够:
理解问题
↓
拆解问题
↓
进行多步推理
↓
必要时选择工具
↓
验证结果
↓
生成最终回答
但是从模型输出机制来说:
最终仍然需要生成后续 Token。

九、GPT、Claude、Gemini、DeepSeek、Qwen 是什么?
理解了 LLM,再看这些名字就容易很多。
首先:
LLM
是一个技术类别。
类似:
Database
下面可以有:
MySQL
PostgreSQL
Oracle
同样:
LLM
├── GPT 系列
├── Claude 系列
├── Gemini 系列
├── DeepSeek 系列
└── Qwen 系列
可以先理解为:
不同厂商推出的大语言模型品牌或模型系列。
不同模型可能在:
代码能力
数学能力
推理能力
多语言
上下文长度
速度
成本
视觉
工具调用
方面表现不同。
其中 GPT 这个名字本身就很有代表性:
GPT
=
Generative
Pre-trained
Transformer
也就是:
Generative
生成式
Pre-trained
预训练
Transformer
Transformer 架构
这一篇我们已经讲了:
Generation
也简单讲了:
Training
至于:
Transformer
我们这一篇先不深入。
只需要知道:
它是今天大语言模型非常核心的一类模型架构。
十、模型和 ChatGPT、Codex、Claude Code 不是一回事
这里还需要分清:
模型
和:
AI 产品
比如:
GPT
Claude
Gemini
DeepSeek
Qwen
更多是在讨论:
模型 / 模型系列
而:
ChatGPT
Codex
Claude Code
Cursor
则更接近:
AI Application
可以简单理解:
AI 产品
↓
调用 LLM
↓
获得模型能力
但是 AI 产品通常还会增加:
文件读取
代码搜索
终端
浏览器
Memory
Tools
Agent Loop
权限控制
Sandbox
Context 管理
所以:
LLM
≠
完整 AI 产品
这个区别后面会越来越重要。
十一、我们能不能自己写一个最简单的 LLM?
真正的:
Large Language Model
当然不是几十行 Java 就能实现的。
因为真正的大模型需要:
海量训练数据
大量模型参数
GPU
Transformer
复杂训练系统
巨大的算力
但是:
我们完全可以自己写一个 Mini Language Model,理解 Language Model 最基础的思想。
注意:
Mini Language Model
不是:
真正的 LLM
但它可以帮我们理解:
给定前面的内容,预测后面的内容。
十二、先准备一点“训练数据”
假设我们只有下面几句话:
我 喜欢 Java
我 喜欢 Spring
我 喜欢 AI
Java 是 编程语言
Spring 是 Java 框架
AI 是 人工智能
为了让程序简单一些,我们假设:
空格
就是 Token 分隔符。
于是:
我 喜欢 Java
可以拆成:
我
喜欢
Java
我们开始统计:
当前 Token
后面通常出现哪个 Token
例如:
我 → 喜欢
出现了:
3 次
而:
喜欢
后面出现:
Java 1 次
Spring 1 次
AI 1 次
于是我们可以得到:
我
↓
喜欢 100%
喜欢
├── Java 33%
├── Spring 33%
└── AI 33%
这其实已经是一个极其简单的:
Language Model

十三、用 Java 实现训练过程
我们可以使用:
Map<String, Map<String, Integer>>
保存:
当前 Token
↓
下一个 Token 出现次数
代码:
import java.util.*;
public class MiniLanguageModel {
private final Map<String, Map<String, Integer>> model =
new HashMap<>();
public void train(String text) {
String[] tokens = text.split("\\\\s+");
for (int i = 0; i < tokens.length – 1; i++) {
String current = tokens[i];
String next = tokens[i + 1];
model
.computeIfAbsent(
current,
k -> new HashMap<>()
)
.merge(
next,
1,
Integer::sum
);
}
}
}
训练:
MiniLanguageModel lm = new MiniLanguageModel();
lm.train("我 喜欢 Java");
lm.train("我 喜欢 Spring");
lm.train("我 喜欢 AI");
lm.train("Java 是 编程语言");
lm.train("Spring 是 Java 框架");
lm.train("AI 是 人工智能");
训练完成之后,模型内部可能类似:
我
└── 喜欢 : 3
喜欢
├── Java : 1
├── Spring : 1
└── AI : 1
Java
└── 是 : 1
Spring
└── 是 : 1
注意:
这里所谓:
训练
其实只是:
统计
而真正 LLM 的训练复杂程度要高无数倍。
但是思想已经开始接近:
根据大量已有内容学习“前面出现什么时,后面可能出现什么”。
十四、再实现“预测下一个 Token”
我们写一个最简单的方法:
public String predictNext(String current) {
Map<String, Integer> candidates = model.get(current);
if (candidates == null || candidates.isEmpty()) {
return null;
}
return candidates
.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElse(null);
}
例如:
predictNext("我");
返回:
喜欢
所以:
我
变成:
我 喜欢
接下来:
predictNext("喜欢");
可能返回:
Java
于是最终得到:
我 喜欢 Java
十五、让它自己连续生成
我们再写一个生成方法:
public String generate(
String start,
int maxTokens) {
StringBuilder result =
new StringBuilder(start);
String current = start;
for (int i = 0; i < maxTokens; i++) {
String next = predictNext(current);
if (next == null) {
break;
}
result.append(" ").append(next);
current = next;
}
return result.toString();
}
调用:
System.out.println(
lm.generate("我", 5)
);
可能输出:
我 喜欢 Java 是 编程语言
到这里,我们已经亲手完成了一个:
输入
↓
预测下一个 Token
↓
生成
↓
继续预测
↓
得到一句话
的小模型。
十六、我们刚才到底实现了什么?
我们的程序本质上是在做:
当前 Token
↓
查看训练数据中的统计关系
↓
预测下一个 Token
↓
生成
比如:
我
↓
喜欢
↓
Java
↓
是
↓
编程语言
这已经非常接近:
Language Model
这个名字最基础的含义。
也就是:
建立语言中前后内容之间的概率关系。
当然,我们的模型弱得可怜。
但是这个实验非常重要。
因为现在再听到:
预测下一个 Token
就不会觉得那么抽象了。
十七、真正的 LLM 和我们的 Mini Model 差在哪里?
差距当然巨大。
我们的模型:
Mini Language Model
训练数据:
几句话
Context:
主要看前一个 Token
模型:
Map + 统计次数
参数:
极少
能力:
只能生成非常简单的句子
真正的 LLM:
Large Language Model
训练数据:
海量文本、代码等数据
Context:
可以处理非常长的信息
模型:
Transformer
参数:
数量巨大
能力:
语言、代码、数学、推理、工具调用……
可以对比:
| 训练数据 | 几句话 | 海量数据 |
| 上下文 | 极短 | 很长 |
| 学习方式 | 简单统计 | 神经网络训练 |
| 模型结构 | Map | Transformer |
| 参数规模 | 极少 | 巨大 |
| 语言理解 | 几乎没有 | 很强 |
| 代码能力 | 没有 | 很强 |
| Reasoning | 没有 | 可以很强 |
| Tool Calling | 没有 | 可以支持 |
但是两者有一件事可以帮助我们建立联系:
已有内容
↓
计算后续内容
↓
继续生成

十八、那为什么“预测 Token”最终会变成推理能力?
这是最容易产生疑问的地方。
我们的 Mini Model 也会:
预测下一个 Token
但是它完全不会:
数学
推理
Java
写代码
分析系统
真正 LLM 为什么可以?
因为:
预测下一个 Token
听起来简单,但如果要在极其复杂的数据中把它做好,就必须学会很多东西。
例如:
public User getUser(
后面应该怎么写?
模型需要学习:
Java 语法
方法定义
类型
参数
代码结构
再比如:
100 元涨价 20%,再打八折
后面应该是什么?
模型需要掌握:
数字关系
百分比
计算步骤
再比如:
Spring Boot CPU 不高,
但 SQL 接口越来越慢
要产生高质量后续内容,模型需要形成:
数据库
磁盘 IO
连接池
线程
系统负载
这些概念之间的复杂关系。
所以:
“预测下一个 Token”是输出任务,但为了把这个任务做到足够好,模型内部必须学会越来越复杂的语言、知识和问题模式。
这也是为什么模型规模、数据规模和训练方式不断发展以后,会逐渐出现更强的:
理解
推理
代码
规划
能力。
十九、现在重新看“模型能力”
以后我们经常会说:
这个模型能力很强。
这里的能力可能包括:
自然语言理解
代码理解
代码生成
数学
Reasoning
长 Context
结构化输出
视觉
工具调用
多语言
如果你是 Java 程序员,实际更应该关注:
它能不能读懂 Spring 项目?
能不能分析异常栈?
能不能理解多个 Java 文件?
能不能生成可靠 SQL?
能不能按照已有代码风格修改代码?
能不能根据测试结果继续排查?
能不能正确使用 Tools?
这些才是真正在:
AI Application
里能感受到的模型能力。
二十、一个非常重要的问题:为什么它会 Java,却不知道我的 Java 项目?
现在假设你问模型:
HashMap 的底层结构是什么?
模型通常可以回答。
因为:
Java
HashMap
哈希表
数组
链表
这些知识和模式可能已经在训练过程中形成了模型能力。
但是如果你问:
我的 UserService.java
为什么出现空指针?
问题就不一样了。
因为:
UserService.java
可能是你今天上午才写出来的。
模型训练的时候根本没见过。
而且默认情况下:
你的电脑
│
X
│
LLM
模型也没有你电脑的文件读取权限。
所以:
会 Java
属于:
模型能力
但是:
知道你的 UserService.java
属于另一个问题:
模型这一轮到底看到了什么?
二十一、怎么让模型看见 UserService.java?
最简单的方法其实非常直接。
Java 程序先读取文件:
String code = Files.readString(
Path.of("UserService.java")
);
然后把代码一起交给模型:
String prompt = """
下面是 UserService.java:
%s
请分析代码中可能出现空指针的位置。
""".formatted(code);
最终:
UserService.java
↓
Java 程序读取
↓
加入模型输入
↓
LLM
↓
生成分析结果
所以:
不是模型突然看见了你的电脑,而是应用程序把代码提供给了模型。
这就是下一篇要正式进入的概念:
Context

二十二、LLM 和普通函数、数据库、搜索引擎有什么区别?
最后用一个简单表格收一下。
| 普通函数 | 按程序员提前写好的规则执行 |
| 数据库 | 准确存储和查询真实数据 |
| 搜索引擎 | 从已有资料中寻找相关信息 |
| LLM | 根据当前输入理解、推理和生成结果 |
例如:
int add(int a, int b) {
return a + b;
}
这是:
固定规则
数据库:
SELECT *
FROM orders
WHERE create_time >= CURDATE();
是在:
查询真实业务数据
搜索引擎:
Java 最新版本
是在:
寻找最新资料
而 LLM:
请根据下面 100 条订单,
总结最近用户消费变化。
是在:
理解
分析
推理
生成
它们不是谁替代谁。
现代 AI Application 更常见的是:
Database
+
Search
+
Tools
+
LLM
组合使用。
二十三、重新看一次 LLM
到这里,我们再回到文章开头。
最简单的理解仍然是:
输入一组信息
↓
LLM
↓
生成一个结果
现在我们已经知道,中间其实包含:
输入内容
↓
Token
↓
模型根据训练得到的参数进行计算
↓
预测后续 Token
↓
不断生成
↓
最终形成结果
而现代 LLM 在这个基础上,还逐渐表现出了:
理解
推理
代码
规划
工具选择
等更高级的能力。
所以,如果现在重新给 LLM 一个定义:
LLM 是一种经过大规模数据训练得到的语言模型。它根据当前输入和 Context 进行计算,并不断生成后续 Token,从而表现出语言理解、代码处理、内容生成和一定程度的问题推理能力。

