49714 Programming for Online Prototypes
· 9 members
A hands on introduction to building online products and services through code
A text enabled chatbot that lets you search for products online. It is intended to scale into a peer to peer buy-sell platform in order to promote the circular and sharing economy models.
The main reason I sought to build this project was to promote circular and sharing economy practices. As a person who has moved through 5 different cities across 2 countries in the past year, I can say from personal experience that it is a very painful process to setup a place, use it and finally, find people to pass on the things that one initially started with. For instance - mattresses, table, chair, bed frame, lamps, even clothes that are in a good condition. Another thought behind this was the model of sharing economy, suppose I want to use a drilling machine to drill 4/5 holes in my apartment. Now the upfront cost of purchasing this would be too much, but I wouldn't mind paying a few dollars to rent the machine for a few hours. Building up on these experiences, I sought to build a chatbot which can enable this.
Accio is aimed to be a fun, friendly and helpful bot. The main reason to build on the smalltalk feature (offered by Dialogflow) is to handle all cases where users perform actions not intended or perceived as usual in context of the bot for eg. I am bored, I am sleepy, Do not talk to me, Tell me a joke etc.
The following data diagram illustrates how the user data is going to be stored on the server.
Previously the bot was called 'buy sell' while testing the interaction in Botsoceity.
Botsoceity is a useful too for mocking up sample interactions with a bot. https://botsociety.io/
ruby '2.4.4'
source 'https://rubygems.org'
gem 'sinatra'
gem 'sinatra-contrib'
gem 'dotenv-rails', :groups => [:development, :test]
gem 'twilio-ruby', ">5.0.0"
gem "google-api-client", '~> 0.8'
gem 'google-cloud-dialogflow', '~> 0.2.2'
gem 'rakuten_web_service'
gem 'activerecord'
gem 'pg'
gem 'sinatra-activerecord' # excellent gem that ports ActiveRecord for Sinatra
gem 'rake', '>= 0.9.2'
gem 'json'
gem 'shotgun'
Click to Expand
def determine_response (body)
body = body.downcase.strip
no = "i didnt quite understand what you mean"
project_id = ENV["GOOGLE_CLOUD_PROJECT"]
query_result = detect_intent_texts project_id: project_id,
session_id: SecureRandom.uuid,
texts: [body],
language_code:"en-US"
intent = query_result.intent
parameters = JSON.parse(query_result.parameters.to_json)
fullfillment_text = query_result.fulfillment_text
if intent.blank?
response = fullfillment_text
else
intent = intent.display_name
if intent == "EventIntent"
service = Google::Apis::CalendarV3::CalendarService.new
service.client_options.application_name = APPLICATION_NAME
service.authorization = authorize
# Fetch the next 10 events for the user
calendar_id = 'primary'
reply = service.list_events(calendar_id,
max_results: 10,
single_events: true,
order_by: 'startTime',
time_min: Time.now.iso8601)
puts = 'Upcoming events:'
puts = 'No upcoming events found' if reply.items.empty?
reply.items.each do |event|
start = event.start.date || event.start.date_time
reply = "- #{event.summary} (#{start})"
response = reply
end
elsif intent == "WelcomeIntent"
time = Time.new
time_today = time.strftime("%A %B %d, %Y %H:%M")
evening_greetings = ["Toodles", "Namaste", "Accio says hi", "Hej hej", "Hola!", "good evening friend!"]
morning_greeting = ["good morning", "hello sunshine", "wakey wakey", "good morgon", "lumos"]
media = "https://media.giphy.com/media/13ZHjidRzoi7n2/giphy.gif"
if time.hour >= 12
message = evening_greetings.sample
elsif time.hour <12
message = morning_greeting.sample
end
response = message
elsif intent == "AboutIntent"
response = "Hello, I am Accio! I can help you to buy or sell things. If you're stuck, type help."
elsif intent == "SearchIntent"
items = RakutenWebService::Ichiba::Product.search(keyword: body) # This returns Enumerable object
items.first(10).each do |item|
puts "#{item['productName']}, #{item['maxPrice'] * 0.0089} USD" # You can refer to values as well as Hash.
response = "#{item['productName']}, #{item['maxPrice'] * 0.0089} USD"
end
elsif intent == "JokeIntent"
array_of_lines = IO.readlines("jokes.txt")
response = array_of_lines.sample
elsif intent == "HelpIntent"
response = "To buy or sell a product, type buy or sell followed by the name of the product. You can also type Accio followed by the product's name for buying"
elsif intent == "DefaultFallbackIntent"
response = fullfillment_text
elsif intent == "productNameIntent"
# puts parameters
# if parameters.blank?
# response = fullfillment_text
# else
# puts parameters['product_name']
product_name = parameters['fields']['productName']['listValue']['values']
number = parameters['fields']['number']['listValue']['values']
puts product_name
puts number
if !product_name.empty?
product_name = product_name[0]['stringValue'].to_s
end
if !number.empty?
number = number[0]['numberValue'].to_s
end
if product_name.empty? || number.empty?
response = fullfillment_text
else
# response = product_name + " " + number
response = "I found these items : "
items = RakutenWebService::Ichiba::Product.search(keyword: product_name) # This returns Enumerable object
items.first(5).each do |item|
puts item.to_s
puts "#{item['productName']}, #{item['maxPrice'] * 0.0089 * number.to_i} USD" # You can refer to values as well as Hash.
response = response + "
#{item['productName']}, #{item['maxPrice'] * 0.0089 * number.to_i} USD
#{item['productUrlMobile']}
"
end
end
# end
else
response = intent + " " + fullfillment_text
end
end
return response
end
Click to Expand
get '/accio_userdetails' do
AccioUserdetail.all.to_json
end
get '/accio_userdetails/create' do
user = {}
user['name'] = "Harshika Jain"
user['location'] = "Pittsburgh"
user['phone_number'] = "+7163308752"
userOut = AccioUserdetail.new(user)
if userOut.save
userOut.to_json
else
halt 422, userOut.errors.full_messages.to_json
end
end
get '/accio_purchases' do
AccioPurchase.all.to_json
end
get '/accio_purchases/create' do
purchase = {}
purchase['amount_paid'] = 500
purchase['paid_by_id'] = 4
purchase['product_id'] = 71
purchaseOut = AccioPurchase.new(purchase)
if purchaseOut.save
purchaseOut.to_json
else
halt 422, purchaseOut.errors.full_messages.to_json
end
end
Click to Expand
When I first experimented with Dialogflow, I ended up hooking it just to Twilio due to which intent detection and answers were being given by Dialogflow itself without the user inputs touching the ruby code at all. In the second iteration, Dialogflow was used to pick up intents while the user queries were answered using the Ruby programme.
the dialogflow ruby integration for intent detection can be found here: https://github.com/Harshikerfuffle/flying-unicorns/blob/master/technical_guide.md
This project is only accessible by signed in users. Be considerate and think twice before sharing.
A hands on introduction to building online products and services through code
A text enabled chatbot that lets you search for products online. It is intended to scale into a peer to peer buy-sell platform in order to promote the circular and sharing economy models.
October 19th, 2018