# [LangChain] 範例-翻譯機 日期:2023/09/19 ## 敘述 - 主題:MultiPromptChain()、LLMRouterChain() - 使用情境:翻譯機。除了正常的翻譯以外,也可透過自然語言要求程式切換成其他語言種類,讓它在之後依照提供的語言進行翻譯。 - 輸入:1. 想要翻譯的文本。2.要求切換成別種翻譯語言(設定之後希望翻譯的語言) - 輸出:將在設定的兩種語言中來回進行翻譯 ## 目錄 - [1. 主程式](#1-主程式) - [2. 輸入輸出](#2-輸入輸出) __________________ ## 1. 主程式 導入套件 ```python= from dotenv import load_dotenv load_dotenv() from langchain.chat_models import ChatOpenAI from langchain.prompts import ( PromptTemplate, ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, ) from langchain import LLMChain llm = ChatOpenAI(temperature=0.7) ``` ```python= import re from langchain.chains.router import MultiPromptChain from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE ``` 以下為翻譯機的主程式。 在此程式中,比較重要的物件包含MultiPromptChain()、LLMRouterChain()、MULTI_PROMPT_ROUTER_TEMPLATE()。 透過此程式可讓程式自行判斷需要使用帶有甚麼prompt的chain,進而達到不同輸入不同行動的效果。程式可執行的動作包含:1. 翻譯輸入的文本 2. 切換使用的語言。 如上述所說,因此程式中包含了兩個可以使用的chain。 切換使用語言的chain,所使用的prompt即為`language_choice_prompt`變數,會將這個prompt的資訊提供給LLMRouterChain(),讓LLMRouterChain()可以選擇是否使用帶有這個prompt的chain; 而翻譯所使用的chain,則是作為MultiPromptChain()的default_chain。只要輸入不是要求切換語言種類時,就會使用著個chain進行翻譯。 ```python= #先給予預設的翻譯語言。 lang1 = 'en' lang2 = 'zh' def translator(input_text): #將lang1和lang2定義為全域變數,讓語言變數可以在函式內重新定義,並在下一次呼叫函式時一同被使用。 global lang1, lang2 #定義destination prompt language_choice_prompt = """請確認<>中提及的語言種類,將列舉兩個提及的語言種類。請遵循以下規則,並且不要產生其他以外的回答。 輸出規則: 1. 使用ISO 639語言代碼列舉,例如:en, zh 2. 輸出的語言代碼需不多不少剛好兩個。若只有發現一種語言,則兩個語言輸出則為相同的代號。 <{input}> """ #使用以下格式整理所有promtpt prompt_infos = [ { "name": "language_choice", "description": "適用於當輸入為以下幾種時:1.提及要切換翻譯語言 2.提及兩種語言種類。", "prompt_template": language_choice_prompt, }, ] #使用所有prompt定義各自的chain destination_chains = {} for p_info in prompt_infos: name = p_info["name"] prompt_template = p_info["prompt_template"] prompt = PromptTemplate(template=prompt_template, input_variables=["input"]) chain = LLMChain(llm=llm, prompt=prompt) destination_chains[name] = chain #destinations_str包含各個不同prompt的名稱與敘述,router_chain將根據destinations_str選擇使用甚麼prompt destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos] destinations_str = "\n".join(destinations) #定義router_chain router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str) router_prompt = PromptTemplate( template=router_template, input_variables=["input"], output_parser=RouterOutputParser(), ) router_chain = LLMRouterChain.from_llm(OpenAI(), router_prompt) # #定義default_chain systemmessage = f'''請擔任翻譯機,而不要回答任何問題,將任何輸入都進行翻譯。 翻譯規則: <若輸入為語言-{lang1},則翻譯成語言-{lang2}; 若輸入為語言-{lang2},則翻譯成語言-{lang1}。> 另外,若需要翻譯成ZHTW,請使用台灣會使用的詞彙。''' default_prompt = ChatPromptTemplate( messages = [ SystemMessagePromptTemplate.from_template(systemmessage), HumanMessagePromptTemplate.from_template("{input}") ] ) default_chain = LLMChain(llm=llm, prompt=default_prompt) #將chain都加入到MultiPromptChain()中 chain = MultiPromptChain( router_chain=router_chain, destination_chains=destination_chains, default_chain=default_chain, verbose=False, ) #輸入提供到整個chain中 output = chain.run(input=input_text) #確認輸出是否為語言種類列舉。若是,將利用其中包含的語言代碼重新定義lang1和lang2 if re.match(r'^[a-zA-Z]{2}(?:, [a-zA-Z]{2})*$', output): lang_list = output.split(", ") lang1 = lang_list[0] lang2 = lang_list[1] return output ``` ## 2. 輸入輸出 將以下句子輸入提供給程式進行翻譯。 ```python= input_text = '有沒有可能天空下起血雨?' print(translator(input_text)) ``` :::success \> Entering new MultiPromptChain chain... None: {'input': '有沒有可能天空下起血雨?'} \> Finished chain. 有沒有可能天空下起血雨? Is it possible for blood rain to fall from the sky? ::: 上面輸出結果中的None,表示程式使用了默認的chain。 ```python= input_text = "今天是美好的星期五。" print(translator(input_text)) ``` :::success \> Entering new MultiPromptChain chain... None: {'input': '今天是美好的星期五。'} \> Finished chain. Today is a wonderful Friday. ::: 上面輸出結果中的None,表示程式使用了默認的chain。 ```python= input_text = "切換翻譯語言到中文和日文" print(translator(input_text)) ``` :::success \> Entering new MultiPromptChain chain... language_choice: {'input': '切換翻譯語言到中文和日文'} \> Finished chain. zh, ja ::: 上面輸出結果中的language_choice,表示程式使用了帶有language_choice這個prompt的chain。 輸出為『zh, ja』,表示之後的翻譯語言將使用中文和日文。 ___________________ 將多個句子供給程式進行翻譯。 為了讓畫面更簡潔,此處已將MultiPromptChain()的verbose參數設為False,僅顯示最終的輸出結果。 ```python= input_list = [ "Switch translation language to Chinese and English", "你是一位非常優秀的數學家。 你很擅長回答數學問題。", "有沒有一種可能,是所有人都活在一個虛擬世界當中?", "切換翻譯語言到中文和日文", "你都被打到流血了!", "有沒有可能天空下起血雨?", "今天是美好的星期五。", "今天是美好的星期五,下班後去吃點好料。", "切換翻譯語言,中文和英文", "Tell me, do you bleed?", "Please use the latest version of Python", ] for n in input_list: print('-'*40) print('輸入: ', n) print('輸出: ', translator(n)) ``` :::success \---------------------------------------- 輸入: Switch translation language to Chinese and English 輸出: zh, en \---------------------------------------- 輸入: 你是一位非常優秀的數學家。 你很擅長回答數學問題。 輸出: You are a very talented mathematician. You are excellent at solving math problems. \---------------------------------------- 輸入: 有沒有一種可能,是所有人都活在一個虛擬世界當中? 輸出: Is it possible for everyone to live in a virtual world? \---------------------------------------- 輸入: 切換翻譯語言到中文和日文 輸出: zh, ja \---------------------------------------- 輸入: 你都被打到流血了! 輸出: あなたは血を流している! \---------------------------------------- 輸入: 有沒有可能天空下起血雨? 輸出: 血雨が降る可能性はありますか? \---------------------------------------- 輸入: 今天是美好的星期五。 輸出: 今天は素敵な金曜日です。 \---------------------------------------- 輸入: 今天是美好的星期五,下班後去吃點好料。 輸出: 今天は素敵な金曜日です、仕事の後に美味しいものを食べに行きましょう。 \---------------------------------------- 輸入: 切換翻譯語言,中文和英文 輸出: zh, en \---------------------------------------- 輸入: Tell me, do you bleed? 輸出: 告訴我,你流血嗎? \---------------------------------------- 輸入: Please use the latest version of Python 輸出: 請使用最新版本的Python ::: 關於切換語言的方法,提供以下幾種輸入也能成功切換語言。 ```python= input_list = [ '我想要英翻中', '我的英文不好,幫我把英文句子成中文', '今天會使用到的語言有中文和日文', '我朋友是說義大利語,而我是使用中文', ] for n in input_list: print('-'*40) print(translator(n)) ``` :::success \---------------------------------------- en, zh \---------------------------------------- en, zh \---------------------------------------- zh, ja \---------------------------------------- zh, it :::