Large Language Models: 改变世界的语言革命

前言 2018 年 6 月,OpenAI 发布了首个基于 Transformer 架构的语言模型 GPT(Generative Pre-trained Transformer),标志着大语言模型(Large Language Models, LLM)时代的到来。 笔者接触 LLM 的时间很晚。笔者第一次了解到人工智能技术大约是在 2020 年,了解的是 Siri——一款 Apple 公司推出的智能语音助手。那时,笔者对人工智能的认知还停留在语音识别和图像识别这类传统的、基于规则或特定任务的 AI 技术上。 直到 2023 年,ChatGPT 的出现彻底打破了这种刻板印象。它不再是那种只会回答"对不起,我没听懂"的死板程序,而是展现出了令人惊叹的上下文理解与生成能力。直至 2024 年,LLM 已经跃升为人工智能领域的核心基础设施,并在自然语言处理、代码生成、知识问答等多个领域展现出强大的降维打击能力。 彼时,笔者第一次尝试使用 ChatGPT 进行代码生成,切身体验了 LLM 在编程辅助方面的巨大潜力。通过与 ChatGPT 的自然语言交互,笔者能够快速生成复杂的代码片段、精准调试报错程序。即使是面对晦涩的算法问题,它也能像一位不知疲倦的资深工程师一样,提供详细的逻辑拆解和替代方案。这种革命性的交互式编程体验,让笔者深刻认识到:我们正在经历一场软件工程范式的重构。 9.11 > 9.9 ?? 在大家惊叹于 LLM 无所不能的同时,也发生了一些令人啼笑皆非的"降智"事件。当时引发群众广泛讨论的一个有趣话题是:为什么询问 ChatGPT"9.11 和 9.9 哪个更大"时,它的回答往往是 9.11 更大? 人们尝试用不同的语气提问,甚至切换不同的语言,但早期的 LLM 几乎都会掉进这个陷阱。这一现象虽然看似荒诞,但却完美暴露了 LLM 底层运行逻辑的一个核心特征:它是一个"文字接龙"的高手,而不是一个内置了计算器的数学天才。 造成这个现象的原因主要有两个: 分词机制(Tokenization):LLM 看待世界的方式不是单个字母,而是"词元(Token)"。在切分 9.11 时,它可能会将其视为 9、.、11。在语言模型的潜意识里,整数 11 显然大于 9。 语料库的语义偏差:在人类互联网的海量文本中,带小数点的数字经常被用作"软件版本号"。从版本迭代的逻辑来看,v9.11 确实是 v9.9 之后发布的新版本。 这个经典的错觉引发了学术界和工业界对 LLM 逻辑推理边界的深刻反思,也成为了推动模型向"深度思考"和"强化学习"演进的催化剂。这让我们不禁要问:这些看起来像人的机器,到底是由什么构成的? ...

📅 June 22, 2026 · ⏱️ 20 min · 📝 约 3118 字 · 👁️ 次阅读

解析代码的正确姿势:Tree-sitter 的原理和实践

前言 如果你用过 GitHub Copilot、ChatGPT 或者其他 AI 编程助手,你可能会注意到它们在理解代码结构和语法方面表现得非常出色。这背后有一个关键技术—— Tree-sitter 。本文将深入探讨 Tree-sitter 的原理、它在 AI Agent 时代的不可替代性,以及如何在 Python 和 C++ 项目中构建一套代码解析流水线。 什么是 Tree-sitter? 简单来说,Tree-sitter 是一个用于解析代码的增量解析器生成器,它可以将源代码解析成抽象语法树(AST),并提供高效的增量更新能力。它支持多种编程语言,并且可以生成高性能的解析器,使得开发者能够快速构建代码分析工具、编辑器插件和其他与代码相关的应用。 AST(抽象语法树) 抽象语法树(AST,Abstract Syntax Tree),简称 AST,是源代码的抽象语法结构的树状表示。它位于源代码和机器代码之间,提供了一种更高层次的代码表示方式。AST 的节点表示语言的语法结构,如变量声明、函数调用、条件语句等,而边则表示这些结构之间的关系。 AST 的核心作用 代码分析:AST 提供了对代码结构的深入理解,使得静态分析工具能够检测潜在的错误、代码风格问题和安全漏洞。 代码转换:通过操作 AST,开发者可以实现代码的自动重构、优化和转换,例如将一种编程语言的代码转换为另一种语言。 代码生成:编译器可以通过 AST 生成目标代码,从而实现源代码到机器代码的转换。 例如,在 JavaScript 中,以下代码: javascript Copy function add(a, b) { return a + b; } 可以被解析为如下的 AST: ...

