iT邦幫忙

2023 iThome 鐵人賽

DAY 19
1
AI & Data

以 OpenAI 以及 LangChain 實做我的聊天機器人系列 第 19

[D19] LangChain 專題實做 - 詞彙教學智慧生成

  • 分享至 

  • xImage
  •  

在這篇文章中,我們將深入探討如何實現一個全面而詳盡的詞彙教學智慧生成流程。在之前的文章中,我們已經展示了如何利用 LLMChain 把有前後相依性的語言提示任務串接起來,形成一個連續的呼叫流程。但如果這個流程更加複雜和冗長呢?LangChain 是否提供了更進階的工具來幫助我們處理這種情況?

本篇文章的主要目的就是透過實作一個更加詳細和冗長的詞彙教學生成流程,來展示 LangChain 的進階功能。

在我們正式開始之前,讓我們先來詳細說明幾個本篇文章中會被頻繁使用的 LangChain 基本功能。

LLMChain 的各類呼叫方式

在前一篇文章中,我們已經簡單介紹了如何使用 LLMChain 的最基本呼叫方式。現在,讓我們先來複習最基本的呼叫方式,然後再來看看其他可行的方法。

基本呼叫方式

首先,最基本的呼叫方式如下:

from langchain import PromptTemplate, OpenAI, LLMChain

llmchain_template = "請將 {sentence} 翻譯成英文"
chain1 = LLMChain(
    llm=chat_model,
    prompt=PromptTemplate.from_template(llmchain_template)
)

# 執行方法一
chain1('很高興認識你')

--- 輸出結果 ---
>> {'sentence': '很高興認識你', 'text': 'Nice to meet you.'}

使用 run 函式

你也可以使用 run 函式來執行,這樣你就需要用字典形式傳入參數。這種方式只會回傳翻譯結果。

# 執行方法二
chain1.run({
    "sentence": "很高興認識你"
})

--- 輸出結果 ---
>> Nice to meet you.

**使用 inputs 參數

第三種方式與第一種相似,但你需要明確地使用 inputs 參數來傳入你的句子。

# 執行方法三
chain1(inputs={
    "sentence": "很高興認識你"
})

--- 輸出結果 ---
>> {'sentence': '很高興認識你', 'text': 'Nice to meet you.'}

只回傳 output

最後,如果你只想要回傳輸出結果,你可以使用 return_only_outputs 參數。

# 執行方法四,只回傳 output
chain1(inputs={
        "sentence": "很高興認識你"
    }, return_only_outputs=True)

--- 輸出結果 ---
>> {'text': 'Nice to meet you.'}

Chain 的除錯訊息

Chain 物件採用封裝的設計方式,使得在構建複雜的提示訊息流程時,我們能更加清晰和有效地管理各個提示單元的狀態和互動行為。然而,這種封裝在開發階段有時會帶來除錯的困難。

考慮到設計和實際運作階段的不同需求,Chain 物件因此原生支持一個名為 verbose 的參數,用以輔助開發者進行除錯。當將 verbose 參數設置為 True,Chain 物件會提供更多的執行細節,以便我們進行分析和調整。

以下是一個範例,展示了如何使用 verbose=True 獲取詳細的執行信息:

from langchain import PromptTemplate, OpenAI, LLMChain

llmchain_template = "請將 {sentence} 翻譯成英文"
#llmchain_template = "What is a good name for a company that makes {product}?"
chain2 = LLMChain(
    llm=chat_model,
    prompt=PromptTemplate.from_template(llmchain_template),
    verbose=True
)

# 執行方法一
chain2('很高興認識你')

在這個例子中,當 verbose 設定為 True,結果會包括提示訊息的完整狀態和執行結果,例如:

> Entering new LLMChain chain...
Prompt after formatting:
請將 很高興認識你 翻譯成英文

> Finished chain.
{'sentence': '很高興認識你', 'text': 'Nice to meet you.'}

這些詳細的執行細節能讓我們更容易理解 Chain 物件的內部運作機制,並有助於我們在開發過程中進行調試和優化。

LangChain 的基礎 Chain 類別介紹

