JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

大型語言模型如何生成文本

在底層,聊天機器人是一次生成一個詞元的,每一步都在一串機率上擲骰子。本文講清這個循環是怎麼運轉的——以及為什麼同一個提示會給出不同的回答。

一次一個詞元

到現在你已經知道,大型語言模型是一個Transformer,它在預訓練階段被訓練去玩一個看似簡單到不行的遊戲:預測下一段文本。當你和它聊天時,它做的始終只有這一件事。模型從不會先在心裡把整段話規劃好再打出來。相反,它一次只生成一個詞元,而它產出的每一個詞元都會被重新餵回去,成為下一步輸入的一部分。

一個詞元(token)就是一小塊文本——常常是一個單字,有時是像 "-ing" 這樣的片段,或一個單獨的字元——它由分詞產生(你在前面見過像位元組對編碼這樣的方案)。在每一步,模型讀入到目前為止的全部文本,讓它穿過自己的各層,輸出的並不是一個詞,而是為詞表裡*每一個*詞元打的分——成千上萬個數字。一個 softmax 把這些分數變成一個機率分布:一張列表,說著「下一個詞元有 40% 的機率是「巴黎」,12% 是「這」,0.001% 是「香蕉」」,如此覆蓋整個詞表。

這個循環——預測一個分布、挑一個詞元、把它接上去、再重複——叫做自迴歸解碼。「自迴歸」的意思無非是:每一個輸出都依賴於模型自己之前的輸出。文本從左到右地生長,就像一個只能選定下一個詞、永遠無法往前預看的寫作者,直到一個特殊的「停止」詞元出現,或者撞上長度上限為止。

context = tokenize(prompt)
while not done:
    scores = model(context)        # one score per vocab token
    probs  = softmax(scores / T)   # T = temperature
    next   = sample(probs)         # pick ONE token
    context.append(next)           # feed it back in
    done = (next == END) or len(context) > limit
解碼循環的偽代碼:預測、採樣一個詞元、接上、重複。

從一張機率清單到一個詞

這裡有個關鍵的缺口:模型遞給你的是一個*分布*,可你需要的是恰好*一個*詞元寫下來。你怎麼選,就叫做解碼策略採樣策略,它是獨立於模型權重之外的另一個旋鈕——你可以改它而不必重新訓練任何東西。最簡單的選法是貪婪解碼:永遠取那個機率最高的詞元。聽起來很穩妥,但它往往產出平淡、重複的文字,還可能卡進死循環(「的的的」)。

另一種做法是真正地採樣:擲一個加權的骰子,每個詞元被選中的機會就等於它的機率。這樣一來,「巴黎」通常會贏,但並非總是,文字也因此有了多樣性和生氣。訣竅在於控制這枚骰子*有多愛冒險*,而這恰恰就是溫度、top-k 和 top-p 讓你能做的事。

溫度、top-k 與 top-p

溫度(temperature)在你抽取之前先重塑整個分布。注意上面循環裡的 `scores / T`:把分數除以一個數 T 再做 softmax,會拉伸或壓平這條曲線。低溫(比如 0.2)讓峰值更尖銳——最靠前的選項變得更有可能,於是輸出聚焦而可預測。高溫(比如 1.2)把一切壓平,讓稀有詞元也有真正出頭的機會,於是輸出富有創意但更冒險。溫度為 0 就退化成貪婪解碼。這個旋鈕就是溫度採樣

Top-ktop-p 走的是另一條路:在採樣之前先*裁剪*這張清單,讓骰子根本擲不到荒唐的詞元上。Top-k 只保留機率最高的 k 個詞元(比如前 40 個),其餘全部清零。Top-p,又叫*核採樣*(nucleus sampling),更聰明:它保留機率累加剛好達到 p(比如 0.9)的那一小撮最靠前的詞元,再在其中採樣。於是當模型很有把握時,top-p 可能只留下兩三個候選;當它沒把握時,就留下許多。這兩種截斷就是top-k 與 top-p 採樣,實踐中人們常把一個溫度和一個 top-p 上限搭配著用。

