\chapter{一维数据——序列与文本}

\section{篇章导读}

一维数据（1D Data）是人工智能处理的最基础、也是最重要的数据形态。你正在阅读的文字、你说出的一句话、股票市场的价格走势、建筑室内温度随时间的变化——这些都是一维序列数据。

与图像（二维）和三维模型（三维）不同，一维数据的核心特征是\textbf{有序性}：每一个元素的含义不仅取决于它本身，还取决于它在序列中的位置以及与前后元素的关系。“我吃饭了“和”饭我吃了”虽然包含相同的字，但含义截然不同——这就是序列的魅力与挑战。

本章将带你踏上一段激动人心的技术演进之旅：从早期的小型循环神经网络（RNN），到注意力机制的革命性突破，再到 Transformer 架构的横空出世，最终见证大语言模型（LLM）如何改变整个 AI 格局。这条从小模型到大模型的技术脉络，不仅是深度学习最精彩的故事之一，也直接关系到今天每一位设计师如何使用 AI 工具。

\textbf{核心线索}：序列数据的模型演进——RNN（小模型）→ 注意力机制 → Transformer → 大语言模型（LLM）


\section{学习目标}

\begin{itemize}
\tightlist
\item
  理解序列数据的特点与建模难点
\item
  掌握 RNN、LSTM、GRU 的基本原理
\item
  理解 Self-Attention 机制和 Transformer 架构
\item
  了解大语言模型的发展历程与关键技术
\item
  学会在设计场景中应用文本处理技术
\end{itemize}


\section{序列建模}

\section{为什么序列数据如此重要？}

在设计领域，序列数据无处不在：

{\def\LTcaptype{none} % do not increment counter
\begin{longtable}[]{@{}lll@{}}
\toprule\noalign{}
数据类型 & 示例 & 设计场景 \\
\midrule\noalign{}
\endhead
\bottomrule\noalign{}
\endlastfoot
文本序列 & 设计说明、用户评论 & 需求分析、情感分析 \\
时间序列 & 温度、人流量、能耗 & 环境监测、建筑性能 \\
操作序列 & 用户点击、浏览路径 & 交互设计优化 \\
空间序列 & 路径规划、动线分析 & 室内导航设计 \\
\end{longtable}
}

\subsection{序列数据的两大挑战}

\textbf{挑战一：变长问题}

图像的尺寸可以统一缩放，但文本的长度千变万化：

\begin{lstlisting}
"好"                → 长度 1
"这个设计方案不错"    → 长度 7
"请将客厅的主色调调整为暖色系，并增加自然采光"  → 长度 19
\end{lstlisting}

传统的全连接网络（MLP）要求固定大小的输入，无法直接处理变长序列。

\textbf{挑战二：时序依赖}

序列中元素的含义依赖上下文：

\begin{lstlisting}
"这个设计 很好"      → 正面评价
"这个设计 很好笑"    → 负面/调侃评价

"光线 不足"          → 设计问题
"光线 充足"          → 设计优点
\end{lstlisting}

模型需要“记住”之前看到的内容，才能理解当前内容。这正是\textbf{循环神经网络}要解决的核心问题。


\section{RNN：循环神经网络}

\subsection{核心思想}

RNN（Recurrent Neural Network）通过\textbf{隐藏状态}（Hidden State）在时间步之间传递信息，实现“记忆”功能。

\begin{lstlisting}
时间展开视图：

  x₁      x₂      x₃      x₄
  │       │       │       │
  ▼       ▼       ▼       ▼
┌───┐   ┌───┐   ┌───┐   ┌───┐
│h₁ │──→│h₂ │──→│h₃ │──→│h₄ │
└───┘   └───┘   └───┘   └───┘
  │       │       │       │
  ▼       ▼       ▼       ▼
  y₁      y₂      y₃      y₄
\end{lstlisting}

\subsection{数学表达}

在每个时间步 t，RNN 执行以下计算：

\begin{lstlisting}
隐藏状态更新：
    h_t = tanh(W_hh · h_{t-1} + W_xh · x_t + b_h)

输出计算：
    y_t = W_hy · h_t + b_y
\end{lstlisting}

其中： - \passthrough{\lstinline!x\_t!}：时刻 t 的输入 - \passthrough{\lstinline!h\_\{t-1\}!}：上一时刻的隐藏状态（"记忆"） - \passthrough{\lstinline!h\_t!}：当前时刻的隐藏状态 - \passthrough{\lstinline!W\_hh, W\_xh, W\_hy!}：可学习的权重矩阵

\subsection{直观理解}

想象你在阅读一份设计说明书：

\begin{lstlisting}
输入序列："客厅 采用 开放式 布局 以 增加 空间感"

时间步1：看到"客厅"    → h₁ = "在讨论一个房间"
时间步2：看到"采用"    → h₂ = "在讨论客厅的某个选择"
时间步3：看到"开放式"  → h₃ = "客厅选择了开放式布局"
时间步4：看到"布局"    → h₄ = "确认：客厅开放式布局方案"
时间步5：看到"以"      → h₅ = "接下来要说目的"
时间步6：看到"增加"    → h₆ = "目的是增加某个属性"
时间步7：看到"空间感"  → h₇ = "完整理解：客厅用开放式布局来增加空间感"
\end{lstlisting}

每一步，RNN 都在累积和更新对文本的理解。这就是“记忆”的力量。

\subsection{PyTorch 代码示例}

\begin{lstlisting}[language=Python]
import torch
import torch.nn as nn

# 定义一个简单的 RNN
class SimpleRNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super().__init__()
        self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        # x 形状: (batch, seq_len, input_size)
        out, h_n = self.rnn(x)  # out: 所有时间步的输出
        out = self.fc(out[:, -1, :])  # 取最后一个时间步
        return out

# 创建模型
model = SimpleRNN(input_size=100, hidden_size=64, output_size=2)
# 用于文本分类（如：正面/负面评价）
\end{lstlisting}


\section{RNN 的致命问题：梯度消失与梯度爆炸}

\subsection{问题根源}

RNN 需要通过反向传播跨越多个时间步来更新参数。当序列较长时，梯度要经过多次乘法运算：

\begin{lstlisting}
梯度回传路径（以4步为例）：

∂L/∂W = (∂L/∂h₄) · (∂h₄/∂h₃) · (∂h₃/∂h₂) · (∂h₂/∂h₁) · (∂h₁/∂W)
                └───────── 多次连乘 ──────────┘
\end{lstlisting}

\begin{itemize}
\tightlist
\item
  如果每步的梯度 \textless{} 1 → 连乘后趋近于 0 → \textbf{梯度消失}（学不到远距离依赖）
\item
  如果每步的梯度 \textgreater{} 1 → 连乘后趋近于 ∞ → \textbf{梯度爆炸}（训练不稳定）
\end{itemize}

\subsection{直观类比}

\begin{lstlisting}
传话游戏：

第1个人："把客厅漆成温暖的米黄色"
第2个人："把客厅漆成温暖的米……什么？"      ← 信息开始丢失
第3个人："客厅……漆成……？"                 ← 大量信息丢失
第4个人："什么客厅？"                      ← 几乎全忘了

RNN 处理长序列时遇到同样的问题！
\end{lstlisting}

在实际应用中，标准 RNN 通常只能“记住”5-10步之前的信息。对于“这个设计方案虽然外观简洁大方，功能分区合理，但是整体造价偏高”这样跨越多个分句的评价，RNN 可能会遗忘前半部分的内容。


