こんにちは、とらのあなラボのはっとりです。
本日は、OpenAI APIをより手軽かつ効率的に操作するためのライブラリ、LangChainをご紹介します。
※ このブログの内容は、OpenAI APIを活用して最適化し、より読みやすい形に修正しています。
OpenAI APIはその高度な応答能力で多様な用途に対応していますが、特定の要求に応じて個々の応答をカスタマイズするにはどうしたらよいでしょうか?
ここで役立つのがLangChainです。このライブラリを使用することで、OpenAI APIの応答を容易にカスタマイズできます。
以下のシナリオを考えてみましょう。
- 質問内容に基づいて特定の処理を行い、その結果をOpenAI APIに反映させたい。
- 社内ルールに従った応答をOpenAI APIに行わせたい。
これらのシナリオを実現するためのコード例を以下に示します。
環境設定
使用する環境は以下の通りです。
- OS: Debian GNU/Linux 12 (bookworm)
- Python: 3.11.4
- パッケージ管理にはpipenvを使用します。
セットアップ方法は以下の通りです。
pipenv install langchain openai faiss-cpu tiktoken pipenv shell
OpenAI APIの実装
まずは、OpenAI APIの基本的な実装方法を見てみましょう。事前に環境変数 OPENAI_API_KEY
にOpenAI APIのAPIトークン、 OPENAI_ORGANIZATION
にOrganization IDを設定しておく必要があります。
from langchain.chat_models import ChatOpenAI chat_model = ChatOpenAI(model_name="gpt-3.5-turbo-16k", temperature=0) result = chat_model.predict("とらのあなについて3行で!") print(result) # とらのあなは、日本の大手同人誌販売店であり、アニメやマンガ関連商品も取り扱っています。 # オンラインショップや実店舗があり、多くのファンに支持されています。 # 豊富な品揃えと高品質なサービスが特徴です。
このように、非常にシンプルに書くことができます。
※ 環境変数が使えない場合は直接指定することも可能ですが、ソースコードに直接書き込むとソース管理が難しくなるため、検証用以外では注意が必要です。
chat_model = ChatOpenAI( openai_api_key="xxxxxxxxxx", openai_organization="org-xxxxxxxxxx", model_name="gpt-3.5-turbo-16k", temperature=0 )
独自処理の組み込み
掃除当番を決定する処理を作成します。
from langchain.agents import initialize_agent, AgentType, Tool from langchain.chat_models import ChatOpenAI from datetime import datetime from zoneinfo import ZoneInfo chat_model = ChatOpenAI(model_name="gpt-3.5-turbo-16k", temperature=0) timezone = ZoneInfo("Asia/Tokyo") today = datetime.now(timezone) base_date = datetime(2023, 1, 1, 0, 0, 0, tzinfo=timezone) members = [ "Aさん", "Bさん", "Cさん", "Dさん", "Eさん", "Fさん", ] def CleaningDuty(target: str): d = datetime.fromisoformat(target) index = (d - base_date).days % len(members) return members[index] tools = [ Tool( name = "CleaningDuty", func = CleaningDuty, # OpenAI APIは現在の日付を取れないので、今日の日付を渡す必要がある。 description = f"日付渡すとその日の掃除当番の名前を返します。日付はISO8601形式でタイムゾーン・時間まで渡してください。今日の日付は{today.isoformat()}です。", ), ] agent = initialize_agent(tools, chat_model, agent=AgentType.OPENAI_FUNCTIONS) print("Input:") text = input() # text = "明日の掃除当番は誰?" result = agent.run(text) print(result) # Output: # 明日の掃除当番はAさんです。
このように、質問が投げられると、必要に応じてCleaningDuty関数に日付が渡され、関数が担当者を返すとそれに基づいて返答されます。開発者は関数の処理とdescriptionの内容に集中できます。
独自データの組み込み
社内ルールに基づいた応答をOpenAI APIに行わせたい場合を考えます。
社内ルールのQ&Aをまとめたドキュメントは以下のようになります。
Q: 有給休暇の申請はどのようにすればよいですか。 A: 勤怠システムから事前有給休暇申請を行ってください。 http://example.com/attend --- Q: 突発的な体調不良での欠勤に有給休暇を利用したいです。どのようにすれば良いですか。 A: 出勤時の朝会で上長にその旨を伝え、勤怠システムから事後有給休暇申請を行ってください。 http://example.com/attend?a=1
コードは以下のようになります。
from langchain.chat_models import ChatOpenAI from langchain.chains import ConversationalRetrievalChain from langchain.document_loaders import TextLoader from langchain.embeddings.openai import OpenAIEmbeddings from langchain.text_splitter import CharacterTextSplitter from langchain.vectorstores import FAISS chat_model = ChatOpenAI(model_name="gpt-3.5-turbo-16k", temperature=0) loader = TextLoader("qa.txt", encoding='utf-8') doc = loader.load() text_splitter = CharacterTextSplitter( separator = "---", chunk_size = 1000, chunk_overlap = 0, ) documents = text_splitter.split_documents(doc) embeddings = OpenAIEmbeddings() vectorstore = FAISS.from_documents(documents, embeddings) chain = ConversationalRetrievalChain.from_llm( llm = chat_model, retriever = vectorstore.as_retriever(search_kwargs={"k": 1}), ) print("Input:") text = input() # text = "有給をとりたい。申請方法教えて。" result = chain({ "question": text, "chat_history": [] }) print(result['answer']) # Output: # 勤怠システムから事前有給休暇申請を行ってください。申請方法の詳細は以下のリンクを参照してください。 # http://example.com/attend
これを実行すると、ドキュメントの内容に基づいた返答が得られます。開発者はドキュメントの内容を充実させることに集中できます。
まとめ
LangChainを使用することで、OpenAI APIのカスタマイズが容易になることをご理解いただけたと思います。LangChainは多くの利用例があり、今後のさらなる発展が期待できます。
Fantia開発採用情報
虎の穴ラボでは現在、一緒にFantiaを開発していく仲間を積極募集中です!
多くのユーザーに使っていただけるtoCサービスの開発をやってみたい方は、ぜひ弊社の採用情報をご覧ください。
yumenosora.co.jp