1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[翻訳] LangChain Expression Languageを使い始める

Posted at

Get started | 🦜️🔗 Langchainの翻訳です。

本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。

LCELによって、基本的なコンポーネントによる複雑なチェーンを容易に構築することができ、ストリーミング、並列処理、ロギングのような機能をすぐに活用できます。

基本的な例: プロンプト + モデル + 出力パーサー

最も基本的で一般的なユースケースは、プロンプトテンプレートとモデルのチェーンを構成するというものです。これがどのように動作するのかを見るために、トピックを受け取りジョークを生成するチェーンを作成しましょう:

%pip install --upgrade --quiet  langchain-core langchain-community langchain-openai
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

prompt = ChatPromptTemplate.from_template("tell me a short joke about {topic}")
model = ChatOpenAI(model="gpt-4")
output_parser = StrOutputParser()

chain = prompt | model | output_parser

chain.invoke({"topic": "ice cream"})
"Why don't ice creams ever get invited to parties?\n\nBecause they always drip when things heat up!"

LCELを用いて異なるコンポーネントを単一のチェーンにまとめ上げているこのコードの以下の行に注意してください:

chain = prompt | model | output_parser

シンボル|は、さまざまなコンポーネントの出力を次のコンポーネントの入力として流し込むチェーンであるunixのパイプ演算子と似ています。

このチェーンでは、ユーザーの入力はプロンプトテンプレートに引き渡され、プロンプトテンプレートの出力はモデルに引き渡され、モデルの出力は出力パーサーに引き渡されます。何が起きているのかをきちんと理解するためにそれぞれのコンポーネントを個別に見ていきましょう。

1. プロンプト

promptBasePromptTemplateであり、テンプレート変数のディクショナリーを受け取り、PromptValueを生成することを意味します。PromptValueは、(入力として文字列を受け取る)LLMや(入力としてメッセージのシーケンスを受け取る)ChatModelに引き渡されるコンプリートされたプロンプトに対するラッパーです。BaseMessagesや文字列を生成する両方のロジックを定義しているので、いずれの言語モデルでも動作します。

prompt_value = prompt.invoke({"topic": "ice cream"})
prompt_value
ChatPromptValue(messages=[HumanMessage(content='tell me a short joke about ice cream')])
prompt_value.to_messages()
[HumanMessage(content='tell me a short joke about ice cream')]
prompt_value.to_string()
'Human: tell me a short joke about ice cream'

2. モデル

PromptValuemodelに引き渡されます。この場合、modelChatModelであり、出力はBaseMessageであることを意味します。

message = model.invoke(prompt_value)
message
AIMessage(content="Why don't ice creams ever get invited to parties?\n\nBecause they always bring a melt down!")

modelLLMの場合、出力は文字列となります。

from langchain_openai.llms import OpenAI

llm = OpenAI(model="gpt-3.5-turbo-instruct")
llm.invoke(prompt_value)
'\n\nRobot: Why did the ice cream truck break down? Because it had a meltdown!'

3. 出力パーサー

そして、最後にmodelの出力はBaseOutputParserであるoutput_parserに引き渡され、入力として文字列やBaseMessageを受け取ることを意味します。特にStrOutputParserはシンプルにいかなる入力を文字列に変換します。

output_parser.invoke(message)
"Why did the ice cream go to therapy? \n\nBecause it had too many toppings and couldn't find its cone-fidence!"

4. 全体のパイプライン

以下のステップを踏みます:

  1. {"topic": "ice cream"}のように欲しいトピックに関するユーザー入力を引き渡します。
  2. プロンプトを構成するためにtopicを用いてPromptValueを構築するために、promptコンポーネントがユーザー入力を受け取ります。
  3. 生成されたプロンプトをmodelコンポーネントを受け取り、評価のためにOpenAIのLLMモデルに引き渡します。モデルから生成された出力はChatMessageオブジェクトとなります。
  4. 最後に、output_parserコンポーネントがChatMessageを受け取り、呼び出されたメソッドから返却されるPython文字列に変換します。