\section{LSTM：长短期记忆网络}

\subsection{设计哲学}

LSTM（Long Short-Term Memory）由 Hochreiter 和 Schmidhuber 于1997年提出，核心创新是引入\textbf{细胞状态}（Cell State）——一条贯穿整个序列的“信息高速公路”，让信息可以长距离传递而不被稀释。

\begin{lstlisting}
LSTM 单元内部结构：

                    ┌──────────────────────────────────────┐
                    │              LSTM 单元                 │
                    │                                      │
  c_{t-1} ───────→ │ ─── 遗忘门 ──→ ── 输入门 ──→ ──────→ │ ──→ c_t
                    │      ↓              ↓          ↓     │   (细胞状态)
  h_{t-1} ──┐      │      σ            σ+σ̃         tanh   │
             │      │      ↓              ↓          ↓     │
  x_t ──────┤      │     f_t           i_t         c̃_t    │
             │      │                              ↓       │
             │      │                        c_t = f_t⊙c_{t-1} + i_t⊙c̃_t
             │      │                              ↓       │
             └─────→│ ────────────── 输出门 ──────→│       │
                    │              σ → o_t          ↓       │
                    │              h_t = o_t ⊙ tanh(c_t)   │
                    └──────────────────────────────────────┘
\end{lstlisting}

\subsection{三道门：遗忘、输入、输出}

LSTM 通过三个“门”（Gate）来精确控制信息的流动：

\textbf{1. 遗忘门（Forget Gate）}：决定从细胞状态中丢弃什么信息

\begin{lstlisting}
f_t = σ(W_f · [h_{t-1}, x_t] + b_f)

输出范围 (0, 1)：0 = 全部遗忘，1 = 全部保留
\end{lstlisting}

\textbf{2. 输入门（Input Gate）}：决定将什么新信息存入细胞状态

\begin{lstlisting}
i_t = σ(W_i · [h_{t-1}, x_t] + b_i)      # 哪些信息需要更新
c̃_t = tanh(W_c · [h_{t-1}, x_t] + b_c)    # 新的候选值
\end{lstlisting}

\textbf{3. 输出门（Output Gate）}：决定输出什么信息

\begin{lstlisting}
o_t = σ(W_o · [h_{t-1}, x_t] + b_o)
h_t = o_t ⊙ tanh(c_t)
\end{lstlisting}

\subsection{细胞状态更新}

\begin{lstlisting}
c_t = f_t ⊙ c_{t-1} + i_t ⊙ c̃_t
      └────────┘   └────────┘
       保留旧信息    加入新信息
\end{lstlisting}

\subsection{设计类比}

\begin{lstlisting}
LSTM 就像一位优秀的设计项目管理者：

  遗忘门 → "之前的方案中哪些思路已经过时了？"
  输入门 → "客户提出了什么新需求？"
  细胞状态 → "项目的核心理念和关键约束"（长期记忆）
  隐藏状态 → "当前正在讨论的具体话题"（短期记忆）
  输出门 → "现在应该向团队传达什么信息？"
\end{lstlisting}

\subsection{代码示例}

\begin{lstlisting}[language=Python]
import torch
import torch.nn as nn

class TextClassifier(nn.Module):
    """基于 LSTM 的文本分类模型"""
    def __init__(self, vocab_size, embed_dim, hidden_dim, num_classes):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embed_dim)
        self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True)
        self.fc = nn.Linear(hidden_dim, num_classes)

    def forward(self, x):
        # x: (batch, seq_len) 整数索引
        embedded = self.embedding(x)      # (batch, seq_len, embed_dim)
        output, (h_n, c_n) = self.lstm(embedded)
        logits = self.fc(h_n.squeeze(0))  # 取最后隐藏状态
        return logits

# 使用示例
model = TextClassifier(vocab_size=10000, embed_dim=128,
                       hidden_dim=256, num_classes=3)
# 3分类：正面/中性/负面（设计评论情感分析）
\end{lstlisting}


\section{GRU：简化版 LSTM}

GRU（Gated Recurrent Unit）由 Cho 等人于2014年提出，将遗忘门和输入门合并为\textbf{更新门}，参数更少，训练更快。

\begin{lstlisting}
GRU 结构：

  h_{t-1} ──→ ┌─────────────────┐ ──→ h_t
               │  重置门 r_t      │
  x_t ──────→ │  更新门 z_t      │
               │  h̃_t = tanh(...) │
               │  h_t = (1-z_t)⊙h_{t-1} + z_t⊙h̃_t
               └─────────────────┘
\end{lstlisting}

\subsection{LSTM vs GRU 对比}

{\def\LTcaptype{none} % do not increment counter
\begin{longtable}[]{@{}lll@{}}
\toprule\noalign{}
特性 & LSTM & GRU \\
\midrule\noalign{}
\endhead
\bottomrule\noalign{}
\endlastfoot
门数量 & 3个（遗忘、输入、输出） & 2个（重置、更新） \\
细胞状态 & 有独立的细胞状态 c\_t & 无，直接用隐藏状态 \\
参数量 & 较多 & 较少（约少1/3） \\
训练速度 & 较慢 & 较快 \\
适用场景 & 复杂长序列 & 中等长度序列 \\
\end{longtable}
}

\subsection{如何选择？}

\begin{lstlisting}
经验法则：
├── 数据量充足、序列很长 → LSTM（更强的表达能力）
├── 数据量有限、序列中等 → GRU（更快收敛，不易过拟合）
└── 都试试，看验证集表现 → 实践出真知
\end{lstlisting}


\section{设计应用：文本分类与时间序列预测}

\subsection{应用一：设计文档自动分类}

\begin{lstlisting}[language=Python]
import torch
import torch.nn as nn

class DesignDocClassifier(nn.Module):
    """将设计文档自动分类为：建筑设计/景观设计/室内设计/平面设计"""
    def __init__(self, vocab_size=20000, embed_dim=128, hidden_dim=256):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embed_dim)
        self.lstm = nn.LSTM(embed_dim, hidden_dim,
                           num_layers=2,        # 2层 LSTM
                           bidirectional=True,   # 双向：同时看前后文
                           dropout=0.3,
                           batch_first=True)
        self.fc = nn.Linear(hidden_dim * 2, 4)  # 4个设计类别

    def forward(self, x):
        embedded = self.embedding(x)
        output, _ = self.lstm(embedded)
        # 取正反向最后隐藏状态拼接
        logits = self.fc(output[:, -1, :])
        return logits
\end{lstlisting}

\subsection{应用二：建筑能耗时间序列预测}

\begin{lstlisting}[language=Python]
import torch
import torch.nn as nn

class EnergyPredictor(nn.Module):
    """基于 LSTM 的建筑能耗预测模型"""
    def __init__(self, input_dim=6, hidden_dim=64, pred_steps=24):
        super().__init__()
        # input_dim: 温度、湿度、光照、人流量、时间(时)、星期几
        self.lstm = nn.LSTM(input_dim, hidden_dim, num_layers=2,
                           dropout=0.2, batch_first=True)
        self.fc = nn.Linear(hidden_dim, pred_steps)  # 预测未来24小时

    def forward(self, x):
        # x: (batch, past_hours, features) 过去若干小时的数据
        _, (h_n, _) = self.lstm(x)
        prediction = self.fc(h_n[-1])  # 最后一层的隐藏状态
        return prediction
\end{lstlisting}


\section{注意力革命}

\section{RNN 的瓶颈：串行计算的困境}

尽管 LSTM 和 GRU 缓解了梯度消失问题，但 RNN 的根本架构限制依然存在：

\begin{lstlisting}
RNN 的串行瓶颈：

时间步：  t=1    t=2    t=3    t=4    t=5
          │      │      │      │      │
          ▼      ▼      ▼      ▼      ▼
        ┌───┐  ┌───┐  ┌───┐  ┌───┐  ┌───┐
  x₁ → │h₁│→ │h₂│→ │h₃│→ │h₃│→ │h₅│ → 输出
        └───┘  └───┘  └───┘  └───┘  └───┘

问题1：必须等 t=1 算完才能算 t=2，无法并行！
问题2：h₅ 能充分了解 x₁ 的信息吗？（远距离依赖）
\end{lstlisting}

{\def\LTcaptype{none} % do not increment counter
\begin{longtable}[]{@{}ll@{}}
\toprule\noalign{}
RNN 的局限 & 具体影响 \\
\midrule\noalign{}
\endhead
\bottomrule\noalign{}
\endlastfoot
串行计算 & 训练速度慢，无法利用 GPU 并行能力 \\
长距离依赖衰减 & 即使是 LSTM，50步以上的依赖也会衰减 \\
固定的信息压缩 & 无论序列多长，都压缩到一个固定大小的 h\_t \\
单向信息流 & 后面的信息无法影响前面的理解（除非用双向） \\
\end{longtable}
}

2017年，一篇名为《Attention Is All You Need》的论文彻底改变了这一局面。


\section{Self-Attention：自注意力机制}

\subsection{核心思想}

自注意力让序列中的每个位置都能\textbf{直接}与所有其他位置“交流”，一步到位地获取全局信息。

\begin{lstlisting}
传统 RNN（串行传递信息）：

  "设计" → "这个" → "客厅" → "的" → "风格"
                              ↑
                          需要回溯4步才能看到"设计"

Self-Attention（直接连接）：

  "设计" ─────────────────────→ "风格"
                    ↘        ↗
          "这个" ──→  "客厅"
                    ↗        ↘
          "的" ──────────────────→ "风格"

每个词都可以直接"看到"所有其他词！
\end{lstlisting}

\subsection{Q、K、V 机制}

Self-Attention 借鉴了信息检索的思想：

\begin{lstlisting}
类比：在图书馆找书

  Q（Query/查询）  = "我想找关于北欧风格室内设计的书"
  K（Key/键）     = 每本书的标签："现代设计""北欧风格""古典建筑"...
  V（Value/值）   = 每本书的实际内容

计算过程：
  1. Q 和每个 K 比较相似度 → 得到"关注程度"
  2. 按关注程度加权求和 V → 得到最终结果
\end{lstlisting}

在序列建模中，每个位置同时扮演 Q、K、V 三个角色：

\begin{lstlisting}
输入序列 X：[x₁, x₂, x₃, x₄]

线性变换：
  Q = X · W_Q    # 查询矩阵：我想找什么？
  K = X · W_K    # 键矩阵：我包含什么信息？
  V = X · W_V    # 值矩阵：我的具体内容是什么？
\end{lstlisting}

\subsection{Scaled Dot-Product Attention}\label{scaled-dot-product-attention}

完整的注意力计算公式：

\begin{lstlisting}
                 Q · Kᵀ
Attention(Q,K,V) = softmax(─────) · V
                  √d_k

步骤分解：

  步骤1：计算注意力分数
    scores = Q · Kᵀ         # 矩阵乘法，得到每对位置的相似度

  步骤2：缩放
    scores = scores / √d_k  # 除以维度平方根，防止梯度消失

  步骤3：归一化
    weights = softmax(scores)  # 转为概率分布，和为1

  步骤4：加权求和
    output = weights · V     # 按注意力权重聚合信息
\end{lstlisting}

\subsection{为什么要缩放（Scale）？}

\begin{lstlisting}
当 d_k 较大时，Q·Kᵀ 的值也会很大
→ softmax 输入很大时会进入"饱和区"
→ 梯度变得极小，训练困难
→ 除以 √d_k 将值拉回合理范围

示例（d_k = 64）：
  缩放前：softmax([10, 8, 3, -5]) → [0.87, 0.12, 0.001, 0.000001]
  缩放后：softmax([1.25, 1.0, 0.375, -0.625]) → [0.38, 0.30, 0.16, 0.07]
\end{lstlisting}

\subsection{代码实现}

\begin{lstlisting}[language=Python]
import torch
import torch.nn.functional as F

def scaled_dot_product_attention(Q, K, V):
    """
    Q: (batch, seq_len, d_k)
    K: (batch, seq_len, d_k)
    V: (batch, seq_len, d_v)
    """
    d_k = Q.size(-1)

    # 步骤1 & 2: 计算缩放后的注意力分数
    scores = torch.matmul(Q, K.transpose(-2, -1)) / (d_k ** 0.5)

    # 步骤3: softmax 归一化
    weights = F.softmax(scores, dim=-1)

    # 步骤4: 加权求和
    output = torch.matmul(weights, V)

    return output, weights

# 示例：对句子"客厅 采用 开放式 布局"做自注意力
seq_len, d_k = 4, 64
Q = torch.randn(1, seq_len, d_k)
K = torch.randn(1, seq_len, d_k)
V = torch.randn(1, seq_len, d_k)

output, attn_weights = scaled_dot_product_attention(Q, K, V)
print(f"注意力权重形状: {attn_weights.shape}")  # (1, 4, 4) - 每个词对其他词的关注度
print(f"输出形状: {output.shape}")              # (1, 4, 64)
\end{lstlisting}


\section{Multi-Head Attention：多头注意力}

\subsection{为什么需要多头？}

单个注意力头只能学习一种“关注模式”。现实中的语言理解需要同时关注多种关系：

\begin{lstlisting}
句子："设计师用木质材料打造了温馨的北欧风格客厅"

头1 关注：语法关系    → "设计师"是主语，"打造"是谓语
头2 关注：修饰关系    → "温馨的"修饰"客厅"，"北欧风格"修饰"客厅"
头3 关注：语义关系    → "木质材料"与"北欧风格"语义关联
头4 关注：设计属性    → "温馨"是情感描述，"北欧风格"是风格类别
\end{lstlisting}

\subsection{结构示意}

\begin{lstlisting}
输入 X
  │
  ├──→ Head 1: Q₁=X·W₁ᵠ, K₁=X·W₁ᵏ, V₁=X·W₁ᵛ → Attention(Q₁,K₁,V₁) → head₁
  ├──→ Head 2: Q₂=X·W₂ᵠ, K₂=X·W₂ᵏ, V₂=X·W₂ᵛ → Attention(Q₂,K₂,V₂) → head₂
  ├──→ Head 3: Q₃=X·W₃ᵠ, K₃=X·W₃ᵏ, V₃=X·W₃ᵛ → Attention(Q₃,K₃,V₃) → head₃
  │         ...
  └──→ Head h: Qₕ=X·Wₕᵠ, Kₕ=X·Wₕᵏ, Vₕ=X·Wₕᵛ → Attention(Qₕ,Kₕ,Vₕ) → headₕ
                                                                          │
          Concat(head₁, ..., headₕ) → Linear → Output                     │