📅 June 21, 2026 · ⏱️ 12 min · 📝 约 1901 字 · 👁️ 次阅读

状态机——Agent 的行为骨架

前言 做 Agent 开发时,最让工程师头疼的问题往往不是底层大模型(LLM)不够聪明,而是 Agent 的行为难以可控。在真实的业务场景中,用户的一句话可能隐含多种意图,或者意图非常模糊。这就要求 Agent 必须学会在不同的"对话阶段"之间灵活切换——从最初的寒暄问候,到多轮的信息收集,再到决定调用外部工具,最后与用户确认并结束对话。 如果仅仅依靠 Prompt 让大模型自主决定下一步该做什么(例如纯粹的 ReAct 模式),系统会变得极其脆弱。模型可能会陷入死循环、产生幻觉,或者跳过关键的业务校验步骤。为了解决这种复杂性,我们需要引入软件工程中久经考验的标准工具:状态机(State Machine)。它能为概率性的 LLM 提供一个确定性的行为骨架。 什么是状态机 理解状态机最直观的方法是想象一扇普通的门。这扇门有两个状态:开 与 关。你可以对它施加两个事件(动作):推 与 拉。 如果你对一扇处于关状态的门执行推事件,门就会进入开状态。但如果门已经是开的状态,再执行推就没有任何意义(甚至是一个非法操作)。这就是状态机的核心逻辑:当前状态 + 触发事件 $\to$ 新状态。 在计算机科学中,它的形式化定义通常是一个五元组: 状态集合($S$):系统所有可能状态的有限集合。 初始状态($s_0$):系统启动时的默认状态($s_0 \in S$)。 事件集合($E$):触发状态改变的输入或条件。 转移函数($\delta: S \times E \to S$):定义了在特定状态下接收到特定事件时,应该转移到哪个新状态。 终止状态集合($F$):表示流程结束的状态集合($F \subseteq S$)。 在构建 Agent 时,我们通常会遇到两种常见的状态机类型: 有限状态机(Finite State Machine, FSM):状态和事件的数量是有限的,所有的状态流转(转移函数)都是在代码中严格预先定义好的。它非常适合逻辑固定、边界清晰的任务。 图状态机(Graph-based State Machine):这是目前复杂 Agent 框架的主流(如 LangGraph)。它的状态流转可以是动态计算的,原生支持条件分支、循环回路以及并行处理,更适合处理多轮对话和复杂的逻辑编排。 为什么 Agent 需要状态机 一个可靠的 Agent 绝不能是一个"黑盒"。它的运行生命周期应该经历明确的阶段,并且每个阶段(状态)都有单一、清晰的职责。我们来看一个典型的 Agent 运转流程: flowchart TD A[空闲 IDLE] -->|用户提问| B[分析意图 ANALYZING] B -->|需要工具| C[调用工具 TOOL_CALL] B -->|无需工具| D[生成回复 RESPOND] C -->|工具完成| D D -->|发送回复| A 在这个流程中,核心关键点在于意图分析后的条件分支。有些用户请求(如"你是谁?")可以直接生成回复;而有些请求(如"今天香港的天气如何?")则必须先去调用天气 API。 ...

📅 June 19, 2026 · ⏱️ 19 min · 📝 约 2903 字 · 👁️ 次阅读

PyMuPDF 使用指南:PDF 处理神器

