人間のあるべき姿の探索

思索・人形・エンジニアリング

Azure OpenAI ServiceのFunction Callingでロボットを操作してみた。

デモ

人と会話しながら、左を見て!正面を見て!というと、Function Callingでトリガーしてロボットがその方向を向く関数を実行します。

youtu.be

背景

先月、Azure OpenAI ServiceでもFunction Callingがサポートされ、言語生成による応用の可能性が更に広まりました。

今まではChatGPTをはじめとした大規模言語モデルの使用方法はチャットボットや会話の要約といった自然言語をインプットとして自然言語をアウトプットする仕組みでした。しかし、Function Callingではフックしたい関数の定義を文章と同時にインプットに与えてやることで、自作の関数や外部APIを呼び出すための引数を含むJSONオブジェクトを必要なタイミングで作成できる機能です。

この機能のメリットとして、関数をトリガーするタイミングを自然言語の入力に応じてモデルが判定する為、自然言語の入力に対して特定のキーワードでトリガーといったシンプルなロジックではなく意味を考慮したオーケストレーションを手軽に作成することができます。ただ、事前に流れが決まっている処理については従来通りコードで処理を記述する方が確実ですし、手軽であること及び自然言語JSONへの変換が可能である点がメリットであると感じます。細かいプロンプトエンジニアリングについてはMicrosoft Partner Seminerで紹介されている為、是非ご参照ください。

learn.microsoft.com

www.youtube.com

実装

全体の構成は以下の通りです。ユーザーとの対話部分は音声認識→言語生成→音声合成の流れで実施され、言語生成の際にAzure OpenAI Serviceの出力が会話文の場合はそのまま音声合成にテキストを送り、Function Callingの場合はロボット操作システムで事前に定義した関数を呼び出します。

ロボット操作システムでは以下のような関数を定義しています。ここでは特定の方向に

また、引数はカテゴリ型のテキストを渡していますが、言語生成の結果によっては"斜め上"のような値を返してしまう場合もあるので、強く出力結果を制約するプロンプトを作成するか、もしくは数値での入力を受け付けてFunction Callingのパラメータで数値を返すようプロンプトエンジニアリングで調整する余地があります。

functions= [  
    {
        "name": "move_robot_neck",
        "description": "Move robot's neck for looking direction based on parameter provided",
        "parameters": {
            "type": "object",
            "properties": {
                "direction": {
                    "type": "string",
                    "description": "the direction for robot looks at \
                        (select from these example. 'front', 'right', 'left', 'up')"
                }
            },
            "required": ["direction"],
        },
    }
]  

プログラム実行例

ロボットに対して普通の会話をすると返答をしてくれますが、左を向くように指示をすると会話文ではなく呼び出す関数の名前およびパラメータが返ってくることが分かります。見ている方向によって返答が変わりますが、これは前に人間、左にトマトがあることを事前にシステムプロンプトで教示しています。この部分については、move_robot_neckの呼び出し後に連鎖してカメラ撮影および画像認識を実行して結果をユーザー入力を"you can see {recognized_object_name}. {user_input}"のように組み込むことでそれを考慮した会話ができます。ただ、トークン数の制約から現状のOpenAI Serviceの構成では長期的な文脈の考慮やあまり複雑な判断ができないのではないか、と思います。

say something : Hello, please tell me about yourself.
reply : I am an android woman created as a companion robot for interacting with humans.
say something : what can you see?
reply:I can see a human in front of me.
say something : Good! Then, look left to find something.
Function calling : move_robot_neck, {
"direction": "left"
}
say something : what can you see now?
reply : I can see a tomato.

参考までに、Azure OpenAI Serviceへのリクエストを記載します。システムプロンプトを少し書いているので、毎回ある程度のトークン数がやり取りされます。また、ステートフルAPIの為、マルチターンの会話で会話履歴を考慮したい場合はリクエストごとに履歴を含める必要がありますが、今回は履歴を含めずに対話しています。

system_input = "You are android woman.\
You were created for companion robot interact with human.\
You must not ask human what you should do.\
In front of you, you can see human.\
When you are looking front, you can see human.\
When you are looking left, you can see tomato.\
When you are looking above, you can see potato.\
"

user_input_prefix = "Please answer the following conversation in one sentence."
messages= [
    {"role": "system", "content": system_input},
    {"role": "user", "content": "you can look only {0} of you.".format(robot.now_direction)},
    {"role": "assistant", "content": "Ok, I'm looking {0}".format(robot.now_direction)},
    {"role": "user", "content": user_input_prefix + user_input}
]

response = openai.ChatCompletion.create(
    engine="gpt35",
    messages=messages,
    functions=functions,
    function_call="auto", 
)

ここ数か月、大規模言語モデルの発展が著しいことは周知の事実です。数年間機械学習関係の研究室にいた身としては、スコアの勝負や疑似タスクを用いた論文が出ており一部チャットボットが作られていたところから、具体的な応用をビジネスレベルで考え始めたところや、それがコモディティ化されつつあることが一つの転換点のように感じます。

世界的ですもんね 乗るしかない、このビッグウェーブ