Skip to content

Instantly share code, notes, and snippets.

@secretpray
Created April 3, 2023 14:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save secretpray/2cf09ec4c6b896d48d54238185e91ce4 to your computer and use it in GitHub Desktop.
Save secretpray/2cf09ec4c6b896d48d54238185e91ce4 to your computer and use it in GitHub Desktop.

Для интеграции ChatGPT в приложение Rails вам потребуются следующие шаги:

  1. Получите API-ключ GPT, откройте сайт https://openai.com/ и зарегистрируйте аккаунт, елкгда будут инструкции по получению ключа.

  2. Добавьте библиотеку 'httparty' в файл Gemfile вашего приложения и запустите

bundle install
  1. Создайте класс в папке 'lib' вашего приложения для обращения к сервису GPT:
class GPT
  include HTTParty
  base_uri 'https://api.openai.com/v1'
  headers 'Content-Type' => 'application/json',
  'Authorization' => "Bearer #{ENV['OPENAI_GPT_API_KEY']}"

  def ask(question, model='text-davinci-002', max_tokens=100)
    response = self.class.post('/engines/'+ model + '/completions',
                                body: JSON.dump({ prompt: question,
                                                  temperature: 0.5,
                                                  max_tokens: max_tokens
                                                })
                               )
                               

    return response['choices'][0]['text']
  end
end
  1. Добавьте переменную окружения OPENAI_GPT_API_KEY в файл '.env' вашего приложения:
OPENAI_GPT_API_KEY=<ваш_ключ_GPT>
  1. В вашем контроллере добавьте действие, которое будет обращаться к классу GPT и возвращать ответ на заданный вопрос:
class QuestionsController < ApplicationController
  def chat
    @question = params[:question]
    @answer = GPT.new.ask(@question)
  end
end
  1. Создайте представление для отображения ответа в чате:
<h2>GPT response:</h2>
<%= @answer %></p>
  1. Настройте маршруты в вашем файле 'config/routes.rb':
Rails.application.routes.draw do
  get '/chat', to: 'questions#chat'
end
  1. В вашем файле 'app/views' добавьте форму для отправки вопроса:
<h2>Ask a question:</h2>
action="/chat" method="get">
<input type="text" name="question">
<input type="submit" value="Ask">
</form>
@secretpray
Copy link
Author

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-........." \
  -d '{
    "model": "gpt-3.5-turbo",
    "messages": [{"role": "user", "content": "Как изучить аглийский язык?"}]
  }'

result

{"id":"chatcmpl-71HaTn7eNAMSCiDLopE4FuhYUw8gj","object":"chat.completion","created":1680540289,"model":"gpt-3.5-turbo-0301","usage":{"prompt_tokens":24,"completion_tokens":458,"total_tokens":482},"choices":[{"message":{"role":"assistant","content":"Как ИИ, я могу дать несколько советов по изучению английского языка:\n\n1. Изучайте язык регулярно. Выделите каждый день какое-то время на практику, старайтесь изучать новые слова и грамматические правила.\n\n2. Используйте разнообразные источники для изучения языка. Это могут быть учебные пособия, ресурсы в Интернете, курсы, аудио- и видеоматериалы.\n\n3. Занимайтесь с носителями языка. Общение с родными говорящими поможет вам улучшить ваши навыки говорения, понимания и более глубокого погружения в языковую среду.\n\n4. Совершенствуйте свой английский язык постоянно. Старайтесь не ограничиваться изучением только элементарных навыков, и продолжайте углубляться в изучение языка.\n\n5. Помните, что один из лучших способов научиться аглийскому языку, это использовать его в жизни. Читайте на английском, смотрите фильмы и слушайте музыку на английском языке, общайтесь с носителями языка - так вы сможете быстро достичь успеха в изучении языка."},"finish_reason":"stop","index":0}]}

@secretpray
Copy link
Author

gem "ruby-openai"

