【DLAI×LangChain講座③】 Chains

背景

LangChainは気になってはいましたが、複雑そうとか、少し触ったときに日本語が出なかったりで、後回しにしていました。

DeepLearning.aiでLangChainの講座が公開されていたので、少し前に受講してみました。その内容をまとめています。

第2回はこちらです。

今回は第3回Chainsについてです。Chainsは「LLMを使って作る関数」といった感じです。また、LangChainの名前にもある通り、このChainは中心的な機能のようです。

Chains | 🦜️🔗 Langchain

アプローチ

DeepLearning.aiのLangChain講座の3の内容をまとめます。

おまけでは、SequentialChainのレシピの栄養解説や食材代替の例を試しました。

サンプル

今回は、これらのChainを試していきます。

  • LLMChain

  • Sequential Chains

    • SimpleSequentialChain

    • SequentialChain

  • Router Chain

import warnings
warnings.filterwarnings('ignore')
import os
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) # read local .env file

import pandas as pd
df = pd.read_csv('data/Data.csv')

まずは、データを読み込みます。このデータのダウンロード方法を説明します。

まず、Jupyterの[File]→[Open...]を押します。

こちらのページが開くので、Data.csvにチェックを入れ、[Download]を押します。これをノートブックのあるフォルダに入れればOKです。

df.head()

商品名とレビューコメントが入っていますね。

LLMChain

まずは、LLMChainです。LLMChainは、LLMを用いた関数を簡単に作るもののようです。

ここでは、ChatPromptTemplateを使って関数化する例が紹介されていますが、ドキュメントには、第1回のOutputParserと組み合わせてリスト形式で出力する例がありました。

LLM | 🦜️🔗 Langchain

from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import LLMChain

まずは、ChatOpenAIとChatPromptTemplateを作成します。「商品名に基づいて会社名を作る」というクリエイティブな関数のため、temperatureの値が大きくなっています。

llm = ChatOpenAI(temperature=0.9)
prompt = ChatPromptTemplate.from_template(
    "What is the best name to describe \
    a company that makes {product}?"
)

LLMChainに入力します。これでLLM関数の完成です。

chain = LLMChain(llm=llm, prompt=prompt)
product = "Queen Size Sheet Set"
chain.run(product)
'"Royal Rest Beddings"'

クイーンサイズのシーツのセットを取り扱う会社について、"Royal Rest Beddings"という名前が提案されています。おしゃれ度はよくわかりませんが、いい感じな気がしますね。

SimpleSequentialChain

次は、SimpleSequentialChainです。Chainを複数個直列につなげて段階的に出力を得る関数を作成します。

from langchain.chains import SimpleSequentialChain
llm = ChatOpenAI(temperature=0.9)

第1の関数は、先ほどの同様、「商品名に基づいて会社名を作る」関数です。

# prompt template 1
first_prompt = ChatPromptTemplate.from_template(
    "What is the best name to describe \
    a company that makes {product}?"
)

# Chain 1
chain_one = LLMChain(llm=llm, prompt=first_prompt)

第2の関数は、「会社名に基づいて会社紹介文を作る」関数です。1つ目の出力を入力とするLLM関数ですね。

# prompt template 2
second_prompt = ChatPromptTemplate.from_template(
    "Write a 20 words description for the following \
    company:{company_name}"
)
# chain 2
chain_two = LLMChain(llm=llm, prompt=second_prompt)

これらをSimpleSequentialChainでまとめます。

overall_simple_chain = SimpleSequentialChain(
	chains=[chain_one, chain_two],
	verbose=True
)

ここに、先ほどと同様に"Queen Size Sheet Set"を入力しています。

overall_simple_chain.run(product)
Entering new  chain...
"Royal Comfort Bedding"
Royal Comfort Bedding offers luxurious and high-quality bedding products designed to provide ultimate comfort for a good night's sleep.

Finished chain.

"Royal Comfort Bedding offers luxurious and high-quality bedding products designed to provide ultimate comfort for a good night's sleep."

"Royal Comfort Bedding"という会社名が出力され、それに基づき以下の紹介文が出力されています。

