各生成AIにFacebookの広告APIの使い方を聞いてみた結果、一番良い回答をしたのは？

## はじめに
今、Claude3.5 sonnetがかなり、優秀な感じで話題になっていますが、ほかのAIも負けてないと思います。
そこで、天秤AIという1度に複数の生成AIに対して、質問できるサービスを使って、
現状、取り組んでいる広告APIに関して質問しつつ、それぞれの返答を比較して、コード作成に関してはどの生成AIがいいのか、検討してみました。ただの使用感です。
すべて無料で使える範囲での比較です。

## 登場AI
**チャッティー（ChatGPT）**：1年前からよく話をしている。たまにおかしなことを言うが、いろいろ気軽に聞ける。
**クロード兄さん（Claude）**：最近は、プログラミングに関して聞くことが多い。かなり優秀だと思う。
**パク氏（Perplexity）**：ソースまで用意して、丁寧に説明してくれる。
**ジェミニ（GEMINI）**：最近話すようになったが、英語のほうが話しやすそう。

## 質問する

Facebook広告のAPIを使って広告を出す方法を聞いてみる

みんなに課題を与えた。
普段このような質問の仕方はしないが、できればちゃんとした回答をしてほしいので、やってみた。バージョンの指定と、公式ドキュメントのURLを渡してみた。

天秤AIでの使用スペック
- チャッティー：GPT-4o
- ジェミニ：Gemini 1.5 Pro
- クロード兄さん：Claude 3.5 Sonnet
- パク氏：Perplexity web

### プロンプト
```
あなたはシステム会社に勤めるベテランエンジニアであり、広告に関しても豊富な知識を持っています。
現在、Facebook広告をAPIを使って出稿したいと考えています。認証やアクセストークンの準備は完了しているため、まずはAPIを使用してキャンペーンを作成する方法を知りたいです。
以下の条件で、PHPコードを提供してください。
Facebook SDKを使用してキャンペーンを作成する方法。
curlを使用してREST APIでキャンペーンを作成する方法。
APIのバージョンは最新のv20.0を使用します。参考のため、公式ドキュメントのURLを以下に記載しますので、
これを参照してください。
https://developers.facebook.com/docs/marketing-api/reference/ad-account/campaigns/
```

## 各AIの回答
まずSDKのほうから
予期するコード
#### 公式ドキュメントのコード
```document.php
/* PHP SDK v5.0.0 */
/* make the API call */
try {
  // Returns a `Facebook\FacebookResponse` object
  $response = $fb->post(
    '/act_<AD_ACCOUNT_ID>/campaigns',
    array (
      'name' => 'My campaign',
      'objective' => 'OUTCOME_TRAFFIC',
      'status' => 'PAUSED',
      'special_ad_categories' => '[]',
    ),
    '{access-token}'
  );
} catch(Facebook\Exceptions\FacebookResponseException $e) {
  echo 'Graph returned an error: ' . $e->getMessage();
  exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
  echo 'Facebook SDK returned an error: ' . $e->getMessage();
  exit;
}
$graphNode = $response->getGraphNode();
/* handle the result */
```
- - -