require "ruby/openai"

api_key = 'sk-.............'

client = OpenAI::Client.new(access_token: api_key)
prompt = 'Что такое kidium.com.ua?'
response = client.completions(
  parameters: {
       model: "text-davinci-003",
       prompt: prompt,
       max_tokens: 2000
     })
 puts response['choices'][0]['text']

@secretpray
Copy link
Author

secretpray commented Apr 4, 2023

100% перевірений, робочий варіант


routes.rb

post 'posts/answer_ai', to: 'posts#answer_ai', as: :answer_ai

Controller

class PostsController < BaseController
    require "ruby/openai"
    include ActionView::RecordIdentifier

    def answer_ai
      # [TODO] 
      # chatGPT from API має дуже велику фантазію)
      # додати перевірку на наявність api_key 
      # додати виведення сповіщень про помилки: порожній пошуковий запит, немає api_key, тривале не отримання відповіді
      # додати логіку закриття блоку з відповіддю 
      # переробити на отримання відповіді у фоновій задачі, або з лоадером 
      @ask = params.dig(:post, :name)
      api_key = ENV['OPEN_AI_API_KEY']
      return if @ask.blank? || api_key.blank?

      client = OpenAI::Client.new(access_token: api_key)
      response = client.completions(
        parameters: {
          model: "text-davinci-003", # інші працюють ще гірше
          prompt: @ask,
          max_tokens: 200,
          temperature: 0
        }
      )
      @answer = response['choices'][0]['text']
      respond_to do |format|
        format.turbo_stream do
          flash.now[:success] = 'AI ответил на Ваш вопрос'
          render turbo_stream: [
            # виводимо відповідь разом із питанням
            turbo_stream.update(dom_id(current_user, :ask_messages),
                                partial: 'social/posts/ai/messages',
                                locals: { ask: @ask,
                                          answer: @answer }
                                ),
            # очищаємо форму
            turbo_stream.update( dom_id(current_user, :ask_form),
                                partial: 'social/posts/ai/form',
                                locals: { post: Post.new }
                               ),
            render_turbo_flash
          ]
        end
        format.html
      end
    end

Gemfile

gem "ruby-openai"

views

      <div>
        <div>
          <div class='d-flex col-12 col-md-7 justify-content-center justify-content-md-end pe-md-4 mb-3' id='<%= dom_id(current_user, :ask_form) %>'>
            <%= render 'social/posts/ai/form', post: Post.new %>
          </div>
        </div>
      </div>
        
      <div id='<%= dom_id(current_user, :ask_messages) %>' class='row mt-2 mb-5 shadow'>
        <%= render 'social/posts/ai/messages', ask: @ask, answer: @answer %>
      </div>

partials
_form.html.erb

<%= simple_form_for post, 
                    url: answer_ai_path, 
                    method: :post,
                    wrapper: :inline_form,
                    html: { class: "form-inline d-flex w-100"} do |f| %>
  <%= f.input :name, 
              label: false, 
              placeholder: 'Введите свой вопрос',
              wrapper_html: { class: 'me-2 w-100'},
              input_html: { class: 'form-control string required form-control rounded-6 py-2 px-4 w-100' } %>
  <%= f.submit 'Спросить у AI', class: 'btn btn-outline-kidium mx-4 mx-md-0 px-3 py-2 rounded-pill ms-2' %>
<% end %>

_messages.html.erb

<% if answer.present? %>
  <div class="card col-12 px-0">
    <div class="card-header px-4">
      Ваше запитання: <%= ask %>
    </div>
    <div class="card-body">
      <h5 class="card-title px-3">Штучний інтелект відповів:</h5>
      <p class="card-text fs-55 px-4 py-3"><%= answer %></p>
    </div>
  </div>
<% end %>

PS render turbo flash (class ApplicationController)

  def render_turbo_flash
    turbo_stream.prepend('service-frame', partial: "shared/flash")
  end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment