【OpenAI】RailsでChat GPTを導入しよう

## はじめに
どうもこんにちはもきお([@mokio_50](https://twitter.com/mokio_50))です。突然ですが皆さんはChat GPTは好きですか？ 自分は大好きです。

どれほど開発の手助けになってきたことか。そんなChat GPTを会社のシステムとAPI連携することになりました。その機能開発を担当したので今回はRailsでChatGPTのAPI連携する流れを記事にしたいと思います。

実際の実装でなく、実装の流れを知りたいよって方は以下の記事も併せてご覧いただけますと幸いです。

https://qiita.com/mokio/items/13b8a572e38e542469ca

## 目次
1. APIキーの発行
2. 今回の実装イメージ
3. 実装
4. 検証

## 1. APIキーの発行
外部APIとの連携を行うためにはAPIキーが必要になります。以下の記事が参考になりました。

https://programming-zero.net/openai-api-key/

## 2. 実装イメージ
通常の外部API連携だと例えば法人番号を取得できるAPIと連携するとしましょう。その場合法人番号が取得できるリクエストを作成し、返ってきたレスポンスに対して整形し表示なりデータベースに保存するなりする流れになるかなと思います。

今回はChat機能を連携するのですが、その場合通常と異なる点があります。
Chat GPTは今までのチャットの流れを把握した上で返答をするので、今回の場合はチャットの流れを記憶させておく必要があります。

そういったイメージを持って実装すると少し実装がしやすくなるかなと思います。

## 3. 実装
いよいよ実装に入ります。今回リクエスト、レスポンスが簡易的な記述で実装できるようFaradayというGemを使用しました。また、``ruby-openai``というGemで実装するのが簡単そうでしたが今回は実務の汎用性を考慮し使用しませんでした。

https://github.com/alexrudall/ruby-openai
### Faradayのインストール

まずはGemfileに以下を追加します。
```ruby:Gemfile
  gem 'faraday'
```
railsコマンドで以下を実行します。
```
bundle install
```

これでFaradayを使用し、簡易的な記述でHTTPリクエスト、レスポンスを取得することができるようになります。

### APIキーを環境変数に入れる
次にAPIキーを直接ファイルに書いてはいけない（不正利用されちゃう可能性がある）ので、環境変数に入れます。ターミナルにて``vi .env``で``.env``ファイルを開いて以下を追加します。

```.env
  OPEN_AI_API_KEY=ご自身のAPI Key
```
そして``settings``に``.env``で定義したAPI KeyをRailsで使用できるよう記載します。
```ruby: config/settings.yml
  open_ai:
    api_key: <%= ENV["OPEN_AI_API_KEY"] %>
```

とりあえずローカルで動かしたいとかだけなら実装コードの``@api_key``に直接APIキーを記載しても動きます。

### 実装コード
さて、実装準備が整いました。今回実装したコードは以下です。``lib``配下にファイルを置きました。

```ruby:lib/open_ai/chat_api.rb
class ChatApi
  def initialize(prompt)
    @api_key = Settings.open_ai.api_key
    @base_url = "https://api.openai.com/v1/chat/completions"
    @histories = []

    if prompt
      @histories.push({ role: "system", content: prompt })
    end
  end

  def get_api_headers
    {
      "Authorization" => "Bearer #{@api_key}",
      "Content-type" => "application/json",
    }
  end

  def chat(content)
    @histories.push({ role: "user", content: content })

    conn = Faraday.new(url: @base_url) do |faraday|
      faraday.request :json
      faraday.response :json, content_type: /\bjson$/
      faraday.adapter Faraday.default_adapter
    end

    payload = {
      model: "gpt-3.5-turbo",
      max_tokens: 512,
      temperature: 0.9,
      messages: @histories,
    }

    response = conn.post do |req|
      req.headers = get_api_headers
      req.body = payload.to_json
    end

    message = response.body["choices"][0]["message"]
    @histories.push(message)
    message["content"]
  end
end
```


## 4. 検証
実装ができたところで早速Railsコンソールで試してみましょう。
Railsコマンドが打てる状態で``rails c``でコンソールを立ち上げます。
コンソールを立ち上げてからの流れはこちら
```ruby:
open_ai = Open::Ai::ChatApi.new("事前にChatGPTにどう返答してほしいかを記載")
open_ai.chat("チャットしたい文言を記載")
open_ai.chat("チャットしたい文言を記載")
...
```
まず、定義したクラスをnewしてオブジェクトを定義します。その際にChatGPTにどう返答してほしいかを最初に渡しておきます。例えば「あなたはRubyとRailsのスペシャリストです。エンジニアに対してアドバイスするようお願いします。」とかね。

実際にコンソールで試した結果は以下。

![スクリーンショット 2023-11-14 21.57.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/0b2e2750-b73e-5046-0cbf-f43e13a7411c.png)

こんな感じでChat GPTとコンソール上でチャットすることができました。あとは自作アプリや自社システムにUIを追加したりチャット結果をデータベースに保存されるようにしていく流れかなーと思います。

## おわりに
普段ブラウザ上でChatGPTを使用しているのでコンソールでチャットが返ってくるのはなんか不思議な感覚でした。ChatGPTをシステムに導入する企業も多い気がするので今回触れることができてよかったです。

最後までご覧いただきありがとうございました！
記事を書くモチベーションになりますので少しでも良かったと思っていただけたら左上のいいねボタンポチッといただけますと幸いです。