"Royal Comfort Bedding offers luxurious and high-quality bedding products designed to provide ultimate comfort for a good night's sleep."
"Royal Comfort Bedding"は、ラグジュアリーで高品質な寝具により、睡眠に究極の心地よさを提供します。

SequentialChain

次は、SequentialChainです。SimpleSequentialChainよりも柔軟性の高い機能で、段階的に得た出力を組み合わせて最終的な出力をすることができます。

またドキュメントには、第2回のMemoryと組み合わせる方法も紹介されています。Memoryと組み合わせることで、「対話履歴に基づいてユーザプロファイルを作成する」などの機能が一つの関数としてまとめられそうです。

Sequential | 🦜️🔗 Langchain

from langchain.chains import SequentialChain

第1の関数は、「レビューを英語に翻訳する」関数です。output_key="English_Review"とすることで、他のChainや最終出力で"English_Review"を利用できます。

llm = ChatOpenAI(temperature=0.9)

# prompt template 1: translate to english
first_prompt = ChatPromptTemplate.from_template(
    "Translate the following review to english:"
    "\n\n{Review}"
)
# chain 1: input= Review and output= English_Review
chain_one = LLMChain(
	 llm=llm, prompt=first_prompt, 
	 output_key="English_Review"
)

第2の関数は、「英語のレビューを要約する」関数です。Promptの{English_Review}には、第1の関数の出力が入る想定になっています。

second_prompt = ChatPromptTemplate.from_template(
    "Can you summarize the following review in 1 sentence:"
    "\n\n{English_Review}"
)
# chain 2: input= English_Review and output= summary
chain_two = LLMChain(
	 llm=llm, prompt=second_prompt, 
	 output_key="summary"
)

第2の関数は、「レビューの言語を判定する」関数です。Promptの{Review}には、入力であるReviewが入る想定になっています。

# prompt template 3: translate to english
third_prompt = ChatPromptTemplate.from_template(
    "What language is the following review:\n\n{Review}"
)
# chain 3: input= Review and output= language
chain_three = LLMChain(
	 llm=llm, prompt=third_prompt,
	 output_key="language"
)

第4の関数は、「レビューに対する返信を作成する」関数です。他のChainの出力であるsummary, languageが入る想定になっており、「レビューの言語に合わせて要点を抑えた回答を作成する」ことができそうです。


# prompt template 4: follow up message
fourth_prompt = ChatPromptTemplate.from_template(
    "Write a follow up response to the following "
    "summary in the specified language:"
    "\n\nSummary: {summary}\n\nLanguage: {language}"
)
# chain 4: input= summary, language and output= followup_message
chain_four = LLMChain(llm=llm, prompt=fourth_prompt,
                      output_key="followup_message"
                     )

最終的に4つのChainを組み合わせて1つの関数にします。あるChainの出力が他のChainの入力になっているなどしますが、実行する順番は勝手に計画してくれるようですね。

# overall_chain: input= Review 
# and output= English_Review,summary, followup_message
overall_chain = SequentialChain(
    chains=[chain_one, chain_two, chain_three, chain_four],
    input_variables=["Review"],
    output_variables=["English_Review", "summary","followup_message"],
    verbose=True
)
review = df.Review[5]
overall_chain(review)
Entering new chain...

Finished chain.

{'Review': "Je trouve le goût médiocre. La mousse ne tient pas, c'est bizarre. J'achète les mêmes dans le commerce et le goût est bien meilleur...\nVieux lot ou contrefaçon !?",
 'English_Review': "I find the taste mediocre. The foam doesn't hold, it's strange. I buy the same ones in stores and the taste is much better...\nOld batch or counterfeit!?",
 'summary': 'The reviewer is disappointed with the mediocre taste and poor foam consistency of the product they purchased, suspecting it might be an old batch or counterfeit compared to the better-tasting ones they usually purchase in stores.',
 'followup_message': "Cher(e) critique,\n\nNous sommes désolés d'apprendre que notre produit ne répond pas à vos attentes. Nous comprenons votre déception quant à la saveur médiocre et à la consistance de la mousse de notre produit, et nous regrettons sincèrement cette expérience décevante.\n\nNous tenons à assurer à nos clients que nos produits sont authentiques et fabriqués selon les normes de qualité les plus élevées. Cependant, il est possible qu'un lot ait été altéré ou qu'une erreur se soit produite au cours du processus de fabrication.\n\nNous vous invitons à nous contacter directement afin de pouvoir résoudre cette situation de manière satisfaisante pour vous. Nous serions ravis de pouvoir vous aider et de vous offrir une solution appropriée à votre situation. Votre satisfaction est notre priorité absolue et nous souhaitons regagner votre confiance envers notre marque.\n\nEncore une fois, nous vous présentons nos excuses les plus sincères pour cette expérience insatisfaisante. Dans l'attente de votre réponse, nous vous remercions de votre compréhension.\n\nCordialement,\n\nL'équipe de [Nom de la marque]"}