在我們之前的多篇文章中,大家可能已經對 LLMChain 非常熟悉。然而,LangChain 不僅有 LLMChain,它還提供了一系列易用且功能豐富的基礎 Chain 類別。今天我們就來介紹其中幾個在本次實作中使用到的的基礎類別。

SimpleSequentialChain: 簡單序列串接

https://ithelp.ithome.com.tw/upload/images/20230923/20154415WMFM2p9iO9.png
首先介紹的是 SimpleSequentialChain 類別。這個類別最大的特點是它僅支持單一輸入和輸出,使得這個類別成為入門序列串接操作的絕佳選擇。因為它相對簡單,所以對於初學者來說非常友好。

基本用法

假設我們首先需要一個 Chain,其工作是根據特定的主題(如 "旅行用語")隨機生成一個英文句子。

from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain

template1 = "請從{topic}這個情境下,隨機產生一個英文例句。"
prompt_tempalte1 = PromptTemplate.from_template(template1)
simple_seq_chain1 = LLMChain(llm=chat_model, prompt=prompt_tempalte1, verbose=True)

接下來,我們希望對這個英文句子進行翻譯。

template2 = "將 {translating_sentence} 翻譯成中文"
prompt_tempalte2 = PromptTemplate.from_template(template2)
simple_seq_chain2 = LLMChain(llm=chat_model, prompt=prompt_tempalte2, verbose=True)

串接與執行

定義了這兩個 LLMChain 元件後,我們可以使用 SimpleSequentialChain 來實現這兩個 Chain 的串接。這意味著,當我們向這個 SimpleSequentialChain 類別輸入 "旅行用語",它將經過 simple_seq_chain1 生成一個英文句子,再透過 simple_seq_chain2 將其翻譯成中文。

由於我們開啟了 verbose 模式,我們可以清晰地看到每個 Chain 在運行過程中到底發生了什麼事情。

# combine all the chains together
from langchain.chains import SimpleSequentialChain

sequential_chain = SimpleSequentialChain(
    chains=[
        simple_seq_chain1,
        simple_seq_chain2,
    ],
    verbose=True)

sequential_chain('旅行用語')

--- 以下是實際的輸出 ---
> Entering new SimpleSequentialChain chain...

> Entering new LLMChain chain...
Prompt after formatting:
請從旅行用語這個情境下,隨機產生一個英文例句。

> Finished chain.
I can't wait to explore the vibrant streets of Tokyo and immerse myself in the local culture during my upcoming trip.

> Entering new LLMChain chain...
Prompt after formatting:
將 I can't wait to explore the vibrant streets of Tokyo and immerse myself in the local culture during my upcoming trip. 翻譯成中文

> Finished chain.
我迫不及待地想要在即將到來的旅行中探索東京充滿活力的街道,並沉浸在當地的文化中。

> Finished chain.
{'input': '旅行用語', 'output': '我迫不及待地想要在即將到來的旅行中探索東京充滿活力的街道,並沉浸在當地的文化中。'}

這樣的設計使得 SimpleSequentialChain 不僅易於理解,而且也方便我們進行除錯和追蹤程序的執行流程。所以,無論您是一位經驗豐富的開發者還是剛入門的新手,這個類別都能讓您的開發工作變得更加輕鬆。

SequentialChain: 可高度客制的序列訊息傳遞元件

https://ithelp.ithome.com.tw/upload/images/20230923/20154415RWzluxBduD.png
與 SimpleSequentialChain 相比,SequentialChain 提供了更高度的彈性和自定義能力。簡單來說,這個類別讓您能夠在一個完整的流程中,傳遞多個輸入和輸出變數。這樣的設計讓流程更加靈活和可控。

如何使用?

第一步:設定隨機生成例句的提示

首先,我們像以前一樣,先設定一個根據特定主題隨機生成英文例句的 LLMChain。

template1 = "請從{topic}這個情境下,隨機產生一個英文例句。"
prompt_tempalte1 = PromptTemplate.from_template(template1)
seq_chain1 = LLMChain(llm=chat_model, prompt=prompt_tempalte1, output_key='generated_sentence', verbose=True)

第二步:設定多變數的提示訊息

接著,我們會設計一個需要兩個變數(生成的句子和目標語言)的 LLMChain。

