Hugging FaceがAIエージェントフレームワークを公開してました!
大晦日リリースということで、さすが見に過ごしてました
まずですね、アイコンが可愛いです!
可愛すぎ~~
ローンチブログはこちら
ローンチブログでは、「AIエージェントとはなにか?」「AIエージェントを使うべきとき/避けるべきとき」といった、ベーシックだけど、とてもためになる話が載ってますので、ぜひ一読ください。
smolagentsの特徴
smolagentsの特徴はズバリ 「Cade Agent」 です。
LLMに外部ツールを使わせる、いわゆるFunction Callingのアプローチでは、JSONを介してツール名やパラメーターをLLMに渡しますが、smolagentsでは、Pythonコードを渡すという動作になります。
いくつかの論文で、JSONではなくプログラムコードを渡すほうが精度が良いという結果になっているようです。
左がJSONを渡す形のFunction Callingです。複数ターンでやっと回答に辿り着くということが説明されています。
右がプログラムコードを渡す形で、この場合は、1ターンで回答にたどりつけます。
ブログでは他に以下の特徴も触れられています。
- シンプル:smolagentsの実装コードは1,000行ちょっと。とても軽量です
- Hugging Faceとの統合:構築したAIエージェントをSpacesとしてHugging Faceにアップロード可能です
- 様々なLLMに対応:OpenAIのAPIやHugging FaceでホストされているAPIはもちろん、LiteLLMに対応しているので、100以上のLLMに対応しています
エージェントを作ってみる
smolagentsをインストールします。
pip install smolagents
from smolagents import CodeAgent, DuckDuckGoSearchTool, LiteLLMModel
model = LiteLLMModel(
model_id="bedrock/amazon.nova-pro-v1:0", aws_region_name="us-east-1"
)
agent = CodeAgent(tools=[DuckDuckGoSearchTool()], model=model)
agent.run("東京から大阪に時速10kmで進むと、何日後に到着しますか?直進することとします。")
コードはかなり短いですね。
少しだけ解説します。
-
model
モデルは、
TransformersModel
、HfApiModel
、LiteLLMModel
、AzureOpenAIServerModel
、MLXModel
が用意されています。
一見少なそうですが、LiteLLMModelは内部でLiteLLMが使われており、GeminiやBedrockなど多数のモデルを使用できます。 -
tools
エージェントが使用できるツールを定義します。smolagentsにビルトインのツールとして、「DuckDuckGo web search」「Python code interpreter」「Transcriber」が用意されています。独自のツールを定義することも可能です。
実行して思考の様子を確認します。
以下、コンソールに出力されたログです
-
思考と実行の様子
╭──────────────────────────────────────────────────── New run ────────────────────────────────────────────────────╮ │ │ │ 東京から大阪に時速10kmで進むと、何日後に到着しますか?直進することとします。 │ │ │ ╰─ LiteLLMModel - bedrock/amazon.nova-pro-v1:0 ───────────────────────────────────────────────────────────────────╯
ステップ1が始まります。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Step 1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Pythonのコードを生成します。
─ Executing parsed code: ──────────────────────────────────────────────────────────────────────────────────────── import math # Step 1: Find the distance between Tokyo and Osaka distance_query = "distance between Tokyo and Osaka" distance_result = web_search(query=distance_query) print("Distance result:", distance_result) # Step 2: Calculate the time it takes to travel the distance at 10 km/h speed = 10 # km/h time_hours = None # will be calculated after getting the distance if "km" in distance_result: distance_km = float(distance_result.split()[0]) time_hours = distance_km / speed # Step 3: Convert the time from hours to days time_days = time_hours / 24 if time_hours is not None else None print("Time in days:", time_days) ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
生成したPythonコードを実行しますがエラーとなります。
Code execution failed at line 'if "km" in distance_result: distance_km = float(distance_result.split()[0]) time_hours = distance_km / speed' due to: ValueError: could not convert string to float: '##'
エラーになるとステップが終了します。
ステップ2が始まります━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Step 2 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
先ほどとは別のPythonコードが生成されます。
distance_result
変数の値はステップ1での実行で取得した値と思われます。新しく実行されるわけではなく、先程の続きで実行されるようです。─ Executing parsed code: ──────────────────────────────────────────────────────────────────────────────────────── import re # Extract the distance from the HTML content distance_match = re.search(r'The distance between Tokyo and Osaka is (\d+) km.', distance_result) if distance_match: distance_km = float(distance_match.group(1)) time_hours = distance_km / speed time_days = time_hours / 24 print("Time in days:", time_days) else: print("Distance not found in the search results.") ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
ステップ2の結果が出力されます。
Execution logs: Time in days: 2.1458333333333335 Out: 2.1458333333333335
ここで終わりそうですが、ステップ3が始まります。
次に生成されるコードは以下のような簡単なものでした。
どうやら、final_answer
関数の結果が、最終回塔になるようです。─ Executing parsed code: ──────────────────────────────────────────────────────────────────────────────────────── final_answer(2.15) ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────
そして、最終的に回答「2.15」が出力されました。
まとめ
smolagentsを軽く触ってみました。
アプローチは面白うそうだと感じましたが、生成するコードが結構実行時エラーになるので、体当たりしてる感がありますねw