関数呼び出しと構造化されたJSON出力による Ollama
Function calling(関数呼び出し)により、LLMがコード内の関数を呼び出すことを自ら決定できます。例えば、天気検索、データベースへのクエリ、メール送信などです。引数は適切な形式で返されます。Ollama のfunction callingは2つの要素で構成されています。1つは有効なJSONを保証するためのformatパラメータ、もう1つは利用可能な関数を宣言するためのAPIのtoolsフィールドです。このガイドでは、Pythonでの両方の実装方法、実際に信頼できるローカルモデル、そしてスキーマ検証とリトライによる堅牢化の方法を示します。
#ローカルでfunction callingを使う理由
LLMが生成するのはテキストであり、アクションではありません。function callingはこの隔たりを埋めます。モデルは通常の文章で回答する代わりに、「都市をParisとしてget_meteo関数を呼び出す」という指示を示す構造化オブジェクトを返します。ユーザー側のコードがその関数を実行して実際の結果を取得し、その結果をモデルに渡すと、モデルが最終的な回答を作成します。これは、外部の世界とやり取りするエージェントやアシスタントの基本的な仕組みです。
ローカル環境では課題は二重です。まず、出力が100%パース可能なJSONであることを保証することです。「JSONはこちら:」と追加する饒舌なモデルは、パイプライン全体を壊します。次に、モデルが正しい関数と正しい引数を選択することを確認することです。これは小型モデルでは困難になります。OllamaはAPIを通じて両方を処理しますが、知っておくべきガードレールがあります。
- JSON出力が保証されています
- formatパラメータはデコードを制約します。モデルは構文的に正しいJSONしか出力できず、特定のスキーマに準拠させることもできます。
- 関数呼び出し
- toolsフィールドはOpenAI形式の関数を宣言しています。モデルは引数を含むtool_callsを返します。
- 100 % ローカル
- すべてがお使いのマシン上で、http://localhost:11434のOllamaデーモンを通じて動作します。APIキーは不要で、データの漏洩もありません。
#前提条件と対応モデル
このガイドでモデルの導入まで、キットでエディタ内でコードを書くコパイロットの導入まで進められます。
- 永久に利用できるオンラインスペース
- PDF + ファイル
- 生涯アップデート
JSON モード(format パラメータ)は、どのモデルでも機能します。一方、tools を使う関数呼び出しには、ツール使用のために訓練されたモデルが必要です。そうでなければ、tool_calls フィールドは空のままになります。すべてのモデルが同等というわけではありません。仕様上は「対応」とされる3Bモデルでも引数をよく間違えますが、14B以上のモデルなら単純なスキーマには十分対応できます。
- Ollama インストール済み
- デーモンが起動しており、http://localhost:11434 に接続できる状態。ollama listで確認してください。
- Python SDK
- pip install ollama pydantic — le client officiel plus Pydantic pour la validation.
- 信頼できるツール使用モデル
- qwen3.5:9b、mistral-small (24B)、gpt-oss:20b は、2026 年にまず試すモデルとして優れた選択肢です。Q4 で必要な VRAM は、Qwen 3.5 9B が約 6.6 GB、24B モデルが約 14 GB です。
- 推奨GPU
- RTX 3060 12GBならQwen 3.5 9Bを快適に動かせます。ツール呼び出しの信頼性をしっかり確保するには、20~24Bモデル(RTX 4070/4080 16 GB)を目指してください。
#formatパラメータで正しい形式のJSONを強制する
最も簡単なケースは、モデルに常にJSONで応答させ、自由形式のテキストでは一切応答させない場合です。chat呼び出しに format: 'json' を指定してください。するとOllamaは、構文的に有効なオブジェクトを生成するよう、トークンごとにデコードを制約します。重要なのは、期待するフィールドを明示した指示をプロンプトに残しておくことです。そうしないと、モデルが構造を勝手に作ってしまいます。
#JSONスキーマに基づく構造化出力(structured outputs)
2024年末以降、Ollamaではformatに文字列'json'だけでなく、完全なJSONスキーマも指定できます。この場合、デコードにはスキーマを守る制約がかかり、型、必須フィールド、列挙値が遵守されます。モデルが構造上、スキーマに適合しないオブジェクトを生成できなくなるため、'json'だけを指定するよりもはるかに堅牢です。Pydanticを使えば、スキーマを自動生成できます。
ここではデコード時の出力形式がPersonneの構造に固定され、model_validate_jsonがPython側で再度検証を行います。二重のチェックにより、出力が解析可能で、かつ宣言された型に適合することが保証されます。これは、ローカルの本番環境で行うあらゆるデータ抽出に推奨されるパターンです。
#Python での tools API の手順解説
本格的なfunction callingに移りましょう。関数はOpenAI形式(name、description、JSON Schemaのparameters)でtoolsフィールドに宣言します。モデルはこれらの定義を読み、関数呼び出しが有用だと判断した場合、テキストメッセージの代わりに1つ以上のtool_callsを返します。関数を実行して結果を返すのはあなたです。
- 01関数を説明する各関数には、明確なname、正確なdescription(モデルはこれを使って関数を選びます)、そして引数とそのうちどれがrequiredなのかを列挙したJSON Schema形式のparametersを指定してください。
- 02toolsを指定して呼び出しを送信するollama.chat に tools のリストを渡してください。モデルは独自に判断して、関数を呼び出すか直接回答するかを決定します。
- 03tool_callsの内容を確認するresp['message'].get('tool_calls') を確認してください。tool_callsが存在する場合、モデルは渡された引数で関数を呼び出そうとしています。
- 04実行して結果を返す実際のPython関数を呼び出し、その結果をroleが'tool'のメッセージとしてモデルに返し、最終的な回答を作成させてください。
#呼び出し → 実行 → 応答のループ
Function callingは往復のやり取りです。最初の呼び出し: モデルはtool_callを返します。関数を実行します。2回目の呼び出し: 結果を返送し、モデルが自然言語で回答を作成します。以下は、複数の関数に再利用可能な完全なループです。
#スキーマ検証とリトライのパターン
ローカル環境では、小規模なモデルが時折失敗することがあります。引数の欠落、型の誤り、存在しない関数の指定などです。未検証の出力を決してそのまま信頼しないでください。各 tool_call にPydanticによる検証を適用し、検証に失敗した場合はエラーメッセージをコンテキストに含めて再試行してください。多くの場合、モデルは2回目の試行で自己修正します。
- 実行前に検証する
- 関数ごとにPydanticモデルを用意すると、引数の不足や型の誤りを、引数がコードに渡される前に検出できます。
- フィードバック付きリトライ
- エラーメッセージをコンテキストに再投入することで、モデルが修正へ向かいます。2〜3回の試行でほぼ常に解決します。
- 関数の許可リスト
- dispatchに含まれない関数名はすべて拒否してください。これはセキュリティ対策であると同時に、ハルシネーションを防ぐためのガードレールでもあります。
- 適切なフォールバック処理
- N 回の失敗後は、ユーザーに明確なメッセージを返すようにし、特に小型モデルではクラッシュしないようにしてください。
#ツール使用における小型モデルの罠
ツールの使用には高度な判断能力が必要です。モデルは意図を理解し、適切な関数を選び、引数を対応付け、指定された形式を守らなければなりません。7B未満では結果が不安定です。以下では、ローカル環境で特によく起きる問題と、その対処法を紹介します。
- tool_calls は空です
- モデルが関数を呼び出さず、テキストで応答します。多くの場合、モデルがツール使用向けに学習されていないか、関数の説明が曖昧すぎることが原因です。Qwen 3.5またはMistral Smallに切り替え、関数の説明を丁寧に整えてください。
- 誤った引数
- モデルが存在しないフィールドを作り出したり、必要なフィールドを省いたりします。スキーマでそれらを required に指定し、一度に公開する関数の数を減らして、必ず検証してください。
- 存在しない関数の呼び出し
- モデルが存在しない関数を呼び出します。呼び出しを振り分ける側では、許可リストが必須です。
- 余計なテキストが混ざったJSON
- 形式を指定しないと、小型モデルはJSONの前後にテキストを追加します。抽出結果だけを出力させるには、常にformat='json'またはスキーマを使用してください。
- 機能が多すぎる
- ツールが 5〜6 個を超えると、小規模モデルは混乱します。サブタスクごとに分割するか、2 ステップのルーティングを行ってください。
#さらに詳しく
関数呼び出しは、エージェントや高度な連携の基盤となる機能です。本ガイドの内容をさらに掘り下げる、本サイトの関連ガイドはこちらです:
- PythonでREST APIを介してOllamaを統合
- ポート:11434のOpenAI互換エンドポイント、ストリーミング、JSONモードを、実際のFastAPI/Flaskアプリで使う。
- LangChainとOllamaを使ってローカルAIエージェントを作成する
- 単体の関数呼び出しから、ツール、メモリ、推論を順次組み合わせる本格的なエージェントへ移行する。
- MCPとローカルLLM:OllamaにMCPサーバーを接続する
- 各関数を手作業で定義する代わりに、Model Context Protocolを通じてツール(ファイル、ウェブ、データベース)へのアクセスを標準化する。
ご意見、誤りのご指摘、補足はありますか?ぜひお知らせください。皆さんにとってより良いガイドにするために役立ちます。