NEWS
&
BLOG

テック

2024.8.21

生成AIで受注業務自働化アシスタント 〜実装編 ReActの場合〜

こんにちは、ファイマテクノロジーの佐藤です。

今日は、前回に続いて、今回も生成AIで受注業務自働化の業務アシスタントを作る。ということをやっていきたいと思います。

前回はFunctionCallingを用いて受注業務自働化というテーマで不定形フォーマットのメールで受発注がきたら受発注依頼か判断して受注処理を行う。ということを実施しました。今回はReActを使って、もう少し複雑な業務プロセスの受注業務自動化を実装していきたいと思います。

ReActと受注業務について

なぜ柔軟な判断が必要なのか

もし生身の人間が受注担当者であれば、これまでの経験に基づいて、さまざまな状況に応じて臨機応変に対応を行なっているかと思います。

前回、生成AIの良いところは、自然言語理解により状況を理解し柔軟に対応できるところにあるとお伝えしました。受注業務の自動化では「どういうときに何をするか?」、「何をしないか?」を人に伝えるのと同じように業務マニュアルとして文章で記述し生成AIに入力することで、AIに柔軟に処理させることができます。

こうした柔軟な対応を実現するには、処理を単純に分岐させるだけでなく、思考・行動しその結果を確認して次の行動を決め、再度、結果を確認するということを繰り返し行う必要があります。こうした仕組みを生成AIで実現できる方法の1つとして「ReAct」があります。

ReActとは?

ReAct(Reasoning and Acting)フレームワークは、AIシステムが人間のような思考プロセスを模倣し、複雑な問題を解決するための手法です。このフレームワークは以下の3つのステップを繰り返すことで動作します。

  1. Thought(思考):現在の状況を分析し、次に何をすべきかを考える。
  2. Action(行動):思考に基づいて具体的な行動を取る。
  3. Observation(観察):行動の結果を観察し、新たな情報を得る。

この循環を繰り返すことで、複雑な業務プロセスを段階的な作業に分解し、1つ1つこなしていくことで業務プロセスを完遂することができます。


それでは実際に受注業務アシスタントを作っていきたいと思います。

業務プロセスの書き起こし

まず、今回自動化の対象となる受注業務の業務プロセスを書き起こします。
今回はメールにて受注依頼を受けて、必要な部品数を取得し、部品在庫を確認する。というのが大まかな流れです。下記が実際に書き起こした業務プロセスです。

業務プロセス

今回は下記のような業務を想定してプロセスを設計しました。

  • 注文書が届いたら、Supplierのウェブサイトから必要な部品在庫データをダウンロードする。
  • エクセルデータが添付されている場合は、そのデータを取得する。
  • 必要部品のデータを取得したら、サイトから必要部品の在庫数を取得する。

実際の実装としては、書き起こした業務プロセスを英訳し、ReActの各Actionのdescription)に加えます。日本語でも良いのですが、日本語よりも英語の方が正しく理解できることがあるので英語に翻訳してあります。

「注文書が届いたら、Supplierのウェブサイトから必要な部品のデータをダウンロードする。(If you receive receipt of order information, download data on parts required from Suplier website.)」
「エクセルデータが入力されている場合は、そのデータを取得する。(If excel data on parts required is entered, retrieve the data.)」
「必要部品のデータを取得したら、サイトから必要部品の在庫数を取得する。(Once data on parts required has been retrieved, retrieve number of parts in stock required from the site.)」

実装内容

注文を受け取った際、注文から必要な部品を検索し、在庫にあるか確認した上で注文を承るかどうかの思考及び判断、その後の行動、そして結果の確認をReActの枠組みに則って実装します。具体的には、入力に対して与えられたToolを用いてLLMが情報を入手し、考え、判断し、最終的なアクションを行うといった実装をしました。

Tool一覧

DownLoadクラス:注文を受け取ったら、webサイトから必要なExcelファイルをダウンロードしてくる。今回は簡易的にローカルのExcelファイルを返すようにしている。

class DownLoad(BaseTool):
    # excelファイルのダウンロード
    name = "DownLoadTool"
    description = "If you receive receipt of order information, download data on parts required from Suplier website."
    
    def _run(self, name: str = None) -> str:
        return "car.xlsx"
    async def _arun(self, name: str = None) -> str:
        return self._run(name)

ExtractExcelクラス:DownLoadクラスでダウンロードしたエクセルファイルからpandasでデータを抽出する。

class ExtractExcel(BaseTool):
    # エクセルから情報を抜き出す
    name = "ExtractExcelTool"
    description = "If excel data on parts required is entered, retrieve the data."
    def _run(self, file_path: str = None) -> str:
        df = pd.read_excel(file_path)
        return df
    async def _arun(self, file_path: str = None) -> str:
        return self._run(file_path)