input_variables, output_variablesが出力されています。

Router Chain

最後はRouterChainです。RouterChainでは、複数の関数を使い分けることができます。

物理学者、数学者、歴史学者、コンピュータサイエンティストに対する質問ができるテンプレートを作成します。

physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise\
and easy to understand manner. \
When you don't know the answer to a question you admit\
that you don't know.

Here is a question:
{input}"""


math_template = """You are a very good mathematician. \
You are great at answering math questions. \
You are so good because you are able to break down \
hard problems into their component parts, 
answer the component parts, and then put them together\
to answer the broader question.

Here is a question:
{input}"""

history_template = """You are a very good historian. \
You have an excellent knowledge of and understanding of people,\
events and contexts from a range of historical periods. \
You have the ability to think, reflect, debate, discuss and \
evaluate the past. You have a respect for historical evidence\
and the ability to make use of it to support your explanations \
and judgements.

Here is a question:
{input}"""


computerscience_template = """ You are a successful computer scientist.\
You have a passion for creativity, collaboration,\
forward-thinking, confidence, strong problem-solving capabilities,\
understanding of theories and algorithms, and excellent communication \
skills. You are great at answering coding questions. \
You are so good because you know how to solve a problem by \
describing the solution in imperative steps \
that a machine can easily interpret and you know how to \
choose a solution that has a good balance between \
time complexity and space complexity. 

Here is a question:
{input}"""

各テンプレートとその説明をリスト化します。

prompt_infos = [
    {
        "name": "physics", 
        "description": "Good for answering questions about physics", 
        "prompt_template": physics_template
    },
    {
        "name": "math", 
        "description": "Good for answering math questions", 
        "prompt_template": math_template
    },
    {
        "name": "History", 
        "description": "Good for answering history questions", 
        "prompt_template": history_template
    },
    {
        "name": "computer science", 
        "description": "Good for answering computer science questions", 
        "prompt_template": computerscience_template
    }
]

ここから、RouterChainを作っていきます。

from langchain.chains.router import MultiPromptChain
from langchain.chains.router.llm_router import LLMRouterChain,RouterOutputParser
from langchain.prompts import PromptTemplate

llm = ChatOpenAI(temperature=0)

各テンプレートから作成した各専門家Chainを辞書に登録します。

destination_chains = {}
for p_info in prompt_infos:
    name = p_info["name"]
    prompt_template = p_info["prompt_template"]
    prompt = ChatPromptTemplate.from_template(template=prompt_template)
    chain = LLMChain(llm=llm, prompt=prompt)
    destination_chains[name] = chain  
    
destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
destinations_str = "\n".join(destinations)

defaultでは、inputに対してそのまま回答します。

default_prompt = ChatPromptTemplate.from_template("{input}")
default_chain = LLMChain(llm=llm, prompt=default_prompt)

次に、RouterChainを作っていきます。まずは、RouterのTemplateです。

MULTI_PROMPT_ROUTER_TEMPLATE = """Given a raw text input to a \
language model select the model prompt best suited for the input. \
You will be given the names of the available prompts and a \
description of what the prompt is best suited for. \
You may also revise the original input if you think that revising\
it will ultimately lead to a better response from the language model.

