AI應用必備:探索LangChain PromptTemplate 提示模板的入門與應用-1

Sean Yeh
Python Everywhere -from Beginner to Advanced
19 min readJul 27, 2024

--

Ronda, España
目錄  

何謂PromptTemplate提示模板?
LangChain PromptTemplate入門
字串提示模板(PromptTemplate)
對話提示模板(ChatPromptTemplate)
小結

隨著人工智慧技術的迅速發展,AI大型語言模型(LLM)的橫空出現。如何運用AI模型建立各式的應用服務,應用在各行各業中成為了開發者關注的焦點。

LangChain是一個用來開發大型語言模型(LLM)應用程式的框架,記得曾經在「LangChain框架揭秘: 從零開始了解開發LLM模型應用」一文中提到: LangChain 的整個模型的輸入與輸出過程(又稱為Model I/O)中,包括了從一開始的prompt提示到與LLM語言模型的互動,最終輸出特定格式的結果。而本篇要討論的PromptTemplate提示模板就屬於整個流程中的第一部分。

透過 PromptTemplate 這樣的提示模板技術,能夠顯著提升AI模型的性能。在本篇文章中我們將介紹 LangChain PromptTemplate 的基本概念。包括「什麼是PromptTemplate?」、「為何我們需要它?」到「如何安裝設置PromptTemplate?」 以及「如何在實際的應用上進行各項操作」。希望藉著這樣的說明能夠幫助大家快掌握它。

此外,我們將會再進一步討論PromptTemplate中的字串提示模板( PromptTemplate )與對話提示模板( ChatPromptTemplate ),並且示範如何利用這些提示模板來優化AI的提示。

之後,我們還會進一步的介紹對話提示模板的角色物件以及提示模板的進階使用方式,希望這些介紹可以為大家提供一個學習 LangChain 的指引。

何謂PromptTemplate提示模板?

PromptTemplate是LangChain中一個強大且靈活的工具,也是 LangChain 重要的核心概念之一。PromptTemplate 提示模板在LangChain中扮演重要的角色。它的設計目的是在透過結構化的模板來簡化重複的內容並提高使用AI模型的效率與準確性。

舉例來說,在一個能夠自動產生食譜的AI應用服務中,可能會需要像是『請提供一個使用牛肉製作一道菜的食譜』的提示指令,或者是『請提供一個使用鯖魚製作一道菜的食譜』的提示指令。如果沒有使用PromptTemplate的話,您可能需要很多個類似但不一樣的指令,就像上面一樣,需要兩個不同的指令。

然而若使用PromptTemplate提示模板的話,就可以簡化Prompt指令的設計過程,將重複性很高的部分從Prompt提示指令中抽象化出來,作為參數,並將剩下的提示放入模板中。因此,如上面的例子我們可以將「牛肉」與「鯖魚」這個部分抽出來抽象化為參數{food},當我們需要使用「羊肉」、「雞肉」等等其他食物時,就不用重新改寫提示指令。這樣可以讓提示模板在需要時得以快速的替換參數的內容,讓開發者省去煩惱,將心力專注於優化模型的性能。

因此,這些提示模板有著下面的特性:

# 結構清晰

首先,PromptTemplate允許開發者定義清晰的結構,可將原本複雜的輸入資料進行分解和整理。這樣一來,讓模型更容易地分析和理解我們輸入的指令,進而提高其準確性和一致性。

# 靈活運用

由於在實際的應用上,不同的情境下可能會需要使用不同的提示模板,PromptTemplate提供了靈活的配置方式,讓開發者可以根據具體需要來調整模板的設計。

# 使用簡單

LangChain的PromptTemplate設計簡單且直覺。開發者可以透過簡單的語法來進行模板的設計,提示模板中包括固定「不變」的部分和「可變動」的部分。就如前面所提到的食譜應用服務的例子一樣,在固定不變動的部分(例如:請提供一個使用OO製作一道菜的食譜),用來設置不變的提示結構,而在提示模板中可能會變動的部分(如OO的部分)則允許動態插入不同的資料(牛肉、鯖魚、羊肉或雞肉等等)。這種設計方式大大提高了模板的靈活性和可重用性。

# 單次與多次對話

