% 第二章：相关技术介绍

\section{相关技术介绍}

\counterwithin{table}{section}
\subsection{大语言模型 (LLM)}

\subsubsection{LLM 的起源、发展历程和关键里程碑事件}

大语言模型（LLM）是一种能够理解、生成并与人类语言交互的人工智能技术。
这些模型通过在海量数据集上训练，能够应对科学、技术、艺术和文化等广泛领域的问题，成为信息检索、内容创作和自然语言理解的关键工具。
LLM 主要基于 Transformer 架构，通过处理大规模文本数据来捕捉语言的复杂模式、语法规则和语义关系。

自然语言处理（NLP）的发展为 LLM 奠定了基础。
1966 年，约瑟夫·魏泽鲍姆创建的 ELIZA 被认为是第一个使用 NLP 的程序，它能根据用户输入的关键词给出预设响应。
随着计算机性能的提升，特别是在 20 世纪 90 年代，NLP 技术得到了显著发展。

词语表示方式的演进是 LLM 发展的关键环节。
传统机器学习方法使用数字表格表示词语，难以捕捉词语间关系。
词嵌入技术通过神经网络模型训练解决了这一问题，使模型能够根据上下文理解词语含义。
现代 LLM 采用自注意力机制，能够聚焦输入中的相关部分，评估每个词语在上下文中的重要性，从而提升理解和生成能力。

2017 年 Transformer 模型的引入是 LLM 发展的重要转折点。
基于自注意力机制的 Transformer 架构能有效处理长序列数据并实现并行计算，为大规模语言模型的训练铺平了道路。
2018 年，谷歌发布了 BERT，在自然语言理解任务中取得显著进展；同年，OpenAI 发布了 GPT-1，展示了生成连贯文本的能力。

随后几年，LLM 的规模和能力持续增长。
2019 年的 GPT-2 生成更具说服力的文本；2020 年拥有 1750 亿参数的 GPT-3 达到了前所未有的语言理解和生成水平；2022 年 ChatGPT 的发布引起公众广泛关注；2023 年 GPT-4 在准确性方面有所提升，并具备了多模态能力。
除 OpenAI 外，谷歌的 BERT、PaLM 和 Gemini 系列，Meta 的 Llama 系列，以及 Anthropic 的 Claude 系列等成为主流 LLM。开源模型如 BLOOM 和 LLaMA 的出现进一步推动了该领域发展。

LLM 发展的显著趋势是参数规模的扩大和能力的演变。
参数规模从最初的几百万发展到目前的数千亿甚至万亿，训练数据也从数十亿词语增长到数万亿 tokens，这一趋势被称为"新的摩尔定律"。
随着模型发展，LLM 从最初的文本生成和补全，逐渐展现出复杂推理、解决数学问题、翻译语言和编写代码等高级能力。
近年来，多模态 LLM 的出现扩展了应用范围，使其能够处理和生成文本、图像、音频等多种类型数据。 \textbf{表 \ref{tab:llm_milestones}} 总结了 LLM 发展中的关键里程碑事件。

		
\input{./figures/llm_milestones.tex}

\subsubsection{LLM 辅助编码}
大语言模型在辅助软件开发和编码方面展现出巨大的潜力。它们通过理解和生成代码，可以显著提高开发效率并改善代码质量。
LLM 在代码生成、代码补全、错误检测与修复等多个方面都有具体的应用。

在代码生成方面，LLM 能够根据自然语言描述生成代码片段甚至完整的函数。
开发者可以使用自然语言描述所需功能，LLM 即可生成相应的代码，从而加速开发过程。
例如，开发者只需描述一个排序算法，LLM 就能生成相应的代码实现。
一些知名的 LLM，如 OpenAI 的 Codex、Meta 的 Code Llama 和 Google 的 PaLM 2，都经过专门优化用于代码生成。
此外，LLM 还可以生成代码文档和注释，提高代码可读性和可维护性。

代码补全是 LLM 在编码辅助方面的另一重要应用。
LLM 能够根据已有代码上下文，预测并建议接下来可能需要的代码片段或整行代码，甚至生成完整的函数或类。
GitHub Copilot、Tabnine 和 Replit Ghostwriter 等工具通过集成到集成开发环境（IDE）中，为开发者提供实时的代码建议，显著提高了编码效率。
LLM 能够理解多种编程语言的语法、编码风格和编程实践，从而提供更智能、更准确的补全建议。

