#25 Goで学ぶAI API(ChatGPT等)の呼び出し方の基本

はじめに

ChatGPTのようなAI(人工知能)を使ったサービスは、プログラムから「API(エーピーアイ)」と呼ばれる窓口を通して呼び出すことができます。APIとは、あるプログラムが別のプログラムの機能を使うための「決められたやり取りのルール」のことです。難しく聞こえますが、実はやっていることはシンプルで、「インターネット越しにデータを送って、返ってきたデータを受け取る」だけです。

この記事では、Go言語を使ってAI APIのようなWebサービスを呼び出す際の「基本の型」を解説します。実際のサービスに接続するコードそのものというより、どんな流れで書けば良いのかという考え方を身につけることが目的です。

AI APIとのやり取りの流れ

ChatGPTのようなAI APIの多くは、次のような流れで動いています。

  1. 「こう質問したい」という内容をJSON(Webでよく使われるデータの形式)にまとめる
  2. そのJSONをHTTP(インターネット通信の約束事)のPOSTリクエストとしてAPIのサーバーに送る
  3. サーバーがAIに問い合わせて、答えをJSONで返してくる
  4. 返ってきたJSONを読み取り、必要な部分(AIの回答文など)を取り出す

つまり「JSONを作る → 送る → JSONを受け取って読む」という3ステップが基本の流れです。Goでこれをどう書くか、順番に見ていきましょう。

net/httpでPOSTリクエストを送る

GoにはHTTP通信を行うための標準ライブラリnet/httpが最初から用意されています。PythonのrequestsやJavaScriptのfetchのような外部ライブラリを別途インストールしなくても、標準機能だけでAPI通信ができるのがGoの特徴の一つです。

POSTリクエスト(サーバーにデータを送るタイプのリクエスト)を送る基本形は次のようになります。

req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
if err != nil {
    log.Fatal(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer " + apiKey)

client := &http.Client{}
resp, err := client.Do(req)

http.NewRequestでリクエストの中身(送り先のURL、送るデータ)を組み立て、client.Doで実際に送信します。ヘッダー(通信の付加情報)には、送るデータの種類(Content-Type)と、APIキー(利用者を識別するための認証用の文字列)を設定するのが一般的です。

APIキーの扱い方に注意

APIキーはいわば「サービスを使うためのパスワード」です。コードに直接書き込んでGitHubなどに公開してしまうと、第三者に不正利用されてしまう危険があります。実際の開発では、環境変数(OSに設定しておく値)から読み込むのが基本です。Goではos.Getenv("API_KEY")のように書くことで、コードにキーを直書きせずに済みます。

JSONのエンコードとデコード

Goは静的型付け言語(変数の型をあらかじめ決めておく言語)です。JSONを扱うときも「構造体(struct)」と呼ばれる型を定義してから変換するのが一般的なやり方です。PythonやJavaScriptのように辞書やオブジェクトへ自由に詰め込むのとは少し感覚が異なります。

type RequestBody struct {
    Model    string    `json:"model"`
    Messages []Message `json:"messages"`
}

type Message struct {
    Role    string `json:"role"`
    Content string `json:"content"`
}

reqBody := RequestBody{
    Model: "gpt-example",
    Messages: []Message{
        {Role: "user", Content: "こんにちは"},
    },
}
jsonData, err := json.Marshal(reqBody)

json:"model"のような部分は「タグ」と呼ばれ、Goの構造体のフィールド名とJSONのキー名を対応付けるものです。json.Marshalは構造体をJSONの文字列(正確にはバイト列)に変換する関数で、これを「エンコード」と呼びます。

反対に、受け取ったJSONをGoの構造体に変換することを「デコード」と呼び、json.Unmarshalを使います。ここでのResponseBodyも、先ほどのRequestBodyと同じように、受け取るJSONの形に合わせて自分で定義しておく構造体です。

var result ResponseBody
err = json.Unmarshal(body, &result)

「どんな形式のデータが返ってくるか」をAPIのドキュメントで確認し、それに沿った構造体を用意するのがGoでのAPI連携の基本です。

レスポンスを読み取る

サーバーから返ってきたレスポンス(応答)の本文は、resp.Bodyから読み出します。読み終わったら必ず閉じる必要があるため、deferという「関数が終わるときに実行する処理」を使うのが定番です。

defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)

こうして取得したバイト列を先ほどのjson.Unmarshalでデコードすれば、AIの回答文などを構造体のフィールドとして取り出せるようになります。

まとめ

GoでAI APIを呼び出す基本は、次の流れでした。「構造体でリクエストの形を定義する → JSONにエンコードする → net/httpでPOST送信する → 返ってきたJSONを構造体にデコードする」という流れです。動的型付け言語に比べると事前に型を定義する手間はありますが、その分「どんなデータをやり取りしているか」がコード上で明確になるのがGoらしい書き方だと言えます。まずはこの基本の型を押さえておけば、どんなAI APIやWeb APIを相手にしても応用が利くはずです。

関連記事


本ページはプロモーションを含みます。

参考書籍(PR)

Goをもっと学びたい方には「Go言語入門」がおすすめです。

コメント

このブログの人気の投稿

#11 Rustで学ぶエラーハンドリングの基本

#16 TypeScriptで学ぶ辞書型(マップ)の基本

#19 Goで学ぶテスト(単体テスト)の基本