除了以字串為基礎之 「PromptTemplate 字串提示模板」外, LangChain 還提供了以對話訊息為基礎之「ChatPromptTemplate 對話提示模板」。「PromptTemplate 字串提示模板」適用於簡單的提問與回答,而「ChatPromptTemplate 對話提示模板」則專門設計用來處理需要上下文多次來回對話的情境,

ChatPromptTemplate 對話提示模板允許開發者定義不同角色的提示,例如 AIMessage、HumanMessage 和SystemMessage。透過這種設計方式可以更逼真的模擬對話情境,使語言模型能夠在對話中提供更自然和具連貫性的回答。

簡單總結來說,PromptTemplate提示模板透過結構化的設計,幫助開發者將輸入的指令標準化,來提高AI模型的效率和準確性。無論是處理單一任務還是多輪對話,它都能提供強大的支援,可以說是LangChain中一個強大且靈活的工具。

LangChain PromptTemplate入門

在這一個段落,我們將介紹如何安裝和設置 PromptTemplate提示模板,並透過實際的程式碼案例來說明PromptTemplate的基本語法和使用方法。

1. 安裝與設置

LangChain的PromptTemplate安裝實際上相當的簡單。首先,要先確認您的工作環境(也可能是虛擬環境)中已經安裝了Python。然後,使用以下命令在工作環境環境中安裝LangChain:

pip install langchain

當然,您也會需要用到AI語言模型,除了OpenAI之外,您也可以選擇Google的Gemini或者是Claude等語言模型,在這裏我們依然使用OpenAI模型來做示範。因此,也請在同樣的環境中執行下面的指令安裝 langchain_openai 套件。

pip install langchain_openai

安裝完成後,就可以建立一個python檔案(例如:app.py或main.py等),開始進行基本的設定與環境配置。在您的Python檔案中引入所需要的套件:

# 引入語言模型
from langchain_openai import ChatOpenAI

# 引入PromptTemplate
from langchain.prompts import PromptTemplate

這樣就完成了LangChain PromptTemplate的主要設置。接下來,可以根據需要進行更詳細的配置,來適應不同的應用情境。

2. 基礎語法與使用方法

LangChain PromptTemplate的語法非常直覺,開發者可以快速上手。您可以從定義一個基本的PromptTemplate提示模板開始著手。

#定義模板

首先,我們只要使用剛才引入的PromptTemplate類別(from langchain.prompts import PromptTemplate),就可以輕鬆建立一個簡單的提示模板:

template = PromptTemplate(
template="This is a template with {variable1} and {variable2}.",
input_variables=["variable1", "variable2"]
)

在這個例子中,我們建立了一個包含兩個變數的模板。當我們要使用這個模板時,可以提供相對應的變數值(variable1="value1", variable2="value2"):

prompt_string = template.format(variable1="value1", variable2="value2")
print(prompt_string)

執行到目前為止的程式碼,將會輸出下面的結果:

This is a template with value1 and value2.

就這樣,我們已經建立了一個基本的PromptTemplate。是不是很簡單?接下來,就可以進一步討論使用這些模板了。

就整體來說,安裝與設置 LangChain PromptTemplate並不算困難,而使用它的基礎語法也相當直覺。只需要透過幾個簡單的步驟,就可以讓開發者快速上手並建立有效的提示模板。在下一段中,我們將探討如何使用字串提示模板(PromptTemplate)和對話提示模板(ChatPromptTemplate)。

字串提示模板(PromptTemplate)

字串提示模板(PromptTemplate)是LangChain中最基本的一種模板形式,它以字串為基礎,用來生成靜態的文本提示。

PromptTemplate其主要功能是將預先定義好的模板與動態資料相結合,來生成特定格式的字串。它的變數可以在建立模板時預先指定,並在使用時將具體的內容值填入,進而組成最後的提示字串。

這種方式可以簡化文本生成的過程,尤其是在當我們想要多次生成具重複性高,且相似度極高文本的情況。在這樣的情況下 PromptTemplate 提供的靈活且有效率的解決方案,更能顯現出它的優勢,以下舉例說明。

使用範例1:直接帶入PromptTemplate的參數

在下面的程式碼中,透過直接帶入參數的方式使用這樣的PromptTemplate模板:

from langchain.prompts import PromptTemplate

# 定義模板:直接帶入參數
prompt_template = PromptTemplate(
template="Hello {name}, today's date is {date}."
input_variables=["name", "date"],
)

