LLM 系列 (十二):预训练数据工程:大模型的燃料是如何炼成的

前面几篇我们已经把 LLM 的几条主线串起来了:从 AI 到 LLM,理解大模型为什么会出现;从数学、算法、Transformer 到 Dense/MoE,理解模型结构和学习机制;再到预训练、后训练、分布式训练、推理服务和长上下文,理解一套大模型系统如何被训练出来、部署出去。到了这里,还有一个更底层的问题需要单独展开:模型训练时,究竟吃了什么?

很多人讨论大模型时,容易把注意力放在参数量、GPU 数量、训练框架、Attention 结构、MoE 路由和推理加速上。但如果把大模型训练看成一条生产线,数据才是最早进入系统的原材料。没有好的数据,再大的模型也只是在更大规模地学习噪声;没有合理的数据配比,模型就会偏科;没有去重和去污染,模型可能只是记住了训练集和评测答案;没有隐私、安全、版权和版本治理,模型能力越强,风险也越难控制。

所以这篇文章想讲的,不是“怎么多收集一些文本”,而是预训练数据工程如何把互联网、书籍、代码、论文、百科、问答和合成样本,炼成一个可学习、可控制、可评估的数据分布。它贯穿数据来源、解析抽取、清洗规范化、去重、质量过滤、安全过滤、数据配比、采样、tokenization、packing、评测去污染、合成数据和版本治理,最终决定模型会学到什么、偏向什么、遗漏什么。

阅读更多

LLM 系列 (十一):长上下文:大模型如何读懂更长的信息

过去我们使用大模型时,常常会遇到一个很直观的限制:输入太长,模型放不下。一篇几十页的论文、一份完整的技术文档、一个代码仓库、一次持续很久的多轮对话,都可能超过模型能够处理的上下文窗口。

随着模型上下文长度从早期常见的 4K token,扩展到今天的 1M token 级别(例如 Gemini 1.5 Pro,以及后续部分 Claude / GPT / Gemini 系列模型),LLM 的使用方式也开始发生变化。它不再只是回答一个短问题,而是可以阅读完整资料、分析复杂代码、理解长期对话,甚至支撑 Agent 执行长程任务。

但长上下文并不只是“把窗口调大”。上下文越长,Attention 计算越重,KV Cache 越占显存,模型也越容易忽略中间信息,或者被大量无关内容干扰。真正的长上下文能力,不只是能放下更多 token,而是能在更长、更复杂的信息中找到关键内容,建立远距离关系,并以可承受的成本完成推理。

阅读更多

LLM 系列 (十):推理模型:大模型如何从回答走向思考

如果说推理服务回答的是“模型如何更快、更便宜地生成 token”,那么推理模型回答的就是另一个更接近能力本质的问题:模型如何在复杂任务中不急着给出结论,而是先分解问题、展开推导、检查约束、验证结果,再输出更可靠的答案。

这里的“推理”不再是 Inference Serving,而是 Reasoning。前者关注系统效率:吞吐、延迟、KV Cache、batch 调度和单位 token 成本;后者关注能力机制:模型为什么愿意多想几步,为什么数学、代码、逻辑和规划任务需要更多 test-time compute,为什么 DeepSeek-R1、OpenAI o 系列、Qwen3 thinking mode 都把“思考过程”和“推理预算”变成核心能力。

阅读更多

LLM 系列 (九):推理服务:大模型如何高效生成 Token

如果说分布式训练回答的是“大模型如何在千卡集群上训练出来”,那么推理服务回答的就是另一个更贴近线上系统的问题:模型训练完成之后,如何在真实业务流量下稳定、快速、低成本地生成答案。

这里的“推理”需要先做一个区分。它既可以指 Inference Serving,也可以指 Reasoning Model。前者关注模型服务系统:请求如何进入模型、token 如何生成、KV Cache 如何管理、延迟和吞吐如何平衡;后者关注模型能力机制:如何通过长链思考、验证器、强化学习和 test-time compute,让模型更擅长数学、代码和复杂推理。

