ruby-openaiを使ってBTSの心に残る言葉を和訳してみた

OpenAIのAPIをRubyで使用してみたかったので、`ruby-openai`を使用して翻訳処理を作ってみました。
Ruby単体で実現可能ですが、Webアプリケーションに組み込むことを想定して今回はRuby on Railsで作っていきます。
以下を事前に済ませています。
- Railsアプリケーションの立ち上げ
- `/lib`配下のクラス読み込みを可能にする

# 作業手順
1. OpenAIの公式ページからAPIキーを発行する
1. `Gemfile`に`ruby-openai`を追加する
1. `/lib`配下にクラスを作成する

# 1. OpenAIの公式ページからAPIキーを発行する
以下よりアカウントを作成した後にAPIキーを確認することができます。現在は無料のクレジットは廃止されているため、利用開始に伴ってクレジットの購入が必要です。
https://platform.openai.com/account/api-keys

↓アカウント作成およびクレジットの購入が完了後、以下の手順よりAPIキーを発行します。
![API_keys_-_OpenAI_API_🔊.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918819/25d7c08f-3522-2227-dbab-0ff5fff208c6.png)

![API_keys_-_OpenAI_API_🔊.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918819/b5120469-55b7-b427-5682-09ea8332f664.png)

![API_keys_-_OpenAI_API_🔊.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918819/61b28559-0ea2-bd5f-7de1-ad89da73c946.png)

# 2. `Gemfile`に`ruby-openai`を追加する
Gemfileに以下を追記して、`bundle install`を実行してください。
```ruby:Gemfile
gem "ruby-openai"
```

# 3. `/lib`配下にクラスを作成する
今回は`/lib`配下を選択していますが、ご自身の運用ルール等に沿ってお好みのフォルダ配下で作成してください。
```
touch lib/chat_gpt.rb
```

```ruby:lib/chat_gpt.rb
class ChatGpt
  API_KEY = Rails.application.credentials.dig(:open_ai, :api_key) # OpenAIのAPIキー
  OPEN_AI_MODEL = "gpt-3.5-turbo" # GPTモデル(LLM)を指定

  def initialize
    @client = OpenAI::Client.new(access_token: API_KEY)
  end

  def translate_ja(text)
    # APIレスポンスを取得
    response = @client.chat(
      parameters: {
        model: OPEN_AI_MODEL,
        messages: [{role: "user", content: create_prompt(text)}]
      }
    )

    # レスポンス内容から返答テキストを抽出して返す
    response["choices"][0]["message"]["content"]
  end

  private

  # 指示するテキストを生成
  def create_prompt(text)
    <<~TEXT
      以下の韓国語を和訳してください。

      #{text}
    TEXT
  end
end

```

Railsコンソール上でクラスを実行してみます。
```ruby
quote = "아미들이 보고 싶을 때 언제든 와도 되고. 또 가야 될 때, 혹은 가고 싶을 때, 언제든 떠나도 괜찮아요. 그런데 이것만은 기억해 주세요. 저는 항상 이 자리에 있다는 걸요"
ChatGpt.new.translate_ja(quote)

=> "ARMYが会いたいときはいつでも来てもいいです。また、行かなければならないとき、または行きたいとき、いつでも去っても大丈夫です。しかし、これだけは覚えてください。私はいつもここにいます。"
```

これで和訳ができました🎉

# コードの説明
```ruby
API_KEY = Rails.application.credentials.dig(:open_ai, :api_key)
OPEN_AI_MODEL = "gpt-3.5-turbo"
```

##### API_KEY
OpenAIの管理画面で発行したAPIキーを定義しています。シークレット情報であるため、`.env`または`Credential`で管理するようにしましょう。

##### OPEN_AI_MODEL
使用するGPTモデルを定義しています。今回はgpt-3.5-turbo系を使用していますが、gpt-4系など他のモデルを使用する場合は、以下のモデル一覧のサイトを参考に適宜変更してください。

```text:example
"gpt-4o"
"gpt-4-turbo"
"gpt-3.5-turbo-1106"
```

https://platform.openai.com/docs/models

```ruby
def create_prompt(text)
  <<~TEXT
    以下の韓国語を和訳してください。

    #{text}
  TEXT
end
```

指示するテキストを生成する処理です。基本的にどんな文字列を指定しても差し支えございませんが、ヒアドキュメントを使用して改行を含む文字列が比較的正確な回答を取得できました。

# OpenAIレスポンスの中身の説明
個人的に重要な項目を抜粋してそれぞれ解説
```ruby
{
 "id"=>"chatcmpl-xxxxxxxxxxxxxxxxxxxxxx",
 "object"=>"chat.completion",
 "created"=>1722936388,
 "model"=>"gpt-3.5-turbo-0125",
 "choices"=>
  [{"index"=>0,
    "message"=>{"role"=>"assistant", "content"=>"ARMYが会いたいときはいつでも来てもいいです。また、行かなければならないとき、または行きたいとき、いつでも去っても大丈夫です。しかし、これだけは覚えてください。私はいつもここにいます。"},
    "logprobs"=>nil,
    "finish_reason"=>"stop"}],
 "usage"=>{"prompt_tokens"=>111, "completion_tokens"=>85, "total_tokens"=>196},
 "system_fingerprint"=>nil
 }
```
- `id`
    - リクエストに固有の識別子
- `created`
    - レスポンスが生成されたUNIXタイムスタンプ
        - Unixエポック時間が返されるため、以下で日本時間のDateTimeに変換できます
            ```ruby
            DateTime.strptime(response["created"], "%s").new_offset(Rational(9, 24))
            ```
- `model`
    - 使用したGPTモデル名
- `choices`
    - `message`
        - `content`
            - 生成されたテキスト
- `usage`
    - `prompt_tokens`
        - 入力トークン数
    - `completion_tokens`
        - 出力トークン数
    - `total_tokens`
        - 合計トークン数

# おわりに
個人情報などをプロンプトに含めると情報漏洩等に繋がる可能性が高いため、使い方は気をつける方が良さそうです。
OpenAIの活用により、あなたのアプリケーションにAI機能を簡単に追加することができますので、参考にいただけますと幸いです。

# 参考文献
https://github.com/alexrudall/ruby-openai

https://platform.openai.com/docs/api-reference