さくらのAI Engine(API)をPHP言語で叩いてみてないコード(たぶん動く)

2025年10月8日
文字数[3501文字] この記事は4分23秒で読めます.

おはようございます.さくらのAI Engine(API)をPHP言語で叩いてみてないコード(たぶん動く)を記事の最終行ぐらいに記載しています.使用したい方はご自由お使い下さい.

さて、いま自分はPHP言語よりPython言語やTypeScript言語に興味があります.TypeScript言語は実務でも見る機会は増えています.ほぼ生成AIで出力したコードを見るのでいきなり中間層が書いたコードを見ることになります.

コードにはレベルがあります、初心者の方がいきなり中間層のコードを見ると何を書いているのか、恐らく分からないという問題に直面します、よって生成AIで出力されたコードが呪文のように見えるのです.

コードを理解するにはコードを読む力やコードを書く力をやっぱ付けないといけないと思います.これからプログラマーになろうと思っている方は、いきなり中間層のコードを目の当たりすると思います.なのでプログラマーという職は非常に狭き門になっていく可能性があります.

この頃、自分は実務でプログラムコードをほぼ書いていない日が続いています.コードを書かない代わりにCLI(プロンプト指示して)がコードを書いています.出力されたコードを確認してテストしてプルリクという感じの日々です.

そういう訳なのでツヨツヨエンジニアさんしか中々厳しい時代になってきたなと思います.

では、AI Engine(API)をPHP言語で叩いてみてないコード(たぶん動く)を下記に添付します.

<?php

/**
 * Sakura AI Chat Completion APIと連携するためのクラス(さくらのAI Engine)
 */
class SakuraAiChatClient {
    private string $apiBase = "https://api.ai.sakura.ad.jp/v1/chat/completions";
    private string $token;
    private string $defaultModel = "gpt-oss-120b";

    /**
     * コンストラクタ
     *
     * @param string $token さくらのAI Engineの認証トークン
     */
    public function __construct(string $token) {
        $this->token = $token;
    }

    /**
     * チャットコンプリーションAPIを呼び出す
     *
     * @param string $query LLMに送るメッセージ(クエリ)
     * @param string|null $model 使用するモデル名(nullの場合はデフォルトモデルを使用)
     * @return string LLMからの応答メッセージの内容
     * @throws Exception APIリクエストまたはJSONデコードに失敗した場合
     */
    public function getCompletion(string $query, ?string $model = null): string {
        $model = $model ?? $this->defaultModel;

        $headers = [
            "Content-Type: application/json",
            "Authorization: Bearer " . $this->token,
        ];

        $messages = [
            ["role" => "user", "content" => $query]
        ];

        $data = [
            "model" => $model,
            "messages" => $messages
        ];

        // cURLを使用してPOSTリクエストを送信
        $ch = curl_init($this->apiBase);
        if ($ch === false) {
            throw new Exception("cURLの初期化に失敗しました。");
        }

        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 実行結果を文字列で返す

        $response = curl_exec($ch);

        if ($response === false) {
            $error = curl_error($ch);
            curl_close($ch);
            throw new Exception("APIリクエストエラー: " . $error);
        }

        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($httpCode !== 200) {
            // エラー応答の場合
            throw new Exception("APIエラーが発生しました。HTTPステータスコード: " . $httpCode . " 応答: " . $response);
        }

        // JSON応答をデコード
        $responseData = json_decode($response, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception("JSONデコードエラー: " . json_last_error_msg() . " 応答: " . $response);
        }

        // 応答からメッセージの内容を抽出
        if (isset($responseData["choices"][0]["message"]["content"])) {
            return $responseData["choices"][0]["message"]["content"];
        } else {
            throw new Exception("API応答からメッセージの内容を取得できませんでした。応答: " . $response);
        }
    }
}

明日へ続く