本文讨论的是第一种:推理服务。它不关心模型参数如何继续学习,而关心一个已经训练好的模型,如何在固定参数下被高效调用。换句话说,预训练和后训练决定模型“会什么”,分布式训练决定模型“怎么训出来”,而推理服务决定这些能力能不能以可承受的成本、稳定地交付给真实用户。

阅读更多

LLM 系列 (八):分布式训练:千卡集群如何训大模型

如果说预训练回答的是“大模型的能力如何形成”,后训练回答的是“这些能力如何被塑造成可用行为”,那么分布式训练回答的就是一个更底层的工程问题:如此庞大的模型,如何真的在成百上千张 GPU 上稳定训练完成?

大模型训练从来不是把一个 PyTorch 脚本复制到很多张卡上那么简单。真正的挑战在于:模型参数放不下,激活值放不下,优化器状态放不下;单卡算力不够,跨卡通信会拖慢训练;训练中还可能遇到 loss spike、节点故障、checkpoint 写入过慢、MoE 负载不均和长上下文显存爆炸。规模越大,问题越不再是单点优化,而是计算、显存、通信、存储、调度和容错的系统协同。

阅读更多

LLM 系列 (七):后训练与对齐:从续写器到协作者

如果说预训练回答的是“大模型的通用能力从哪里来”,那么后训练回答的就是另一个更关键的问题:这些能力如何被稳定、可靠、可控地组织成用户真正可用的行为。

预训练后的 Base Model 已经学到了大量语言、知识、代码、数学和推理模式,但它本质上仍然是一个基于上下文预测下一个 token 的生成模型。它可以续写论文、代码、对话和网页,也可能生成看似合理但不一定真实、安全或符合用户意图的内容。换句话说,Base Model 拥有能力,但还没有被塑造成一个“助手”:它不天然知道什么叫听指令,什么叫有帮助,什么时候应该拒绝,什么时候应该承认不确定,什么时候应该调用工具完成任务。

阅读更多

LLM 系列 (六):预训练的本质:从预测下一个 Token 到通用能力

如果说 Transformer 解决的是“大模型如何理解序列”,Dense 与 MoE 解决的是“大模型如何扩展架构”,多模态解决的是“大模型如何接入更多世界信号”,那么预训练要回答的,就是一个更底层的问题:大模型的通用能力从哪里来?

前几篇我们已经铺垫了大模型的发展脉络、数学基础、算法原理、Transformer 架构和 Dense/MoE 架构。到这里,讨论进入 LLM 训练体系中最关键、最昂贵,也最决定能力上限的一环:预训练。它不是附属步骤,而是基座模型形成语言、知识、代码、推理和迁移能力的主要来源。

阅读更多

LLM 系列 (五):Dense 与 MoE,大模型如何从全量计算走向稀疏激活

过去几年,LLM 能力的提升很大程度上来自 Scaling Law:当模型参数量、训练数据规模和计算量持续扩大时,模型的 loss 往往会呈现较稳定的下降趋势,模型能力也会随之提升。简单来说,规模化训练证明了一件事:更大的模型、更大的数据、更大的算力,通常可以带来更强的模型能力。

但 Scaling Law 也带来了一个现实问题:如果能力提升依赖规模扩展,那么训练成本、推理成本、显存占用和部署复杂度也会同步上升。模型越大,每个 token 需要经过的参数越多;上下文越长,Attention 和 KV Cache 的压力越大;多模态输入又会引入更多 token 和更复杂的计算路径。

阅读更多

LLM 系列 (四):Transformer 架构篇:大模型为什么选择了 Transformer

前三篇文章里,我们已经分别从三个角度为理解大语言模型打了基础:第一篇看发展脉络,知道 LLM 是怎么一步步演进出来的;第二篇看数学基础,理解向量、概率、损失函数、梯度这些底层工具;第三篇看算法基础,从 NLP、词向量、感知机、神经网络,一路讲到 CNN、RNN 和双向 RNN。到了第四篇,我们终于可以进入现代大语言模型最核心的一块内容:Transformer

如果说前几篇是在回答“机器如何把语言变成可以计算的问题”,那么这一篇要回答的是另一个更关键的问题:为什么后来的主流大语言模型,几乎都选择了 Transformer 作为核心架构?

