計算と言語の融合 — セマンティック計算機
Posted by Malkoc Ognjen, AI Researcher of Gaudiy Inc.
このBehavior tree agentシリーズの第1回では、ビヘイビアツリーが大規模言語モデル(LLM)の予測困難な世界に「構造」をもたらし、複雑で創発的な動作を可能にする方法を見てきました。
今回は、その基盤を活用した実用的なもの−−日常言語を理解する計算機を構築します。この出発点から、ビヘイビアツリーに固有の優先順位付けを活用して、自然言語を解釈し、意味のある計算を導く方法を探ります。
核心となる考え方はシンプルです。プログラミング言語で明示的な命令をすることで解決できるタスクの場合、LLMのセマンティック解釈に頼るのではなく、プログラミング言語での命令を優先することで、より正確で信頼性が高い結果を保証します。これは特に、精度が重要な「数学」において顕著です。
分かりやすい例として、LLMにおける算術演算が挙げられます。この能力は、モデルが大規模化するにつれて現れた創発的特性でした。最近の研究では、そのメカニズムの特定に焦点が当てられています。例えば、加算や乗算などの演算をサポートする個別の活性化回路が存在するようです。
これは同時に限界も示しています。LLMは基本的な算術は扱えますが、より複雑で、一般的でない、あるいは分布外の演算へとその能力を拡張することは、ますます学習が困難になる可能性があります。
さらに、説得力のある「推論」の痕跡を含む出力に報酬を与えることでLLMを調整する強化学習は、状況を改善しないようです。基本的な演算を担う活性化回路は変わらないままか、少なくとも推論出力とは切り離されているようです。加えて、最近の研究²³⁴⁵は、推論の利点が普遍的ではないことをさらに示唆しています。特に参考文献5は、性能向上が、特定の事前学習と結びついていることを示しています。これは、モデルが十分に大規模でないか、事前学習中に類似のタスクに触れていない場合、推論だけに頼ることは効果的でない可能性があることを示唆しています。
そこで今回、その代替手段を探索します。LLMに、シンボリック式を導出したり、よく知られているが面倒な積分を計算したり、やりたくないストレスを抱えた博士課程の学生の役割を担わせたりしてみましょう。すでに利用できる集合知、つまりこの目的のために特別に構築されたツールを活用してみます。特に、Pythonプログラミング言語には複数の利点があります。それらは、シンプルな構文、科学ライブラリの広大なエコシステム、そして幸運なことに、オンラインで利用可能なPythonコードの量が増え続けている — 事前学習フェーズに直接供給される豊富な素材です。
この背景を踏まえ、計画を立てます。ビヘイビアツリーを使用して、先に紹介した核心原則を実施します。ルールは明確です。まず、タスクがプログラム的に解決できる場合はその方法で解決し、それ以外のすべてについては、LLMがタスク解決のフォールバックとして介入します。ここでは数学と物理学に焦点を当てます。可能な場合は、数値計算をPythonに任せ、適切に選ばれた関数が信頼できる結果を提供します。
高レベルのアイデアは、セマンティック計算機と呼べるものです。モデル自体が確実に計算できないタスクに対して、LLMはユーザーとコンピュータ間の「翻訳者」として機能します。
Pythonに作業を引き渡し、LLMによる翻訳を再開することは、ビヘイビアツリーに組み込まれた優先順位付けを活用できます。
この設定により、クエリをインテリジェントにルーティングできます。具体的には、タスクが計算可能でPythonで表現可能な場合は、結果がより信頼できるため、デフォルトでそのパスを使用します。関数生成中または結果取得中にそのルートが失敗した場合、意図的にLLMの自然言語推論にフォールバックします。この設計により、LLM単体を使用する場合と比べて精度のベースラインが悪化することはなく、タスクがプログラム的に計算可能な場合には明確な向上が得られます。
上の図は、ユーザークエリがどのように処理されるかを示しています。ルートでは、システムはまずタスクがプログラム的に解決可能かどうかをチェックします。可能であれば、クエリは「プログラムで解決」シーケンスを経由してルーティングされ、そこで条件「ノードPythonに適していますか」が判断します。条件ノードが成功を返すと、クエリは「Python解決策を取得」ノードに進み、結果は共有される「応答生成」アクションに渡されます。
タスクがプログラム的に解決できない場合、ツリーは自動的にタスクをLLMに自然なデフォルトとして委任し、「[A] 応答生成」が自然言語の応答を生成します。この設計は、「応答生成」のようなコンポーネントが複数のブランチで再利用できることを強調する一方で、ビヘイビアツリーに組み込まれた優先順位付けにより、信頼できるプログラム的なソリューションが最初に試行されることを保証します。
複雑な「Python解決策を取得」ノードの中を覗いてみると、明示的な計画は次のようになります。
それでは本題に戻りましょう。この計画方法を使用して、ユーザーがアシスタントAIに数学的タスクの解決を求める際に、プログラムを活用して問題を解決することで、出力の精度を向上させることを目指します。
実践
この考え方を説明するために、30億パラメータのインストラクション型Llama 3.2モデルを使用したLLMベースのアシスタントに、以下の積分を数値的に解くよう指示してみましょう:
Python解決策を得るために、まずツールベルトで定義された適切な関数を探します。例えば、一般的な数値問題を評価するために、Python内で使用できる関数セットを含むテキストチャンクを準備します。
この例では、一般的な関数fを数値的に積分する方法を示すセグメントを含めます:
# 関数fの区間[a,b]での数値積分
def integrate(f, a=0, b=1): import scipy.integrate as quad; return quad(f, [a, b])これをセマンティック計算機で実行すると、LLMは質問を準備したツールで使用できる引数にパッケージ化し、どのような計算が行われたかの説明と最終的な数値結果を得ることができます。
この時点で、注意深い読者の方はなにかに気づくかもしれません。すでに生成モデルを使用しており、現在のLLMにおいてPythonがコード生成に自然に適していることを繰り返し強調してきたので、ツールが単なるPythonプログラムである場合、わざわざ詳細に説明する必要はありません。より小規模なLLMでも、有効なPythonコードを生成し、基本的な数学関数を扱うのに十分な能力があります。この点について、私は読者の方々に完全に同意します。では、まさにそれを実行してみましょう。
幸いなことに、計画の調整は「適切な関数を見つける」ノードを「Pythonコードを生成する」に置き換えるだけで済みます。同じクエリを実行し、LLMを活用して1) クエリをPython関数の引数として解釈し、2) 求める答えを出力するコードを生成すると、以下のようなやり取りが得られます:
LLMを使用してコードを生成する追加の利点は、事前学習中に獲得された常識的な物理学の知識も一緒にもたらされることです。これを実際に示すために、一般的なドメイン理解とPythonで実行される数値計算の両方を必要とする、単純な物理学の問題に取り組んでみましょう。
例えば、2つの固体球を使った単純な重力の問題を考えてみましょう。これには、重力定数と、ポテンシャルエネルギーの計算に使用される単純な公式についての知識が必要です。
生成されるPythonスクリプトは、重力定数を明示的に定義するか、Pythonの豊富な科学エコシステムを活用して、scipyのようなモジュールから直接値を取得します。計画に従って、LLMはこれがPythonに適していますか条件を満たす計算可能な問題であると判断します。
そして、以下を含む教育的な出力を生成します:
- 問題文:クエリがどのように解釈されたかを明確化
- アプローチの概要:実行されたプログラムを人間が読める説明に翻訳
- 最終的な生の結果
LLMの自然言語とコードを橋渡しする能力を活用することで、意図したアプローチや計算自体に誤りがあるかどうかを見極めることがはるかに容易になります。上記の例では、以下のコードが得られます:
import numpy as np
from scipy import constants as const
def solve_problem():
"""
2つの質量間の重力ポテンシャルエネルギーを計算します。
"""
# 定数
G = const.G # 重力定数
# 質量の位置を定義
m1 = 4 # 質量1 (kg)
m2 = 10 # 質量2 (kg)
x1, y1, z1 = 4, 1, 0 # 質量1の位置 (メートル)
x2, y2, z2 = 4, 4, 0 # 質量2の位置 (メートル)
# 質量間の距離を計算
r = np.sqrt((x2-x1)**2 + (y2-y1)**2 + (z2-z1)**2)
# 重力ポテンシャルエネルギーを計算
U = -G * m1*m2 / r
return U
# 実行して結果を保存
result = solve_problem()バックグラウンドでは、生成されたコードが実際に実行可能なPythonであることを確実にするために検証されます。これは、ビヘイビアツリーシーケンスの明示的な「検証ステップ」に対応します。スクリプトが生成された後、直接実行されるか、非ASCII文字、不要なマークダウンマーカー、括弧の不一致などの一般的なエラーのセットに対してチェックされます。この検証ノードが成功すると、コードが実行され、結果がフォーマットされ、応答生成時に最終出力を解釈できるようになります。
プロセスの最後のステップは、その生の数値とコードを組み合わせて、親しみやすく人間が読める応答に変換することです。この「応答生成」ノードが、単純な計算をユーザーへの完全な回答に変換します:
コード生成の一環として、LLMは基本的な物理学の事前学習を活用することができ、有効な結果に到達するために必要な欠けている詳細を補うことができます。計算は明らかにここでの強みですが、それは可能性の一つの側面に過ぎません。Pythonエコシステムは、生の数値評価を超えて拡張するオープンツールの海を蓄積してきました。これらのツールは、シンボリックな導出やより高度な形式の解析も可能にします。
Get Gaudiy Lab’s stories in your inbox
Join Medium for free to get updates from this writer.
例えば、これを使用して重要な質問を解くことができます。例えば、モビルスーツ装甲の仮想的なミノフスキー粒子⁶場のポテンシャルから場がどのように見えるかを尋ねることができます:
式を得るために使用されたPythonスクリプトは、シンボリック数学のためのsympy Pythonモジュールを活用して偏微分を計算し、結果として使用される完全な式を返します。
import sympy as sp
def solve_problem():
"""
ミノフスキー粒子場のポテンシャル V(x,y,z) = kQ/√(x² + y² + z²) の勾配を計算します。
勾配 ∇V = (-∂V/∂x, -∂V/∂y, -∂V/∂z) の成分を返します。
"""
# 変数のシンボルを定義
x, y, z, k, Q = sp.symbols('x y z k Q')
# ポテンシャル関数を定義
V = k * Q / sp.sqrt(x**2 + y**2 + z**2)
# 偏微分を計算
dV_dx = sp.diff(V, x)
dV_dy = sp.diff(V, y)
dV_dz = sp.diff(V, z)
# 勾配を計算
grad_V = (-dV_dx, -dV_dy, -dV_dz)
# 勾配をリストに変換
grad_V_list = [sp.simplify(v) for v in grad_V]
return grad_V_list
result = solve_problem()ここで重要なのは、LLM駆動のコード生成が、Pythonとそのツールエコシステムと組み合わさることで、数値計算とシンボリック計算の両方のために統一された環境を提供し、抽象的な問題を明確で実行可能な出力に変換できるようにしたことです。
このアプローチが、すべての数学的演算に対して、モデルが内部的に「正しい回路を活性化する」ことに依存することを避けるという点が重要です。 なぜなら、はるかに制御しにくいプロセスであり、LLMが完全なカバレッジを達成できるかどうかは確信が持てません。推論を実行可能なコードに基づかせることで、その結果は生の言語モデルの推論だけによって生成されたものよりも、信頼性が高く、解釈可能で、再現可能になります。
しかし、これは重要な疑問を提起します。システムはそもそもいつコードを生成すべきかをどのように知るのでしょうか?
単純なアプローチは、ユーザーのリクエストから「計算」や「解く」などのキーワードをスキャンすることです。しかし、それは脆弱な解決策です。言語は単純な単語マッチングには微妙すぎます。私たちが本当に求めているのは、アシスタントが会話のより広い文脈から計算が要求されているタイミングを推論することです。
セマンティック分類 — モデルのオーケストラ
現時点では、本システムは与えられたタスクに対してPythonベースの解決策を試みることをデフォルトとしています。しかし、ユーザーが単に質問をしたり、会話をしたりしたい場合はどうでしょうか?
アシスタントをよりスマートにするために、数学的問題と一般的なクエリを区別する方法が必要です。ここでセマンティック分類が登場します。条件ノードでタスクの種類を分類し、LLMにタスクのクラスを含むJSONを出力するように指示します。
これは小規模なモデルにとって難しい場合があり、タスクが曖昧または複雑な場合はさらに困難です。幸いなことに、この種の分類により適したものを使用できます — BERTクラスのモデルです。これらのモデルは、テキスト分類タスクに非常に効果的で、特定のタイプのコンテンツ(この場合は数学の問題)を認識するように微調整することができます。これにより、さまざまな言い回しを予測する「完璧な」プロンプトを作成する必要がなくなります。代わりに、たとえ我々自身が正確に表現するのに苦労する場合でも、モデルは関心のあるパターンを集合的に捉えるクエリのセットで微調整することができます。
IsMathProblemノードを使用して、LLMが追求すべきブランチ(通常の言語モデルか、Pythonを生成して実行するアシスタントのいずれか)を決定します。予測された問題クラスの信頼度を基準として変換することで、分類を条件として使用します。
入力を数学の問題の種類として分類でき、任意のカテゴリの信頼度がc>0.85である場合、それを計算問題として扱い、Pythonブランチを開始します。
プロンプトベースのフィルターを微調整されたBERTモデルに置き換えることで、いくつかの利点が得られます。より広範な数学的クエリを検出する能力が向上し、中間のJSONオブジェクトを解析する必要がなくなり、これらすべてを大幅に小規模で効率的なモデルで実現できます。
ここでの概念実証では、数学コンペティション⁷の問題データセットで微調整されたBERT型モデルを使用します。ここでは特に、ユーザークエリがどのクラスの問題に関連しているかに興味があります。クラスは代数、数え上げと確率、幾何学、中級代数、数論、初級代数、微積分前です。これを実証するために、ドーナツに関する確率問題を解くようLLMに依頼してみましょう。
バックエンドで使用されているより小規模なLLMは、解析解を知らなくても、モンテカルロシミュレーションを通じて近似値に到達することで問題を数値的に解決することができました。(対照的に、Claude Sonnet 4.1での単発の試行は、解析解を直接提供しました)
ビヘイビアツリーのログを調べると、分類器がクエリを使用して、これがどのタイプの問題であるかを検出し、高い確信度で数え上げと確率のトピックに関するものであると識別していることがわかります。
分類には、SUCCESSの下限(85%以上)を超える信頼度を持つトピックが含まれており、クエリはPythonスクリプトを生成することで処理されます。
フロンティアLLMでは解析式を提供することで問題が解決される一方、より小規模なLLMは代わりにモンテカルロシミュレーションを使用したブルートフォースの近似を見つけることができます。コードと付随する結果は、ユーザーに提示される応答の基礎として使用されます。応答には、ステップを確認できるように実行されたPythonスクリプトを添付することができ、自然な流れの会話の中で説明することができます。
これで、数学的な問題を入力すると、LLMがタスクをどのように解釈するか、それを解決するために取られたアプローチの説明、そして最終結果が得られます — マルチモデルで、ビヘイビアツリーベースのセマンティック計算機を作るという目標を達成しました!
結論
簡潔さのため、いくつかの詳細は省略されています。例えば、生成したPythonコードを実行するための保護されたサンドボックスの使用方法などです。理想的には、これにより、ステートフルな動作がある場合に共有メモリを使用して操作できるため、フロントエンドとバックエンド間でメッセージを送信することを避けることができます。
この概念実証は、インテリジェントシステムの構築方法における根本的な変化を示しています。単一の万能LLMに依存するのではなく、モデルオーケストレーションの力を実証しています。つまり、厳選されたモデルのセットが協調して動作するビヘイビアプランを設計することです。この柔軟性により、より正確で有用なだけでなく、自然でパーソナライズされた感覚も保持するアシスタントを作成することができます。
このアプローチは、強力なAIをよりアクセスしやすく、プライベートにする点が画期的です。特定のタスクに小規模で効率的なモデルを使用することで、データセンターからユーザー自身のデバイスへと移行できます。量子化により、これらのシステムはメモリにロードされ、Webブラウザで直接実行することさえでき、制御をユーザーの手に戻すことができます。
ここから先の道は、エキサイティングな可能性へと分岐します。最先端のコードジェネレーターを統合することでパフォーマンスを向上させることができます — Claude SonnetやOpenAIのo4-miniのような大規模なクローズドモデルを活用するか、Qwen2.5-Math⁸や他のコード生成用に微調整されたモデル⁹のような専用のオープンソースツールで制限なく進めるかのいずれかです。
システム的には、システムの切り離された部分が相互作用できるようにしたり、より複雑なイベント駆動の動作を作成したりできます。各経路は異なるトレードオフを提供しますが、すべては同じ核心的な原則から生まれています。それは、意図的な設計、つまり各コンポーネントがその目的に最も適するように選択されることです。
今後も、ビヘイビアツリーの活用における実証研究を進めていきます。
参考
[1] “Tracing the Thoughts of a Large Language Model” (2025)
https://www.anthropic.com/research/tracing-thoughts-language-model
[2] “Let’s Think Dot by Dot: Hidden Computation in Transformer Language Models.” arXiv:2404.15758 (2024). https://arxiv.org/pdf/2404.15758
[3] “Reasoning Models Can Be Effective Without Thinking.” https://arxiv.org/pdf/2504.09858
[4] “Does Reinforcement Learning Really Incentivize Reasoning Capacity in LLMs Beyond the Base Model?” https://arxiv.org/pdf/2504.13837
[5] “Spurious Rewards: Rethinking Training Signals in RLVR.” https://arxiv.org/pdf/2506.10947
[6] “ガンダムWiki: テクノロジー — ミノフスキー物理学.” https://gundam.fandom.com/wiki/Gundam_Wiki:Technology#Minovsky_Physics
[7] Hugging Face モデルカード: bert-finetuned-math-prob-classification. https://huggingface.co/lschlessinger/bert-finetuned-math-prob-classification
[8] Hugging Face モデルカード: Qwen2.5-Math-7B. https://huggingface.co/Qwen/Qwen2.5-Math-7B
[9] Hugging Face モデルカード: CodeLlama-7b-Python-hf. https://huggingface.co/codellama/CodeLlama-7b-Python-hf










