Question: ruby-openai api gem in Ruby on Rails: how to implement a streaming conversation?

Openai provides an api which allows you to implement AI services such as ChaGPT or DAL-E.
For Ruby on Rails application, and there are couple of gems available, obe of them being ruby-openai.
It works very well, but the only problem is that it doesn't come with the stream conversation feature, meaning that you can only send one question request at a time without any history tracking of the conversation. In other words, the api forgets every question you asked after having sent the reply.
So how can we fix this?


Answer:
Basically you need to implement the whole behaviour yourself. Here are all the implementation step, including the implementation of the dal-e ai with a response with several pictures rather then just one.
You can also find my whole repository HERE and clone the app!!!
IMPLEMENTING A STREAM CONVERSATION FEATURE
Basic implementation
Check out Doug Berkley's Notion Page for basic implementation of the API
Implement a streaming conversation
By default the openai gem does not come with that feature, hence having to implement it yourself

Create your database with 3 tables (conversations, questions, answers) with thw following sctructure:

# schema.rb
ActiveRecord::Schema[7.0].define(version: 2023_05_29_194913) do
  create_table "answers", force: :cascade do |t|
    t.text "content"
    t.integer "question_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["question_id"], name: "index_answers_on_question_id"
  end

  create_table "conversations", force: :cascade do |t|
    t.text "initial_question"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.text "historic"
  end

  create_table "questions", force: :cascade do |t|
    t.text "content"
    t.integer "conversation_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["conversation_id"], name: "index_questions_on_conversation_id"
  end

  add_foreign_key "answers", "questions"
  add_foreign_key "questions", "conversations"
end


Routes

Rails.application.routes.draw do
  root "pages#home" # supposes that you have a pages controller with a home action
  resources :conversations, only: [:create, :show]
  post "question", to: "conversations#ask_question"
end


Home page view (with just a button that redirects to the create conversation action -- see bellow)

<h1>Let's talk</h1>
<%= button_to "Create New Conversation", conversations_path, method: :post, class: "btn btn-primary my-3" %>


Controller app/controllers/conversations_controller.rb

class ConversationsController < ApplicationController
  def create
    @convo = Conversation.create
    redirect_to conversation_path(@convo)
  end

  def show
    @convo = Conversation.find(params[:id])
  end

  def ask_question
    @question = Question.new(content: params[:entry])
    conversation = Conversation.find(params[:conversation])
    @question.conversation = conversation
    @question.save
    if conversation.historic.nil?
      response = OpenaiService.new(params[:entry]).call 
      conversation.historic = "#{@question.content}\n#{response}"
    else
      response = OpenaiService.new("#{conversation.historic}\n#{params[:entry]}").call
      conversation.historic += "\n#{@question.content}\n#{response}"
    end
    conversation.save
    @answer = Answer.create(content: response, question: @question)
    redirect_to conversation_path(conversation)
  end
end


Show page app/views/conversations/show.html.erb

<h1>This is your conversation</h1>
<p>Ask your question</p>
<form action="<%= question_path %>", method="post">
  <input type="hidden" name="conversation" value="<%= @convo.id %>">
  <textarea rows="5" cols="33" name="entry"></textarea>
  <input type="submit" class="btn btn-primary">
</form>

<br>

<ul>
  <% @convo.questions.each do |question| %>
    <li>
      Q: <%= question.content.capitalize %> <%= "?" if question.content.strip.last != "?" %>
    </li>
    <li>
      A: <%= question.answers.first.content %>
    </li>
  <% end %>
</ul>

<%= link_to "Back", root_path %>



rails s and test :)

Resources:

https://github.com/OGsoundFX/ruby-open-ai
https://doug-berkley.notion.site/doug-berkley/Rails-ChatGPT-Service-Object-Setup-21748fc969514b978bf6345f897b6d3e
https://github.com/alexrudall/ruby-openai

Going Further:

https://gist.github.com/alexrudall/cb5ee1e109353ef358adb4e66631799d