上下文窗口:模型的全部世界

在每一步,模型都會讀「到目前為止的全部文本」——但這能有多少,是有一道硬性天花板的。上下文視窗(也叫上下文長度)是模型一次能關注的詞元數量上限:你的系統指令、對話歷史、你貼進來的任何文件、以及正在生成的回覆,全都共用這一份預算。現代模型的視窗從幾千個詞元到幾十萬個不等,但這個上限永遠是有限的。

當一段對話長到超出視窗,最老的詞元就會從邊緣掉出去——模型字面意義上再也看不見它們了,這就是為什麼一段長聊天似乎會「忘記」你開頭說過的話。這個有限的視窗也是自注意力機制如此重要又如此昂貴的原因:每個詞元都必須和其他每個詞元相比較,所以上下文翻一倍,計算量大約要變成四倍。理解了視窗,就能解釋許多真實表現,它也正是檢索增強生成這類技術存在的理由——只把一個龐大知識庫裡最相關的那幾片餵給模型,而不是一股腦全塞進去。

為什麼輸出會變——以及這究竟意味著什麼

現在來回答那個著名的問題:同一個模型,同樣的問題問兩遍,你可能得到兩個不同的答案。為什麼?幾乎總是因為採樣。如果溫度大於零,你就是在每一個詞元處都擲那枚加權骰子,而早早的一次不同擲點,會把整句話引向一條不同的路。把溫度設成 0(貪婪),模型就會變得*確定性*得多——不過即便如此,硬體在多個並行核心上累加浮點數時那點微小的數值差異,偶爾也會讓一個勢均力敵的抉擇翻盤。

下面是誠實的那一部分,它糾正一個常見的誤解。採樣讓文字*流暢而多樣*,而不是*真實*。模型選的是在它的訓練之下統計上可能的詞元——它並沒有一個單獨的機制去核查這個說法是否正確。當最可能的接續恰好是假的,你就會得到一段自信、措辭工整的謬誤:一次幻覺。調低溫度能減少隨機性,但它不會讓模型更誠實;它只是讓模型更可靠地重複它本來最可能說的話,無論對錯。

再戳破兩個迷思也有幫助。第一,模型並不「一次性嘗試所有答案」——自迴歸解碼嚴格地是一個詞元接一個詞元。第二,你看到的多樣性並不是創造力或理解力在*湧現*的標誌;它是一種你可以一路調到零的、刻意為之的隨機性。這些模型真正令人驚訝之處——一個在巨大規模上訓練出來的下一詞元預測器,竟能翻譯、能摘要、還能分步推理出它從未被明確教過的東西——來自訓練的規模(參見縮放定律以及關於所謂湧現能力的爭論),而不是來自你在生成時擲的那枚骰子。

把這些旋鈕用起來

現在你掌握了全貌:Transformer 把上下文變成一張機率清單,採樣策略把這張清單坍縮成一個詞元,詞元被接上,循環在一個有限的視窗裡再次運行。你在生成時調的一切,都活在那個坍縮的步驟裡。下面是選擇設置的一份簡短清單:

  1. 需要事實、程式碼、或任何要重複跑的東西?用低溫度(0–0.3)和較緊的 top-p——可預測、聚焦、好測試。
  2. 想要腦力激盪、多樣的措辭、或寫小說?把溫度提到 0.8–1.0,並把 top-p 放鬆到大約 0.95。
  3. 出現重複死循環或亂碼?別盲目把溫度往上拉——先加一個 top-k/top-p 截斷,把不可能的詞元裁掉。
  4. 長輸入時撞上奇怪的容量限制?你很可能溢出了上下文視窗——精簡歷史,或改用檢索,而不是把所有內容都貼進去。

有了這些,從原始機率到可讀文章的這條路,就不再是個黑箱了。下一篇指南將完全走出文本,進入*擴散*模型和多模態模型如何生成圖像——那是一個非常不同的解碼故事,卻建立在同一個想法之上:把一個學到的分布變成某種具體的東西。