Langchainで踏み出すChatGPTの世界〜Langchainを使ってチャットボットを作ってみた〜

はじめに

本投稿は TECOTEC Advent Calendar 2023 の最終日(25日目)の記事です。

こんにちは。次世代デジタル基盤開発事業部の山田です。

普段は主にバックエンドエンジニアとしてシステム開発に携わっております。

本記事では私が以前から気になっていた「LangChain」を使って簡単なチャットボットを作ってみようと思います。

LangChainはLLMを活用したアプリケーション開発のフレームワークであり、簡単にLLMをアプリケーションに取り入れることができます。

本記事では以下のようなチャットボットを作成します。

LLMを使ってみたい方やLangChainを使ってWebアプリケーションを実装してみたい方の助けになればと思います。

また、LangChainはとても奥が深くこの記事では紹介できないトピックも多いので物足りないと感じる方もいらっしゃると思いますがその点ご容赦ください。

環境

  • 言語:Python "3.11.3"
  • パッケージ管理:Poetry "1.1.14"
  • バージョン管理:asdf
  • UIフレームワーク:Gradio "3.31.0"
  • LLM:GPT-3.5-Turbo
  • LLMアプリケーション開発フレームワーク:LangChain

利用するパッケージ

pydantic = "1.10.7"
python-dotenv = "1.0.0"
langchain = "0.0.172"
openai = "0.27.6"
unstructured = "0.6.6"
tabulate = "0.9.0"
pdf2image = "1.16.3"
pytesseract = "0.3.10"
chromadb = "0.3.23"
tiktoken = "0.4.0"

OpenAIのAPIキーを発行

  • アカウントを作成し、https://platform.openai.com/api-keysでAPIキーを新規作成します。
    • ※無料枠はありますが、無料枠の使用には事前に5ドル以上の支払いが必要になります。
  • OpenAIページにログインし、アカウントメニューの「API Keys」に行くとAPIキーを生成するためのボタン[+ Create new secret key]があるのでこれを押してAPIキーを生成します。
    • このキーは1回しか見られないので忘れないように他の安全な場所にメモしておいてください。

開発環境の構築

asdf と Poetry を使ってPython環境を構築します。

公式に従って asdf をインストールします。

> cd langchain-tutolial
> git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.13.1

パスを通します

> echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc

GitHubSystem dependenciesから依存関係をインストールします。

  • Mac
> brew install openssl readline sqlite3 xz zlib tcl-tk
  • WSL
> sudo apt update; sudo apt install build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev curl \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

asdfのPythonプラグインをインストールします。

> asdf plugin-add python

langchain-tutolialディレクトリ直下で以下を実行してください。

touch .tool-versions

このファイルにPython 3.11.3と記載し保存した後、以下のコマンドを実行してください。

> asdf install

> python --version
# Python 3.11.3 と表示されればOKです

Python のパッケージ管理のツールとしてPoetryを追加します。

asdf plugin-add poetry

以下のコマンドを実行し.tool-versionspoetry 1.1.14を追加してください。

> asdf plugin-add poetry

その後、以下のコマンドで Poetry をインストールしてください。

> asdf install

> poetry --version
# Poetry version 1.1.14 と表示されればOKです

プロジェクトを初期化します。

> poetry init # 対話的に色々聞かれますが全てEnterで問題ないです

pyproject.tomlというファイルが作成されます。

このファイル内のPythonのバージョンが3.11.3でない場合は変更し保存しておいてください。

Poetryで使用するPythonを指定します

> poetry config virtualenvs.in-project true --local
> which python
# /Users/taishiyamada/.asdf/shims/python
> poetry env use /Users/taishiyamada/.asdf/shims/python # use のあとはみなさんの環境によって異なります

> poetry run python --version
# Python 3.11.3

GradioでチャットボットのWebアプリケーションを実装する

Gradioをインストールします。

poetry add gradio@3.31.0

langchain-tutolialディレクトリ直下にsrcディレクトリを作成しその中にapp.pyを作成します。

Gradioの公式ページからコードをapp.pyにコピペし保存します。

import gradio as gr

def greet(name):
    return "Hello " + name + "!"

demo = gr.Interface(fn=greet, inputs="text", outputs="text")
demo.launch() 

ターミナルで以下のコマンドを実行し出力されたURLにブラウザからアクセスします。