在错误检测与修复方面，LLM 也展现出强大能力。
LLM 可以分析代码，识别潜在的错误模式或问题，帮助开发者快速找到并修复 bug。
它们能够理解代码的语法、编码风格和编程实践，从而识别出代码中的错误和潜在漏洞。一些研究表明，LLM 甚至能够根据错误信息和上下文生成修复代码的建议。
然而，需要注意的是，LLM 生成的代码可能并非总是完美，仍需要开发者进行审查和验证。

综上所述，大语言模型正日益成为软件开发过程中不可或缺的辅助工具。
它们通过代码生成、代码补全和错误检测与修复等功能，极大地提升了开发效率和代码质量。
随着 LLM 技术的不断发展，其在软件开发领域的应用前景将更加广阔。

\subsection{提示工程技术}
提示工程（Prompt Engineering）是设计和优化输入提示（prompts）的系统方法，旨在精确引导大语言模型（LLMs）生成符合预期的输出。
随着生成式人工智能技术的发展，提示工程已成为充分发挥模型能力的关键环节。通过精心构建提示的格式、结构、语言和上下文，提示工程能够显著提升模型理解用户意图的准确性，并引导其生成更加精确、相关且高质量的回应。
专业的提示工程师通过设计最优化的输入指令，使其与生成式 AI 系统的内部机制高效协同，从而获取更为精准和有用的输出结果。

提示工程的重要性主要体现在三个方面：首先，它能够显著提升模型性能，使 LLM 更准确地把握用户意图并生成高质量回复；
其次，通过提供结构化指令和丰富上下文，提示工程能够引导模型避开其训练数据中潜在的偏见和局限性；
最后，精心设计的提示能够优化用户与 AI 系统的交互体验，提高沟通效率和满意度。
在实际应用中，提示工程已成为连接用户需求与 AI 能力的关键桥梁，对于充分发挥大语言模型的潜力至关重要。

提示工程实践涉及多项核心原则和技术策略。
首先，清晰性和精确性是基本原则，即提示应当明确界定任务边界、避免模糊表述，并提供充分的背景信息和具体的输出要求（包括格式、长度、风格和语气等）。
其次，上下文管理作为关键技术，通过提供相关事实、参考资料和关键概念定义，可以显著提高模型输出的相关性和准确性。
同时，少样本学习（few-shot learning）技术通过在提示中嵌入示例性的输入-输出对，为模型提供直观的任务示范，有效引导其生成符合预期的回应。
此外，迭代优化作为核心方法论，通过系统性地测试不同表述方式和结构，并基于模型反馈持续调整，可以逐步提升提示效果。
更进一步，任务分解策略将复杂问题拆分为一系列相互关联的子任务，通过连贯的提示序列引导模型逐步解决问题，有效提升处理复杂任务的能力。
最后，角色定义技术通过为模型赋予特定身份或专业背景，能够引导其从特定视角生成更加专业和一致的回应。

\subsection{模型量化技术}
模型量化（Model Quantization）是大语言模型（LLMs）中使用的一种技术，旨在将高精度数据（通常是 32 位浮点数 (FP32) 或 16 位浮点数 (FP16)）的权重和激活值转换为低精度数据类型，如 8 位整数 (INT8) 或 4 位整数 (INT4)。
模型量化的主要目的是减少模型的内存占用、提高推理速度并降低能耗，使其更易于部署在资源受限的设备上，如移动设备或边缘服务器。

该技术的数学本质是通过线性映射将浮点值域$[r_{\text{min}}, r_{\text{max}}]$映射到整数空间，其量化与反量化过程可表示为：
\begin{equation}
\begin{aligned}
q &= \text{round}\left(\frac{r - r_{\text{min}}}{s}\right) \\
\hat{r} &= s \cdot q + r_{\text{min}}
\end{aligned}
\end{equation}
其中$s=(r_{\text{max}}-r_{\text{min}})/(2^n-1)$为量化步长，$n$为量化位数，$\epsilon=r-\hat{r}$为量化误差。