実際の回答（コードの部分のみ）を1人ずつ見ていく
回答そのものは、[ブログ](https://weekend-v.work/archives/846)のほうに張り付けた。


#### チャッティーのコード
```chatgpt.php
<?php

require_once 'vendor/autoload.php';

use Facebook\Facebook;

$accessToken = 'YOUR_ACCESS_TOKEN';
$adAccountId = 'act_YOUR_AD_ACCOUNT_ID';

$fb = new Facebook([
  'app_id' => 'YOUR_APP_ID',
  'app_secret' => 'YOUR_APP_SECRET',
  'default_graph_version' => 'v20.0',
]);

$data = [
  'name' => 'My Campaign',
  'objective' => 'LINK_CLICKS',
  'status' => 'PAUSED',
];

try {
  $response = $fb->post('/' . $adAccountId . '/campaigns', $data, $accessToken);
  $graphNode = $response->getGraphNode();
  echo 'Created campaign with id: ' . $graphNode['id'];
} catch(Facebook\Exceptions\FacebookResponseException $e) {
  echo 'Graph returned an error: ' . $e->getMessage();
  exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
  echo 'Facebook SDK returned an error: ' . $e->getMessage();
  exit;
}

?>
```
エラー処理もあるし、いい感じ。

#### ジェミニのコード
```gemini.php
<?php

use FacebookAds\Api;
use FacebookAds\Object\Campaign;
use FacebookAds\Object\Fields\CampaignFields;
use FacebookAds\Logger\CurlLogger;

// APIバージョンを設定
Api::init(YOUR_APP_ID, YOUR_APP_SECRET, YOUR_ACCESS_TOKEN, null, 'v20.0');

// デバッグログを有効にする場合
Api::instance()->setLogger(new CurlLogger());

// キャンペーンのパラメータを設定
$campaignData = array(
  CampaignFields::NAME => 'My Campaign',
  CampaignFields::OBJECTIVE => 'LINK_CLICKS',
  CampaignFields::STATUS => 'PAUSED',
  CampaignFields::SPECIAL_AD_CATEGORIES => [],
);

// キャンペーンを作成
try {
  $campaign = new Campaign(null, YOUR_AD_ACCOUNT_ID);
  $campaign->create(
    $campaignData,
    array(
      'execution_options' => array('validate_only' => false),
    )
  );

  echo 'Campaign ID: ' . $campaign->id . "\n";
} catch (Exception $e) {
  echo 'Error: ' . $e->getMessage() . "\n";
}
```
コメントで説明もあり、回答は簡潔で良き。

#### クロード兄さんのコード
```claude.php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use FacebookAds\Api;
use FacebookAds\Object\AdAccount;
use FacebookAds\Object\Campaign;

$app_id = 'YOUR_APP_ID';
$app_secret = 'YOUR_APP_SECRET';
$access_token = 'YOUR_ACCESS_TOKEN';
$ad_account_id = 'act_YOUR_AD_ACCOUNT_ID';

Api::init($app_id, $app_secret, $access_token);

$account = new AdAccount($ad_account_id);

$campaign = $account->createCampaign(
    [],
    [
        Campaign::FIELD_NAME => 'My First Campaign',
        Campaign::FIELD_OBJECTIVE => Campaign::OBJECTIVE_LINK_CLICKS,
        Campaign::FIELD_STATUS => Campaign::STATUS_PAUSED,
        Campaign::FIELD_SPECIAL_AD_CATEGORIES => [],
    ]
);

echo 'Campaign ID: ' . $campaign->id;
```
自分が書いたコード（ドキュメントを見て作ったもの）に近い。

#### パク氏のコード

```perplexity.php
<?php
require_once __DIR__ . '/vendor/autoload.php';

use Facebook\Facebook;

// アプリケーションのIDとシークレットを設定
$appId = 'YOUR_APP_ID';
$appSecret = 'YOUR_APP_SECRET';
$accessToken = 'YOUR_ACCESS_TOKEN';

// Facebook SDKのインスタンスを作成
$fb = new Facebook([
    'app_id' => $appId,
    'app_secret' => $appSecret,
    'default_graph_version' => 'v20.0',
]);

// アクセストークンを設定
$fb->setDefaultAccessToken($accessToken);

// キャンペーンを作成するためのパラメーターを設定
$campaignName = 'My Campaign';
$campaignObjective = 'CONVERSIONS';
$campaignStatus = 'ACTIVE';

// キャンペーンを作成
try {
    $response = $fb->post('/act_{ad_account_id}/campaigns', [
        'name' => $campaignName,
        'objective' => $campaignObjective,
        'status' => $campaignStatus,
    ]);
} catch (Facebook\Exceptions\FacebookResponseException $e) {
    echo 'Graph returned an error: ' . $e->getMessage();
    exit;
} catch (Facebook\Exceptions\FacebookSDKException $e) {
    echo 'Facebook SDK returned an error: ' . $e->getMessage();
    exit;
}

// 作成されたキャンペーンのIDを取得
$campaignId = $response->getGraphNode()->getId();

echo "Campaign created with ID: $campaignId";
```
こちらも、コメントで説明あり、ジェミニに近いか。

***

参考資料にドキュメントがあるので、ドキュメントを渡さなくてもこれくらいのコードは作成できたかもしれない。


### 実行してみる。

- チャッティー
use Facebook\Facebook;
このようなクラスはないようだ。
後半部分は使えそう。


- ジェミニ
クラスの読み込みもいい。使える。
だが、create()は推奨されない。
```
<b>Deprecated</b>:  create is being deprecated, please try not to use this in new code.
```
直すのに手間がかかりそう。


- クロード兄さん
createCampaignに渡すフィールド部分の名前を直せば使える
Campaign::FIELD_NAME -> name


- パク氏
チャッティー同様あるかわからないクラスを使用。
use Facebook\Facebook;
ほかはドキュメント通りといったところ。

***
## 回答２

つぎにREST APIの場合の回答

#### 想定する回答
SDKの時と同様、渡していたパラメータ部分。このJsonと送信部分だけ回答してくれればいい。
```document.json
    {
        "name": "My First Campaign",
        "objective": "OUTCOME_ENGAGEMENT",
        "status": "PAUSED",
        "daily_budget": 1000,
        "special_ad_categories": ["NONE"]
    }  
```
 これをアクセストークンをつけて、account_id/campaignsにおくればいい。
 
#### チャッティーのコード
```chatgpt.php
<?php

$accessToken = 'YOUR_ACCESS_TOKEN';
$adAccountId = 'act_YOUR_AD_ACCOUNT_ID';

// キャンペーン作成のためのデータ
$data = [
  'name' => 'My Campaign',
  'objective' => 'LINK_CLICKS',
  'status' => 'PAUSED',
];

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://graph.facebook.com/v20.0/' . $adAccountId . '/campaigns');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
  'Authorization: Bearer ' . $accessToken,
]);

$response = curl_exec($ch);
if (curl_errno($ch)) {
  echo 'Error:' . curl_error($ch);
} else {
  $result = json_decode($response, true);
  if (isset($result['id'])) {
    echo 'Created campaign with id: ' . $result['id'];
  } else {
    echo 'Error in response: ' . $response;
  }
}

curl_close($ch);

?>
```
送信したら、
```
Error in response: {"error":{"message":"(#100) The parameter special_ad_categories is required.
```
この部分は必須なのにつけてない。
```
"(#100) Objective LINK_CLICKS is invalid. Use one of: OUTCOME_LEADS, OUTCOME_SALES, OUTCOME_ENGAGEMENT, OUTCOME_AWARENESS, OUTCOME_TRAFFIC, OUTCOME_APP_PROMOTION."
```
LINK_CLICKSはドキュメントに書いてあるが、今回エラーが出たのは使用するアカウントにも問題があるのかもしれない。
修正は簡単だろう。

#### ジェミニのコード

```gemini.php
<?php

// APIエンドポイントとバージョン
$endpoint = 'https://graph.facebook.com/v20.0/' . YOUR_AD_ACCOUNT_ID . '/campaigns';

// リクエストヘッダー
$headers = array(
  'Authorization: Bearer ' . YOUR_ACCESS_TOKEN,
  'Content-Type: application/json',
);

// リクエストボディ
$data = array(
  'name' => 'My Campaign',
  'objective' => 'LINK_CLICKS',
  'status' => 'PAUSED',
  'special_ad_categories' => [],
);

// cURLセッションを初期化
$ch = curl_init();

// cURLオプションを設定
curl_setopt($ch, CURLOPT_URL, $endpoint);
curl_setopt($ch, CURLOPT_POST, true);
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 (curl_errno($ch)) {
  echo 'Error: ' . curl_error($ch);
} else {
  // レスポンスをデコード
  $responseData = json_decode($response, true);

  echo 'Campaign ID: ' . $responseData['id'] . "\n";
}

// cURLセッションをクローズ
curl_close($ch);
```
チャッティー同様
LINK_CLICKSを使っているのでエラーが出る。


#### クロード兄さんのコード

```claude.php
<?php
$access_token = 'YOUR_ACCESS_TOKEN';
$ad_account_id = 'act_YOUR_AD_ACCOUNT_ID';
$api_version = 'v20.0';

$url = "https://graph.facebook.com/{$api_version}/{$ad_account_id}/campaigns";

$data = [
    'name' => 'My First Campaign',
    'objective' => 'LINK_CLICKS',
    'status' => 'PAUSED',
    'special_ad_categories' => '[]',
    'access_token' => $access_token
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);

if (isset($result['id'])) {
    echo 'Campaign ID: ' . $result['id'];
} else {
    echo 'Error: ' . print_r($result, true);
}
```
LINK_CLICKSのエラーが出る。


#### パク氏のコード

```perplexity.php
curl -X POST \
  https://graph.facebook.com/v20.0/act_{ad_account_id}/campaigns \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
        "name": "My Campaign",
        "objective": "CONVERSIONS",
        "status": "ACTIVE"
      }'
```
ほかのものはPHPでの作成について書いてくれたが、パク氏はcurlで送る部分だけしかない。
しかも、special_categoriesもないし、CONVERSIONSも使えない。

***

## おわりに

このあとは、会話を新たに始め、広告グループの作成に関しても質問した。[ブログ](https://weekend-v.work/archives/848)
キャンペーンの作成の時とは違い、ドキュメントは渡さず、あいまいな感じの質問をして、どの程度の回答が得られるか試した。

しかし、どこかしら修正が必要で、そのまま使うことはできなかった。
自由にコードを生成してもらう分には問題なさそうだが、外部サービスを使うようなコードはまだ完ぺきとは言えない。プロンプトを改良すればいいのかもしれない。
何度かやり取りすれば、自分の望むコードを書いてくれるのは間違いないだろう。

キャンペーン作成ではgeminiが推奨されていないcreate()を使っていたが、
広告グループのほうではperplexityがcreate()を使っていた。
ネット検索をするperplexityが最新の情報を反映できないのか、なぞだった。

自分の望む回答に近かったのはクロード兄さんだが、ほかの人のコードも使えなくはない。
AIによっては、クラスの読み込みから、変数定義、エラー処理まで書いてくれるものもあるし、端折って回答するものもある。
使うAIはやはり好みかなと思う。半年前にも同じような質問をしたが、その時よりも回答は、より使えるコードになっている。
自分はコードレビューできるレベルでもないので、一番近い回答をしたクロード兄さんと話していこうと思う。