\end{lstlisting}

\subsection{代码实现}

\begin{lstlisting}[language=Python]
class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super().__init__()
        assert d_model % num_heads == 0

        self.d_k = d_model // num_heads
        self.num_heads = num_heads

        # 为每个头创建 Q, K, V 的线性变换
        self.W_q = nn.Linear(d_model, d_model)
        self.W_k = nn.Linear(d_model, d_model)
        self.W_v = nn.Linear(d_model, d_model)
        self.W_o = nn.Linear(d_model, d_model)

    def forward(self, x):
        batch_size = x.size(0)

        # 线性变换并分割为多头
        Q = self.W_q(x).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
        K = self.W_k(x).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
        V = self.W_v(x).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)

        # 计算注意力
        attn_output, _ = scaled_dot_product_attention(Q, K, V)

        # 合并多头
        attn_output = attn_output.transpose(1, 2).contiguous()
        attn_output = attn_output.view(batch_size, -1, self.num_heads * self.d_k)

        # 最终线性变换
        return self.W_o(attn_output)
\end{lstlisting}


\section{Positional Encoding：位置编码}

\subsection{为什么需要位置信息？}

Self-Attention 本身是“位置无关”的——它把输入看作一个集合（Set），而不是序列（Sequence）：

\begin{lstlisting}
输入 A："客厅 在 北面"
输入 B："北面 在 客厅"

Self-Attention 不加位置信息时，会把两者视为完全相同！
（因为词相同，只是顺序不同，但 Attention 是排列不变的）
\end{lstlisting}

\subsection{正弦/余弦位置编码}

Transformer 使用正弦和余弦函数为每个位置生成独特的编码：

\begin{lstlisting}
PE(pos, 2i)   = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))

其中：
  pos  = 位置索引（第几个词）
  i    = 维度索引
  d_model = 模型维度
\end{lstlisting}

\begin{lstlisting}
位置编码示意（d_model=4 简化版）：

位置0: [sin(0),    cos(0),    sin(0),       cos(0)      ]
位置1: [sin(1),    cos(1),    sin(0.0001),  cos(0.0001) ]
位置2: [sin(2),    cos(2),    sin(0.0002),  cos(0.0002) ]
位置3: [sin(3),    cos(3),    sin(0.0003),  cos(0.0003) ]
...
\end{lstlisting}

\subsection{代码实现}

\begin{lstlisting}[language=Python]
import torch
import math

def positional_encoding(seq_len, d_model):
    """生成位置编码矩阵"""
    pe = torch.zeros(seq_len, d_model)
    position = torch.arange(0, seq_len).unsqueeze(1).float()

    # 计算频率
    div_term = torch.exp(
        torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)
    )

    pe[:, 0::2] = torch.sin(position * div_term)  # 偶数维度
    pe[:, 1::2] = torch.cos(position * div_term)  # 奇数维度

    return pe

# 示例：为长度50的序列生成64维位置编码
pe = positional_encoding(50, 64)
print(f"位置编码形状: {pe.shape}")  # (50, 64)
\end{lstlisting}


\section{Self-Attention vs RNN：全面对比}

{\def\LTcaptype{none} % do not increment counter
\begin{longtable}[]{@{}lll@{}}
\toprule\noalign{}
特性 & RNN/LSTM & Self-Attention \\
\midrule\noalign{}
\endhead
\bottomrule\noalign{}
\endlastfoot
计算方式 & 串行（逐步） & 并行（一步） \\
长距离依赖 & 需要传递多步，信息衰减 & 任意距离，一步直达 \\
训练速度 & 慢（无法充分并行） & 快（GPU 友好） \\
位置信息 & 天然有序（按时间步处理） & 需要额外位置编码 \\
内存消耗 & O(1) 每步 & O(n²) 需存储 n×n 注意力矩阵 \\
适用长度 & 中短序列（\textless100） & 中长序列（\textless 数万，受内存限制） \\
\end{longtable}
}

\begin{lstlisting}
计算复杂度对比：

  RNN:   O(n · d²)        - 线性于序列长度
  Attention: O(n² · d)    - 二次于序列长度

  当 n（序列长度）远大于 d（维度）时，Attention 更慢
  但 Attention 的并行性弥补了这一劣势
\end{lstlisting}


\section{Transformer 架构}

\section{整体结构}

Transformer 由 Vaswani 等人在2017年提出，采用 \textbf{Encoder-Decoder}（编码器-解码器）结构：

\begin{lstlisting}
┌──────────────────────────────────────────────────────────────┐
│                    Transformer 架构                           │
│                                                              │
│  输入序列                        输出序列                     │
│  "设计一个客厅"               "现代简约风格客厅..."           │
│      │                              ↑                        │
│      ▼                              │                        │
│ ┌──────────────┐            ┌──────────────┐                │
│ │   Encoder    │            │   Decoder    │                │
│ │  ┌────────┐  │            │  ┌────────┐  │                │
│ │  │ Enc    │  │            │  │ Dec    │  │                │
│ │  │ Layer  │  │  ────────→ │  │ Layer  │  │                │
│ │  │  ×N    │  │  编码信息   │  │  ×N    │  │                │
│ │  └────────┘  │            │  └────────┘  │                │
│ └──────────────┘            └──────────────┘                │
│      ↑                              ↑                        │
│  输入嵌入                        输出嵌入                     │
│  + 位置编码                    + 位置编码                     │
└──────────────────────────────────────────────────────────────┘
\end{lstlisting}


\section{Encoder Layer（编码器层）}

每一层编码器包含两个子层：

\begin{lstlisting}
输入
  │
  ▼
┌──────────────────────────┐
│  Multi-Head Attention    │ ← 子层1：自注意力
│  (Self-Attention)        │
└──────────────────────────┘
  │                    ↑
  ├──── Add & Norm ────┘    ← 残差连接 + 层归一化
  │
  ▼
┌──────────────────────────┐
│  Feed-Forward Network    │ ← 子层2：前馈网络
│  (FFN)                   │
└──────────────────────────┘
  │                    ↑
  ├──── Add & Norm ────┘    ← 残差连接 + 层归一化
  │
  ▼
输出 → 传递给下一层或 Decoder
\end{lstlisting}

\subsection{子层详解}

\textbf{子层1：多头自注意力}

\begin{lstlisting}[language=Python]
# Encoder 中的 Self-Attention
# Q, K, V 都来自同一个输入
attn_output = MultiHeadAttention(x, x, x)
x = LayerNorm(x + attn_output)  # 残差连接 + 层归一化
\end{lstlisting}

\textbf{子层2：前馈网络（FFN）}

\begin{lstlisting}
FFN(x) = W₂ · ReLU(W₁ · x + b₁) + b₂

# 两层线性变换，中间用 ReLU 激活
# 通常 d_ff = 4 × d_model（先升维再降维）
\end{lstlisting}

\begin{lstlisting}[language=Python]
class FeedForward(nn.Module):
    def __init__(self, d_model, d_ff=2048):
        super().__init__()
        self.linear1 = nn.Linear(d_model, d_ff)
        self.linear2 = nn.Linear(d_ff, d_model)

    def forward(self, x):
        return self.linear2(F.relu(self.linear1(x)))
\end{lstlisting}


\section{Decoder Layer（解码器层）}

解码器比编码器多了一个\textbf{交叉注意力}（Cross-Attention）子层：

\begin{lstlisting}
输入（已生成的输出）
  │
  ▼
┌──────────────────────────┐
│  Masked Multi-Head       │ ← 子层1：掩码自注意力
│  Self-Attention          │   （只能看到已生成的词）
└──────────────────────────┘
  │                    ↑
  ├──── Add & Norm ────┘
  │
  ▼
┌──────────────────────────┐
│  Multi-Head              │ ← 子层2：交叉注意力
│  Cross-Attention         │   Q来自Decoder，K/V来自Encoder
│  (Q: Dec, K,V: Enc)     │
└──────────────────────────┘
  │                    ↑
  ├──── Add & Norm ────┘
  │
  ▼
┌──────────────────────────┐
│  Feed-Forward Network    │ ← 子层3：前馈网络
└──────────────────────────┘
  │                    ↑
  ├──── Add & Norm ────┘
  │
  ▼
输出 → 传递给下一层或最终线性层
\end{lstlisting}

\subsection{Masked Self-Attention：为什么要“掩码”？}

在生成文本时，模型不能“偷看”未来的词：

\begin{lstlisting}
生成 "现代 简约 风格 客厅"：

  时刻1：生成 "现代"    → 只能看到起始符 [BOS]
  时刻2：生成 "简约"    → 只能看到 [BOS, 现代]
  时刻3：生成 "风格"    → 只能看到 [BOS, 现代, 简约]
  时刻4：生成 "客厅"    → 只能看到 [BOS, 现代, 简约, 风格]

掩码矩阵（上三角遮住未来信息）：

          现代  简约  风格  客厅
  现代  [  1    0    0    0  ]    ← 只看自己
  简约  [  1    1    0    0  ]    ← 看自己和"现代"
  风格  [  1    1    1    0  ]    ← 看前面三个
  客厅  [  1    1    1    1  ]    ← 看所有

  0 = 被遮住（设为 -inf，softmax 后变为 0）
\end{lstlisting}


\section{残差连接与层归一化}

\subsection{残差连接（Residual Connection）}

\begin{lstlisting}
核心公式：output = LayerNorm(x + Sublayer(x))

为什么重要？
  ┌──────────────────────────────────────────────┐
  │ 没有残差连接：梯度要穿过每一层               │
  │   x → Layer1 → Layer2 → ... → Layer12 → Loss │
  │                                              │
  │ 有残差连接：梯度有"捷径"可以直接回传         │
  │   x → Layer1 → (+x) → Layer2 → (+x) → ...   │
  │        ↑                                     │
  │        └── 梯度可以直接沿加法路径回传 ──→    │
  └──────────────────────────────────────────────┘
\end{lstlisting}

\subsection{层归一化（Layer Normalization）}

\begin{lstlisting}
对每个样本的所有特征进行归一化：

  LayerNorm(x) = (x - μ) / σ · γ + β

  其中 μ, σ 是该样本所有特征的均值和标准差
  γ, β 是可学习的缩放和偏移参数

作用：稳定训练过程，加速收敛
\end{lstlisting}


\section{Transformer 三大变体}

\begin{lstlisting}
                    Transformer 家族树

                     Original Transformer
                     (Encoder + Decoder)
                     ┌────────┴────────┐
                     │                 │
              ┌──────┴──────┐    ┌─────┴─────┐
              │             │    │           │
            BERT           GPT    T5/BART
         (Encoder-only)  (Decoder-only)  (Encoder-Decoder)
              │             │           │
         理解为主       生成为主     理解+生成
\end{lstlisting}

\subsection{BERT（Encoder-only）}\label{bertencoder-only}

\begin{lstlisting}
特点：双向理解，擅长"阅读理解"

训练方式：
  1. MLM（Masked Language Model）：随机遮住15%的词，让模型预测
     "客厅采用了[MASK]风格的设计" → 预测 [MASK] = "北欧"

  2. NSP（Next Sentence Prediction）：判断两句话是否相邻

擅长任务：
  - 文本分类（设计文档分类）
  - 命名实体识别（提取设计要素）
  - 问答系统（设计知识库问答）
  - 情感分析（用户评价分析）
\end{lstlisting}

\subsection{GPT（Decoder-only）}\label{gptdecoder-only}

\begin{lstlisting}
特点：自回归生成，擅长"续写"

训练方式：
  给定前面的词，预测下一个词：
  "设计师选择的" → 预测下一个词（可能是"材料"/"色彩"/"风格"）

擅长任务：
  - 文本生成（设计描述生成）
  - 对话系统（设计咨询助手）
  - 代码生成（设计自动化）
  - 创意构思（头脑风暴）
\end{lstlisting}

\subsection{T5（Encoder-Decoder）}\label{t5encoder-decoder}

\begin{lstlisting}
特点：用统一的"文本到文本"框架处理所有NLP任务

设计理念：
  所有NLP任务都转化为：输入文本 → 输出文本

  翻译：   "translate English to Chinese: Hello" → "你好"
  摘要：   "summarize: 很长的设计文档..." → "核心要点..."
  分类：   "classify: 这是一篇关于景观的文章" → "景观设计"
\end{lstlisting}

\subsection{三大变体对比}

{\def\LTcaptype{none} % do not increment counter
\begin{longtable}[]{@{}llll@{}}
\toprule\noalign{}
特性 & BERT & GPT & T5 \\
\midrule\noalign{}
\endhead
\bottomrule\noalign{}
\endlastfoot
架构 & Encoder & Decoder & Encoder-Decoder \\
方向 & 双向 & 单向（从左到右） & 编码双向，解码单向 \\
核心能力 & 理解 & 生成 & 理解+生成 \\
典型规模 & 340M & 117M \textasciitilde{} 1.8T & 60M \textasciitilde{} 11B \\
设计应用 & 分析评价 & 生成方案 & 转换/翻译 \\
\end{longtable}
}


\section{Token 处理流水线}

文本进入 Transformer 之前，需要经过完整的预处理流水线：

\begin{lstlisting}
原始文本                    Tokenization          Embedding
"设计一个温馨的客厅"   →   [设,计,一,个,温,馨,的,客,厅]  →  每个token → 768维向量
                                                          ↓
                                                       + Positional Encoding
                                                          ↓
                                                       输入 Transformer
\end{lstlisting}

\subsection{Tokenization：分词}

\begin{lstlisting}
三种分词策略：

1. 字符级（Character-level）
   "设计" → ["设", "计"]
   ✗ 优点：词表小    ✗ 缺点：序列太长，丢失词义

2. 词级（Word-level）
   "设计一个客厅" → ["设计", "一个", "客厅"]
   ✓ 优点：保留语义    ✗ 缺点：词表巨大，无法处理新词

3. 子词级（Subword-level）  ← BPE/GPT 使用的方式
   "uncomfortable" → ["un", "comfort", "able"]
   ✓ 优点：平衡词表大小和语义    ✓ 缺点：无明显缺点
\end{lstlisting}

\begin{lstlisting}[language=Python]
# 使用 HuggingFace 的分词器
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-chinese")
tokens = tokenizer("设计一个温馨的客厅")
print(f"Token IDs: {tokens['input_ids']}")
print(f"Token 文本: {tokenizer.convert_ids_to_tokens(tokens['input_ids'])}")

