よりスマートなLLMアプリケーションを構築するための関数呼び出しの活用

大規模言語モデル(LLM)は、もはやテキストを生成することに限定されるものではない。この分野における重要な進歩は関数呼び出しであり、LLMは外部ツール、データベース、APIと相互作用して動的な操作を実行できる。これにより、LLMはテキスト生成にとどまらず、実世界のデータやサービスを扱うことができる。
先日Zillizが主催したBerlin Unstructured Data Meetupで、GoogleのカスタマーエンジニアであるNikolai Danylchykが、最新のLLMであるGeminiがどのように関数呼び出しを使って機能を拡張しているかについて議論した。このブログでは、彼の洞察をまとめ、この強力な機能を活用して高度なLLMアプリケーションを構築する方法を紹介する。より詳しく知りたい方は、YouTubeでニコライの講演のリプレイを見ることをお勧めする。
LLMにおける高度な関数呼び出しの理解LLMは大きく進化しましたが、その真価が発揮されるのは、関数呼び出しを通じて外部システムと相互作用するときです。関数呼び出しを統合することで、LLMは他のシステムとシームレスに接続し、より正確で最新の動的なレスポンスを提供することができます。それでは、Gemini**を例として、関数呼び出しがどのように機能するかを説明しよう。
図1-関数呼び出しのステップと実行時に使用されるコンポーネント](https://assets.zilliz.com/Figure_1_Steps_of_function_calling_and_components_used_at_runtime_14aed523a7.png)
図1:関数呼び出しのステップと実行時に使用されるコンポーネント。
この時点で、開発者はすでにツール内で1つ以上の関数宣言を定義しており、利用可能な関数とその実行方法をGeminiに通知している。ユーザー入力を受け取ると、Gemini APIはその内容とプロンプトを分析し、「関数呼び出し」レスポンスを返す。このレスポンスには、呼び出される関数名や関連するパラメータなどの構造化されたデータが含まれる。
アプリケーションは、Geminiのレスポンスから関数名とパラメータを使用して、外部のサービスにAPIリクエストを行います。開発者は、Pythonの
requests
ライブラリのようなツールを使用して、REST APIやその他のニーズに合ったクライアントライブラリを呼び出す。外部システムがレスポンスを返した後、アプリケーションはそのデータをGeminiに送り返す。追加データが必要な場合、Geminiは別の関数コールを発行し、必要に応じてサイクルを継続することができる。
この高度な機能の重要性を理解するために、関数呼び出し機能を持たない従来のLLMを考えてみよう。LLMの応答は、LLMがトレーニングしたデータに基づいて生成される。しかし、ファンクションコールを使えば、LLMはデータベースからリアルタイムの情報を取り込んだり、顧客関係管理(CRM)システムのレコードを更新したり、さらにはチケットの予約や注文などのアクションをトリガーするコマンドを発行することができる。このアプローチは、モデルの使い勝手を、単にレスポンスを生成することから、タスクを実行することへと拡張します。
技術用語では、LLMの関数呼び出しは、モデルと外部のAPIやサービスとの間の構造化された相互作用を伴います。モデルは、関数呼び出しが必要とされる適切なシナリオを特定し、呼び出しのためのパラメータを定式化し、それを実行します。
例えば、ユーザーが "What's the weather in Berlin? "と質問した場合、ファンクションコールは天気APIをトリガーし、応答を生成するためにリアルタイムのデータを取得する。この場合、LLMはユーザーと外部システムの間のインテリジェントな仲介役として機能し、より正確で有用なインタラクションを編成する。
さて、ここまで関数呼び出しの基本的な概念について説明してきましたが、次にGeminiを使って実際のAPIとやりとりする実用的な実装を見てみましょう。
例為替レート取得のための関数呼び出しの使用
Gemini関数呼び出しを使って為替レートAPIを利用する方法を見てみましょう:
必要なライブラリのインストールとプロジェクト変数の設定。
Google CloudのVertex AIプラットフォームとやり取りするために必要なgoogle-cloud-aiplatform
ライブラリのアップグレードとインストールから始めよう。次に、プロジェクトIDと場所を変数として指定する。
!pip3 install --upgrade --user --quiet google-cloud-aiplatform
PROJECT_ID = "[あなたのプロジェクトID]" # @param {type: "string"}を指定します。
LOCATION = "us-central1" # @param {type: "string"}.
これらは、Google Cloudのどのプロジェクトで、どの地域で作業しているかを識別するためのプレースホルダです。
必要なモジュールのインポートと生成モデルの定義
次に、Vertex AIから生成モデルを定義して動作させるために必要なモジュールをインポートする。requests`ライブラリは後で外部APIからデータを取得するために使用する。
インポートリクエスト
from vertexai.generative_models import (
コンテンツ
関数宣言、
GenerativeModel、
パート
ツール、
)
model = GenerativeModel("gemini-1.5-pro-001")
最後の行は生成モデル(この場合は gemini-1.5-pro-001
)を初期化します。後で、このモデルを使用して、入力プロンプトに基づいて応答を生成します。
為替レート関数の定義とツールの作成
次に、2 つの通貨間の為替レートを取得するために必要なパラメータを記述する関数を作成し、それをツールにまとめます。
get_exchange_rate_func = FunctionDeclaration(
name="get_exchange_rate"、
description="国間の通貨の為替レートを取得する"、
parameters={
"type":"オブジェクト"、
「プロパティ":{
"currency_date":{
"type":"string": "文字列"、
"description":"常に YYYY-MM-DD 形式でなければならない日付、または期間が指定されていない場合は値 'latest'""
},
"currency_from":{
"type":"string": "文字列"、
"description":「ISO 4217 形式で変換する通貨。
},
"currency_to":{
"type":「文字列
"description":「ISO 4217 形式で変換する通貨。
}
},
"required":[
"currency_from"、
"currency_date"、
]
},
)
exchange_rate_tool = Tool(
function_declarations=[get_exchange_rate_func]、
)
パラメータには currency_date
(YYYY-MM-DD
形式またはキーワード latest
), currency_from
(変換元の通貨の ISO 4217 コード), currency_to
(変換先の通貨の ISO 4217 コード) を指定する。requiredセクションでは
currency_fromと
currency_dateが必須であることを指定している。次に、
get_exchange_rate関数宣言をラップする
exchange_rate_tool` という名前のツールを定義する。後ほど、このツールをモデルに渡して為替レートの取得を処理する。
モデルによるレスポンスの生成とレスポンスからのパラメータの抽出
モデルにプロンプトを渡してレスポンスを呼び出してみましょう。モデルが、パラメータを含む関数呼び出しを含むレスポンスを出力することを期待します。
prompt = """オーストラリアドルからスウェーデンクローナへの為替レートはいくらですか?
500オーストラリアドルはスウェーデンクローナでいくらですか?"""
response = model.generate_content(
プロンプト
tools=[exchange_rate_tool]、
)
response.candidates[0].コンテンツ
params = {}とする。
for key, value in response.candidates[0].content.parts[0].function_call.args.items():
params[key[9:]] = value
パラメータ
上記のコードでは、オーストラリアドルとスウェーデンクローナの為替レートを尋ねるプロンプトを定義しています。そして、exchange_rate_tool
とともにプロンプトを渡して、generate_content
を使用してモデルを呼び出します。モデルは応答を生成しようとします。
その後、レスポンスが解析される。params辞書には、
function_call.args` のキーと値を繰り返し入力し、キーの最初の 9 文字を削除して、期待されるパラメータ名と一致させる。
API から為替レートを取得してユーザーにレスポンスを返す
それでは、前のレスポンスから抽出したパラメーターを使用してFrankfurter API(無料の外国為替レートAPI)にリクエストし、ユーザーへのレスポンスを生成してみよう。
インポートリクエスト
url = f "https://api.frankfurter.app/{params['date']}"
api_response = requests.get(url, params=params)
api_response.text
response = model.generate_content(
[
コンテンツ(role="user", parts=[)
Part.from_text(プロンプト + """為替レートや日付など、詳細とコンテキストを含めて、ステップで答えを入力してください。
為替レートと日付を含むコンテキストをステップで入力してください、)
]),
コンテンツ(role="関数", parts=[
Part.from_dict({
"function_call":{
"name":"get_exchange_rate"、
}
})
]),
コンテンツ(role="function", parts=[
パート.from_function_response(
name="get_exchange_rate"、
response={
"content": api_response.text、
}
)
]),
],
tools=[exchange_rate_tool]、
)
response.candidates[0].content.parts[0].text
上記のコードでは、為替レートAPIからレスポンスを得たら、再びgenerate_content
メソッドを呼び出し、今度は複数のコンテンツを渡す。ユーザーからのもの(詳細なステップとコンテキストを要求する)、get_exchange_rate
への関数呼び出し、Frankfurter APIからのレスポンスである。この組み合わせにより、モデルはより詳細なステップ・バイ・ステップのレスポンスを返すようになる。最後に、モデルが生成したコンテンツのテキスト部分を表示する。これがユーザーに返すレスポンスである。
これがユーザーに返すレスポンスです:
図2- オーストラリアドルからスウェーデンクローナへの為替レートを示すプログラムの出力](https://assets.zilliz.com/Figure_2_Output_of_a_program_showing_the_exchange_rate_from_Australian_dollars_to_Swedish_Krona_3511172ea4.png)
図2: オーストラリアドルからスウェーデンクローナへの為替レートを表示するプログラムの出力
この応答は、関数呼び出しが機能し、Frankfurter APIによってリストされた現在の為替レートを示していることを示しています。
ここまで、Geminiの高度な機能である関数呼び出しと、その他多くのLLMについて説明してきた。関数呼び出しだけでも通貨検索のような複雑なタスクを実行することができますが、RAG(Retrieval Augmented Generation)のような他の強力なテクニックと組み合わせることで、その真の可能性が発揮されます。
関数呼び出しと検索拡張生成(RAG)の組み合わせによるインタラクティブ性の向上
検索拡張生成(RAG)は、自然言語処理(NLP)における最も重要なトレンドのひとつとなっている。RAGシステムは、LLMの生成能力と、MilvusやZilliz Cloud(管理型Milvus)のようなベクトルデータベースによる検索システムの効率性を組み合わせたものである。具体的には、RAGシステムでは、ベクトルデータベースがLLMのコンテキスト情報を取得し、LLMが取得した情報をもとに、より正確な応答を生成する。関数呼び出しは、LLMと外部のデータベースやシステムとの間でよりダイナミックな相互作用を可能にすることで、このプロセスを強化します。関数呼び出しを追加することで、LLMは関連データを取得するだけでなく、それをリアルタイムで処理し、相互作用させることで、その機能を拡張することができる。
例えば、RAGとファンクション・コールの両方を使用するカスタマー・サポート・アプリケーションでは、LLMはよりリッチでパーソナライズされたインタラクションを提供します。ユーザーが "最近の注文はどこですか?"と尋ねると、システムはまずRAGを使用してMilvusベクトルデータベースから注文処理に関する一般的な情報を取得し、コンテキストを提供する。例えば、検索された情報は、"注文は通常、配達に3-5営業日かかる"である。同時に、関数を呼び出すことにより、顧客のアカウントを照会してリアルタイムデータにアクセスする。最終的なレスポンスは「**ご注文番号12345は9月10日に出荷され、9月15日に到着予定です。
このようにRAGとファンクション・コールを統合することで、適切で有益なレスポンスを生成するだけでなく、ライブ・データやサービスと積極的に関わり、インタラクティブな次元をもたらすダイナミックなシステムが構築される。この組み合わせにより、LLMsを搭載したインテリジェント・エージェントは、複雑な実世界でのインタラクションが可能になる。
- LLMの関数呼び出し機能を活用してRAGシステムを強化する方法については、このチュートリアルのステップバイステップガイドを参照してください。
RAGと関数呼び出しの組み合わせの使用例
これらの実際の相互作用のいくつかを見てみよう。
ヘルスケア:カルテ検索と予約スケジューリング
ヘルスケアでは、RAGと関数呼び出しの組み合わせにより、LLMは患者と医療提供者の両方に対して、高度にパーソナライズされたデータ駆動型のサポートを提供することができる。医師がシステムに患者の履歴データを求めると、システムはMilvusのようなベクトルデータベースからRAGを使って関連する医療記録を検索する。同時に、LLMは関数呼び出しを通じて外部の病院システムと対話し、フォローアップの予約を取ったり、リアルタイムの診断データを取得したりすることができる。
例:医師が「患者Xの最新の検査結果はどうですか、来週のフォローアップの予約は可能ですか」と尋ねると、システムはまずMilvusに照会して患者の履歴から関連文書を検索し、傾向や状態に関する洞察を提供する。次に、関数呼び出しを使って病院のスケジューリングAPIにアクセスし、患者の予約を取る。
ファイナンス:パーソナライズされた投資インサイトとリアルタイム取引
金融分野では、RAGはMilvusのようなベクトルデータベースに格納された関連市場情報や過去の金融データを取得するために採用されています。これを関数呼び出しと組み合わせることで、LLMは、株の売買、資金移動、ライブデータに基づくカスタム・ポートフォリオの推奨生成などのリアルタイム・アクションを実行することもできます。
**このシステムはまず RAG を使って Milvus からユーザーのポートフォリオ履歴を取得し、過去のパフォー マンスの概要を提供する。次に、関数呼び出しを使って取引APIと対話し、株の購入を実行し、ユーザーに取引を確認する。
Eコマース:商品推薦とリアルタイム注文追跡
Eコマースにおいて、RAGはMilvusから商品情報、レビュー、顧客履歴を取得し、ショッピング体験をパーソナライズするのに役立ちます。機能呼び出しと組み合わせることで、システムはライブ在庫システムと対話し、在庫状況を提供し、リアルタイムで注文を追跡し、さらには支払いを処理することができます。
**LLMはMilvusから顧客の過去の購入情報を取得し、類似製品を推奨します。その後、関数呼び出しを使って注文追跡APIに問い合わせ、現在の注文の配送状況をリアルタイムで更新します。
旅行:旅程の提案と予約管理
旅行とホスピタリティにおいて、RAGはMilvusのようなベクトルデータベースに保存されている目的地、ホテル、旅行日程の詳細を取得することができます。機能呼び出しと組み合わせることで、システムは予約を管理したり、パーソナライズされた旅程を提案したり、フライトや予約に関するリアルタイムの最新情報を提供したりすることができます。
例:ある旅行者が、**イタリアでの5日間の旅程を提案し、より早い日にホテルの予約を変更することはできますか?その後、関数呼び出しを使ってホテルの予約システムとやりとりし、予約を変更し、ユーザーに変更を確認します。
関数呼び出しがRAGのようなシステムをどのように向上させるかを見るにつけ、このような技術を実世界のアプリケーションに展開する際の実際的な課題と利点を認識することが重要である。
実際の使用例における関数呼び出しの課題と利点
関数呼び出しの可能性は計り知れませんが、それなりの課題も伴います。主な懸念事項の一つは、セキュリティとプライバシーの確保です。LLMがファンクション・コールを発行する場合、ユーザー・アカウントや財務情報などの機密データへのアクセスが必要になることがあります。これらのトランザクションが安全で、データプライバシー規制に準拠していることを保証することは非常に重要です。
さらに、1つのワークフローで複数のファンクション・コールを管理する複雑さは、待ち時間の問題につながる可能性があります。例えば、LLMが異なるシステムに複数の関数コールを発行している場合、応答時間が長くなり、ユーザー・エクスペリエンスに影響を与える可能性があります。これは、スピードが重要なリアルタイム・アプリケーションでは特に重要です。
ヘルスケア、金融、顧客サービスなどの業界では、関数呼び出しはルーチン・タスクを自動化することで、業務を合理化することができます。例えば、ヘルスケアの場合、LLMはファンクション・コールを通じて患者の記録を引き出したり、予約を入れたり、リマインダーを送ったりすることができます。
現実的な利点や課題だけでなく、特にデータ・セキュリティやシステムの信頼性に関わる倫理的・技術的な考慮も見逃せない。
倫理的・技術的考察
技術的な観点からは、開発者として、潜在的な落とし穴を避けるために、関数呼び出しの実装方法を注意深く管理する必要がある。**LLMがサードパーティのサービスに対して常に関数コールを発行している場合、シ ステムの信頼性はそれらのサービスの稼働時間と性能に依存することになります。適切なエラー処理とフォールバック・メカニズムが、外部サービスが利用できないときでもシステムが円滑に機能し続けることを保証するために用意されていなければなりません。
**LLMがユーザーの代わりに意思決定をしたり、行動を起こしたりする場合、ユーザーがシステムが何をしているのかを十分に認識することが不可欠です。例えば、金融サービスにおいて、LLMが取引を実行したり、資金を送金したりする場合、利用者は実行されるアクションについて知らされるべきであり、必要であれば介入する能力を持つべきである。このようなシステムの信頼を維持するためには、明確な文書化とユーザー同意の仕組みが不可欠である。
**関数呼び出しが個人データや機密データにアクセスする場合、ユーザーのプライバシーを保護するために厳重な対策が講じられなければならない。開発者は、データが責任を持って取り扱われ、関数呼び出しがGDPRやHIPAAなどのプライバシー規制に準拠していることを確認する必要があります。
結論
Nikolai氏は、関数呼び出しがいかに大規模な言語モデルに重要な機能拡張を提供し、外部システムやデータと相互作用することで実世界のタスクを実行できるようにするかに光を当てる素晴らしい仕事をした。為替レートの検索であろうと、RAG(Retrieval-Augmented Generation:検索拡張生成)による複雑なインタラクションのパワーアップであろうと、関数呼び出しはLLMが達成できることの地平を広げてくれる。
続きを読む
Mistral Large、Nemo、Llamaエージェントによるマルチエージェントシステムの最適化 ](https://zilliz.com/blog/optimize-multi-agent-system-with-mistral-large-mistral-nemo-and-llama-agents)
RAGにはまだVectorDBが必要か? OpenAIの検索機能を比較する ](https://zilliz.com/blog/customizing-openai-built-in-retrieval-using-milvus-vector-database)
MemGPTの紹介とMilvusとの統合 ](https://zilliz.com/blog/introduction-to-memgpt-and-milvus-integration)
Ollama、Llama3、Milvusでの関数呼び出しの使い方 ](https://zilliz.com/blog/function-calling-ollama-llama-3-milvus)
ベクターデータベースとは何か、どのように機能するか ](https://zilliz.com/learn/what-is-vector-database)
あなたのGenAIアプリのためのトップパフォーマンスAIモデル|Zilliz](https://zilliz.com/ai-models)
ジェネレーティブAIリソースハブ|Zilliz](https://zilliz.com/learn/generative-ai)
読み続けて

Introducing Zilliz MCP Server: Natural Language Access to Your Vector Database
The Zilliz MCP Server enables developers to manage vector databases using natural language, simplifying database operations and AI workflows.

Beyond PGVector: When Your Vector Database Needs a Formula 1 Upgrade
This blog explores why Postgres, with its vector search add-on, pgvector, works well for smaller projects and simpler use cases but reaches its limits for large-scale vector search.

Leveraging Milvus and Friendli Serverless Endpoints for Advanced RAG and Multi-Modal Queries
This tutorial has demonstrated how to leverage Milvus and Friendli Serverless Endpoints to implement advanced RAG and multi-modal queries.