阅读更多

LLM 系列 (三):算法原理篇:机器是如何学会语言的

前两篇文章分别介绍了大模型的发展脉络和基础数学知识。到了第三篇,我们还需要补上一块很关键的地基:基本的算法原理。不过,这里的“算法原理”并不是一堂严肃的算法课。本文会尽量站在非算法同学的视角,用更通俗、直观的方式,把语言模型背后那些看起来复杂、晦涩的概念拆开讲清楚。

阅读更多

LLM 系列 (二):机器如何把语言变成数学

上一篇我们从大模型的发展脉络出发,回顾了语言模型如何从早期的统计方法,一步步走向 Transformer、GPT,以及今天无处不在的大模型应用。如果说第一篇回答的是“LLM 是怎么发展到今天的”,那么这一篇想往下多走一层,回答一个更底层的问题:LLM 为什么能被训练出来?机器到底是怎样把语言变成可计算、可优化、可生成的东西?

无论是 Transformer 里的 Attention,预训练里的 loss,微调时的梯度更新,RAG 里的向量检索,还是 LoRA 里的低秩矩阵,本质上都绕不开几类基础数学概念。不过,这篇并不是要把大家重新拉回大学数学课堂。我们不会从定理证明开始,也不会堆大量公式。更重要的是建立一套直觉:机器如何把文字变成向量,如何计算词与词之间的关系,如何预测下一个 token,又如何通过错误和梯度一步步修正自己

阅读更多

LLM 系列 (一):从 AI 到 LLM

过去几年,大语言模型(LLM)从实验室里的研究成果,迅速变成了普通人每天都能接触到的工具。ChatGPT、Claude、Gemini、DeepSeek 等产品,让很多人第一次直观感受到:机器不只是能搜索信息、识别图片、完成分类任务,它似乎开始能够理解问题、组织语言、代码生成、分析文档,甚至参与复杂决策。

但如果只把 LLM 理解成“一个很会聊天的 AI”,其实会低估它背后的技术演进。今天的 LLM,并不是突然出现的魔法,而是人工智能几十年发展积累后的结果:从早期的符号推理,到机器学习;从神经网络,到深度学习;从词向量、注意力机制,到 Transformer;再到预训练、后训练、分布式训练、推理服务、RAG、Agent 和多模态系统,每一步都在回答同一个问题:机器智能是如何产生并不断演进的?

阅读更多

Stateful Serverless 背后的 Flink StateFun 内部机制实现【译】

本篇是 Flink StateFun 的第二篇文章,文中的内容是来自 Stateful Functions Internals: Behind the scenes of Stateful Serverless 的翻译,这篇文章从上层把 Flink StateFun 的内核做了一个比较深入的介绍,个人认为它是一篇很不错的、用来了解 StateFun 内部机制的文章。

阅读更多

Flink StateFun 2.0 浅谈

Stateful Function(简称 StateFun)从 2019 正式对外宣布之后,今年 4 月份已经发了 2.0 版(并且是作为 Apache Flink 项目中的一部分发布),7 月份也发布了 2.1.0 版。在 2.0 的架构中 Function 已经从 JVM 中解耦出来,只需要通过 HTTP/gRPC 来调用即可,新的架构可以充分利用 FAAS 的能力。本篇文章就来简单看下 StateFun 的架构及应用示例,后面还会有陆续有两篇文章来深入剖析一些其内部实现。

阅读更多

Kubenetes 之新手入门篇

近几年来,随着以 Docker 为代表的容器技术的出现,终结了之前 DevOps 中交付和部署环节因环境、配置及程序本身的不同而造成的动辄几种甚至几十种部署配置的困境,将它们统一在容器镜像上。但 Docker 更适用于管理单个容器,一旦开始使用越来越多的容器封装和运行应用程序,必将会导致其管理和编排变得越来越困难。最终,用户不得不对容器实施分组,以便跨所有容器提供网络、安全、监控等服务。于是,以 Kubernetes 为代表的容器编排系统应运而生。本文就是对 Kubernetes 做一个简单的总结,主要从 Kubernetes 架构、组件和核心概念来简单讲述,是一篇关于 Kubernetes 的入门文章。

