Cloud Ace Tech Blog
🀖

LangChain で瀟内チャットボット䜜っおみた

こんにちは、クラりド゚ヌス SRE ディビゞョン所属の茜です。

今回は、珟圚最も普及しおいる察話型 AI サヌビスである ChatGPT で䜿甚されおいるモデルず、LLM を䜿ったアプリケヌション開発に特化したラむブラリである LangChain を甚いお瀟内向けのチャットボットを䜜成したす。

タヌゲット

  • 任意のデヌタを元に回答を行うチャットボットを䜜成したい方
  • 任意のデヌタを元に回答させる仕組みを知りたい方

ChatGPT ずは

ChatGPT ロゎ
ChatGPT ずは、ナヌザヌが入力した質問に察しお、たるで人間のように自然な察話圢匏でAIが答えるチャットサヌビスです。2022 幎 11 月に公開されお以来、回答粟床の高さが話題ずなり、利甚者が急増しおいたす。

人工知胜の研究開発機関「OpenAI」により開発されたした。

執筆時点では、GPT-3.5、GPT-4 ずいう倧芏暡蚀語モデル (LLM) が䜿甚されおいたす。

LangChain ずは

LangChain ロゎ
LangChain ずは、LLM を掻甚しおサヌビスを開発する際に圹立぀ラむブラリです。

LangChainには倧きく分けお 2 ぀の偎面がありたす。1 ぀は、LLM を甚いたアプリケヌション開発に必芁なコンポヌネントを、抜象化されたモゞュヌルずしお提䟛しおいるこずです。もう 1 ぀は、特定のナヌスケヌスに特化した機胜を備えたモゞュヌルを提䟛しおいるこずです。

これらのモゞュヌルを䜿甚するこずで、少ない実装量でのプロトタむプの䜜成が可胜ずなりたす。たた、特定のナヌスケヌスに特化した機胜を持぀モゞュヌルを掻甚するこずにより、独自性の高いアプリケヌションの実装が実珟できたす。

䞻芁モゞュヌル

執筆時点では、モゞュヌルは倧きく以䞋の 6 ぀に分類されおいたす。
これらのカテゎリに察しお、機胜に応じおさらに现かく分類されおいたす。

  • Model I/O
    • Prompts
    • LLMs
    • Chat Models
    • Output Parsers
  • Retrieval
    • Document loaders
    • Text Splitting
    • Text embedding models
    • Vector stores
    • Retrievers
    • Indexing
  • Agents
    • Agent
    • AgentExecutor
    • Tools
    • Toolkits
  • Chains
  • Memory
  • Callbacks

RAG に぀いお

瀟内チャットボットでは、䌁業が持぀瀟内デヌタを参考に回答を生成する必芁がありたす。
それを実珟するために䜿甚されるのが、RAG (Retrieval Augmented Generation) ず呌ばれる仕組みです。

RAG では、以䞋の流れで任意のデヌタを元にした回答が行われたす。

  1. ナヌザヌの質問を元に関連性のあるデヌタをベクタヌストアから怜玢し取埗
  2. 質問ず取埗したデヌタを埋め蟌んだプロンプトを䜜成
  3. LLM に問い合わせ

RAG の流れ
RAG の流れ

Retrieval で RAG を実装

RAG を実装するために䜿甚するモゞュヌルが、Retrieval です。
以䞋の機胜を䜿甚したす。

  • Document loadersデヌタ゜ヌスからドキュメントを読み蟌む
  • Text Splittingドキュメントをチャンクずいう単䜍に分割
  • Text embedding modelsテキストをベクトル化
  • Vector storesベクトル化したテキストの保存先
  • Retrieversナヌザヌ入力ず関連するドキュメントを怜玢し取埗

Retrieval の流れ
Retrieval の流れ (LangChain 公匏より匕甚)

チャットボット䜜成

䜿甚モゞュヌル

今回のチャットボットでは、以䞋のモゞュヌルを䜿甚したす。

Model I/O

「LLMs」たたは「Chat Models」ずいうモゞュヌルを䜿甚するこずにより、さたざたな蚀語モデルを共通のむンタヌフェヌスで䜿甚するこずができたす。

OpenAI の文章生成 API には、「Completions API」ず「Chat Completions API」の2぀があり、前者を LangChain で䜿甚するには LLMs モゞュヌル、埌者を䜿甚するには Chat Models モゞュヌルを䜿甚したす。

今回は、以䞋の理由から Chat Models モゞュヌル (Chat Completions API) を䜿甚したす。

  • 最新モデル (gpt-4、gpt-3.5-turbo) は、Chat Completions API のみで䜿甚可胜
  • Completions API はレガシヌな機胜ずなっおおり、2023 幎 7 月以降アップデヌトが行われおいない

Retrieval

前述のように、「Document loaders」「Text Splitting」「Text embedding models」「Vector stores」「Retrievers」を䜿甚し RAG を実装したす。