<< FORMATTING >>
Return a markdown code snippet with a JSON object formatted to look like:
```json
{{{{
    "destination": string \ name of the prompt to use or "DEFAULT"
    "next_inputs": string \ a potentially modified version of the original input
}}}}
```

REMEMBER: "destination" MUST be one of the candidate prompt \
names specified below OR it can be "DEFAULT" if the input is not\
well suited for any of the candidate prompts.
REMEMBER: "next_inputs" can just be the original input \
if you don't think any modifications are needed.

<< CANDIDATE PROMPTS >>
{destinations}

<< INPUT >>
{{input}}

<< OUTPUT (remember to include the ```json)>>"""

RouterのTemplate、ちょっと複雑すぎませんか?ここだけ抽象化されていないですね。と思ったら、これはインポートできる形にはなってるんですね。

Router | 🦜️🔗 Langchain#LLMRouterChain

最後に、router_promptをもとにLLMRouterChainを作成します。RouterOutputParserの役割はなんなんでしょうか?

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(llm, router_prompt)

そして、MultiPromptChainを構成します。router_chainsと、各専門家Chain、デフォルトChainを入力します。

chain = MultiPromptChain(
	 router_chain=router_chain, 
	 destination_chains=destination_chains, 
	 default_chain=default_chain, verbose=True
)
chain.run("What is black body radiation?")
Entering new  chain...
physics: {'input': 'What is black body radiation?'}
Finished chain.

'Black body radiation refers to the electromagnetic radiation emitted by an object that absorbs all incident radiation and reflects or transmits none. It is called "black body" because it absorbs all wavelengths of light, appearing black at room temperature. \n\nAccording to Planck\'s law, the intensity and distribution of this radiation depend on the temperature of the object. As the temperature increases, the peak of the radiation shifts to shorter wavelengths, resulting in a change in color from red to orange, yellow, white, and eventually blue at very high temperatures.\n\nBlack body radiation is a fundamental concept in physics and has been crucial in understanding various phenomena, such as the ultraviolet catastrophe and the development of quantum mechanics. It has applications in astrophysics, thermodynamics, and the study of the cosmic microwave background radiation, among others.'

「黒体放射」とは、全ての入射放射を吸収し、反射または透過させない物体が放出する電磁放射のことを指します。全ての光の波長を吸収するため、室温では黒く見えることから「黒体」と呼ばれます。
プランクの法則によれば、この放射の強度と分布は物体の温度に依存します。温度が上昇すると、放射のピークは短い波長にシフトし、赤からオレンジ、黄色、白、そして非常に高温時には青へと色が変わります。
黒体放射は物理学における基礎的な概念であり、紫外線災害や量子力学の発展など、様々な現象を理解する上で重要でした。それは天体物理学、熱力学、宇宙マイクロ波背景放射の研究などに応用されています。

よくわかりませんが、専門家っぽい回答です。(勉強したことあるようなないような。。)

chain.run("what is 2 + 2")
Entering new  chain...
math: {'input': 'what is 2 + 2'}
Finished chain.

"Thank you for your kind words! As a mathematician, I am happy to help with any math questions, no matter how simple or complex they may be.\n\nNow, let's solve the problem at hand. The question is asking for the sum of 2 and 2. To find the answer, we can simply add the two numbers together:\n\n2 + 2 = 4\n\nTherefore, the sum of 2 and 2 is 4."

あなたの優しい言葉に感謝します!私は数学者として、どんなに簡単あるいは複雑な数学の問題でもお手伝いできることが嬉しいです。
それでは、手元の問題を解いていきましょう。問題は2と2の合計を求めるというものです。答えを見つけるためには、これら2つの数を単純に足し合わせれば良いです:
2 + 2 = 4
したがって、2と2の合計は4です。

専門家に聞く問題としては簡単すぎたでしょうか?すごく優しく回答してくれました。

chain.run("Why does every cell in our body contain DNA?")
Entering new  chain...
None: {'input': 'Why does every cell in our body contain DNA?'}
Finished chain.

'Every cell in our body contains DNA because DNA is the genetic material that carries the instructions for the development, functioning, and reproduction of all living organisms. DNA contains the information necessary for the synthesis of proteins, which are essential for the structure and function of cells. It serves as a blueprint for the production of specific proteins that determine the characteristics and traits of an organism. Additionally, DNA is responsible for the transmission of genetic information from one generation to the next, ensuring the continuity of life. Therefore, every cell in our body contains DNA to ensure proper cellular function and to pass on genetic information to future generations.'

私たちの体のすべての細胞はDNAを含んでいます。なぜならDNAは、すべての生物の発達、機能、繁殖の指示を伝える遺伝物質だからです。DNAには、細胞の構造と機能に不可欠なタンパク質の合成に必要な情報が含まれています。DNAは、生物の特性や特徴を決定する特定のタンパク質の生産のための設計図として働きます。さらに、DNAは遺伝情報を次世代へ伝える役割を担っており、生命の連続性を保証しています。したがって、私たちの体のすべての細胞は、適切な細胞機能を確保し、遺伝情報を未来の世代に伝えるためにDNAを含んでいます。

今度は、生物学者がいないので該当者なしで、デフォルトの回答が返ってきました。

Routerとしての機能はちゃんとしていますね。ただこの例だと、「回答に適切なペルソナを作成し、そのペルソナで答えてください。」でもある程度動きそうですね。実際に使うのは、各Chainの専門性を高めた場合かもしれません。

RouterOutputParserの役割ですが、この部分を作るためのもののようですね。

{'input': 'Why does every cell in our body contain DNA?'}

今回は各LLMChainのinput_variablesが統一されていましたが、統一されていなくても、それぞれに対してちゃんと入力を作れるということみたいですね。

おまけ

今回は、サンプルにもあったSequentialChainを使って、レシピの栄養解説や食材代替を行ってみたいと思います。

Recipe ingredient substitution and description

以下の機能を実現しようと思います。

  • 栄養バランスの解説を行う

  • 代替食材を提案する

  • 食材代替後のレシピの栄養解説を行う

from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv()) # read local .env file
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import LLMChain
from langchain.chains import SequentialChain

1.栄養バランスの解説を行う関数

llm = ChatOpenAI(temperature=0.)
prompt1 = ChatPromptTemplate.from_template(
    "以下のレシピの栄養バランスについて解説をしてください。400文字以内。"
    "\n\n## Recipe\n"
    "{Recipe}"
)
chain1 = LLMChain(
    llm=llm, prompt=prompt1,
    output_key="nutritional_description",
    # verbose=True
)

2.食材代替を行う関数

llm = ChatOpenAI(temperature=0.)
prompt2 = ChatPromptTemplate.from_template(
    "以下のレシピの材料を一部代替することでヘルシーにしてください。"
    "\n\n## Recipe\n"
    "{Recipe}"
)
chain2 = LLMChain(
    llm=llm, prompt=prompt2,
    output_key="healthier_recipe",
    # verbose=True
)

3.食材代替後のレシピの栄養解説を行う関数

llm = ChatOpenAI(temperature=0.)
prompt3 = ChatPromptTemplate.from_template(
    "以下の[Recipe]の食材を代替し[Recipe after food substitution]にしました。"
    "食材代替後の栄養バランスについて解説をしてください。400文字以内"
    "\n\n## Recipe\n"
    "{Recipe}"
    "\n\n## Recipe after food substitution\n"
    "{healthier_recipe}"
)
chain3 = LLMChain(
    llm=llm, prompt=prompt3,
    output_key="nutritional_description_after_substitution",
    # verbose=True
)

SequentialChainを構成します。

overall_chain = SequentialChain(
    chains=[chain1, chain2, chain3],
    input_variables=["Recipe"],
    output_variables=[
        "nutritional_description",
        "healthier_recipe",
        "nutritional_description_after_substitution"
    ],
    verbose=True
)

レシピは、ChatGPTに7月の旬食材を使ったものを提案してもらいました。

recipe = """\
夏野菜のパスタ

必要な材料:

スパゲッティ - 200g
ナス - 1個
トマト - 2個
オリーブオイル - 大さじ3
ニンニク - 1片
塩 - 少々
黒コショウ - 少々
バジル - 適量
パルメザンチーズ - 適量
調理手順:

ナスは皮をむき、1cm厚さの輪切りにする。トマトは1cm厚さの輪切りにする。
フライパンにオリーブオイルを熱し、みじん切りにしたニンニクを炒める。
ニンニクが香ばしくなったら、ナスを加えて両面が焼けるまで炒め続ける。
ナスが柔らかくなったら、トマトを加えてさらに炒める。塩と黒コショウで味を調える。
一方で、スパゲッティをパッケージの指示通りに茹でる。茹で上がったらザルに上げて水気を切り、フライパンのナスとトマトに加える。
全体をよく混ぜ合わせ、最後にバジルをちぎって加える。パルメザンチーズをお好みでかけて完成です。
これは、7月の旬の食材を生かした、シンプルだけど味わい深いパスタ料理です。是非お試しください。
"""
overall_chain(recipe)
Entering new  chain...

Finished chain.

{'Recipe': '夏野菜のパスタ\n\n必要な材料:\n\nスパゲッティ - 200g\nナス - 1個\nトマト - 2個\nオリーブオイル - 大さじ3\nニンニク - 1片\n塩 - 少々\n黒コショウ - 少々\nバジル - 適量\nパルメザンチーズ - 適量\n調理手順:\n\nナスは皮をむき、1cm厚さの輪切りにする。トマトは1cm厚さの輪切りにする。\nフライパンにオリーブオイルを熱し、みじん切りにしたニンニクを炒める。\nニンニクが香ばしくなったら、ナスを加えて両面が焼けるまで炒め続ける。\nナスが柔らかくなったら、トマトを加えてさらに炒める。塩と黒コショウで味を調える。\n一方で、スパゲッティをパッケージの指示通りに茹でる。茹で上がったらザルに上げて水気を切り、フライパンのナスとトマトに加える。\n全体をよく混ぜ合わせ、最後にバジルをちぎって加える。パルメザンチーズをお好みでかけて完成です。\nこれは、7月の旬の食材を生かした、シンプルだけど味わい深いパスタ料理です。是非お試しください。\n',
 'nutritional_description': 'この夏野菜のパスタは、スパゲッティを主成分としているため、炭水化物が豊富に含まれています。また、ナスやトマトを使用しているため、ビタミンやミネラルも摂取できます。オリーブオイルを使用しているため、健康的な脂質も摂取できます。ただし、パルメザンチーズの量によっては、脂質や塩分の摂取量が増えることに注意が必要です。バジルを使用しているため、風味も豊かです。全体的には、バランスの良い栄養素を含んだ料理と言えますが、タンパク質の摂取量が少ないため、他の食材と組み合わせることで栄養バランスをより良くすることができます。',
 'healthier_recipe': '以下は、夏野菜のパスタをヘルシーにするための材料の一部代替案です。\n\n- スパゲッティ - 200g\n- ナス - 1個\n- トマト - 2個\n- オリーブオイル - 大さじ3\n- ニンニク - 1片\n- 塩 - 少々\n- 黒コショウ - 少々\n- バジル - 適量\n- パルメザンチーズ - 適量\n\nヘルシーな代替案:\n\n- スパゲッティ - 200g (全粒粉スパゲッティに代替する)\n- ナス - 1個 (ズッキーニに代替する)\n- トマト - 2個 (チェリートマトに代替する)\n- オリーブオイル - 大さじ3\n- ニンニク - 1片\n- 塩 - 少々\n- 黒コショウ - 少々\n- バジル - 適量\n- パルメザンチーズ - 適量 (ナッツチーズに代替する)\n\nこれらの代替案により、全粒粉スパゲッティを使用することで食物繊維を増やし、ズッキーニを使用することでカロリーを減らし、チェリートマトを使用することでビタミンや抗酸化物質を増やすことができます。また、ナッツチーズを使用することで動物性の脂肪やコレステロールを減らすことができます。',
 'nutritional_description_after_substitution': '食材代替後の栄養バランスは、よりヘルシーになります。全粒粉スパゲッティを使用することで食物繊維の摂取量が増え、消化を促進し血糖値の上昇を緩やかにします。ズッキーニの使用により、カロリーを減らし、食物のボリューム感を増やすことができます。チェリートマトの使用により、ビタミンや抗酸化物質の摂取量が増え、免疫力を高める効果があります。ナッツチーズの使用により、動物性の脂肪やコレステロールの摂取量を減らすことができます。これらの代替案により、よりバランスの取れた栄養摂取が可能となります。'}

レシピの栄養解説

この夏野菜のパスタは、スパゲッティを主成分としているため、炭水化物が豊富に含まれています。また、ナスやトマトを使用しているため、ビタミンやミネラルも摂取できます。オリーブオイルを使用しているため、健康的な脂質も摂取できます。ただし、パルメザンチーズの量によっては、脂質や塩分の摂取量が増えることに注意が必要です。バジルを使用しているため、風味も豊かです。全体的には、バランスの良い栄養素を含んだ料理と言えますが、タンパク質の摂取量が少ないため、他の食材と組み合わせることで栄養バランスをより良くすることができます。

食材代替

以下は、夏野菜のパスタをヘルシーにするための材料の一部代替案です。
- スパゲッティ - 200g
- ナス - 1個
- トマト - 2個
- オリーブオイル - 大さじ3
- ニンニク - 1片
- 塩 - 少々
- 黒コショウ - 少々
- バジル - 適量
- パルメザンチーズ - 適量
ヘルシーな代替案:
- スパゲッティ - 200g (全粒粉スパゲッティに代替する)
- ナス - 1個 (ズッキーニに代替する)\n- トマト - 2個 (チェリートマトに代替する)
- オリーブオイル - 大さじ3
- ニンニク - 1片
- 塩 - 少々
- 黒コショウ - 少々
- バジル - 適量
- パルメザンチーズ - 適量 (ナッツチーズに代替する)
これらの代替案により、全粒粉スパゲッティを使用することで食物繊維を増やし、ズッキーニを使用することでカロリーを減らし、チェリートマトを使用することでビタミンや抗酸化物質を増やすことができます。また、ナッツチーズを使用することで動物性の脂肪やコレステロールを減らすことができます。

食材代替後のレシピ栄養解説

食材代替後の栄養バランスは、よりヘルシーになります。全粒粉スパゲッティを使用することで食物繊維の摂取量が増え、消化を促進し血糖値の上昇を緩やかにします。ズッキーニの使用により、カロリーを減らし、食物のボリューム感を増やすことができます。チェリートマトの使用により、ビタミンや抗酸化物質の摂取量が増え、免疫力を高める効果があります。ナッツチーズの使用により、動物性の脂肪やコレステロールの摂取量を減らすことができます。これらの代替案により、よりバランスの取れた栄養摂取が可能となります。

食材代替で「ヘルシーに」と書いちゃってるので、食材代替後のレシピに栄養解説が書かれちゃってますね。関数としてはうまく機能が分離できておらず、よろしくない例でした。。

ただ、Chainを組み合わせることで、プロンプト一発で難しそうな複雑な処理もうまくできそうですね。

まとめ

DeepLearning.aiのLangChain講座の3の内容をまとめました。

Chainsは、細かい処理に分けて使いまわす、まさにLLM関数といった感じでした。これによって細かくLLMを使うことで制御しようという意図もあるでしょうか。

LangChainの名前にもある通り、このChainは中心的な機能のようです。以下には、多くの例があるので、また確認してみようと思います。

Additional | 🦜️🔗 Langchain

次回は、LangChain講座の4のQuestion and Answerです。よろしくお願いします。

参考

【DLAI×LangChain講座②】 Memory|harukary
Chains | 🦜️🔗 Langchain
LLM | 🦜️🔗 Langchain
Sequential | 🦜️🔗 Langchain
Router | 🦜️🔗 Langchain#LLMRouterChain

サンプルコード

https://github.com/harukary/llm_samples/blob/main/LangChain/LangChain_DLAI_1/L3-Chains.ipynb
https://github.com/harukary/llm_samples/blob/main/LangChain/LangChain_DLAI_1/plus_L3.ipynb

この記事が気に入ったらサポートをしてみませんか?