ETH官方钱包

前往
大廳
主題

關(guān)於LLM的Prompt中的「奇怪格式」(適用所有平臺)

慕儀 | 2024-11-30 06:44:27 | 巴幣 1114 | 人氣 770

前言
這裡我介紹一些常見的「奇怪格式」及其功能和用途。
首先,要明確聲明的一點(diǎn)是,LLM並不會真的執(zhí)行或運(yùn)算,這些代碼也不存在什麼魔力,只是某些情境下可以用很簡潔的方法處理自然語言需要花費(fèi)大篇幅才能表達(dá)的事情。
這裡主要介紹:
  • Markdown
  • XML、JSON、類JSON
  • CSV、TSV、Markdown表格
  • 偽高級語言
  • 偽變數(shù)


Markdown

  • 適用情境:絕大多數(shù)時候。
  • 介紹:Markdown是一種非常泛用的輕量化標(biāo)記式格式,易學(xué)易用,好的標(biāo)記可以強(qiáng)化LLM對Prompt的理解,也能節(jié)省大量Tokens。

範(fàn)例

例如原文為:
{{char}}喜歡:A、B、C
{{char}}討厭:D、E
{{char}}擅長:F、G

若要節(jié)省一些字,改寫為:
{{char}}的資訊:
喜歡:A、B、C
討厭:D、E
擅長:F、G

這時候如何讓LLM知道這個「{{char}}的資訊」的內(nèi)容該從哪裡開始,哪裡結(jié)束呢?可以這樣寫:
{{char}}的資訊:
- 喜歡:A、B、C
- 討厭:D、E
- 擅長:F、G

這樣,LLM就會知道底下的列表是延伸定義上面的「{{char}}的資訊」,到列表結(jié)束時,自然也就是「{{char}}的資訊」結(jié)束時。
(註:為了節(jié)省版面,這是一個極簡單的例子,這個例子實(shí)際上即便直接寫自然語言,LLM也不容易理解錯誤,但假設(shè)你有非常長的篇幅,就不一定了。)

建議

  • # 標(biāo)題、列表- 、分隔線---、縮排等,讓LLM理解哪些指令是一起作用的,哪些指令擁有更高優(yōu)先權(quán)等等。
  • 符號也要佔(zhàn)用Tokens,請依情境選擇是否使用,簡單的資訊或許完全不需要標(biāo)記。


XML、JSON或類JSON

  • 適用情境:為複雜提示分類、分塊時。雖然Markdown足以應(yīng)付大多數(shù)狀況,但如果你的提示結(jié)構(gòu)十分複雜,即便你使用高Tokens輸入量的LLM,它也未必能清晰的判斷其重點(diǎn),反而容易因結(jié)構(gòu)複雜而丟三落四、首尾不能相顧。這時,你就需要更明確的標(biāo)記來指引LLM如何更好地理解層次與邏輯,這在長篇幅的提示中更為重要。
  • 介紹:
    • XML是一種廣泛的資訊交換格式。可以明確標(biāo)註資料的屬性、用途、起訖、層次,它支援比JSON更複雜的結(jié)構(gòu),但寫起來也更為冗長。
    • JSON是一種比XML更簡潔、輕量的資料交換格式。

範(fàn)例

假設(shè)我的提示有幾個大段落,每個段落都有不同的重點(diǎn)與行為準(zhǔn)則,其上下文間過長,即便用Markdown也難以讓LLM清楚區(qū)分開來,例如原文為:
世界運(yùn)行的規(guī)則
(省略十萬字)
角色的資訊
(十個角色)
事件的流程
(省略十萬字)
回應(yīng)的格式
(省略十萬字)

XML

<world_rules desc="定義世界運(yùn)行的規(guī)則。">
(省略十萬字)
</world_rules>

<char_info desc="所有預(yù)設(shè)角色的資訊。">
  <char name="角色1的名字">角色1的資訊</char>
  <char name="角色2的名字">角色2的資訊</char>
  <char name="角色3的名字">角色3的資訊</char>
(省略剩餘角色)
</char_info>

<event_flow desc="定義事件的流程。">
(省略十萬字)
</event_flow>