这种转换显著降低了存储模型所需的内存空间，并且由于低精度运算通常比高精度运算更快，因此可以提高模型的推理速度。
此外，更快的计算和减少的内存访问通常会降低功耗，这对于电池供电的设备尤其重要，这些极端量化形式显著减小模型尺寸和计算复杂度的同时，精度下降也更明显。

不同的量化级别（如 INT8 和 INT4）对模型性能和资源消耗影响不同。一般来说，更低的量化级别（例如从 INT8 到 INT4）可以进一步减少模型大小并提高推理速度，但通常会导致更大精度损失。量化误差分析表明，当权重服从均匀分布时，误差方差$\text{Var}(\epsilon)\approx s_W^2/12$，与量化步长平方成正比。内存优化效果可通过压缩比$(32-n)/32$量化，例如：
\begin{itemize}
\item INT8：75\% 内存压缩
\item INT4：87.5\% 内存压缩
\end{itemize}

INT8 量化通常被认为是性能和精度之间的良好折衷方案，可在保持较高模型准确性的同时，显著降低内存占用和提高推理速度。INT4 量化更为激进，可实现更高压缩率和更快速度，但通常伴随更明显精度下降，更适用于对资源限制非常严格但对精度要求相对较低的场景。选择合适的量化技术和级别需要在模型大小、推理速度和精度之间进行权衡，通常取决于具体应用场景和硬件条件。

\subsubsection{监督式微调（SFT）概述}

随着大规模预训练语言模型（Large Language Models,
LLMs）在自然语言处理领域展现出强大的通用能力，如何有效地将这些模型适配到特定的应用场景或下游任务中，成为了研究与实践的关键环节。监督式微调（Supervised
Fine-Tuning,
SFT）正是实现这一目标的核心技术之一。它指的是在一个已经经过大规模无标注数据预训练的基础语言模型上，利用一套有标注的、高质量的特定任务数据（通常表现为``指令-响应''或``输入-输出''对的形式）进行进一步训练的过程。

SFT的``监督''特性体现在其训练数据的形式上。与预训练阶段模型从海量文本中自主学习语言模式不同，SFT阶段向模型明确展示了在给定输入（如用户提问、指令）下，期望的、正确的输出（如恰当的回答、符合要求的文本）。模型在学习过程中，通过优化目标函数，不断调整自身参数，力求使其生成的响应尽可能地逼近标注数据中的目标响应。这种有指导的学习方式使得模型能够更精准地理解特定任务的格式要求、知识范畴以及交互模式。

采用SFT的主要目的在于提升模型在特定领域的性能表现和任务遵循能力。预训练模型虽然知识广博，但在特定专业领域或具体任务上的表现可能不够精确或不符合特定规范。通过在相关的高质量标注数据上进行微调，可以有效地向模型注入领域知识，提升其回答的准确性和相关性。同时，SFT也是引导模型学习遵循特定指令、模仿某种对话风格或角色的重要手段，使其行为更加符合人类预期，从而更好地服务于实际应用需求。因此，SFT是连接通用预训练模型与特定应用场景的关键桥梁，是使大模型``落地''不可或缺的技术步骤。在本研究中，我们采用SFT技术来定制化训练语言模型，以满足特定交互任务的需求。

\subsection{QLoRA 微调方法}
QLoRA是一种高效微调大语言模型（LLMs）的方法，它结合了量化和低秩自适应技术，旨在在资源受限的情况下实现与全精度微调相当的性能。QLoRA 的主要原理是在微调过程中冻结预训练 LLM 的权重并将其量化为 4 位精度，然后引入少量可训练的低秩适配器（Low-Rank Adapters, LoRA）。微调期间，梯度通过冻结的 4 位量化预训练语言模型反向传播到这些低秩适配器中。

QLoRA 引入了多项创新技术以在节省内存的同时不牺牲性能。首先是 4 位 NormalFloat (NF4) 数据类型，这是一种专为正态分布权重设计的新数据类型，在信息论上最优，并在实证研究中优于 4 位整数和 4 位浮点数。NF4 基于分位数化，确保每个量化区间分配相等数量的输入张量值，从而有效利用内存。其次是双重量化 (Double Quantization)，通过对第一步量化的量化常数再次进行量化，进一步减少平均内存占用，在不显著损失性能的情况下节省额外内存。最后是分页优化器 (Paged Optimizers)，利用 NVIDIA 统一内存特性管理训练期间的内存峰值，特别是在处理长序列的小批量数据时，从而避免内存不足错误。