template2 = "將 {generated_sentence} 翻譯成 {user_lang}"
prompt_tempalte2 = PromptTemplate.from_template(template2)
seq_chain2 = LLMChain(llm=chat_model, prompt=prompt_tempalte2, output_key='translated_sentence', verbose=True)

第三步:串接與執行

最後,我們使用 SequentialChain 來串接這兩個 Chains。這裏要特別注意 input_variablesoutput_variables 這兩個參數。

  • input_variables 是用於指定整個流程起始時會傳入哪些參數。這不包括在中間流程會用到的變數。
  • output_variables 則用於指定最終輸出的變數
from langchain.chains import SequentialChain

sequential_chain = SequentialChain(
    chains=[
        seq_chain1,
        seq_chain2,
    ],
    input_variables = ['topic', 'user_lang'],
    output_variables = ['generated_sentence', 'transalted_sentence'],
    verbose=True)

sequential_chain({
    'topic': '旅行用語',
    'user_lang': user_lang
})

如何串接變數?

你可能會好奇,第二個提示中的 generated_sentence 參數該如何取得?其實非常簡單,它來自於第一個 LLMChain 的輸出。當你在設定第一個 LLMChain 時,使用了 output_key='generated_sentence',這個設定會讓第一個 LLMChain 使用 generated_sentence 這個鍵值來儲存它的輸出。然後,這個輸出就會直接作為第二個 LLMChain 的輸入參數。

這種設計方式不僅使流程更為靈活,也使得我們能更容易地理解和追蹤每一個 Chain 在流程中的角色和責任。所以,不論你是一個有經驗的開發者或是剛入門的新手,SequentialChain 都能讓你更有效地構建複雜的工作流程。

詞彙教學智慧生成

終於到達了本文的核心部分!在前面的段落中,我們詳細介紹了實現這個詞彙教學的智慧生成程序所需的 LangChain 基本概念和工具。接下來,我們將深入探討這個實作的細節。
https://ithelp.ithome.com.tw/upload/images/20230923/20154415A9zkryV4OY.png

整體流程

這個詞彙教學智慧生成程式的流程相當簡單。首先,程式會假設使用者已經選擇了他們想學習的特定影片內容。然後,我們使用 SequentialChain 來串連一系列的提示模組。

  • 第一步驟:使用 TransformChain 從使用者選定的影片內容中隨機挑選三個例句作為教學材料。
  • 第二步驟:這些隨機選取的例句將被餵進第二個 LLMChain。這個鏈會讓語言模型從這些例句中選取約 5 個詞彙作為教學目標。
  • 第三步驟:最後一個 LLMChain 會根據我們提供的目標詞彙、使用者的需求和相關的背景信息,生成一個完整的語言教學內容。

詞彙選取的設計

首先,我們來看一下第二個步驟,也就是隨機選取教學詞彙的 LLMChain。下面是該模組的程式碼:

# lex selection chain design
from langchain.prompts.chat import (
    ChatPromptTemplate,
    HumanMessagePromptTemplate,
    SystemMessagePromptTemplate
)
from langchain.chains import LLMChain
from langchain.output_parsers import CommaSeparatedListOutputParser

output_parser_lex_learning = CommaSeparatedListOutputParser()

def get_lex_selection_chain():
    template="""你是一個專業的外語老師,你有一個特殊專長是在能夠以影片的內容找出值得教學的內容,你也很擅長做課程的規劃。

    接下來我會提供給挑選出來的教學例句,請在所有教學例句裏面隨機找出 5 個左右值得拿來做教學的詞彙。

    教學例句: {selected_captions}

    {format_instructions}
    """
    system_message_prompt = SystemMessagePromptTemplate(
        prompt = PromptTemplate(
            template = template,
            input_variables=["selected_captions"],
            partial_variables={"format_instructions": output_parser_lex_learning.get_format_instructions()}
        )
    )

    chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt])

    chain = LLMChain(llm=chat_model,
                     prompt=chat_prompt,
                     output_key='selected_lexicons',
                     verbose=True)

    return chain

lex_selection_chain = get_lex_selection_chain()