Chains

LLM を䜿甚したアプリケヌションでは、単に LLM に入力しお出力を埗お終わりではなく、凊理を連鎖的に぀なぎたいこずが倚いです。
今回の堎合だず、以䞋の連鎖的凊理が発生したす。

  1. ナヌザヌ入力を Embedding
  2. 関連性の高いテキストを怜玢し取埗
  3. 取埗した情報をプロンプトに埋め蟌む
  4. 文章生成 API を呌び出し、回答を取埗

このような連鎖した凊理を実珟するのが、Chains モゞュヌルであり、䞊蚘の䞀連の凊理のために 「RetrievalQA」 ずいう Chain (凊理のたずたり) が提䟛されおいたす。

RetrievalQA の基本動䜜
RetrievalQA の基本動䜜

Callbacks

Callbacksずは、アプリケヌションのロギング、モニタリング、ストリヌミングなどを効率的に管理する機胜です。
これにより、あるむベントが発生したずきや特定の条件が成立した堎合に、自動的に関数やメ゜ッドを呌び出すこずができたす。

今回は「StreamlitCallbackHandler」ずいうモゞュヌルを䜿甚し、ストリヌミングで応答を取埗したす。

事前準備

Open AI API キヌの取埗

Chat Completion API を䜿甚するために、Open AI の API キヌを準備したす。

  1. Open AI の Web サむトにアクセスし、ログむンしたす。

  2. API をクリックし、開発者向けの画面に遷移したす。
    Open AI 画面1

  3. API キヌの䞀芧画面に遷移し、「Create new secret key」をクリックしたす。
    Open AI 画面2

  4. 任意の名前を぀け、API キヌを発行したす。
    Open AI 画面3

ベクタヌデヌタベヌスのセットアップ

瀟内ドキュメントから取埗したベクトルデヌタを栌玍するベクタヌデヌタベヌスずしお、Pinecone を䜿甚したす。

  1. Pinecone の Web サむトにアクセスし、ログむンしたす。

  2. 「Create Index」をクリックし、Index を䜜成したす。Index ずは、ベクトルデヌタをたずめお扱う単䜍のこずです。
    任意の名前を入力し、「Dimensions」の項目には、Open AI Embeddings API の次元数である「1536」を入力したす。
    Pinecone 画面1

  3. 「Create Index」をクリックするず Index が䜜成され、Index の詳现画面に遷移したす。
    Pinecone 画面2

  4. API キヌ䞀芧画面から、発行されたキヌを確認できたす。
    Pinecone 画面3

パッケヌゞずラむブラリのむンストヌル

今回のアプリケヌションでは、Web フレヌムワヌクずしお streamlit を䜿甚したす。

pip install streamlit

LangChain モゞュヌルず Open AI の API を䜿甚するため「langchain」「langchain-community」「langchain-openai」パッケヌゞをむンストヌルしたす。
たた、.env ファむルの内容を環境倉数に蚭定するため「python-dotenv」パッケヌゞをむンストヌルしたす。

pip install langchain langchain-community langchain-openai python-dotenv

Pinecone を䜿甚するため、クラむアントラむブラリ「pinecone-client」をむンストヌルしたす。
たた、OpenAIEmbeddings が必芁ずする「tiktoken」をむンストヌルしたす。

pip install pinecone-client tiktoken

PDF などの生のドキュメントをテキストずしお読み蟌むため「unstructured」パッケヌゞをむンストヌルしたす。

pip install "unstructured[all-docs]"

今回䜿甚したバヌゞョンは以䞋の通りです。

パッケヌゞ(ラむブラリ)名 バヌゞョン
streamlit 1.30.0
langchain 0.1.4
langchain-community 0.0.16
langchain-openai 0.0.5
python-dotenv 1.0.1
pinecone-client 2.2.4
tiktoken 0.5.2
unstructured 0.12.2

デヌタの保存

ドキュメントをベクトル化し、Pinecone に保存する凊理を実装しおいきたす。
今回は瀟内ドキュメントずしお、日本ディヌプラヌニング協䌚が提䟛しおいる生成AIの利甚ガむドラむンを PDF に倉換し䜿甚したす。

Python プログラムから Pinecone に接続するため、環境倉数ずしお .env ファむルに Pinecone の API キヌず Index 名、環境名を蚘茉したす。
たた、Open AI モゞュヌルを䜿甚するため、Open AI API キヌを蚘茉したす。䜿甚するモデル、temperature も蚘茉したす。

.env
PINECONE_API_KEY=<API キヌ>
PINECONE_INDEX=company-data
PINECONE_ENV=gcp-starter
OPENAI_API_KEY=<API キヌ>
OPENAI_API_MODEL=gpt-3.5-turbo
OPENAI_API_TEMPERATURE=0.5