QLoRA 的主要优势在于其能够在资源受限情况下实现高效微调。通过将预训练模型量化到 4 位并仅训练少量低秩适配器，QLoRA 显著降低了微调所需的 GPU 内存。例如，QLoRA 能够将微调一个 650 亿参数模型的平均 GPU 内存需求从超过 780GB 降低到低于 48GB，且不降低运行时或预测性能。这使得在单个消费级 GPU 上微调大型模型成为可能，从而大大降低了微调 LLM 的门槛。研究表明，使用 QLoRA 微调的 LLM 在各种任务上可以达到与全精度微调相当甚至更好的性能。

低秩适配器（LoRA）是 QLoRA 的关键组成部分。LoRA 的核心思想是，大型预训练模型在适应下游任务时，其权重变化具有低秩特性。因此，LoRA 冻结原始预训练模型的权重，并在每个 Transformer 层的自注意力模块中注入两个小的低秩矩阵（A 和 B）。LoRA 的数学原理可以表示为：
\begin{equation}
\begin{gathered}
W = W_0 + \Delta W = W_0 + BA
\end{gathered}
\end{equation}
其中，$W_0 \in \mathbb{R}^{d \times k}$ 是预训练模型中的原始权重矩阵，$\Delta W = BA$ 是低秩更新，$B \in \mathbb{R}^{d \times r}$，$A \in \mathbb{R}^{r \times k}$，且秩 $r \ll \min(d, k)$。通过这种方式，原本需要训练 $d \times k$ 个参数，现在只需要训练 $r \times (d + k)$ 个参数。例如，当 $d = k = 1000$ 且 $r = 8$ 时，可训练参数数量从 $10^6$ 减少到约 $1.6 \times 10^4$，减少了约 98.4\%。

微调过程中仅更新这些低秩矩阵的参数，原始模型的权重保持不变。这大大减少了需要训练的参数数量，从而降低了计算成本和内存需求。LoRA 的线性设计也确保与完全微调的模型相比，不会引入额外推理延迟。在推理阶段，可以将低秩更新与原始权重合并：$W = W_0 + BA$，从而不增加模型的推理延迟。QLoRA 通过结合量化和 LoRA，为在资源受限环境中高效微调大语言模型提供了有力方法，使得研究人员和从业人员能够更容易利用和定制最先进的 LLM，推动 NLP 领域进一步发展。

\subsection{Unsloth 算子}

Unsloth 是一个开源软件，旨在简化大语言模型（LLMs）的微调过程。它提供用户友好的界面和强大功能，可帮助 AI 开发初学者和专家轻松管理资源、优化性能并集成各种 AI 工具以提高模型准确性。
Unsloth 的核心优势在于其能够显著加速 LLM 的训练和推理过程，同时降低内存使用。

Unsloth 通过手动推导所有计算密集型数学步骤并编写自定义 GPU 内核来实现加速，而无需更改硬件。
它支持 NVIDIA 自 2018 年以来的各种 GPU，包括 Tesla T4 到 H100，并可移植到 AMD 和英特尔 GPU。
Unsloth 还与 Hugging Face 的 Transformers 库无缝集成，并支持其 TRL、Trainer 和 Seq2SeqTrainer 类。

Unsloth 的主要特点和优势包括：
\begin{itemize}
    \item 加速微调：能够将 LLM 的微调速度提高 2 倍以上，某些情况下甚至高达 30 倍
    \item 降低内存使用：显著减少微调过程中 VRAM 消耗，通常可减少高达 70\%-90\% 的内存使用，使得在有限 GPU 资源的机器上微调更大模型成为可能
    \item 零精度损失：声称在使用 QLoRA（4 位）和 LoRA（16 位）进行微调时不会造成精度下降
    \item 广泛模型支持：支持各种流行 LLM 架构，包括 Llama（版本 1、2 和 3）、Mistral、Gemma 和 Phi-3
    \item 多种训练算法支持：除标准微调外，还支持强化学习技术，如 直接偏好优化(DPO)、群体相对策略优化(GRPO)、近端策略优化(PPO)
    \item 动态 4 位量化：引入动态 4 位量化方法，旨在提高准确性，同时仅比标准 BnB 4 位量化多使用不到 10\% 的 VRAM
    \item 优化内核：所有核心操作均使用 OpenAI 的 Triton 语言编写，并具有手动反向传播引擎，提高了性能
    \item 易于使用和集成：提供易于使用的 Jupyter Notebook ，用户可快速开始微调模型，并与 Hugging Face 生态系统无缝集成
    \item 更快推理：对其支持的所有模型实现 2 倍更快的推理速度
    \item 模型导出：微调后模型可轻松导出为 GGUF、Ollama、vLLM 和 Hugging Face 等各种格式
    \item Windows 支持：可在 Linux 和 Windows 上运行