poetry run python src/app.py

ブラウザからアクセスすると以下のような画面が表示され、画面左側の項目に名前を入力すると画面右側に結果が表示されます。

LLMの実装

LLMを使うための準備をしていきます。

環境変数を読み込むパッケージをインストールします。

poetry add python-dotenv@1.0.0

その後、langchain-tutolialディレクトリ直下に.envファイルを作成し以下を追加してください。

OPENAI_API_KEY=取得したOpenAIのAPIキー

LLMで使うパッケージをターミナルでインストールします。

poetry add langchain@0.0.172 openai@0.27.6

そして、srcディレクトリ直下にllm_engine.pyファイルを用意し今回使うLLMの処理を定義します。

from langchain.chat_models import ChatOpenAI
import langchain

langchain.verbose = True

def llm(message: str) -> str:
    chat = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
    return chat.predict(message)

上で定義したLLMの処理をapp.pyで使うために以下のように書きます。

import gradio as gr
from dotenv import load_dotenv
from llm_engine import llm

def respond(message, chat_history):
    bot_message = llm(message)
    chat_history.append((message, bot_message))
    return "", chat_history


with gr.Blocks() as demo:
    chatbot = gr.Chatbot()
    msg = gr.Textbox()
    clear = gr.Button("Clear")

    msg.submit(respond, [msg, chatbot], [msg, chatbot])
    clear.click(lambda: None, None, chatbot, queue=False)

if __name__ == "__main__":
    load_dotenv()
    demo.launch()

bot_message = llm(message)でLLM処理を呼び出しています。 それ以外のコードについてはGradioの公式から引用してますので下記のクイックスタートをご参照ください。

www.gradio.app

ファイルを保存し、再度サーバーを立ち上げます。 ブラウザをリロードし入力するとチャットボットとして機能していることがわかると思います。

最後に、履歴を踏まえた対話の実装を行いたいと思います。

app.pyChatMessageHistoryをインポートし以下のように実装します。

import gradio as gr
from dotenv import load_dotenv
from llm_engine import llm
from langchain.memory import ChatMessageHistory


def respond(message, chat_history):
    history = ChatMessageHistory()
    for [user_message, ai_message] in chat_history:
        history.add_user_message(user_message)
        history.add_ai_message(ai_message)

    bot_message = llm(message, history)
    chat_history.append((message, bot_message))
    return "", chat_history


with gr.Blocks() as demo:
    chatbot = gr.Chatbot()
    msg = gr.Textbox()
    clear = gr.Button("Clear")

    msg.submit(respond, [msg, chatbot], [msg, chatbot])
    clear.click(lambda: None, None, chatbot, queue=False)

if __name__ == "__main__":
    load_dotenv()
    demo.launch()

また、LLM側で履歴を受け取るように修正します。

from langchain.chat_models import ChatOpenAI
import langchain
from langchain.memory import ChatMessageHistory
from langchain.schema import HumanMessage

langchain.verbose = True

def llm(message: str, history: ChatMessageHistory) -> str:
    chat = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

    messages = history.messages
    messages.append(HumanMessage(content=message))
    return chat(messages).content

稼働中のサーバーを止めて再度立ち上げて確認します。

すると、以下のようにチャットの履歴を踏まえて対話できていることがわかります。

おわりに

以上が、LangChainを使った簡単なチャットボットアプリの紹介です。

これくらいであれば、LangChainを使わなくても実装できるのでは?と思った方もいらっしゃると思いますが、本記事では紹介できなかったLangChainの高度な機能を知るとその有用性がわかると思います。

それらの機能について機会があれば紹介したいと思います。 LangChainを使用することで、ChatGPTをより柔軟かつ効果的に組み込むことができ様々なアプリケーションに展開する可能性が広がるので今後の動きに期待したいですね!

最後まで見ていただきありがとうございます。 皆様のおかげで充実した一年となり、これからも共に歩んでいけることに感謝しています。

良いお年をお迎えください。メリークリスマス!

テコテックの採用活動について

テコテックでは新卒採用、中途採用共に積極的に募集をしています。
採用サイトにて会社の雰囲気や福利厚生、募集内容をご確認いただけます。
ご興味を持っていただけましたら是非ご覧ください。 tecotec.co.jp