前言 笔者今天在处理一批 PDF 文档时,使用了 pyMuPDF 库来提取文本和表格。今天在查阅相关文档时无意间发现了一个名为 pymupdf4llm 的库,它是基于 pyMuPDF 的一个扩展,专门针对将 PDF 内容转换为适合 LLM 输入的 Markdown 格式进行了优化。这个库不仅能提取文本,还能识别表格和图片,并将它们以 Markdown 语法的形式输出,非常适合我们在 RAG 流水线中使用。在这篇文章中,我们先重点关注下pyMuPDF的基本使用。 关于 PyMuPDF PyMuPDF 是一个功能强大的 Python 库,用于处理 PDF、XPS、OpenXPS、CBZ 和 EPUB 等文档格式。它提供了丰富的 API 来提取文本、图像、表格等内容,并支持对文档进行修改和注释。PyMuPDF 的核心优势在于其高效的解析能力和对复杂文档结构的良好支持,使得它成为处理 PDF 文档的首选工具之一。 安装 在 Python 环境中安装 PyMuPDF 非常简单: bash Copy pip install --upgrade pymupdf PyMuPDF 基础功能 1. 打开文档 python Copy import fitz # PyMuPDF 的别名 doc = fitz.open("example.pdf") # 打开 PDF 文档(路径填写相对路径或者绝对路径) print(f"文档页数: {doc.page_count}") 这里,doc 是一个 Document 对象,表示打开的 PDF 文档。你可以通过 doc.page_count 获取文档的总页数。如果你查看 doc 对象的类型,你会发现它是一个 Document 类的实例。 ...

📅 June 16, 2026 · ⏱️ 5 min · 📝 约 852 字 · 👁️ 次阅读

什么是机器学习和深度学习——从规则到数据的范式转移

前言 欢迎来到 Deep Learning 专栏。我们假设你修过一门传统机器学习课程(比如 HKU 的 COMP3314),或者对 ML 有基本了解;你也可能已经装过 PyTorch、跑通过几个示例项目,但对背后的数学原理还没有清晰的理解。这个专栏的目标是:从零开始,系统地拆解深度学习的核心概念和算法,让你不仅"能用",还能"懂"。 传统机器学习 想象一下我们小时候,父母是怎么教我们认识世界的。当你看到一只动物,父母可能会说:“这是一只猫——它有四条腿、毛茸茸的身体、喜欢吃鱼。” 我们会发现,想要区分一个东西是什么,我们会捕捉它的特征(四条腿、毛茸茸、喜欢吃鱼),并把这些特征和一个标签(猫)联系起来。这就是传统机器学习的核心思想:特征工程 + 模型训练。 在传统 ML 中,人类专家负责设计特征(例如图像的边缘直方图、纹理描述子),然后让算法(如 SVM、决策树)学习这些特征与标签之间的映射。这类方法在简单任务上效果不错,但当数据变得复杂——高分辨率图像、自然语言、原始音频——手工设计特征就成了瓶颈:你很难用几百个手工特征去描述一只猫的全部视觉变化。模型的性能天花板,本质上取决于特征的质量。 深度学习:为什么要"深" 为什么出现了深度学习? 在传统机器学习中,面对极其复杂且高维的数据时,依赖人工提取特征(比如手动设计边缘检测算子)遇到了难以逾越的瓶颈。深度学习的出现,正是为了解决“特征工程”的局限性。它通过引入多层次的组合原理,让模型自己从数据中学习表示。简单来说,较低的隐藏层学习简单的概念(如边缘、颜色),较高的隐藏层将这些简单概念组合成复杂的概念(如汽车、狗)。虽然早期的神经网络深受生物大脑机制启发,但现代深度学习已经不再将神经科学作为刚性指导,而是更多地依赖于应用数学(如线性代数、概率论、数值优化)来进行构建。 深度学习的历史 深度学习看似是近几年才爆发的全新领域,但实际上它已经经历了漫长的发展、多次改名与起伏。它的历史大致可以划分为三次浪潮: 第一次浪潮:控制论(Cybernetics,1940s–1960s) — 以生物学习理论为基础,出现了最早的线性模型(感知机 Perceptron、ADALINE)。当时人们希望通过逆向大脑的计算原理来建立智能。然而早期的线性模型存在严重局限——连简单的异或(XOR)函数都无法学习——直接导致了神经网络研究的第一次大衰退。 第二次浪潮:联结主义(Connectionism,1980s–1990s) — 核心思想是”大量简单的计算单元连接在一起时可以实现智能行为”。这一时期提出了对今天至关重要的分布式表示(Distributed Representation) 和 反向传播(Backpropagation) 算法,并引入了处理序列数据的 LSTM。但后来因投资者对 AI 的期望过高而不切实际,加之 SVM 等核方法的崛起,神经网络再次陷入低谷。 第三次浪潮:深度学习复兴(2006 年至今) — 以逐层贪婪预训练(Greedy Layer-wise Pretraining)为突破口,学术界终于找到了有效训练深层网络的方法。深度网络在测试样例上的泛化能力大幅提升,在图像识别、语音识别等复杂任务上全面超越了传统基于手工特征的 AI 系统。 为什么深度学习这几年才爆发 深度学习的核心算法(如反向传播)其实在 80 年代就已经存在,它的真正爆发和走向成熟主要归功于以下三个核心驱动力: 数据量爆炸:ImageNet(2009)、维基百科、YouTube 等大规模标注数据集的涌现。一个粗略的经验法则是:5000 个标注样本能达到可接受的性能,而 1000 万个样本能达到或超越人类水平。你在 COMP3314 课上学 SVM 或逻辑回归时,用的往往是数百行的小型结构化数据集;而 DL 时代面对的是百万级的复杂图像和文本,数据量本身催生了方法论的彻底变革。 算力与模型规模的指数级增长:GPU 从渲染管线变成并行计算引擎,CUDA 生态成熟。这使得神经网络的规模大约每 2.4 年就能翻一倍,如今庞大的参数量使网络能够处理前所未有的复杂任务。 算法演进与基建完善:ReLU 等现代激活函数的广泛使用解决了梯度消失问题、Batch Normalization 加速了训练、ResNet 让训练 100+ 层极深网络成为可能。同时,TensorFlow、PyTorch 等软件库极大降低了工程实现的门槛。 传统 ML vs 深度学习:一张对比表 维度 传统 ML(SVM、XGBoost) 深度学习 特征提取 人工设计,依赖领域知识 网络自动学习层次化表示 数据需求 几百到几千可训练 通常需要大量标注数据 计算资源 CPU 足够 GPU/TPU,训练成本高 可解释性 较高(特征权重可读) 较低,常被称为"黑盒" 代表任务 表格数据、小样本分类 图像、语音、NLP、生成 什么时候用传统 ML,什么时候用 DL 一个快速决策框架: ...

