こんにちは、HolySheep AI の技術ライターです。私は普段、Web アプリケーション開発やデータベース管理工作を行うエンジニアで、日頃から API を使った開発をよく行っています。

今日は、Function Calling という技術を使って、Natural Language(自然言語)から SQL 文を自動生成する方法について、ゼロから丁寧に解説します。プログラミング経験が全くなくても、この記事を読み終えれば、自分のデータベースに日本語で質問できるようになります。

Function Calling とは?

Function Calling とは、AI に対して「こういう処理をしてほしい」という指示を、事先定義好的 JSON スキーマとして渡す技術です。AI はその指示に従って、構造化されたデータを返してくれます。

例えば、こんなことができます:

なぜ HolySheep AI なのか?

私は複数の AI API を使ってきた経験から、HolySheheep AI の魅力を実感しています:

実践的なコード例

1. シンプルな SELECT 文の生成

まずは最も基本的な例として、データベースからデータを取得する SELECT 文を生成してみましょう。

import urllib.request
import json

def generate_sql_with_function_calling():
    """
    HolySheep AI を使用して自然言語からSQLを生成する例
    私の一番シンプルな実装パターンです
    """
    
    url = "https://api.holysheep.ai/v1/chat/completions"
    
    headers = {
        "Authorization": "Bearer YOUR_HOLYSHEEP_API_KEY",
        "Content-Type": "application/json"
    }
    
    # Function Calling の定義:SQL生成専用ツール
    functions = [
        {
            "name": "generate_sql_query",
            "description": "自然言語からSQLクエリを生成します。データベースはMySQL互換を前提としています。",
            "parameters": {
                "type": "object",
                "properties": {
                    "sql_statement": {
                        "type": "string",
                        "description": "生成されたSQL文"
                    },
                    "explanation": {
                        "type": "string",
                        "description": "SQL文の日本語での説明"
                    },
                    "estimated_rows": {
                        "type": "integer",
                        "description": "予想される結果行数"
                    }
                },
                "required": ["sql_statement", "explanation"]
            }
        }
    ]
    
    payload = {
        "model": "gpt-4o",
        "messages": [
            {
                "role": "system",
                "content": "あなたは経験豊富なデータベースエンジニアです。与えられた自然言語から正確なSQL文を生成してください。"
            },
            {
                "role": "user", 
                "content": "customers テーブルから、2024年に登録したユーザーの名前とメールアドレスを取得して"
            }
        ],
        "functions": functions,
        "function_call": "auto"
    }
    
    req = urllib.request.Request(
        url, 
        data=json.dumps(payload).encode('utf-8'),
        headers=headers,
        method='POST'
    )
    
    try:
        with urllib.request.urlopen(req, timeout=30) as response:
            result = json.loads(response.read().decode('utf-8'))
            return result['choices'][0]['message']
            
    except urllib.error.HTTPError as e:
        print(f"HTTPエラー: {e.code} - {e.read().decode('utf-8')}")
    except Exception as e:
        print(f"エラー発生: {str(e)}")

関数の呼び出し

result = generate_sql_with_function_calling() print("生成されたSQL:", result.get('function_call', {}).get('arguments'))

2. 複数のテーブルを結合する複雑なクエリ

実際の業務では、複数のテーブル結合が必要な場面がよくあります。こんなとき、Function Calling は非常に便利です。

import urllib.request
import json