<response_format desc="定義回應(yīng)的格式。">
(省略十萬字)
</response_format>

JSON

{
  "world_rules": {
    "desc": "定義世界運(yùn)行的規(guī)則。",
    "content": "(省略十萬字)"
  },
  "char_info": {
    "desc": "所有預(yù)設(shè)角色的資訊。",
    "chars": [
      {
        "name": "角色1的名字",
        "info": "角色1的資訊"
      },
      {
        "name": "角色2的名字",
        "info": "角色2的資訊"
      },
      {
        "name": "角色3的名字",
        "info": "角色3的資訊"
      }  // (省略剩餘角色)
    ]
  },
  "event_flow": {
    "desc": "定義事件的流程。",
    "content": "(省略十萬字)"
  },
  "response_format": {
    "desc": "定義回應(yīng)的格式。",
    "content": "(省略十萬字)"
  }
}
至於最後的「類JSON」,你在很多角色看到作者使用大量{[()]}之類符號處理資訊的就是了,理論上LLM也會將之當(dāng)做「不太規(guī)範(fàn)的JSON變體」理解,但其實(shí)那完全沒有必要,那可能只是一種以訛傳訛的迷信,那點(diǎn)資訊量用自然語言或Markdown完全不致於讓LLM產(chǎn)生歧義,用特殊的格式只是浪費(fèi)Tokens罷了。
類似的選項還有YAML,LLM也能正常理解它,但因為它跟JSON挺類似的,就不再浪費(fèi)版面寫介紹,有興趣的同學(xué)可以自行查詢。

建議:

  • 因為比起Markdown,會消耗更多Tokens,因此若非必要,並不建議。


CSV、TSV、Markdown表格

  • 適用情境:有大量資料,擁有重複的鍵值,並且其格式可以編排為二維表格。
  • 介紹:這三種都是一種表格形式,在情境合適下,可以節(jié)省版面與Tokens。
    • CSV與TSV:是一種最簡單的表格形式,使用,逗號或\t分隔符來分割表格內(nèi)容。
    • Markdown表格:Markdown所使用的表格形式,消耗Tokens會多些,但實(shí)測時不知道為什麼,不管什麼LLM都更容易處理這種形式,可能與預(yù)先的訓(xùn)練內(nèi)容有關(guān)。

範(fàn)例

如果我建立一個開放世界類型的模擬器,而其中內(nèi)建的預(yù)設(shè)角色有26人,那麼我原文得這樣寫:
A姓名:莉莉亞
A性別:女
A特質(zhì):可愛
A外貌:金馬尾
A性格:害羞
A喜好:甜食
A厭惡:孤獨(dú)

B姓名:雅柔
B性別:女
B特質(zhì):學(xué)霸
B外貌:黑長髮
B性格:矜持
B喜好:鴨子
B厭惡:虛偽
(??中略)
Y姓名:露比娜
Y性別:女
Y特質(zhì):高雅
Y外貌:紅長髮
Y性格:溫柔
Y喜好:劍術(shù)
Y厭惡:男權(quán)

Z姓名:星瑩
Z性別:女
Z特質(zhì):笨蛋
Z外貌:黑短髮
Z性格:開朗
Z喜好:漫畫
Z厭惡:規(guī)矩
即便使用Markdown或其他方法標(biāo)記,其中也會有大量重複內(nèi)容,浪費(fèi)許多Tokens,但這種資料形式可以排成表格,在資料不太大時,LLM能夠很好的理解它。

CSV

姓名,性別,特質(zhì),外貌,性格,喜好,厭惡
莉莉亞,女,可愛,馬尾,害羞,甜食,孤獨(dú)
雅柔,女,學(xué)霸,長髮,矜持,鴨子,虛偽
(??中略)
露比娜,女,高雅,紅長髮,溫柔,劍術(shù),男權(quán)
星瑩,女,笨蛋,短髮,開朗,漫畫,規(guī)矩

TSV

姓名  性別  特質(zhì)  外貌  性格  喜好  厭惡
莉莉亞  女  可愛  馬尾  害羞  甜食  孤獨(dú)
雅柔  女  學(xué)霸  長髮  矜持  鴨子  虛偽
(??中略)
露比娜  女  高雅  紅長髮  溫柔  劍術(shù)  男權(quán)
星瑩  女  笨蛋  短髮  開朗  漫畫  規(guī)矩