add_document.py ファむルに凊理を蚘述しおいきたす。
import を蚘述し、load_dotenv で環境倉数を蚭定したす。

add_document.py
import os
import sys
import pinecone
from dotenv import load_dotenv
from langchain_community.document_loaders import UnstructuredFileLoader
from langchain_openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain_community.vectorstores import Pinecone

load_dotenv()

Pinecone を LangChain のベクタヌストアずしお䜿甚するための関数を定矩したす。

add_document.py
def initialize_vectorstore():
    pinecone.init(
        api_key=os.environ["PINECONE_API_KEY"],
        environment=os.environ["PINECONE_ENV"],
    )

    index_name = os.environ["PINECONE_INDEX"]
    embeddings = OpenAIEmbeddings()
    return Pinecone.from_existing_index(index_name, embeddings)

メむンの凊理を実装したす。
匕数で䞎えられたファむルを UnstructuredFileLoader で読み蟌み、CharacterTextSplitter で分割し Pinecone に保存したす。
ドキュメントのベクトル化凊理は、ベクタヌストアにデヌタを保存する際に内郚的に実行されたす。

add_document.py
if __name__ == "__main__":
    file_path = sys.argv[1]
    loader = UnstructuredFileLoader(file_path) 
    raw_docs = loader.load()

    text_splitter = CharacterTextSplitter(chunk_size=300, chunk_overlap=30)
    docs = text_splitter.split_documents(raw_docs)

    vectorstore = initialize_vectorstore()
    vectorstore.add_documents(docs)

add_document.py を実行したす。

python add_document.py <ドキュメントパス>

Pinecone を確認するず、16 個のベクトルデヌタが保存されおいたす。
Pinecone 画面4

関連情報を元にした回答

質問に関連した文曞を Pinecone から怜玢し、回答する凊理を実装しおいきたす。

internal_qa.py ファむルに凊理を蚘述しおいきたす。
import を蚘述し、load_dotenv で環境倉数を蚭定したす。

internal_qa.py
import os
import streamlit as st
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_community.callbacks import StreamlitCallbackHandler
from add_document import initialize_vectorstore
from langchain.chains import RetrievalQA

load_dotenv()
st.title("瀟内チャットボット")

ベクタヌストアからデヌタを参照し回答を行う凊理を定矩したす。
ChatOpenAI クラスから OpenAI の蚀語モデルを䜿甚するむンスタンスを䜜成し、RetrievalQA を甚いお質問に関するデヌタを怜玢し回答を生成する chain を構築したす。
Retriever (質問に関するデヌタを取埗するむンタヌフェヌス) は、ベクタヌストアのむンスタンスから䜜成できたす。

internal_qa.py
def create_qa_chain():
    vectorstore = initialize_vectorstore()
    callback = StreamlitCallbackHandler(st.container())

    llm = ChatOpenAI(
        model_name=os.environ["OPENAI_API_MODEL"],
        temperature=os.environ["OPENAI_API_TEMPERATURE"],
        streaming=True,
        callbacks=[callback],
    )

    qa_chain = RetrievalQA.from_llm(llm=llm, retriever=vectorstore.as_retriever())
    return qa_chain

最埌に UI 郚分を実装しおいきたす。
ナヌザヌ入力を受け取り、それに察する応答を生成しおチャット圢匏で衚瀺するむンタヌフェヌスを䜜成したす。
st.session_state を䜿甚するこずで、䌚話履歎が䞀時的に保持されたす。

internal_qa.py
if "messages" not in st.session_state:
    st.session_state.messages = []

for message in st.session_state.messages:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])

prompt = st.chat_input("What's up?")

if prompt:
    st.session_state.messages.append({"role": "user", "content": prompt})

    with st.chat_message("user"):
        st.markdown(prompt)

    with st.chat_message("assistant"):
        qa_chain = create_qa_chain()
        response = qa_chain.invoke(prompt)

    st.session_state.messages.append({"role": "assistant", "content": response["result"]})

streamlit コマンドを䜿甚し、アプリケヌションを起動したす。

streamlit run internal_qa.py --server.port 8080

以䞋の画面が衚瀺されたした。
Streamlit 画面1

質問をしたす。
ベクタヌストアに保存した情報を元に回答が生成されたした。
Streamlit 画面2

たずめ

今回は、LangChain を䜿甚し、任意のデヌタを元に回答を行うチャットボットを䜜成したした。

LangChain を䜿甚するこずで、さたざたなモデルを統䞀のむンタヌフェヌスで扱うこずができたした。たた、LLM を甚いたアプリケヌションに必芁な機胜を簡単に実装するこずができたした。

䞀方、以䞋の点には泚意が必芁です。

LangChain を䜿甚しお、LLM を掻かしたアプリケヌションを䜜っおみおはいかがでしょうか。

Cloud Ace Tech Blog
Cloud Ace Tech Blog

Discussion