這段代碼會使語言模型扮演一個專業的外語老師,專門從影片內容中挑選出值得教學的詞彙。

詞彙教學的設計

接著是第三個 LLMChain 的設計,這個鏈負責生成詞彙教學內容。程式碼如下:

# lex teaching chain design
def get_lex_teaching_chain():
    template="""你是一個專業的語言教材編輯,我會提供給你幾個要教學的詞彙,請你以親切且簡短的口吻,針對那幾個詞彙做說明。
    並且在你說明詞彙時,同時提供例句以及例句的翻譯(in {user_lang})。

    教學詞彙: {selected_lexicons}
    """
    system_message_prompt = SystemMessagePromptTemplate(
        prompt = PromptTemplate(
            template = template,
            input_variables=["user_lang", "selected_lexicons"],
        )
    )

    humman_message_prompt = HumanMessagePromptTemplate.from_template('{input}')
    chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, humman_message_prompt])

    chain = LLMChain(llm=chat_model,
            prompt=chat_prompt,
            verbose=True)

    return chain

lex_teaching_chain = get_lex_teaching_chain()

在這裡,語言模型會變成一位語言教材編輯,用親切、簡短的口吻對選出的詞彙進行詳細說明。

完整的 SequentialChain

有了以上所有的必要單元後,我們可以這樣來定義完整的 SequentialChain

lex_teaching_overall_chain = SequentialChain(
    chains=[sentence_random_selection_chain, lex_selection_chain, lex_teaching_chain],
    input_variables=["user_lang", "input"],
    # Here we return multiple variables
    output_variables=["selected_captions", "selected_lexicons", "text"],
    #output_variables=["video_source"],
    verbose=True)

實際應用

最後,讓我們看一下這個 SequentialChain 實際執行後的輸出:

# test lex_teaching_overall_chain
response = lex_teaching_overall_chain({
    'user_lang': user_lang,
    'input': '我想多學一些詞彙。~'
})

print(response['text'])

--- 以下是實際的輸出結果 ---

當然!我很樂意幫助你學習新詞彙。以下是你提供的詞彙的說明:

1. celebration (慶祝) - Celebration 是指慶祝特殊事件或重要時刻的活動。這可以是一個節日、生日、婚禮或其他值得慶祝的場合。例如:We had a big celebration for my sister's graduation. (我們為我妹妹的畢業舉辦了一個盛大的慶祝活動。)

2. stories (故事) - Stories 是指以文字或口述方式傳遞的故事。這些故事可以是虛構的,也可以是真實的。例如:I love reading bedtime stories to my children. (我喜歡給我的孩子們讀睡前故事。)

3. art (藝術) - Art 是指以創造性方式表達思想、情感或美感的活動。這可以包括繪畫、雕塑、音樂、舞蹈等形式。例如:She is studying art at university. (她正在大學學習藝術。)

4. storytelling (說故事) - Storytelling 是指以口述方式講述故事的技巧或活動。這可以是在家庭、學校或其他場合進行的。例如:The children gathered around the campfire for an evening of storytelling. (孩子們圍著營火聚集,度過了一個說故事的晚上。)

5. history (歷史) - History 是指過去事件和人物的記錄和研究。它可以包括國家、社會、文化和個人的歷史。例如:I enjoy learning about ancient history. (我喜歡學習古代歷史。)

希望這些說明和例句能幫助你更好地理解這些詞彙!如果你還有其他需要學習的詞彙,請隨時告訴我。

這個輸出結果是一個完整的詞彙教學內容,其中包括了詞彙的解釋、例句以及例句的翻譯。

結語

這就是我們今天要介紹的所有概念和實作!如果您對於這個過程有更多的興趣,您可以訪問這裡查看更多詳細的執行過程和除錯信息:D19. LangChain 專案實做 - 詞彙教學智慧生成.ipynb

希望這篇文章能對您有所幫助!如有任何問題或建議,請隨時與我們聯繫。謝謝!


上一篇
[D18] LangChain 專案實做 - 例句推薦與 LLMChain 介紹
下一篇
[D20] LangChain 專題實做 - 資料的讀取與轉換
系列文
以 OpenAI 以及 LangChain 實做我的聊天機器人41
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言