# AI 的回答裡能藏暗號嗎？

> 可以。AI 每次選字都有好幾個候選，選哪一個就能代表 0 或 1。本篇用白話講 GPT-2 隱寫的原理、和水印的差別與風險。

- 作者：Michael Kuo（https://mk-ai-notes.pages.dev/about/）
- 發布日期：2026-11-02（2026-11-02T20:07:00+08:00）
- 原文網址：https://mk-ai-notes.pages.dev/posts/ep07-steganography/
- 分類：一人公司工作流＋學習系列（https://mk-ai-notes.pages.dev/category/workflow/）
- 系列：動手學大模型 12 問 第 8 篇／共 12 篇（https://mk-ai-notes.pages.dev/series/dive-into-llms/）
- 標籤：AI 安全、隱寫、水印
- 閱讀時間：約 8 分鐘（約 1398 字）
- 參考來源：https://github.com/Lordog/dive-into-llms/tree/main/documents/chapter7

![AI 的回答裡能藏暗號嗎？](https://mk-ai-notes.pages.dev/og/ep07-steganography.png)

---

## 一句話回答

可以。語言模型每生成一個字，都會列出好幾個「都說得通」的候選字；如果事先約定「選第一個代表 00、選第二個代表 01……」，一段看起來普通的文字就能夾帶一串 0 與 1。這種技術叫文本隱寫（text steganography）。

## 為什麼值得知道

- **理解 AI 生成的本質**：模型是一個字一個字從機率分布裡挑，懂了這點，就明白為什麼每次回答不一樣。
- **資安與內容治理**：看起來無害的文字可能夾帶資訊，這對資料外洩防護、內容審查都是新的課題。
- **分辨隱寫與水印**：近年常聽到「AI 生成內容要加水印」，兩者用的是相近的手法，但目的完全不同，弄懂一個就容易懂另一個。

## 白話原理

### 選字就是編碼

想像你在玩接龍，每一步都有四個合理的詞可以接。朋友事先跟你約定：

| 你選的詞 | 代表的位元 |
| --- | --- |
| 機率第 1 高 | 00 |
| 機率第 2 高 | 01 |
| 機率第 3 高 | 10 |
| 機率第 4 高 | 11 |

你想傳「0111」，第一步就選第 2 個詞、第二步選第 4 個詞。外人看到的只是一句通順的話；朋友手上有**同一個模型、同一個開頭**，就能重算每一步的候選排序，反推出你選的是第幾個，把位元還原回來。

### 兩種編碼方法

教程實作了兩種把位元對應到候選字的方式：

- **固定長度編碼（Fixed Length Coding, FLC）**：取機率最高的 2 的 k 次方個候選，每個候選固定代表 k 個位元。優點是簡單，每一步藏的量固定；缺點是不管候選字機率高低一律平等對待，有時會被迫選一個不太自然的字。
- **霍夫曼編碼（Huffman Coding）**：先依候選字的機率建一棵霍夫曼樹，機率高的字拿到短編碼、機率低的拿到長編碼。直覺上，常見的字較容易被選中、每次只帶少量位元，冷門的字較少出現，生成的文字因此比較接近模型原本的習慣，通常也比較自然。

兩者都只在前幾個高機率候選裡挑，所以文字大致通順；k 越大藏得越多，但越可能選到怪字。

### 隱寫和水印差在哪？

| | 隱寫 | 水印 |
| --- | --- | --- |
| 目的 | 偷偷傳遞一段祕密訊息 | 標記「這段文字是某個模型產生的」 |
| 希望誰發現 | 只有收件人 | 有檢測工具的人都能驗證 |
| 藏的內容 | 任意資料 | 固定的身分標記 |
| 典型用途 | 隱密通訊、研究 | 來源追蹤、防止濫用 |

簡單說，隱寫追求「別人看不出來」，水印追求「該看出來的人一定看得出來」。

## 教程裡實際做了什麼

這章的實作是一個 Jupyter notebook（llm_stega.ipynb）：

1. 安裝 PyTorch、Transformers 與 Jupyter。
2. 載入 GPT-2（約 500 MB，第一次執行會自動下載）。
3. 隨機產生一串 0／1 當作要藏的祕密位元。
4. 用霍夫曼編碼或 FLC 建立「隱寫處理器」，設定 k 值。
5. 給一個英文開頭（範例是 Once upon a time），讓模型逐字生成：每一步取下一個字的機率分布，交給處理器依照待藏位元選字。
6. 同時用一般隨機抽樣產生一段「沒藏東西」的文字當對照，兩份結果各存成一個 txt 檔。
7. 解碼端用同樣的模型與開頭重算機率，從每個被選中的字反推回位元。

核心選字邏輯很短，大意如下（改寫自原 notebook，FLC 版）：

```python
prob, idx = torch.topk(pred_prob, k=2**self.k, dim=1)  # 取前 2^k 個候選
codes = [bin(i)[2:].zfill(self.k) for i in range(2**self.k)]
bit = self.bits[:self.k]          # 取出接下來要藏的 k 個位元
chosen = idx[0][codes.index(bit)] # 對應到第幾個候選字
```

硬體：原文說 CUDA 是選用，建議有 GPU 較快；GPT-2 小模型在一般筆電的 CPU 上也跑得動，只是比較慢。

## 動手試試

這章是全系列最容易上手的一章之一：

1. 開一個 Google Colab 筆記本，CPU 執行階段即可。
2. `pip install transformers`（Colab 已內建 PyTorch）。
3. 下載原教程的 llm_stega.ipynb 依序執行。
4. 比較兩份輸出：藏了位元的文字和一般生成的文字，你分得出來嗎？
5. 把 k 從 2 改成 3、4，觀察文字是否變得越來越不自然。

觀察重點是「自然度」，這是評估隱寫方法的核心指標之一。請把它當成理解生成原理的實驗，不要拿來規避任何單位的通訊監管或資安政策。

## 常見誤解

- **「隱寫就是加密。」** 加密是讓人看得到但讀不懂；隱寫是讓人根本不知道有東西。兩者可以搭配，但不是同一件事。
- **「拿到文字就能解出來。」** 解碼需要同一個模型、開頭和編碼規則。
- **「隱寫文字一定讀起來很怪。」** 只在高機率候選裡挑時，文字通常相當通順，這也是它難被發現的原因；但 k 太大時確實會變怪。
- **「這技術只能用來做壞事。」** 它也是水印研究的基礎；風險在用途，偵測技術也要同步進步。

## 延伸閱讀

- 第 7 章原文：https://github.com/Lordog/dive-into-llms/tree/main/documents/chapter7
- 第 7 章投影片（PDF）：https://github.com/Lordog/dive-into-llms/blob/main/documents/chapter7/stega.pdf
- 本章 notebook：https://github.com/Lordog/dive-into-llms/blob/main/documents/chapter7/llm_stega.ipynb

> 本文整理自上海交通大學《動手學大模型》第 7 章，原教程：https://github.com/Lordog/dive-into-llms/tree/main/documents/chapter7。內容由 MK 以自己的話解說，如有錯誤歡迎留言指正。

---

本系列整理自上海交通大學《動手學大模型》公益教程（https://github.com/Lordog/dive-into-llms），以自己的話解說，非官方內容。

引用本文請附原文網址：https://mk-ai-notes.pages.dev/posts/ep07-steganography/（作者：Michael Kuo）