阅读更多

浅谈 CPU 分支预测技术

最近在看 SQL 优化之 Code Generation 相关的内容,我们知道 Code Generation 是 SQL 优化的大杀器之一,不管是在 Apache Spark 还是 Apache Flink 中都有比较深入的应用(特别是在 Spark 中),Code Generation 最开始是在数据库中应用的,Spark 将其引入到 Spark SQL 的中优化,后来的 Flink 也借鉴了这一思想。Code Generation 是要解决什么问题呢?相信大部分人应该有所了解,简单来说就是减少虚函数调用、尽可能利用 CPU 分支预测的能力(会在 Code Generation 部分详细介绍,这里只需要了解这一背景即可),那么什么是 CPU 分支预测(Wikipedia: CPU Branch Predictor)呢?为什么虚函数调用会极大消耗 CPU 性能呢?这就是本文将要给大家介绍的内容。

阅读更多

Flink 基于 MailBox 实现的 StreamTask 线程模型

本篇文章是 Flink 系列 的第八篇,在介绍 TaskManager 第二部分之前,先来给介绍一下目前 StreamTask 中基于 MailBox 实现的线程模型,这个模型从 1.9 开始实现,在目前发布的 1.10 版本中,基本上已经改造完成,具体 issue 见 FLINK-12477: Change threading-model in StreamTask to a mailbox-based approach,其设计文档见 Change threading-model in StreamTask to a mailbox-based approach,去年,vinoyang 也写了一篇关于它的介绍,见 重磅!Flink 将重构其核心线程模型。因为 Flink 1.10 已经发布,本篇关于 MailBox 实现的介绍会基于 1.10 最新的代码来讲述(系列的其他篇,没有说明的话,默认还是以 1.9 的代码为例),这个功能在 1.9 中还并没有完全完成,所以本文以 1.10 代码为例讲述。

阅读更多

Flink TaskManager 详解(一)

本篇文章是 Flink 系列 的第七篇,这篇文章主要会讲述 Flink 中的 TaskManager 的一些内容,TaskManager 是 Flink 的 worker 节点,它负责 Flink 中本机 slot 资源的管理以及具体 task 的执行。TaskManager 上的基本资源单位是 slot,一个作业的 task 最终会部署在一个 TM 的 slot 上运行,TM 会负责维护本地的 slot 资源列表,并来与 Flink Master 和 JobManager 通信,预计将会通过两篇左右的文章来向大家揭秘 TaskManager 内部的实现原理。另外,本篇将采用先提出问题,然后再根据源码实现去解答这些问题的形式叙述,如果大家有其他建议,欢迎(博客/公众号)留言反馈。

阅读更多

Flink JobManager 详解

本篇文章是 Flink 系列 的第六篇,紧接着上篇文章,本篇主要讲述 Flink Master 中另一个组件 —— JobManager(在源码中对应的实现类是 JobMaster)。每个作业在启动后,Dispatcher 都会为这个作业创建一个 JobManager 对象,用来做这个作业相关的协调工作,比如:调度这个作业的 task、触发 Checkpoint 以及作业的容错恢复等。另外,本篇文章也将会看下一个作业在生成 ExecutionGraph 之后是如何在集群中调度起来的。

阅读更多

Flink Master 详解

本篇文章是 Flink 系列 的第五篇,从这篇开始会向大家介绍一下 Flink Runtime 中涉及到的分布式调度相关的内容。Flink 本身也是 Master/Slave 架构(当前的架构是在 FLIP-6 - Flink Deployment and Process Model - Standalone, Yarn, Mesos, Kubernetes, etc 中实现的),这个 Master 节点就类似于 Storm 中 Nimbus 节点,它负责整个集群的一些协调工作,Flink 中 Master 节点主要包含三大组件:Flink Resource Manager、Flink Dispatcher 以及为每个运行的 Job 创建一个 JobManager 服务,本篇文章主要给大家介绍一下 Flink 中 Master 节点相关内容。

阅读更多