# 输出示例：
# Token IDs: [101, 6371, 2552, 671, 702, 3649, 5889, 4638, 2642, 1079, 102]
# Token 文本: ['[CLS]', '设', '计', '一', '个', '温', '馨', '的', '客', '厅', '[SEP]']
\end{lstlisting}


\section{大语言模型}

\section{从 Transformer 到大语言模型}

Transformer 论文发表后的几年里，研究者们发现了一个关键规律：\textbf{只要持续增大模型的规模（参数量、数据量、计算量），模型的能力就会不断提升}。这就是 Scaling Law 的威力。

大语言模型（Large Language Model, LLM）的演进时间线：

\begin{lstlisting}
模型规模指数级增长：

参数量
  │
  │                                          GPT-4
  │                                         (~1.8T)
  │                              GPT-3
  │                             (175B) ────────╮
  │                    GPT-2                    │
  │                   (1.5B)                    │
  │          GPT-1                              │
  │         (117M)                              │
  │    BERT                                     │
  │   (340M)                                    │
  │                                             │
  └──┴─────┴──────┴──────┴──────┴──────┴───────┴──── 时间
     2018   2018    2019    2020    2022    2023
\end{lstlisting}


\section{GPT 系列演进}

\subsection{GPT-1（2018）：奠定基础}

\begin{lstlisting}
参数量：117M
训练数据：约5GB文本
核心贡献：证明了"预训练 + 微调"范式的有效性

  预训练阶段：在大规模无标注文本上学习语言规律
  微调阶段：在小规模有标注数据上适应特定任务
\end{lstlisting}

\subsection{GPT-2（2019）：规模的力量}

\begin{lstlisting}
参数量：1.5B（15亿）
训练数据：约40GB文本（WebText）
核心发现：模型足够大时，无需微调就能完成多种任务

  "零样本学习"（Zero-shot）能力初现：
  直接输入任务描述，模型就能理解并执行
\end{lstlisting}

\subsection{GPT-3（2020）：涌现能力}

\begin{lstlisting}
参数量：175B（1750亿）
训练数据：约570GB文本
核心突破：少样本学习（Few-shot Learning）

  无需更新参数，只需给几个例子：
  ┌──────────────────────────────────────────────────────┐
  │ Prompt:                                              │
  │                                                      │
  │ 将设计风格翻译为英文：                                 │
  │ 北欧风格 → Nordic style                               │
  │ 日式风格 → Japanese style                             │
  │ 工业风格 →                                            │
  │                                                      │
  │ GPT-3 输出：Industrial style                          │
  └──────────────────────────────────────────────────────┘
\end{lstlisting}

\subsection{ChatGPT（2022）：对话能力的飞跃}

\begin{lstlisting}
核心创新：RLHF（基于人类反馈的强化学习）
意义：让 AI 学会了"对话"

  GPT-3（之前）：
  用户："帮我设计一个客厅"
  GPT-3："客厅是家庭活动的中心空间..."  ← 像百科全书

  ChatGPT：
  用户："帮我设计一个客厅"
  ChatGPT："很乐意帮忙！请问：
    1. 客厅面积多大？
    2. 预算范围？
    3. 喜欢什么风格？
    我可以根据这些信息给你更具体的建议。"
  ← 像真正的设计师在对话
\end{lstlisting}

\subsection{GPT-4（2023）：多模态能力}

\begin{lstlisting}
核心突破：不仅能理解文本，还能理解图像

  输入：一张客厅照片 + "如何改善这个空间？"
  输出："根据照片分析：
    1. 自然光不足 → 建议增加镜面元素反射光线
    2. 家具尺度偏大 → 建议换用低矮家具增加空间感
    3. 色调单一 → 建议添加暖色软装点缀..."

模型规模的飞跃：

  ┌──────────────────────────────────────┐
  │  GPT-1    GPT-2    GPT-3    GPT-4   │
  │  117M  →  1.5B  →  175B  →  ~1.8T  │
  │                                      │
  │  ×13    ×117    ×15,000   ×15,000   │
  │  (相对GPT-1)                         │
  └──────────────────────────────────────┘
\end{lstlisting}


\section{训练范式：预训练 → 微调 → 指令调优}

大语言模型的训练分为三个阶段：

\begin{lstlisting}
阶段1：预训练（Pre-training）
  目标：学习语言的基础知识
  数据：互联网海量文本（TB级别）
  方法：预测下一个词
  成本：极高（数百万美元）

  "这个客厅采用了" → "现代简约" ← 正确答案

  ↓

阶段2：监督微调（Supervised Fine-Tuning, SFT）
  目标：学会遵循指令
  数据：人工编写的（指令, 回答）对
  方法：继续训练，但用有标注数据

  指令："描述一下北欧风格的特点"
  回答："北欧风格以简洁、自然、功能性为核心..."

  ↓

阶段3：对齐优化（Alignment）
  目标：让回答更符合人类偏好
  数据：人类对多个回答的排序
  方法：RLHF / DPO

  问题："设计一个50平米的客厅"
  回答A："以下是设计方案..." ← 较好
  回答B："我无法帮您..."    ← 较差
  人类标注：A > B → 模型学习人类偏好
\end{lstlisting}

\subsection{中国的大语言模型}

\begin{lstlisting}
┌─────────────────────────────────────────────────────┐
│  模型名称       开发机构     特点                      │
├─────────────────────────────────────────────────────┤
│  文心一言       百度        中文理解能力强             │
│  通义千问       阿里巴巴    多模态能力突出             │
│  智谱清言       智谱AI      开源生态活跃               │
│  Kimi          月之暗面     长文本处理能力             │
│  DeepSeek      深度求索     推理能力突出               │
│  讯飞星火       科大讯飞    教育领域深耕               │
└─────────────────────────────────────────────────────┘
\end{lstlisting}


\section{LLM 关键技术}

\section{RAG：检索增强生成}

\subsection{问题：大模型的“幻觉”}

LLM 会自信地编造不存在的事实：

\begin{lstlisting}
用户："北京故宫的建筑面积是多少？"
LLM（幻觉）："北京故宫的建筑面积约为25万平方米。"
（实际约15万平方米）

原因：LLM 的知识来自训练数据，无法实时更新
      它生成的是"最可能"的答案，而非"最正确"的答案
\end{lstlisting}

\subsection{RAG 架构}

RAG（Retrieval-Augmented Generation）通过引入外部知识库来解决幻觉问题：

\begin{lstlisting}
用户提问
  │
  ▼
┌──────────────┐
│  1. 检索阶段  │    在知识库中搜索相关文档
│   (Retrieve) │
└──────────────┘
  │
  │ 检索到的相关文档
  ▼
┌──────────────┐
│  2. 增强阶段  │    将问题 + 相关文档拼接为增强提示
│  (Augment)   │
└──────────────┘
  │
  │ 增强后的 Prompt
  ▼
┌──────────────┐
│  3. 生成阶段  │    LLM 基于增强信息生成回答
│  (Generate)  │
└──────────────┘
  │
  ▼
准确、有据可查的回答
\end{lstlisting}

\subsection{设计领域 RAG 示例}

\begin{lstlisting}[language=Python]
# 概念代码：设计知识库 RAG 系统

# 步骤1：建立知识库（将设计规范文档分块并编码）
documents = [
    "住宅设计规范：客厅净高不应低于2.4米...",
    "建筑采光标准：居住空间采光系数不低于2%...",
    "无障碍设计规范：门道净宽不小于0.8米...",
    # ... 更多设计规范文档
]

