このガイドでは、基本的な仕組みを説明します。 このキットには、Cline + Aiderと調整済みの設定を含むセットアップ一式がそろっており、30分で準備が整います。 ローカルコパイロットキット → # なぜツール呼び出し(tool calling)を使うのか?LLM単体では、学習後の現実世界の状況はわかりません。今日の天気も、口座の残高も、ご自身のデータベースの内容も知りません。ツール呼び出しは、この不足を補います。利用可能な関数の一覧をモデルに提示すると、モデルはどの関数をどの引数で呼び出すかを決めます。ご自身のコードがそれらの関数を実行し、結果をモデルに返すことで、モデルはその情報に基づいた回答を作成します。
理解しておくべき重要な点は、モデル自身は何も実行しないということです。モデルは「ville='Lyon' を指定して get_meteo を呼び出してください」という構造化されたリクエストを生成するだけです。関数を実行し、すべての制御を保持するのは、あなたのPythonプログラムです。この役割の分離によって、ツール呼び出しは安全で予測可能になります。
最新のデータ モデルは、学習時の記憶をもとに推測するのではなく、リアルタイムでAPIに問い合わせます。
具体的なアクション チケットの作成、メールの送信、データベースへの書き込み。LLMが処理を統括し、実際の操作はユーザーのコードが行います。
信頼性 計算や厳密な検索は決定論的なコードに任せ、モデルがハルシネーションで結果を作り出すことを避けます。
100 % ローカル Ollamaを使えば、処理の全工程が手元のマシン内で完結します。APIキーは不要で、外部へのリクエストも、トークンごとの課金もありません。 # Ollamaのツール呼び出しの仕組み✓
ローカルコパイロットキット
このガイドでモデルの導入まで、キットでエディタ内でコードを書くコパイロットの導入まで進められます。
永久に利用できるオンラインスペース PDF + ファイル 生涯アップデート 完全なサイクルは5つの段階で構成されます。これを明確に視覚化することは、最も頻繁な混乱、すなわち「1回の呼び出しで十分だ」という誤解を避けるために重要です。少なくとも2回の呼び出しが必要です。1回目はツールの要求を取得するため、2回目は最終的な回答を取得するためです。
01
質問とツールを送信します
チャットリクエストにはユーザーのメッセージと利用可能なツールのリスト(tools パラメータ)が含まれます。
02
モデルがツール呼び出しの要求を返します
テキストで回答する代わりに、関数名と引数を含む tool_calls を1つ以上返します。
03
自分のコードが関数を実行する
nameとargumentsを取得し、対応する実際のPython関数を呼び出して、結果を取得します。
04
結果を返します
結果は「tool」ロールのメッセージとして履歴に追加され、その後、chatを再度実行します。
05
モデルが最終的な回答を生成する
結果に基づき、今回はユーザー向けに自然言語で応答を生成します。
i
最低 2 回の呼び出し
完全なツール呼び出しサイクル = 最低でもモデルへの二回のパス。モデルが複数のツールを連続して実行する場合、応答に tool_calls がなくなるまでループします。
# 前提条件必要なのは三つです。起動している Ollama デーモン、実際にツール呼び出しに対応したモデル、そして公式 Python ライブラリです。二つ目には注意してください。すべてのモデルがツール呼び出しに対応しているわけではありません。この機能向けに設計された最近のモデルファミリーを選んでください。
Ollamaが最新版である ツール呼び出しのストリーミングを利用するには、0.17系以降のバージョンが必要です。デーモンはhttp://localhost:11434で待ち受けます。
ツールに対応したモデル Qwen 3.5, Granite 4.2, Mistral Small, Devstral, gpt-oss。ollama.com/library に「tools」マークがついているモデル。
十分なVRAM テストには小規模なモデル(Qwen 3.5 4B、約3.4 GB)で十分です。Granite 4.2 8B(約5.3 GB)や Qwen 3.5 9B(約6.6 GB)のほうが、複数のツールを使う指示により忠実に従います。入門用の構成には RTX 3060 12 GB が適しています。
ollamaのライブラリ pip install -U ollama。型付きのPython関数から、ツールのスキーマを直接構築できます。 環境の準備 ⧉ コピー
# Le daemon Ollama doit tourner (souvent déjà lancé en service)
ollama serve
# Un modèle qui supporte les outils
ollama pull qwen3.5:4b
# La librairie Python officielle
pip install -U ollama!
ツールサポートのないモデル
toolsパラメータを、それに対応していないモデルに渡しても、必ずしも明確なエラーが出るとは限りません。モデルがツールを無視してテキストで応答したり、応答内容にJSONらしきものを返したりすることがあります。コードを書く前に、必ずモデルの「Tools」ラベルを確認してください。
ツールは、OpenAIのスキーマに厳密に合わせたJSONスキーマで記述します。type: "function"のオブジェクトに、名前、説明、JSON Schema形式のparametersオブジェクトを含めます。説明は非常に重要です。モデルはその説明を読んで、いつ、どのようにツールを呼び出すかを判断します。具体的かつ明確に記述してください。
OpenAI形式でのツールの定義 ⧉ コピー
{
"type": "function",
"function": {
"name": "get_meteo",
"description": "Renvoie la météo actuelle pour une ville donnée",
"parameters": {
"type": "object",
"properties": {
"ville": {
"type": "string",
"description": "Nom de la ville, ex : Lyon"
},
"unite": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Unité de température souhaitée"
}
},
"required": ["ville"]
}
}
}→
スキーマの作成をライブラリに任せる
Pythonでは、このJSONを手作業で書く必要はありません。型注釈とdocstringを備えた関数を直接渡せば、ollamaライブラリがスキーマ(名前、型、説明)を自動的に導き出します。これは、JSON内のタイプミスを避ける最も確実な方法です。
# Pythonでの最初のツール呼び出しまずは最も簡単なケースから始めましょう。関数を1つ、質問を1つ用意して、モデルがどう判断するかを観察します。型アノテーションとdocstringは、モデルに送るスキーマを生成するために使われます。
最初のtool call ⧉ コピー
import ollama
def get_meteo(ville: str, unite: str = "celsius") -> str:
"""Renvoie la météo actuelle pour une ville donnée.
Args:
ville: Nom de la ville (ex : Lyon).
unite: Unité de température, celsius ou fahrenheit.
"""
# Ici, un vrai appel à une API météo. On simule le retour.
return f"21 degrés, ciel dégagé à {ville} ({unite})."
reponse = ollama.chat(
model="qwen3.5:4b",
messages=[{"role": "user", "content": "Quel temps fait-il à Lyon ?"}],
tools=[get_meteo], # la lib introspecte signature + docstring
)
# Le modèle n'a pas répondu en texte : il demande un outil
for appel in reponse.message.tool_calls or []:
print(appel.function.name) # -> get_meteo
print(appel.function.arguments) # -> {'ville': 'Lyon'}この段階では、message.contentは通常空です。モデルは呼び出し要求をmessage.tool_callsに格納して返しています。各tool_callには、function.name(文字列)とfunction.arguments(ライブラリによってすでにPythonの辞書にデシリアライズ済み)が含まれています。あとはツールを実行して結果を返すだけです。
# 完全な実行ループ以下は、ツール呼び出しを行うエージェントの再利用可能な基本構成です。各ツール名と対応する関数を辞書で結び付け、要求された呼び出しを実行し、結果を履歴に追加してから、最終回答のために2回目の呼び出しを行います。モデルが複数のツールを続けて呼び出す場合に対応できるよう、全体をループで囲みます。
エージェントループの全体 ⧉ コピー
import ollama
def get_meteo(ville: str, unite: str = "celsius") -> str:
"""Météo actuelle d'une ville."""
return f"21 degrés, ciel dégagé à {ville}."
# Registre nom -> fonction réelle
OUTILS = {"get_meteo": get_meteo}
messages = [{"role": "user", "content": "Météo à Lyon puis à Marseille ?"}]
while True:
reponse = ollama.chat(model="qwen3.5:4b", messages=messages, tools=[get_meteo])
messages.append(reponse.message) # on garde la demande dans l'historique
if not reponse.message.tool_calls:
# Plus d'outil demandé : c'est la réponse finale
print(reponse.message.content)
break
for appel in reponse.message.tool_calls:
fonction = OUTILS.get(appel.function.name)
if fonction is None:
resultat = f"Erreur : outil inconnu '{appel.function.name}'"
else:
resultat = fonction(**appel.function.arguments)
messages.append({
"role": "tool",
"tool_name": appel.function.name,
"content": str(resultat),
})!
引数を決して信用しない
引数はモデルが生成するため、不完全だったり、型が不適切だったり、許容範囲を外れていたりする可能性があります。関数を実行する前に引数を検証してください。特に、ファイルシステム、データベース、シェルコマンドを扱う関数では重要です。検証を行わないツール呼び出しは、インジェクション攻撃の入り口になります。
結果メッセージには tool ロールと、どの呼び出しへの応答なのかを示す tool_name フィールドが含まれます。content は文字列でなければなりません。オブジェクトは返す前に json.dumps でシリアライズしてください。モデルはこの内容を、外界を観察して得られた情報であるかのように読み直します。
# OpenAIと同等の使い方:openaiクライアントで同じコードを使うOllama は /v1 に OpenAI 互換のエンドポイントを提供しています。コードですでに openai クライアントを使用している場合、変更はほとんど不要です。base_url を Ollama に向け、ダミーの API キーを設定してください。ツールと tool_calls の形式は同一です。この「OpenAI との同等性」によって、移行が非常に簡単になります。
OpenAIクライアント経由でのツール呼び出し ⧉ コピー
from openai import OpenAI
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
reponse = client.chat.completions.create(
model="qwen3.5:4b",
messages=[{"role": "user", "content": "Météo à Lyon ?"}],
tools=[{
"type": "function",
"function": {
"name": "get_meteo",
"description": "Météo actuelle d'une ville",
"parameters": {
"type": "object",
"properties": {"ville": {"type": "string"}},
"required": ["ville"],
},
},
}],
)
print(reponse.choices[0].message.tool_calls)i
覚えておくべき違い
openaiクライアントでは、function.argumentsはJSON文字列として返されます(json.loadsでパースする必要があります)。一方、ollamaのネイティブライブラリでは、すでに辞書形式で返されます。クライアントを切り替える際は、この違いに注意してください。
# ツール呼び出しのストリーミング(0.17系)以前は、ストリーミングを有効にするとツール呼び出しが無効になるため、どちらかを選ぶ必要がありました。0.17シリーズ以降、Ollamaは生成の進行に合わせてツール呼び出しをストリーミングできるようになりました。具体的には、ストリームのチャンク内でtool_callsを受け取り、テキストがある場合はそれも同時に受け取ります。これにより、滑らかに応答を表示しながらツールを実行できます。
ツール呼び出しのストリーミング ⧉ コピー
import ollama
flux = ollama.chat(
model="qwen3.5:4b",
messages=[{"role": "user", "content": "Météo à Nice ?"}],
tools=[get_meteo],
stream=True,
)
for morceau in flux:
# Le texte arrive token par token
if morceau.message.content:
print(morceau.message.content, end="", flush=True)
# Les appels d'outils arrivent aussi dans le flux
for appel in morceau.message.tool_calls or []:
print("\n[outil]", appel.function.name, appel.function.arguments)→
ストリーミングのタイミング
ストリーミングは、ユーザーが回答の生成過程を見られる会話型インターフェースで特に効果を発揮します。バッチ処理やデータ抽出では、非ストリーミングモードを使ってください。そのほうが扱いやすく、回答全体を一度に取得できます。
# 構造化出力:JSON Schemaに準拠した出力を強制するツール呼び出しは操作を実行するためのもので、構造化出力は応答の形式を保証するためのものです。formatパラメータにJSON Schemaを渡すと、Ollamaがデコード時にそのスキーマを適用します。モデルにはトークンごとに制約がかかり、スキーマに適合する有効な出力だけを生成するようになります。不完全なJSONを不安定な方法でパースする必要はなくなり、仕組みそのものによって構造が保証されます。
Pythonで最も実用的な方法は、Pydanticモデルで構造を定義し、model_json_schema()でスキーマを取得することです。その後、型付きかつ検証されたオブジェクトを取得できます。
Pydantic による構造化出力の検証 ⧉ コピー
from pydantic import BaseModel
import ollama
class Facture(BaseModel):
numero: str
montant_ttc: float
devise: str
lignes: list[str]
reponse = ollama.chat(
model="qwen3.5:4b",
messages=[{
"role": "user",
"content": "Extrais numéro, montant TTC, devise et lignes de : "
"Facture F-2026-0042, total 149,90 EUR, "
"prestations : audit, rédaction.",
}],
# Le schéma est appliqué au décodage : sortie garantie conforme
format=Facture.model_json_schema(),
)
facture = Facture.model_validate_json(reponse.message.content)
print(facture.montant_ttc) # -> 149.9i
format="json" と完全なスキーマの比較
format="json"は有効なJSONの出力だけを強制し、構造までは指定しません。完全なJSON Schemaを渡すと、さらに踏み込んで、デコード時にフィールド、型、許可される値を制約できます。期待する形式が分かっている場合は、常に明示的なスキーマを使ってください。
→
最適な組み合わせ
ツール呼び出しでデータを取得し、構造化出力で整った形で返します。APIを呼び出した後に、検証済みのPydanticオブジェクトを返すエージェントは、「JSONで答えてください」とモデルに頼んで、うまくいくことを期待するだけの場合よりも、はるかに堅牢です。
# エラー処理とよくある落とし穴ツール呼び出しの失敗が目立つ形で現れることはまれです。多くの場合、モデルは気づかれないまま「脱線」します。よくある不具合と、その対処方法を紹介します。
tool_callが返されません ツールを使う必要があったのに、モデルはテキストで回答しました。ツールの説明を改善するか、モデルを変更してください。小型モデルは、ツールを呼び出すべきかどうかの判断をよく誤ります。
欠落または誤った引数 function.argumentsでは、requiredで指定されたフィールドが欠けていたり、型が誤っていたりすることがあります。実際の関数を呼び出す前にPydanticまたはtry/exceptで検証し、エラーをツールの結果としてモデルに返してください。
モデルが捏造したツール モデルが存在しない関数名を作り出します。そのため、OUTILS.get(name)を使い、処理が異常終了する代わりにエラーメッセージを返すようにしています。これにより、モデルは次のターンで自分の誤りを修正できます。
ツール呼び出しの無限ループ モデルは同じツールを無限に繰り返し要求する可能性があります。最大反復回数カウンター(例:5)を追加することで、ループを切断し、無駄な処理を回避できます。
コンテキストの切り詰め Ollamaはデフォルトでコンテキストを2048トークンに制限することがあり、長いセッションではツールの履歴が切り捨てられてしまいます。モデルのオプションでnum_ctxを増やしてください。
シリアライズされていない結果 Pythonオブジェクトをそのままcontentとして返すと、リクエストが正常に処理されなくなります。メッセージに追加する前に、必ずjson.dumpsまたはstrで文字列に変換してください。 ツールの防御的実行 ⧉ コピー
import json
def executer_outil(appel, registre, garde_fou=5):
nom = appel.function.name
fonction = registre.get(nom)
if fonction is None:
return f"Erreur : outil inconnu '{nom}'."
try:
resultat = fonction(**appel.function.arguments)
except TypeError as e:
return f"Erreur d'arguments pour {nom} : {e}"
except Exception as e:
return f"Échec de {nom} : {e}"
return json.dumps(resultat, ensure_ascii=False, default=str)キーポイントは、ツールのエラーがエージェントをクラッシュさせないことです。エラーメッセージをモデルにそのまま返すようにし、そのメッセージを結果として処理させます。良いモデルは「認識できないツール」や「欠落した引数」といった情報を読み取り、次の呼び出しを自ら調整します。
# さらに詳しくこれで、PythonでOllamaのツール呼び出しを使う方法が身につきました。ツールのJSON形式、実行ループ、OpenAIと同等の機能、ストリーミング、スキーマで制約された構造化出力を扱えます。以下のガイドでは、このテーマをさらに掘り下げます。
Ollama の REST API 「REST APIを使ってOllamaをPythonアプリケーションに統合する」—エンドポイント:11434、ストリーミング、JSONモードの基礎を解説し、このガイド全体の土台となるガイドです。
LangChain と組み合わせたエージェント 「PythonでLangChainとOllamaを使ってローカルAIエージェントを作成する」— 基本的なツール呼び出しを土台に、複数のツールとメモリを連携させる。
量子化の選び方 「量子化の選択(Q4、Q5、Q8、FP16)」— ツールを操作するモデルのVRAM使用量と品質のバランスを取るために。 ローカルコパイロットキット
すぐに使えて、初回から動作するこのセットアップ
このガイドでは基本的な仕組みを説明します。パック 「ローカル・コード・コパイロット」 すべての設定をコピペ可能な形で提供(Ollama + Cline + Aider + Tabby)、調整済みのModelfiles、トラブルシューティング章 — 30分で動作開始。ローカルの限界についても率直にお伝えします。クラウドの代わりにはなりません。
キットを見る → 一括払い · 生涯アップデート 無料の要点まとめ
メモを受け取る VRAM → 最適なコーディング用モデル → Ollamaコマンド メールで。1つの画面、コピー&ペースト、最新状態。
スパムはありません。1クリックで配信停止できます。お客様のデータは当サイト内で保管されます。
このガイドは役に立ちましたか?
ご意見、誤りのご指摘、補足はありますか?ぜひお知らせください。皆さんにとってより良いガイドにするために役立ちます。
👍 役に立った 👎 わかりにくい ✏️ エラーを報告