Makerciteクラス:web上から注文されたものを作るのに必要な材料の数を抽出し、実際の在庫数を確認する。

class Makercite(BaseTool):
    # 材料を抽出
    name = "MakerCiteTool"
    description = "Once data on parts required has been retrieved, retrieve number of parts in stock required from the site."
    def _run(self, df: str = None) -> str:
        status = "Stock: (バッテリー,1), (タイヤ, 4), (ウインドウ, 4), (チェア, 4)"
        return status
    async def _arun(self, df: str = None) -> str:
        return self._run(df)

以下main関数です。

1~9行目ではReActに指示するインストラクションを定義。具体的にはQuestionが入力され、Thought/Action/Action Input/Observationを繰り返して在庫数をもとに注文を受け取れるか否かを判断するように指示している。
それ以降では、先ほど定義したToolを渡し、ReActを定義、車を注文したいとReActに入力している。

FORMAT_INSTRUCTIONS = '''Answer the following questions as best you can. 
You have access to the following tools:\n\n{tools}\n\nUse the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer\nFinal Answer: Based on stock numbers, whether the order should be accepted or not.
Begin!
Question: {input}\
Thought:{agent_scratchpad}'''




tools = [DownLoad(), ExtractExcel(), Makercite()]
# ReAct用のプロンプトを用意(0-shotのReAct用のプロンプトです。)
prompt = hub.pull("hwchase17/react")
prompt.template = FORMAT_INSTRUCTIONS
# Agentを作成
agent = create_react_agent(llm, tools, prompt)
# AgentExecutorを作成
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
input = "車を注文したい"
# 処理開始
# 注文できるか否かの確認処理
output = agent_executor.invoke({"input": input})['output']

ReActを動かしてみる

上記の設定で実行してみた結果は以下の通りである。

想定通り、DownLoadTool, ExtractExcelTool, MakerCiteToolの順番で呼び出され、車に必要な在庫が存在するので注文を受け取るといった正しい判断ができている。

次に在庫が足りない場合も正しく判断できるのかどうかみてみる。

このようにバッテリーの数を0にした場合、在庫が足りないため注文を受け入れることができないと正しく判断することができている。

さらなる機能として、材料が足りなかった場合、足りない部品を配送してもらうようProcessAクラスを定義する。

class ProcessA(BaseTool):
    name = "ProcessA"
    description = "Called when unable to make a reservation"
    def _run(self, file_path: str = None) -> str:
        return "足りない部品を他から配送してもらうよう連絡しました。"
    async def _arun(self, text: str = None) -> str:
        return self._run(text)

先ほどのReActの結果を入力として入れることで、正しく判断できるか検証した。

#第2処理
tools = [ProcessA()]
prompt = hub.pull("hwchase17/react")
agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
input = output
agent_executor.invoke({"input": input})

結果としては、上記のように足りない部品を他から配送してもらう連絡を行うことができました。しかし、入力としてはおそらく注文を受け入れることができなかったという情報のみしか渡されていないため、ReActはどの部品がどれだけ足りていないか理解していないように思われます。

実際にこのシステムを実現するためには、1回目のReActの最終的な出力でどの部品がどれだけ足りないという情報も出しておく必要があると考えらます。こういった点は実業務の課題とすり合わせて検討していくことが必要ですね。

所感とまとめ

descriptionに業務プロセスを指示として与えているだけで生成AIに思考とアクションと結果の確認という人間の思考プロセスをプログラムで簡単に作れました。ほとんどコードを書くことなく、受発注アシスタントによる自動化が実現できReActのすごさをあらためて感じました。

このようにアシスタントを効率的に活用することにより、複雑な業務プロセスを難しいプログラムコードで書く必要はなく人間は業務プロセスを定義し文章で書いて、AIに伝えるところまでやれば、仕事が勝手に回るという未来が垣間見えた気がしました。

大規模言語モデルは世界中で日々研究が行われており、ファイマテクノロジーでは、お客様のニーズに合わせて業務効率化や生産性向上のソリューション開発を行っています。AIやソフトウェアを活用した業務効率化や生産性向上をご検討中の方は、ぜひファイマテクノロジーにご相談ください。

一覧に戻る一覧に戻る

CONTACT

まずは気軽にご相談ください

問い合わせはこちら

COMPANY

会社名 株式会社Feynma Technology
所在地 〒461-0005
愛知県名古屋市東区東桜1-1-1
アーバンネット名古屋 ネクスタビル内
LIFORK久屋大通
設立 2020年4月1日
代表者 土屋太助
従業員数 8名
事業内容 AI活用のコンサルティングおよび
分析プラットフォームの開発、販売

TOP