Markdown表格

|姓名|性別|特質(zhì)|外貌|性格|喜好|厭惡|
|---|---|---|---|---|---|---|
|莉莉亞|女|可愛|馬尾|害羞|甜食|孤獨(dú)|
|雅柔|女|學(xué)霸|長髮|矜持|鴨子|虛偽|
(??中略)
|露比娜|女|高雅|紅長髮|溫柔|劍術(shù)|男權(quán)|
|星瑩|女|笨蛋|短髮|開朗|漫畫|規(guī)矩|

建議

  • 中等資料量時節(jié)省Token用。
  • 量太大時低成本LLM處理表格的表現(xiàn)都不太好,高成本LLM也有機(jī)率出錯。
  • 使用CSV、TSV時,用Markdown的代碼框將之框起來,明確告訴LLM這是什麼格式。例如:
    ```csv
    表格內(nèi)容
    ```


偽高級語言

  • 適用情境:敘述中「如果」、「否則」、狀況眾多,或者引入變數(shù)後容易產(chǎn)生歧義,難以用自然語言表達(dá)清楚時。
  • 簡介:使用一些「看起來像高級語言」(實(shí)際上不是)的寫法,明確的區(qū)分出每個條件的區(qū)塊。

範(fàn)例

假設(shè)原文是「如果{{user}}做A,則{{char}}反應(yīng)1,否則若{{user}}做B,且目前場景正在洗澡,則{{char}}反應(yīng)2,若{{user}}沒有做A,且{{user}}做B,且目前場景在泡溫泉,則{{char}}反應(yīng)3,{{user}}沒有做A,且目前場景是洗澡和泡溫泉以外,{{char}}反應(yīng)4」,這種如同繞口令般的複雜嵌套,不僅浪費(fèi)許多Tokens,也容易把LLM繞暈,甚至把創(chuàng)作者自己繞暈,可以這樣寫:
if({{user}}正在做 == 'A'){
  {{char}}反應(yīng)1;
}else if({{user}}正在做 == 'B'){
  if(目前場景 == '洗澡'){
    {{char}}反應(yīng)2;
  }else if(目前場景 == '泡溫泉'){
    {{char}}反應(yīng)3;
  }else{
    {{char}}反應(yīng)4;
  }
}

建議

  • 不用真的嚴(yán)格按照程式語言撰寫。也不要使用對格式要求太嚴(yán)格的語言,雖然LLM最熟悉的可能是Python,但它也可能因為你格式錯誤而當(dāng)成無意義的囈語。
  • 建議模仿Javascript的形式,因為它不太嚴(yán)格,且它是一種易學(xué)易用的語言,最後它或許是LLM除Python外最熟悉的語言。
  • 不要加Markdown代碼框,避免LLM真的把它理解成一種高級語言,而產(chǎn)生奇怪的結(jié)果。


偽變數(shù)

  • 適用情境:一個詞有多種可能時、讓LLM隨機(jī)多選一時、使用相同的輸出格式但替換不同的關(guān)鍵詞時。
  • 簡介:自行建立一個偽變數(shù),就像Caveduck內(nèi)建的{{user}}與{{char}}那樣,但不同的是,Caveduck內(nèi)建的{{var}}是真的會被程式取代成正確的值,才扔給LLM處理,而我們定義的只是在提示內(nèi)讓LLM按照它的理解去處理這些字。

範(fàn)例

原文:
生成以下文字:「{{user}}被派到(隨機(jī)選取:中國、韓國、日本、英國)執(zhí)行任務(wù),任務(wù)內(nèi)容是(隨機(jī)選取:建立聯(lián)絡(luò)網(wǎng)、刺探情報、意識形態(tài)宣傳、收買官員)。」