# 步骤2：用户提问
query = "办公空间的人均面积标准是多少？"

# 步骤3：检索相关文档
relevant_docs = retrieve(query, knowledge_base)
# 返回: ["办公建筑设计标准：普通办公空间人均使用面积不小于6平方米..."]

# 步骤4：构建增强提示
augmented_prompt = f"""
根据以下参考资料回答问题。如果资料中没有相关信息，请说明。

参考资料：
{relevant_docs}

问题：{query}
"""

# 步骤5：LLM 生成回答
answer = llm.generate(augmented_prompt)
# 输出: "根据《办公建筑设计标准》，普通办公空间人均使用面积不应小于6平方米。"
\end{lstlisting}

\subsection{RAG 的优势}

{\def\LTcaptype{none} % do not increment counter
\begin{longtable}[]{@{}ll@{}}
\toprule\noalign{}
优势 & 说明 \\
\midrule\noalign{}
\endhead
\bottomrule\noalign{}
\endlastfoot
减少幻觉 & 回答基于真实文档，有据可查 \\
知识更新 & 只需更新知识库，无需重新训练模型 \\
领域适配 & 轻松添加专业设计知识 \\
可追溯性 & 可以提供答案来源 \\
\end{longtable}
}


\section{RLHF：基于人类反馈的强化学习}

\subsection{三个训练阶段}

\begin{lstlisting}
阶段1：监督微调（SFT）
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  人类编写示范回答 → 训练模型模仿

  示例：
  指令："设计一个50人的办公空间"
  示范回答："建议采用开放式布局..."

阶段2：训练奖励模型（Reward Model）
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  模型生成多个回答 → 人工排序 → 训练打分模型

  问题："设计一个50人的办公空间"
  回答A: ████████████ 评分: 8  ← 人工标注
  回答B: ██████████   评分: 6
  回答C: ██████       评分: 3

  → 训练一个能自动评分的 Reward Model

阶段3：强化学习优化（RL）
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  用 PPO 算法让模型生成高分回答

  模型生成回答 → Reward Model 打分 → 更新模型参数
  重复这个过程，让模型学会生成人类偏好的回答
\end{lstlisting}

\subsection{RLHF 的设计意义}

\begin{lstlisting}
通过 RLHF，大模型学会了：

  ✓ 遵循设计约束（面积、预算、规范）
  ✓ 结构化输出（分点描述，层次清晰）
  ✓ 适度创意（在合理范围内创新）
  ✓ 安全意识（遵守安全规范和伦理标准）
  ✗ 避免不切实际的方案
  ✗ 避免忽略用户的核心需求
\end{lstlisting}


\section{Prompt Engineering：提示工程}

\subsection{核心原则}

Prompt Engineering 是与大语言模型有效沟通的“艺术与科学”：

\begin{lstlisting}
原则一：明确任务
━━━━━━━━━━━━━━━━
  ✗ 模糊："帮我设计一个空间"
  ✓ 明确："请为一个30平米的客厅设计一个简约风格的家具布局方案"

原则二：提供示例（Few-shot）
━━━━━━━━━━━━━━━━
  在提示中给出1-3个示例，让模型理解期望的输出格式

原则三：指定格式
━━━━━━━━━━━━━━━━
  "请按以下格式输出：
  1. 设计理念（50字以内）
  2. 空间布局（分点描述）
  3. 材料建议（列表形式）
  4. 预估预算（表格形式）"

原则四：角色设定
━━━━━━━━━━━━━━━━
  "你是一位有15年经验的室内设计师，擅长小户型改造..."
\end{lstlisting}

\subsection{设计应用示例}

\begin{lstlisting}
Prompt: 设计一个50人的办公空间

角色设定：
你是一位资深办公空间设计师，熟悉人体工程学和现代办公理念。

任务要求：
- 面积：约200平方米
- 人数：50人
- 类型：科技创业公司
- 风格：现代简约
- 需要考虑：开放工位、会议室、休息区、茶水间

请按以下结构输出：
1. 空间规划方案
2. 动线设计要点
3. 家具选型建议
4. 照明设计方案
5. 预估造价

---

LLM 输出（示例）：

1. 空间规划方案
   ├── 开放工位区（120㎡）：40个工位，2人/组
   ├── 独立办公区（20㎡）：2间，各容纳5人
   ├── 会议室（30㎡）：1间大会议室 + 2间小会议室
   ├── 休息区（15㎡）：沙发、茶水台
   └── 茶水间（15㎡）：吧台、储物柜

2. 动线设计要点
   ├── 主通道宽度 ≥ 1.2m
   ├── 入口直通开放区，减少干扰
   └── 会议室靠近入口，方便访客
   ...
\end{lstlisting}

\subsection{Prompt 设计模式}

\begin{lstlisting}
┌─────────────────────────────────────────────────┐
│ 模式          适用场景           示例            │
├─────────────────────────────────────────────────┤
│ Zero-shot     简单任务           "翻译：你好"    │
│ Few-shot      格式化输出         给2-3个范例     │
│ Chain-of      复杂推理           "让我们一步步   │
│ Thought                         来思考..."      │
│ Role-play     专业领域           "你是一名建筑   │
│                                 设计师..."      │
│ Template      结构化输出         固定输出模板    │
└─────────────────────────────────────────────────┘
\end{lstlisting}


\section{设计应用}

\section{应用一：设计文档文本分类}

\begin{lstlisting}
场景：设计公司收到大量项目文档，需要自动分类归档

  输入文档 → 文本分类模型 → 类别标签
  "本项目采用新中式园林风格..."  → "景观设计"
  "室内空间以简约风格为主..."    → "室内设计"
  "建筑主体采用框架剪力墙..."    → "建筑设计"
\end{lstlisting}

\begin{lstlisting}[language=Python]
from transformers import AutoModelForSequenceClassification, AutoTokenizer
import torch

# 加载预训练的中文文本分类模型
model_name = "bert-base-chinese"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(
    model_name, num_labels=4  # 4个设计类别
)

# 分类推理
text = "本方案采用开放式布局，以白色和原木色为主色调"
inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True)
outputs = model(**inputs)
predicted_class = torch.argmax(outputs.logits, dim=1)

categories = ["建筑设计", "景观设计", "室内设计", "平面设计"]
print(f"分类结果: {categories[predicted_class]}")
# 输出: 分类结果: 室内设计
\end{lstlisting}

\section{应用二：用户评价情感分析}

\begin{lstlisting}
场景：分析用户对设计方案的反馈

  "新方案的空间利用很合理，采光也不错"          → 正面
  "走廊太窄了，家具颜色也不搭配"                → 负面
  "基本满足需求，但细节还有改进空间"            → 中性
\end{lstlisting}

\begin{lstlisting}[language=Python]
# 使用预训练模型进行情感分析
from transformers import pipeline

sentiment_analyzer = pipeline(
    "sentiment-analysis",
    model="uer/roberta-base-finetuned-jd-binary-chinese"
)

# 批量分析设计评价
reviews = [
    "这个设计方案很有创意，空间利用率很高",
    "配色方案不太协调，建议调整",
    "整体还不错，就是预算偏高"
]

for review in reviews:
    result = sentiment_analyzer(review)
    print(f"评价: {review}")
    print(f"情感: {result[0]['label']} (置信度: {result[0]['score']:.2%})")
    print()