\end{itemize}
Unsloth 通过优化内存使用和速度，使得在资源有限环境中进行 LLM 微调和推理变得更容易、更高效，推动了 LLM 技术的更广泛应用。

\subsection{Gradio 框架}

Gradio 是一个开源 Python 包，允许用户快速构建机器学习模型、API 或任何任意 Python 函数的演示或 Web 应用程序。用户可以使用 Gradio 的内置共享功能在几秒钟内分享其演示或 Web 应用程序的链接。该框架无需 JavaScript、CSS 或 Web 托管经验，使其成为机器学习从业者和研究人员的理想工具。

Gradio 提供了一系列核心特性，使其在机器学习应用开发中脱颖而出。通过简单的 pip 安装，用户只需在项目中添加几行代码即可创建功能完备的 Gradio 界面。Gradio 能够与任何 Python 库无缝集成，只要用户能够编写 Python 函数，就能利用 Gradio 构建交互式应用。在展示和共享方面，Gradio 界面可以轻松嵌入 Python 笔记本或作为独立网页呈现，并能自动生成公共链接，方便用户与同事共享，使他们能够远程与用户计算机上的模型进行交互。此外，创建的界面还可以永久托管在 Hugging Face Spaces 上，Hugging Face 将在其服务器上托管界面并提供持久的共享链接。

Gradio 框架提供了多种构建组件，适应不同的应用需求。\texttt{gr.Interface} 是一个高级类，专为创建接受一个或多个输入并返回一个或多个输出的机器学习模型演示而设计。它接受三个核心参数：\texttt{fn}（要包装用户界面的函数，通常是机器学习模型的预测函数）、\texttt{inputs}（用于输入的 Gradio 组件，数量应与函数参数数量匹配）和 \texttt{outputs}（用于输出的 Gradio 组件，数量应与函数返回值数量匹配）。对于需要更高度定制化的布局和数据流，Gradio 提供了 \texttt{gr.Blocks} 类作为低级方法。Blocks 支持精确控制组件显示位置、处理多个数据流和更复杂的交互（例如将输出作为其他函数的输入），以及根据用户交互动态更新组件属性或可见性。此外，Gradio 还包含 \texttt{gr.ChatInterface} 高级类，专门用于创建聊天机器人用户界面，用户只需提供处理函数，Gradio 就会自动创建功能齐全的聊天机器人界面。

Gradio 不仅是一个用户界面库，更是一个通过 UI 和 API 与机器学习模型交互的完整框架，在性能、安全性和响应能力方面提供强大保证。它包含完整的 Python 和 JavaScript 库生态系统，支持以编程方式在这两种语言中构建或查询机器学习应用。Gradio Sketch 功能允许用户无需编写代码即可构建 Gradio 应用，只需在终端中键入 gradio sketch 即可打开可视化编辑器，用户可以通过 Web 界面定义和修改组件、调整布局、添加事件。在流式输出方面，Gradio 通过使用 \texttt{yield} 语句的简单 Python 生成器提供流式传输功能，支持令牌到令牌的文本生成流式传输、逐步图像生成更新，甚至通过 HTTP Live Streaming (HLS) 协议实现流畅的音频和视频流式传输。

Gradio 框架的主要优势在于其易用性、灵活性以及与机器学习生态系统的强大集成，使其成为构建和共享机器学习模型演示的理想选择。通过简化从模型到用户界面的过程，Gradio 使研究人员和开发者能够更专注于模型本身的开发和优化，同时提供直观、交互式的方式向他人展示其工作成果。