Commit 9e151325 authored by  Joel  Oksanen's avatar Joel Oksanen
Browse files

Added support for rest of simple dialogue and plural arguments using the inflect library.

parent f7569324
......@@ -186,9 +186,29 @@ class Agent:
attacker_strengths = {a : self.strengths[a] for a in attackers}
return max(attacker_strengths, key=attacker_strengths.get)
def supported_argument(self, argument):
def liked_argument(self, argument):
return len(self.supporting_phrases(argument)) >= len(self.attacking_phrases(argument))
def supported_argument(self, argument):
return (self.get_strongest_supporting_subfeature(argument) != None and
self.strengths[self.get_strongest_supporting_subfeature(argument)] > 0)
def attacked_argument(self, argument):
return (self.get_strongest_attacking_subfeature(argument) != None and
self.strengths[self.get_strongest_attacking_subfeature(argument)] > 0)
def best_supporting_phrase(self, argument):
phrases = {vp['phrase'] : vp['sentiment'] for vp in self.supporting_phrases(argument)}
if len(phrases) == 0:
return None
return max(phrases, key=phrases.get)
def best_attacking_phrase(self, argument):
phrases = {vp['phrase'] : vp['sentiment'] for vp in self.attacking_phrases(argument)}
if len(phrases) == 0:
return None
return min(phrases, key=phrases.get)
def supporting_phrases(self, argument):
return list(filter(lambda vp: vp['sentiment'] > 0, self.vote_phrases[argument]))
......
from anytree import Node
camera = Node('camera')
image = Node('image', parent=camera)
images = Node('images', parent=camera)
video = Node('video', parent=camera)
battery = Node('battery', parent=camera)
flash = Node('flash', parent=camera)
......@@ -12,12 +12,12 @@ lens = Node('lens', parent=camera)
zoom = Node('zoom', parent=lens)
af = Node('af', parent=lens)
arguments = [camera, image, video, battery, flash, audio, price, shipping, lens, zoom, af]
features = [image, video, battery, flash, audio, price, shipping, lens, zoom, af]
arguments = [camera, images, video, battery, flash, audio, price, shipping, lens, zoom, af]
features = [images, video, battery, flash, audio, price, shipping, lens, zoom, af]
glossary = {
camera: ['camera', 'device', 'product'],
image: ['image', 'picture', ' pic '],
images: ['image', 'picture', ' pic '],
video: ['video'],
battery: ['battery'],
flash: ['flash'],
......
......@@ -2,6 +2,7 @@ from argumentquery import ArgumentQuery
from dataloader import DataLoader
from argument import *
from agent import Agent
import inflect
class ADAMessage:
......@@ -16,11 +17,12 @@ class Communicator:
ArgumentQuery(1, 'Why was the {arg} poorly rated?'),
ArgumentQuery(2, 'Why was the {arg} considered to be good?'),
ArgumentQuery(3, 'Why was the {arg} considered to be poor?'),
ArgumentQuery(4, 'Why did users say about the {arg} being good?'),
ArgumentQuery(5, 'Why did users say about the {arg} being poor?'),
ArgumentQuery(4, 'What did users say about the {arg} being good?'),
ArgumentQuery(5, 'What did users say about the {arg} being poor?'),
]
agent = Agent()
inflect = inflect.engine()
def __init__(self, dl):
self.dl = dl
......@@ -46,14 +48,37 @@ class Communicator:
if query_id == 0:
supp_node = self.agent.get_strongest_supporting_subfeature(q_arg_node)
att_node = self.agent.get_strongest_attacking_subfeature(q_arg_node)
text = 'The {} was highly rated because the {} was good'.format(q_arg.name, self.arguments[supp_node].name)
text = 'The {} was highly rated because the {} {} good'.format(
q_arg.name, self.arguments[supp_node].name, self.was_were(self.arguments[supp_node]))
if att_node:
text += 'although the {} was poor.'.format(self.arguments[att_node].name)
text += ', although the {} {} poor.'.format(
self.arguments[att_node].name, self.was_were(self.arguments[att_node]))
args = [q_arg_node, supp_node, att_node]
else:
text += '.'
args = [q_arg_node, supp_node]
args = [self.arguments[arg].withQueries(self.get_queries(arg)) for arg in args]
if query_id == 2:
supp_node = self.agent.get_strongest_supporting_subfeature(q_arg_node)
att_node = self.agent.get_strongest_attacking_subfeature(q_arg_node)
text = 'The {} was considered to be good because the {} {} good'.format(
q_arg.name, self.arguments[supp_node].name, self.was_were(self.arguments[supp_node]))
if att_node:
text += ', although the {} {} poor.'.format(
self.arguments[att_node].name, self.was_were(self.arguments[att_node]))
args = [q_arg_node, supp_node, att_node]
else:
text += '.'
args = [q_arg_node, supp_node]
if query_id == 4 or query_id == 5:
phrase = self.agent.best_supporting_phrase(q_arg_node) if query_id == 4 else self.agent.best_attacking_phrase(q_arg_node)
while phrase[-1] == '.':
phrase = phrase[:-1]
text = '\"...{}...\"'.format(phrase)
args = [q_arg_node]
args = [self.arguments[arg].withQueries(self.get_queries(arg)) for arg in args]
return ADAMessage(text, args)
......@@ -61,17 +86,22 @@ class Communicator:
arg = self.arguments[arg_node]
queries = []
if arg.id == 0:
# product
prod = self.arguments[self.argument_nodes[0]]
if self.dl.get_avg_star_rating(self.product_id) > 3:
queries.append(self.queries[0].withArgument(prod))
else:
queries.append(self.queries[1].withArgument(prod))
else:
base = 0 if arg.id == 0 else 2
if self.agent.liked_argument(arg_node):
if self.agent.supported_argument(arg_node):
queries.append(self.queries[2].withArgument(arg))
else:
queries.append(self.queries[3].withArgument(arg))
queries.append(self.queries[base].withArgument(arg))
supp_phrase = self.agent.best_supporting_phrase(arg_node)
if supp_phrase:
queries.append(self.queries[4].withArgument(arg))
else:
if self.agent.attacked_argument(arg_node):
queries.append(self.queries[base + 1].withArgument(arg))
att_phrase = self.agent.best_attacking_phrase(arg_node)
if att_phrase:
queries.append(self.queries[5].withArgument(arg))
return queries
def was_were(self, arg):
return 'were' if self.inflect.singular_noun(arg.name) else 'was'
import pandas as pd
data_location = 'amazon_reviews_us_Camera_v1_00.tsv'
training_data_location = 'reviews_trained_on.tsv'
min_characters = 50
reviews = pd.read_csv(data_location, sep='\t', error_bad_lines=False)
# drop reviews used for training
training_reviews = pd.read_csv(training_data_location, sep='\t', error_bad_lines=False)
reviews = pd.concat([reviews,training_reviews])
reviews = reviews.drop_duplicates(keep=False)
# drop reviews with empty review body
reviews = reviews[~reviews['review_body'].isnull()]
# try to filter out reviews for camera accessories
filter_words = ['accessor', 'battery', 'charger', 'tripod', 'strap', 'case', 'bag',
'backpack', 'kit', 'printer', 'adapter', 'album', 'surveillance', 'security']
filter = ''
for word in filter_words:
word_filter = '[' + word[0].upper() + word[0].lower() + ']' + word[1:]
filter += word_filter + '|'
filter = filter[:-1]
reviews = reviews[~reviews['product_title'].str.contains(pat = filter, regex = True)]
# drop reviews with less than min_characters characters
reviews = reviews[reviews['review_body'].apply(lambda x: len(str(x)) >= min_characters)]
# drop reviews for products with less than min_reviews reviews
grouped = reviews.groupby(['product_id', 'product_title'], sort=False).size().sort_values(ascending=False)
print(grouped.head(50))
......@@ -44,5 +44,4 @@ def message(request):
query_id = parsed['queryID']
arg_id = parsed['argumentID']
response = communicator.get_response(query_id, arg_id)
print(response.text)
return HttpResponse(jsonpickle.encode(response, unpicklable=False), content_type="application/json")
......@@ -17,7 +17,10 @@ class ConnectionManager: ObservableObject {
// ADAMessage(text: "The camera was highly rated because the lens was good, although the battery was poor.", arguments: [Argument(name: "camera"), Argument(name: "lens"), Argument(name: "battery")])
init() {
requestProduct(id: "B00RTGK0N0")
requestProduct(id: "B0012YA85A")
// B00RTGK0N0 - red Canon camera
// B004J3V90Y - Canon T3i
}
private func requestProduct(id: String) {
......@@ -105,10 +108,13 @@ class ConnectionManager: ObservableObject {
}
func addMessageWithDelay(_ message: Message, delay: Double) {
messageQueue = [message]
messageQueue = [Message]()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.messages.append(message)
for message in self.messageQueue! {
self.messages.append(message)
withAnimation(.linear(duration: 0.3)) {
self.messages.append(message)
}
}
self.messageQueue = nil
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment