はじめに
langchainはええよ~って話も聞くけど「いや、openai api素直に使ったらええやないですか」っていう心の声もあり
どっちがいいのかを比べてみた
先に結論
- OpenAI APIでできることは当然LangChainでもできる
- LangChainがなくても同じようなプログラミングはできるけど、OpenAI APIだとわざわざ作りこまないといけないところをLangChainは先まわって作ってくれるのでストレスが少ない
- 今回は比較のために初歩的なところの比較しかできないけどLangChainには様々な便利クラスがある
- ちょろいAIプログラミングならOpenAI APIでもいいけど、しっかりとしたものを作るならLangChainを使ったほうがいいなって思いました
Chat Completions API vs Chat models
Chat Completions(OpenAI API)
import openai
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello! I'm John."}
]
)
print(response)
出力結果はエスケープされたUnicodeエンコードとなっているので変換されていた。
変換結果は
はい、先ほどジョンさんと名乗られましたので、お名前が分かりました。
私は会話の中でお客様の情報を記憶することができます。どのようにお手伝いできますか?
と書いてました。
参考:https://tech-unlimited.com/escape-unicode.html
Chat models(LangChain)
from langchain.chat_models import ChatOpenAI
from langchain.schema import AIMessage, HumanMessage, SystemMessage
chat = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
messages = [
SystemMessage(content="You are a helpful assistant."),
HumanMessage(content="こんにちは!私はジョンと言います!"),
AIMessage(content="こんにちは、ジョンさん!どのようにお手伝いできますか?"),
HumanMessage(content= "私の名前が分かりますか?")
]
result = chat(messages)
print(result.content)
出力結果。
回答内容にほぼ差はないけど、何より「Unicodeエンコード」されてるのをちゃんと変換した状態で出してくれるのがイイ…!
ストリーミング
OpenAI API
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello! I'm John."}
],
stream=True
)
for chunk in response:
choice = chunk["choices"][0]
if choice["finish_reason"] is None:
print(choice["delta"]["content"])
LangChain
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage
chat = ChatOpenAI(
model_name="gpt-3.5-turbo",
temperature=0,
streaming=True,
callbacks=[StreamingStdOutCallbackHandler()],
)
messages = [HumanMessage(content="自己紹介してください")]
result = chat(messages)
リアルタイム出力するところは一緒だけど勝手に改行しないのでそこは結構嬉しかったりする
PromptTemplate
OpenAI API
def generate_recipe(dish_name):
prompt_template = f"""
以下の料理のレシピを考えてください。
料理名: {dish_name}
"""
openai.api_key = api_key # APIキーを設定
response = openai.Completion.create(
engine="text-davinci-002", # 使用するエンジンを選択
prompt=prompt_template,
max_tokens=100, # 応答の最大トークン数
)
return response.choices[0].text
dish_name = "カレー"
recipe = generate_recipe(dish_name)
print(recipe)
作り方次第でテンプレート作れる。ちょっと作りこみが大変かなって。
LangChain
from langchain.prompts import PromptTemplate
template = """
以下の料理のレシピを考えてください。
料理名: {dish}
"""
prompt = PromptTemplate(
input_variables=["dish"],
template=template,
)
result = prompt.format(dish="カレー")
print(chat.predict(result))
出力結果。
やたらとしっかりした文章になってるのは気になるけど問題はそこじゃなくて…
PromptTemplateってクラスを独自で作ってるおかげですごい直感的で作りやすくなってる
LangChainにはほかのTemplateクラスある
ChatPromptTemplateクラスだと、SystemMessageとHumanMessageのそれぞれにテンプレートパターンを作れる。
LangChainを勉強してると自然とAIプログラミングができる気分になってきたー
from langchain.prompts import (
ChatPromptTemplate,
PromptTemplate,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.schema import HumanMessage, SystemMessage
chat_prompt = ChatPromptTemplate.from_messages([
SystemMessagePromptTemplate.from_template("あなたは{country}料理のプロフェッショナルです。"),
HumanMessagePromptTemplate.from_template("以下の料理のレシピを考えてください。\n\n料理名: {dish}")
])
messages = chat_prompt.format_prompt(country="イギリス", dish="肉じゃが").to_messages()
print(messages)
from langchain.chat_models import ChatOpenAI
chat = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
result = chat(messages)
print(result.content)