このチュートリアルでは、SQLを活用したエージェントの実装方法について説明します。 smolagents
.
なぜシンプルにして、標準的なテキストからSQLへのパイプラインを使わないのか?
標準的なtext-to-sqlパイプラインは、生成されるSQLクエリが不正確である可能性があるため、もろい。さらに悪いことに、クエリが不正確であってもエラーにはならず、アラームを発生させることなく不正確な、あるいは役に立たない出力をすることもある。
その代わり、エージェントシステムは出力を批判的に検査し、クエリを変更する必要があるかどうかを判断することができる。
このエージェントを作ろう💪
まず、SQL環境をセットアップする:
コピー
from sqlalchemy import ( create_engine、 メタデータ、 テーブル カラム 文字列 整数、 Float、 を挿入する、 検査する、 text、 ) engine = create_engine("sqlite:///:memory:") metadata_obj = MetaData() # city SQLテーブルの作成 テーブル名 = "領収書" receipts = テーブル( テーブル名、 metadata_obj、 カラム("receipt_id", 整数, primary_key=True)、 カラム("customer_name", String(16), primary_key=True)、 Column("価格", Float)、 カラム("チップ", Float)、 ) metadata_obj.create_all(engine) rows = [ {"receipt_id":1, "customer_name":"Alan Payne", "price":12.06、"チップ":1.20}, {"receipt_id":2, "customer_name": "アレックス・メイソン":"アレックス・メイソン", "価格":23.86、チップ0.24}, {"receipt_id":3, "customer_name": "ウッドロウ・ウィルソン":"ウッドロウ・ウィルソン", "価格":53.43、チップ5.43}, {"receipt_id":4, "customer_name": "マーガレット・ジェームズ":"マーガレット・ジェームズ", "価格":21.11、チップ1.00}, ] for rows: stmt = insert(receipts).values(**row) with engine.begin() as connection: カーソル = connection.execute(stmt)
エージェントの構築 #
では、SQLテーブルをツールで検索できるようにしてみよう。
ツールのdescription属性は、エージェントシステムによってLLMのプロンプトに埋め込まれます。ここでSQLテーブルについて説明します。
コピー
inspector = inspect(engine) columns_info = [(col["name"], col["type"]) for col in inspector.get_columns("receipts")]. table_description = "列:◆n" + "◆n".join([f" - {name}: {col_type}" for name, col_type in columns_info]) print(table_description)
コピー
カラム - receipt_id:INTEGER - 顧客名: VARCHAR(16) - 価格FLOAT - チップ: FLOAT
それではツールを作ってみよう。それには以下のものが必要だ:(読む ツールドック 詳細はこちら)
- docstringに
引数:
引数を列挙する部分。 - 入力と出力の両方にヒントを入力する。
コピー
from smolagents import tool ツール def sql_engine(query: str) -> str: """ テーブルに対してSQLクエリを実行できるようにします。結果の文字列表現を返します。 テーブルの名前は 'receipts' である。その説明は以下の通りである: カラム - receipt_id:INTEGER - 顧客名: VARCHAR(16) - 価格:FLOAT - チップ: FLOAT 引数 クエリ:実行するクエリ。これは正しいSQLでなければなりません。 """ 出力 = "" with engine.connect() as con: rows = con.execute(text(query)) for rows: output += "行" + str(行) 出力を返す
では、このツールを活用するエージェントを作ってみよう。
を使用している。 コードエージェント
これはsmolagentsのメイン・エージェント・クラスで、ReActフレームワークに従って、コードでアクションを記述し、以前の出力を反復することができるエージェントである。
モデルはエージェントシステムを動かすLLMです。HfApiModelはHFの推論APIを使ってLLMを呼び出すことができます。
コピー
from smolagents import CodeAgent, HfApiModel agent = CodeAgent( tools=[sql_engine]、 model=HfApiModel("meta-llama/Meta-Llama-3.1-8B-Instruct")、 ) agent.run("Can you give me the name of the client who got the most expensive receipt?")
レベル2: テーブル結合 #
では、もっと難易度を上げてみよう!エージェントに複数のテーブルの結合を処理させたいのです。
そこで、レシートIDごとにウェイターの名前を記録した2つ目のテーブルを作ってみよう!
コピー
テーブル名 = "ウェイター" receipts = テーブル( テーブル名 metadata_obj、 カラム("receipt_id", 整数, primary_key=True)、 カラム("waiter_name", String(16), primary_key=True)、 ) metadata_obj.create_all(engine) rows = [ {"receipt_id":1, "waiter_name":"Corey Johnson"}、 {"receipt_id": 1, "waiter_name": "Corey Johnson"}:2, "waiter_name":「マイケル・ワッツ} {"receipt_id": 2, "waiter_name": "Michael Watts"}:3, "waiter_name": "Michael Watts":「マイケル・ワッツ"}、 4, "waiter_name":「マーガレット・ジェームス} ] for rows: stmt = insert(receipts).values(**row) with engine.begin() as connection: カーソル = connection.execute(stmt)
テーブルを変更したので SQLExecutorツール
LLMがこのテーブルの情報を適切に活用できるようにするために、このテーブルの説明をこのテーブルに追加する。
コピー
updated_description = """テーブルに対してSQLクエリを実行できます。このツールの出力は実行出力の文字列表現であることに注意してください。 以下のテーブルを使用できます:"" inspector = inspect(engine) for table in ["receipts", "waiters"]: columns_info = [(col["name"], col["type"]) for col in inspector.get_columns(table)]. table_description = f "テーブル '{table}':˶n" table_description += "カラム:{n}" + "{n}".join([f" - {name}: {col_type}" for name, col_type in columns_info]) updated_description += "Ⅾ" + table_description print(updated_description)
このリクエストは前のものよりも少し難しいので、LLMエンジンをより強力な Qwen/Qwen2.5-コーダー-32B-インストラクター!
コピー
sql_engine.description = updated_description agent = CodeAgent( tools=[sql_engine]、 model=HfApiModel("Qwen/Qwen2.5-Coder-32B-Instruct")、 ) agent.run("Which waiter got more total money from tips?")
直接機能する!セットアップは驚くほど簡単だったでしょう?
この例は終わった!我々はこれらの概念に触れた:
- 新しいツールを作る。
- ツールの説明を更新する
- より強力なLLMに切り替えることは、エージェントの推論を助ける。
✅ これで、ずっと夢見ていたtext-to-SQLシステムを構築することができます!✨