Screenshot 2024-03-19 at 14.58.00.png

任意のコンポーネントの出力に興味があるのであれば、中間結果を確認するためにpronptprompt | modelのように小さいチェーンをいつでもテストすることができます:

input = {"topic": "ice cream"}

prompt.invoke(input)
# > ChatPromptValue(messages=[HumanMessage(content='tell me a short joke about ice cream')])

(prompt | model).invoke(input)
# > AIMessage(content="Why did the ice cream go to therapy?\nBecause it had too many toppings and couldn't cone-trol itself!")

RAG検索の例

次の例として、質問に反応する際にいくつかのコンテキストを追加するために、retrieval-augmented generationのチェーンを実行したいものとします。

# Requires:
# pip install langchain docarray tiktoken

from langchain_community.vectorstores import DocArrayInMemorySearch
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_openai.chat_models import ChatOpenAI
from langchain_openai.embeddings import OpenAIEmbeddings

vectorstore = DocArrayInMemorySearch.from_texts(
    ["harrison worked at kensho", "bears like to eat honey"],
    embedding=OpenAIEmbeddings(),
)
retriever = vectorstore.as_retriever()

template = """Answer the question based only on the following context:
{context}

Question: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()
output_parser = StrOutputParser()

setup_and_retrieval = RunnableParallel(
    {"context": retriever, "question": RunnablePassthrough()}
)
chain = setup_and_retrieval | prompt | model | output_parser

chain.invoke("where did harrison work?")

この場合、コンポーネントのチェーンは以下のようになります:

chain = setup_and_retrieval | prompt | model | output_parser

これを説明すると、最初に上のプロンプトテンプレートが、プロンプトで置き換えられる値としてcontextquestionを受け取ることがわかります。プロンプトテンプレートを構築する前に、検索に適した文書を取得し、コンテキストの一部としてそれらを含める必要があります。

準備段階として、クエリーに基づいて文書を取得できるメモリストアを用いたリトリーバーをセットアップしています。これは、実行可能なコンポーネントであり、他のコンポーネントとチェーンすることができますが、これらを個別に実行することもできます:

retriever.invoke("where did harrison work?")

そして、文書検索のリトリーバとユーザーの質問を引き渡すためのRunnablePassthroughを用いて取得した文書のエントリーとオリジナルのユーザーの質問を用いて、期待される入力をプロンプトにまとめるためにRunnableParallelを使用します:

setup_and_retrieval = RunnableParallel(
    {"context": retriever, "question": RunnablePassthrough()}
)

完全なチェーンを確認します:

setup_and_retrieval = RunnableParallel(
    {"context": retriever, "question": RunnablePassthrough()}
)
chain = setup_and_retrieval | prompt | model | output_parser

フローは以下の通りとなります:

  1. 最初のステップでは2つのエントリーを持つRunnableParallelオブジェクトを作成します。最初のエントリーcontextには、リトリーバーによって取得された結果文書が含まれます。2つ目のエントリーquestionには、ユーザーのオリジナルの質問が含まれます。質問を引き渡すために、このエントリーをコピーするためにRunnablePassthroughを使っています。
  2. 上のステップのディクショナリーをpromptコンポーネントに入力します。そして、プロンプトを構成し、PromptValueを出力するために、ユーザー入力であるquestionと取得した文書であるcontextを受け取ります。
  3. modelコンポーネントは生成されたプロンプトを受け取り、評価のためにOpenAIのLLMモデルに入力します。モデルから生成された出力はChatMessageオブジェクトとなります。
  4. 最後に、output_parserコンポーネントがChatMessageを受け取り、呼び出しメソッドの戻り値となるPython文字列に変換します。

Screenshot 2024-03-19 at 15.12.32.png

次のステップ

LCELがある場合とない場合とで、一般的な機能を作成するために必要アコードの隣り合わせの比較をするために、次のセクションWhy use LCELを読むことをお勧めします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?