def generate_complex_sql():
    """
    私が行っている複雑なSQL生成の例
    Orders、Customers、Productsテーブルを結合するケース
    """
    
    url = "https://api.holysheep.ai/v1/chat/completions"
    
    headers = {
        "Authorization": "Bearer YOUR_HOLYSHEEP_API_KEY", 
        "Content-Type": "application/json"
    }
    
    # データベーススキーマ情報を含むFunction定義
    schema_context = """
    テーブル構造:
    - customers (id, name, email, registration_date)
    - orders (id, customer_id, product_id, order_date, quantity, total_price)
    - products (id, name, category, price)
    
    リレーション:
    - orders.customer_id → customers.id
    - orders.product_id → products.id
    """
    
    payload = {
        "model": "gpt-4o",
        "messages": [
            {
                "role": "system",
                "content": f"あなたはデータベースエンジニアです。以下のスキーマ情報を元にSQLを生成してください。\n{schema_context}"
            },
            {
                "role": "user",
                "content": """2024年第1四半期(1月〜3月)に、
                電子機器カテゴリで合計購入額が5000円以上の顧客について、
                顧客名・総注文数・総購入額を一覧表示してください。
                総購入額が多い順にソートしてください。"""
            }
        ],
        "functions": [
            {
                "name": "execute_sql_builder",
                "description": "SQLクエリビルダー:SELECT/INSERT/UPDATE/DELETE文を生成",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "query": {
                            "type": "object",
                            "properties": {
                                "statement": {
                                    "type": "string",
                                    "description": "生成されたSQL文"
                                },
                                "query_type": {
                                    "type": "string", 
                                    "enum": ["SELECT", "INSERT", "UPDATE", "DELETE"],
                                    "description": "SQL文の種類"
                                },
                                "tables_used": {
                                    "type": "array",
                                    "items": {"type": "string"},
                                    "description": "使用されたテーブル一覧"
                                },
                                "join_types": {
                                    "type": "array", 
                                    "items": {"type": "string"},
                                    "description": "使用されたJOINの種類"
                                },
                                "where_conditions": {
                                    "type": "array",
                                    "items": {"type": "string"},
                                    "description": "WHERE句の条件"
                                },
                                "risk_level": {
                                    "type": "string",
                                    "enum": ["LOW", "MEDIUM", "HIGH"],
                                    "description": "SQLの危険度(SELECTはLOW、DELETE/UPDATEはHIGHになる傾向)"
                                }
                            },
                            "required": ["statement", "query_type", "tables_used", "risk_level"]
                        }
                    },
                    "required": ["query"]
                }
            }
        ],
        "function_call": "auto"
    }
    
    req = urllib.request.Request(
        url,
        data=json.dumps(payload).encode('utf-8'),
        headers=headers,
        method='POST'
    )
    
    with urllib.request.urlopen(req, timeout=30) as response:
        data = json.loads(response.read().decode('utf-8'))
        function_response = data['choices'][0]['message']
        
        # Function Calling の結果を解析
        if 'function_call' in function_response:
            args = json.loads(function_response['function_call']['arguments'])
            print("=== 生成されたSQL ===")
            print(args['query']['statement'])
            print("\n=== 詳細情報 ===")
            print(f"種類: {args['query']['query_type']}")
            print(f"使用テーブル: {args['query']['tables_used']}")
            print(f"危険度: {args['query']['risk_level']}")
            
            return args['query']

実行

result = generate_complex_sql()

生成されるSQLの例

上記のコードを実行すると、以下のようなSQLが生成されます:

-- 2024年Q1の電子機器購入者リスト(合計5000円以上)
SELECT 
    c.name AS 顧客名,
    COUNT(o.id) AS 総注文数,
    SUM(o.total_price) AS 総購入額
FROM customers c
INNER JOIN orders o ON c.id = o.customer_id
INNER JOIN products p ON o.product_id = p.id
WHERE o.order_date BETWEEN '2024-01-01' AND '2024-03-31'
  AND p.category = '電子機器'
GROUP BY c.id, c.name
HAVING SUM(o.total_price) >= 5000
ORDER BY 総購入額 DESC;

Function Calling を使った SQL 生成のアーキテクチャ

私が行っている実践的なアーキテクチャでは、以下のようなフローになります:

Function Calling パラメータの詳細解説

function_call パラメータには2種類の指定方法があります:

よくあるエラーと対処法

エラー1:401 Unauthorized - 認証エラー

# ❌ 誤ったKeyの例
headers = {
    "Authorization": "Bearer sk-xxxxx-wrong-key",  # 無効なキー
    "Content-Type": "application/json"
}

✅ 正しい例:HolySheheep AI のダッシュボードからコピーしたKeyを使用

headers = { "Authorization": f"Bearer {os.environ.get('HOLYSHEEP_API_KEY')}", "Content-Type": "application/json" }

環境変数からKeyを取得することを強く推奨

import os os.environ['HOLYSHEEP_API_KEY'] = 'your-actual-key-from-dashboard'

解決方法:HolySheheep AI のダッシュボードからAPI Keyを確認し、正確にコピーしてください。Keyの先頭に余分なスペースが入らないようにしましょう。

エラー2:Function Calling が呼ばれない

# ❌ 問題のあるコード:function_call 指定が不正
payload = {
    "model": "gpt-4o",
    "messages": [...],
    "functions": [...],
    "function_call": "generate_sql"  # 文字列で関数名を指定 - 動作しない
}

✅ 正しい例:functions を省略して function_call のみ指定

payload = { "model": "gpt-4o", "messages": [...], "functions": [...], "function_call": {"name": "generate_sql_query"} # オブジェクト形式で指定 }

または "auto" を使用(推奨)

payload = { "model": "gpt-4o", "messages": [...], "functions": [...], "function_call": "auto" # AI に判断任由 }

解決方法:function_call は "auto"(自動判定)か、{"name": "関数名"}(オブジェクト形式)で指定してください。文字列で関数名だけを書いても動作しません。

エラー3:JSONDecodeError - 関数レスポンスの解析エラー

# ❌ 問題のあるコード:引数のパース処理が不十分
function_response = result['choices'][0]['message']
args = json.loads(function_response['function_call']['arguments'])  # ここでエラー

✅ 正しい例:構造を確認してからパース

function_response = result['choices'][0]['message'] if 'function_call' in function_response: fc = function_response['function_call'] # arguments がすでに辞書の場合( моделиによる ) if isinstance(fc.get('arguments'), dict): args = fc['arguments'] else: # arguments が文字列の場合 args = json.loads(fc['arguments']) print(f"生成SQL: {args.get('sql_statement')}") else: print("Function Calling が行われませんでした")

解決方法:API から返される arguments の型はモデルによって異なります。文字列として返される場合と辞書として返される場合があるので、isinstance で型を確認してから json.loads してください。

エラー4:timeout - 接続タイムアウト

# ❌ 問題のあるコード:タイムアウト設定なし
req = urllib.request.Request(url, data=data, headers=headers)
with urllib.request.urlopen(req) as response:  # 永久に待つ可能性
    ...

✅ 正しい例:適切なタイムアウト設定

req = urllib.request.Request( url, data=json.dumps(payload).encode('utf-8'), headers=headers, method='POST' ) try: # HolySheheep AI は <50ms レイテンシ なので 10秒で十分 with urllib.request.urlopen(req, timeout=10) as response: result = json.loads(response.read().decode('utf-8')) except urllib.error.URLError as e: if isinstance(e.reason, socket.timeout): print("タイムアウト: ネットワーク接続を確認してください") else: print(f"接続エラー: {e.reason}")

解決方法:urllib.request.urlopen に timeout パラメータを設定してください。HolySheheep AI の場合は <50ms の高速応答を 提供しているので、10〜30秒のタイムアウトで十分です。

応用:安全性を高める SQL バリデーションレイヤー

私は Function Calling で生成された SQL をそのまま実行することは避け、常にバリデーションを設けています:

def validate_generated_sql(sql_statement, risk_level):
    """
    生成されたSQLの安全性をチェック
    私の実装では必ずこの関数を通しています
    """
    
    # 大文字に変換してチェック
    sql_upper = sql_statement.upper().strip()
    
    # 高リスクSQLのチェック
    dangerous_keywords = ['DROP', 'TRUNCATE', 'ALTER', 'CREATE']
    for keyword in dangerous_keywords:
        if keyword in sql_upper:
            raise ValueError(f"危険: {keyword} 文は実行禁止です")
    
    # 危険度レベルによる制限
    if risk_level == "HIGH" and not sql_upper.startswith("SELECT"):
        raise ValueError("高リスクSQLはシステム管理者の承認が必要です")
    
    # SQLインジェクション対策:セミコロンを含む複数文を拒否
    if ';' in sql_statement[:-1] if sql_statement.endswith(';') else ';' in sql_statement:
        raise ValueError("複数SQL文の実行は禁止されています")
    
    return True

使用例

if validate_generated_sql(generated_sql, risk_level): print("✅ SQL検証通過:実行可能です") # execute_query(generated_sql)

まとめ

Function Calling を使った SQL 文の自動生成はデータベース操作を大きく変える技術です。私の経験では、

HolySheheep AI なら ¥1=$1 という破格の料金で、これらの恩恵を受けることができます。<50ms の高速応答で、リアルタイムのクエリ生成にも十分対応可能です。

まずは無料クレジットを使って、実際に試してみてください。

👉 HolySheheep AI に登録して無料クレジットを獲得