# 填入訊息
filled_template = prompt_template.format(name="Alice", date="2024–07–24")
print(filled_template)

在定義模板的階段,使用PromptTemplate類別建立字串提示模板時,我們需要帶入「template」與「input_variable」兩個參數:

  • template:需放入提示模板中「固定不變」的部分,並對其中需要變動的地方以大括號( { } )的方式設定為模板參數。(template=”Hello {name}, today’s date is {date}.”
  • input_variable:需放入提示模板中「可變動」的參數名稱。參數名稱需使用list串列的方式表示。(input_variables=[“name”, “date”]

若想要看到組合後的完整Prompt提示詞,可以使用 print(prompt_template) 指令印出來。

## 透過format方法填入提示詞的參數值

我們建立好的PromptTemplate,需要透過format方法將模板參數也就是將「可變動」的參數值填入。( prompt_template.format(name=”Alice”, date=”2024–07–24")

在上面的例子中我們將參數 nameAlice填入,而參數 date則使用2024–07–24填入。執行後輸出的提示詞結果將會是:

Hello Alice, today's date is 2024–07–24.

## 透過invoke方法填入提示詞的參數值

除了透過format方法填入參數值外,我們另外也可使用invoke方法來將參數代入。不過,使用這個方式需要以字典的形式帶入參數值。我們可以修改一下上面的程式碼:

# 原始程式碼(format):
filled_template = prompt_template.format(name="Alice", date="2024–07–24")
print(filled_template)

# 修改後程式碼(invoke):
filled_template = prompt_template.invoke({"name":"Alice", "date":"2024–07–24"})
print(filled_template)

執行後輸出的結果是:

text="Hello Alice, today's date is 2024–07–24."

與前者類似,但是前面多了一個text。這是因為這個方式會建立一個StringPromptValue物件。物件中的text屬性才是我們需要的提示內容。

#使用範例2:不帶入PromptTemplate參數法

除了使用上面的方式,直接將參數帶入PromptTemplate物件中。我們也可以採用from_template 方法來建立PromptTemplate物件。其範例如下:

from langchain.prompts import PromptTemplate

# 定義模板:不帶入參數
prompt_template = PromptTemplate.from_template("Hello {name}, today's date is {date}.")

# 填入訊息:format
filled_template = prompt_template.format(name="Alice", date="2024–07–24")
print(filled_template)

使用這種方式會直接從提示中解析出模板裡面的參數,因此我們不必另外設定input_variables參數。在建立物件時更加方便。

## 可用加號臨時增加內容

此外,如果需要在既有的模板下增加內容時,也可以使用加號( + )來增加提示內容。

# 定義模板:不帶入參數
prompt_template = PromptTemplate.from_template("Hello {name}, today's date is {date}."
+ "try to tell me the a story about {place}.")

# 填入訊息:format
filled_template = prompt_template.format(name="Alice", date="2024–07–24", place="US")
print(filled_template)

## 亦可透過invoke方法填入提示詞的參數值

這裏跟「範例1:直接帶入PromptTemplate的參數」的說明一樣,我們除了使用format填入提示詞的參數值外,也可以使用invoke方法替換模板參數,不過在使用上需要以字典的格式帶入參數值。

# 定義模板:不帶入參數
prompt_template = PromptTemplate.from_template("Hello {name}, today's date is {date}."
+ "try to tell me the a story about {place}.")

# 填入訊息:invoke
filled_template = prompt_template.invoke({"name": "Alice", "date": "2024–07–24", "place": "US"})
print(filled_template)

我們從以上的例子可以看到,PromptTemplate 透過變數的替換來形成動態的內容。非常適合用在各種需要將輸出的文本格式化之情境。

對話提示模板(ChatPromptTemplate)

接下來要討論另一種提示模板。與前面提到的字串提示模板不同,對話提示模板(ChatPromptTemplate)是一種專為多回合對話設計的模板型態。對話提示模板讓開發者可以分別定義不同角色的提示,讓AI模型能夠更自然地進行對話。

ChatPromptTemplate可以模擬對話中的多個角色,是它的核心功能。這些角色除了使用者輸入的訊息(HumanMessage)外,還包括AI生成的訊息(AIMessage)以及系統提示或背景訊息(SystemMessage)。

透過這樣的結構化方式,可以產生更自然而連貫的對話體驗。接著我們就透過範例來說明。

#使用範例

以下是一個展示多回合對話的設計的ChatPromptTemplate範例:

from langchain_core.prompts import ChatPromptTemplate

# 定義對話模板
chat_template = ChatPromptTemplate.from_messages(
[
("system","You are a helpful {role}."),
("human","What is {topic}"),
("ai","Ok the answer is here")
]
)

print(chat_template)

首先需要從 LangChain 中( langchain_core.prompts )引入ChatPromptTemplate。然後要利用ChatPromptTemplate建立一個物件來定義對話模板。

我們可以使用from_messages方法(注意:前面提到的字串模板使用的是from_template ),建立對話提示模板物件。輸入from_messages方法的內容需要以tuple的方式將個別角色的訊息打包起來。如下:

[
("system","You are a helpful {role}."),
("human","What is {topic}"),
("ai","Ok the answer is here")
]

並且在各角色指令訊息中把未來需要被替換的部分設定為模板參數。例如:{role}{topic} 等位置。

設置完畢後執行程式碼,將會輸出下面的結果:

input_variables=['role', 'topic'] 
messages=[
SystemMessagePromptTemplate(
prompt=PromptTemplate(
input_variables=['role'],
template='You are a {role}.')
),
HumanMessagePromptTemplate(
prompt=PromptTemplate(
input_variables=['topic'],
template='What is {topic}')
),
AIMessagePromptTemplate(
prompt=PromptTemplate(
input_variables=[],
template='Ok the answer is here')
)
]

由上結果可知,我們已經建立好物件。接著可以帶入提示詞的參數。

## 透過format_messages方法填入提示詞的參數值

在此使用format_messages 來替換上面對話訊息中的參數值。請注意,這裡是 format_ 而前面用的是 from_ ,兩者乍看之下很像,請務必注意。

chat_messages = chat_template.format_messages(
role="high school teacher",
topic="the capital of France"
)

print(chat_messages)

執行後將得到下面的提示詞結果,是個訊息物件的list串列:

[
SystemMessage(content='You are a high school teacher.'),
HumanMessage(content='What is the capital of France'),
AIMessage(content='Ok the answer is here')
]

從上面的結果可以看到原本設定的模板參數,都已經被替換為我們輸入的值了。

## 亦可透過invoke方法填入提示詞的參數值

當然,除了使用 format_messages 填入參數值外,我們一樣可以使用 invoke 方法填入參數值。但是還記得嗎?使用 invoke 方法填入參數值的時候,需要以「字典」的方式代入。

# invoke
chat_messages = chat_template.invoke({"role": "high school teacher", "topic": "the capital of France"})

print(chat_messages)

執行後應該會得到下面的提示詞結果:

messages=[
SystemMessage(content='You are a high school teacher.'),
HumanMessage(content='What is the capital of France'),
AIMessage(content='Ok the answer is here')
]

到目前為止,我們所產生的都還是「提示詞」,還不是經過語言模型回答的結果。若想要知道剛剛產生的prompt會得到什麼樣的結果的話,可以再使用invoke方法將前面產生的「提示詞」傳入chat_model 語言模型裡面:

chats = chat_model.invoke(chat_messages).content

print(chats)

這樣print出來的結果就會是語言模型回答的內容:

The capital of France is Paris.

透過以上的例子可以暸解到如何使用 ChatPromptTemplate 來建立一個複雜的多回合對話,並且動態的增加新訊息。

小結

總結來說,PromptTemplate和ChatPromptTemplate在LangChain中提供了靈活且強大的工具,幫助開發者有效率的產出和管理提示文本。這些工具在自然語言處理、聊天對話系統和其他各種AI應用服務中都受到廣泛的應用,我們暫時停在這裡。

下一篇文章中,我們將探討「對話提示模板( ChatPromptTemplate )」的三種角色物件( AIMessage, HumanMessage, SystemMessage )還沒有提及的部分,以及提示模板的其他使用方式。敬請期待,不要錯過!

延伸閱讀

--

--

Sean Yeh
Python Everywhere -from Beginner to Advanced

# Taipei, Internet Digital Advertising,透過寫作讓我們回想過去、理解現在並思考未來。並樂於分享,這才是最大贏家。