# Hello AI world with Ruby!

### Building a small terminal-based chatbot app with OpenAI.

%[https://youtu.be/QhiKOhzuYr0] 

In this tutorial, we'll delve into creating your first AI-powered apps using Ruby, Langchain.rb library and OpenAI's GPTPT-4 API.

**Objective**

We'll create a terminal-based chatbot that allows you to OpenAI'S GPT-4. This chatbot will be able to process user inputs and generate relevant, context-aware responses.

1\. First, we'll need to create a ruby file. Let's call this chat.rb

2\. What we want to do next is import the necessary libraries

```ruby
require "openai"
require "langchain"
require "reline"
```

* **OpenAI**: The openai library is a Ruby client for interacting with OpenAI's API.
    
* **Langchain**: Langchain is a Ruby library designed for building language applications.
    
* **reline**: Reline is a Ruby library used for readline-compatible input in command-line applications.
    

3\. Create an instance of `Langchain::LLM::OpenAI`. This class is a wrapper around OpenAI's API, specifically tailored for language models (LLMs).

**Side Note:** The great thing with Langchain.rb is it supports other models, too, offering flexibility to switch between different AI models based on requirements.

4\. Chat Interaction

```ruby
# What we'll do next is to Define a method to prompt for and handle user messages
def prompt_for_message
  # Print instructions for multiline input
  puts "(multiline input; type 'end' on its own line when done. or exit to exit)"

  # Read multiline input from the user, checking if the last word is a termination keyword
  user_message = Reline.readmultiline("Question: ", true) do |multiline_input|
    last = multiline_input.split.last # Get the last word of the input
    DONE.include?(last) # Check if the last word is a termination keyword
  end

  # Return a no-operation symbol if there is no user message
  return :noop unless user_message

  # Process the multiline input to handle the termination keyword
  lines = user_message.split("\n")
  if lines.size > 1 && DONE.include?(lines.last)
    # Remove the "done" keyword from the message
    user_message = lines[0..-2].join("\n")
  end

  # Check if the user wants to exit the program
  return :exit if DONE.include?(user_message.downcase)

  # Return the processed user message
  user_message
end
```

The method `prompt_for_message`, handles multiline user inputs and implements commands for ending the input or exiting the program. The commands are: "done", "end", "eof", and "exit".

5\. Interactive Loop

```ruby
# Our next step is to create infinite loop to continuously handle user input
begin
  loop do
    user_message = prompt_for_message # We get the user message using the defined method above

    # Handle different cases of user message
    case user_message
    when :noop # If no operation, continue to the next iteration of the loop
      next
    when :exit # If exit, break the loop to end the program
      break
    end

    # Using Langchain's instance method 'message, we send the user message to OpenAI and print the OpenAI's response
    puts chat.message(user_message)
  end
# Lastly, we handle the Interrupt exception to gracefully exit the program if interrupted (e.g., Ctrl+C)
rescue Interrupt
  exit 0
end
```

The code continuously fetches user messages and uses `chat.message` to obtain and display responses from the AI, creating a dynamic conversation flow.

### Full code of chatbot.rb

```ruby
require "openai"
require "langchain"
require "reline"

Langchain.logger.level = :info

openai = Langchain::LLM::OpenAI.new(
  api_key: ENV["OPENAI_API_KEY"], # Use the OpenAI API key from the environment variable
  llm_options: {}, # Options for the language learning model (empty in this case)
  default_options: { chat_completion_model_name: "gpt-4" } # Set GPT-4 as the default chat model
)

chat = Langchain::Conversation.new(llm: openai)
chat.set_context("You are a chatbot from the future") # Set the context of the conversation

DONE = %w[done end eof exit].freeze

puts "Welcome to the chatbot from the future!"

def prompt_for_message
  puts "(multiline input; type 'end' on its own line when done. or exit to exit)"

  user_message = Reline.readmultiline("Question: ", true) do |multiline_input|
    last = multiline_input.split.last # Get the last word of the input
    DONE.include?(last) # Check if the last word is a termination keyword
  end

  return :noop unless user_message

  lines = user_message.split("\n")
  if lines.size > 1 && DONE.include?(lines.last)
    user_message = lines[0..-2].join("\n")
  end

  return :exit if DONE.include?(user_message.downcase)

  user_message
end

begin
  loop do
    user_message = prompt_for_message

    case user_message
    when :noop
      next
    when :exit
      break
    end
    puts chat.message(user_message)
  end

rescue Interrupt
  exit 0
end
```

*Originally posted on:*  
[https://blog.ademartutor.com/p/hello-ai-world-with-ruby](https://blog.ademartutor.com/p/hello-ai-world-with-ruby)

---

> Hello there!
> 
> Do you have a startup idea or an exciting project you’re passionate about? I’d love to bring your vision to life!
> 
> I’m a software developer with 13 years of experience in building apps for startups, I specialize in Rails + Hotwire/React.
> 
> Whether you’re looking to innovate, grow your business, or bring a creative idea to the forefront, I’m here to provide tailored solutions that meet your unique needs.
> 
> [**Let’s collaborate to make something amazing!**](https://www.linkedin.com/in/ademar-tutor-0a95972a)
> 
> Sincerely,  
> Ademar Tutor  
> [**hey@ademartutor.com**](mailto:hey@ademartutor.com)