📅 June 15, 2026 · ⏱️ 12 min · 📝 约 1815 字 · 👁️ 次阅读

深度学习从拆箱开始——序言

为什么要写这个专栏 笔者在上学期学习了 COMP3314,一门传统机器学习课程。然而,传统机器学习在特征提取和模型设计上都需要大量的人工干预,难以适应复杂的现实世界数据。相比之下,深度学习通过多层神经网络自动学习数据的特征表示,在图像识别、自然语言处理等领域取得了许多重要突破。这个专栏旨在记录笔者从零开始学习深度学习的过程,分享理论推导和实战经验,希望能帮助同样对深度学习感兴趣的读者快速入门并逐步深入理解这一领域。 写作说明 这个专栏不会被写成一份固定课程表。深度学习本身发展很快,我自己的学习兴趣也会随着论文、项目和课程不断变化;如果一开始就把文章顺序钉死,反而容易限制后面真正想写的问题。 因此,这里更像是一组持续更新的学习笔记:有些文章会解释基础概念,例如什么是机器学习和深度学习;有些文章会拆解训练机制,例如正向传播与反向传播;也会有一些文章直接进入具体模型,例如为什么 ResNet 能训练 152 层。 如果某篇文章里的数学推导开始依赖更复杂的矩阵知识,我会把这部分拆到独立的 Math 专栏(线性代数 与 AI Math)里。比如 ResNet 中关于 Jacobian、向量-Jacobian 乘积和恒等矩阵的部分,就可以配合矩阵微积分如何服务反向传播一起看。这样,Deep Learning 专栏可以保持主线清晰,而数学细节也有足够空间展开。

📅 June 15, 2026 · ⏱️ 3 min · 📝 约 485 字 · 👁️ 次阅读

使用 GitHub Actions 将 Hugo 博客自动部署到远程服务器