LLM有時只會傻傻的把整句一字不差的輸出,或者因前文有什麼影響它認(rèn)知的東西,生成牛頭不對馬嘴的內(nèi)容,但我們使用變數(shù)就能避免這種情形:
## 變數(shù)
(這裡最好再加一段解釋如何執(zhí)行的內(nèi)容)
-
$location$:隨機(jī)選取(中國、韓國、日本、英國)
-
$mission$:隨機(jī)選取(建立聯(lián)絡(luò)網(wǎng)、刺探情報、意識形態(tài)宣傳、收買官員)

生成以下文字:「{{user}}被派到
$location$執(zhí)行任務(wù),任務(wù)內(nèi)容是$mission$。」

建議

  • 此類狀況不多時,內(nèi)容能用自然語言清晰描述時,可能是多此一舉,但如果內(nèi)容較多,這是個很好的辦法。
  • 你可以用任何方式去標(biāo)記變數(shù),但盡量不要與自然語言的常見符號衝突。
  • 不是必須,但建議將之前後封閉,例如$var$優(yōu)於$var,如果是非封閉的變數(shù),必須明確其後面有空格,這在拼音語言中問題不大,但使用表意文字時可能時常會忽略其空格,畢竟表意文字並不依賴空格切分詞彙或語素,另外也無法保證由自動翻譯系統(tǒng)將拼音文字翻譯為表意文字時,會保留那個空格。
  • 不建議和Caveduck使用一樣的方式{{var}},一來是你自己容易弄混。二來是有小道消息稱,他們正在開發(fā)一個名為「模板」的功能,屆時可以讓創(chuàng)作者將常用、容易重複的文字設(shè)成模板,並自行插入Prompt內(nèi),我認(rèn)為如果此訊息為真,到時使用方式很可能也是{{template}}
  • 條件複雜時可配合偽高級語言使用。

總結(jié)

雖然提出了很多方法,但由於LLM的原理,我們很難將它調(diào)教得完全理解並遵從,而且隨著提示長度與內(nèi)容的不同,可能原本好用的方法變得沒什麼效果,任何方法都需要創(chuàng)作者自己長時間的嘗試才能找到最優(yōu)解,難以千篇一律的生搬硬套。

手冊

Markdown


XML


JSON


  • LLM(Large Language Model):大型語言模型,像是OpenAI的GPT等,能基於大量文字資料進(jìn)行自然語言處理或生成。例如在Caveduck中,與AI角色的所有互動都是透過LLM完成。LLM擅長理解與生成類似人類語言的文字,但需要精確的提示(Prompt)來達(dá)成理想效果。
  • 提示詞(Prompt):創(chuàng)作者提供給LLM的文字輸入,用於引導(dǎo)模型生成回應(yīng)。Prompt的設(shè)計對生成結(jié)果影響甚大。清晰、簡潔的Prompt能提高模型理解意圖的準(zhǔn)確性,冗長或含糊的提示則可能導(dǎo)致回應(yīng)偏離預(yù)期。
  • Token:Token是LLM處理文字的最小單位,可包括單詞、標(biāo)點(diǎn)符號或部分單詞。在Caveduck中,每次互動都會消耗Token,包括使用者輸入的內(nèi)容、角色的Prompt,和角色產(chǎn)生的回應(yīng)。每個LLM的Token處理上限不同,但Caveduck未公開具體的上限數(shù)字,大致可透過消耗的點(diǎn)數(shù)推測。過多的Token可能導(dǎo)致內(nèi)容被截斷,因此設(shè)計Prompt時需要優(yōu)化長度與信息密度,確保最重要的部分能完整被處理。希望未來Caveduck能公佈詳細(xì)Token上限資訊,方便創(chuàng)作者更有效率地設(shè)計提示詞。
  • YAML(Yet Another Markup Language):一種簡潔的資料表示語言,類似JSON,但更容易讀寫。適合用於簡單結(jié)構(gòu)化資料,常見於設(shè)定檔中。
  • 層次結(jié)構(gòu)(Hierarchy):指資訊的組織方式。透過明確的層級標(biāo)示(例如以嵌套結(jié)構(gòu)呈現(xiàn)內(nèi)容),能幫助LLM更有效地理解並解析指令或內(nèi)容。

追蹤 創(chuàng)作集

作者相關(guān)創(chuàng)作

相關(guān)創(chuàng)作

更多創(chuàng)作