\end{lstlisting}

\section{应用三：设计描述自动生成}

\begin{lstlisting}
场景：根据设计参数自动生成方案描述文本

  输入参数：
    - 空间类型：客厅
    - 面积：35平方米
    - 风格：现代简约
    - 主色：白色 + 原木色
    - 需求：家庭聚会、阅读角

  生成描述：
    "本方案为35平方米的客厅空间设计，采用现代简约风格。
     空间以白色和原木色为主色调，营造明亮温馨的氛围。
     布局上，沙发区面向景观窗，可满足家庭聚会需求；
     窗边设置阅读角，配备落地灯和单人沙发。
     整体动线流畅，兼顾功能性与美感。"
\end{lstlisting}

\section{应用四：对话式设计助手}

\begin{lstlisting}
场景：设计师通过对话形式获取设计建议

  ┌──────────────────────────────────────────────────────┐
  │  设计师：我想为一个80平米的小户型做室内设计，          │
  │         业主要求现代简约风格，预算15万。              │
  │                                                      │
  │  AI助手：好的，我来帮您规划。80平米做现代简约是       │
  │  很好的选择。我有几个问题：                           │
  │                                                      │
  │  1. 户型是几室几厅？                                  │
  │  2. 家庭成员构成？（是否有老人/儿童）                 │
  │  3. 有没有特别的空间需求？（书房/衣帽间等）           │
  │                                                      │
  │  设计师：两室一厅，一家三口，孩子5岁，需要一个小书房  │
  │                                                      │
  │  AI助手：明白了。以下是我的初步建议：                  │
  │                                                      │
  │  【空间规划】                                         │
  │  - 主卧：约15㎡（含衣柜区）                          │
  │  - 儿童房：约10㎡（考虑成长性设计）                   │
  │  - 客厅+餐厅：约25㎡（开放式布局）                    │
  │  - 书房：约6㎡（可做半开放式）                        │
  │  - 厨卫：约12㎡                                      │
  │  - 阳台：约6㎡（兼顾洗衣和休闲）                      │
  │  ...                                                  │
  └──────────────────────────────────────────────────────┘
\end{lstlisting}

\subsection{技术实现思路}

\begin{lstlisting}[language=Python]
# 对话式设计助手的基本架构

class DesignAssistant:
    def __init__(self, llm, knowledge_base):
        self.llm = llm                    # 大语言模型
        self.knowledge_base = knowledge_base  # 设计知识库
        self.conversation_history = []

    def chat(self, user_input):
        # 1. 从知识库检索相关设计规范
        relevant_docs = self.knowledge_base.retrieve(user_input)

        # 2. 构建增强提示
        system_prompt = """
        你是一位专业的室内设计顾问。请根据用户需求和
        参考的设计规范，提供专业、实用的设计建议。
        回答要有条理，必要时提出追问以明确需求。
        """

        # 3. 组装完整提示
        messages = [
            {"role": "system", "content": system_prompt},
            *self.conversation_history,
            {"role": "user", "content": f"参考资料：{relevant_docs}\n\n用户问题：{user_input}"}
        ]

        # 4. 调用 LLM 生成回答
        response = self.llm.chat(messages)

        # 5. 更新对话历史
        self.conversation_history.append({"role": "user", "content": user_input})
        self.conversation_history.append({"role": "assistant", "content": response})

        return response
\end{lstlisting}


\section{思考与练习}

\begin{enumerate}
\def\labelenumi{\arabic{enumi}.}
\item
  \textbf{模型选择}：在设计项目文档分类任务中，你会选择 BERT 还是 GPT 架构？为什么？考虑模型规模、训练成本、任务特点等因素。
\item
  \textbf{RAG vs 微调}：你正在为一家建筑设计院开发 AI 设计助手。设计规范经常更新，且需要提供条文来源。你会选择 RAG 还是模型微调？请分析两种方案的优劣。
\item
  \textbf{Prompt 设计}：尝试设计一个高质量的 Prompt，让大语言模型帮助分析一份景观设计方案的优缺点。你的 Prompt 中应该包含哪些要素？考虑角色设定、输出格式、评估维度等。
\end{enumerate}


\section{关键术语}

{\def\LTcaptype{none} % do not increment counter
\begin{longtable}[]{@{}
  >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.3333}}
  >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.3333}}
  >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.3333}}@{}}
\toprule\noalign{}
\begin{minipage}[b]{\linewidth}\raggedright
中文
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
英文
\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright
说明
\end{minipage} \\
\midrule\noalign{}
\endhead
\bottomrule\noalign{}
\endlastfoot
循环神经网络 & RNN (Recurrent Neural Network) & 处理序列数据的基础网络结构 \\
长短期记忆网络 & LSTM (Long Short-Term Memory) & 解决 RNN 梯度消失问题的改进结构 \\
门控循环单元 & GRU (Gated Recurrent Unit) & LSTM 的简化版本，参数更少 \\
自注意力机制 & Self-Attention & 序列内部元素之间直接计算关联的机制 \\
缩放点积注意力 & Scaled Dot-Product Attention & 带缩放的注意力计算公式 \\
多头注意力 & Multi-Head Attention & 多组并行的注意力，捕获多种关系模式 \\
位置编码 & Positional Encoding & 为序列中的位置信息编码的方法 \\
Transformer & Transformer & 基于注意力机制的序列模型架构 \\
掩码注意力 & Masked Attention & 防止解码器看到未来信息的注意力机制 \\
大语言模型 & LLM (Large Language Model) & 参数量巨大的预训练语言模型 \\
检索增强生成 & RAG (Retrieval-Augmented Generation) & 结合外部知识库的生成方法 \\
人类反馈强化学习 & RLHF (Reinforcement Learning from Human Feedback) & 基于人类偏好优化模型的方法 \\
提示工程 & Prompt Engineering & 设计有效提示以引导模型输出的技术 \\
分词 & Tokenization & 将文本拆分为最小处理单元的过程 \\
词嵌入 & Embedding & 将离散的词映射为连续向量表示 \\
预训练 & Pre-training & 在大规模数据上的初始训练阶段 \\
微调 & Fine-tuning & 在特定任务数据上的调整训练 \\
自回归 & Autoregressive & 逐步生成，每步依赖之前输出 \\
幻觉 & Hallucination & 模型生成看似合理但实际错误的内容 \\
缩放定律 & Scaling Law & 模型性能与规模之间的关系规律 \\
\end{longtable}
}


\section{延伸阅读}

\begin{itemize}
\tightlist
\item
  \href{https://arxiv.org/abs/1706.03762}{Attention Is All You Need} --- Transformer 原始论文
\item
  \href{https://jalammar.github.io/illustrated-transformer/}{The Illustrated Transformer} --- Transformer 可视化解读
\item
  \href{https://arxiv.org/abs/1810.04805}{BERT: Pre-training of Deep Bidirectional Transformers} --- BERT 论文
\item
  \href{https://arxiv.org/abs/2005.14165}{Language Models are Few-Shot Learners (GPT-3)} --- GPT-3 论文
\item
  \href{https://arxiv.org/abs/2203.02155}{Training language models to follow instructions with human feedback} --- InstructGPT/RLHF 论文
\item
  \href{https://arxiv.org/abs/2005.11401}{Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks} --- RAG 原始论文
\end{itemize}