前言 假如你经常更新博客内容,每次写完文章后还要手动登录服务器执行 rsync 命令来部署,就显得非常麻烦了。更理想的情况是:每次 push 代码到 GitHub 后,GitHub Actions 自动帮我们构建 Hugo 站点并同步到服务器上,这样我们就可以专注于写作,而不必担心部署细节。 什么是 GitHub Actions GitHub Actions 是 GitHub 提供的一套 CI/CD(持续集成/持续部署)工具,允许我们在代码仓库中定义自动化工作流程。当特定事件发生时(例如 push、pull request、release 等),GitHub Actions 就会触发相应的工作流程,执行预定义的任务。我们可以使用 GitHub Actions 来自动化构建 Hugo 站点,并将生成的静态文件部署到远程服务器上。 准备工作 要使用 GitHub Actions 自动部署 Hugo 博客,我们需要准备以下几个方面: 远程服务器:你需要有一台远程服务器,已经安装了 Nginx 或 Apache,并且配置好了网站根目录(例如 /var/www/html/)。 GitHub 仓库:你需要在 GitHub 上创建一个仓库,用来存放你的博客源码。这个仓库将作为 GitHub Actions 的触发源,当你 push 代码到这个仓库时,GitHub Actions 就会自动执行部署流程。 SSH 密钥:为了让 GitHub Actions 能够安全地连接到你的远程服务器并执行部署操作,你需要生成一对 SSH 密钥,并将公钥添加到服务器的 ~/.ssh/authorized_keys 文件中,同时将私钥存储在 GitHub 仓库的 Secrets 中。 什么是 SSH 密钥 首先,我们需要知道什么是 SSH 协议。SSH(Secure Shell)是一种网络协议,用于在不安全的网络上安全地访问远程计算机。SSH 使用公钥加密技术来验证用户身份和保护数据传输的安全性。 SSH 密钥对由两部分组成:公钥和私钥。公钥可以公开分享,而私钥必须保密。使用 SSH 密钥对进行身份验证时,用户将私钥保存在本地计算机上,并将公钥上传到远程服务器。当用户尝试连接到服务器时,服务器会使用公钥来验证用户的身份,如果验证成功,用户就可以访问服务器。 ...

📅 June 15, 2026 · ⏱️ 12 min · 📝 约 1815 字 · 👁️ 次阅读

初见

前言 大家好,这里是 HJJJ。 想必作为一个 CS 学生,搭建一个个人博客是必经之路。然而由于本人先前的懒惰,一直没有探索这个领域。直到最近,突然发现自己已经学了不少东西了,而有些学到的东西由于缺少实际应用,已经快要忘记了——于是我决定搭建一个个人博客,用来记录学习过程和心得体会。 什么是网站? 网站是由一系列通过超链接相互关联的网页组成的集合,通过域名访问,并托管在一个或多个服务器上。服务器负责存储网站的内容,域名则提供了用户访问的地址。网站可以包含文本、图片、视频、音频等多种类型的内容,用户通过浏览器来访问这些内容。 静态网站和动态网站 网站大致分为静态网站和动态网站两类。 静态网站是指那些内容固定不变的网站,用户访问时看到的内容是预先生成的。这些网站通常使用 HTML、CSS 和 JavaScript 来构建,内容由开发者手动编写和更新。静态网站的优点是加载速度快且安全性较高,因为它们不依赖服务器端的处理。 动态网站则是指那些内容可以根据用户的请求动态生成的网站。这些网站通常使用服务器端语言(如 PHP、Python、Ruby 等)和数据库来存储和管理内容。动态网站的优点是可以提供个性化的用户体验和更丰富的功能,但它们可能会面临性能和安全方面的挑战。 对于个人博客来说,大多数时候我们只是在展示静态内容——文章、图片、代码片段。动态网站的功能虽然强大,但维护成本和性能开销都更高。因此,静态网站生成器成了我的首选。 选择 Hugo 静态网站生成器有很多选择:Jekyll、Hexo、Hugo、Zola……每个都有自己的特点。我最终选择 Hugo,主要看中三点: 速度极快:Hugo 基于 Go 语言构建,生成整个站点通常只需要几毫秒到几秒,远快于大多数同类工具。 单文件部署:Hugo 是一个独立的可执行文件,不需要安装任何依赖环境,下载就能用。 主题丰富:Hugo 社区提供了大量现成的主题,直接拿来用就能得到一个美观的博客。 Hugo 允许用户使用 Markdown 文件来编写内容,并通过模板系统来定义网站的结构和样式,对我这种想专注于写作的人来说非常友好。 如何使用 Hugo 搭建博客 首先,你需要寻找一个地方来放你的源码。这里以 Windows 系统为例,打开命令行工具,进入你想要存放博客源码的目录。例如,我想把源码放在 D 盘的 blog 文件夹下: PowerShell Copy cd D:\blog 接下来,使用 Hugo 命令创建一个新的站点文件夹(我们这里先给它起名叫 myblog,你也可以换成别的名字): ...

📅 June 11, 2026 · ⏱️ 9 min · 📝 约 1401 字 · 👁️ 次阅读
Comments