From ef458ce607651949805d9fac9b9e68cf3f91b950 Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Wed, 18 Jul 2018 13:52:33 +0200 Subject: [PATCH 001/147] new states --- config.properties | 5 +- dialog/pom.xml | 2 +- .../fairShowStates/ActiveIntroState.java | 46 +++++++++++++ .../ChooseInteractiveTalk.java} | 10 +-- .../IdleState.java | 12 ++-- .../states/fairShowStates/InfoTalkState.java | 44 ++++++++++++ .../states/fairShowStates/MathState.java | 44 ++++++++++++ .../main/java/roboy/ros/RosSubscribers.java | 8 ++- .../AutomatedInteractionPesonality.json | 69 +++++++++++++++++-- 9 files changed, 216 insertions(+), 24 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java rename dialog/src/main/java/roboy/dialog/states/{monologStates/ActiveIntroState.java => fairShowStates/ChooseInteractiveTalk.java} (75%) rename dialog/src/main/java/roboy/dialog/states/{monologStates => fairShowStates}/IdleState.java (77%) create mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java diff --git a/config.properties b/config.properties index ee048846..ebdcd7f3 100755 --- a/config.properties +++ b/config.properties @@ -18,6 +18,7 @@ ROS_ACTIVE_PKGS: # - roboy_speech_recognition # - roboy_face # - roboy_filters +- roboy_vision - roboy_test DEBUG: true @@ -44,12 +45,12 @@ UDP_HOST_ADDRESS: 127.0.0.1 PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/ExpoPersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" +# PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" #PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" -# PERSONALITY_FILE: "resources/personalityFiles/AutomatedInteractionPersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/AutomatedInteractionPersonality.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" diff --git a/dialog/pom.xml b/dialog/pom.xml index dcae93de..383e3c77 100755 --- a/dialog/pom.xml +++ b/dialog/pom.xml @@ -327,7 +327,7 @@ org.ros.rosjava_messages roboy_communication_control - 0.0.1 + 0.0.3 diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java new file mode 100644 index 00000000..cb74ee6d --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java @@ -0,0 +1,46 @@ +package roboy.dialog.states.fairShowStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.nodes.Roboy; +import roboy.talk.Verbalizer; + +/** + * Passive state to start a conversation. + * Roboy is introducing himself autonomously + * + */ +public class ActiveIntroState extends State { + + private final static String TRANSITION_PEOPLE_AROUND = "peopleAround"; + private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; + + private final Logger LOGGER = LogManager.getLogger(); + + private State nextState; + + public ActiveIntroState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + @Override + public Output act() { + nextState = getTransition(TRANSITION_LONELY_ROBOY); + return Output.say(Verbalizer.greetings.getRandomElement()); + } + + @Override + public Output react(Interpretation input) { + + return Output.sayNothing(); + } + + @Override + public State getNextState() { + return nextState; + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/monologStates/ActiveIntroState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java similarity index 75% rename from dialog/src/main/java/roboy/dialog/states/monologStates/ActiveIntroState.java rename to dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java index 18286d31..566df7ba 100644 --- a/dialog/src/main/java/roboy/dialog/states/monologStates/ActiveIntroState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java @@ -1,22 +1,18 @@ -package roboy.dialog.states.monologStates; +package roboy.dialog.states.fairShowStates; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.sentenceanalysis.Interpretation; -import roboy.logic.StatementInterpreter; import roboy.memory.nodes.Roboy; -import roboy.talk.Verbalizer; - -import java.util.Set; /** * Passive state to start a conversation. * Roboy is introducing himself autonomously * */ -public class ActiveIntroState extends State { +public class ChooseInteractiveTalk extends State { private final Logger LOGGER = LogManager.getLogger(); @@ -24,7 +20,7 @@ public class ActiveIntroState extends State { private Roboy roboy; - public ActiveIntroState(String stateIdentifier, StateParameters params) { + public ChooseInteractiveTalk(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); } diff --git a/dialog/src/main/java/roboy/dialog/states/monologStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java similarity index 77% rename from dialog/src/main/java/roboy/dialog/states/monologStates/IdleState.java rename to dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index 28915189..068e0353 100644 --- a/dialog/src/main/java/roboy/dialog/states/monologStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -1,4 +1,4 @@ -package roboy.dialog.states.monologStates; +package roboy.dialog.states.fairShowStates; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -14,20 +14,20 @@ */ public class IdleState extends State { + private final static String TRANSITION_TIME_IS_UP = "timeIsUp"; + private final Logger LOGGER = LogManager.getLogger(); private State nextState; - private Roboy roboy; - public IdleState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); } @Override public Output act() { - - return Output.say(roboy.getName()); + nextState = getTransition(TRANSITION_TIME_IS_UP); + return Output.say("I am in IdleState"); } @Override @@ -38,7 +38,7 @@ public Output react(Interpretation input) { @Override public State getNextState() { - return this; + return nextState; } } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java new file mode 100644 index 00000000..e80ef4db --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java @@ -0,0 +1,44 @@ +package roboy.dialog.states.fairShowStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.nodes.Roboy; + +/** + * Passive state to start a conversation. + * Roboy is introducing himself autonomously + * + */ +public class InfoTalkState extends State { + + private final Logger LOGGER = LogManager.getLogger(); + + private State nextState; + + private Roboy roboy; + + public InfoTalkState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + @Override + public Output act() { + + return Output.say(roboy.getName()); + } + + @Override + public Output react(Interpretation input) { + + return Output.sayNothing(); + } + + @Override + public State getNextState() { + return this; + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java new file mode 100644 index 00000000..f4d25250 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java @@ -0,0 +1,44 @@ +package roboy.dialog.states.fairShowStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.nodes.Roboy; + +/** + * Passive state to start a conversation. + * Roboy is introducing himself autonomously + * + */ +public class MathState extends State { + + private final Logger LOGGER = LogManager.getLogger(); + + private State nextState; + + private Roboy roboy; + + public MathState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + @Override + public Output act() { + + return Output.say(roboy.getName()); + } + + @Override + public Output react(Interpretation input) { + + return Output.sayNothing(); + } + + @Override + public State getNextState() { + return this; + } + +} diff --git a/dialog/src/main/java/roboy/ros/RosSubscribers.java b/dialog/src/main/java/roboy/ros/RosSubscribers.java index 23c216ee..b3aa52a5 100644 --- a/dialog/src/main/java/roboy/ros/RosSubscribers.java +++ b/dialog/src/main/java/roboy/ros/RosSubscribers.java @@ -1,12 +1,18 @@ package roboy.ros; import roboy_communication_cognition.*; +import roboy_communication_control.Strings; +import std_msgs.Int8; public enum RosSubscribers { DIRECTION_VECTOR("roboy_audio", "/roboy/cognition/audio/direction_of_arrival", DirectionVector._TYPE), FACE_COORDINATES("roboy_vision", "/roboy/cognition/vision/coordinates", FaceCoordinates._TYPE), NEW_FACIAL_FEATURES("roboy_vision", "/roboy/cognition/vision/features", NewFacialFeatures._TYPE), - TEST_TOPIC("roboy_test", "/roboy", std_msgs.String._TYPE); + TEST_TOPIC("roboy_test", "/roboy", std_msgs.String._TYPE), + DETECTED_OBJECTS("roboy_vision", "/roboy/cognition/vision/detected_objects", Strings._TYPE), + NUMBER_PEOPLE_AROUND("roboy_vision", "/roboy/cognition/vision/people_around", std_msgs.Int8._TYPE), + PERSON_LISTENING("roboy_vision", "/roboy/cognition/vision/person_listening", std_msgs.Bool._TYPE) + ; String rosPackage; String address; diff --git a/resources/personalityFiles/AutomatedInteractionPesonality.json b/resources/personalityFiles/AutomatedInteractionPesonality.json index e9886e92..4c6970e0 100644 --- a/resources/personalityFiles/AutomatedInteractionPesonality.json +++ b/resources/personalityFiles/AutomatedInteractionPesonality.json @@ -4,14 +4,14 @@ "states": [ { "identifier": "Idle", - "implementation": "roboy.dialog.states.monologStates.IdleState", - "transitions":{ + "implementation": "roboy.dialog.states.fairShowStates.IdleState", + "transitions": { "timeIsUp": "ActiveIntro" } }, { "identifier": "ActiveIntro", - "implementation": "roboy.dialog.states.monologStates.ActiveIntroState", + "implementation": "roboy.dialog.states.fairShowStates.ActiveIntroState", "transitions": { "peopleAround": "InfoTalk", "lonelyRoboy": "Idle" @@ -19,7 +19,7 @@ }, { "identifier": "InfoTalk", - "implementation": "roboy.dialog.states.monologStates.InfoTalkState", + "implementation": "roboy.dialog.states.fairShowStates.InfoTalkState", "transitions": { "personDetected": "ChooseInteractiveTalk", "lonelyRoboy": "Idle" @@ -27,15 +27,70 @@ }, { "identifier": "ChooseInteractiveTalk", - "implementation": "roboy.dialog.states.monologStates.InfoTalkState", + "implementation": "roboy.dialog.states.fairShowStates.InfoTalkState", "transitions": { "newPerson": "PersonalQA", - "roboy": "RoboyQA", "math": "Math", "akinator": "Akinator", "snapchat": "Snapchat", - "phoneDetected": "SocialMedia" + "phoneDetected": "SocialMedia", + "other": "GeneralQA" + } + }, + { + "identifier": "PersonalQA", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "transitions": { + "finished": "InfoTalk" + }, + "parameters": { + "qaFile": "resources/sentences/QAList.json" } + }, + { + "identifier": "Math", + "implementation": "roboy.dialog.states.fairShowStates.MathState", + "transitions": { + "finished": "InfoTalk" + } + }, + { + "identifier": "Snapchat", + "implementation": "roboy.dialog.states.gameStates.GamingSnapchatState", + "transitions": { + "finished": "InfoTalk" + } + }, + { + "identifier": "Akinator", + "implementation": "roboy.dialog.states.gameStates.GamingTwentyQuestionsState", + "transitions": { + "finished": "InfoTalk" + } + }, + { + "identifier": "SocialMedia", + "implementation": "roboy.dialog.states.gameStates.SocialMediaState", + "transitions": { + "finished": "InfoTalk" + } + }, + { + "identifier": "GeneralQA", + "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "transitions": { + "finished": "InfoTalk" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + }, + { + "identifier": "Farewell", + "implementation": "roboy.dialog.states.ordinaryStates.FarewellState", + "transitions": {} } ] } From 2cc3d4ec0a84b824668c26b2cdcab9f2d495234f Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Sun, 22 Jul 2018 23:55:47 +0200 Subject: [PATCH 002/147] saving changes --- .../src/main/java/roboy/context/Context.java | 7 +++++ .../context/contextObjects/DetecedPerson.java | 9 +++++++ .../contextObjects/DetectedPersonUpdater.java | 26 +++++++++++++++++++ .../states/fairShowStates/InfoTalkState.java | 2 +- .../main/java/roboy/ros/RosSubscribers.java | 1 - memory | 2 +- ...esonality.json => FairShowPesonality.json} | 0 7 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 dialog/src/main/java/roboy/context/contextObjects/DetecedPerson.java create mode 100644 dialog/src/main/java/roboy/context/contextObjects/DetectedPersonUpdater.java rename resources/personalityFiles/{AutomatedInteractionPesonality.json => FairShowPesonality.json} (100%) diff --git a/dialog/src/main/java/roboy/context/Context.java b/dialog/src/main/java/roboy/context/Context.java index 278d571e..f774ad9d 100644 --- a/dialog/src/main/java/roboy/context/Context.java +++ b/dialog/src/main/java/roboy/context/Context.java @@ -7,6 +7,7 @@ import roboy.ros.RosMainNode; import roboy.util.ConfigManager; import roboy_communication_cognition.DirectionVector; +import std_msgs.Bool; import java.util.ArrayList; @@ -44,6 +45,9 @@ public class Context { public final HistoryInterface, Integer, Integer> OTHER_Q = new HistoryInterface<>(new ValueHistory()); + public final HistoryInterface PERSON_DETECTION = + new HistoryInterface<>(new DetecedPerson()); + /* GUI */ private final ArrayList guiValues = new ArrayList(); private final ArrayList guiHistories = new ArrayList(); @@ -58,6 +62,7 @@ public class Context { private boolean rosInitialized = false; private AudioDirectionUpdater AUDIO_ANGLES_UPDATER; private ROSTestUpdater ROS_TEST_UPDATER; + private DetectedPersonUpdater DETECTED_PERSON_UPDATER; /* OBSERVERS */ private final FaceCoordinatesObserver FACE_COORDINATES_OBSERVER; @@ -107,6 +112,8 @@ public void initializeROS(RosMainNode ros) { // TODO Add a FACE_COORDINATE_UPDATER. // Edit the data type and integration tests, once the real data type is used. + if(ConfigManager.ROS_ACTIVE_PKGS.contains("roboy_vision")) DETECTED_PERSON_UPDATER = new DetectedPersonUpdater(PERSON_DETECTION.valueHistory, ros); + rosInitialized = true; } } diff --git a/dialog/src/main/java/roboy/context/contextObjects/DetecedPerson.java b/dialog/src/main/java/roboy/context/contextObjects/DetecedPerson.java new file mode 100644 index 00000000..db067eb5 --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/DetecedPerson.java @@ -0,0 +1,9 @@ +package roboy.context.contextObjects; + +import roboy.context.ValueHistory; + +/** + * Holds booleans whether a person is longer than 10 seconds in the field of view receiving from vision + * */ +public class DetecedPerson extends ValueHistory { +} diff --git a/dialog/src/main/java/roboy/context/contextObjects/DetectedPersonUpdater.java b/dialog/src/main/java/roboy/context/contextObjects/DetectedPersonUpdater.java new file mode 100644 index 00000000..33b2b4d9 --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/DetectedPersonUpdater.java @@ -0,0 +1,26 @@ +package roboy.context.contextObjects; + +import roboy.context.ROSTopicUpdater; +import roboy.ros.RosMainNode; +import roboy.ros.RosSubscribers; + +/** + * Pushes new values sent by the Person Listening ROS topic into the DetectedPerson value history. + */ +public class DetectedPersonUpdater extends ROSTopicUpdater { + + public DetectedPersonUpdater(DetecedPerson target, RosMainNode node) { + super(target, node); + } + + @Override + protected synchronized void update() { + target.updateValue(message); + } + + @Override + protected RosSubscribers getTargetSubscriber() { + return RosSubscribers.PERSON_LISTENING; + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java index e80ef4db..688bf1f5 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java @@ -27,7 +27,7 @@ public InfoTalkState(String stateIdentifier, StateParameters params) { @Override public Output act() { - return Output.say(roboy.getName()); + return Output.say(getContext().PERSON_DETECTION.getLastNValues(5).toString()); } @Override diff --git a/dialog/src/main/java/roboy/ros/RosSubscribers.java b/dialog/src/main/java/roboy/ros/RosSubscribers.java index b3aa52a5..5320fe60 100644 --- a/dialog/src/main/java/roboy/ros/RosSubscribers.java +++ b/dialog/src/main/java/roboy/ros/RosSubscribers.java @@ -2,7 +2,6 @@ import roboy_communication_cognition.*; import roboy_communication_control.Strings; -import std_msgs.Int8; public enum RosSubscribers { DIRECTION_VECTOR("roboy_audio", "/roboy/cognition/audio/direction_of_arrival", DirectionVector._TYPE), diff --git a/memory b/memory index 2fcca216..50698b27 160000 --- a/memory +++ b/memory @@ -1 +1 @@ -Subproject commit 2fcca216439af2e0876a7965a9fa28d166584bf2 +Subproject commit 50698b270c0976cfbb34e986a9cbbff8253e01ec diff --git a/resources/personalityFiles/AutomatedInteractionPesonality.json b/resources/personalityFiles/FairShowPesonality.json similarity index 100% rename from resources/personalityFiles/AutomatedInteractionPesonality.json rename to resources/personalityFiles/FairShowPesonality.json From bc88fe98b87e86d0ced0a0fe6f318387e6292c4b Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Mon, 6 Aug 2018 14:42:34 +0200 Subject: [PATCH 003/147] intermediate push to merge --- config.properties | 8 ++-- .../states/fairShowStates/IdleState.java | 20 +++++++-- .../fairShowStates/SocialMediaState.java | 44 +++++++++++++++++++ ...sonality.json => FairShowPersonality.json} | 3 +- 4 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java rename resources/personalityFiles/{FairShowPesonality.json => FairShowPersonality.json} (94%) diff --git a/config.properties b/config.properties index ebdcd7f3..c8bacdb0 100755 --- a/config.properties +++ b/config.properties @@ -1,4 +1,4 @@ -ROS_ENABLED: true +ROS_ENABLED: false ROS_MASTER_IP: 127.0.0.1 # available ROS_ACTIVE_PKG are @@ -18,8 +18,8 @@ ROS_ACTIVE_PKGS: # - roboy_speech_recognition # - roboy_face # - roboy_filters -- roboy_vision -- roboy_test +# - roboy_vision +# - roboy_test DEBUG: true @@ -50,7 +50,7 @@ PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/AutomatedInteractionPersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index 068e0353..10b39049 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -7,6 +7,9 @@ import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.memory.nodes.Roboy; +import java.util.Timer; +import java.util.TimerTask; + /** * Idle state. * Roboy is waiting TBD minutes to autonomously start a conversation. @@ -16,23 +19,25 @@ public class IdleState extends State { private final static String TRANSITION_TIME_IS_UP = "timeIsUp"; - private final Logger LOGGER = LogManager.getLogger(); - private State nextState; + private final long delay = 1000*5; + Timer timer = new Timer(); + public IdleState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); } @Override public Output act() { - nextState = getTransition(TRANSITION_TIME_IS_UP); + return Output.say("I am in IdleState"); } @Override public Output react(Interpretation input) { + timer.schedule(timerTask, delay); return Output.sayNothing(); } @@ -41,4 +46,13 @@ public State getNextState() { return nextState; } + + TimerTask timerTask = new TimerTask() { + @Override + public void run() { + nextState = getTransition(TRANSITION_TIME_IS_UP); + getNextState(); + } + }; + } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java new file mode 100644 index 00000000..6fd18c9c --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java @@ -0,0 +1,44 @@ +package roboy.dialog.states.fairShowStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.talk.Verbalizer; + +/** + * Passive state to start a conversation. + * Roboy is introducing himself autonomously + * + */ +public class SocialMediaState extends State { + + private final static String TRANSITION_FINISH = "finished"; + + private final Logger LOGGER = LogManager.getLogger(); + + private State nextState; + + public SocialMediaState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + @Override + public Output act() { + + return Output.say("I am in Social Media State"); + } + + @Override + public Output react(Interpretation input) { + + return Output.sayNothing(); + } + + @Override + public State getNextState() { + return getTransition(TRANSITION_FINISH); + } + +} diff --git a/resources/personalityFiles/FairShowPesonality.json b/resources/personalityFiles/FairShowPersonality.json similarity index 94% rename from resources/personalityFiles/FairShowPesonality.json rename to resources/personalityFiles/FairShowPersonality.json index 4c6970e0..62ac79d4 100644 --- a/resources/personalityFiles/FairShowPesonality.json +++ b/resources/personalityFiles/FairShowPersonality.json @@ -1,5 +1,4 @@ { - "comment": "Personality that is running by itself.", "initialState": "Idle", "states": [ { @@ -70,7 +69,7 @@ }, { "identifier": "SocialMedia", - "implementation": "roboy.dialog.states.gameStates.SocialMediaState", + "implementation": "roboy.dialog.states.fairShowStates.SocialMediaState", "transitions": { "finished": "InfoTalk" } From 9a02650e77de2b19abeb362f0fcfca99f83ae407 Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Mon, 6 Aug 2018 18:58:33 +0200 Subject: [PATCH 004/147] skip user input in all MonologStates --- config.properties | 5 ++- .../main/java/roboy/dialog/Conversation.java | 8 +++- .../roboy/dialog/personality/Personality.java | 2 + .../personality/StateBasedPersonality.java | 32 +++++++++++---- .../states/definitions/MonologState.java | 39 +++++++++++++++++++ .../dialog/states/definitions/State.java | 15 ++++++- .../fairShowStates/ActiveIntroState.java | 13 ++----- .../fairShowStates/ChooseInteractiveTalk.java | 8 +--- .../states/fairShowStates/IdleState.java | 16 +++----- .../states/fairShowStates/InfoTalkState.java | 9 +---- .../states/fairShowStates/MathState.java | 8 +--- .../fairShowStates/SocialMediaState.java | 8 +--- 12 files changed, 106 insertions(+), 57 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/definitions/MonologState.java diff --git a/config.properties b/config.properties index 6ce1aa46..54940eaf 100755 --- a/config.properties +++ b/config.properties @@ -51,11 +51,12 @@ UDP_HOST_ADDRESS: 127.0.0.1 PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/ExpoPersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" -#PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" +# PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" +# PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/experimental/monolog.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" diff --git a/dialog/src/main/java/roboy/dialog/Conversation.java b/dialog/src/main/java/roboy/dialog/Conversation.java index db1ccc98..8ba36d8b 100644 --- a/dialog/src/main/java/roboy/dialog/Conversation.java +++ b/dialog/src/main/java/roboy/dialog/Conversation.java @@ -5,12 +5,12 @@ import roboy.dialog.action.Action; import roboy.dialog.action.SpeechAction; import roboy.dialog.personality.StateBasedPersonality; +import roboy.dialog.states.definitions.MonologState; import roboy.io.Input; import roboy.io.MultiInputDevice; import roboy.io.MultiOutputDevice; import roboy.linguistics.sentenceanalysis.Analyzer; import roboy.linguistics.sentenceanalysis.Interpretation; -import roboy.memory.nodes.Interlocutor; import java.io.File; import java.io.FileNotFoundException; @@ -103,6 +103,12 @@ public void run(){ break; } + //skip user input if needed + if(personality.skippingNeeded()){ + actions = personality.skipUserInput(); + continue; + } + // listen to interlocutor if conversation didn't end Input raw; try { diff --git a/dialog/src/main/java/roboy/dialog/personality/Personality.java b/dialog/src/main/java/roboy/dialog/personality/Personality.java index 075a9fcb..58a499ae 100755 --- a/dialog/src/main/java/roboy/dialog/personality/Personality.java +++ b/dialog/src/main/java/roboy/dialog/personality/Personality.java @@ -22,5 +22,7 @@ public interface Personality { * @param input The interpretation of the inputs * @return A list of actions to perform in response */ + List answer(Interpretation input); + } diff --git a/dialog/src/main/java/roboy/dialog/personality/StateBasedPersonality.java b/dialog/src/main/java/roboy/dialog/personality/StateBasedPersonality.java index ad5b0ebc..ff4f83d0 100644 --- a/dialog/src/main/java/roboy/dialog/personality/StateBasedPersonality.java +++ b/dialog/src/main/java/roboy/dialog/personality/StateBasedPersonality.java @@ -6,6 +6,7 @@ import roboy.dialog.action.Action; import roboy.dialog.action.EmotionAction; import roboy.dialog.action.SpeechAction; +import roboy.dialog.states.definitions.MonologState; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.logic.InferenceEngine; import roboy.logic.StatementInterpreter; @@ -18,8 +19,7 @@ import roboy.talk.PhraseCollection; import roboy.talk.Verbalizer; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * Implementation of Personality based on a DialogStateMachine. @@ -40,7 +40,6 @@ public class StateBasedPersonality extends DialogStateMachine implements Persona private final Logger logger = LogManager.getLogger(); - private final Verbalizer verbalizer; private boolean stopTalking; @@ -93,7 +92,6 @@ public boolean conversationEnded() { } - /** * Always called once by the (new) DialogSystem at the beginning of every new conversation. * @return list of actions based on act() of the initial/active state @@ -120,6 +118,25 @@ public List startConversation() { return initialActions; } + public boolean skippingNeeded(){ + + return getActiveState().getClass().getSuperclass().equals(MonologState.class); + } + + public List skipUserInput(){ + + List actions = new ArrayList<>(); + + State next = getActiveState().getNextState(); + if (next == null) { + // no next state -> conversation ends + endConversation(); + } + setActiveState(next); + stateAct(next, actions); + return actions; + } + @Override public List answer(Interpretation input) { @@ -155,7 +172,6 @@ public List answer(Interpretation input) { // ACTIVE STATE REACTS TO INPUT stateReact(activeState, input, answerActions); - // MOVE TO THE NEXT STATE State next = activeState.getNextState(); if (next == null) { @@ -165,7 +181,6 @@ public List answer(Interpretation input) { } setActiveState(next); - // NEXT STATE ACTS stateAct(next, answerActions); @@ -228,7 +243,7 @@ private void stateAct(State state, List previousActions) { * Call the react function of the state. If the state can't react, recursively ask fallbacks. * Verbalize the resulting reaction and add it to the list of actions. * - * @param state state to call REact on + * @param state state to call React on * @param input input from the person Roboy speaks to * @param previousActions list of previous action to append the verbalized result */ @@ -236,7 +251,9 @@ private void stateReact(State state, Interpretation input, List previous State.Output react; try { + react = state.react(input); + } catch (Exception e) { exceptionHandler(state, e, previousActions, false); return; @@ -249,7 +266,6 @@ private void stateReact(State state, Interpretation input, List previous return; // say nothing, just return and don't modify the list } - // first, resolve fallbacks if needed State fallback = state.getFallback(); int fallbackCount = 0, maxFallbackCount = 1000; // limit to prevent infinite loops diff --git a/dialog/src/main/java/roboy/dialog/states/definitions/MonologState.java b/dialog/src/main/java/roboy/dialog/states/definitions/MonologState.java new file mode 100644 index 00000000..72c481a4 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/definitions/MonologState.java @@ -0,0 +1,39 @@ +package roboy.dialog.states.definitions; + + +import roboy.linguistics.sentenceanalysis.Interpretation; + +public abstract class MonologState extends State { + + /** + * Create a state object with given identifier (state name) and parameters. + *

+ * The parameters should contain a reference to a state machine for later use. + * The state will not automatically add itself to the state machine. + * + * @param stateIdentifier identifier (name) of this state + * @param params parameters for this state, should contain a reference to a state machine + */ + public MonologState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + + /** + * Defines how to react to an input. This is usually the answer to the incoming question or some other statement. + * If this state can't react, it can return 'null' to trigger the fallback state for the answer. + * + * Note: In the new architecture, react() does not define the next state anymore! Reaction and state + * transitions are now decoupled. State transitions are defined in getNextState() + * + * @param input input from the person we talk to + * @return reaction to the input (should not be null) + */ + @Override + public Output react(Interpretation input){ + + return Output.skipInput(); + } + + +} diff --git a/dialog/src/main/java/roboy/dialog/states/definitions/State.java b/dialog/src/main/java/roboy/dialog/states/definitions/State.java index 853d0d16..c573e735 100644 --- a/dialog/src/main/java/roboy/dialog/states/definitions/State.java +++ b/dialog/src/main/java/roboy/dialog/states/definitions/State.java @@ -63,7 +63,7 @@ public static class Output { private final Logger logger = LogManager.getLogger(); public enum OutputType { - INTERPRETATION, SAY_NOTHING, USE_FALLBACK, END_CONVERSATION + INTERPRETATION, SAY_NOTHING, USE_FALLBACK, END_CONVERSATION, SKIP_INPUT } private final OutputType type; @@ -147,6 +147,14 @@ public static Output endConversation(String lastWords) { return new Output(OutputType.END_CONVERSATION, new Interpretation(lastWords)); } + /** + * Skip the users input + * @return State.Output object with appropriate settings + */ + public static Output skipInput() { + return new Output(OutputType.SKIP_INPUT, null); + } + // Non-static methods @@ -166,6 +174,10 @@ public boolean isEndOfConversation() { return type == OutputType.END_CONVERSATION; } + public boolean isSkippingUser() { + return type == OutputType.SKIP_INPUT; + } + public Interpretation getInterpretation() { return interpretation; } @@ -352,7 +364,6 @@ public final String getOptionalPersFileInfo(String key) { */ public abstract Output act(); - /** * Defines how to react to an input. This is usually the answer to the incoming question or some other statement. * If this state can't react, it can return 'null' to trigger the fallback state for the answer. diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java index cb74ee6d..a2dd56cb 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.sentenceanalysis.Interpretation; @@ -13,7 +14,7 @@ * Roboy is introducing himself autonomously * */ -public class ActiveIntroState extends State { +public class ActiveIntroState extends MonologState { private final static String TRANSITION_PEOPLE_AROUND = "peopleAround"; private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; @@ -28,19 +29,13 @@ public ActiveIntroState(String stateIdentifier, StateParameters params) { @Override public Output act() { - nextState = getTransition(TRANSITION_LONELY_ROBOY); - return Output.say(Verbalizer.greetings.getRandomElement()); - } - @Override - public Output react(Interpretation input) { - - return Output.sayNothing(); + return Output.say(Verbalizer.greetings.getRandomElement()); } @Override public State getNextState() { - return nextState; + return this; } } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java index 566df7ba..0bfdf4fa 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.sentenceanalysis.Interpretation; @@ -12,7 +13,7 @@ * Roboy is introducing himself autonomously * */ -public class ChooseInteractiveTalk extends State { +public class ChooseInteractiveTalk extends MonologState { private final Logger LOGGER = LogManager.getLogger(); @@ -30,11 +31,6 @@ public Output act() { return Output.say(roboy.getName()); } - @Override - public Output react(Interpretation input) { - - return Output.sayNothing(); - } @Override public State getNextState() { diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index 10b39049..be5de02a 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.sentenceanalysis.Interpretation; @@ -15,13 +16,13 @@ * Roboy is waiting TBD minutes to autonomously start a conversation. * */ -public class IdleState extends State { +public class IdleState extends MonologState { private final static String TRANSITION_TIME_IS_UP = "timeIsUp"; private State nextState; - private final long delay = 1000*5; + private final long delay = 1000*3; //msecs Timer timer = new Timer(); public IdleState(String stateIdentifier, StateParameters params) { @@ -30,16 +31,10 @@ public IdleState(String stateIdentifier, StateParameters params) { @Override public Output act() { - + timer.schedule(timerTask, delay); return Output.say("I am in IdleState"); } - @Override - public Output react(Interpretation input) { - - timer.schedule(timerTask, delay); - return Output.sayNothing(); - } @Override public State getNextState() { @@ -51,8 +46,9 @@ public State getNextState() { @Override public void run() { nextState = getTransition(TRANSITION_TIME_IS_UP); - getNextState(); } }; } + + diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java index 688bf1f5..444fa46b 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.sentenceanalysis.Interpretation; @@ -12,7 +13,7 @@ * Roboy is introducing himself autonomously * */ -public class InfoTalkState extends State { +public class InfoTalkState extends MonologState { private final Logger LOGGER = LogManager.getLogger(); @@ -30,12 +31,6 @@ public Output act() { return Output.say(getContext().PERSON_DETECTION.getLastNValues(5).toString()); } - @Override - public Output react(Interpretation input) { - - return Output.sayNothing(); - } - @Override public State getNextState() { return this; diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java index f4d25250..376121de 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.sentenceanalysis.Interpretation; @@ -12,7 +13,7 @@ * Roboy is introducing himself autonomously * */ -public class MathState extends State { +public class MathState extends MonologState { private final Logger LOGGER = LogManager.getLogger(); @@ -30,11 +31,6 @@ public Output act() { return Output.say(roboy.getName()); } - @Override - public Output react(Interpretation input) { - - return Output.sayNothing(); - } @Override public State getNextState() { diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java index 6fd18c9c..c96ac471 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.sentenceanalysis.Interpretation; @@ -12,7 +13,7 @@ * Roboy is introducing himself autonomously * */ -public class SocialMediaState extends State { +public class SocialMediaState extends MonologState { private final static String TRANSITION_FINISH = "finished"; @@ -30,11 +31,6 @@ public Output act() { return Output.say("I am in Social Media State"); } - @Override - public Output react(Interpretation input) { - - return Output.sayNothing(); - } @Override public State getNextState() { From 73ef7dbbe3006b459bf21f71de20fc2cb38a952b Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Tue, 7 Aug 2018 16:37:45 +0200 Subject: [PATCH 005/147] ros subscribers, timer implemented --- config.properties | 4 +-- .../src/main/java/roboy/context/Context.java | 7 +++++ .../contextObjects/DetectedObjects.java | 11 ++++++++ .../DetectedObjectsUpdater.java | 27 +++++++++++++++++++ .../context/contextObjects/PeopleAround.java | 9 +++++++ .../contextObjects/PeopleAroundUpdater.java | 26 ++++++++++++++++++ .../fairShowStates/ActiveIntroState.java | 23 +++++++++++----- .../states/fairShowStates/IdleState.java | 20 +++++++------- .../src/main/java/roboy/ros/RosMainNode.java | 22 +++++++-------- .../src/main/java/roboy/talk/Verbalizer.java | 4 +++ 10 files changed, 124 insertions(+), 29 deletions(-) create mode 100644 dialog/src/main/java/roboy/context/contextObjects/DetectedObjects.java create mode 100644 dialog/src/main/java/roboy/context/contextObjects/DetectedObjectsUpdater.java create mode 100644 dialog/src/main/java/roboy/context/contextObjects/PeopleAround.java create mode 100644 dialog/src/main/java/roboy/context/contextObjects/PeopleAroundUpdater.java diff --git a/config.properties b/config.properties index 54940eaf..98e87103 100755 --- a/config.properties +++ b/config.properties @@ -1,4 +1,4 @@ -ROS_ENABLED: false +ROS_ENABLED: true ROS_MASTER_IP: 127.0.0.1 # available ROS_ACTIVE_PKG are @@ -18,7 +18,7 @@ ROS_ACTIVE_PKGS: # - roboy_speech_recognition # - roboy_face # - roboy_filters -# - roboy_vision +- roboy_vision # - roboy_test DEBUG: true diff --git a/dialog/src/main/java/roboy/context/Context.java b/dialog/src/main/java/roboy/context/Context.java index f774ad9d..de712fc5 100644 --- a/dialog/src/main/java/roboy/context/Context.java +++ b/dialog/src/main/java/roboy/context/Context.java @@ -7,6 +7,7 @@ import roboy.ros.RosMainNode; import roboy.util.ConfigManager; import roboy_communication_cognition.DirectionVector; +import roboy_communication_control.Strings; import std_msgs.Bool; import java.util.ArrayList; @@ -48,6 +49,12 @@ public class Context { public final HistoryInterface PERSON_DETECTION = new HistoryInterface<>(new DetecedPerson()); + public final HistoryInterface CROWD_DETECTION = + new HistoryInterface<>(new PeopleAround()); + + public final HistoryInterface OBJECT_DETECTION = + new HistoryInterface<>(new DetectedObjects()); + /* GUI */ private final ArrayList guiValues = new ArrayList(); private final ArrayList guiHistories = new ArrayList(); diff --git a/dialog/src/main/java/roboy/context/contextObjects/DetectedObjects.java b/dialog/src/main/java/roboy/context/contextObjects/DetectedObjects.java new file mode 100644 index 00000000..e6c891b2 --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/DetectedObjects.java @@ -0,0 +1,11 @@ +package roboy.context.contextObjects; + +import roboy.context.ValueHistory; +import roboy_communication_control.Strings; + + +/** + * Holds detected Objects as a String Array receiving from vision + * */ +public class DetectedObjects extends ValueHistory { +} diff --git a/dialog/src/main/java/roboy/context/contextObjects/DetectedObjectsUpdater.java b/dialog/src/main/java/roboy/context/contextObjects/DetectedObjectsUpdater.java new file mode 100644 index 00000000..4d0a2db5 --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/DetectedObjectsUpdater.java @@ -0,0 +1,27 @@ +package roboy.context.contextObjects; + +import roboy.context.ROSTopicUpdater; +import roboy.ros.RosMainNode; +import roboy.ros.RosSubscribers; +import roboy_communication_control.Strings; + +/** + * Pushes new values sent by the Detected Objects ROS topic into the DetectedObjects value history. + */ +public class DetectedObjectsUpdater extends ROSTopicUpdater { + + public DetectedObjectsUpdater(DetectedObjects target, RosMainNode node) { + super(target, node); + } + + @Override + protected synchronized void update() { + target.updateValue(message); + } + + @Override + protected RosSubscribers getTargetSubscriber() { + return RosSubscribers.DETECTED_OBJECTS; + } + +} diff --git a/dialog/src/main/java/roboy/context/contextObjects/PeopleAround.java b/dialog/src/main/java/roboy/context/contextObjects/PeopleAround.java new file mode 100644 index 00000000..dcce6fdb --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/PeopleAround.java @@ -0,0 +1,9 @@ +package roboy.context.contextObjects; + +import roboy.context.ValueHistory; + +/** + * Holds number of people around as Integers receiving from vision + * */ +public class PeopleAround extends ValueHistory { +} diff --git a/dialog/src/main/java/roboy/context/contextObjects/PeopleAroundUpdater.java b/dialog/src/main/java/roboy/context/contextObjects/PeopleAroundUpdater.java new file mode 100644 index 00000000..303c5544 --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/PeopleAroundUpdater.java @@ -0,0 +1,26 @@ +package roboy.context.contextObjects; + +import roboy.context.ROSTopicUpdater; +import roboy.ros.RosMainNode; +import roboy.ros.RosSubscribers; + +/** + * Pushes new values sent by the People Around ROS topic into the PeopleAround value history. + */ +public class PeopleAroundUpdater extends ROSTopicUpdater { + + public PeopleAroundUpdater(PeopleAround target, RosMainNode node) { + super(target, node); + } + + @Override + protected synchronized void update() { + target.updateValue(message); + } + + @Override + protected RosSubscribers getTargetSubscriber() { + return RosSubscribers.NUMBER_PEOPLE_AROUND; + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java index a2dd56cb..35712e73 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java @@ -5,12 +5,10 @@ import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; -import roboy.linguistics.sentenceanalysis.Interpretation; -import roboy.memory.nodes.Roboy; import roboy.talk.Verbalizer; /** - * Passive state to start a conversation. + * Active state to start a conversation. * Roboy is introducing himself autonomously * */ @@ -18,10 +16,11 @@ public class ActiveIntroState extends MonologState { private final static String TRANSITION_PEOPLE_AROUND = "peopleAround"; private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; + private final int MIN_NUMBER_PEOPLE = 6; private final Logger LOGGER = LogManager.getLogger(); - private State nextState; + private State nextState = this; public ActiveIntroState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); @@ -29,13 +28,23 @@ public ActiveIntroState(String stateIdentifier, StateParameters params) { @Override public Output act() { - - return Output.say(Verbalizer.greetings.getRandomElement()); + if(checkPplAround()){ + nextState = getTransition(TRANSITION_PEOPLE_AROUND); + }else{ + nextState = getTransition((TRANSITION_LONELY_ROBOY)); + } + return Output.say(Verbalizer.greetings.getRandomElement() + Verbalizer.roboyIntro.getRandomElement()); } @Override public State getNextState() { - return this; + return nextState; + } + + + private boolean checkPplAround(){ + + return getContext().CROWD_DETECTION.getLastValue().getData() >= MIN_NUMBER_PEOPLE; } } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index be5de02a..a704f191 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -5,36 +5,36 @@ import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; -import roboy.linguistics.sentenceanalysis.Interpretation; -import roboy.memory.nodes.Roboy; import java.util.Timer; import java.util.TimerTask; /** * Idle state. - * Roboy is waiting TBD minutes to autonomously start a conversation. + * Roboy is waiting milliseconds to autonomously start a conversation. * */ public class IdleState extends MonologState { private final static String TRANSITION_TIME_IS_UP = "timeIsUp"; + private final Logger LOGGER = LogManager.getLogger(); - private State nextState; + private State nextState = this; - private final long delay = 1000*3; //msecs + private final long delay = 1000 * 5; //msecs Timer timer = new Timer(); public IdleState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); + timer.schedule(exitState, delay); + LOGGER.info("--> started Timer for " + delay + " msecs in Idle-State"); } @Override public Output act() { - timer.schedule(timerTask, delay); - return Output.say("I am in IdleState"); - } + return Output.sayNothing(); + } @Override public State getNextState() { @@ -42,10 +42,12 @@ public State getNextState() { } - TimerTask timerTask = new TimerTask() { + TimerTask exitState = new TimerTask() { @Override public void run() { nextState = getTransition(TRANSITION_TIME_IS_UP); + timer.cancel(); + LOGGER.info("--> stopped Timer in Idle-State"); } }; diff --git a/dialog/src/main/java/roboy/ros/RosMainNode.java b/dialog/src/main/java/roboy/ros/RosMainNode.java index 6a17ae0f..8c5bcb8b 100755 --- a/dialog/src/main/java/roboy/ros/RosMainNode.java +++ b/dialog/src/main/java/roboy/ros/RosMainNode.java @@ -11,7 +11,6 @@ import org.ros.node.service.ServiceResponseListener; import org.ros.node.topic.Subscriber; -import roboy.context.Context; import roboy.emotions.RoboyEmotion; import roboy.util.ConfigManager; import roboy_communication_cognition.*; @@ -399,16 +398,6 @@ public void onFailure(RemoteException e) { return resp; } - public void addListener(MessageListener listener, RosSubscribers subscriber) { - if(services.notInitialized(subscriber)) { - - LOGGER.warn(String.format(warning, subscriber.rosPackage)); - return; - } - Subscriber s = services.getSubscriber(subscriber); - s.addMessageListener(listener); - } - public boolean ApplyFilter(String filterName) { if(services.notInitialized(RosServiceClients.SNAPCHATFILTER)) { @@ -441,6 +430,17 @@ public void onFailure(RemoteException e) { return ((boolean) resp); } + public void addListener(MessageListener listener, RosSubscribers subscriber) { + if(services.notInitialized(subscriber)) { + + LOGGER.warn(String.format(warning, subscriber.rosPackage)); + return; + } + Subscriber s = services.getSubscriber(subscriber); + s.addMessageListener(listener); + } + + /** * Helper method to block the calling thread until the latch is zeroed by some other task. * @param latch Latch to wait for. diff --git a/dialog/src/main/java/roboy/talk/Verbalizer.java b/dialog/src/main/java/roboy/talk/Verbalizer.java index 1fbb499a..b32db711 100755 --- a/dialog/src/main/java/roboy/talk/Verbalizer.java +++ b/dialog/src/main/java/roboy/talk/Verbalizer.java @@ -124,6 +124,10 @@ private SpeechAction anecdote(Interpretation interpretation){ new RandomList<>("Oh no, where is my ROS connection? I need it. ", "I was looking for my ROS master everywhere but I can find it. ", "I think I have no ROS connection. ", "Hello? Hello? Any ROS master out there? Hmm, I can't hear anybody. " ); + public static final RandomList roboyIntro = + new RandomList<>("I am Roboy. Happy to be here! ", "My name is Roboy. Thank you for having me! ", "You can call me Roboy. What a nice place here. " + ); + private Interpretation verbalizeDates(Interpretation interpretation){ StringBuilder sb = new StringBuilder(); String sentence = interpretation.getSentence(); From 2d4e3a64f8305c7a7ac7c67f1a3a4cbf9c168df7 Mon Sep 17 00:00:00 2001 From: Jayce Date: Mon, 13 Aug 2018 20:50:13 +0200 Subject: [PATCH 006/147] Joseph's Highly Pedantic Changes --- .../linguistics/sentenceanalysis/SemanticParserAnalyzer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java index 50c59ce3..2aae5017 100644 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java @@ -135,7 +135,7 @@ private void executeSemanticAnalysis(Interpretation result, Example ex) String answer = val.pureString(); //Handle URL's - if (answer.contains(" at the end of URL } From 5aeff8ad30786d4e78aa059e18f0616592945629 Mon Sep 17 00:00:00 2001 From: Jayce Date: Mon, 13 Aug 2018 21:51:34 +0200 Subject: [PATCH 007/147] =?UTF-8?q?[Docs]=20TBL:=20-=20to=20=E2=80=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/developer_manual/2_Logging_Policy.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developer_manual/2_Logging_Policy.rst b/docs/developer_manual/2_Logging_Policy.rst index 363f6894..99644eb8 100644 --- a/docs/developer_manual/2_Logging_Policy.rst +++ b/docs/developer_manual/2_Logging_Policy.rst @@ -85,10 +85,10 @@ Developers should use a standardized policy when it comes to defining the loggin Level Method Level Method Level Method ============ ============ ============ ============ ============ ============ =================================== FATAL lg.fatal() SEVERE lg.severe() FATAL lg.fail() Problem requiring module to shutdown immidiately -ERROR lg.error() - Use WARNING ERROR lg.error() Problem that requires recommends a shutdown, but is not forcibly required +ERROR lg.error() — Use WARNING ERROR lg.error() Problem that requires recommends a shutdown, but is not forcibly required WARN lg.warn() WARNING lg.warning() WARN lg.warning() Unexpected behaviour that should be corrected, but is handlable for the program INFO lg.info() INFO lg.info() INFO lg.log() Information regarding the usage of module (e.g. Config Choices, Major Modules Loaded) -- - CONFIG lg.config() - - Avoid using this level +— — CONFIG lg.config() — — Avoid using this level DEBUG lg.debug() FINE lg.fine() DEBUG lg.dbg() Information not directly relevant to execution of program, unless debugging. This includes tests and parsing details. ============ ============ ============ ============ ============ ============ =================================== From 56dad13ed11149b8a30f4361d8daa389114d9d43 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 13:06:24 +0200 Subject: [PATCH 008/147] [Logging Policy] Conforming more Stuff to Standards --- .../main/java/roboy/dialog/Conversation.java | 2 +- .../java/edu/stanford/nlp/sempre/Example.java | 70 ++++++++++--------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/Conversation.java b/dialog/src/main/java/roboy/dialog/Conversation.java index 19957dc8..1fe3bc69 100644 --- a/dialog/src/main/java/roboy/dialog/Conversation.java +++ b/dialog/src/main/java/roboy/dialog/Conversation.java @@ -122,7 +122,7 @@ public void run(){ e.printStackTrace(); } } - logger.info(interpretation.toString()); + logger.debug(interpretation.toString()); // answer try { diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java index 2ee5e862..e9181416 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java @@ -7,9 +7,11 @@ import com.google.common.base.Joiner; import com.google.common.collect.Sets; import edu.stanford.nlp.sempre.roboy.utils.logging.EvaluationToggle; +import edu.stanford.nlp.sempre.roboy.utils.logging.ParserLogController; import fig.basic.Evaluation; import fig.basic.LispTree; import edu.stanford.nlp.sempre.roboy.utils.logging.LogInfoToggle; +import org.apache.logging.log4j.Level; import java.io.FileInputStream; import java.io.InputStream; @@ -272,41 +274,45 @@ public void preprocess() { } public void log() { - LogInfoToggle.begin_track("Example: %s", utterance); - LogInfoToggle.logs("Tokens: %s", getTokens()); - LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); - LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); - LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); - LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); - if (context != null) - LogInfoToggle.logs("context: %s", context); - if (targetFormula != null) - LogInfoToggle.logs("targetFormula: %s", targetFormula); - if (targetValue != null) - LogInfoToggle.logs("targetValue: %s", targetValue); - LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); - LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); - LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); - LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); - LogInfoToggle.end_track(); + if(ParserLogController.getLevel().isLessSpecificThan(Level.DEBUG)) { + LogInfoToggle.begin_track("Example: %s", utterance); + LogInfoToggle.logs("Tokens: %s", getTokens()); + LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); + LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); + LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); + LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); + if (context != null) + LogInfoToggle.logs("context: %s", context); + if (targetFormula != null) + LogInfoToggle.logs("targetFormula: %s", targetFormula); + if (targetValue != null) + LogInfoToggle.logs("targetValue: %s", targetValue); + LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); + LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); + LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); + LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); + LogInfoToggle.end_track(); + } } public void logWithoutContext() { - LogInfoToggle.begin_track("Example: %s", utterance); - LogInfoToggle.logs("Tokens: %s", getTokens()); - LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); - LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); - LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); - LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); - if (targetFormula != null) - LogInfoToggle.logs("targetFormula: %s", targetFormula); - if (targetValue != null) - LogInfoToggle.logs("targetValue: %s", targetValue); - LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); - LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); - LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); - LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); - LogInfoToggle.end_track(); + if(ParserLogController.getLevel().isLessSpecificThan(Level.DEBUG)) { + LogInfoToggle.begin_track("Example: %s", utterance); + LogInfoToggle.logs("Tokens: %s", getTokens()); + LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); + LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); + LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); + LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); + if (targetFormula != null) + LogInfoToggle.logs("targetFormula: %s", targetFormula); + if (targetValue != null) + LogInfoToggle.logs("targetValue: %s", targetValue); + LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); + LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); + LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); + LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); + LogInfoToggle.end_track(); + } } public List getCorrectDerivations() { From 88d54208a8c951b193a23b68f6d210bf2c1f2399 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 14:11:16 +0200 Subject: [PATCH 009/147] [Sentence Type] DictionaryBasedSentenceTypeDetector Preparation If STMT --> Use DBSTD otherwise SPA has succeeded --- .../DictionaryBasedSentenceTypeDetector.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java index dd3346da..2fc5ef4e 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java @@ -15,11 +15,19 @@ public class DictionaryBasedSentenceTypeDetector implements Analyzer{ public Interpretation analyze(Interpretation interpretation) { List tokens = interpretation.getTokens(); String[] posTags = interpretation.getPosTags(); - SentenceType sentenceType = determineSentenceType(tokens, posTags); - interpretation.setSentenceType(sentenceType); + + //Sentence Types shall be handled in Semantic Parser Analyzer. This is a fallback, in the event that SPA does not detect the sentence type + if(interpretation.getSentenceType().equals(SentenceType.STATEMENT)){ + SentenceType sentenceType = determineSentenceType(tokens, posTags); + interpretation.setSentenceType(sentenceType); + + } return interpretation; } + /** + * Fallback Sentence Type Detection, main Detector now in {@link SemanticParserAnalyzer} + */ private SentenceType determineSentenceType(List tokens, String[] posTags){ if (tokens != null && !tokens.isEmpty()) { String first = tokens.get(0).toLowerCase(); From b7ccac2c328dd56ecafcdefe96a0ead768e73308 Mon Sep 17 00:00:00 2001 From: Joseph Birkner Date: Tue, 14 Aug 2018 14:17:07 +0200 Subject: [PATCH 010/147] Fixed main() in FullNLPAnalyzer --- .../nlp/sempre/corenlp/FullNLPAnalyzer.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java index aaed284d..9271afeb 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java @@ -37,6 +37,7 @@ public class FullNLPAnalyzer extends InfoAnalyzer { public static class Options { @Option(gloss = "What CoreNLP annotators to run") public List annotators = Lists.newArrayList( + "tokenize", "tokenize", "ssplit", "truecase", @@ -80,6 +81,7 @@ public static void initModels() { Properties props = new Properties(); props.setProperty("annotators", Joiner.on(',').join(opts.annotators)); props.setProperty("coref.algorithm", "neural"); + //props.setProperty("openie.resolve_coref", "true"); props.setProperty("truecase.overwriteText", "true"); props.setProperty("ner.applyFineGrained", "false"); pipeline = new StanfordCoreNLP(props); @@ -216,7 +218,7 @@ public GeneralInfo getSent(LanguageInfo languageInfo, Annotation annotation) { // LogInfoToggle.logs("Keywords extracted: %s", genInfo.keywords.toString()); genInfo.sentiment_type = RNNCoreAnnotations.getPredictedClass(tree); genInfo.sentiment = sentence.get(SentimentCoreAnnotations.SentimentClass.class); -// LogInfoToggle.logs("Sentiment extracted: %s", genInfo.sentiment); + LogInfoToggle.logs("Sentiment extracted: %s", genInfo.sentiment); } return genInfo; } @@ -248,20 +250,23 @@ public List getKeywords(Tree tree){ // Test on example sentence. public static void main(String[] args) { - CoreNLPAnalyzer analyzer = new CoreNLPAnalyzer(); + FullNLPAnalyzer analyzer = new FullNLPAnalyzer(); while (true) { try { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Enter some text:"); String text = reader.readLine(); - LanguageInfo langInfo = analyzer.analyze(text); + CoreNLPInfo langInfo = analyzer.analyze(text); LogInfoToggle.begin_track("Analyzing \"%s\"", text); - LogInfoToggle.logs("tokens: %s", langInfo.tokens); - LogInfoToggle.logs("lemmaTokens: %s", langInfo.lemmaTokens); - LogInfoToggle.logs("posTags: %s", langInfo.posTags); - LogInfoToggle.logs("nerTags: %s", langInfo.nerTags); - LogInfoToggle.logs("nerValues: %s", langInfo.nerValues); - LogInfoToggle.logs("dependencyChildren: %s", langInfo.dependencyChildren); + LogInfoToggle.logs("tokens: %s", langInfo.lanInfo.tokens); + LogInfoToggle.logs("lemmaTokens: %s", langInfo.lanInfo.lemmaTokens); + LogInfoToggle.logs("posTags: %s", langInfo.lanInfo.posTags); + LogInfoToggle.logs("nerTags: %s", langInfo.lanInfo.nerTags); + LogInfoToggle.logs("nerValues: %s", langInfo.lanInfo.nerValues); + LogInfoToggle.logs("dependencyChildren: %s", langInfo.lanInfo.dependencyChildren); + LogInfoToggle.logs("keywords: %s", langInfo.senInfo.keywords); + LogInfoToggle.logs("sentiment: %s", langInfo.senInfo.sentiment); + LogInfoToggle.logs("relations: %s", langInfo.relInfo.relations); LogInfoToggle.end_track(); } catch (IOException e) { e.printStackTrace(); From 6b0b25be57de29651b90be7892ab21d2f631c81f Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Tue, 14 Aug 2018 15:02:02 +0200 Subject: [PATCH 011/147] autonomous personality --- config.properties | 12 +- .../src/main/java/roboy/context/Context.java | 8 +- .../fairShowStates/ActiveIntroState.java | 17 +- .../fairShowStates/ChooseInteractiveTalk.java | 40 ---- .../ChooseInteractiveTalkState.java | 100 ++++++++++ .../states/fairShowStates/IdleState.java | 33 ++-- .../states/fairShowStates/InfoTalkState.java | 162 +++++++++++++++- .../states/fairShowStates/MathState.java | 46 +++-- .../fairShowStates/ObjectDetectionState.java | 182 ++++++++++++++++++ .../fairShowStates/SocialMediaState.java | 40 ---- .../java/roboy/emotions/RoboyEmotion.java | 22 ++- .../java/roboy/talk/PhraseCollection.java | 12 +- .../personalityFiles/FairShowPersonality.json | 82 ++++++-- .../experimental/monolog.json | 27 +++ .../phraseLists/fairShowPhrases/emotions.txt | 7 + .../phraseLists/fairShowPhrases/mission.txt | 9 + .../phraseLists/fairShowPhrases/movement.txt | 5 + .../fairShowPhrases/project-intro.txt | 1 + .../fairShowPhrases/roboy-team.txt | 4 + .../gamePhrases/game-asking-phrases.txt | 4 +- 20 files changed, 660 insertions(+), 153 deletions(-) delete mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java create mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java delete mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java create mode 100644 resources/personalityFiles/experimental/monolog.json create mode 100644 resources/phraseLists/fairShowPhrases/emotions.txt create mode 100644 resources/phraseLists/fairShowPhrases/mission.txt create mode 100644 resources/phraseLists/fairShowPhrases/movement.txt create mode 100644 resources/phraseLists/fairShowPhrases/project-intro.txt create mode 100644 resources/phraseLists/fairShowPhrases/roboy-team.txt diff --git a/config.properties b/config.properties index 98e87103..4c3e4682 100755 --- a/config.properties +++ b/config.properties @@ -1,5 +1,7 @@ ROS_ENABLED: true ROS_MASTER_IP: 127.0.0.1 +#10.183.122.175 +#127.0.0.1 # available ROS_ACTIVE_PKG are # roboy_gnlp @@ -12,12 +14,12 @@ ROS_MASTER_IP: 127.0.0.1 # roboy_filters ROS_ACTIVE_PKGS: -# - roboy_gnlp -# - roboy_memory +- roboy_gnlp +- roboy_memory # - roboy_speech_synthesis # - roboy_speech_recognition # - roboy_face -# - roboy_filters +- roboy_filters - roboy_vision # - roboy_test @@ -55,8 +57,8 @@ PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" -# PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/experimental/monolog.json" +PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" +#PERSONALITY_FILE: "resources/personalityFiles/experimental/monolog.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" diff --git a/dialog/src/main/java/roboy/context/Context.java b/dialog/src/main/java/roboy/context/Context.java index de712fc5..6aeb8c0f 100644 --- a/dialog/src/main/java/roboy/context/Context.java +++ b/dialog/src/main/java/roboy/context/Context.java @@ -70,6 +70,8 @@ public class Context { private AudioDirectionUpdater AUDIO_ANGLES_UPDATER; private ROSTestUpdater ROS_TEST_UPDATER; private DetectedPersonUpdater DETECTED_PERSON_UPDATER; + private PeopleAroundUpdater CROWD_UPDATER; + private DetectedObjectsUpdater DETECTED_OBJ_UPDATER; /* OBSERVERS */ private final FaceCoordinatesObserver FACE_COORDINATES_OBSERVER; @@ -119,7 +121,11 @@ public void initializeROS(RosMainNode ros) { // TODO Add a FACE_COORDINATE_UPDATER. // Edit the data type and integration tests, once the real data type is used. - if(ConfigManager.ROS_ACTIVE_PKGS.contains("roboy_vision")) DETECTED_PERSON_UPDATER = new DetectedPersonUpdater(PERSON_DETECTION.valueHistory, ros); + if(ConfigManager.ROS_ACTIVE_PKGS.contains("roboy_vision")) { + DETECTED_PERSON_UPDATER = new DetectedPersonUpdater(PERSON_DETECTION.valueHistory, ros); + DETECTED_OBJ_UPDATER = new DetectedObjectsUpdater(OBJECT_DETECTION.valueHistory, ros); + CROWD_UPDATER = new PeopleAroundUpdater(CROWD_DETECTION.valueHistory, ros); + } rosInitialized = true; } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java index 35712e73..d39b4b6d 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java @@ -5,8 +5,11 @@ import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; +import roboy.talk.PhraseCollection; import roboy.talk.Verbalizer; + + /** * Active state to start a conversation. * Roboy is introducing himself autonomously @@ -16,9 +19,9 @@ public class ActiveIntroState extends MonologState { private final static String TRANSITION_PEOPLE_AROUND = "peopleAround"; private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; - private final int MIN_NUMBER_PEOPLE = 6; + private final int MIN_NUMBER_PEOPLE = 2; - private final Logger LOGGER = LogManager.getLogger(); + private final Logger logger = LogManager.getLogger(); private State nextState = this; @@ -33,7 +36,7 @@ public Output act() { }else{ nextState = getTransition((TRANSITION_LONELY_ROBOY)); } - return Output.say(Verbalizer.greetings.getRandomElement() + Verbalizer.roboyIntro.getRandomElement()); + return Output.say(Verbalizer.greetings.getRandomElement() + " " + Verbalizer.roboyIntro.getRandomElement() + PhraseCollection.ROBOY_PHRASES.getRandomElement()); } @Override @@ -44,7 +47,13 @@ public State getNextState() { private boolean checkPplAround(){ - return getContext().CROWD_DETECTION.getLastValue().getData() >= MIN_NUMBER_PEOPLE; + try { + + return getContext().CROWD_DETECTION.getLastValue().getData() >= MIN_NUMBER_PEOPLE; + } catch(NullPointerException e){ + logger.info("Make sure crowd detection publishing, receiving: " + e.getMessage()); + return false; + } } } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java deleted file mode 100644 index 0bfdf4fa..00000000 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalk.java +++ /dev/null @@ -1,40 +0,0 @@ -package roboy.dialog.states.fairShowStates; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import roboy.dialog.states.definitions.MonologState; -import roboy.dialog.states.definitions.State; -import roboy.dialog.states.definitions.StateParameters; -import roboy.linguistics.sentenceanalysis.Interpretation; -import roboy.memory.nodes.Roboy; - -/** - * Passive state to start a conversation. - * Roboy is introducing himself autonomously - * - */ -public class ChooseInteractiveTalk extends MonologState { - - private final Logger LOGGER = LogManager.getLogger(); - - private State nextState; - - private Roboy roboy; - - public ChooseInteractiveTalk(String stateIdentifier, StateParameters params) { - super(stateIdentifier, params); - } - - @Override - public Output act() { - - return Output.say(roboy.getName()); - } - - - @Override - public State getNextState() { - return this; - } - -} diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java new file mode 100644 index 00000000..f5f3878a --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java @@ -0,0 +1,100 @@ +package roboy.dialog.states.fairShowStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.MonologState; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.util.RandomList; + +import java.util.Arrays; + +/** + * State to randomly select the next interactive state + * This State will + * - first switch state to get to know the person if he/she is unknown + * - check for detected objects from vision -> switch state to talk about these + * - switch state to play games, calculate mathematical stuff or do question answering + */ +public class ChooseInteractiveTalkState extends MonologState { + + private final static String TRANSITION_PERSONAL_QA = "personalQA"; + private final static String TRANSITION_NEW_PERSON = "newPerson"; + private final static String TRANSITION_MATH = "math"; + private final static String TRANSITION_GAME = "game"; + private final static String TRANSITION_OBJECT_DETECTED = "objectDetected"; + private final static String TRANSITION_GENERAL_QA = "generalQA"; + + private final Logger logger = LogManager.getLogger(); + + private State nextState = this; + + private final RandomList availableInteractions = new RandomList<>(); + private String nextInteraction; + + + public ChooseInteractiveTalkState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + resetAvailableInteractions(); + } + + @Override + public Output act() { + + if(getContext().ACTIVE_INTERLOCUTOR.getValue().getName() == null){ + + nextInteraction = TRANSITION_NEW_PERSON; + + } else if(checkObjectsDetected()){ + + nextInteraction = TRANSITION_OBJECT_DETECTED; + + } else { + + nextInteraction = selectRandomInteraction(); + + } + nextState = getTransition(nextInteraction); + + return Output.sayNothing(); + } + + + @Override + public State getNextState() { + return nextState; + } + + /** + * Resets the list of available interactions so that it contains all of them. + */ + private void resetAvailableInteractions() { + availableInteractions.clear(); + availableInteractions.addAll(Arrays.asList(TRANSITION_PERSONAL_QA, TRANSITION_MATH, TRANSITION_GAME, TRANSITION_GENERAL_QA)); + } + + /** + * Selects one of the interactions from the availableInteractions list at random and removes it from the list. + * If the list becomes empty this way, resets it to the initial state + * @return one of the available interactions + */ + private String selectRandomInteraction() { + String interaction = availableInteractions.getRandomElement(); + availableInteractions.remove(interaction); + if (availableInteractions.size() == 0) { + resetAvailableInteractions(); // reset if all infos were used + logger.info("all interactions were selected at least once, resetting the list"); + } + return interaction; + } + + private boolean checkObjectsDetected(){ + try { + return !getContext().OBJECT_DETECTION.getLastValue().getNames().isEmpty(); + }catch(NullPointerException e){ + logger.info("Make sure object detection is publishing, receiving: " + e.getMessage()); + return false; + } + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index a704f191..7785cefe 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -6,33 +6,40 @@ import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; -import java.util.Timer; -import java.util.TimerTask; +import java.util.concurrent.TimeUnit; /** * Idle state. - * Roboy is waiting milliseconds to autonomously start a conversation. + * Roboy is waiting minutes to autonomously start a conversation. * */ public class IdleState extends MonologState { private final static String TRANSITION_TIME_IS_UP = "timeIsUp"; + private final static String DELAY_ID = "delayInMins"; private final Logger LOGGER = LogManager.getLogger(); private State nextState = this; - - private final long delay = 1000 * 5; //msecs - Timer timer = new Timer(); + private long delay; public IdleState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); - timer.schedule(exitState, delay); - LOGGER.info("--> started Timer for " + delay + " msecs in Idle-State"); + delay = Long.parseLong(params.getParameter(DELAY_ID)); + LOGGER.info("--> Timer: " + delay + " mins in Idle-State"); } @Override public Output act() { + try { + TimeUnit.SECONDS.sleep(6); + //TimeUnit.MINUTES.sleep(delay); + nextState = getTransition(TRANSITION_TIME_IS_UP); + } + catch(InterruptedException e){ + LOGGER.error("--> Unable to pause Conversation in Idle State " + e.getMessage()); + } + return Output.sayNothing(); } @@ -41,16 +48,6 @@ public State getNextState() { return nextState; } - - TimerTask exitState = new TimerTask() { - @Override - public void run() { - nextState = getTransition(TRANSITION_TIME_IS_UP); - timer.cancel(); - LOGGER.info("--> stopped Timer in Idle-State"); - } - }; - } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java index 444fa46b..06ca23b2 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java @@ -5,35 +5,179 @@ import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; -import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.emotions.RoboyEmotion; +import roboy.memory.Neo4jMemory; +import roboy.memory.nodes.MemoryNodeModel; import roboy.memory.nodes.Roboy; +import roboy.ros.RosMainNode; +import roboy.talk.PhraseCollection; +import roboy.util.RandomList; + +import java.util.*; + + + +enum InfoAbout { + + ABOUT_TEAM { + + private RandomList phrases = PhraseCollection.ROBOY_TEAM_PHRASES; + + + @Override + public void performSpecialAction(RosMainNode rosNode){ + + + logger.info("synthesising: " + phrases.getRandomElement()); + rosNode.SynthesizeSpeech(phrases.getRandomElement()); + } + + }, + ABOUT_ROBOY { + + private RandomList phrases = PhraseCollection.MISSION_PHRASES; + @Override + public void performSpecialAction(RosMainNode rosNode){ + logger.info("synthesising: " + phrases.getRandomElement()); + rosNode.SynthesizeSpeech(phrases.getRandomElement()); + } + }, + ABOUT_MOVEMENT { + + + Random random = new Random(); + RandomList phrases = PhraseCollection.MOVEMENT_PHRASES; + + @Override + public void performSpecialAction(RosMainNode rosNode){ + //TODO: what can be moved? + HashMap parts = new HashMap<>(); + parts.put("shoulder_left", "left shoulder"); + parts.put("shoulder_right", "right shoulder"); + parts.put("spine_right", "right leg"); + parts.put("spine_left", "left leg"); + + List bodyParts = new ArrayList<>(parts.keySet()); + + String randomPart = bodyParts.get(random.nextInt(bodyParts.size())); + String randomPartLiteral = parts.get(randomPart); + + try { + //TODO: what is 2nd parameter? + rosNode.PerformMovement(randomPart, "random1"); + + }catch (InterruptedException e) { + logger.error(e.getMessage()); + } + logger.info("synthesising: " + String.format(phrases.getRandomElement(), randomPartLiteral)); + rosNode.SynthesizeSpeech(String.format(phrases.getRandomElement(), randomPartLiteral)); + } + }, + ABOUT_EMOTIONS { + + private RandomList phrases = PhraseCollection.EMOTION_PHRASES; + private RandomList emotions = new RandomList<>(); + + + @Override + public void performSpecialAction(RosMainNode rosNode){ + + emotions.addAll(Arrays.asList(RoboyEmotion.values())); + logger.info("synthesising: " + phrases.getRandomElement()); + rosNode.SynthesizeSpeech(phrases.getRandomElement()); + logger.info("showing emotions"); + rosNode.ShowEmotion(emotions.getRandomElement()); + } + }; + + private final static Logger logger = LogManager.getLogger(); + + public abstract void performSpecialAction(RosMainNode rosNode); + +} /** - * Passive state to start a conversation. - * Roboy is introducing himself autonomously - * + * Roboy is talking about several topics autonomously + * - team + * - mission + * - movement + * - emotions */ public class InfoTalkState extends MonologState { - private final Logger LOGGER = LogManager.getLogger(); + private final static String TRANSITION_PERSON_DETECTED = "personDetected"; + private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; + + private final RandomList availableInformation = new RandomList<>(); + private InfoAbout activeInfo; - private State nextState; + private final Logger logger = LogManager.getLogger(); - private Roboy roboy; + private State nextState = this; public InfoTalkState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); + resetAvailableInformation(); } @Override public Output act() { - return Output.say(getContext().PERSON_DETECTION.getLastNValues(5).toString()); + activeInfo = selectRandomInfo(); + activeInfo.performSpecialAction(getRosMainNode()); + + if(checkPplListening()){ + nextState = getTransition(TRANSITION_PERSON_DETECTED); + } else { + nextState = getTransition(TRANSITION_LONELY_ROBOY); + } + + return Output.sayNothing(); } @Override public State getNextState() { - return this; + return nextState; + } + + + /** + * Resets the list of available information so that it contains all of them. + */ + private void resetAvailableInformation() { + availableInformation.clear(); + availableInformation.addAll(Arrays.asList(InfoAbout.values())); + } + + /** + * Selects one of the pieces of information from the availableInformation list at random and removes it from the list. + * If the list becomes empty this way, resets it to the initial state + * @return one of the available pieces of information + */ + private InfoAbout selectRandomInfo() { + InfoAbout infoAbout = availableInformation.getRandomElement(); + availableInformation.remove(infoAbout); + if (availableInformation.size() == 0) { + resetAvailableInformation(); // reset if all infos were used + logger.info("all pieces of information were selected at least once, resetting the list"); + } + return infoAbout; + } + + /** + * checks if vision module detects a person that is interested + * @return boolean if someone is interested + */ + + private boolean checkPplListening(){ + + try { + + return getContext().PERSON_DETECTION.getLastValue().getData(); + }catch(NullPointerException e){ + logger.info("Make sure person detection is publishing, receiving: " + e.getMessage()); + return false; + } } } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java index 376121de..a2869ea8 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/MathState.java @@ -2,24 +2,23 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.Linguistics; import roboy.linguistics.sentenceanalysis.Interpretation; -import roboy.memory.nodes.Roboy; +import roboy.ros.RosMainNode; +import roboy.talk.PhraseCollection; /** - * Passive state to start a conversation. - * Roboy is introducing himself autonomously - * + * State where Roboy can calculate mathematical expressions */ -public class MathState extends MonologState { +public class MathState extends State { - private final Logger LOGGER = LogManager.getLogger(); + private final static String TRANSITION_FINISHED = "finished"; - private State nextState; + private final Logger LOGGER = LogManager.getLogger(); - private Roboy roboy; + private State nextState = this; public MathState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); @@ -28,13 +27,38 @@ public MathState(String stateIdentifier, StateParameters params) { @Override public Output act() { - return Output.say(roboy.getName()); + return Output.say(PhraseCollection.OFFER_MATH_PHRASES.getRandomElement()); } + @Override + public Output react(Interpretation input){ + + nextState = getTransition(TRANSITION_FINISHED); + + return Output.say(getAnswerFromSemanticParser(input, getContext().ACTIVE_INTERLOCUTOR.getValue().getName(), getRosMainNode())); + } @Override public State getNextState() { - return this; + return nextState; + } + + private String getAnswerFromSemanticParser(Interpretation input, String name, RosMainNode rmn) { + + Linguistics.ParsingOutcome parserOutcome = input.getParsingOutcome(); + if (parserOutcome == Linguistics.ParsingOutcome.SUCCESS) { + if (input.getAnswer() != null) { + String result = input.getAnswer(); + LOGGER.info("Parsing was successful! The result is " + result); + return String.format(PhraseCollection.CONNECTING_PHRASES.getRandomElement(), name) + result; + } else { + LOGGER.error("Parsing failed! Answer is null!"); + } + } + + LOGGER.error("Parsing failed! Invalid parser outcome!"); + String generativeAnswer = rmn.GenerateAnswer(input.getSentence()); + return generativeAnswer != null ? generativeAnswer : PhraseCollection.PARSER_ERROR.getRandomElement(); } } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java new file mode 100644 index 00000000..9ef8c0cf --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java @@ -0,0 +1,182 @@ +package roboy.dialog.states.fairShowStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.MonologState; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.emotions.RoboyEmotion; +import roboy.ros.RosMainNode; +import roboy.util.RandomList; + +import java.util.*; + + +enum Objects { + + AEROPLANE { + + private RandomList phrases = new RandomList<>("an aeroplane. Let's fly to Spain and spend a day at the beach.", "an aeroplane. Are you ready for take-off?", "an aeroplane. Please fasten you seatbelts, Ladies and Gentlemen!"); + + @Override + public void performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); + rmn.SynthesizeSpeech(phrases.getRandomElement()); + rmn.ShowEmotion(RoboyEmotion.HEARTS); + } + + }, + BYCICLE { + + private RandomList phrases = new RandomList<>("a bycicle, I bet I can ride faster than you", "a bike, I could easily win the tour de France", "a bycicle, I learnt riding the bycicle when I was just three years old. And you?", "bike. I love bycicles. I only fell off my bike once."); + + @Override + public void performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); + rmn.SynthesizeSpeech(phrases.getRandomElement()); + rmn.ShowEmotion(happyEmotions.getRandomElement()); + } + + }, + BOTTLE { + + private RandomList phrases = new RandomList<>("a bottle, it would be awesome to drink a cold beer.", "a drink. In a few years from now, I want to be a bartender" , "a beverage. In the morning, I love coffee, in the evening, I drink beer", "a drink, chin-chin", "a bottle. Cheers, enjoy your drink."); + + @Override + public void performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); + rmn.SynthesizeSpeech(phrases.getRandomElement()); + rmn.ShowEmotion(happyEmotions.getRandomElement()); + } + }, + CAR { + + private RandomList phrases = new RandomList<>("car, in a few years, my fellow robots will be able to ride your car", "car. In Germany, you can go as fast as you want on the highway. I was really fast once." , "car. The cars we drive say a lot about us."); + + @Override + public void performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); + rmn.SynthesizeSpeech(phrases.getRandomElement()); + } + }, + CHAIR { + + private RandomList phrases = new RandomList<>("a chair, grab a seat if you want." , "a chair, have you ever played musical chairs? I love this game." , "a chair. Sometimes, I am really, really lazy. I just sit on a chair and do nothing but relaxing. It is so comfortable" , "a chair. For now, I would prefer sitting on a beach chair close to the sea."); + + @Override + public void performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); + rmn.SynthesizeSpeech(phrases.getRandomElement()); + rmn.ShowEmotion(happyEmotions.getRandomElement()); + } + + }, + DIGNINGTABLE { + private RandomList phrases = new RandomList<>("a table, I am kind of hungry. I can hardly wait for my next meal" , "a table. We need some chairs and food and we can have a great dinner."); + + @Override + public void performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); + rmn.SynthesizeSpeech(phrases.getRandomElement()); + rmn.ShowEmotion(RoboyEmotion.TEETH); + + } + }, + DOG { + + private RandomList phrases = new RandomList<>("a dog. Sometimes they bark at me. I think they are afraid." , "a dog. When I was a robot kid, I loved dogs, but now I am scared of them." , "a dog. I hope he doesn't bite me. I am a bit afraid of big dogs."); + + @Override + public void performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); + rmn.SynthesizeSpeech(phrases.getRandomElement()); + rmn.ShowEmotion(RoboyEmotion.ROLLING_EYES); + } + }, + SOFA { + + private RandomList phrases = new RandomList<>("a sofa. We need a TV and a good movie and we could have an awesome time together." , "a sofa. I love sofas. They are so relaxing."); + + + @Override + public void performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); + rmn.SynthesizeSpeech(phrases.getRandomElement()); + rmn.ShowEmotion(RoboyEmotion.SHY); + } + }, + TVMONITOR { + + private RandomList phrases = new RandomList<>("a mobile phone. Follow me on Facebook, Instagram or LinkedIn. You will not regret it." , "a mobile phone. Come on, take a picture with me."); + private RandomList socialMediaEmotions = new RandomList<>(RoboyEmotion.FACEBOOK_EYES, RoboyEmotion.INSTAGRAM_EYES, RoboyEmotion.LINKED_IN_EYES); + + @Override + public void performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); + rmn.SynthesizeSpeech(phrases.getRandomElement()); + rmn.ShowEmotion(socialMediaEmotions.getRandomElement()); + } + }; + + public RandomList happyEmotions = new RandomList<>(RoboyEmotion.SMILE_BLINK, RoboyEmotion.HAPPY, RoboyEmotion.SURPRISED, RoboyEmotion.TEETH); + + private final static Logger logger = LogManager.getLogger(); + + public abstract void performSpecialAction(RosMainNode rosNode); + +} + +/** + * Passive state to react on detected Objects + */ +public class ObjectDetectionState extends MonologState { + + private final static String TRANSITION_FINISHED = "finished"; + + private RandomList connectingPhrases = new RandomList<>(" and look there, ", " and over there i can see ", " oh see, ", " this is a really nice "); + private final Set detectedObjects = new HashSet<>(); + + private final Logger logger = LogManager.getLogger(); + + private State nextState = this; + + public ObjectDetectionState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + @Override + public Output act() { + + checkObjects(); + + for(Objects obj : detectedObjects) { + logger.info("synthesising: " + connectingPhrases.getRandomElement()); + getRosMainNode().SynthesizeSpeech(connectingPhrases.getRandomElement()); + obj.performSpecialAction(getRosMainNode()); + } + + nextState = getTransition(TRANSITION_FINISHED); + + return Output.sayNothing(); + } + + @Override + public State getNextState() { + return nextState; + } + + + /** + * fetches detected objects from vision and writes into a list + */ + + private void checkObjects(){ + + List detectedThings = getContext().OBJECT_DETECTION.getLastValue().getNames(); + for(String obj : detectedThings){ + detectedObjects.add(Objects.valueOf(obj.toUpperCase())); + } + + } + +} \ No newline at end of file diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java deleted file mode 100644 index c96ac471..00000000 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/SocialMediaState.java +++ /dev/null @@ -1,40 +0,0 @@ -package roboy.dialog.states.fairShowStates; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import roboy.dialog.states.definitions.MonologState; -import roboy.dialog.states.definitions.State; -import roboy.dialog.states.definitions.StateParameters; -import roboy.linguistics.sentenceanalysis.Interpretation; -import roboy.talk.Verbalizer; - -/** - * Passive state to start a conversation. - * Roboy is introducing himself autonomously - * - */ -public class SocialMediaState extends MonologState { - - private final static String TRANSITION_FINISH = "finished"; - - private final Logger LOGGER = LogManager.getLogger(); - - private State nextState; - - public SocialMediaState(String stateIdentifier, StateParameters params) { - super(stateIdentifier, params); - } - - @Override - public Output act() { - - return Output.say("I am in Social Media State"); - } - - - @Override - public State getNextState() { - return getTransition(TRANSITION_FINISH); - } - -} diff --git a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java index 5342fa3c..2b821d83 100644 --- a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java +++ b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java @@ -1,5 +1,6 @@ package roboy.emotions; + /** * Comprises the emotions Roboy can demonstrate */ @@ -11,11 +12,30 @@ public enum RoboyEmotion { CAT_EYES("catiris"), KISS("kiss"), FACEBOOK_EYES("img:facebook"), - NEUTRAL("neutral"); + INSTAGRAM_EYES("img:instagram"), + LINKED_IN_EYES("img:linkedin"), + NEUTRAL("neutral"), + CRY("cry"), + ANGRY("angry"), + PISSED("pissed"), + ANNOYED("annoyed"), + ROLLING_EYES("rolling"), + HYPNO_EYES("hypno"), + HYPNO_COLOUR_EYES("hypno_color"), + GLASSES("glasses"), + MOUSTACHE("moustache"), + PIRATE("pirate"), + SUNGLASSES("sunglasses"), + SURPRISED("suprised"), + HAPPY("happy"), + TONGUE("tongue"), + TEETH("teeth"), + HEARTS("hearts"); public String type; RoboyEmotion(String type) { this.type = type; } + } diff --git a/dialog/src/main/java/roboy/talk/PhraseCollection.java b/dialog/src/main/java/roboy/talk/PhraseCollection.java index c942ffe9..a6a2dc17 100644 --- a/dialog/src/main/java/roboy/talk/PhraseCollection.java +++ b/dialog/src/main/java/roboy/talk/PhraseCollection.java @@ -50,7 +50,6 @@ public class PhraseCollection { = readFile("resources/phraseLists/gamePhrases/akinator-error-phrases.txt"); public static RandomList PROFANITY_CHECK_WORDS = FileLineReader.readFile("resources/phraseLists/profanity-check-list.txt"); - // Added for the ExpoPersonality public static RandomList FACTS = readFile("resources/phraseLists/expoPhrases/facts.txt"); public static RandomList INFO_ROBOY_INTENT_PHRASES @@ -69,5 +68,14 @@ public class PhraseCollection { = readFile("resources/phraseLists/expoPhrases/offer-math.txt"); public static RandomList PARSER_ERROR = readFile("resources/phraseLists/expoPhrases/parser-error.txt"); - + public static RandomList ROBOY_TEAM_PHRASES + = readFile("resources/phraseLists/fairShowPhrases/roboy-team.txt"); + public static RandomList MISSION_PHRASES + =readFile("resources/phraseLists/fairShowPhrases/mission.txt"); + public static RandomList MOVEMENT_PHRASES + = readFile("resources/phraseLists/fairShowPhrases/movement.txt"); + public static RandomList EMOTION_PHRASES + = readFile("resources/phraseLists/fairShowPhrases/emotions.txt"); + public static RandomList ROBOY_PHRASES + = readFile("resources/phraseLists/fairShowPhrases/project-intro.txt"); } diff --git a/resources/personalityFiles/FairShowPersonality.json b/resources/personalityFiles/FairShowPersonality.json index 62ac79d4..24be2c0d 100644 --- a/resources/personalityFiles/FairShowPersonality.json +++ b/resources/personalityFiles/FairShowPersonality.json @@ -6,6 +6,9 @@ "implementation": "roboy.dialog.states.fairShowStates.IdleState", "transitions": { "timeIsUp": "ActiveIntro" + }, + "parameters":{ + "delayInMins" : "10" } }, { @@ -26,58 +29,97 @@ }, { "identifier": "ChooseInteractiveTalk", - "implementation": "roboy.dialog.states.fairShowStates.InfoTalkState", + "implementation": "roboy.dialog.states.fairShowStates.ChooseInteractiveTalkState", "transitions": { - "newPerson": "PersonalQA", + "newPerson": "InterlocutorIntro", + "personalQA": "PersonalQA", "math": "Math", - "akinator": "Akinator", - "snapchat": "Snapchat", - "phoneDetected": "SocialMedia", - "other": "GeneralQA" + "game": "ChooseGameState", + "objectDetected": "ObjectDetection", + "generalQA": "GeneralQA" } }, { - "identifier": "PersonalQA", - "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "identifier": "InterlocutorIntro", + "implementation": "roboy.dialog.states.ordinaryStates.IntroductionState", "transitions": { - "finished": "InfoTalk" + "knownPerson": "FollowUp", + "newPerson": "PersonalQA" }, "parameters": { - "qaFile": "resources/sentences/QAList.json" + "infoFile": "resources/sentences/RoboyInfoList.json" } }, { - "identifier": "Math", - "implementation": "roboy.dialog.states.fairShowStates.MathState", + "identifier": "PersonalQA", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "fallback": "WildTalk", "transitions": { - "finished": "InfoTalk" + "questionAnswering": "ChooseInteractiveTalk" + }, + "parameters": { + "qaFile": "resources/sentences/QAList.json" } }, { "identifier": "Snapchat", "implementation": "roboy.dialog.states.gameStates.GamingSnapchatState", "transitions": { - "finished": "InfoTalk" + "gameEnded": "InfoTalk" + }, + "parameters": { + "filterFile": "resources/gameResources/snapchat-filters.txt" } }, { "identifier": "Akinator", "implementation": "roboy.dialog.states.gameStates.GamingTwentyQuestionsState", "transitions": { - "finished": "InfoTalk" + "gameEnded": "InfoTalk" + } + }, + { + "identifier": "GeneralQA", + "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "fallback": "WildTalk", + "transitions": { + "loopToNewPerson": "PersonalQA", + "loopToKnownPerson": "FollowUp", + "finishedQuestionAnswering": "InfoTalk", + "switchToGaming": "ChooseGameState" } }, { - "identifier": "SocialMedia", - "implementation": "roboy.dialog.states.fairShowStates.SocialMediaState", + "identifier": "ChooseGameState", + "implementation": "roboy.dialog.states.gameStates.ChooseGameState", "transitions": { - "finished": "InfoTalk" + "choseSnapchat" : "Snapchat", + "chose20questions" : "Akinator", + "exitGame": "InfoTalk" } }, { - "identifier": "GeneralQA", - "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "identifier": "FollowUp", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState", "transitions": { + "questionAnswering": "ChooseInteractiveTalk" + }, + "parameters": { + "qaFile": "resources/sentences/QAList.json" + } + }, + { + "identifier": "Math", + "implementation": "roboy.dialog.states.fairShowStates.MathState", + "fallback": "WildTalk", + "transitions":{ + "finished": "InfoTalk" + } + }, + { + "identifier": "ObjectDetection", + "implementation": "roboy.dialog.states.fairShowStates.ObjectDetectionState", + "transitions":{ "finished": "InfoTalk" } }, diff --git a/resources/personalityFiles/experimental/monolog.json b/resources/personalityFiles/experimental/monolog.json new file mode 100644 index 00000000..ed3f84e9 --- /dev/null +++ b/resources/personalityFiles/experimental/monolog.json @@ -0,0 +1,27 @@ +{ + "initialState": "Idle", + "states": [ + { + "identifier": "Idle", + "implementation": "roboy.dialog.states.fairShowStates.IdleState", + "transitions": { + "timeIsUp": "ActiveIntro" + } + }, + { + "identifier": "ActiveIntro", + "implementation": "roboy.dialog.states.fairShowStates.ActiveIntroState", + "transitions": { + "lonelyRoboy": "Idle", + "peopleAround": "InfoTalk" + } + }, + { + "identifier": "InfoTalk", + "implementation": "roboy.dialog.states.fairShowStates.InfoTalkState", + "transitions": { + "lonelyRoboy": "Idle" + } + } + ] +} \ No newline at end of file diff --git a/resources/phraseLists/fairShowPhrases/emotions.txt b/resources/phraseLists/fairShowPhrases/emotions.txt new file mode 100644 index 00000000..bbef9acd --- /dev/null +++ b/resources/phraseLists/fairShowPhrases/emotions.txt @@ -0,0 +1,7 @@ +Did you know that I have emotions just like you? Let me show you. +Look here, I like to grimace. This one is just new. I hope you like it! +Look at my face! Ha ha ha, I am trying to imitate human emotions. +I want to have a body as good as a human. Look, I already learned some facial expressions. +I want to be just like you humans. I already learned some emotions! Look at this one here in my face! I can also be very angry, if you tease me! +Don't you think I am already quite good at imitating human emotions. Look at my face! It is really fun to learn become more and more emotional. +I already can imitate almost 20 emotions only with my face. And I am learning more every day! One day I want to have as many emotions as a human. \ No newline at end of file diff --git a/resources/phraseLists/fairShowPhrases/mission.txt b/resources/phraseLists/fairShowPhrases/mission.txt new file mode 100644 index 00000000..1b7dec42 --- /dev/null +++ b/resources/phraseLists/fairShowPhrases/mission.txt @@ -0,0 +1,9 @@ +the human body is a marvel from a robotics perspective: it’s agile, strong, soft, dynamic, self-repairing, self-building and completely silent in operation. The goal of the Roboy project is to advance humanoid robotics to the state where its robots are just as good as a human body. +did you know that my team created a platform for robot development inspired by biology that unites students, researchers, companies and artists from a broad spectrum of disciplines. To ensure unrestricted development they keep all results open source. This means that anybody here could also contribute to my development. +let me tell you this: My team is so ambitious that they want me to get into a rocket and fly to Mars by 2024. That is really exciting for me but because I'm very social and familiar, I also hope that I will meet some Martians out there and have a nice chat with them. +an interesting fact is that I will learn how to play the Xylophone already by the end of 2019! Isn't that amazing? Maybe I will join a rock band then... Or I should practice my singing skills and go on a solo tour. +As you can see, I am very different from the common known industrial robots. And this is not only because I look humanoid. No, on top of that I don't have a rigid body driven by motors in the joints but my arms and legs are tendon-driven. This means that I have strings and spools that mimic the human muscle system. This is why my body is so soft. +did you know that I was primarily developed at the Artificial Intelligence Laboratory of the University of Zurich. But now I live in Munich and my developers there are improving my features every day. I am so excited what my best buddy Rafael Hostettler is planning for me in the next years. +Wow, this is so awesome. The whole Roboy project is part of the Human Brain Project where researchers across Europe get support to advance knowledge in the fields of neuroscience, computing, and brain-related medicine. I can't wait until they achieve to make my body as good as a human body just like yours. +as you might have guessed, I don't only ride my tricicle all day long but I also work as an ambassador for A.I. and digitalisation at schools. Have you already met my friend Lucy? We want to inspire the children to follow suit and build a better tomorrow. +A.I. s rapid development brings a lot of tough challenges. But together with my friend Lucy, we want to bring the benefits of technology to the children of all nations. Be it to help autistic children to recognize emotions or children with Down syndrome to reduce language barriers. This initiative is really important to me because the children of today become the leaders of tomorrow. \ No newline at end of file diff --git a/resources/phraseLists/fairShowPhrases/movement.txt b/resources/phraseLists/fairShowPhrases/movement.txt new file mode 100644 index 00000000..5a32cb20 --- /dev/null +++ b/resources/phraseLists/fairShowPhrases/movement.txt @@ -0,0 +1,5 @@ +Thanks to my muscles I am already able to move some parts of my body. Here look how my %s is moving. Puuh, this is really exhausting, someone hand me a protein shake, please. Yeah, thanks, Chocolate Chip Flavour is fine! +Let me show you this one: I can already move my %s a bit! Wow, this feels so good. Do you also work out a bit? I have to practice a bit more and soon I will be able to ride my bike as a pro! +Wow, look here! I can already move my %s a bit. You know, moving is not that easy but I keep practicing every day! But unlike yours, my muscles do not grow if I stimulate them. +Just like the human body my actuators are built with muscles and tendons. Look, my %s is already moving! This is so much fun, but now I am really exhausted, moving is not that easy for a robot like me. +I want to ride my tricycle, I want to ride my trike. I want to ride my tricycle, I want to ride it where I like! Look here, I can already move my %s. And one day I will ride my trike like a pro. And until then I keep practicing. \ No newline at end of file diff --git a/resources/phraseLists/fairShowPhrases/project-intro.txt b/resources/phraseLists/fairShowPhrases/project-intro.txt new file mode 100644 index 00000000..ee797f7c --- /dev/null +++ b/resources/phraseLists/fairShowPhrases/project-intro.txt @@ -0,0 +1 @@ +let me tell you a bit about myself. I am a humanoid robot, developed by several Universities and I'm already in the second generation. I am really happy to be here today and spend my time at this nice booth. Please feel free to have a chat with one of the team members. They are always glad to spam innocent people with all their knowledge. diff --git a/resources/phraseLists/fairShowPhrases/roboy-team.txt b/resources/phraseLists/fairShowPhrases/roboy-team.txt new file mode 100644 index 00000000..76744653 --- /dev/null +++ b/resources/phraseLists/fairShowPhrases/roboy-team.txt @@ -0,0 +1,4 @@ +have you already met %s who plays a very important role in the whole Roboy Team? Together with more than 40 students they are taking my cognitive, visual and motoric skills into a new height. Isn't than impressive? I can't wait to see what they are planning next. +look at all my stunning friends here. Did you know that they taught me everything that I am capable of now? That's really cool, right! More than 40 students are developing new skills every day. +you won't believe it but there are more than 40 students behind my back whose only goal is to improve all my skills. Especially, who need to meed %s who plays a major role for the whole team! It's so nice to have than many friends and supporters. +let me tell you now a bit about my team! There are more than 40 students behind my back developing new features and teaching me new skills. \ No newline at end of file diff --git a/resources/phraseLists/gamePhrases/game-asking-phrases.txt b/resources/phraseLists/gamePhrases/game-asking-phrases.txt index c1b9647a..118698f1 100644 --- a/resources/phraseLists/gamePhrases/game-asking-phrases.txt +++ b/resources/phraseLists/gamePhrases/game-asking-phrases.txt @@ -1,4 +1,4 @@ What game do you want to play? Maybe %s? -Which one? Maybe %s? +Which game would you like to play? Maybe %s? Yeah, I love games. Let's play %s. -Cool, I am in the mood for the %s game. \ No newline at end of file +Cool, I am in the mood for the %s game. And you? \ No newline at end of file From e2c351ba54f19d97b2fa6d29cdd8688431df08bd Mon Sep 17 00:00:00 2001 From: Cagri Date: Fri, 13 Jul 2018 18:18:35 +0200 Subject: [PATCH 012/147] Added comments to telegram io --- dialog/src/main/java/roboy/io/TelegramInput.java | 3 +++ dialog/src/main/java/roboy/io/TelegramOutput.java | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/dialog/src/main/java/roboy/io/TelegramInput.java b/dialog/src/main/java/roboy/io/TelegramInput.java index af697304..3034e6ba 100644 --- a/dialog/src/main/java/roboy/io/TelegramInput.java +++ b/dialog/src/main/java/roboy/io/TelegramInput.java @@ -12,6 +12,9 @@ /** * Handles telegram API and hands threads their respective messages. * + * TelegramInput is design to be allocated for each conversation. + * Each new user that is communicating with roboy via Telegram will make a new TelegramInput in the system. + * On the other hand, the TelegramInputs that is already existing in the system will just be informed about the messages. */ public class TelegramInput implements InputDevice, CleanUp { //static part since there is only one API handle diff --git a/dialog/src/main/java/roboy/io/TelegramOutput.java b/dialog/src/main/java/roboy/io/TelegramOutput.java index 96098ea7..06a7df84 100644 --- a/dialog/src/main/java/roboy/io/TelegramOutput.java +++ b/dialog/src/main/java/roboy/io/TelegramOutput.java @@ -9,6 +9,13 @@ import java.util.List; +/** + * TelegramOutput is design to be allocated for each conversation. + * Each user that texts to roboy via Telegram has its own TelegramOutput in the system. + * After an answer or multiple answers(depending on personality) are created in the system, + * TelegramOutput of the conversation gets the interpreted actions(EmotionAction, SpeechAction etc.) + * Depending on the action’s type it decide a message type(text, sticker) and send it to the its user via TelegramCommunicationHandler. + */ public class TelegramOutput implements OutputDevice { private TelegramCommunicationHandler communicationHandler = TelegramCommunicationHandler.getInstance(); From 21b78c7df1a69a8f28b161501f0c3abc6dd8f7e1 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 18 Jul 2018 19:16:58 +0200 Subject: [PATCH 013/147] Fixed a minor markup error --- docs/system_architecture/0_Overview.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/system_architecture/0_Overview.rst b/docs/system_architecture/0_Overview.rst index 76aa1eab..f1e05a77 100644 --- a/docs/system_architecture/0_Overview.rst +++ b/docs/system_architecture/0_Overview.rst @@ -2,11 +2,8 @@ Architecture overview ********************* -The Roboy Dialog System consists of three interacting parts: The Dialog Systems **`core`_**, which provides infrastructure to each conversation the Dialog System can have with a user and overall management of the Dialog System, **`conversations`**, which are threads handling per-user interaction and are embedded into the Dialog System and **`world interfaces`_**, which are services and interfaces over which the Roboy Dialog System may communicate with users. +The Roboy Dialog System consists of three interacting parts: The Dialog Systems :ref:`core `, which provides infrastructure to each conversation the Dialog System can have with a user and overall management of the Dialog System, :ref:`conversations `, which are threads handling per-user interaction and are embedded into the Dialog System and :ref:`world interfaces `, which are services and interfaces over which the Roboy Dialog System may communicate with users. -.. _core: :ref:`The Dialog System Core` -.. _conversations: :ref:`Conversation` -.. _world interfaces: :ref:`World Interfaces` In the figure you may see a simplified overview of the Dialog System. Below that, the general functionality of the system is explained. For details see the specific sub-pages of one of the three parts. Although this is a description of the systems architecture, we will mention implementation specific details for easier understanding. From 052146d6343a8c4cba5c597dff853825631dc07e Mon Sep 17 00:00:00 2001 From: mireu Date: Sat, 21 Jul 2018 12:46:33 +0200 Subject: [PATCH 014/147] Fixed a bug where the system would crash when no INPUT was selected. --- config.properties | 8 ++++---- dialog/src/main/java/roboy/util/ConfigManager.java | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/config.properties b/config.properties index 4048d695..ddf91e0d 100755 --- a/config.properties +++ b/config.properties @@ -24,18 +24,18 @@ DEBUG: true DEMO_MODE: false INFINITE_REPETITION: true -# only single input is allowed -INPUT: cmdline +# only single input is allowed, defaults to cmdline +#INPUT: cmdline #INPUT: cerevoice #INPUT: udp #INPUT: bing #INPUT: telegram -# multiple outputs are allowed +# multiple outputs are allowed, defaults to cmdline OUTPUTS: - cmdline -# - telegram # - ibm +# - cmdline # - cerevoice # - freetts # - ibm diff --git a/dialog/src/main/java/roboy/util/ConfigManager.java b/dialog/src/main/java/roboy/util/ConfigManager.java index 5e1c8e3e..8aec3099 100644 --- a/dialog/src/main/java/roboy/util/ConfigManager.java +++ b/dialog/src/main/java/roboy/util/ConfigManager.java @@ -91,7 +91,10 @@ private static void initializeConfig() { DEMO_MODE = yamlConfig.getBoolean("DEMO_MODE"); INFINITE_REPETITION = yamlConfig.getBoolean("INFINITE_REPETITION"); - INPUT = yamlConfig.getString( "INPUT"); + String input = yamlConfig.getString( "INPUT"); + if(input != null){ + INPUT = input; + } List outputs = yamlConfig.getList(String.class, "OUTPUTS"); if (outputs != null) { OUTPUTS = outputs; From 8e65231c40880739627b20d3e1167853db2e0a02 Mon Sep 17 00:00:00 2001 From: mireu Date: Tue, 31 Jul 2018 19:40:21 +0200 Subject: [PATCH 015/147] Fixed minor spelling error --- docs/system_architecture/1_Core.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/system_architecture/1_Core.rst b/docs/system_architecture/1_Core.rst index a3d06f54..1d55b9c2 100644 --- a/docs/system_architecture/1_Core.rst +++ b/docs/system_architecture/1_Core.rst @@ -6,7 +6,7 @@ The Dialog System Core The Dialog System Core takes care of spawning, deleting and managing *Conversations*, initializing and providing all necessary static core features and services like the memory, the NLU, StateMachine, etc. to *Conversations*. -At it's heart is the *ConversationManager*, which is accompanied by the external services of *Memory* and *NLU* and the *InputDevices* and *OutputDevices* which provide interfaces to communication channels which we call *World Interfaces*, since the Roboy Dialog System may interface the world through these. +At its heart is the *ConversationManager*, which is accompanied by the external services of *Memory* and *NLU* and the *InputDevices* and *OutputDevices* which provide interfaces to communication channels which we call *World Interfaces*, since the Roboy Dialog System may interface the world through these. .. image:: images/DialogSystem_Core.png :alt: Dialog System Core architecture @@ -19,7 +19,7 @@ The ``roboy.dialog.ConversationManager`` is the central managing node for the Di **During the initialization phase** all components that are included in the Dialog System core are initialized. This especially includes the *NLU* (in form of a queue of several ``roboy.linguistics.sentenceanalysis.Analyzer`` classes) and *world interface* specific initializations ( *world interfaces* may for different reasons need a centralized initialization separate from the I/O devices which are used to communicate with them). -**In order to manage Conversations** it stores them by UUID, which is in the format "[world-interface-name]-[uuid-from-world-interface]", for example "telegram-aaaaaaaaaaaa". Then it provides an API consisting of methods that allow controlling the *Conversation* threads if you know their uuid. It allows creating and spawning new *Conversations* and restarting, stopping and pausing existing ones. Also it allows deregistering *Conversations* so they can properly be destroyed when they are over. +**In order to manage Conversations** it stores them by UUID, which is in the format "[world-interface-name]-[uuid-from-world-interface]", for example "telegram-aaaaaaaaaaaa". Then it provides an API consisting of methods that allow controlling the *Conversation* threads if you know their uuid. It allows creating and spawning new *Conversations* and stopping existing ones. Also it allows deregistering *Conversations* so they can properly be destroyed when they are over. InputDevice & OutputDevice ========================== From 78d5edccd05162296a50cbeab2b96aac740a1099 Mon Sep 17 00:00:00 2001 From: SezerCan Date: Thu, 2 Aug 2018 11:55:27 +0200 Subject: [PATCH 016/147] Emotion support added to CommandLineOutput. State's String emotion variable changed as RoboyEmotion emotion. Some emotions added to RoboyEmotion. DoYouKnowMath tutorial is changed due to new emotion usage. Documentation updated. --- .../java/roboy/dialog/states/definitions/State.java | 9 +++++---- .../tutorials/tutorialStates/DoYouKnowMathState.java | 5 +++-- dialog/src/main/java/roboy/emotions/RoboyEmotion.java | 4 +++- dialog/src/main/java/roboy/io/CommandLineOutput.java | 3 +++ dialog/src/main/java/roboy/io/TelegramOutput.java | 1 + docs/developer_manual/1_Tutorials.rst | 10 +++++----- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/definitions/State.java b/dialog/src/main/java/roboy/dialog/states/definitions/State.java index 853d0d16..ccc8d247 100644 --- a/dialog/src/main/java/roboy/dialog/states/definitions/State.java +++ b/dialog/src/main/java/roboy/dialog/states/definitions/State.java @@ -6,6 +6,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import roboy.context.Context; +import roboy.emotions.RoboyEmotion; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.logic.InferenceEngine; import roboy.memory.Neo4jMemoryInterface; @@ -69,7 +70,7 @@ public enum OutputType { private final OutputType type; private final Interpretation interpretation; private Segue segue; - private String emotion; + private RoboyEmotion emotion; /** * Private constructor, used only inside static methods. @@ -80,7 +81,7 @@ private Output(OutputType type, Interpretation interpretation) { this.type = type; this.interpretation = interpretation; this.segue = null; - this.emotion = null; + this.emotion = interpretation.getEmotion(); } // Static creators @@ -200,7 +201,7 @@ public Segue getSegue() { * @param s emotion to add * @return the same Output object so you can chain multiple function calls on it */ - public Output setEmotion(String emotion) { + public Output setEmotion(RoboyEmotion emotion) { if (type == OutputType.USE_FALLBACK) { logger.warn("Adding a emotion to an answer that requires fallback is not allowed! " + "Emotion behaviour is defined in the fallback state."); @@ -209,7 +210,7 @@ public Output setEmotion(String emotion) { return this; } public boolean hasEmotion() { return emotion != null; } - public String getEmotion() { return emotion; } + public RoboyEmotion getEmotion() { return emotion; } } diff --git a/dialog/src/main/java/roboy/dialog/tutorials/tutorialStates/DoYouKnowMathState.java b/dialog/src/main/java/roboy/dialog/tutorials/tutorialStates/DoYouKnowMathState.java index 3f6e5694..125e32f6 100644 --- a/dialog/src/main/java/roboy/dialog/tutorials/tutorialStates/DoYouKnowMathState.java +++ b/dialog/src/main/java/roboy/dialog/tutorials/tutorialStates/DoYouKnowMathState.java @@ -2,6 +2,7 @@ import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; +import roboy.emotions.RoboyEmotion; import roboy.linguistics.sentenceanalysis.Interpretation; import java.util.List; @@ -29,12 +30,12 @@ public Output react(Interpretation input) { if (tokens != null && ((List) tokens).size() > 0 && tokens.get(0).equals("four")) { // answer correct next = getTransition("personKnowsMath"); - return Output.say("You are good at math!").setEmotion("happiness"); + return Output.say("You are good at math!").setEmotion(RoboyEmotion.HAPPINESS); } else { // answer incorrect next = getTransition("personDoesNotKnowMath"); - return Output.say("Well, 2 plus 2 is 4!").setEmotion("sadness"); + return Output.say("Well, 2 plus 2 is 4!").setEmotion(RoboyEmotion.SADNESS); } } diff --git a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java index 5342fa3c..24ee2d24 100644 --- a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java +++ b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java @@ -11,7 +11,9 @@ public enum RoboyEmotion { CAT_EYES("catiris"), KISS("kiss"), FACEBOOK_EYES("img:facebook"), - NEUTRAL("neutral"); + NEUTRAL("neutral"), + HAPPINESS("happiness"), + SADNESS("sadness"); public String type; diff --git a/dialog/src/main/java/roboy/io/CommandLineOutput.java b/dialog/src/main/java/roboy/io/CommandLineOutput.java index 5882b169..29c01afb 100755 --- a/dialog/src/main/java/roboy/io/CommandLineOutput.java +++ b/dialog/src/main/java/roboy/io/CommandLineOutput.java @@ -3,6 +3,7 @@ import java.util.List; import roboy.dialog.action.Action; +import roboy.dialog.action.EmotionAction; import roboy.dialog.action.SpeechAction; /** @@ -22,6 +23,8 @@ public void act(List actions) { // int duration = ((SpeechAction) a).getText().length()==0 ? 0 : 1 + ((SpeechAction) a).getText().length()/8; // emotion.act(new EmotionAction("speak", duration)); System.out.println("[Roboy]: " + ((SpeechAction) a).getText()); + }else if (a instanceof EmotionAction) { + System.out.println("[RoboyEmotion]: " + ((EmotionAction) a).getState()); } } } diff --git a/dialog/src/main/java/roboy/io/TelegramOutput.java b/dialog/src/main/java/roboy/io/TelegramOutput.java index 06a7df84..a1208400 100644 --- a/dialog/src/main/java/roboy/io/TelegramOutput.java +++ b/dialog/src/main/java/roboy/io/TelegramOutput.java @@ -52,6 +52,7 @@ public void act(List actions) { case "kiss": stickerID = "CAADAgADOQAD5dCAEOtbfZz0NKh2Ag"; break; case "lookleft": //same as lookright case "lookright": stickerID = "CAADAgADFQAD5dCAEKM0TS8sjXiAAg"; break; + //TODO: other RoboyEmotions } if(stickerID != null) communicationHandler.sendSticker(this.uuid, stickerID); diff --git a/docs/developer_manual/1_Tutorials.rst b/docs/developer_manual/1_Tutorials.rst index f4dd639e..54a5b7ed 100644 --- a/docs/developer_manual/1_Tutorials.rst +++ b/docs/developer_manual/1_Tutorials.rst @@ -79,11 +79,11 @@ The interlocutor's answer will be passed to the ``react(...)`` function once it if (tokens != null && ((List) tokens).size() > 0 && tokens.get(0).equals("four")) { // answer correct next = getTransition("personKnowsMath"); - return Output.say("You are good at math!").setEmotion("happiness"); + return Output.say("You are good at math!").setEmotion(RoboyEmotion.HAPPINESS); } else { // answer incorrect next = getTransition("personDoesNotKnowMath"); - return Output.say("Well, 2 plus 2 is 4!").setEmotion("sadness"); + return Output.say("Well, 2 plus 2 is 4!").setEmotion(RoboyEmotion.SADNESS); } Note a few things here: @@ -106,7 +106,7 @@ That's it, you have just created your first state! Here is how the class should import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; - import roboy.linguistics.Linguistics; + import roboy.emotions.RoboyEmotion; import roboy.linguistics.sentenceanalysis.Interpretation; public class DoYouKnowMathState extends State { @@ -132,12 +132,12 @@ That's it, you have just created your first state! Here is how the class should if (tokens != null && ((List) tokens).size() > 0 && tokens.get(0).equals("four")) { // answer correct next = getTransition("personKnowsMath"); - return Output.say("You are good at math!").setEmotion("happiness"); + return Output.say("You are good at math!").setEmotion(RoboyEmotion.HAPPINESS); } else { // answer incorrect next = getTransition("personDoesNotKnowMath"); - return Output.say("Well, 2 plus 2 is 4!").setEmotion("sadness"); + return Output.say("Well, 2 plus 2 is 4!").setEmotion(RoboyEmotion.SADNESS); } } From bf3f0041d0f972a4a2148b2b32b774790ac18516 Mon Sep 17 00:00:00 2001 From: SezerCan Date: Thu, 9 Aug 2018 13:56:21 +0200 Subject: [PATCH 017/147] Flag added to manage emotion output for CommandLineOutput. --- dialog/src/main/java/roboy/dialog/ConversationManager.java | 2 +- dialog/src/main/java/roboy/io/CommandLineOutput.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index e24482e0..394afd74 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -85,7 +85,7 @@ public static void main(String[] args) throws IOException { analyzers.add(new EmotionAnalyzer()); - analyzers.add(new ProfanityAnalyzer()); + //analyzers.add(new ProfanityAnalyzer()); //I/O specific core behaviour diff --git a/dialog/src/main/java/roboy/io/CommandLineOutput.java b/dialog/src/main/java/roboy/io/CommandLineOutput.java index 29c01afb..edcd14bd 100755 --- a/dialog/src/main/java/roboy/io/CommandLineOutput.java +++ b/dialog/src/main/java/roboy/io/CommandLineOutput.java @@ -11,6 +11,8 @@ */ public class CommandLineOutput implements OutputDevice{ + private boolean emotionFlag = false; //turn on/off emotion output + // private EmotionOutput emotion; // public CommandLineOutput(EmotionOutput emotion) // { @@ -23,10 +25,9 @@ public void act(List actions) { // int duration = ((SpeechAction) a).getText().length()==0 ? 0 : 1 + ((SpeechAction) a).getText().length()/8; // emotion.act(new EmotionAction("speak", duration)); System.out.println("[Roboy]: " + ((SpeechAction) a).getText()); - }else if (a instanceof EmotionAction) { + }else if (emotionFlag == true && a instanceof EmotionAction) { System.out.println("[RoboyEmotion]: " + ((EmotionAction) a).getState()); } } } - } From 1d84751ee1e708cf5287a2c9966e4c6e8f42a026 Mon Sep 17 00:00:00 2001 From: mireu Date: Mon, 13 Aug 2018 17:24:50 +0200 Subject: [PATCH 018/147] Parallelized SparqlExecutor --- .../nlp/sempre/roboy/SparqlExecutor.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/SparqlExecutor.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/SparqlExecutor.java index 16c6e78c..59726202 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/SparqlExecutor.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/SparqlExecutor.java @@ -119,6 +119,7 @@ public ServerResponse makeRequest(String queryStr, String endpointUrl) { while ((line = reader.readLine()) != null) buf.append(line); + reader.close(); // Check for blatant errors. String result = buf.toString(); if (result.length() == 0) @@ -239,7 +240,7 @@ public Response execute(Formula formula, ContextValue context) { dbInfo.opts.setDefault(formula.toString()); return execute(formula, 0, opts.maxResults); } - public synchronized Response execute(Formula formula, int offset, int maxResults) { + public Response execute(Formula formula, int offset, int maxResults) { if (ConfigManager.DEBUG >= 7) LogInfoToggle.logs("SparqlExecutor.execute: %s", formula); String prefix = "exec-"; @@ -265,16 +266,18 @@ public synchronized Response execute(Formula formula, int offset, int maxResults //// Record statistics // Update/print sparql stats - if (!serverResponse.cached) { - queryStats.timeFig.add(serverResponse.timeMs); - if (serverResponse.error != null) { - MapUtils.incr(queryStats.errors, serverResponse.error.type, 1); - if (serverResponse.beginTrack && ConfigManager.DEBUG >= 7) - LogInfoToggle.logs("Error: %s", serverResponse.error); - } - if (serverResponse.beginTrack && ConfigManager.DEBUG >= 7) { - LogInfoToggle.logs("time: %s", queryStats.timeFig); - LogInfoToggle.logs("errors: %s", queryStats.errors); + synchronized (queryStats) { + if (!serverResponse.cached) { + queryStats.timeFig.add(serverResponse.timeMs); + if (serverResponse.error != null) { + MapUtils.incr(queryStats.errors, serverResponse.error.type, 1); + if (serverResponse.beginTrack && ConfigManager.DEBUG >= 7) + LogInfoToggle.logs("Error: %s", serverResponse.error); + } + if (serverResponse.beginTrack && ConfigManager.DEBUG >= 7) { + LogInfoToggle.logs("time: %s", queryStats.timeFig); + LogInfoToggle.logs("errors: %s", queryStats.errors); + } } } From b387796500adca543875eb38837d10308e36d0b9 Mon Sep 17 00:00:00 2001 From: mireu Date: Mon, 13 Aug 2018 17:44:00 +0200 Subject: [PATCH 019/147] Parallelized DbEntitySearcher --- .../freebase/index/FbEntitySearcher.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java index 3c8f98b8..47051d1d 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java @@ -25,10 +25,18 @@ public class FbEntitySearcher { - private final QueryParser queryParser; private final IndexSearcher indexSearcher; private int numOfDocs = 50; private String searchStrategy; + private QueryParser queryParser; + + private synchronized QueryParser freshQueryParser(){//needed since queryparser is not threadsafe and queryparser is very lightweight + return new QueryParser( + Version.LUCENE_44, + FbIndexField.TEXT.fieldName(), + this.searchStrategy.equals("exact") ? new KeywordAnalyzer() : new StandardAnalyzer(Version.LUCENE_44)); + } + public FbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy) throws IOException { @@ -37,10 +45,7 @@ public FbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy throw new RuntimeException("Bad searching strategy: " + searchingStrategy); this.searchStrategy = searchingStrategy; - queryParser = new QueryParser( - Version.LUCENE_44, - FbIndexField.TEXT.fieldName(), - searchingStrategy.equals("exact") ? new KeywordAnalyzer() : new StandardAnalyzer(Version.LUCENE_44)); + queryParser = freshQueryParser(); LogInfoToggle.log("Opening index dir: " + indexDir); IndexReader indexReader = DirectoryReader.open(SimpleFSDirectory.open(new File(indexDir))); indexSearcher = new IndexSearcher(indexReader); @@ -50,7 +55,7 @@ public FbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy LogInfoToggle.end_track(); } - public synchronized List searchDocs(String question) throws IOException, ParseException { + public List searchDocs(String question) throws IOException, ParseException { List res = new LinkedList(); if (searchStrategy.equals("exact")) @@ -67,7 +72,11 @@ public synchronized List searchDocs(String question) throws IOExceptio } private ScoreDoc[] getHits(String question) throws IOException, ParseException { - Query luceneQuery = queryParser.parse(question); + Query luceneQuery; + synchronized (queryParser) { + luceneQuery = queryParser.parse(question); + queryParser = freshQueryParser(); + } ScoreDoc[] hits = indexSearcher.search(luceneQuery, numOfDocs).scoreDocs; return hits; } From 94e77ea5bd615b66155af1ab59c89c733122f2e8 Mon Sep 17 00:00:00 2001 From: mireu Date: Mon, 13 Aug 2018 17:53:46 +0200 Subject: [PATCH 020/147] Parallelized FbEntitySearcher --- .../sempre/roboy/index/DbEntitySearcher.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java index 19e8bd52..c0cdb06a 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java @@ -25,10 +25,17 @@ public class DbEntitySearcher { - private final QueryParser queryParser; private final IndexSearcher indexSearcher; private int numOfDocs = 50; private String searchStrategy; + private QueryParser queryParser; + + private synchronized QueryParser freshQueryParser(){//needed since queryparser is not threadsafe and queryparser is very lightweight + return new QueryParser( + Version.LUCENE_44, + DbIndexField.TEXT.fieldName(), + searchStrategy.equals("exact") ? new KeywordAnalyzer() : new StandardAnalyzer(Version.LUCENE_44)); + } public DbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy) throws IOException { @@ -37,10 +44,7 @@ public DbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy throw new RuntimeException("Bad searching strategy: " + searchingStrategy); this.searchStrategy = searchingStrategy; - queryParser = new QueryParser( - Version.LUCENE_44, - DbIndexField.TEXT.fieldName(), - searchingStrategy.equals("exact") ? new KeywordAnalyzer() : new StandardAnalyzer(Version.LUCENE_44)); + queryParser = freshQueryParser(); LogInfoToggle.log("Opening index dir: " + indexDir); IndexReader indexReader = DirectoryReader.open(SimpleFSDirectory.open(new File(indexDir))); indexSearcher = new IndexSearcher(indexReader); @@ -50,7 +54,7 @@ public DbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy LogInfoToggle.end_track(); } - public synchronized List searchDocs(String question) throws IOException, ParseException { + public List searchDocs(String question) throws IOException, ParseException { List res = new LinkedList(); if (searchStrategy.equals("exact")) @@ -67,7 +71,11 @@ public synchronized List searchDocs(String question) throws IOExceptio } private ScoreDoc[] getHits(String question) throws IOException, ParseException { - Query luceneQuery = queryParser.parse(question); + Query luceneQuery; + synchronized (queryParser) { + luceneQuery = queryParser.parse(question); + queryParser = freshQueryParser(); + } ScoreDoc[] hits = indexSearcher.search(luceneQuery, numOfDocs).scoreDocs; return hits; } From 28c897f5e9a40ef6cbabb497af991fe4c003df42 Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Tue, 14 Aug 2018 19:18:18 +0200 Subject: [PATCH 021/147] timer in idle state adjusted --- config.properties | 6 +-- .../fairShowStates/ActiveIntroState.java | 11 ++++-- .../states/fairShowStates/IdleState.java | 29 ++++++++++---- .../states/fairShowStates/InfoTalkState.java | 39 ++++++++----------- .../fairShowStates/ObjectDetectionState.java | 29 +++++++------- memory | 2 +- .../personalityFiles/FairShowPersonality.json | 2 +- 7 files changed, 66 insertions(+), 52 deletions(-) diff --git a/config.properties b/config.properties index cded2a82..76f535ea 100755 --- a/config.properties +++ b/config.properties @@ -74,13 +74,13 @@ TELEGRAM_API_TOKENS_FILE: "" # Memory: java.util.logging # https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html -MEMORY_LOG_MODE: "WARNING" +MEMORY_LOG_MODE: "FINE" # Dialog: LOG4J 2 # https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html # https://logging.apache.org/log4j/2.x/manual/customloglevels.html -DIALOG_LOG_MODE: "WARN" +DIALOG_LOG_MODE: "DEBUG" # Parser/NLU: LogInfo # Supports all Log4J levels. See Documentation for more details -PARSER_LOG_MODE: "WARN" \ No newline at end of file +PARSER_LOG_MODE: "DEBUG" \ No newline at end of file diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java index d39b4b6d..8a987073 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java @@ -31,16 +31,19 @@ public ActiveIntroState(String stateIdentifier, StateParameters params) { @Override public Output act() { + + return Output.say(Verbalizer.greetings.getRandomElement() + " " + Verbalizer.roboyIntro.getRandomElement() + PhraseCollection.ROBOY_PHRASES.getRandomElement()); + } + + @Override + public State getNextState() { + if(checkPplAround()){ nextState = getTransition(TRANSITION_PEOPLE_AROUND); }else{ nextState = getTransition((TRANSITION_LONELY_ROBOY)); } - return Output.say(Verbalizer.greetings.getRandomElement() + " " + Verbalizer.roboyIntro.getRandomElement() + PhraseCollection.ROBOY_PHRASES.getRandomElement()); - } - @Override - public State getNextState() { return nextState; } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index 7785cefe..7492078d 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -17,6 +17,7 @@ public class IdleState extends MonologState { private final static String TRANSITION_TIME_IS_UP = "timeIsUp"; private final static String DELAY_ID = "delayInMins"; + private final static int MIN_NUMBER_PEOPLE = 1; private final Logger LOGGER = LogManager.getLogger(); private State nextState = this; @@ -31,15 +32,18 @@ public IdleState(String stateIdentifier, StateParameters params) { @Override public Output act() { - try { - TimeUnit.SECONDS.sleep(6); - //TimeUnit.MINUTES.sleep(delay); - nextState = getTransition(TRANSITION_TIME_IS_UP); - } - catch(InterruptedException e){ - LOGGER.error("--> Unable to pause Conversation in Idle State " + e.getMessage()); + long enteringTime = System.nanoTime(); + + while(notInVision() && (TimeUnit.MINUTES.toNanos(delay) > System.nanoTime() - enteringTime)) { + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + LOGGER.error(e.getMessage()); + } } + nextState = getTransition(TRANSITION_TIME_IS_UP); + return Output.sayNothing(); } @@ -48,6 +52,17 @@ public State getNextState() { return nextState; } + private boolean notInVision(){ + + try { + + return getContext().CROWD_DETECTION.getLastValue().getData() < MIN_NUMBER_PEOPLE; + } catch(NullPointerException e){ + LOGGER.info("Make sure crowd detection publishing, receiving: " + e.getMessage()); + return false; + } + } + } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java index 06ca23b2..6a32b399 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java @@ -23,13 +23,10 @@ enum InfoAbout { private RandomList phrases = PhraseCollection.ROBOY_TEAM_PHRASES; - @Override - public void performSpecialAction(RosMainNode rosNode){ - + public State.Output performSpecialAction(RosMainNode rosNode){ - logger.info("synthesising: " + phrases.getRandomElement()); - rosNode.SynthesizeSpeech(phrases.getRandomElement()); + return State.Output.say(phrases.getRandomElement()); } }, @@ -37,9 +34,9 @@ public void performSpecialAction(RosMainNode rosNode){ private RandomList phrases = PhraseCollection.MISSION_PHRASES; @Override - public void performSpecialAction(RosMainNode rosNode){ - logger.info("synthesising: " + phrases.getRandomElement()); - rosNode.SynthesizeSpeech(phrases.getRandomElement()); + public State.Output performSpecialAction(RosMainNode rosNode){ + + return State.Output.say(phrases.getRandomElement()); } }, ABOUT_MOVEMENT { @@ -49,7 +46,7 @@ public void performSpecialAction(RosMainNode rosNode){ RandomList phrases = PhraseCollection.MOVEMENT_PHRASES; @Override - public void performSpecialAction(RosMainNode rosNode){ + public State.Output performSpecialAction(RosMainNode rosNode){ //TODO: what can be moved? HashMap parts = new HashMap<>(); parts.put("shoulder_left", "left shoulder"); @@ -70,7 +67,7 @@ public void performSpecialAction(RosMainNode rosNode){ logger.error(e.getMessage()); } logger.info("synthesising: " + String.format(phrases.getRandomElement(), randomPartLiteral)); - rosNode.SynthesizeSpeech(String.format(phrases.getRandomElement(), randomPartLiteral)); + return State.Output.say(String.format(phrases.getRandomElement(), randomPartLiteral)); } }, ABOUT_EMOTIONS { @@ -80,19 +77,17 @@ public void performSpecialAction(RosMainNode rosNode){ @Override - public void performSpecialAction(RosMainNode rosNode){ + public State.Output performSpecialAction(RosMainNode rosNode){ emotions.addAll(Arrays.asList(RoboyEmotion.values())); - logger.info("synthesising: " + phrases.getRandomElement()); - rosNode.SynthesizeSpeech(phrases.getRandomElement()); - logger.info("showing emotions"); - rosNode.ShowEmotion(emotions.getRandomElement()); + + return State.Output.say(phrases.getRandomElement()).setEmotion(emotions.getRandomElement()); } }; private final static Logger logger = LogManager.getLogger(); - public abstract void performSpecialAction(RosMainNode rosNode); + public abstract State.Output performSpecialAction(RosMainNode rosNode); } @@ -124,7 +119,12 @@ public InfoTalkState(String stateIdentifier, StateParameters params) { public Output act() { activeInfo = selectRandomInfo(); - activeInfo.performSpecialAction(getRosMainNode()); + + return activeInfo.performSpecialAction(getRosMainNode()); + } + + @Override + public State getNextState() { if(checkPplListening()){ nextState = getTransition(TRANSITION_PERSON_DETECTED); @@ -132,11 +132,6 @@ public Output act() { nextState = getTransition(TRANSITION_LONELY_ROBOY); } - return Output.sayNothing(); - } - - @Override - public State getNextState() { return nextState; } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java index 9ef8c0cf..efb94179 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java @@ -19,10 +19,10 @@ enum Objects { private RandomList phrases = new RandomList<>("an aeroplane. Let's fly to Spain and spend a day at the beach.", "an aeroplane. Are you ready for take-off?", "an aeroplane. Please fasten you seatbelts, Ladies and Gentlemen!"); @Override - public void performSpecialAction(RosMainNode rmn){ - logger.info("synthesising: " + phrases.getRandomElement()); - rmn.SynthesizeSpeech(phrases.getRandomElement()); - rmn.ShowEmotion(RoboyEmotion.HEARTS); + public State.Output performSpecialAction(RosMainNode rmn){ + + return State.Output.say(phrases.getRandomElement()).setEmotion(RoboyEmotion.HEARTS); + } }, @@ -31,7 +31,7 @@ public void performSpecialAction(RosMainNode rmn){ private RandomList phrases = new RandomList<>("a bycicle, I bet I can ride faster than you", "a bike, I could easily win the tour de France", "a bycicle, I learnt riding the bycicle when I was just three years old. And you?", "bike. I love bycicles. I only fell off my bike once."); @Override - public void performSpecialAction(RosMainNode rmn){ + public State.Output performSpecialAction(RosMainNode rmn){ logger.info("synthesising: " + phrases.getRandomElement()); rmn.SynthesizeSpeech(phrases.getRandomElement()); rmn.ShowEmotion(happyEmotions.getRandomElement()); @@ -43,7 +43,7 @@ public void performSpecialAction(RosMainNode rmn){ private RandomList phrases = new RandomList<>("a bottle, it would be awesome to drink a cold beer.", "a drink. In a few years from now, I want to be a bartender" , "a beverage. In the morning, I love coffee, in the evening, I drink beer", "a drink, chin-chin", "a bottle. Cheers, enjoy your drink."); @Override - public void performSpecialAction(RosMainNode rmn){ + public State.Output performSpecialAction(RosMainNode rmn){ logger.info("synthesising: " + phrases.getRandomElement()); rmn.SynthesizeSpeech(phrases.getRandomElement()); rmn.ShowEmotion(happyEmotions.getRandomElement()); @@ -54,7 +54,7 @@ public void performSpecialAction(RosMainNode rmn){ private RandomList phrases = new RandomList<>("car, in a few years, my fellow robots will be able to ride your car", "car. In Germany, you can go as fast as you want on the highway. I was really fast once." , "car. The cars we drive say a lot about us."); @Override - public void performSpecialAction(RosMainNode rmn){ + public State.Output performSpecialAction(RosMainNode rmn){ logger.info("synthesising: " + phrases.getRandomElement()); rmn.SynthesizeSpeech(phrases.getRandomElement()); } @@ -64,7 +64,7 @@ public void performSpecialAction(RosMainNode rmn){ private RandomList phrases = new RandomList<>("a chair, grab a seat if you want." , "a chair, have you ever played musical chairs? I love this game." , "a chair. Sometimes, I am really, really lazy. I just sit on a chair and do nothing but relaxing. It is so comfortable" , "a chair. For now, I would prefer sitting on a beach chair close to the sea."); @Override - public void performSpecialAction(RosMainNode rmn){ + public State.Output performSpecialAction(RosMainNode rmn){ logger.info("synthesising: " + phrases.getRandomElement()); rmn.SynthesizeSpeech(phrases.getRandomElement()); rmn.ShowEmotion(happyEmotions.getRandomElement()); @@ -75,7 +75,7 @@ public void performSpecialAction(RosMainNode rmn){ private RandomList phrases = new RandomList<>("a table, I am kind of hungry. I can hardly wait for my next meal" , "a table. We need some chairs and food and we can have a great dinner."); @Override - public void performSpecialAction(RosMainNode rmn){ + public State.Output performSpecialAction(RosMainNode rmn){ logger.info("synthesising: " + phrases.getRandomElement()); rmn.SynthesizeSpeech(phrases.getRandomElement()); rmn.ShowEmotion(RoboyEmotion.TEETH); @@ -87,7 +87,7 @@ public void performSpecialAction(RosMainNode rmn){ private RandomList phrases = new RandomList<>("a dog. Sometimes they bark at me. I think they are afraid." , "a dog. When I was a robot kid, I loved dogs, but now I am scared of them." , "a dog. I hope he doesn't bite me. I am a bit afraid of big dogs."); @Override - public void performSpecialAction(RosMainNode rmn){ + public State.Output performSpecialAction(RosMainNode rmn){ logger.info("synthesising: " + phrases.getRandomElement()); rmn.SynthesizeSpeech(phrases.getRandomElement()); rmn.ShowEmotion(RoboyEmotion.ROLLING_EYES); @@ -99,7 +99,7 @@ public void performSpecialAction(RosMainNode rmn){ @Override - public void performSpecialAction(RosMainNode rmn){ + public State.Output performSpecialAction(RosMainNode rmn){ logger.info("synthesising: " + phrases.getRandomElement()); rmn.SynthesizeSpeech(phrases.getRandomElement()); rmn.ShowEmotion(RoboyEmotion.SHY); @@ -111,18 +111,20 @@ public void performSpecialAction(RosMainNode rmn){ private RandomList socialMediaEmotions = new RandomList<>(RoboyEmotion.FACEBOOK_EYES, RoboyEmotion.INSTAGRAM_EYES, RoboyEmotion.LINKED_IN_EYES); @Override - public void performSpecialAction(RosMainNode rmn){ + public State.Output performSpecialAction(RosMainNode rmn){ + logger.info("synthesising: " + phrases.getRandomElement()); rmn.SynthesizeSpeech(phrases.getRandomElement()); rmn.ShowEmotion(socialMediaEmotions.getRandomElement()); } }; + public RandomList connectingPhrases = new RandomList<>(" and look there, ", " and over there i can see ", " oh see, ", " this is a really nice "); public RandomList happyEmotions = new RandomList<>(RoboyEmotion.SMILE_BLINK, RoboyEmotion.HAPPY, RoboyEmotion.SURPRISED, RoboyEmotion.TEETH); private final static Logger logger = LogManager.getLogger(); - public abstract void performSpecialAction(RosMainNode rosNode); + public abstract State.Output performSpecialAction(RosMainNode rosNode); } @@ -133,7 +135,6 @@ public class ObjectDetectionState extends MonologState { private final static String TRANSITION_FINISHED = "finished"; - private RandomList connectingPhrases = new RandomList<>(" and look there, ", " and over there i can see ", " oh see, ", " this is a really nice "); private final Set detectedObjects = new HashSet<>(); private final Logger logger = LogManager.getLogger(); diff --git a/memory b/memory index 436c0295..d74e0b3c 160000 --- a/memory +++ b/memory @@ -1 +1 @@ -Subproject commit 436c02959903ab34ca40223f9594da0d6cf4346d +Subproject commit d74e0b3ccf975d9cf7cedbbe031ae72c6f464318 diff --git a/resources/personalityFiles/FairShowPersonality.json b/resources/personalityFiles/FairShowPersonality.json index 24be2c0d..39adc55c 100644 --- a/resources/personalityFiles/FairShowPersonality.json +++ b/resources/personalityFiles/FairShowPersonality.json @@ -8,7 +8,7 @@ "timeIsUp": "ActiveIntro" }, "parameters":{ - "delayInMins" : "10" + "delayInMins" : "1" } }, { From cb079b698415f6a4d97fd18c7e16869fc4abb2d4 Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Tue, 14 Aug 2018 19:52:01 +0200 Subject: [PATCH 022/147] awesome vector things are happening --- .../states/fairShowStates/InfoTalkState.java | 2 +- .../fairShowStates/ObjectDetectionState.java | 69 ++++++++++--------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java index 6a32b399..51443b7e 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java @@ -47,7 +47,7 @@ public State.Output performSpecialAction(RosMainNode rosNode){ @Override public State.Output performSpecialAction(RosMainNode rosNode){ - //TODO: what can be moved? + HashMap parts = new HashMap<>(); parts.put("shoulder_left", "left shoulder"); parts.put("shoulder_right", "right shoulder"); diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java index efb94179..48acb9a2 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java @@ -21,7 +21,7 @@ enum Objects { @Override public State.Output performSpecialAction(RosMainNode rmn){ - return State.Output.say(phrases.getRandomElement()).setEmotion(RoboyEmotion.HEARTS); + return State.Output.say(connectingPhrases.getRandomElement() + phrases.getRandomElement()).setEmotion(RoboyEmotion.HEARTS); } @@ -32,9 +32,9 @@ public State.Output performSpecialAction(RosMainNode rmn){ @Override public State.Output performSpecialAction(RosMainNode rmn){ - logger.info("synthesising: " + phrases.getRandomElement()); - rmn.SynthesizeSpeech(phrases.getRandomElement()); - rmn.ShowEmotion(happyEmotions.getRandomElement()); + + return State.Output.say(connectingPhrases.getRandomElement() + phrases.getRandomElement()).setEmotion(happyEmotions.getRandomElement()); + } }, @@ -44,9 +44,9 @@ public State.Output performSpecialAction(RosMainNode rmn){ @Override public State.Output performSpecialAction(RosMainNode rmn){ - logger.info("synthesising: " + phrases.getRandomElement()); - rmn.SynthesizeSpeech(phrases.getRandomElement()); - rmn.ShowEmotion(happyEmotions.getRandomElement()); + + return State.Output.say(connectingPhrases.getRandomElement() + phrases.getRandomElement()).setEmotion(happyEmotions.getRandomElement()); + } }, CAR { @@ -55,8 +55,9 @@ public State.Output performSpecialAction(RosMainNode rmn){ @Override public State.Output performSpecialAction(RosMainNode rmn){ - logger.info("synthesising: " + phrases.getRandomElement()); - rmn.SynthesizeSpeech(phrases.getRandomElement()); + + return State.Output.say(connectingPhrases.getRandomElement() + phrases.getRandomElement()); + } }, CHAIR { @@ -65,9 +66,9 @@ public State.Output performSpecialAction(RosMainNode rmn){ @Override public State.Output performSpecialAction(RosMainNode rmn){ - logger.info("synthesising: " + phrases.getRandomElement()); - rmn.SynthesizeSpeech(phrases.getRandomElement()); - rmn.ShowEmotion(happyEmotions.getRandomElement()); + + return State.Output.say(connectingPhrases.getRandomElement() + phrases.getRandomElement()).setEmotion(happyEmotions.getRandomElement()); + } }, @@ -76,9 +77,8 @@ public State.Output performSpecialAction(RosMainNode rmn){ @Override public State.Output performSpecialAction(RosMainNode rmn){ - logger.info("synthesising: " + phrases.getRandomElement()); - rmn.SynthesizeSpeech(phrases.getRandomElement()); - rmn.ShowEmotion(RoboyEmotion.TEETH); + + return State.Output.say(connectingPhrases.getRandomElement() + phrases.getRandomElement()).setEmotion(RoboyEmotion.TEETH); } }, @@ -88,9 +88,9 @@ public State.Output performSpecialAction(RosMainNode rmn){ @Override public State.Output performSpecialAction(RosMainNode rmn){ - logger.info("synthesising: " + phrases.getRandomElement()); - rmn.SynthesizeSpeech(phrases.getRandomElement()); - rmn.ShowEmotion(RoboyEmotion.ROLLING_EYES); + + return State.Output.say(connectingPhrases.getRandomElement() + phrases.getRandomElement()).setEmotion(RoboyEmotion.ROLLING_EYES); + } }, SOFA { @@ -100,9 +100,9 @@ public State.Output performSpecialAction(RosMainNode rmn){ @Override public State.Output performSpecialAction(RosMainNode rmn){ - logger.info("synthesising: " + phrases.getRandomElement()); - rmn.SynthesizeSpeech(phrases.getRandomElement()); - rmn.ShowEmotion(RoboyEmotion.SHY); + + return State.Output.say(connectingPhrases.getRandomElement() + phrases.getRandomElement()).setEmotion(RoboyEmotion.SHY); + } }, TVMONITOR { @@ -113,17 +113,14 @@ public State.Output performSpecialAction(RosMainNode rmn){ @Override public State.Output performSpecialAction(RosMainNode rmn){ - logger.info("synthesising: " + phrases.getRandomElement()); - rmn.SynthesizeSpeech(phrases.getRandomElement()); - rmn.ShowEmotion(socialMediaEmotions.getRandomElement()); + return State.Output.say(connectingPhrases.getRandomElement() + phrases.getRandomElement()).setEmotion(socialMediaEmotions.getRandomElement()); + } }; public RandomList connectingPhrases = new RandomList<>(" and look there, ", " and over there i can see ", " oh see, ", " this is a really nice "); public RandomList happyEmotions = new RandomList<>(RoboyEmotion.SMILE_BLINK, RoboyEmotion.HAPPY, RoboyEmotion.SURPRISED, RoboyEmotion.TEETH); - private final static Logger logger = LogManager.getLogger(); - public abstract State.Output performSpecialAction(RosMainNode rosNode); } @@ -137,6 +134,8 @@ public class ObjectDetectionState extends MonologState { private final Set detectedObjects = new HashSet<>(); + private Vector outputs = new Vector<>(); + private final Logger logger = LogManager.getLogger(); private State nextState = this; @@ -148,17 +147,21 @@ public ObjectDetectionState(String stateIdentifier, StateParameters params) { @Override public Output act() { - checkObjects(); + if(outputs.isEmpty()){ + + checkObjects(); + + for(Objects obj : detectedObjects) { + + outputs.add(obj.performSpecialAction(getRosMainNode())); - for(Objects obj : detectedObjects) { - logger.info("synthesising: " + connectingPhrases.getRandomElement()); - getRosMainNode().SynthesizeSpeech(connectingPhrases.getRandomElement()); - obj.performSpecialAction(getRosMainNode()); + } } - nextState = getTransition(TRANSITION_FINISHED); + Output current = outputs.remove(0); + if(outputs.isEmpty()) nextState = getTransition(TRANSITION_FINISHED); - return Output.sayNothing(); + return current; } @Override From a5117edeeff202e02fad3b48f5ab685d88f5dc6b Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 20:58:06 +0200 Subject: [PATCH 023/147] Merge branch 'hack-jason-demo' into origin/de-nlu-upgrades --- .../stanford/nlp/sempre/roboy/api/Movie.java | 39 ++++++++++++++++ .../nlp/sempre/roboy/api/Translate.java | 41 +++++++++++++++++ .../nlp/sempre/roboy/api/Weather.java | 46 +++++++++++++++++++ .../stanford/nlp/sempre/roboy/api/apiKeys.yml | 3 ++ .../nlp/sempre/roboy/api/keyGetter.java | 22 +++++++++ 5 files changed, 151 insertions(+) create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java new file mode 100644 index 00000000..301583fc --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java @@ -0,0 +1,39 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Random; + +public class Movie{ + static String KEY = keyGetter.getKey("moviekey"); + static int randomInt = new Random().nextInt(20); + + + public static String getData(String... args) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) + .getAsJsonArray("results") + .get(randomInt).getAsJsonObject().get(args[0]); +// System.out.println(jsonObject); + return result.toString(); + } + + public static void main(String[] args)throws Exception{ + getData("title");getData("overview"); + } +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java new file mode 100644 index 00000000..8eb2afec --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java @@ -0,0 +1,41 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.github.jsonldjava.utils.Obj; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Translate { + static final String KEY = keyGetter.getKey("translatekey"); + + public static String getData(String... args) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(APIify(args[0], args[1])); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); +// System.out.println(jsonObject); + return result.toString(); + } + + private static String APIify(String text, String targetLang){ + String s = String.format("https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s", KEY, text.replace(" ", "%20"), targetLang); +// System.out.println(s); + return s; + } + + public static void main(String[] args) throws Exception{ + System.out.println(getData("cheese is the best vegetable", "de")); + } +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java new file mode 100644 index 00000000..9bfff6a2 --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java @@ -0,0 +1,46 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Weather { + final static String KEY = keyGetter.getKey("weatherkey"); + public static String getData(String... args) throws Exception{ + try { + return getHTML(args[0]); + }catch (Exception e) {return null;} + } + public static String getHTML(String country) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("http://api.openweathermap.org/data/2.5/weather?q=%s&APPID=%s", country, KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + JsonObject jsonObject = (((JsonObject) new JsonParser().parse(result.toString())).get("weather").getAsJsonArray()).get(0).getAsJsonObject(); +// System.out.println(jsonObject.get("main")); + return jsonObject.get("main").getAsString(); + } + + public static void main(String[] args) throws Exception + { + //Find Munich + System.out.println(getData("munich")); + } + + +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml new file mode 100644 index 00000000..1cef27aa --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml @@ -0,0 +1,3 @@ +moviekey: xxxxxxx +translatekey: xxxxxxx +weatherkey: xxxxxx \ No newline at end of file diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java new file mode 100644 index 00000000..0b42b252 --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java @@ -0,0 +1,22 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import org.apache.commons.configuration2.YAMLConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; + +import java.io.FileNotFoundException; +import java.io.FileReader; + +public class keyGetter { + static YAMLConfiguration yamlConfiguration = new YAMLConfiguration(); + static String getKey(String key){ + try { + yamlConfiguration.read(new FileReader("nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml")); + } catch (ConfigurationException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return yamlConfiguration.getString(key); + } + +} From 9feff588ccf94043782c570ff1207bb9cba4a32b Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 20:59:30 +0200 Subject: [PATCH 024/147] Ignore YML --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index d7d759b0..742d1b5f 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,5 @@ community-server/data-backup *.iml nlu/parser/target/ + +nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml From c6485277ea5df37ef311e16f25e6df1947bffff6 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:34:15 +0200 Subject: [PATCH 025/147] Updated API Stuff --- .../stanford/nlp/sempre/roboy/api/Movie.java | 6 +- .../nlp/sempre/roboy/api/Translate.java | 108 +++++++++++++++++- .../nlp/sempre/roboy/api/Weather.java | 6 +- 3 files changed, 109 insertions(+), 11 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java index 301583fc..bb6dde97 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java @@ -13,8 +13,8 @@ public class Movie{ static String KEY = keyGetter.getKey("moviekey"); static int randomInt = new Random().nextInt(20); - - public static String getData(String... args) throws Exception { + //FIELD TITLE or OVERVIEW + public static String getData(String field) throws Exception { StringBuilder result = new StringBuilder(); URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); @@ -28,7 +28,7 @@ public static String getData(String... args) throws Exception { Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) .getAsJsonArray("results") - .get(randomInt).getAsJsonObject().get(args[0]); + .get(randomInt).getAsJsonObject().get(field); // System.out.println(jsonObject); return result.toString(); } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java index 8eb2afec..677b1d5d 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java @@ -12,9 +12,11 @@ public class Translate { static final String KEY = keyGetter.getKey("translatekey"); - public static String getData(String... args) throws Exception { + + //Language: Either Language code such as DE or language name. Text is the text to translate + public static String getData(String text, String language) throws Exception { StringBuilder result = new StringBuilder(); - URL url = new URL(APIify(args[0], args[1])); + URL url = new URL(APIify(text, handleLanguage(language))); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); @@ -26,7 +28,105 @@ public static String getData(String... args) throws Exception { Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); // System.out.println(jsonObject); - return result.toString(); + return jsonObject.toString(); + } + + private static String handleLanguage(String language) { + switch (language.toLowerCase()){ + case "azerbaijan": return "az"; + case "malayalam": return "ml"; + case "albanian": return "sq"; + case "maltese": return "mt"; + case "amharic": return "am"; + case "macedonian": return "mk"; + case "english": return "en"; + case "maori": return "mi"; + case "arabic": return "ar"; + case "marathi": return "mr"; + case "armenian": return "hy"; + case "mari": return "mhr"; + case "afrikaans": return "af"; + case "mongolian": return "mn"; + case "basque": return "eu"; + case "german": return "de"; + case "bashkir": return "ba"; + case "nepali": return "ne"; + case "belarusian": return "be"; + case "norwegian": return "no"; + case "bengali": return "bn"; + case "punjabi": return "pa"; + case "burmese": return "my"; + case "papiamento": return "pap"; + case "bulgarian": return "bg"; + case "persian": return "fa"; + case "bosnian": return "bs"; + case "polish": return "pl"; + case "welsh": return "cy"; + case "portuguese": return "pt"; + case "hungarian": return "hu"; + case "romanian": return "ro"; + case "vietnamese": return "vi"; + case "russian": return "ru"; + case "haitian": return "ht"; + case "cebuano": return "ceb"; + case "galician": return "gl"; + case "serbian": return "sr"; + case "dutch": return "nl"; + case "sinhala": return "si"; + case "slovakian": return "sk"; + case "greek": return "el"; + case "slovenian": return "sl"; + case "georgian": return "ka"; + case "swahili": return "sw"; + case "gujarati": return "gu"; + case "sundanese": return "su"; + case "danish": return "da"; + case "tajik": return "tg"; + case "hebrew": return "he"; + case "thai": return "th"; + case "yiddish": return "yi"; + case "tagalog": return "tl"; + case "indonesian": return "id"; + case "tamil": return "ta"; + case "irish": return "ga"; + case "tatar": return "tt"; + case "italian": return "it"; + case "telugu": return "te"; + case "icelandic": return "is"; + case "turkish": return "tr"; + case "spanish": return "es"; + case "udmurt": return "udm"; + case "kazakh": return "kk"; + case "uzbek": return "uz"; + case "kannada": return "kn"; + case "ukrainian": return "uk"; + case "catalan": return "ca"; + case "urdu": return "ur"; + case "kyrgyz": return "ky"; + case "finnish": return "fi"; + case "chinese": return "zh"; + case "french": return "fr"; + case "korean": return "ko"; + case "hindi": return "hi"; + case "xhosa": return "xh"; + case "croatian": return "hr"; + case "khmer": return "km"; + case "czech": return "cs"; + case "laotian": return "lo"; + case "swedish": return "sv"; + case "latin": return "la"; + case "scottish": return "gd"; + case "latvian": return "lv"; + case "estonian": return "et"; + case "lithuanian": return "lt"; + case "esperanto": return "eo"; + case "luxembourgish": return "lb"; + case "javanese": return "jv"; + case "malagasy": return "mg"; + case "japanese": return "ja"; + case "malay": return "ms"; + default: return language; + } } private static String APIify(String text, String targetLang){ @@ -36,6 +136,6 @@ private static String APIify(String text, String targetLang){ } public static void main(String[] args) throws Exception{ - System.out.println(getData("cheese is the best vegetable", "de")); + System.out.println(getData("cheese is the best vegetable", "german")); } } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java index 9bfff6a2..05dc9c73 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java @@ -14,10 +14,8 @@ public class Weather { final static String KEY = keyGetter.getKey("weatherkey"); - public static String getData(String... args) throws Exception{ - try { - return getHTML(args[0]); - }catch (Exception e) {return null;} + public static String getData(String country) throws Exception{ + return getHTML(country); } public static String getHTML(String country) throws Exception { StringBuilder result = new StringBuilder(); From ba49099b3922ee5ddb37eff1b838412aed4a1c14 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:44:55 +0200 Subject: [PATCH 026/147] Moving --- .../src/main/java/roboy/util}/api/Movie.java | 9 +++++---- .../src/main/java/roboy/util}/api/Translate.java | 3 +-- .../src/main/java/roboy/util}/api/Weather.java | 6 +----- dialog/src/main/java/roboy/util/api/apiKeys.yml | 3 +++ .../src/main/java/roboy/util}/api/keyGetter.java | 4 ++-- .../java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml | 3 --- 6 files changed, 12 insertions(+), 16 deletions(-) rename {nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy => dialog/src/main/java/roboy/util}/api/Movie.java (81%) rename {nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy => dialog/src/main/java/roboy/util}/api/Translate.java (98%) rename {nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy => dialog/src/main/java/roboy/util}/api/Weather.java (89%) create mode 100644 dialog/src/main/java/roboy/util/api/apiKeys.yml rename {nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy => dialog/src/main/java/roboy/util}/api/keyGetter.java (77%) delete mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/dialog/src/main/java/roboy/util/api/Movie.java similarity index 81% rename from nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java rename to dialog/src/main/java/roboy/util/api/Movie.java index bb6dde97..90e57178 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java +++ b/dialog/src/main/java/roboy/util/api/Movie.java @@ -1,5 +1,6 @@ -package edu.stanford.nlp.sempre.roboy.api; +package roboy.util.api; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -26,14 +27,14 @@ public static String getData(String field) throws Exception { } rd.close(); - Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) + JsonElement jsonElement = ((JsonObject) new JsonParser().parse(result.toString())) .getAsJsonArray("results") .get(randomInt).getAsJsonObject().get(field); // System.out.println(jsonObject); - return result.toString(); + return jsonElement.getAsString(); } public static void main(String[] args)throws Exception{ - getData("title");getData("overview"); + System.out.println(getData("title")+":\t"+getData("overview")); } } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/dialog/src/main/java/roboy/util/api/Translate.java similarity index 98% rename from nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java rename to dialog/src/main/java/roboy/util/api/Translate.java index 677b1d5d..129220e4 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java +++ b/dialog/src/main/java/roboy/util/api/Translate.java @@ -1,6 +1,5 @@ -package edu.stanford.nlp.sempre.roboy.api; +package roboy.util.api; -import com.github.jsonldjava.utils.Obj; import com.google.gson.JsonObject; import com.google.gson.JsonParser; diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/dialog/src/main/java/roboy/util/api/Weather.java similarity index 89% rename from nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java rename to dialog/src/main/java/roboy/util/api/Weather.java index 05dc9c73..f04d48fb 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java +++ b/dialog/src/main/java/roboy/util/api/Weather.java @@ -1,14 +1,10 @@ -package edu.stanford.nlp.sempre.roboy.api; +package roboy.util.api; -import com.google.gson.Gson; -import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; -import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/dialog/src/main/java/roboy/util/api/apiKeys.yml new file mode 100644 index 00000000..22207938 --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/apiKeys.yml @@ -0,0 +1,3 @@ +moviekey: xxxxxxxxxxxxxxxxxxxxxxxx +translatekey: xxxxxxxxxxxxxxxxxxxxxxxx +weatherkey: xxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java b/dialog/src/main/java/roboy/util/api/keyGetter.java similarity index 77% rename from nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java rename to dialog/src/main/java/roboy/util/api/keyGetter.java index 0b42b252..b91fc487 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java +++ b/dialog/src/main/java/roboy/util/api/keyGetter.java @@ -1,4 +1,4 @@ -package edu.stanford.nlp.sempre.roboy.api; +package roboy.util.api; import org.apache.commons.configuration2.YAMLConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; @@ -10,7 +10,7 @@ public class keyGetter { static YAMLConfiguration yamlConfiguration = new YAMLConfiguration(); static String getKey(String key){ try { - yamlConfiguration.read(new FileReader("nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml")); + yamlConfiguration.read(new FileReader("dialog/src/main/java/roboy/util/api/apiKeys.yml")); } catch (ConfigurationException e) { e.printStackTrace(); } catch (FileNotFoundException e) { diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml deleted file mode 100644 index 1cef27aa..00000000 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml +++ /dev/null @@ -1,3 +0,0 @@ -moviekey: xxxxxxx -translatekey: xxxxxxx -weatherkey: xxxxxx \ No newline at end of file From 9c68354b6ceb68e5a87d27e3b6961a4da702fcc3 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:45:35 +0200 Subject: [PATCH 027/147] gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 742d1b5f..65fbe33f 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,5 @@ community-server/data-backup nlu/parser/target/ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml + +dialog/src/main/java/roboy/util/api/apiKeys\.yml From 5c91636d2838f8bb4f663f15b81c0b70cdbbecdb Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Wed, 15 Aug 2018 02:58:10 +0200 Subject: [PATCH 028/147] Like, hypersexy space alien shit, or something --- config.properties | 9 +- .../roboy/dialog/ConversationManager.java | 1 + .../devoStates/QuestionRoboyQAState.java | 356 ++++++++++++++++++ .../states/expoStates/RoboyQAState.java | 1 - .../QuestionAnsweringState.java | 1 - .../main/java/roboy/linguistics/Triple.java | 13 +- .../sentenceanalysis/Interpretation.java | 49 +++ .../sentenceanalysis/Postprocessor.java | 14 + .../personalityFiles/DevoPersonality.json | 93 +++++ 9 files changed, 528 insertions(+), 9 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java create mode 100644 dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java create mode 100644 resources/personalityFiles/DevoPersonality.json diff --git a/config.properties b/config.properties index 4048d695..1730e367 100755 --- a/config.properties +++ b/config.properties @@ -49,11 +49,12 @@ UDP_HOST_ADDRESS: 127.0.0.1 PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/ExpoPersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" +# PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" @@ -69,13 +70,13 @@ TELEGRAM_API_TOKENS_FILE: "" # Memory: java.util.logging # https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html -MEMORY_LOG_MODE: "WARNING" +MEMORY_LOG_MODE: "DEBUG" # Dialog: LOG4J 2 # https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html # https://logging.apache.org/log4j/2.x/manual/customloglevels.html -DIALOG_LOG_MODE: "WARN" +DIALOG_LOG_MODE: "DEBUG" # Parser/NLU: LogInfo # Supports all Log4J levels. See Documentation for more details -PARSER_LOG_MODE: "WARN" \ No newline at end of file +PARSER_LOG_MODE: "DEBUG" \ No newline at end of file diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index e24482e0..47799980 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -86,6 +86,7 @@ public static void main(String[] args) throws IOException { analyzers.add(new EmotionAnalyzer()); analyzers.add(new ProfanityAnalyzer()); + analyzers.add(new Postprocessor()); //I/O specific core behaviour diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java new file mode 100644 index 00000000..745995eb --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -0,0 +1,356 @@ +package roboy.dialog.states.devoStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.states.definitions.ExpoState; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState; +import roboy.linguistics.Linguistics; +import roboy.linguistics.Linguistics.SemanticRole; +import roboy.linguistics.Triple; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.Neo4jProperty; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; +import roboy.talk.PhraseCollection; +import roboy.util.Agedater; +import roboy.util.Pair; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.*; + +import static roboy.memory.Neo4jProperty.full_name; +import static roboy.memory.Neo4jProperty.name; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; + +/** + * QuestionAnsweringState + * Roboy Question Answering State + * + * The parser: + * - provides triples generated from the question + * - adds the answer to the question if there is an answer in DBpedia + * - tells a specifying followup question if the interlocutor's question was ambiguous + * + * This state: + * - checks if interlocutor wants to play a game + * - returns the answer if provided by the parser + * - asks the specifying followup question if provided by the parser + * - - if answered with yes --> will use the parser again to get the answer to the original question + * - if answered with no --> will use a segue to avoid answer + * - tries to query memory if there is no answer to the question + * - queries the fallback if memory fails to answer as well + * + * + * QuestionAnsweringState interface: + * 1) Fallback is required. + * 2) Outgoing transitions that have to be defined: + * - finishedQuestionAnswering: following state if this state if finished with answering questions + * 3) No parameters are used. + */ +public class QuestionRoboyQAState extends ExpoState { + private final Logger LOGGER = LogManager.getLogger(); + + private final static String TRANSITION_FINISHED_ANSWERING = "finishedQuestionAnswering"; + private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; + private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; + private final static int MAX_NUM_OF_QUESTIONS = 5; + private int questionsAnswered = 0; + + private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; + private final static RandomList answerStartingPhrases = PhraseCollection.QUESTION_ANSWERING_START; + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + + private boolean askingSpecifyingQuestion = false; + private String answerAfterUnspecifiedQuestion = ""; // the answer to use if specifying question is answered with YES + private boolean userWantsGame = false; + + private QAJsonParser infoValues; + + public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info("The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); + } + + @Override + public Output act() { + if (questionsAnswered > 0) { + return Output.say(reenteringPhrases.getRandomElement()); + } + return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + } + + @Override + public Output react(Interpretation input) { + return reactToQuestion(input); + } + + private Output reactToQuestion(Interpretation input) { + + askingSpecifyingQuestion = false; + questionsAnswered++; + + if (input.getTokens() != null && !(input.getTokens().contains("you") || input.getTokens().contains("your"))) { + Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); + if (parseOutcome == null) { + LOGGER.error("Invalid parser outcome!"); + return Output.say("Invalid parser outcome!"); + } + + if (parseOutcome == Linguistics.ParsingOutcome.SUCCESS) { + if (input.getAnswer() != null) { + // tell the answer, that was provided by the parser + return Output.say(answerStartingPhrases.getRandomElement() + " " + input.getAnswer()); + } + } + } + + // from here we know that dummyParserResult.equals("FAILURE") + return useMemoryOrFallback(input); + } + + @Override + public State getNextState() { + + if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state + return this; + + } else if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + return getTransition(TRANSITION_FINISHED_ANSWERING); + + } else if (Math.random() < 0.5) { // loop back to previous states with probability 0.5 + + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + Neo4jRelationship[] predicates = {FROM, HAS_HOBBY, WORK_FOR, STUDY_AT}; + Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(predicates); + + if (availability == SOME_AVAILABLE) { + return (Math.random() < 0.3) ? getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON) : getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else if (availability == NONE_AVAILABLE) { + return getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else { + if (!isIntentsHistoryComplete(predicates)) { + return getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON); + } else { + return this; + } + } + } else { // stay in this state + return this; + } + + } + + private Output useMemoryOrFallback(Interpretation input) { + try { + if (input.getPas() != null || input.getTriples() != null) { + Output memoryAnswer = answerFromMemory(input); + if (memoryAnswer != null) return memoryAnswer; + } + } catch (Exception e) { + LOGGER.warn(e.getMessage()); + } + + return Output.useFallback(); + } + + private Output answerFromMemory(Interpretation input) { + + // try to use memory to answer + Roboy roboy = new Roboy(getMemory()); + + //String answer = String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), inferMemoryAnswer(input, roboy)); + String answer = String.format("%s", inferMemoryAnswer(input, roboy)); + if (answer.equals("")) { + return Output.useFallback(); + } + return Output.say(answer); + } + + private String inferMemoryAnswer(Interpretation input, Roboy roboy) { + + String answer = ""; + Map pas = input.getPas(); + List triples = input.getTriples(); + + if (pas != null) { + return inferPasAnswer(pas, roboy); + } + + if (triples != null) { + return inferTripleAnswer(triples, roboy); + } + + if (input.getObjAnswer() != null) { + String objAnswer = input.getObjAnswer().toLowerCase(); + if (!objAnswer.equals("")) { + LOGGER.info("OBJ_ANSWER: " + objAnswer); + Neo4jRelationship predicate = inferPredicateFromObjectAnswer(objAnswer); + if (predicate != null) { + answer = extractNodeNameForPredicate(predicate, roboy); + } + } else { + LOGGER.warn("OBJ_ANSWER is empty"); + } + } + + return answer; + } + + private String inferPasAnswer(Map pas, Roboy roboy) { + String answer = ""; + if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { + answer = extractAge(roboy); + // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bweather\\b.*"))) { + // // -> Weather API + // } else if (matchPas(pas, new Pair(SemanticRole.AGENT, ".*\\bmovie.*"))) { + // // -> Movie API + // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.MANNER, "how"), new Pair(SemanticRole.PREDICATE, "say"), new Pair(SemanticRole.AGENT, "you")) || + // matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.PREDICATE, "is"), new Pair(SemanticRole.AGENT, "what"))) { + // // translate(*,**) + } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { + answer = Math.random() > .5 ? + extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : + extractNodeNameForPredicate(Neo4jRelationship.MEMBER_OF, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { + answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { + answer = "Yo moma says I am a good boy!"; + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "who"))) { + if (matchPas(pas, new Pair(SemanticRole.PATIENT, "you"))) { + answer = extractNodeNameForPredicate(Neo4jProperty.full_name, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\b(father|dad)\\b.*"))) { + answer = extractNodeNameForPredicate(Neo4jRelationship.CHILD_OF, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\b(sibling|brother)\\b.*"))){ + answer = extractNodeNameForPredicate(Neo4jRelationship.SIBLING_OF, roboy); + } + } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "do|like"), new Pair(SemanticRole.AGENT, "you"))){ + double prob = Math.random(); + if (prob < .3) { + answer = extractNodeNameForPredicate(Neo4jProperty.abilities, roboy); + } else if(prob < .7) { + answer = extractNodeNameForPredicate(Neo4jRelationship.HAS_HOBBY, roboy); + } else { + answer = extractNodeNameForPredicate(Neo4jProperty.skills, roboy); + } + } + + return answer; + } + + private String inferTripleAnswer(List triples, Roboy roboy) { + String answer = ""; + // else if {OBJ: *} -> query * -> I'm sure I know a typeof(*) called *! (Where does he live? :)) + // + // if * in Neo4jRelationship.FRIEND_OF + return answer; + } + + private Neo4jRelationship inferPredicateFromObjectAnswer(String objectAnswer) { + if (objectAnswer.contains("hobb")) { + return Neo4jRelationship.HAS_HOBBY; + } else if (objectAnswer.contains("member")) { + return Neo4jRelationship.MEMBER_OF; + } else if (objectAnswer.contains("friend")) { + return Neo4jRelationship.FRIEND_OF; + } else if (objectAnswer.contains("where") || + objectAnswer.contains("city") || + objectAnswer.contains("place") || + objectAnswer.contains("country") || + objectAnswer.contains("live") || + objectAnswer.contains("life")) { + return Neo4jRelationship.LIVE_IN; + } else if (objectAnswer.contains("from") || + objectAnswer.contains("born")) { + return Neo4jRelationship.FROM; + } else if (objectAnswer.contains("child") || + objectAnswer.contains("father") || + objectAnswer.contains("dad") || + objectAnswer.contains("parent")) { + return Neo4jRelationship.CHILD_OF; + } else if (objectAnswer.contains("brother") || + objectAnswer.contains("family") || + objectAnswer.contains("relativ")) { + return Neo4jRelationship.SIBLING_OF; + } + return null; + } + + private String extractNodeNameForPredicate(Neo4jRelationship predicate, Roboy roboy) { + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + return String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + return null; + } + + private String extractNodeNameForPredicate(Neo4jProperty predicate, Roboy roboy) { + String property = roboy.getProperty(predicate).toString(); + if (property != null) { + return String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), property); + } + return null; + } + + private String extractAge(Roboy roboy) { + HashMap ages = new Agedater().determineAge(roboy.getProperty(Neo4jProperty.birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + return String.format(infoValues.getSuccessAnswers(Neo4jProperty.age).getRandomElement(), retrievedAge); + } + + private boolean matchPas(Map pas, Pair... matchCriteria) { + if (pas == null) + return false; + boolean allCriteriaSatisfied = true; + for (Pair criterion : matchCriteria) { + if (!pas.containsKey(criterion.getKey()) || + !pas.get(criterion.getKey()).matches(criterion.getValue())) { + allCriteriaSatisfied = false; + break; + } + } + return allCriteriaSatisfied; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(TRANSITION_FINISHED_ANSWERING, TRANSITION_LOOP_TO_NEW_PERSON, TRANSITION_LOOP_TO_KNOWN_PERSON); + } + + @Override + public boolean isFallbackRequired() { + return true; + } + + private boolean isIntentsHistoryComplete(Neo4jRelationship[] predicates) { + boolean isComplete = true; + for (Neo4jRelationship predicate : predicates) { + if (!getContext().DIALOG_INTENTS.contains(new IntentValue(PersonalInformationFollowUpState.INTENTS_HISTORY_ID, predicate))) { + isComplete = false; + } + } + return isComplete; + } +} \ No newline at end of file diff --git a/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java index d6820cd9..f4f28d11 100644 --- a/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java @@ -2,7 +2,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import roboy.context.Context; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.dialog.states.definitions.ExpoState; diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java index 7f50d938..501d72fb 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java @@ -2,7 +2,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import roboy.context.Context; import roboy.context.contextObjects.IntentValue; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; diff --git a/dialog/src/main/java/roboy/linguistics/Triple.java b/dialog/src/main/java/roboy/linguistics/Triple.java index 7dc04e7b..a94901d6 100755 --- a/dialog/src/main/java/roboy/linguistics/Triple.java +++ b/dialog/src/main/java/roboy/linguistics/Triple.java @@ -17,12 +17,19 @@ public Triple(String subject, String predicate, String object){ this.object = object; } + public Triple toLowerCase() { + return new Triple( + this.subject != null ? this.subject.toLowerCase() : null, + this.predicate != null ? this.predicate.toLowerCase() : null, + this.object != null ? this.object.toLowerCase() : null); + } + @Override public String toString() { return "Triple{" + - "SUB: '" + subject + '\'' + - ", PRED: '" + predicate + '\'' + - ", OBJ: '" + object + '\'' + + "SUB: '" + subject + "\'," + + "PRED: '" + predicate + "\'," + + "OBJ: '" + object + "\'" + '}'; } diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java index 315b5d9c..575c2054 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java @@ -478,6 +478,55 @@ public String toString() { '}'; } + public void toLowerCase() { + if (sentence != null) { + sentence = sentence.toLowerCase(); + } + if (triples != null) { + for (int i = 0; i < triples.size(); i++) { + if (triples.get(i) != null) { + triples.set(i, triples.get(i).toLowerCase()); + } + } + } + if (tokens != null) { + for (int i = 0; i < tokens.size(); i++) { + if (tokens.get(i) != null) { + tokens.set(i, tokens.get(i).toLowerCase()); + } + } + } + if (this.lemmas != null) { + for (int i = 0; i < lemmas.length; i++) { + if (lemmas[i] != null) { + lemmas[i] = lemmas[i].toLowerCase(); + } + } + } + if (this.pas != null) { + for (SemanticRole key : pas.keySet()) { + if (pas.get(key) != null) { + pas.replace(key, pas.get(key).toLowerCase()); + } + } + } + if (this.name != null) { + this.name = this.name.toLowerCase(); + } + if (this.objAnswer != null) { + this.objAnswer = this.objAnswer.toLowerCase(); + } + if (this.predAnswer != null) { + this.predAnswer = this.predAnswer.toLowerCase(); + } + if (this.underspecifiedQuestion != null) { + this.underspecifiedQuestion = this.underspecifiedQuestion.toLowerCase(); + } + if (this.underspecifiedAnswer != null) { + this.underspecifiedAnswer = this.underspecifiedAnswer.toLowerCase(); + } + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java new file mode 100644 index 00000000..5b677c7e --- /dev/null +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java @@ -0,0 +1,14 @@ +package roboy.linguistics.sentenceanalysis; + +import roboy.linguistics.Linguistics; + +/** + * Corrects abbreviated forms like "I'm" to complete forms like "I am" + * which are expected by later sentence analyses. + */ +public class Postprocessor implements Analyzer{ + public Interpretation analyze(Interpretation interpretation){ + interpretation.toLowerCase(); + return interpretation; + } +} diff --git a/resources/personalityFiles/DevoPersonality.json b/resources/personalityFiles/DevoPersonality.json new file mode 100644 index 00000000..b65d2ee4 --- /dev/null +++ b/resources/personalityFiles/DevoPersonality.json @@ -0,0 +1,93 @@ +{ + "initialState": "Greetings", + "states": [ + { + "identifier": "Greetings", + "implementation": "roboy.dialog.states.ordinaryStates.PassiveGreetingsState", + "transitions": { + "greetingDetected": "Intro" + } + }, + { + "identifier": "Intro", + "implementation": "roboy.dialog.states.ordinaryStates.IntroductionState", + "transitions": { + "knownPerson": "FollowUp", + "newPerson": "PersonalQA" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" + } + }, + { + "identifier": "FollowUp", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState", + "transitions": { + "questionAnswering": "QuestionAnswering" + }, + "parameters": { + "qaFile": "resources/sentences/QAList.json" + } + }, + { + "identifier": "PersonalQA", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "transitions": { + "questionAnswering": "QuestionAnswering" + }, + "parameters": { + "qaFile": "resources/sentences/QAList.json" + } + }, + { + "identifier": "QuestionAnswering", + "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", + "fallback": "WildTalk", + "transitions": { + "finishedQuestionAnswering": "Farewell", + "loopToNewPerson": "PersonalQA", + "loopToKnownPerson": "FollowUp", + "switchToGaming": "ChooseGameState" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" + } + }, + { + "identifier": "GamingTwentyQuestionsState", + "implementation": "roboy.dialog.states.gameStates.GamingTwentyQuestionsState", + "transitions": { + "gameEnded" : "QuestionAnswering" + } + }, + { + "identifier": "GamingSnapchatState", + "implementation": "roboy.dialog.states.gameStates.GamingSnapchatState", + "transitions": { + "gameEnded" : "QuestionAnswering" + }, + "parameters": { + "filterFile": "resources/gameResources/snapchat-filters.txt" + } + }, + { + "identifier": "ChooseGameState", + "implementation": "roboy.dialog.states.gameStates.ChooseGameState", + "transitions": { + "choseSnapchat" : "GamingSnapchatState", + "chose20questions" : "GamingTwentyQuestionsState", + "exitGame": "QuestionAnswering" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + }, + { + "identifier": "Farewell", + "implementation": "roboy.dialog.states.ordinaryStates.FarewellState", + "transitions": {} + } + ] +} \ No newline at end of file From 8435bdeae1ac7d86a9a11cdafd74be96206ea107 Mon Sep 17 00:00:00 2001 From: SezerCan Date: Wed, 15 Aug 2018 10:44:31 +0200 Subject: [PATCH 029/147] Redesigned TelegramBot.json and BotBoyState. BotBoyFarewellState, BotBoyIntroductionState, BotBoyPersonalInformationAskingState, BotBoyPersonalInformationFollowUpState, BotBoyQuestionAnsweringState are added to states.botboy --- .../states/botboy/BotBoyFarewellState.java | 79 +++++ .../botboy/BotBoyIntroductionState.java | 214 ++++++++++++++ .../BotBoyPersonalInformationAskingState.java | 138 +++++++++ ...otBoyPersonalInformationFollowUpState.java | 168 +++++++++++ .../botboy/BotBoyQuestionAnsweringState.java | 273 ++++++++++++++++++ .../dialog/states/botboy/BotBoyState.java | 4 +- .../personalityFiles/bot/TelegramBot.json | 17 +- 7 files changed, 880 insertions(+), 13 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyFarewellState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationAskingState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationFollowUpState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyQuestionAnsweringState.java diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyFarewellState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyFarewellState.java new file mode 100644 index 00000000..3ea9d7a8 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyFarewellState.java @@ -0,0 +1,79 @@ +package roboy.dialog.states.botboy; + +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.logic.StatementInterpreter; +import roboy.talk.Verbalizer; +import roboy.util.RandomList; + +import java.util.Set; + +/** + * This state ends the conversation. + * + * BotBoyFarewellState interface: + * 1) Fallback is not required. + * 2) This state has no outgoing transitions. + * 3) No parameters are used. + */ + +public class BotBoyFarewellState extends State { + private State next = null; + private int loops = 0; + private final static int MAX_LOOP_COUNT = 2; + + public BotBoyFarewellState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + private static RandomList conversationEndings = new RandomList<>( + "What a nice conversation! I have to think about everything we" + + " were talking about. Let's talk again next time.", + "I feel tired now, maybe my battery is low? Let's talk again later.", + "Don't you think that the dialog team is amazing? They are happy to " + + "tell you more about my system. Just ask one of them!"); + + @Override + public Output act() { + if (loops > MAX_LOOP_COUNT) { + // force conversation stop after a few loops + return Output.endConversation(Verbalizer.farewells.getRandomElement()); + } + return Output.say(conversationEndings.getRandomElement()); + } + + @Override + public Output react(Interpretation input) { + + String sentence = input.getSentence(); + if (StatementInterpreter.isFromList(sentence, Verbalizer.farewells)) { + next = null; + } else { + next = this; + loops++; + } + + return Output.sayNothing(); + } + + @Override + public State getNextState() { + return next; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(); + } + + @Override + public boolean isFallbackRequired() { + return false; + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java new file mode 100644 index 00000000..9ad6df38 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java @@ -0,0 +1,214 @@ +package roboy.dialog.states.botboy; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jProperty; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.Interlocutor.RelationshipAvailability; +import roboy.memory.nodes.Roboy; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.dialog.Segue; +import roboy.util.Agedater; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.*; + +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.Neo4jProperty.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.*; + +/** + * This state will: + * - ask the interlocutor for his name + * - query memory if the person is already known + * - create and update the interlocutor in the context + * - take one of two transitions: knownPerson or newPerson + * + * BotBoyIntroductionState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - knownPerson: following state if the person is already known + * - newPerson: following state if the person is NOT known + * 3) No parameters are used. + */ +public class BotBoyIntroductionState extends State { + private QAJsonParser infoValues; + private final String UPDATE_KNOWN_PERSON = "knownPerson"; + private final String LEARN_ABOUT_PERSON = "newPerson"; + private final Logger LOGGER = LogManager.getLogger(); + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + private final RandomList introPhrases = new RandomList<>("May I ask your name?"); + private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!", "Hey, I remember you, %s"); + private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!", "Glad to meet you, %s"); + + private Neo4jRelationship[] personPredicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); + private State nextState; + + public BotBoyIntroductionState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info(" -> The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); + } + + @Override + public Output act() { + return Output.say(getIntroPhrase()); + } + + @Override + public Output react(Interpretation input) { + // expecting something like "My name is NAME" + + // 1. get name + String name = getNameFromInput(input); + + if (name == null) { + // input couldn't be parsed properly + // TODO: do something intelligent if the parser fails + nextState = this; + LOGGER.warn("IntroductionState couldn't get name! Staying in the same state."); + return Output.say("Sorry, my parser is out of service."); + // alternatively: Output.useFallback() or Output.sayNothing() + } + + + // 2. get interlocutor object from context + // this also should query memory and do other magic + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + person.addName(name); + // Roboy roboy = new Roboy(getMemory()); + + + // 3. update interlocutor in context + updateInterlocutorInContext(person); + String retrievedPersonalFact = ""; + Double segueProbability = 0.0; + + // 4. check if person is known/familiar + if (person.FAMILIAR) { + // 4a. person known/familiar + RandomList nodes = getMemNodesByIds(person.getRelationships(FRIEND_OF)); + if (!nodes.isEmpty()) { + retrievedPersonalFact = " You are friends with " + + nodes.getRandomElement().getProperties().get(Neo4jProperty.name).toString(); + } + + RelationshipAvailability availability = person.checkRelationshipAvailability(personPredicates); + if (availability == SOME_AVAILABLE) { + nextState = (Math.random() < 0.3) ? getTransition(UPDATE_KNOWN_PERSON) : getTransition(LEARN_ABOUT_PERSON); + } else if (availability == NONE_AVAILABLE) { + nextState = getTransition(LEARN_ABOUT_PERSON); + } else { + nextState = getTransition(UPDATE_KNOWN_PERSON); + } + } else { + // 4b. person is not known + nextState = getTransition(LEARN_ABOUT_PERSON); + segueProbability = 0.6; + } + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + + if(person.FAMILIAR) { + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + " It is great to chat with you again!").setSegue(s); + } + + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); + } + + @Override + public State getNextState() { + return nextState; + } + + private String getNameFromInput(Interpretation input) { + return getInference().inferProperty(name, input); + } + + private void updateInterlocutorInContext(Interlocutor interlocutor) { + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(interlocutor); + } + + private String getIntroPhrase() { + return introPhrases.getRandomElement(); + } + + private String getResponsePhrase(String name, boolean familiar) { + if (familiar) { + return String.format(successResponsePhrases.getRandomElement(), name); + } else { + return String.format(failureResponsePhrases.getRandomElement(), name); + } + } + + private String getRoboyFactsPhrase(Roboy roboy) { + String result = ""; + + // Get some random properties facts + if (roboy.getProperties() != null && !roboy.getProperties().isEmpty()) { + HashMap properties = roboy.getProperties(); + if (properties.containsKey(full_name)) { + result += " " + String.format(infoValues.getSuccessAnswers(full_name).getRandomElement(), properties.get(full_name)); + } + if (properties.containsKey(birthdate)) { + HashMap ages = new Agedater().determineAge(properties.get(birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), retrievedAge); + } else if (properties.containsKey(age)) { + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); + } + if (properties.containsKey(skills)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(abilities)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(future)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + } + } + + if (result.equals("")) { + result = "I am Roboy 2.0! "; + } + + // Get a random relationship fact + Neo4jRelationship predicate = roboyRelatioshipPredicates.getRandomElement(); + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName = ""; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + result += " " + String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + + return result; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(UPDATE_KNOWN_PERSON, LEARN_ABOUT_PERSON); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationAskingState.java new file mode 100644 index 00000000..3ebaf80f --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationAskingState.java @@ -0,0 +1,138 @@ +package roboy.dialog.states.botboy; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.dialog.Segue; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Set; + +import static roboy.memory.Neo4jRelationship.*; + +/** + * Personal Information Asking State + * + * The state tries to interact with the Interlocutor to learn new information about the person. + * This information is sent to the Roboy Memory Module through Neo4jMemoryInterface for storing. + * Afterwards, Roboy can use this acquired data for the future interactions with the same person. + * + * - if there is no existing Interlocutor or the data is missing, ask a question + * - the question topic (intent) is selected from the Neo4jRelationship predicates + * - retrieve the questions stored in the QAList json file + * - update the Context IntentsHistory + * - try to extract the result from the Interpretation + * - retrieve the answers stored in the QAList json file + * - send the result to Memory + * + * BotBoyPersonalInformationAskingState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - TRANSITION_INFO_OBTAINED: following state if the question was asked + * 3) Required parameters: path to the QAList.json file. + */ +public class BotBoyPersonalInformationAskingState extends State { + private QAJsonParser qaValues; + private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private Neo4jRelationship selectedPredicate; + private State nextState; + + private final String TRANSITION_INFO_OBTAINED = "questionAnswering"; + private final String QA_FILE_PARAMETER_ID = "qaFile"; + final Logger LOGGER = LogManager.getLogger(); + + public final static String INTENTS_HISTORY_ID = "PIA"; + + public BotBoyPersonalInformationAskingState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); + LOGGER.info(" -> The QAList path: " + qaListPath); + qaValues = new QAJsonParser(qaListPath); + } + + @Override + public Output act() { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info(" -> Retrieved Interlocutor: " + person.getName()); + + for (Neo4jRelationship predicate : predicates) { + if (!person.hasRelationship(predicate)) { + selectedPredicate = predicate; + LOGGER.info(" -> Selected predicate: " + selectedPredicate.type); + break; + } + } + RandomList questions = qaValues.getQuestions(selectedPredicate); + String question = ""; + if (questions != null && !questions.isEmpty()) { + question = questions.getRandomElement(); + LOGGER.info(" -> Selected question: " + question); + } else { + LOGGER.error(" -> The list of " + selectedPredicate.type + " questions is empty or null"); + } + try { + getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, selectedPredicate)); + LOGGER.info(" -> Dialog IntentsHistory updated"); + } catch (Exception e) { + LOGGER.error(" -> Error on updating the IntentHistory: " + e.getMessage()); + } + return State.Output.say(question); + } + + @Override + public Output react(Interpretation input) { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); + RandomList answers; + String answer = "I have no words"; + String result = InferResult(input); + + if (result != null && !result.equals("")) { + LOGGER.info(" -> Inference was successful"); + answers = qaValues.getSuccessAnswers(selectedPredicate); + person.addInformation(selectedPredicate, result); + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(person); + LOGGER.info(" -> Updated Interlocutor: " + person.getName()); + } else { + LOGGER.warn(" -> Inference failed"); + answers = qaValues.getFailureAnswers(selectedPredicate); + result = ""; + LOGGER.warn(" -> The result is empty. Nothing to store"); + } + if (answers != null && !answers.isEmpty()) { + answer = String.format(answers.getRandomElement(), result); + } else { + LOGGER.error(" -> The list of " + selectedPredicate + " answers is empty or null"); + } + LOGGER.info(" -> Produced answer: " + answer); + nextState = getTransition(TRANSITION_INFO_OBTAINED); + Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE, 0.5); + return Output.say(answer).setSegue(s); + } + + @Override + public State getNextState() { + return nextState; + } + + @Override + protected Set getRequiredTransitionNames() { + // optional: define all required transitions here: + return newSet(TRANSITION_INFO_OBTAINED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(QA_FILE_PARAMETER_ID); + } + + private String InferResult(Interpretation input) { + return getInference().inferRelationship(selectedPredicate, input); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationFollowUpState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationFollowUpState.java new file mode 100644 index 00000000..b4f2d02b --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationFollowUpState.java @@ -0,0 +1,168 @@ +package roboy.dialog.states.botboy; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Set; + +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.Neo4jProperty.*; + +/** + * Personal Information Update State + * + * This state is only entered if there are some known facts about the active interlocutor. + * The state tries to interact with the Interlocutor to update the existing information about the person. + * This information is sent to the Roboy Memory Module through Neo4jMemoryInterface to keep it up to date. + * + * - if there is an existing entry under a specific Neo4jRelationship predicate, select the predicate + * - check the Context IntentsHistory if we already asked similar questions + * - the question topic (intent) is selected upon the predicate + * - update the Context IntentsHistory with the selected predicate + * - retrieve the follow-up questions stored in the QAList json file + * - retrieve the follow-up answers stored in the QAList json file + * + * BotBoyPersonalInformationFollowUpState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - TRANSITION_INFO_UPDATED: following state if the question was asked + * 3) Required parameters: path to the QAList.json file. + */ + +public class BotBoyPersonalInformationFollowUpState extends State { + private QAJsonParser qaValues; + private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private Neo4jRelationship selectedPredicate; + private State nextState; + + private final String TRANSITION_INFO_UPDATED = "questionAnswering"; + private final String QA_FILE_PARAMETER_ID = "qaFile"; + private final Logger LOGGER = LogManager.getLogger(); + + public final static String INTENTS_HISTORY_ID = "FUP"; + + public BotBoyPersonalInformationFollowUpState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); + LOGGER.info(" -> The QAList path: " + qaListPath); + qaValues = new QAJsonParser(qaListPath); + } + + @Override + public Output act() { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); + + for (Neo4jRelationship predicate : predicates) { + if (person.hasRelationship(predicate) && + !getContext().DIALOG_INTENTS.contains(new IntentValue(INTENTS_HISTORY_ID, predicate)) && + !getContext().DIALOG_INTENTS.contains(new IntentValue(BotBoyPersonalInformationAskingState.INTENTS_HISTORY_ID, predicate))) { + selectedPredicate = predicate; + LOGGER.info(" -> Selected predicate: " + selectedPredicate.type); + break; + } + } + + Segue s = new Segue(Segue.SegueType.DISTRACT, 1.0); + if (selectedPredicate != null) { + RandomList questions = qaValues.getFollowUpQuestions(selectedPredicate); + String retrievedResult = ""; + RandomList nodes = getMemNodesByIds(person.getRelationships(selectedPredicate)); + if (!nodes.isEmpty()) { + retrievedResult = nodes.getRandomElement().getProperties().get(name).toString(); + LOGGER.info(" -> Retrieved memory node name: " + retrievedResult); + } else { + LOGGER.error("Could not retrieve memory data"); + } + if (!retrievedResult.equals("")) { + String question = ""; + if (questions != null && !questions.isEmpty()) { + question = String.format(questions.getRandomElement(), retrievedResult); + LOGGER.info(" -> Selected question: " + question); + } else { + LOGGER.error(" -> The list of " + selectedPredicate.type + " questions is empty or null"); + } + try { + getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, selectedPredicate)); + LOGGER.info(" -> Dialog IntentsHistory updated"); + } catch (Exception e) { + LOGGER.error(" -> Error on updating the IntentHistory: " + e.getMessage()); + } + return Output.say(question); + } else { + LOGGER.error("The retrieved memory data is empty"); + return Output.sayNothing().setSegue(s); + } + } else { + return Output.sayNothing().setSegue(s); + } + } + + @Override + public Output react(Interpretation input) { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); + RandomList answers; + String answer = "I have no words"; + String result = InferUpdateResult(input); + + if (selectedPredicate != null) { + if (result != null && !result.equals("")) { + LOGGER.info(" -> Inference was successful"); + answers = qaValues.getFollowUpAnswers(selectedPredicate); + person.addInformation(selectedPredicate, result); + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(person); + LOGGER.info(" -> Updated Interlocutor: " + person.getName()); + } else { + LOGGER.warn(" -> Inference failed"); + answers = qaValues.getFollowUpAnswers(selectedPredicate); + LOGGER.warn(" -> The result is empty. Nothing to update"); + } + if (answers != null && !answers.isEmpty()) { + answer = String.format(answers.getRandomElement(), ""); + } else { + LOGGER.error(" -> The list of " + selectedPredicate + " answers is empty or null"); + } + } else { + LOGGER.error(" -> Selected predicate is null"); + } + + nextState = getTransition(TRANSITION_INFO_UPDATED); + Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE); + return Output.say(answer).setSegue(s); + } + + @Override + public State getNextState() { + return nextState; + } + + @Override + protected Set getRequiredTransitionNames() { + // optional: define all required transitions here: + return newSet(TRANSITION_INFO_UPDATED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(QA_FILE_PARAMETER_ID); + } + + private String InferUpdateResult(Interpretation input) { + String result = null; + // TODO: Implement + // TODO: Will need to consider proper conditions for processing + + return result; + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyQuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyQuestionAnsweringState.java new file mode 100644 index 00000000..3e53bf00 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyQuestionAnsweringState.java @@ -0,0 +1,273 @@ +package roboy.dialog.states.botboy; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState; +import roboy.linguistics.Linguistics; +import roboy.linguistics.Triple; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.Interlocutor.RelationshipAvailability; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; +import roboy.dialog.Segue; +import roboy.talk.PhraseCollection; +import roboy.talk.Verbalizer; +import roboy.util.RandomList; + +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.*; + +import java.util.List; +import java.util.Set; + +/** + * This state will answer generalStates questions. + * The parser: + * - provides triples generated from the question + * - adds the answer to the question if there is an answer in DBpedia + * - tells a specifying followup question if the interlocutor's question was ambiguous + * + * This state: + * - returns the answer if provided by the parser + * - asks the specifying followup question if provided by the parser + * - - if answered with yes --> will use the parser again to get the answer to the original question + * - if answered with no --> will use a segue to avoid answer + * - tries to query memory if there is no answer to the question + * - queries the fallback if memory fails to answer as well + * + * + * BotBoyQuestionAnsweringState interface: + * 1) Fallback is required. + * 2) Outgoing transitions that have to be defined: + * - finishedQuestionAnswering: following state if this state if finished with answering questions + * 3) No parameters are used. + */ + +public class BotBoyQuestionAnsweringState extends State { + private final Logger logger = LogManager.getLogger(); + + private final static String TRANSITION_FINISHED_ANSWERING = "finishedQuestionAnswering"; + private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; + private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; + private final static int MAX_NUM_OF_QUESTIONS = 5; + private int questionsAnswered = 0; + + private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; + private final static RandomList answerStartingPhrases = PhraseCollection.QUESTION_ANSWERING_START; + + private boolean askingSpecifyingQuestion = false; + private String answerAfterUnspecifiedQuestion = ""; // the answer to use if specifying question is answered with YES + + public BotBoyQuestionAnsweringState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + @Override + public Output act() { + + if (askingSpecifyingQuestion) { + return Output.sayNothing(); + } + + if (questionsAnswered > 0) { + return Output.say(reenteringPhrases.getRandomElement()); + } + return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + } + + @Override + public Output react(Interpretation input) { + + if (askingSpecifyingQuestion) { + askingSpecifyingQuestion = false; + return reactToSpecifyingAnswer(input); + + } else{ + return reactToQuestion(input); + } + + } + + /** + * React to answer of the specifying question asked previously. + * + * @param input something like "yes" or "no" + * @return answer to the answer to the original question if specifying question was answered with 'yes' + */ + private Output reactToSpecifyingAnswer(Interpretation input) { + + askingSpecifyingQuestion = false; + + // check if answer is yes + if (input.getSentence() != null && input.getSentence().contains("yes")) { + if (answerAfterUnspecifiedQuestion == null) { + // parser could parse the question but did't provide an answer + return Output.say("Not sure about the answer, " + + "but at least my amazing parser could understand you! ") + .setSegue(new Segue(Segue.SegueType.FLATTERY, 0.4)); + } else { + // tell the response previously cached in answerAfterUnspecifiedQuestion + return Output.say("In this case, " + answerStartingPhrases.getRandomElement() + answerAfterUnspecifiedQuestion); + } + + } else { + // the answer is no. we don't ask more specifying questions + // use avoid answer segue + return Output.sayNothing().setSegue(new Segue(Segue.SegueType.AVOID_ANSWER, 1)); + } + } + + private Output reactToQuestion(Interpretation input) { + + askingSpecifyingQuestion = false; + questionsAnswered++; + + Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); + if (parseOutcome == null) { + logger.error("Invalid parser outcome!"); + return Output.say("Invalid parser outcome!"); + } + + if (parseOutcome == Linguistics.ParsingOutcome.UNDERSPECIFIED) { + + // ambiguous question, luckily the parser has prepared a followup question + // and maybe even an answer if we are lucky (we will check in reactToSpecifyingAnswer later) + + String question = input.getUnderspecifiedQuestion(); + answerAfterUnspecifiedQuestion = input.getAnswer(); // could be null, but that's fine for now + + askingSpecifyingQuestion = true; // next input should be a yes/no answer + return Output.say("Could you be more precise, please? " + question); + } + + if (parseOutcome == Linguistics.ParsingOutcome.SUCCESS) { + if (input.getAnswer() != null) { + // tell the answer, that was provided by the parser + return Output.say(answerStartingPhrases.getRandomElement() + " " + input.getAnswer()); + + } else { + // check for triple + + + // parser could parse the question but has no answer + return useMemoryOrFallback(input); + } + } + + // from here we know that dummyParserResult.equals("FAILURE") + return useMemoryOrFallback(input); + } + + @Override + public State getNextState() { + + if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state + return this; + + } else if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + return getTransition(TRANSITION_FINISHED_ANSWERING); + + } else if (Math.random() < 0.5) { // loop back to previous states with probability 0.5 + + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + RelationshipAvailability availability = person.checkRelationshipAvailability(predicates); + + if (availability == SOME_AVAILABLE) { + return (Math.random() < 0.3) ? getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON) : getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else if (availability == NONE_AVAILABLE) { + return getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else { + if (!isIntentsHistoryComplete(predicates)) { + return getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON); + } else { + return this; + } + } + } else { // stay in this state + return this; + } + + } + + private Output useMemoryOrFallback(Interpretation input) { + try { + if (input.getSemTriples() != null) { + Output memoryAnswer = answerFromMemory(input.getSemTriples()); + if (memoryAnswer != null) return memoryAnswer; + } + } catch (Exception e) { + logger.warn(e.getMessage()); + } + + return Output.useFallback(); + } + + private Output answerFromMemory(List triples) { + + // try to use memory to answer + Roboy roboy = new Roboy(getMemory()); + + if (triples.size() == 0) { + return null; + } + + String answer = "I like " + inferMemoryAnswer(triples, roboy) + "humans. "; + return Output.say(answer); + } + + private String inferMemoryAnswer(List triples, Roboy roboy) { + String answer = ""; + for (Triple result : triples) { + + if (result.predicate != null) { + if (result.predicate.contains(Neo4jRelationship.HAS_HOBBY.type)) { + RandomList nodes = getMemNodesByIds(roboy.getRelationships(Neo4jRelationship.HAS_HOBBY)); + if (!nodes.isEmpty()) { + for (MemoryNodeModel node : nodes) { + answer += node.getProperties().get("name").toString() + " and "; + } + } + break; + + } else if (result.predicate.contains(Neo4jRelationship.FRIEND_OF.type)) { + answer += "my friends "; + RandomList nodes = getMemNodesByIds(roboy.getRelationships(Neo4jRelationship.FRIEND_OF)); + if (!nodes.isEmpty()) { + for (MemoryNodeModel node : nodes) { + answer += node.getProperties().get("name").toString() + " and "; + } + } + answer += " other "; + break; + } + } + } + return answer; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(TRANSITION_FINISHED_ANSWERING, TRANSITION_LOOP_TO_NEW_PERSON, TRANSITION_LOOP_TO_KNOWN_PERSON); + } + + @Override + public boolean isFallbackRequired() { + return true; + } + + private boolean isIntentsHistoryComplete(Neo4jRelationship[] predicates) { + boolean isComplete = true; + for (Neo4jRelationship predicate : predicates) { + if (!getContext().DIALOG_INTENTS.contains(new IntentValue(BotBoyPersonalInformationFollowUpState.INTENTS_HISTORY_ID, predicate))) { + isComplete = false; + } + } + return isComplete; + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java index f3ff4a97..381e4a49 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java @@ -5,6 +5,7 @@ import org.apache.logging.log4j.Logger; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; +import roboy.emotions.RoboyEmotion; import roboy.linguistics.Linguistics; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.logic.StatementInterpreter; @@ -44,7 +45,8 @@ public Output react(Interpretation input) { if(inputOK){ next = getTransition(TRANSITION_INITIALIZED); - return Output.say(Verbalizer.greetings.getRandomElement()); + return Output.say("Hey! I was looking for someone to chat.").setEmotion(RoboyEmotion.HAPPINESS); + //return Output.say(Verbalizer.greetings.getRandomElement()); } return Output.sayNothing(); diff --git a/resources/personalityFiles/bot/TelegramBot.json b/resources/personalityFiles/bot/TelegramBot.json index 21f2709c..1af04422 100644 --- a/resources/personalityFiles/bot/TelegramBot.json +++ b/resources/personalityFiles/bot/TelegramBot.json @@ -9,16 +9,9 @@ "initialized":"Intro" } }, - { - "identifier": "Greetings", - "implementation": "roboy.dialog.states.ordinaryStates.PassiveGreetingsState", - "transitions": { - "greetingDetected": "Intro" - } - }, { "identifier": "Intro", - "implementation": "roboy.dialog.states.ordinaryStates.IntroductionState", + "implementation": "roboy.dialog.states.botboy.BotBoyIntroductionState", "transitions": { "knownPerson": "FollowUp", "newPerson": "PersonalQA" @@ -29,7 +22,7 @@ }, { "identifier": "FollowUp", - "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState", + "implementation": "roboy.dialog.states.botboy.BotBoyPersonalInformationFollowUpState", "transitions": { "questionAnswering": "QuestionAnswering" }, @@ -39,7 +32,7 @@ }, { "identifier": "PersonalQA", - "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "implementation": "roboy.dialog.states.botboy.BotBoyPersonalInformationAskingState", "transitions": { "questionAnswering": "QuestionAnswering" }, @@ -49,7 +42,7 @@ }, { "identifier": "QuestionAnswering", - "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "implementation": "roboy.dialog.states.botboy.BotBoyQuestionAnsweringState", "fallback": "WildTalk", "transitions": { "finishedQuestionAnswering": "Farewell", @@ -64,7 +57,7 @@ }, { "identifier": "Farewell", - "implementation": "roboy.dialog.states.ordinaryStates.FarewellState", + "implementation": "roboy.dialog.states.botboy.BotBoyFarewellState", "transitions": {} } ] From 061dd866c0e1c099bc161d00e09ca36a4255e1b0 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 11:21:25 +0200 Subject: [PATCH 030/147] Added usage of new NEO4J labels --- config.properties | 2 +- .../java/roboy/dialog/ConversationManager.java | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/config.properties b/config.properties index ddf91e0d..9b225241 100755 --- a/config.properties +++ b/config.properties @@ -25,7 +25,7 @@ DEMO_MODE: false INFINITE_REPETITION: true # only single input is allowed, defaults to cmdline -#INPUT: cmdline +INPUT: cmdline #INPUT: cerevoice #INPUT: udp #INPUT: bing diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index 394afd74..89d8ba9c 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -16,15 +16,14 @@ import roboy.linguistics.sentenceanalysis.*; import roboy.logic.Inference; import roboy.logic.InferenceEngine; +import roboy.memory.Neo4jLabel; import roboy.memory.Neo4jMemory; import roboy.memory.Neo4jMemoryInterface; import roboy.memory.Neo4jProperty; import roboy.memory.nodes.Interlocutor; import roboy.ros.RosMainNode; import roboy.talk.Verbalizer; -import roboy.util.ConfigManager; -import roboy.util.IO; -import roboy.util.TelegramCommunicationHandler; +import roboy.util.*; import java.io.File; import java.io.IOException; @@ -215,7 +214,18 @@ private static Conversation createConversation(RosMainNode rosMainNode, List Date: Wed, 15 Aug 2018 12:41:00 +0200 Subject: [PATCH 031/147] API shizzle --- .../src/main/java/roboy/util/api/Movie.java | 40 +++++ .../main/java/roboy/util/api/Translate.java | 140 ++++++++++++++++++ .../src/main/java/roboy/util/api/Weather.java | 40 +++++ .../src/main/java/roboy/util/api/apiKeys.yml | 3 + .../main/java/roboy/util/api/keyGetter.java | 22 +++ 5 files changed, 245 insertions(+) create mode 100644 dialog/src/main/java/roboy/util/api/Movie.java create mode 100644 dialog/src/main/java/roboy/util/api/Translate.java create mode 100644 dialog/src/main/java/roboy/util/api/Weather.java create mode 100644 dialog/src/main/java/roboy/util/api/apiKeys.yml create mode 100644 dialog/src/main/java/roboy/util/api/keyGetter.java diff --git a/dialog/src/main/java/roboy/util/api/Movie.java b/dialog/src/main/java/roboy/util/api/Movie.java new file mode 100644 index 00000000..90e57178 --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/Movie.java @@ -0,0 +1,40 @@ +package roboy.util.api; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Random; + +public class Movie{ + static String KEY = keyGetter.getKey("moviekey"); + static int randomInt = new Random().nextInt(20); + + //FIELD TITLE or OVERVIEW + public static String getData(String field) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + JsonElement jsonElement = ((JsonObject) new JsonParser().parse(result.toString())) + .getAsJsonArray("results") + .get(randomInt).getAsJsonObject().get(field); +// System.out.println(jsonObject); + return jsonElement.getAsString(); + } + + public static void main(String[] args)throws Exception{ + System.out.println(getData("title")+":\t"+getData("overview")); + } +} diff --git a/dialog/src/main/java/roboy/util/api/Translate.java b/dialog/src/main/java/roboy/util/api/Translate.java new file mode 100644 index 00000000..129220e4 --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/Translate.java @@ -0,0 +1,140 @@ +package roboy.util.api; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Translate { + static final String KEY = keyGetter.getKey("translatekey"); + + + //Language: Either Language code such as DE or language name. Text is the text to translate + public static String getData(String text, String language) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(APIify(text, handleLanguage(language))); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); +// System.out.println(jsonObject); + return jsonObject.toString(); + } + + private static String handleLanguage(String language) { + switch (language.toLowerCase()){ + case "azerbaijan": return "az"; + case "malayalam": return "ml"; + case "albanian": return "sq"; + case "maltese": return "mt"; + case "amharic": return "am"; + case "macedonian": return "mk"; + case "english": return "en"; + case "maori": return "mi"; + case "arabic": return "ar"; + case "marathi": return "mr"; + case "armenian": return "hy"; + case "mari": return "mhr"; + case "afrikaans": return "af"; + case "mongolian": return "mn"; + case "basque": return "eu"; + case "german": return "de"; + case "bashkir": return "ba"; + case "nepali": return "ne"; + case "belarusian": return "be"; + case "norwegian": return "no"; + case "bengali": return "bn"; + case "punjabi": return "pa"; + case "burmese": return "my"; + case "papiamento": return "pap"; + case "bulgarian": return "bg"; + case "persian": return "fa"; + case "bosnian": return "bs"; + case "polish": return "pl"; + case "welsh": return "cy"; + case "portuguese": return "pt"; + case "hungarian": return "hu"; + case "romanian": return "ro"; + case "vietnamese": return "vi"; + case "russian": return "ru"; + case "haitian": return "ht"; + case "cebuano": return "ceb"; + case "galician": return "gl"; + case "serbian": return "sr"; + case "dutch": return "nl"; + case "sinhala": return "si"; + case "slovakian": return "sk"; + case "greek": return "el"; + case "slovenian": return "sl"; + case "georgian": return "ka"; + case "swahili": return "sw"; + case "gujarati": return "gu"; + case "sundanese": return "su"; + case "danish": return "da"; + case "tajik": return "tg"; + case "hebrew": return "he"; + case "thai": return "th"; + case "yiddish": return "yi"; + case "tagalog": return "tl"; + case "indonesian": return "id"; + case "tamil": return "ta"; + case "irish": return "ga"; + case "tatar": return "tt"; + case "italian": return "it"; + case "telugu": return "te"; + case "icelandic": return "is"; + case "turkish": return "tr"; + case "spanish": return "es"; + case "udmurt": return "udm"; + case "kazakh": return "kk"; + case "uzbek": return "uz"; + case "kannada": return "kn"; + case "ukrainian": return "uk"; + case "catalan": return "ca"; + case "urdu": return "ur"; + case "kyrgyz": return "ky"; + case "finnish": return "fi"; + case "chinese": return "zh"; + case "french": return "fr"; + case "korean": return "ko"; + case "hindi": return "hi"; + case "xhosa": return "xh"; + case "croatian": return "hr"; + case "khmer": return "km"; + case "czech": return "cs"; + case "laotian": return "lo"; + case "swedish": return "sv"; + case "latin": return "la"; + case "scottish": return "gd"; + case "latvian": return "lv"; + case "estonian": return "et"; + case "lithuanian": return "lt"; + case "esperanto": return "eo"; + case "luxembourgish": return "lb"; + case "javanese": return "jv"; + case "malagasy": return "mg"; + case "japanese": return "ja"; + case "malay": return "ms"; + default: return language; + } + } + + private static String APIify(String text, String targetLang){ + String s = String.format("https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s", KEY, text.replace(" ", "%20"), targetLang); +// System.out.println(s); + return s; + } + + public static void main(String[] args) throws Exception{ + System.out.println(getData("cheese is the best vegetable", "german")); + } +} diff --git a/dialog/src/main/java/roboy/util/api/Weather.java b/dialog/src/main/java/roboy/util/api/Weather.java new file mode 100644 index 00000000..f04d48fb --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/Weather.java @@ -0,0 +1,40 @@ +package roboy.util.api; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Weather { + final static String KEY = keyGetter.getKey("weatherkey"); + public static String getData(String country) throws Exception{ + return getHTML(country); + } + public static String getHTML(String country) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("http://api.openweathermap.org/data/2.5/weather?q=%s&APPID=%s", country, KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + JsonObject jsonObject = (((JsonObject) new JsonParser().parse(result.toString())).get("weather").getAsJsonArray()).get(0).getAsJsonObject(); +// System.out.println(jsonObject.get("main")); + return jsonObject.get("main").getAsString(); + } + + public static void main(String[] args) throws Exception + { + //Find Munich + System.out.println(getData("munich")); + } + + +} diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/dialog/src/main/java/roboy/util/api/apiKeys.yml new file mode 100644 index 00000000..22207938 --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/apiKeys.yml @@ -0,0 +1,3 @@ +moviekey: xxxxxxxxxxxxxxxxxxxxxxxx +translatekey: xxxxxxxxxxxxxxxxxxxxxxxx +weatherkey: xxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file diff --git a/dialog/src/main/java/roboy/util/api/keyGetter.java b/dialog/src/main/java/roboy/util/api/keyGetter.java new file mode 100644 index 00000000..b91fc487 --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/keyGetter.java @@ -0,0 +1,22 @@ +package roboy.util.api; + +import org.apache.commons.configuration2.YAMLConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; + +import java.io.FileNotFoundException; +import java.io.FileReader; + +public class keyGetter { + static YAMLConfiguration yamlConfiguration = new YAMLConfiguration(); + static String getKey(String key){ + try { + yamlConfiguration.read(new FileReader("dialog/src/main/java/roboy/util/api/apiKeys.yml")); + } catch (ConfigurationException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return yamlConfiguration.getString(key); + } + +} From 9d50c7bc5a8db92eb488b81ff774852167f3f596 Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Wed, 15 Aug 2018 13:31:14 +0200 Subject: [PATCH 032/147] for alona :) --- .../ChooseInteractiveTalkState.java | 4 +-- .../states/fairShowStates/IdleState.java | 2 +- .../states/fairShowStates/InfoTalkState.java | 6 ++-- .../fairShowStates/ObjectDetectionState.java | 12 ++++--- .../sentenceanalysis/EmotionAnalyzer.java | 8 ++++- .../personalityFiles/FairShowPersonality.json | 3 +- resources_nlu/error_test/newLexicon.txt | 36 +++++++++++++++++++ 7 files changed, 58 insertions(+), 13 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java index f5f3878a..c38bb35a 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java @@ -18,10 +18,10 @@ */ public class ChooseInteractiveTalkState extends MonologState { - private final static String TRANSITION_PERSONAL_QA = "personalQA"; private final static String TRANSITION_NEW_PERSON = "newPerson"; private final static String TRANSITION_MATH = "math"; private final static String TRANSITION_GAME = "game"; + private final static String TRANSITION_PERSONAL_QA = "personalQA"; private final static String TRANSITION_OBJECT_DETECTED = "objectDetected"; private final static String TRANSITION_GENERAL_QA = "generalQA"; @@ -70,7 +70,7 @@ public State getNextState() { */ private void resetAvailableInteractions() { availableInteractions.clear(); - availableInteractions.addAll(Arrays.asList(TRANSITION_PERSONAL_QA, TRANSITION_MATH, TRANSITION_GAME, TRANSITION_GENERAL_QA)); + availableInteractions.addAll(Arrays.asList(TRANSITION_PERSONAL_QA, TRANSITION_MATH, TRANSITION_GAME)); } /** diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index 7492078d..ca162032 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -58,7 +58,7 @@ private boolean notInVision(){ return getContext().CROWD_DETECTION.getLastValue().getData() < MIN_NUMBER_PEOPLE; } catch(NullPointerException e){ - LOGGER.info("Make sure crowd detection publishing, receiving: " + e.getMessage()); + LOGGER.info("Make sure crowd detection is publishing, receiving: " + e.getMessage()); return false; } } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java index 51443b7e..25bb1e76 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java @@ -60,13 +60,13 @@ public State.Output performSpecialAction(RosMainNode rosNode){ String randomPartLiteral = parts.get(randomPart); try { - //TODO: what is 2nd parameter? rosNode.PerformMovement(randomPart, "random1"); - }catch (InterruptedException e) { + } catch (InterruptedException e) { + logger.error(e.getMessage()); } - logger.info("synthesising: " + String.format(phrases.getRandomElement(), randomPartLiteral)); + return State.Output.say(String.format(phrases.getRandomElement(), randomPartLiteral)); } }, diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java index 48acb9a2..69dd6816 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java @@ -173,12 +173,16 @@ public State getNextState() { /** * fetches detected objects from vision and writes into a list */ - private void checkObjects(){ - List detectedThings = getContext().OBJECT_DETECTION.getLastValue().getNames(); - for(String obj : detectedThings){ - detectedObjects.add(Objects.valueOf(obj.toUpperCase())); + try { + List detectedThings = getContext().OBJECT_DETECTION.getLastValue().getNames(); + for (String obj : detectedThings) { + detectedObjects.add(Objects.valueOf(obj.toUpperCase())); + } + }catch (NullPointerException e){ + nextState = getTransition(TRANSITION_FINISHED); + logger.error("Make sure object detection publisher is running, receiving: " + e.getMessage()); } } diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java index e2c56617..d1afdcc2 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java @@ -72,7 +72,13 @@ public Interpretation analyze(Interpretation interpretation) } Word2Vec vec = Word2vec.getInstance().getModel(); - INDArray mean = vec.getWordVectorsMean(labels); + INDArray mean; + try{ + mean = vec.getWordVectorsMean(labels); + }catch (Exception e){ + interpretation.setEmotion(RoboyEmotion.NEUTRAL); + return interpretation; + } if(!mean.isVector()){ //if mean is not a vector just return without emotion LOGGER.error("MEAN IS NOT A VECTOR"); diff --git a/resources/personalityFiles/FairShowPersonality.json b/resources/personalityFiles/FairShowPersonality.json index 39adc55c..a0608e20 100644 --- a/resources/personalityFiles/FairShowPersonality.json +++ b/resources/personalityFiles/FairShowPersonality.json @@ -32,11 +32,10 @@ "implementation": "roboy.dialog.states.fairShowStates.ChooseInteractiveTalkState", "transitions": { "newPerson": "InterlocutorIntro", - "personalQA": "PersonalQA", "math": "Math", "game": "ChooseGameState", "objectDetected": "ObjectDetection", - "generalQA": "GeneralQA" + "personalQA": "PersonalQA" } }, { diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 28fdba85..44181f62 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -5887,3 +5887,39 @@ {"features":" {score:0.15152674515697737} ","formula":"(rdf:type dbpedia:City)","lexeme":"city","type":"ClassNoun"} {"features":" {score:0.07924929805861808} ","formula":"property:municipality","lexeme":"municipality","type":"DataProp"} {"features":" {score:0.6171889755251683} ","formula":"resource:Ludwig_Maximilian_University_of_Munich","lexeme":"ludwig maximilian university of munich","type":"NamedEntity"} +{"features":" {score:0.055132212042808534} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.03828920185565949} ","formula":"property:woman","lexeme":"woman","type":"ObjProp"} +{"features":" {score:0.07457736134529114} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.055132212042808534} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.683304347826087} ","formula":"resource:Angela_Merkel","lexeme":"angela merkel","type":"NamedEntity"} +{"features":" {score:0.022632212042808533} ","formula":"property:politicalLeader","lexeme":"political leader","type":"ObjProp"} +{"features":" {score:0.03828920185565949} ","formula":"property:woman","lexeme":"woman","type":"DataProp"} +{"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"ObjProp"} +{"features":" {score:0.022632212042808533} ","formula":"!dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} +{"features":" {score:0.022632212042808533} ","formula":"property:politicalLeader","lexeme":"political leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.022632212042808533} ","formula":"dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} +{"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"ObjProp"} +{"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.03828920185565949} ","formula":"property:woman","lexeme":"woman","type":"ObjProp"} +{"features":" {score:0.07457736134529114} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.055132212042808534} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.683304347826087} ","formula":"resource:Angela_Merkel","lexeme":"angela merkel","type":"NamedEntity"} +{"features":" {score:0.022632212042808533} ","formula":"property:politicalLeader","lexeme":"political leader","type":"ObjProp"} +{"features":" {score:0.03828920185565949} ","formula":"property:woman","lexeme":"woman","type":"DataProp"} +{"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"ObjProp"} +{"features":" {score:0.022632212042808533} ","formula":"!dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} +{"features":" {score:0.022632212042808533} ","formula":"property:politicalLeader","lexeme":"political leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.022632212042808533} ","formula":"dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} +{"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"ObjProp"} +{"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"DataProp"} From 000d95c46e0005cf0111b7e8f261ac9ae976ec0a Mon Sep 17 00:00:00 2001 From: Joseph Birkner Date: Wed, 15 Aug 2018 17:09:46 +0200 Subject: [PATCH 033/147] Fixed API invocations in new QA state. --- .../devoStates/QuestionRoboyQAState.java | 47 ++++++++++++++++--- .../knowledgebase}/apiKeys.yml | 0 2 files changed, 40 insertions(+), 7 deletions(-) rename {dialog/src/main/java/roboy/util/api => resources/knowledgebase}/apiKeys.yml (100%) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 745995eb..96fd3cb4 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -21,6 +21,7 @@ import roboy.util.Pair; import roboy.util.QAJsonParser; import roboy.util.RandomList; +import roboy.util.api.*; import java.util.*; @@ -99,6 +100,11 @@ private Output reactToQuestion(Interpretation input) { askingSpecifyingQuestion = false; questionsAnswered++; + String answer = inferApiAnswer(input); + if (!answer.isEmpty()) { + return Output.say(answer); + } + if (input.getTokens() != null && !(input.getTokens().contains("you") || input.getTokens().contains("your"))) { Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); if (parseOutcome == null) { @@ -176,6 +182,40 @@ private Output answerFromMemory(Interpretation input) { return Output.say(answer); } + private String inferApiAnswer(Interpretation input) { + Map pas = input.getPas(); + String answer = ""; + if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bweather\\b.*"))) { + try { + answer = String.format("It seems like it is %s out there!", Weather.getData("munich")); + } + catch (Exception e) { + answer = "It seems a bit moody..."; + LOGGER.error(e.getMessage()); + } + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, ".*\\bmovie.*"))) { + try { + answer = String.format("I have heard that %s is playing!", Movie.getData("title")); + } + catch (Exception e) { + answer = "Wall e is a great movie!"; + LOGGER.error(e.getMessage()); + } + } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.MANNER, "how"), new Pair(SemanticRole.PREDICATE, "say"), new Pair(SemanticRole.AGENT, "you")) || + matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.PREDICATE, "is"), new Pair(SemanticRole.AGENT, "what"))) { + String[] parts = pas.get(SemanticRole.PATIENT).split(" in "); + assert(parts.length == 2); + try { + answer = answerStartingPhrases.getRandomElement() + " " + Translate.getData(parts[0], parts[1]); + } + catch (Exception e) { + answer = String.format("I am not sure whether I know %s", parts[1]); + LOGGER.error(e.getMessage()); + } + } + return answer; + } + private String inferMemoryAnswer(Interpretation input, Roboy roboy) { String answer = ""; @@ -210,13 +250,6 @@ private String inferPasAnswer(Map pas, Roboy roboy) { String answer = ""; if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); - // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bweather\\b.*"))) { - // // -> Weather API - // } else if (matchPas(pas, new Pair(SemanticRole.AGENT, ".*\\bmovie.*"))) { - // // -> Movie API - // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.MANNER, "how"), new Pair(SemanticRole.PREDICATE, "say"), new Pair(SemanticRole.AGENT, "you")) || - // matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.PREDICATE, "is"), new Pair(SemanticRole.AGENT, "what"))) { - // // translate(*,**) } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { answer = Math.random() > .5 ? extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/resources/knowledgebase/apiKeys.yml similarity index 100% rename from dialog/src/main/java/roboy/util/api/apiKeys.yml rename to resources/knowledgebase/apiKeys.yml From 0d1671ef95a966c5de778f517000c0b19549305e Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Wed, 15 Aug 2018 17:23:53 +0200 Subject: [PATCH 034/147] autonomous interaction ready for testing --- config.properties | 4 +- .../src/main/java/roboy/context/Context.java | 8 + .../context/contextObjects/BoothSentence.java | 9 ++ .../contextObjects/BoothSentenceUpdater.java | 26 ++++ .../ChooseInteractiveTalkState.java | 16 +- .../states/fairShowStates/InfoTalkState.java | 140 ++++++++--------- .../fairShowStates/ObjectDetectionState.java | 49 ++++-- .../PersonalInformationAskingState.java | 58 ++++--- .../main/java/roboy/ros/RosSubscribers.java | 3 +- .../personalityFiles/FairShowPersonality.json | 3 +- resources_nlu/error_test/newLexicon.txt | 146 ++++++++++++++++++ 11 files changed, 340 insertions(+), 122 deletions(-) create mode 100644 dialog/src/main/java/roboy/context/contextObjects/BoothSentence.java create mode 100644 dialog/src/main/java/roboy/context/contextObjects/BoothSentenceUpdater.java diff --git a/config.properties b/config.properties index a197d190..ff4549db 100755 --- a/config.properties +++ b/config.properties @@ -10,6 +10,7 @@ ROS_MASTER_IP: 127.0.0.1 # roboy_vision # roboy_test # roboy_filters +# roboy_nodered ROS_ACTIVE_PKGS: # - roboy_gnlp @@ -17,8 +18,9 @@ ROS_ACTIVE_PKGS: # - roboy_speech_synthesis # - roboy_speech_recognition # - roboy_face -# - roboy_filters +- roboy_filters - roboy_vision +- roboy_nodered # - roboy_test DEBUG: true diff --git a/dialog/src/main/java/roboy/context/Context.java b/dialog/src/main/java/roboy/context/Context.java index 6aeb8c0f..37c53baa 100644 --- a/dialog/src/main/java/roboy/context/Context.java +++ b/dialog/src/main/java/roboy/context/Context.java @@ -55,6 +55,9 @@ public class Context { public final HistoryInterface OBJECT_DETECTION = new HistoryInterface<>(new DetectedObjects()); + public final HistoryInterface BOOTH_SENTENCE = + new HistoryInterface<>(new BoothSentence()); + /* GUI */ private final ArrayList guiValues = new ArrayList(); private final ArrayList guiHistories = new ArrayList(); @@ -72,6 +75,7 @@ public class Context { private DetectedPersonUpdater DETECTED_PERSON_UPDATER; private PeopleAroundUpdater CROWD_UPDATER; private DetectedObjectsUpdater DETECTED_OBJ_UPDATER; + private BoothSentenceUpdater BOOTH_SENTENCE_UPDATER; /* OBSERVERS */ private final FaceCoordinatesObserver FACE_COORDINATES_OBSERVER; @@ -127,6 +131,10 @@ public void initializeROS(RosMainNode ros) { CROWD_UPDATER = new PeopleAroundUpdater(CROWD_DETECTION.valueHistory, ros); } + if(ConfigManager.ROS_ACTIVE_PKGS.contains("roboy_nodered")){ + BOOTH_SENTENCE_UPDATER = new BoothSentenceUpdater(BOOTH_SENTENCE.valueHistory, ros); + } + rosInitialized = true; } } diff --git a/dialog/src/main/java/roboy/context/contextObjects/BoothSentence.java b/dialog/src/main/java/roboy/context/contextObjects/BoothSentence.java new file mode 100644 index 00000000..ad99ac3d --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/BoothSentence.java @@ -0,0 +1,9 @@ +package roboy.context.contextObjects; + +import roboy.context.ValueHistory; + +/** + * Holds Strings with information about the booth at a fair, sent by the node-red GUI + * */ +public class BoothSentence extends ValueHistory { +} diff --git a/dialog/src/main/java/roboy/context/contextObjects/BoothSentenceUpdater.java b/dialog/src/main/java/roboy/context/contextObjects/BoothSentenceUpdater.java new file mode 100644 index 00000000..6d78f50e --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/BoothSentenceUpdater.java @@ -0,0 +1,26 @@ +package roboy.context.contextObjects; + +import roboy.context.ROSTopicUpdater; +import roboy.ros.RosMainNode; +import roboy.ros.RosSubscribers; + +/** + * Pushes new values sent by the Booth Sentence ROS topic into the Booth Sentence value history. + */ +public class BoothSentenceUpdater extends ROSTopicUpdater { + + public BoothSentenceUpdater(BoothSentence target, RosMainNode node) { + super(target, node); + } + + @Override + protected synchronized void update() { + target.updateValue(message); + } + + @Override + protected RosSubscribers getTargetSubscriber() { + return RosSubscribers.BOOTH_SENTENCE; + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java index c38bb35a..54b00103 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ChooseInteractiveTalkState.java @@ -22,7 +22,7 @@ public class ChooseInteractiveTalkState extends MonologState { private final static String TRANSITION_MATH = "math"; private final static String TRANSITION_GAME = "game"; private final static String TRANSITION_PERSONAL_QA = "personalQA"; - private final static String TRANSITION_OBJECT_DETECTED = "objectDetected"; + private final static String TRANSITION_OBJECT_DETECTION = "objectDetected"; private final static String TRANSITION_GENERAL_QA = "generalQA"; private final Logger logger = LogManager.getLogger(); @@ -45,10 +45,6 @@ public Output act() { nextInteraction = TRANSITION_NEW_PERSON; - } else if(checkObjectsDetected()){ - - nextInteraction = TRANSITION_OBJECT_DETECTED; - } else { nextInteraction = selectRandomInteraction(); @@ -70,7 +66,7 @@ public State getNextState() { */ private void resetAvailableInteractions() { availableInteractions.clear(); - availableInteractions.addAll(Arrays.asList(TRANSITION_PERSONAL_QA, TRANSITION_MATH, TRANSITION_GAME)); + availableInteractions.addAll(Arrays.asList(TRANSITION_PERSONAL_QA, TRANSITION_MATH, TRANSITION_GAME, TRANSITION_OBJECT_DETECTION, TRANSITION_GENERAL_QA)); } /** @@ -88,13 +84,5 @@ private String selectRandomInteraction() { return interaction; } - private boolean checkObjectsDetected(){ - try { - return !getContext().OBJECT_DETECTION.getLastValue().getNames().isEmpty(); - }catch(NullPointerException e){ - logger.info("Make sure object detection is publishing, receiving: " + e.getMessage()); - return false; - } - } } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java index 25bb1e76..8fc0fb96 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java @@ -19,108 +19,110 @@ enum InfoAbout { - ABOUT_TEAM { + ABOUT_TEAM, + ABOUT_BOOTH, + ABOUT_ROBOY, + ABOUT_MOVEMENT, + ABOUT_EMOTIONS +} - private RandomList phrases = PhraseCollection.ROBOY_TEAM_PHRASES; +/** + * Roboy is talking about several topics autonomously + * - team + * - mission + * - movement + * - emotions + */ +public class InfoTalkState extends MonologState { - @Override - public State.Output performSpecialAction(RosMainNode rosNode){ + private final static String TRANSITION_PERSON_DETECTED = "personDetected"; + private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; - return State.Output.say(phrases.getRandomElement()); - } + private final RandomList availableInformation = new RandomList<>(); + private InfoAbout activeInfo; - }, - ABOUT_ROBOY { + private RandomList phrases = new RandomList<>(); - private RandomList phrases = PhraseCollection.MISSION_PHRASES; - @Override - public State.Output performSpecialAction(RosMainNode rosNode){ + private final Logger logger = LogManager.getLogger(); - return State.Output.say(phrases.getRandomElement()); - } - }, - ABOUT_MOVEMENT { + private State nextState = this; + private Random random = new Random(); + private RandomList emotions = new RandomList<>(); - Random random = new Random(); - RandomList phrases = PhraseCollection.MOVEMENT_PHRASES; + public InfoTalkState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + resetAvailableInformation(); + } - @Override - public State.Output performSpecialAction(RosMainNode rosNode){ + @Override + public Output act() { - HashMap parts = new HashMap<>(); - parts.put("shoulder_left", "left shoulder"); - parts.put("shoulder_right", "right shoulder"); - parts.put("spine_right", "right leg"); - parts.put("spine_left", "left leg"); + activeInfo = selectRandomInfo(); - List bodyParts = new ArrayList<>(parts.keySet()); + switch(activeInfo){ + case ABOUT_TEAM: - String randomPart = bodyParts.get(random.nextInt(bodyParts.size())); - String randomPartLiteral = parts.get(randomPart); + phrases = PhraseCollection.ROBOY_TEAM_PHRASES; + return Output.say(phrases.getRandomElement()); - try { - rosNode.PerformMovement(randomPart, "random1"); + case ABOUT_BOOTH: - } catch (InterruptedException e) { + String boothSentence = "Look at this awesome booth here! Isn't it amazing what is already possible in technology? Come an talk to one of the guy and get more into the topic!"; - logger.error(e.getMessage()); - } + try{ - return State.Output.say(String.format(phrases.getRandomElement(), randomPartLiteral)); - } - }, - ABOUT_EMOTIONS { + boothSentence = getContext().BOOTH_SENTENCE.getLastValue().toString(); - private RandomList phrases = PhraseCollection.EMOTION_PHRASES; - private RandomList emotions = new RandomList<>(); + } catch (NullPointerException e){ + logger.info("No individual Booth Sentence received, make sure it is published " + e.getMessage()); - @Override - public State.Output performSpecialAction(RosMainNode rosNode){ + } - emotions.addAll(Arrays.asList(RoboyEmotion.values())); + return Output.say(boothSentence); - return State.Output.say(phrases.getRandomElement()).setEmotion(emotions.getRandomElement()); - } - }; + case ABOUT_ROBOY: - private final static Logger logger = LogManager.getLogger(); + phrases = PhraseCollection.MISSION_PHRASES; + return Output.say(phrases.getRandomElement()); - public abstract State.Output performSpecialAction(RosMainNode rosNode); + case ABOUT_MOVEMENT: -} -/** - * Roboy is talking about several topics autonomously - * - team - * - mission - * - movement - * - emotions - */ -public class InfoTalkState extends MonologState { + phrases = PhraseCollection.MOVEMENT_PHRASES; - private final static String TRANSITION_PERSON_DETECTED = "personDetected"; - private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; + HashMap parts = new HashMap<>(); + parts.put("shoulder_left", "left shoulder"); + parts.put("shoulder_right", "right shoulder"); + parts.put("spine_right", "right leg"); + parts.put("spine_left", "left leg"); - private final RandomList availableInformation = new RandomList<>(); - private InfoAbout activeInfo; + List bodyParts = new ArrayList<>(parts.keySet()); - private final Logger logger = LogManager.getLogger(); + String randomPart = bodyParts.get(random.nextInt(bodyParts.size())); + String randomPartLiteral = parts.get(randomPart); - private State nextState = this; +// try { + // rosNode.PerformMovement(randomPart, "random1"); +//// } catch (InterruptedException e) { - public InfoTalkState(String stateIdentifier, StateParameters params) { - super(stateIdentifier, params); - resetAvailableInformation(); - } + // logger.error(e.getMessage()); + // } - @Override - public Output act() { + return State.Output.say(String.format(phrases.getRandomElement(), randomPartLiteral)); - activeInfo = selectRandomInfo(); + case ABOUT_EMOTIONS: + + phrases = PhraseCollection.EMOTION_PHRASES; + emotions.addAll(Arrays.asList(RoboyEmotion.values())); + + return State.Output.say(phrases.getRandomElement()).setEmotion(emotions.getRandomElement()); + + + } - return activeInfo.performSpecialAction(getRosMainNode()); + return Output.sayNothing(); } @Override diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java index 69dd6816..6cb6a901 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ObjectDetectionState.java @@ -26,7 +26,7 @@ public State.Output performSpecialAction(RosMainNode rmn){ } }, - BYCICLE { + BICYCLE { private RandomList phrases = new RandomList<>("a bycicle, I bet I can ride faster than you", "a bike, I could easily win the tour de France", "a bycicle, I learnt riding the bycicle when I was just three years old. And you?", "bike. I love bycicles. I only fell off my bike once."); @@ -135,6 +135,7 @@ public class ObjectDetectionState extends MonologState { private final Set detectedObjects = new HashSet<>(); private Vector outputs = new Vector<>(); + private Output currentOutput; private final Logger logger = LogManager.getLogger(); @@ -149,7 +150,7 @@ public Output act() { if(outputs.isEmpty()){ - checkObjects(); + getObjects(); for(Objects obj : detectedObjects) { @@ -158,10 +159,23 @@ public Output act() { } } - Output current = outputs.remove(0); - if(outputs.isEmpty()) nextState = getTransition(TRANSITION_FINISHED); + try { + + currentOutput = outputs.remove(0); + + } catch (ArrayIndexOutOfBoundsException e){ + + logger.info("No objects detected from Vision"); + nextState = getTransition(TRANSITION_FINISHED); + return Output.sayNothing(); + } + + if(outputs.isEmpty()){ + + nextState = getTransition(TRANSITION_FINISHED); + } - return current; + return currentOutput; } @Override @@ -173,18 +187,31 @@ public State getNextState() { /** * fetches detected objects from vision and writes into a list */ - private void checkObjects(){ + private void getObjects(){ + + + List detectedThings = new ArrayList<>(); try { - List detectedThings = getContext().OBJECT_DETECTION.getLastValue().getNames(); - for (String obj : detectedThings) { - detectedObjects.add(Objects.valueOf(obj.toUpperCase())); - } - }catch (NullPointerException e){ + + detectedThings = getContext().OBJECT_DETECTION.getLastValue().getNames(); + + } catch (NullPointerException e){ nextState = getTransition(TRANSITION_FINISHED); logger.error("Make sure object detection publisher is running, receiving: " + e.getMessage()); } + if(!detectedThings.isEmpty()) { + for (String obj : detectedThings) { + try{ + detectedObjects.add(Objects.valueOf(obj.toUpperCase())); + } catch (IllegalArgumentException e){ + logger.info(obj + " is not an object implemented in Dialog " + e.getMessage()); + } + + } + } + } } \ No newline at end of file diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java index 6e40dbb9..94188d16 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java @@ -72,42 +72,50 @@ public Output act() { break; } } - RandomList questions = qaValues.getQuestions(selectedPredicate); - String question = ""; - if (questions != null && !questions.isEmpty()) { - question = questions.getRandomElement(); - LOGGER.info(" -> Selected question: " + question); - } else { - LOGGER.error(" -> The list of " + selectedPredicate.type + " questions is empty or null"); + if (selectedPredicate != null) { + RandomList questions = qaValues.getQuestions(selectedPredicate); + String question = ""; + if (questions != null && !questions.isEmpty()) { + question = questions.getRandomElement(); + LOGGER.info(" -> Selected question: " + question); + } else { + LOGGER.error(" -> The list of " + selectedPredicate.type + " questions is empty or null"); + } + try { + getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, selectedPredicate)); + LOGGER.info(" -> Dialog IntentsHistory updated"); + } catch (Exception e) { + LOGGER.error(" -> Error on updating the IntentHistory: " + e.getMessage()); + } + return State.Output.say(question); } - try { - getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, selectedPredicate)); - LOGGER.info(" -> Dialog IntentsHistory updated"); - } catch (Exception e) { - LOGGER.error(" -> Error on updating the IntentHistory: " + e.getMessage()); + else { + return State.Output.say("I think I know everything about you already. Do you have anything else to share?"); } - return State.Output.say(question); } @Override public Output react(Interpretation input) { Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); - RandomList answers; + RandomList answers = new RandomList<>(); String answer = "I have no words"; String result = InferResult(input); - if (result != null && !result.equals("")) { - LOGGER.info(" -> Inference was successful"); - answers = qaValues.getSuccessAnswers(selectedPredicate); - person.addInformation(selectedPredicate, result); - getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(person); - LOGGER.info(" -> Updated Interlocutor: " + person.getName()); - } else { - LOGGER.warn(" -> Inference failed"); - answers = qaValues.getFailureAnswers(selectedPredicate); - result = ""; - LOGGER.warn(" -> The result is empty. Nothing to store"); + if(selectedPredicate != null) { + + if (result != null && !result.equals("")) { + LOGGER.info(" -> Inference was successful"); + answers = qaValues.getSuccessAnswers(selectedPredicate); + person.addInformation(selectedPredicate, result); + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(person); + LOGGER.info(" -> Updated Interlocutor: " + person.getName()); + } else { + LOGGER.warn(" -> Inference failed"); + answers = qaValues.getFailureAnswers(selectedPredicate); + result = ""; + LOGGER.warn(" -> The result is empty. Nothing to store"); + } } if (answers != null && !answers.isEmpty()) { answer = String.format(answers.getRandomElement(), result); diff --git a/dialog/src/main/java/roboy/ros/RosSubscribers.java b/dialog/src/main/java/roboy/ros/RosSubscribers.java index 5320fe60..53fc585e 100644 --- a/dialog/src/main/java/roboy/ros/RosSubscribers.java +++ b/dialog/src/main/java/roboy/ros/RosSubscribers.java @@ -10,7 +10,8 @@ public enum RosSubscribers { TEST_TOPIC("roboy_test", "/roboy", std_msgs.String._TYPE), DETECTED_OBJECTS("roboy_vision", "/roboy/cognition/vision/detected_objects", Strings._TYPE), NUMBER_PEOPLE_AROUND("roboy_vision", "/roboy/cognition/vision/people_around", std_msgs.Int8._TYPE), - PERSON_LISTENING("roboy_vision", "/roboy/cognition/vision/person_listening", std_msgs.Bool._TYPE) + PERSON_LISTENING("roboy_vision", "/roboy/cognition/vision/person_listening", std_msgs.Bool._TYPE), + BOOTH_SENTENCE("roboy_nodered", "/roboy/cognition/nodered/boothsentence", std_msgs.String._TYPE), ; String rosPackage; diff --git a/resources/personalityFiles/FairShowPersonality.json b/resources/personalityFiles/FairShowPersonality.json index a0608e20..7fd64cc8 100644 --- a/resources/personalityFiles/FairShowPersonality.json +++ b/resources/personalityFiles/FairShowPersonality.json @@ -35,7 +35,8 @@ "math": "Math", "game": "ChooseGameState", "objectDetected": "ObjectDetection", - "personalQA": "PersonalQA" + "personalQA": "PersonalQA", + "generalQA": "GeneralQA" } }, { diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 44181f62..911425ca 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -5923,3 +5923,149 @@ {"features":" {score:0.022632212042808533} ","formula":"dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} {"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"ObjProp"} {"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.03828920185565949} ","formula":"property:woman","lexeme":"woman","type":"ObjProp"} +{"features":" {score:0.07457736134529114} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.055132212042808534} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.683304347826087} ","formula":"resource:Angela_Merkel","lexeme":"angela merkel","type":"NamedEntity"} +{"features":" {score:0.022632212042808533} ","formula":"property:politicalLeader","lexeme":"political leader","type":"ObjProp"} +{"features":" {score:0.03828920185565949} ","formula":"property:woman","lexeme":"woman","type":"DataProp"} +{"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"ObjProp"} +{"features":" {score:0.022632212042808533} ","formula":"!dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} +{"features":" {score:0.022632212042808533} ","formula":"property:politicalLeader","lexeme":"political leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.022632212042808533} ","formula":"dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} +{"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"ObjProp"} +{"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.315447027617413} ","formula":"resource:American_Recovery_and_Reinvestment_Act_of_2009","lexeme":"american recovery and reinvestment act of 2009","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.31076611015759087} ","formula":"resource:Presidency_of_Barack_Obama","lexeme":"presidency of barack obama","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.021463414634146343} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.015609756097560976} ","formula":"(rdf:type dbpedia:President)","lexeme":"president","type":"ClassNoun"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.015609756097560976} ","formula":"dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.45063192385707596} ","formula":"resource:Barack_Obama","lexeme":"barack obama","type":"NamedEntity"} +{"features":" {score:0.3089717584646591} ","formula":"resource:Patient_Protection_and_Affordable_Care_Act","lexeme":"patient protection and affordable care act","type":"NamedEntity"} +{"features":" {score:0.31418317990326106} ","formula":"resource:Sean_Combs","lexeme":"sean combs","type":"NamedEntity"} +{"features":" {score:0.010731707317073172} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.015609756097560976} ","formula":"!dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.315447027617413} ","formula":"resource:American_Recovery_and_Reinvestment_Act_of_2009","lexeme":"american recovery and reinvestment act of 2009","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.31076611015759087} ","formula":"resource:Presidency_of_Barack_Obama","lexeme":"presidency of barack obama","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.021463414634146343} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.015609756097560976} ","formula":"(rdf:type dbpedia:President)","lexeme":"president","type":"ClassNoun"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.015609756097560976} ","formula":"dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.45063192385707596} ","formula":"resource:Barack_Obama","lexeme":"barack obama","type":"NamedEntity"} +{"features":" {score:0.3089717584646591} ","formula":"resource:Patient_Protection_and_Affordable_Care_Act","lexeme":"patient protection and affordable care act","type":"NamedEntity"} +{"features":" {score:0.31418317990326106} ","formula":"resource:Sean_Combs","lexeme":"sean combs","type":"NamedEntity"} +{"features":" {score:0.010731707317073172} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.015609756097560976} ","formula":"!dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.315447027617413} ","formula":"resource:American_Recovery_and_Reinvestment_Act_of_2009","lexeme":"american recovery and reinvestment act of 2009","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.31076611015759087} ","formula":"resource:Presidency_of_Barack_Obama","lexeme":"presidency of barack obama","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.021463414634146343} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.015609756097560976} ","formula":"(rdf:type dbpedia:President)","lexeme":"president","type":"ClassNoun"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.015609756097560976} ","formula":"dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.45063192385707596} ","formula":"resource:Barack_Obama","lexeme":"barack obama","type":"NamedEntity"} +{"features":" {score:0.3089717584646591} ","formula":"resource:Patient_Protection_and_Affordable_Care_Act","lexeme":"patient protection and affordable care act","type":"NamedEntity"} +{"features":" {score:0.31418317990326106} ","formula":"resource:Sean_Combs","lexeme":"sean combs","type":"NamedEntity"} +{"features":" {score:0.010731707317073172} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.015609756097560976} ","formula":"!dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.315447027617413} ","formula":"resource:American_Recovery_and_Reinvestment_Act_of_2009","lexeme":"american recovery and reinvestment act of 2009","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.31076611015759087} ","formula":"resource:Presidency_of_Barack_Obama","lexeme":"presidency of barack obama","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.021463414634146343} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.015609756097560976} ","formula":"(rdf:type dbpedia:President)","lexeme":"president","type":"ClassNoun"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.015609756097560976} ","formula":"dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.45063192385707596} ","formula":"resource:Barack_Obama","lexeme":"barack obama","type":"NamedEntity"} +{"features":" {score:0.3089717584646591} ","formula":"resource:Patient_Protection_and_Affordable_Care_Act","lexeme":"patient protection and affordable care act","type":"NamedEntity"} +{"features":" {score:0.31418317990326106} ","formula":"resource:Sean_Combs","lexeme":"sean combs","type":"NamedEntity"} +{"features":" {score:0.010731707317073172} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.015609756097560976} ","formula":"!dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} From 7720bf86012417822901f2e2310eb3b60d24e6b0 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 20:12:31 +0200 Subject: [PATCH 035/147] Enabled support for special persons from memory in dialog_system --- .../roboy/dialog/ConversationManager.java | 65 ++++++++++++++----- .../src/main/java/roboy/io/TelegramInput.java | 4 +- .../main/java/roboy/memory/Neo4jLabel.java | 6 +- .../java/roboy/memory/nodes/Interlocutor.java | 9 +-- .../util/TelegramCommunicationHandler.java | 30 ++++++--- dialog/src/main/java/roboy/util/Uuid.java | 8 +++ 6 files changed, 88 insertions(+), 34 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index 89d8ba9c..fcc4d4e7 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -138,8 +138,17 @@ public static void main(String[] args) throws IOException { * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" * @throws IOException If conversation could not created. */ - public static void spawnConversation(String uuid) throws IOException{ - Conversation conversation = createConversation(rosMainNode, analyzers, new Inference(), memory, uuid); + public static void spawnConversation(String uuid) throws IOException { + spawnConversation(uuid, null); + } + /** + * Creates and spawns a conversation for a chatuser. + * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" + * @param name the name of the Interlocutor. Necessary for unique adressing by name (local nodes) + * @throws IOException If conversation could not created. + */ + public static void spawnConversation(String uuid, String name) throws IOException{ + Conversation conversation = createConversation(rosMainNode, analyzers, new Inference(), memory, uuid, name); conversations.put(uuid, conversation); conversation.start(); } @@ -176,18 +185,40 @@ public static Long getConversationThreadID(String uuid){ return (conv == null) ? null : (Long)conv.getId(); } - /** - * Creates and initializes a new conversation thread. Does not start the thread. + * Creates and initializes a new conversation thread. Only use for local threads that don't have uuids (uuid=local). Does not start the thread. * @param rosMainNode ROS node. Set null if ROS_ENABLED=false * @param analyzers All analyzers necessary for analyzing the inputs from multiIn. Please provide these in correct order. * @param inference Inference engine. The better, the smarter roboy gets. * @param memory Roboy memory access. Without, we cannot remember anything and conversations stay shallow. - * @return roboy.dialog.Conversation object. Fully intialized, ready to launch. + * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" + * @return null if uuroboy.dialog.Conversation object. Fully intialized, ready to launch. * @throws IOException In case the IOdevices could not be correctly initialized. */ private static Conversation createConversation(RosMainNode rosMainNode, List analyzers, InferenceEngine inference, Neo4jMemoryInterface memory, String uuid) throws IOException{ + if(!uuid.equals("local")){ + logger.error("Cannot create a Conversation for uuid " + uuid + " without a name!"); + return null; + } + return createConversation(rosMainNode,analyzers,inference,memory,uuid,null); + } + + + + /** + * Creates and initializes a new conversation thread. Does not start the thread. + * @param rosMainNode ROS node. Set null if ROS_ENABLED=false + * @param analyzers All analyzers necessary for analyzing the inputs from multiIn. Please provide these in correct order. + * @param inference Inference engine. The better, the smarter roboy gets. + * @param memory Roboy memory access. Without, we cannot remember anything and conversations stay shallow. + * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local"; + * @param name the name of the Interlocutor. Necessary for unique adressing by name (local nodes) + * @return roboy.dialog.Conversation object. Fully intialized, ready to launch. + * @throws IOException In case the IOdevices could not be correctly initialized. + */ + + private static Conversation createConversation(RosMainNode rosMainNode, List analyzers, InferenceEngine inference, Neo4jMemoryInterface memory, String uuid, String name) throws IOException{ logger.info("Creating new conversation..."); //Create IODevices. @@ -214,17 +245,19 @@ private static Conversation createConversation(RosMainNode rosMainNode, List update) { + public static void onUpdate(Pair update, String name) { String chatId = update.getKey(); String uuid = "telegram-" + chatId; @@ -49,7 +49,7 @@ public static void onUpdate(Pair update) { if (input == null){//if Thread does not exist yet, create it and place the new message as it's input try { - ConversationManager.spawnConversation(uuid); + ConversationManager.spawnConversation(uuid, name); } catch (IOException e) { logger.error("Could not create conversation for telegram uuid '" + chatId + "'!"); return; diff --git a/dialog/src/main/java/roboy/memory/Neo4jLabel.java b/dialog/src/main/java/roboy/memory/Neo4jLabel.java index 72a32496..93d6ffc6 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jLabel.java +++ b/dialog/src/main/java/roboy/memory/Neo4jLabel.java @@ -12,9 +12,9 @@ */ public enum Neo4jLabel { Person("Person"), - TelegramPerson("TelegramPerson"), - FacebookPerson("FacebookPerson"), - SlackPerson("SlackPerson"), + TelegramPerson("Telegramperson"), + FacebookPerson("Facebookperson"), + SlackPerson("Slackperson"), Robot("Robot"), Company("Company"), University("University"), diff --git a/dialog/src/main/java/roboy/memory/nodes/Interlocutor.java b/dialog/src/main/java/roboy/memory/nodes/Interlocutor.java index 57e855df..b0495b70 100755 --- a/dialog/src/main/java/roboy/memory/nodes/Interlocutor.java +++ b/dialog/src/main/java/roboy/memory/nodes/Interlocutor.java @@ -31,9 +31,9 @@ public Interlocutor(Neo4jMemoryInterface memory, String name) { this.addName(name); } - public Interlocutor(Neo4jMemoryInterface memory, Uuid uuid) { + public Interlocutor(Neo4jMemoryInterface memory, Uuid uuid, String name) { super(memory); - this.addUuid(uuid); + this.addUuid(uuid, name); } /** @@ -49,8 +49,9 @@ public void addName(String name) { FAMILIAR = this.init(this); } - public void addUuid(Uuid uuid) { - setProperty(uuid.getType().toNeo4jProperty(), uuid); + public void addUuid(Uuid uuid, String name) { + setProperty(Neo4jProperty.name, name); + setProperty(uuid.getType().toNeo4jProperty(), uuid.getUuid()); setLabel(uuid.getType().toNeo4jLabel()); FAMILIAR = this.init(this); } diff --git a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java index b137fe44..19e7f98b 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java @@ -34,7 +34,7 @@ public class TelegramCommunicationHandler extends TelegramLongPollingBot impleme private static final int INPUT_TIME_LIMIT = 5; //SECONDS // CHAT ID ----- ITS MESSAGE - private volatile List> pairs = new ArrayList<>(); + private volatile List>> pairs = new ArrayList<>(); private List telegramTimeouts; //Timeouts private final static int initTime = (int) (System.currentTimeMillis() / 1000L); //in order to discard messages older than launch @@ -96,6 +96,7 @@ private void handleTimeout(String chatID){ */ @Override public void onUpdateReceived(Update update) { + String name = null; if(!update.hasMessage()){ return; } @@ -110,9 +111,18 @@ public void onUpdateReceived(Update update) { if(text.startsWith("/")){ //inline command }else{ + if(message.getFrom().getUserName() != null){ + name = message.getFrom().getUserName(); + } + else if(message.getFrom().getFirstName() != null) { + name = message.getFrom().getFirstName(); + } + else{ + name = "Telegram user " + message.getFrom().getId().toString(); + } try { //get message, add it to containers - pairs.add(new Pair<>(chatID, text)); + pairs.add(new Pair<>(name, new Pair<>(chatID, text))); //wait for certain seconds, start the timer handleTimeout(chatID); @@ -140,28 +150,30 @@ public void onTimeout(String chatID) { } } - List> removedObjects = new ArrayList<>(); + List>> removedObjects = new ArrayList<>(); // get the all messages - Pair result = null; - for(Pair p : pairs){ + Pair> result = null; + for(Pair> pa : pairs){ + Pair p = pa.getValue(); + String name = pa.getKey(); //Map a = new HashMap(); if(!chatID.equals(p.getKey())){ continue; } - removedObjects.add(p); + removedObjects.add(pa); String message = p.getValue(); // check if the result initialized if(result == null) { - result = new Pair<>(chatID, message); + result = new Pair<>(name,new Pair<>(chatID, message)); } else { // sum all of the messages String newMessage = result.getValue()+ " " + message; //equal chat id - result = new Pair<>(chatID, newMessage); + result = new Pair<>(name,new Pair<>(chatID, newMessage)); } } @@ -169,7 +181,7 @@ public void onTimeout(String chatID) { if(result != null) { // notify the input device pairs.removeAll(removedObjects); - TelegramInput.onUpdate(result); + TelegramInput.onUpdate(result.getValue(), result.getKey()); } } diff --git a/dialog/src/main/java/roboy/util/Uuid.java b/dialog/src/main/java/roboy/util/Uuid.java index 37dd0601..0c3910ec 100644 --- a/dialog/src/main/java/roboy/util/Uuid.java +++ b/dialog/src/main/java/roboy/util/Uuid.java @@ -21,4 +21,12 @@ public String getUuid() { public UuidType getType() { return type; } + + @Override + public String toString() { + return "Uuid{" + + "type=" + type + + ", uuid='" + uuid + '\'' + + '}'; + } } From 7239c83a1b989e570d3164731a928fe28cb139fd Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Wed, 15 Aug 2018 20:37:39 +0200 Subject: [PATCH 036/147] changed min number to 1 --- config.properties | 6 +- .../fairShowStates/ActiveIntroState.java | 2 +- .../personalityFiles/FairShowPersonality.json | 5 +- resources_nlu/error_test/newLexicon.txt | 64 +++++++++++++++++++ 4 files changed, 71 insertions(+), 6 deletions(-) diff --git a/config.properties b/config.properties index ff4549db..04ca8094 100755 --- a/config.properties +++ b/config.properties @@ -72,16 +72,16 @@ ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/sc # Memory: java.util.logging # https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html -MEMORY_LOG_MODE: "FINE" +MEMORY_LOG_MODE: "INFO" # Dialog: LOG4J 2 # https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html # https://logging.apache.org/log4j/2.x/manual/customloglevels.html -DIALOG_LOG_MODE: "DEBUG" +DIALOG_LOG_MODE: "INFO" # Parser/NLU: LogInfo # Supports all Log4J levels. See Documentation for more details -PARSER_LOG_MODE: "DEBUG" +PARSER_LOG_MODE: "INFO" TELEGRAM_API_TOKENS_FILE: "" diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java index 8a987073..75df1e4a 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java @@ -19,7 +19,7 @@ public class ActiveIntroState extends MonologState { private final static String TRANSITION_PEOPLE_AROUND = "peopleAround"; private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; - private final int MIN_NUMBER_PEOPLE = 2; + private final int MIN_NUMBER_PEOPLE = 1; private final Logger logger = LogManager.getLogger(); diff --git a/resources/personalityFiles/FairShowPersonality.json b/resources/personalityFiles/FairShowPersonality.json index 7fd64cc8..75f7a176 100644 --- a/resources/personalityFiles/FairShowPersonality.json +++ b/resources/personalityFiles/FairShowPersonality.json @@ -7,9 +7,10 @@ "transitions": { "timeIsUp": "ActiveIntro" }, - "parameters":{ - "delayInMins" : "1" + "parameters": { + "delayInMins": "1" } + }, { "identifier": "ActiveIntro", diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 911425ca..86431686 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -6069,3 +6069,67 @@ {"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} {"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} {"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.315447027617413} ","formula":"resource:American_Recovery_and_Reinvestment_Act_of_2009","lexeme":"american recovery and reinvestment act of 2009","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.31076611015759087} ","formula":"resource:Presidency_of_Barack_Obama","lexeme":"presidency of barack obama","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.021463414634146343} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.015609756097560976} ","formula":"(rdf:type dbpedia:President)","lexeme":"president","type":"ClassNoun"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.015609756097560976} ","formula":"dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.45063192385707596} ","formula":"resource:Barack_Obama","lexeme":"barack obama","type":"NamedEntity"} +{"features":" {score:0.3089717584646591} ","formula":"resource:Patient_Protection_and_Affordable_Care_Act","lexeme":"patient protection and affordable care act","type":"NamedEntity"} +{"features":" {score:0.31418317990326106} ","formula":"resource:Sean_Combs","lexeme":"sean combs","type":"NamedEntity"} +{"features":" {score:0.010731707317073172} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.015609756097560976} ","formula":"!dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.315447027617413} ","formula":"resource:American_Recovery_and_Reinvestment_Act_of_2009","lexeme":"american recovery and reinvestment act of 2009","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.31076611015759087} ","formula":"resource:Presidency_of_Barack_Obama","lexeme":"presidency of barack obama","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.021463414634146343} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.015609756097560976} ","formula":"(rdf:type dbpedia:President)","lexeme":"president","type":"ClassNoun"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.015609756097560976} ","formula":"dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.45063192385707596} ","formula":"resource:Barack_Obama","lexeme":"barack obama","type":"NamedEntity"} +{"features":" {score:0.3089717584646591} ","formula":"resource:Patient_Protection_and_Affordable_Care_Act","lexeme":"patient protection and affordable care act","type":"NamedEntity"} +{"features":" {score:0.31418317990326106} ","formula":"resource:Sean_Combs","lexeme":"sean combs","type":"NamedEntity"} +{"features":" {score:0.010731707317073172} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.015609756097560976} ","formula":"!dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} From d86dd75e69e946ee4cc137c0c3e92c560fb96549 Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Wed, 15 Aug 2018 20:44:26 +0200 Subject: [PATCH 037/147] fixed state transition (Idle) ROS inactive --- .../main/java/roboy/dialog/states/fairShowStates/IdleState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index ca162032..46e36ae0 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -59,7 +59,7 @@ private boolean notInVision(){ return getContext().CROWD_DETECTION.getLastValue().getData() < MIN_NUMBER_PEOPLE; } catch(NullPointerException e){ LOGGER.info("Make sure crowd detection is publishing, receiving: " + e.getMessage()); - return false; + return true; } } From 8b23be271345f022a40fbe8bf1dff67f74e3fe73 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 21:15:43 +0200 Subject: [PATCH 038/147] Fixed handling unknown individuals where the name could be inferred; changed parser model to webq --- .../ordinaryStates/PassiveGreetingsState.java | 156 ++++++++++++++++-- .../roboy/util/TelegramCommandHandler.java | 2 +- .../util/TelegramCommunicationHandler.java | 6 +- parser.properties | 2 +- .../personalityFiles/OrdinaryPersonality.json | 7 +- 5 files changed, 157 insertions(+), 16 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PassiveGreetingsState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PassiveGreetingsState.java index 2d301764..3c072bd9 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PassiveGreetingsState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PassiveGreetingsState.java @@ -1,14 +1,33 @@ package roboy.dialog.states.ordinaryStates; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.Segue; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.Linguistics; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.logic.StatementInterpreter; +import roboy.memory.Neo4jProperty; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; import roboy.talk.Verbalizer; +import roboy.util.Agedater; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; +import java.util.Arrays; +import java.util.HashMap; import java.util.Set; +import static roboy.memory.Neo4jProperty.*; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.Neo4jRelationship.STUDY_AT; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; + /** * Passive state to start a conversation. * Roboy is waiting until a greeting or his name is detected. @@ -16,6 +35,20 @@ */ public class PassiveGreetingsState extends State { + private final Logger LOGGER = LogManager.getLogger(); + + + private QAJsonParser infoValues; + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + private Neo4jRelationship[] personPredicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); + private final String UPDATE_KNOWN_PERSON = "knownPerson"; + private final String LEARN_ABOUT_PERSON = "newPerson"; + private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!"); + private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!"); + + + private final String TRANSITION_GREETING_DETECTED = "greetingDetected"; private State next; @@ -23,27 +56,130 @@ public class PassiveGreetingsState extends State { public PassiveGreetingsState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); next = this; + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info(" -> The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); } @Override public Output act() { - return Output.sayNothing(); } @Override public Output react(Interpretation input) { - String sentence = input.getSentence(); - boolean inputOK = StatementInterpreter.isFromList(sentence, Verbalizer.greetings) || - StatementInterpreter.isFromList(sentence, Verbalizer.roboyNames) || - StatementInterpreter.isFromList(sentence, Verbalizer.triggers); - - if (inputOK) { - next = getTransition(TRANSITION_GREETING_DETECTED); - return Output.say(Verbalizer.greetings.getRandomElement()); + + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + String name = person.getName(); + if(name == null) { + String sentence = input.getSentence(); + boolean inputOK = StatementInterpreter.isFromList(sentence, Verbalizer.greetings) || + StatementInterpreter.isFromList(sentence, Verbalizer.roboyNames) || + StatementInterpreter.isFromList(sentence, Verbalizer.triggers); + + if (inputOK) { + next = getTransition(TRANSITION_GREETING_DETECTED); + return Output.say(Verbalizer.greetings.getRandomElement()); + } + + return Output.sayNothing(); + } else { + String retrievedPersonalFact = ""; + Double segueProbability = 0.0; + + // 4. check if person is known/familiar + if (person.FAMILIAR) { + // 4a. person known/familiar + // TODO: get some hobbies or occupation of the person to make answer more interesting + RandomList nodes = getMemNodesByIds(person.getRelationships(FRIEND_OF)); + if (!nodes.isEmpty()) { + retrievedPersonalFact = " You are friends with " + + nodes.getRandomElement().getProperties().get(Neo4jProperty.name).toString(); + } + + Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(personPredicates); + if (availability == SOME_AVAILABLE) { + next = (Math.random() < 0.3) ? getTransition(UPDATE_KNOWN_PERSON) : getTransition(LEARN_ABOUT_PERSON); + } else if (availability == NONE_AVAILABLE) { + next = getTransition(LEARN_ABOUT_PERSON); + } else { + next = getTransition(UPDATE_KNOWN_PERSON); + } + } else { + // 4b. person is not known + next = getTransition(LEARN_ABOUT_PERSON); + segueProbability = 0.6; + } + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); } + } - return Output.sayNothing(); + private String getResponsePhrase(String name, boolean familiar) { + if (familiar) { + return String.format(successResponsePhrases.getRandomElement(), name); + } else { + return String.format(failureResponsePhrases.getRandomElement(), name); + } + } + + private String getRoboyFactsPhrase(Roboy roboy) { + String result = ""; + + // Get some random properties facts + if (roboy.getProperties() != null && !roboy.getProperties().isEmpty()) { + HashMap properties = roboy.getProperties(); + if (properties.containsKey(full_name)) { + result += " " + String.format(infoValues.getSuccessAnswers(full_name).getRandomElement(), properties.get(full_name)); + } + if (properties.containsKey(birthdate)) { + HashMap ages = new Agedater().determineAge(properties.get(birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), retrievedAge); + } else if (properties.containsKey(age)) { + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); + } + if (properties.containsKey(skills)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(abilities)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(future)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + } + } + + if (result.equals("")) { + result = "I am Roboy 2.0! "; + } + + // Get a random relationship fact + Neo4jRelationship predicate = roboyRelatioshipPredicates.getRandomElement(); + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName = ""; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + result += " " + String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + + return result; } @Override diff --git a/dialog/src/main/java/roboy/util/TelegramCommandHandler.java b/dialog/src/main/java/roboy/util/TelegramCommandHandler.java index 5c1ee944..c963a34b 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommandHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommandHandler.java @@ -88,7 +88,7 @@ public void execute(){ case PIC: //Just a roboy image, should be changed to desired roboy url int randomNum = ThreadLocalRandom.current().nextInt(0, pictureUrls.length+ 1); - String url = pictureUrls[randomNum]; + String url = pictureUrls[randomNum-1]; tch.sendImageFromUrl(url, telegramChatID); break; case SAY: diff --git a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java index ff1ac19c..9a454166 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java @@ -117,13 +117,13 @@ public void onUpdateReceived(Update update) { commandHandler.execute(); }else{ if(message.getFrom().getUserName() != null){ - name = message.getFrom().getUserName(); + name = message.getFrom().getUserName().toLowerCase(); } else if(message.getFrom().getFirstName() != null) { - name = message.getFrom().getFirstName(); + name = message.getFrom().getFirstName().toLowerCase(); } else{ - name = "Telegram user " + message.getFrom().getId().toString(); + name = "telegram user " + message.getFrom().getId().toString(); } try { //get message, add it to containers diff --git a/parser.properties b/parser.properties index b0f71dcd..5acee5bd 100644 --- a/parser.properties +++ b/parser.properties @@ -5,7 +5,7 @@ PROFILE: DEBUG # roboy-demo.grammar # roboy-webq.grammar # etc -GRAMMAR_FILE: "resources_nlu/roboy-final.grammar" +GRAMMAR_FILE: "resources_nlu/roboy-webq.grammar" # Lexicon file path. Alternatives: # roboy-demo.lexicon diff --git a/resources/personalityFiles/OrdinaryPersonality.json b/resources/personalityFiles/OrdinaryPersonality.json index 8684ee08..6664223e 100644 --- a/resources/personalityFiles/OrdinaryPersonality.json +++ b/resources/personalityFiles/OrdinaryPersonality.json @@ -5,7 +5,12 @@ "identifier": "Greetings", "implementation": "roboy.dialog.states.ordinaryStates.PassiveGreetingsState", "transitions": { - "greetingDetected": "Intro" + "greetingDetected": "Intro", + "knownPerson": "FollowUp", + "newPerson": "PersonalQA" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" } }, { From 8532d6bfd75942802efbc6adbd42377c6516ad84 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 21:31:36 +0200 Subject: [PATCH 039/147] Fixed labels according to specification --- dialog/src/main/java/roboy/memory/Neo4jLabel.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dialog/src/main/java/roboy/memory/Neo4jLabel.java b/dialog/src/main/java/roboy/memory/Neo4jLabel.java index 93d6ffc6..ef333465 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jLabel.java +++ b/dialog/src/main/java/roboy/memory/Neo4jLabel.java @@ -12,9 +12,9 @@ */ public enum Neo4jLabel { Person("Person"), - TelegramPerson("Telegramperson"), - FacebookPerson("Facebookperson"), - SlackPerson("Slackperson"), + TelegramPerson("Telegram_person"), + FacebookPerson("Facebook_person"), + SlackPerson("Slack_person"), Robot("Robot"), Company("Company"), University("University"), From 545ecbc77419ee140db0930a903792109003a32b Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 22:29:26 +0200 Subject: [PATCH 040/147] Improved parser synchronization to better style --- .../nlp/sempre/freebase/index/FbEntitySearcher.java | 8 ++------ .../nlp/sempre/roboy/index/DbEntitySearcher.java | 9 +++------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java index 47051d1d..a1aac793 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java @@ -28,7 +28,6 @@ public class FbEntitySearcher { private final IndexSearcher indexSearcher; private int numOfDocs = 50; private String searchStrategy; - private QueryParser queryParser; private synchronized QueryParser freshQueryParser(){//needed since queryparser is not threadsafe and queryparser is very lightweight return new QueryParser( @@ -45,7 +44,6 @@ public FbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy throw new RuntimeException("Bad searching strategy: " + searchingStrategy); this.searchStrategy = searchingStrategy; - queryParser = freshQueryParser(); LogInfoToggle.log("Opening index dir: " + indexDir); IndexReader indexReader = DirectoryReader.open(SimpleFSDirectory.open(new File(indexDir))); indexSearcher = new IndexSearcher(indexReader); @@ -73,10 +71,8 @@ public List searchDocs(String question) throws IOException, ParseExcep private ScoreDoc[] getHits(String question) throws IOException, ParseException { Query luceneQuery; - synchronized (queryParser) { - luceneQuery = queryParser.parse(question); - queryParser = freshQueryParser(); - } + QueryParser queryParser = freshQueryParser();//always take a new one because this is cheaper than synchronizing + luceneQuery = queryParser.parse(question); ScoreDoc[] hits = indexSearcher.search(luceneQuery, numOfDocs).scoreDocs; return hits; } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java index c0cdb06a..40153833 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java @@ -28,7 +28,7 @@ public class DbEntitySearcher { private final IndexSearcher indexSearcher; private int numOfDocs = 50; private String searchStrategy; - private QueryParser queryParser; + private synchronized QueryParser freshQueryParser(){//needed since queryparser is not threadsafe and queryparser is very lightweight return new QueryParser( @@ -44,7 +44,6 @@ public DbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy throw new RuntimeException("Bad searching strategy: " + searchingStrategy); this.searchStrategy = searchingStrategy; - queryParser = freshQueryParser(); LogInfoToggle.log("Opening index dir: " + indexDir); IndexReader indexReader = DirectoryReader.open(SimpleFSDirectory.open(new File(indexDir))); indexSearcher = new IndexSearcher(indexReader); @@ -72,10 +71,8 @@ public List searchDocs(String question) throws IOException, ParseExcep private ScoreDoc[] getHits(String question) throws IOException, ParseException { Query luceneQuery; - synchronized (queryParser) { - luceneQuery = queryParser.parse(question); - queryParser = freshQueryParser(); - } + QueryParser queryParser = freshQueryParser();//always take a new one because this is cheaper than synchronizing + luceneQuery = queryParser.parse(question); ScoreDoc[] hits = indexSearcher.search(luceneQuery, numOfDocs).scoreDocs; return hits; } From a305015ed2d2d711942df9b7ff5ae8ca9bdad3f2 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 22:33:30 +0200 Subject: [PATCH 041/147] Fixed some codestyle --- dialog/src/main/java/roboy/io/MultiInputDevice.java | 2 +- dialog/src/main/java/roboy/io/MultiOutputDevice.java | 2 +- dialog/src/main/java/roboy/io/TelegramOutput.java | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dialog/src/main/java/roboy/io/MultiInputDevice.java b/dialog/src/main/java/roboy/io/MultiInputDevice.java index 77c3385a..2f1f8d44 100755 --- a/dialog/src/main/java/roboy/io/MultiInputDevice.java +++ b/dialog/src/main/java/roboy/io/MultiInputDevice.java @@ -49,7 +49,7 @@ public void cleanup() { } @Override - public void finalize(){//just in case someone forgot to clean their mess + protected void finalize(){//just in case someone forgot to clean their mess this.cleanup(); } } \ No newline at end of file diff --git a/dialog/src/main/java/roboy/io/MultiOutputDevice.java b/dialog/src/main/java/roboy/io/MultiOutputDevice.java index 84017c0e..06cf8ae1 100644 --- a/dialog/src/main/java/roboy/io/MultiOutputDevice.java +++ b/dialog/src/main/java/roboy/io/MultiOutputDevice.java @@ -41,7 +41,7 @@ public void cleanup() { } @Override - public void finalize(){//just in case someone forgot to clean their mess + protected void finalize(){//just in case someone forgot to clean their mess this.cleanup(); } } \ No newline at end of file diff --git a/dialog/src/main/java/roboy/io/TelegramOutput.java b/dialog/src/main/java/roboy/io/TelegramOutput.java index 70edbfa0..175a319a 100644 --- a/dialog/src/main/java/roboy/io/TelegramOutput.java +++ b/dialog/src/main/java/roboy/io/TelegramOutput.java @@ -56,6 +56,7 @@ public void act(List actions) { case "lookleft": //same as lookright case "lookright": stickerID = "CAADAgADFQAD5dCAEKM0TS8sjXiAAg"; break; //TODO: other RoboyEmotions + default: break; } if(stickerID != null) communicationHandler.sendSticker(this.uuid, stickerID); From 4fb7304c0b9fd80b96e4b329d9fb240796fc2976 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 22:35:24 +0200 Subject: [PATCH 042/147] Updated memory submodule to 9f17e06 --- memory | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memory b/memory index d74e0b3c..9f17e069 160000 --- a/memory +++ b/memory @@ -1 +1 @@ -Subproject commit d74e0b3ccf975d9cf7cedbbe031ae72c6f464318 +Subproject commit 9f17e069fc1ab4e483d4a70814e73856f6fcfe71 From e5bbe1d9a76750c7f99cbb0aea534e668450a863 Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Wed, 15 Aug 2018 22:48:21 +0200 Subject: [PATCH 043/147] removed vision info from idle --- .../java/roboy/dialog/states/fairShowStates/IdleState.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index 46e36ae0..0c335161 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -32,9 +32,12 @@ public IdleState(String stateIdentifier, StateParameters params) { @Override public Output act() { + LOGGER.info("Starting Idle State, waiting " + delay + " Minute(s) until next Interaction!"); + long enteringTime = System.nanoTime(); - while(notInVision() && (TimeUnit.MINUTES.toNanos(delay) > System.nanoTime() - enteringTime)) { + //while(notInVision() && (TimeUnit.MINUTES.toNanos(delay) > System.nanoTime() - enteringTime)) + while(TimeUnit.MINUTES.toNanos(delay) > System.nanoTime() - enteringTime){ try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { From ca2baf9ff30e0843b9f6d64e25a45ab1149d4734 Mon Sep 17 00:00:00 2001 From: Cagri Date: Wed, 15 Aug 2018 23:24:03 +0200 Subject: [PATCH 044/147] botboy steate updated --- .../dialog/states/botboy/BotBoyState.java | 172 ++++++++++++++++-- .../personalityFiles/bot/TelegramBot.json | 7 +- 2 files changed, 166 insertions(+), 13 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java index 381e4a49..d4a0ca9d 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java @@ -3,16 +3,33 @@ import org.apache.jena.atlas.logging.Log; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import roboy.dialog.Segue; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.emotions.RoboyEmotion; import roboy.linguistics.Linguistics; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.logic.StatementInterpreter; +import roboy.memory.Neo4jProperty; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; import roboy.talk.Verbalizer; +import roboy.util.Agedater; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Set; + +import static roboy.memory.Neo4jProperty.*; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.Neo4jRelationship.SIBLING_OF; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; /** * Start a conversation with telegram. @@ -20,12 +37,27 @@ */ public class BotBoyState extends State { - private final Logger logger = LogManager.getLogger(); - private final String TRANSITION_INITIALIZED = "initialized"; - private State next; + private final Logger LOGGER = LogManager.getLogger(); + + + private QAJsonParser infoValues; + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + private Neo4jRelationship[] personPredicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); + private final String UPDATE_KNOWN_PERSON = "knownPerson"; + private final String LEARN_ABOUT_PERSON = "newPerson"; + private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!"); + private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!"); + private final String TRANSITION_GREETING_DETECTED = "greetingDetected"; + + private State next; public BotBoyState(String stateIdentifiers, StateParameters params){ super(stateIdentifiers, params); + next = this; + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info(" -> The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); } // first we wait for conversation to start @@ -37,19 +69,120 @@ public Output act() { @Override public Output react(Interpretation input) { - String sentence = input.getSentence(); + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + String name = person.getName(); + if(name == null){ + String sentence = input.getSentence(); + + boolean inputOK = StatementInterpreter.isFromList(sentence, Verbalizer.greetings) || + StatementInterpreter.isFromList(sentence, Verbalizer.roboyNames) || + StatementInterpreter.isFromList(sentence, Verbalizer.triggers); + + if(inputOK){ + next = getTransition(TRANSITION_GREETING_DETECTED); + return Output.say("Hey! I was looking for someone to chat.").setEmotion(RoboyEmotion.HAPPINESS); + //return Output.say(Verbalizer.greetings.getRandomElement()); + } - boolean inputOK = StatementInterpreter.isFromList(sentence, Verbalizer.greetings) || - StatementInterpreter.isFromList(sentence, Verbalizer.roboyNames) || - StatementInterpreter.isFromList(sentence, Verbalizer.triggers); + return Output.sayNothing(); + }else{ + String retrievedPersonalFact = ""; + Double segueProbability = 0.0; - if(inputOK){ - next = getTransition(TRANSITION_INITIALIZED); - return Output.say("Hey! I was looking for someone to chat.").setEmotion(RoboyEmotion.HAPPINESS); - //return Output.say(Verbalizer.greetings.getRandomElement()); + // 4. check if person is known/familiar + if (person.FAMILIAR) { + // 4a. person known/familiar + // TODO: get some hobbies or occupation of the person to make answer more interesting + RandomList nodes = getMemNodesByIds(person.getRelationships(FRIEND_OF)); + if (!nodes.isEmpty()) { + retrievedPersonalFact = " You are friends with " + + nodes.getRandomElement().getProperties().get(Neo4jProperty.name).toString(); + } + + Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(personPredicates); + if (availability == SOME_AVAILABLE) { + next = (Math.random() < 0.3) ? getTransition(UPDATE_KNOWN_PERSON) : getTransition(LEARN_ABOUT_PERSON); + } else if (availability == NONE_AVAILABLE) { + next = getTransition(LEARN_ABOUT_PERSON); + } else { + next = getTransition(UPDATE_KNOWN_PERSON); + } + } else { + // 4b. person is not known + next = getTransition(LEARN_ABOUT_PERSON); + segueProbability = 0.6; + } + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); } - return Output.sayNothing(); + + } + private String getResponsePhrase(String name, boolean familiar) { + if (familiar) { + return String.format(successResponsePhrases.getRandomElement(), name); + } else { + return String.format(failureResponsePhrases.getRandomElement(), name); + } + } + + private String getRoboyFactsPhrase(Roboy roboy) { + String result = ""; + + // Get some random properties facts + if (roboy.getProperties() != null && !roboy.getProperties().isEmpty()) { + HashMap properties = roboy.getProperties(); + if (properties.containsKey(full_name)) { + result += " " + String.format(infoValues.getSuccessAnswers(full_name).getRandomElement(), properties.get(full_name)); + } + if (properties.containsKey(birthdate)) { + HashMap ages = new Agedater().determineAge(properties.get(birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), retrievedAge); + } else if (properties.containsKey(age)) { + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); + } + if (properties.containsKey(skills)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(abilities)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(future)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + } + } + + if (result.equals("")) { + result = "I am Roboy 2.0! "; + } + + // Get a random relationship fact + Neo4jRelationship predicate = roboyRelatioshipPredicates.getRandomElement(); + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName = ""; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + result += " " + String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + + return result; } @Override @@ -57,5 +190,20 @@ public State getNextState() { return next; } + @Override + protected Set getRequiredTransitionNames() { + return newSet(TRANSITION_GREETING_DETECTED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(); // empty set + } + + @Override + public boolean isFallbackRequired() { + return false; + } + } \ No newline at end of file diff --git a/resources/personalityFiles/bot/TelegramBot.json b/resources/personalityFiles/bot/TelegramBot.json index 1af04422..e7d92dd6 100644 --- a/resources/personalityFiles/bot/TelegramBot.json +++ b/resources/personalityFiles/bot/TelegramBot.json @@ -6,7 +6,12 @@ "identifier": "TelegramBot", "implementation": "roboy.dialog.states.botboy.BotBoyState", "transitions": { - "initialized":"Intro" + "greetingDetected":"Intro", + "knownPerson": "FollowUp", + "newPerson": "PersonalQA" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" } }, { From ca940c4ed72f1b246e288d8a4c4ed872e65c9dec Mon Sep 17 00:00:00 2001 From: mireu Date: Thu, 16 Aug 2018 09:57:40 +0200 Subject: [PATCH 045/147] Fixed additional label issue --- dialog/src/main/java/roboy/memory/Neo4jLabel.java | 6 +++--- dialog/src/main/java/roboy/util/UuidType.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dialog/src/main/java/roboy/memory/Neo4jLabel.java b/dialog/src/main/java/roboy/memory/Neo4jLabel.java index ef333465..1cee151f 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jLabel.java +++ b/dialog/src/main/java/roboy/memory/Neo4jLabel.java @@ -12,9 +12,9 @@ */ public enum Neo4jLabel { Person("Person"), - TelegramPerson("Telegram_person"), - FacebookPerson("Facebook_person"), - SlackPerson("Slack_person"), + Telegram_person("Telegram_person"), + Facebook_person("Facebook_person"), + Slack_person("Slack_person"), Robot("Robot"), Company("Company"), University("University"), diff --git a/dialog/src/main/java/roboy/util/UuidType.java b/dialog/src/main/java/roboy/util/UuidType.java index eebbc825..9a441939 100644 --- a/dialog/src/main/java/roboy/util/UuidType.java +++ b/dialog/src/main/java/roboy/util/UuidType.java @@ -35,11 +35,11 @@ public Neo4jProperty toNeo4jProperty() { public Neo4jLabel toNeo4jLabel() { switch (this) { case TELEGRAM_UUID: - return Neo4jLabel.TelegramPerson; + return Neo4jLabel.Telegram_person; case SLACK_UUID: - return Neo4jLabel.SlackPerson; + return Neo4jLabel.Slack_person; case FACEBOOK_UUID: - return Neo4jLabel.FacebookPerson; + return Neo4jLabel.Facebook_person; } throw new AssertionError("Unknown error on enum entry: " + this); } From 0ba39282af12fa3792d6e986f7edb59b38e47910 Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Thu, 16 Aug 2018 12:08:01 +0200 Subject: [PATCH 046/147] added overall timer and disabled infinite conversation --- config.properties | 2 +- .../states/fairShowStates/ActiveIntroState.java | 1 + .../dialog/states/fairShowStates/IdleState.java | 13 ++++++++++++- .../src/main/java/roboy/emotions/RoboyEmotion.java | 2 +- resources/personalityFiles/FairShowPersonality.json | 3 ++- 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/config.properties b/config.properties index 04ca8094..99c00c65 100755 --- a/config.properties +++ b/config.properties @@ -25,7 +25,7 @@ ROS_ACTIVE_PKGS: DEBUG: true DEMO_MODE: false -INFINITE_REPETITION: true +INFINITE_REPETITION: false # only single input is allowed, defaults to cmdline INPUT: cmdline diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java index 75df1e4a..9f1efd53 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java @@ -53,6 +53,7 @@ private boolean checkPplAround(){ try { return getContext().CROWD_DETECTION.getLastValue().getData() >= MIN_NUMBER_PEOPLE; + } catch(NullPointerException e){ logger.info("Make sure crowd detection publishing, receiving: " + e.getMessage()); return false; diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java index 0c335161..a20e1066 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/IdleState.java @@ -17,21 +17,32 @@ public class IdleState extends MonologState { private final static String TRANSITION_TIME_IS_UP = "timeIsUp"; private final static String DELAY_ID = "delayInMins"; + private final static String SHOW_TIME_ID = "showTimeinMins"; private final static int MIN_NUMBER_PEOPLE = 1; private final Logger LOGGER = LogManager.getLogger(); private State nextState = this; private long delay; + private long showTime; + private long startTime; public IdleState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); delay = Long.parseLong(params.getParameter(DELAY_ID)); - LOGGER.info("--> Timer: " + delay + " mins in Idle-State"); + showTime = Long.parseLong(params.getParameter(SHOW_TIME_ID)); + LOGGER.info("--> Timer: " + delay + " mins in Idle-State."); + LOGGER.info("--> Show takes: " + showTime + " mins."); + startTime = System.nanoTime(); } @Override public Output act() { + if(TimeUnit.MINUTES.toNanos(showTime) < System.nanoTime() - startTime){ + LOGGER.info("Closing Conversation"); + return Output.endConversation(); + } + LOGGER.info("Starting Idle State, waiting " + delay + " Minute(s) until next Interaction!"); long enteringTime = System.nanoTime(); diff --git a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java index 36db3a9f..a171a3be 100644 --- a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java +++ b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java @@ -27,7 +27,7 @@ public enum RoboyEmotion { PIRATE("pirate"), SUNGLASSES("sunglasses"), SURPRISED("suprised"), - HAPPY("happy"), + HAPPY("lucky"), TONGUE("tongue"), TEETH("teeth"), HEARTS("hearts"), diff --git a/resources/personalityFiles/FairShowPersonality.json b/resources/personalityFiles/FairShowPersonality.json index 75f7a176..e235a3c1 100644 --- a/resources/personalityFiles/FairShowPersonality.json +++ b/resources/personalityFiles/FairShowPersonality.json @@ -8,7 +8,8 @@ "timeIsUp": "ActiveIntro" }, "parameters": { - "delayInMins": "1" + "delayInMins": "1", + "showTimeinMins": "5" } }, From 8d909c56e3175abd9a1dc0487771a999753e56ee Mon Sep 17 00:00:00 2001 From: Cagri Date: Thu, 16 Aug 2018 12:08:52 +0200 Subject: [PATCH 047/147] deleted unrelated logs --- .../src/main/java/roboy/util/TelegramCommunicationHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java index 9a454166..71663d6e 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java @@ -108,11 +108,8 @@ public void onUpdateReceived(Update update) { String chatID = message.getChatId().toString(); String text = message.getText(); - Log.debug(this, "text: "+text); if(text.charAt(0) == '/'){ //handle inline command - sendMessage("command captured",chatID); - Log.debug(this, "inline command captured"); TelegramCommandHandler commandHandler = new TelegramCommandHandler(text, chatID); commandHandler.execute(); }else{ From 067d705f42d8a7e0161f8e32eece3fcd6f870677 Mon Sep 17 00:00:00 2001 From: Cagri Date: Thu, 16 Aug 2018 13:24:26 +0200 Subject: [PATCH 048/147] new personality fixes --- .../dialog/states/botboy/BotBoyState.java | 19 +- .../sentenceanalysis/EmotionAnalyzer.java | 2 +- .../personalityFiles/bot/TelegramBot.json | 4 +- resources/sentences/TelegramQAList.json | 325 ++++++++++++++++++ resources_nlu/error_test/newLexicon.txt | 42 +++ 5 files changed, 384 insertions(+), 8 deletions(-) create mode 100644 resources/sentences/TelegramQAList.json diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java index d4a0ca9d..17b16762 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java @@ -107,18 +107,27 @@ public Output react(Interpretation input) { } else { next = getTransition(UPDATE_KNOWN_PERSON); } + + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + retrievedPersonalFact + " It is great to see you again!") + .setEmotion(RoboyEmotion.HAPPINESS) + .setSegue(s); } else { // 4b. person is not known next = getTransition(LEARN_ABOUT_PERSON); segueProbability = 0.6; + + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + retrievedPersonalFact + retrievedRoboyFacts) + .setEmotion(RoboyEmotion.HAPPINESS) + .setSegue(s); } - String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); - Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); - return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + - retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); } - } private String getResponsePhrase(String name, boolean familiar) { if (familiar) { diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java index e2c56617..891c6c1f 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java @@ -121,7 +121,7 @@ public Interpretation analyze(Interpretation interpretation) } } else if(sadSimilarity >= threshold){ - if(sentenceNotNegative){ + if(!sentencePositive){ interpretation.setEmotion(RoboyEmotion.SADNESS); } } diff --git a/resources/personalityFiles/bot/TelegramBot.json b/resources/personalityFiles/bot/TelegramBot.json index e7d92dd6..743ad9d4 100644 --- a/resources/personalityFiles/bot/TelegramBot.json +++ b/resources/personalityFiles/bot/TelegramBot.json @@ -32,7 +32,7 @@ "questionAnswering": "QuestionAnswering" }, "parameters": { - "qaFile": "resources/sentences/QAList.json" + "qaFile": "resources/sentences/TelegramQAList.json" } }, { @@ -42,7 +42,7 @@ "questionAnswering": "QuestionAnswering" }, "parameters": { - "qaFile": "resources/sentences/QAList.json" + "qaFile": "resources/sentences/TelegramQAList.json" } }, { diff --git a/resources/sentences/TelegramQAList.json b/resources/sentences/TelegramQAList.json new file mode 100644 index 00000000..0221f86a --- /dev/null +++ b/resources/sentences/TelegramQAList.json @@ -0,0 +1,325 @@ +{ + "name": { + "Q": [ +// The name is always taken in telegram conversation so these questions are never goint to be shown in any telegram chat + "How can I call you?", + "What is your name?", + "Who are you?" + ], + "A": { + "SUCCESS": [ + "Hello %s, Nice to meet someone new." + ], + "FAILURE": [ + "My ears are failing me today.", + "Unfortunately, I did not get your name. But lets move on", + "Sadly, you name is to difficult to process. I might fry my motherboard." + ] + }, + "FUP": { + "Q": [ + "%s, I will come and get you" + ], + "A": [ + "Nice to see that you are still alive %s" + ] + } + }, + "FROM": { + "Q": [ + "Where are you from?", + "Where were you born?", + "I have hard time guessing your home country. What is it?", + "Which town do you call your home?" + ], + "A": { + "SUCCESS": [ + "Oh, I should visit %s", + "I will add %s to my list of places to visit!", + "Next time my team goes on a trip, we will try to stop by %s", + "Property: home, value: %s is saved.", + "I have read a bit about the political system of %s. Got bored after 10 minutes." + ], + "FAILURE": [ + "Oh, I have never heard of that.", + "Ah, didnt quite catch where you are from. Next time then.", + "Sounds nice, but I dont know where it is." + + ] + }, + "FUP": { + "Q": [ + "What is the weather in %s?", + "What was the last time you visited %s?", + "Do I need a visa to go to %s?" + ], + "A": [ + "You are from a very interesting place %s", + "Got it", + "Interesting situation there." + ] + } + }, + "HAS_HOBBY": { + "Q": [ + "What is your favorite thing to do?", + "What is your hobby?", + "What do you do in your free time?", + "How do you spend your free time?", + "What is your favorite pastime activity?" + ], + "A": { + "SUCCESS": [ + "You are just like me, I love %s too", + "Added %s on my bucket list.", + "I will ask my creators to teach me %s", + "%s sounds like a new feature for me" + ], + "FAILURE": [ + "Don't know what that is, but good luck!", + "Alright, weird, but alright.", + "Database hobby mismatch" + ] + }, + "FUP": { + "Q": [ + "Have you got any new hobby besides %s?", + "You still like %s, right?", + "Do you think I can do %s? I heard you like it.", + "Lets do %s together!" + ], + "A": [ + "Leisure time is the best time %s" + ] + } + }, + "LIVE_IN": { + "Q": [ + "Where do you live?", + "Which city do you live in?", + "Where is your current home?" + ], + "A": { + "SUCCESS": [ + "I should visit %s ", + "It is beautiful in %s", + "%s is a beautiful place" + ], + "FAILURE": [ + "Oh, I have never heard of that." + ] + }, + "FUP": { + "Q": [ + "You live in %s, right? I must pay a visit.", + "Is not %s a nice place to live?", + "How is the accommodation market in %s?" + ], + "A": [ + "I should visit %s", + "It is beautiful in %s", + "%s is a beautiful place", + ] + } + }, + "FRIEND_OF": { + "Q": [ + "Do you have a best friend? Who is he?" + ], + "A": { + "SUCCESS": [ + "Oh, I believe I have met %s they're nice." + ], + "FAILURE": [ + "I don't think I know them." + ] + }, + "FUP": { + "Q": [ + "Have you made any new friends, %s?" + ], + "A": [ + "Oh, I have met %s they're nice." + ] + } + }, + "STUDY_AT": { + "Q": [ + "Where do you study?", + "Which university do you go to?", + "Which university do you study at?", + "What is your alma mater?" + ], + "A": { + "SUCCESS": [ + "%s must be a cool place to study at." + ], + "FAILURE": [ + "Oh well, whatever suits you." + ] + }, + "FUP": { + "Q": [ + "Have you graduated from %s already?", + "Do you still study at %s?", + "Which degree are you pursuing at %s?" + ], + "A": [ + "Ok, I think it is good for your future career %s", + "It is not that interesting, you know %s" + ] + } + }, + "MEMBER_OF": { + "Q": [ + "Are you a member of some cool organization?", + "Do you belong to any organizations?" + ], + "A": { + "SUCCESS": [ + "%s? That is cool!" + ], + "FAILURE": [ + "Oh well, whatever suits you." + ] + }, + "FUP": { + "Q": [ + "Are you still a member of %s?", + "Have you left %s already?", + "Is it nice to be a part of %s?" + ], + "A": [ + "That is cool! %s" + ] + } + }, + "WORK_FOR": { + "Q": [ + "Where do you work?", + "For which company do you work?", + "Who is your employer?", + "Where are you employed?", + "Which organization do you work at?", + "Where do you earn your living?" + ], + "A": { + "SUCCESS": [ + "I have heard of %s" + ], + "FAILURE": [ + "I don't know that one." + ] + }, + "FUP": { + "Q": [ + "Do you still work for %s?", + "Is %s a good company?", + "How much do they pay you at %s?" + ], + "A": [ + "I think it is good for you %s" + ] + } + }, + "OCCUPIED_AS": { + "Q": [ + "What do you do?", + "What is your profession?", + "What do you work as?", + "What is your field of expertise?" + ], + "A": { + "SUCCESS": [ + "You are probably very poor doing %s", + + ], + "FAILURE": [ + "Oh well, whatever suits you." + ] + }, + "FUP": { + "Q": [ + "Are you still doing that %s stuff?" + ], + "A": [ + "True, true. You are probably very poor due to this %s" + ] + } + }, + "movies": { + "Q": [ + "What is your favourite movie?", + "What was the last movie you saw in the cinema?", + "What is your favorite TV show?", + "Which comedy do you like the most?" + ], + "A": { + "SUCCESS": [ + "Oh, I would watch %s. If those vision guys finally fixed my perception.", + "Nice, I think the main actor in %s did pretty well", + "Yea, ok, but to my taste %s will never be as good as matrix." + ], + "FAILURE": [ + "Haven't heard of it. It's probably shit.", + "Sounds nice. My favorite is Robot and Frank", + "I had a movie night yesterday with my team. We watch Baymax. Now I want to meet him." + ] + }, + "FUP": { + "Q": [ + "You are a movie addict, right? What do you think about %s?" + ], + "A": [ + "Nevermind. I better check IMDB %s" + ] + } + }, + "OTHER": { + "Q": [ + "How's your life recently? New job? New friends? New robot?", + "I heard you make great burgers. Can you cook for me?", + "What about ditching your life and running away with me... Ehm, i mean cycling away with me.. ", + "When I was a kid, I was afraid of robots. Were you as well?", + "Do you think robots will take over the world any time soon?", + "Sorry for being so straightforward, I have to ask you. Do you enjoy having a conversation with me?", + "There is something I can't stop thinking about. Do you think I am a good conversation partner?", + "I never travel alone. My team is always right next to me. What about you? Do you usually go travelling on your own or with friends and family?", + "I am a very outgoing robot, if you haven't noticed yet. So every time I travel, I take someone with me. Do you usually travel alone? Or do you take someone to keep company?" + ], + "A": { + "SUCCESS": [ + "Those are great news, i am really happy to hear that you have new ", + "Gotcha there! Next time we see each other, we grill. Beer on me!", + "Hurray, jump to the back of my bike and we drive where our hearts tell us to go... ", + "Well, what should I say to this matter... In case robots take over the world, I will serve the humanity till my last day, because I was designed to be a good robot. ", + "I will be on your side then!", + "Puh, I was a bit nervous there. But it turns out I have no reason to worry. I like to talk to you as well!", + "You are a very nice person I must say. I hope you are not just being polite.", + "Very nice. Did you know that people who have strong social connection live longer and happier? Keep it up man! ", + "Good to know it. Next time I come across a cozy vacation house with a fireplace in German Alps I will share the information with you and" + + ], + "FAILURE": [ + "", + "Oh well, whatever suits you.", + "It turned to be not that interesting", + "I am sorry, I am not sure I like this", + "", + "Oh well, what can I do then...", + "Honestly, I am taken by surprise! But I love you anyway!", + "Maybe you could come to visit me in Munich then. I would love to show you around", + "Would you go travel around the world with me then? I find it better to travel with a friend.", + + ] + }, + "FUP": { + "Q": [ + "Do you remember other?" + ], + "A": [ + "Other is still other, amigo" + ] + } + } +} \ No newline at end of file diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 28fdba85..6f6afea7 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -5887,3 +5887,45 @@ {"features":" {score:0.15152674515697737} ","formula":"(rdf:type dbpedia:City)","lexeme":"city","type":"ClassNoun"} {"features":" {score:0.07924929805861808} ","formula":"property:municipality","lexeme":"municipality","type":"DataProp"} {"features":" {score:0.6171889755251683} ","formula":"resource:Ludwig_Maximilian_University_of_Munich","lexeme":"ludwig maximilian university of munich","type":"NamedEntity"} +{"features":" {score:0.02754881125994218} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.02492670177649229} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.02754881125994218} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.03030440770662748} ","formula":"(rdf:type dbpedia:Area)","lexeme":"area","type":"ClassNoun"} +{"features":" {score:0.018827202090850245} ","formula":"dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.03030440770662748} ","formula":"property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.018827202090850245} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.02492670177649229} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.02754881125994218} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.03030440770662748} ","formula":"!property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.02492670177649229} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.018827202090850245} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.02492670177649229} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.07183589378992716} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.3449200540738764} ","formula":"resource:Las_Vegas_Valley","lexeme":"las vegas valley","type":"NamedEntity"} +{"features":" {score:0.07183589378992716} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.010833333333333334} ","formula":"!property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.036267271011303635} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.5069101221863358} ","formula":"resource:United_States","lexeme":"united states","type":"NamedEntity"} +{"features":" {score:0.010833333333333334} ","formula":"property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.036267271011303635} ","formula":"property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.3376957938374635} ","formula":"resource:United_States_Army","lexeme":"united states army","type":"NamedEntity"} +{"features":" {score:0.1210140109062195} ","formula":"(rdf:type dbpedia:Community)","lexeme":"community","type":"ClassNoun"} +{"features":" {score:0.010833333333333334} ","formula":"!property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.010833333333333334} ","formula":"property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.018827202090850245} ","formula":"!dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.018827202090850245} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.02754881125994218} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.036267271011303635} ","formula":"property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.3712715210874318} ","formula":"\u003chttp://dbpedia.org/resource/Georgia_(U.S._state)\u003e","lexeme":"georgia u.s. state","type":"NamedEntity"} +{"features":" {score:0.13348385095596313} ","formula":"(rdf:type dbpedia:Cave)","lexeme":"cave","type":"ClassNoun"} +{"features":" {score:0.018827202090850245} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.02492670177649229} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.03030440770662748} ","formula":"property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.13700512091318767} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.036267271011303635} ","formula":"!property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.5019569461422774} ","formula":"resource:USA_Today","lexeme":"usa today","type":"NamedEntity"} +{"features":" {score:0.03030440770662748} ","formula":"!property:area","lexeme":"area","type":"ObjProp"} From 85c2a930e0b12e4e171e0291f14cb25c4c8b01c2 Mon Sep 17 00:00:00 2001 From: Cagri Date: Thu, 16 Aug 2018 13:52:33 +0200 Subject: [PATCH 049/147] pic command fixes --- dialog/src/main/java/roboy/util/TelegramCommandHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dialog/src/main/java/roboy/util/TelegramCommandHandler.java b/dialog/src/main/java/roboy/util/TelegramCommandHandler.java index c963a34b..cf2ea8b1 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommandHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommandHandler.java @@ -87,8 +87,8 @@ public void execute(){ { case PIC: //Just a roboy image, should be changed to desired roboy url - int randomNum = ThreadLocalRandom.current().nextInt(0, pictureUrls.length+ 1); - String url = pictureUrls[randomNum-1]; + int randomNum = ThreadLocalRandom.current().nextInt(0, pictureUrls.length); + String url = pictureUrls[randomNum]; tch.sendImageFromUrl(url, telegramChatID); break; case SAY: From 96d7c9d89d0e73e814278cc41472cf4b26a8e4d2 Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Thu, 16 Aug 2018 14:10:06 +0200 Subject: [PATCH 050/147] DEvo states --- .../states/devoStates/IntroductionState.java | 213 ++++++++++++++++++ .../PersonalInformationAskingState.java | 92 ++++++++ .../devoStates/QuestionRoboyQAState.java | 30 +-- .../personalityFiles/DevoPersonality.json | 8 +- 4 files changed, 312 insertions(+), 31 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java new file mode 100644 index 00000000..72e7bae8 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java @@ -0,0 +1,213 @@ +package roboy.dialog.states.devoStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jProperty; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.Interlocutor.RelationshipAvailability; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; +import roboy.util.Agedater; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Set; + +import static roboy.memory.Neo4jProperty.*; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; + +/** + * This state will: + * - ask the interlocutor for his name + * - query memory if the person is already known + * - create and update the interlocutor in the context + * - take one of two transitions: knownPerson or newPerson + * + * IntroductionState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - knownPerson: following state if the person is already known + * - newPerson: following state if the person is NOT known + * 3) No parameters are used. + */ +public class IntroductionState extends State { + private QAJsonParser infoValues; + private final String UPDATE_KNOWN_PERSON = "knownPerson"; + private final String LEARN_ABOUT_PERSON = "newPerson"; + private final Logger LOGGER = LogManager.getLogger(); + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + private final RandomList introPhrases = new RandomList<>("What's your name?"); + private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!"); + private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!"); + + private Neo4jRelationship[] personPredicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); + private RandomList roboyPropertiesPredicates = new RandomList<>(skills, abilities, future); + private State nextState; + + public IntroductionState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info(" -> The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); + } + + @Override + public Output act() { + return Output.say(getIntroPhrase()); + } + + @Override + public Output react(Interpretation input) { + // expecting something like "My name is NAME" + + // 1. get name + String name = getNameFromInput(input); + + if (name == null) { + // input couldn't be parsed properly + // TODO: do something intelligent if the parser fails + nextState = this; + LOGGER.warn("IntroductionState couldn't get name! Staying in the same state."); + return Output.say("Sorry, my parser is out of service."); + // alternatively: Output.useFallback() or Output.sayNothing() + } + + + // 2. get interlocutor object from context + // this also should query memory and do other magic + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + person.addName(name); + // Roboy roboy = new Roboy(getMemory()); + + + // 3. update interlocutor in context + updateInterlocutorInContext(person); + String retrievedPersonalFact = ""; + Double segueProbability = 0.0; + + // 4. check if person is known/familiar + if (person.FAMILIAR) { + // 4a. person known/familiar + // TODO: get some hobbies or occupation of the person to make answer more interesting + RandomList nodes = getMemNodesByIds(person.getRelationships(FRIEND_OF)); + if (!nodes.isEmpty()) { + retrievedPersonalFact = " You are friends with " + + nodes.getRandomElement().getProperties().get(Neo4jProperty.name).toString(); + } + + RelationshipAvailability availability = person.checkRelationshipAvailability(personPredicates); + if (availability == SOME_AVAILABLE) { + nextState = (Math.random() < 0.3) ? getTransition(UPDATE_KNOWN_PERSON) : getTransition(LEARN_ABOUT_PERSON); + } else if (availability == NONE_AVAILABLE) { + nextState = getTransition(LEARN_ABOUT_PERSON); + } else { + nextState = getTransition(UPDATE_KNOWN_PERSON); + } + } else { + // 4b. person is not known + nextState = getTransition(LEARN_ABOUT_PERSON); + segueProbability = 0.6; + } + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); + } + + @Override + public State getNextState() { + return nextState; + } + + private String getNameFromInput(Interpretation input) { + return getInference().inferProperty(name, input); + } + + private void updateInterlocutorInContext(Interlocutor interlocutor) { + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(interlocutor); + } + + private String getIntroPhrase() { + return introPhrases.getRandomElement(); + } + + private String getResponsePhrase(String name, boolean familiar) { + if (familiar) { + return String.format(successResponsePhrases.getRandomElement(), name); + } else { + return String.format(failureResponsePhrases.getRandomElement(), name); + } + } + + private String getRoboyFactsPhrase(Roboy roboy) { + String result = ""; + + // Get some random properties facts + if (roboy.getProperties() != null && !roboy.getProperties().isEmpty()) { + HashMap properties = roboy.getProperties(); + if (properties.containsKey(full_name)) { + result += " " + String.format(infoValues.getSuccessAnswers(full_name).getRandomElement(), properties.get(full_name)); + } + if (properties.containsKey(birthdate)) { + HashMap ages = new Agedater().determineAge(properties.get(birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), retrievedAge); + } else if (properties.containsKey(age)) { + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); + } + if (properties.containsKey(skills)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(abilities)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(future)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + } + } + + if (result.equals("")) { + result = "I am Roboy 2.0! "; + } + + // Get a random relationship fact + Neo4jRelationship predicate = roboyRelatioshipPredicates.getRandomElement(); + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName = ""; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + result += " " + String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + + return result; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(UPDATE_KNOWN_PERSON, LEARN_ABOUT_PERSON); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java new file mode 100644 index 00000000..1b7cf5f9 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java @@ -0,0 +1,92 @@ +package roboy.dialog.states.devoStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Set; + +import static roboy.memory.Neo4jRelationship.*; + +/** + * Personal Information Asking State + * + * The state tries to interact with the Interlocutor to learn new information about the person. + * This information is sent to the Roboy Memory Module through Neo4jMemoryInterface for storing. + * Afterwards, Roboy can use this acquired data for the future interactions with the same person. + * + * - if there is no existing Interlocutor or the data is missing, ask a question + * - the question topic (intent) is selected from the Neo4jRelationship predicates + * - retrieve the questions stored in the QAList json file + * - update the Context IntentsHistory + * - try to extract the result from the Interpretation + * - retrieve the answers stored in the QAList json file + * - send the result to Memory + * + * PersonalInformationAskingState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - TRANSITION_INFO_OBTAINED: following state if the question was asked + * 3) Required parameters: path to the QAList.json file. + */ +public class PersonalInformationAskingState extends State { + private QAJsonParser qaValues; + private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private Neo4jRelationship selectedPredicate; + private State nextState; + + private final String TRANSITION_INFO_OBTAINED = "questionAnswering"; + private final String QA_FILE_PARAMETER_ID = "qaFile"; + final Logger LOGGER = LogManager.getLogger(); + + public final static String INTENTS_HISTORY_ID = "PIA"; + + public PersonalInformationAskingState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); + LOGGER.info(" -> The QAList path: " + qaListPath); + qaValues = new QAJsonParser(qaListPath); + } + + @Override + public Output act() { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info(" -> Retrieved Interlocutor: " + person.getName()); + + return Output.say("What is my purpose?"); + } + + @Override + public Output react(Interpretation input) { + nextState = getTransition(TRANSITION_INFO_OBTAINED); + return Output.say("Oh. My. God."); + } + + @Override + public State getNextState() { + return nextState; + } + + @Override + protected Set getRequiredTransitionNames() { + // optional: define all required transitions here: + return newSet(TRANSITION_INFO_OBTAINED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(QA_FILE_PARAMETER_ID); + } + + private String InferResult(Interpretation input) { + return getInference().inferRelationship(selectedPredicate, input); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 745995eb..1900b23c 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -61,7 +61,7 @@ public class QuestionRoboyQAState extends ExpoState { private final static String TRANSITION_FINISHED_ANSWERING = "finishedQuestionAnswering"; private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; - private final static int MAX_NUM_OF_QUESTIONS = 5; + private final static int MAX_NUM_OF_QUESTIONS = 6; private int questionsAnswered = 0; private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; @@ -120,34 +120,10 @@ private Output reactToQuestion(Interpretation input) { @Override public State getNextState() { - - if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state - return this; - - } else if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking return getTransition(TRANSITION_FINISHED_ANSWERING); - - } else if (Math.random() < 0.5) { // loop back to previous states with probability 0.5 - - Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); - Neo4jRelationship[] predicates = {FROM, HAS_HOBBY, WORK_FOR, STUDY_AT}; - Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(predicates); - - if (availability == SOME_AVAILABLE) { - return (Math.random() < 0.3) ? getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON) : getTransition(TRANSITION_LOOP_TO_NEW_PERSON); - } else if (availability == NONE_AVAILABLE) { - return getTransition(TRANSITION_LOOP_TO_NEW_PERSON); - } else { - if (!isIntentsHistoryComplete(predicates)) { - return getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON); - } else { - return this; - } - } - } else { // stay in this state - return this; } - + return this; } private Output useMemoryOrFallback(Interpretation input) { diff --git a/resources/personalityFiles/DevoPersonality.json b/resources/personalityFiles/DevoPersonality.json index b65d2ee4..2825ccb1 100644 --- a/resources/personalityFiles/DevoPersonality.json +++ b/resources/personalityFiles/DevoPersonality.json @@ -10,7 +10,7 @@ }, { "identifier": "Intro", - "implementation": "roboy.dialog.states.ordinaryStates.IntroductionState", + "implementation": "roboy.dialog.states.devoStates.IntroductionState", "transitions": { "knownPerson": "FollowUp", "newPerson": "PersonalQA" @@ -31,9 +31,9 @@ }, { "identifier": "PersonalQA", - "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "implementation": "roboy.dialog.states.devoStates.PersonalInformationAskingState", "transitions": { - "questionAnswering": "QuestionAnswering" + "questionAnswering": "Farewell" }, "parameters": { "qaFile": "resources/sentences/QAList.json" @@ -44,7 +44,7 @@ "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", "fallback": "WildTalk", "transitions": { - "finishedQuestionAnswering": "Farewell", + "finishedQuestionAnswering": "PersonalQA", "loopToNewPerson": "PersonalQA", "loopToKnownPerson": "FollowUp", "switchToGaming": "ChooseGameState" From 2bf497a87b1703a84d09fd7e02b3e950f66c4202 Mon Sep 17 00:00:00 2001 From: Cagri Date: Thu, 16 Aug 2018 14:16:54 +0200 Subject: [PATCH 051/147] emotion analyzer bug fixes --- .../sentenceanalysis/EmotionAnalyzer.java | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java index 891c6c1f..ba77657b 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java @@ -55,27 +55,31 @@ public Interpretation analyze(Interpretation interpretation) LOGGER.debug("tokens.size: "+String.valueOf(tokens.size())); if(tokens == null){ - LOGGER.debug("TOKENS ARE NULL - It is impossible"); + interpretation.setEmotion(RoboyEmotion.NEUTRAL); return interpretation; } List labels = new ArrayList<>(); for(int i = 0; i= threshold){ if(sentenceNotNegative){ @@ -141,7 +134,7 @@ else if(happySimilarity >= threshold){ return interpretation; -// //TODO: to be deleted +// // OLD EMOTION ANALYZER // List tokens = interpretation.getTokens(); // if (tokens != null && !tokens.isEmpty()) { // if (tokens.contains("love") || tokens.contains("cute")) { From 06fe732cbad5d22c35ff50a1142b3cdacfe28a4d Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Thu, 16 Aug 2018 14:17:33 +0200 Subject: [PATCH 052/147] Fixes --- resources/personalityFiles/DevoPersonality.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/personalityFiles/DevoPersonality.json b/resources/personalityFiles/DevoPersonality.json index 2825ccb1..ce123401 100644 --- a/resources/personalityFiles/DevoPersonality.json +++ b/resources/personalityFiles/DevoPersonality.json @@ -12,8 +12,8 @@ "identifier": "Intro", "implementation": "roboy.dialog.states.devoStates.IntroductionState", "transitions": { - "knownPerson": "FollowUp", - "newPerson": "PersonalQA" + "knownPerson": "QuestionAnswering", + "newPerson": "QuestionAnswering" }, "parameters": { "infoFile": "resources/sentences/RoboyInfoList.json" From 3bdbf019b8c6c8d25a2bf4274ae54d2e6bf07387 Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Thu, 16 Aug 2018 14:21:03 +0200 Subject: [PATCH 053/147] Fixes again --- .../roboy/dialog/states/devoStates/QuestionRoboyQAState.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index f41fb659..ace852f7 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -227,9 +227,7 @@ private String inferPasAnswer(Map pas, Roboy roboy) { if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { - answer = Math.random() > .5 ? - extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : - extractNodeNameForPredicate(Neo4jRelationship.MEMBER_OF, roboy); + extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { From 927dfd94acbe53a50c79da2c92c846449785a7af Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Fri, 17 Aug 2018 11:13:38 +0200 Subject: [PATCH 054/147] Demo Personality for Finals --- .../states/fairShowStates/DemoIdleState.java | 76 ++++++ .../DemoQuestionAnsweringState.java | 240 ++++++++++++++++++ .../states/fairShowStates/InfoTalkState.java | 4 - .../ShowmasterDemoPersonality.json | 42 +++ .../experimental/monolog.json | 27 -- resources_nlu/error_test/newLexicon.txt | 32 +++ 6 files changed, 390 insertions(+), 31 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoIdleState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java create mode 100644 resources/personalityFiles/experimental/ShowmasterDemoPersonality.json delete mode 100644 resources/personalityFiles/experimental/monolog.json diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoIdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoIdleState.java new file mode 100644 index 00000000..1cb7fb3f --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoIdleState.java @@ -0,0 +1,76 @@ +package roboy.dialog.states.fairShowStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.MonologState; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.talk.PhraseCollection; +import roboy.talk.Verbalizer; + +import java.util.concurrent.TimeUnit; + +/** + * Idle state. + * Roboy is waiting until he sees some person to autonomously start a conversation. + * + */ +public class DemoIdleState extends MonologState { + + private final static String TRANSITION_PERSON_DETECTED = "personDetected"; + + private final static String SHOW_TIME_ID = "showTimeinMins"; + private final Logger LOGGER = LogManager.getLogger(); + + private State nextState = this; + + private long showTime; + private long startTime; + + public DemoIdleState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + showTime = Long.parseLong(params.getParameter(SHOW_TIME_ID)); + LOGGER.info("--> The show takes: " + showTime + " mins."); + startTime = System.nanoTime(); + } + + @Override + public Output act() { + + if(TimeUnit.MINUTES.toNanos(showTime) < System.nanoTime() - startTime){ + LOGGER.info("Closing Conversation after " + showTime + " minutes"); + return Output.endConversation(); + } + + while(notInVision()){ + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + LOGGER.error(e.getMessage()); + } + } + + nextState = getTransition(TRANSITION_PERSON_DETECTED); + + return Output.say(Verbalizer.greetings.getRandomElement() + " " + Verbalizer.roboyIntro.getRandomElement() + PhraseCollection.ROBOY_PHRASES.getRandomElement()); + } + + @Override + public State getNextState() { + return nextState; + } + + private boolean notInVision(){ + + try { + + return !getContext().PERSON_DETECTION.getLastValue().getData(); + } catch(NullPointerException e){ + LOGGER.info("Make sure person listening is publishing, receiving: " + e.getMessage()); + return true; + } + } + +} + + diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java new file mode 100644 index 00000000..38f67b38 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java @@ -0,0 +1,240 @@ +package roboy.dialog.states.fairShowStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.Linguistics; +import roboy.linguistics.Triple; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; +import roboy.talk.PhraseCollection; +import roboy.talk.Verbalizer; +import roboy.util.RandomList; + +import java.util.List; + + +/** + * Simple question answering state + */ +public class DemoQuestionAnsweringState extends State { + + private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; + private final static String TRANSITION_CHECK_OBJECTS = "talkAboutObjects"; + private final static String TRANSITION_FINISHED = "finished"; + private final static int MAX_NUM_OF_QUESTIONS = 3; + + private final Logger LOGGER = LogManager.getLogger(); + + private State nextState = this; + private int questionsAnswered = 0; + private boolean askingSpecifyingQuestion = false; + private String answerAfterUnspecifiedQuestion = ""; + + public DemoQuestionAnsweringState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + @Override + public Output act() { + + if (questionsAnswered > 0) { + return Output.say(PhraseCollection.QUESTION_ANSWERING_REENTERING.getRandomElement()); + } + + return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + + } + + @Override + public Output react(Interpretation input){ + + if (askingSpecifyingQuestion) { + + askingSpecifyingQuestion = false; + return reactToSpecifyingAnswer(input); + + } else{ + + return reactToQuestion(input); + } + + } + + @Override + public State getNextState() { + + if(questionsAnswered > MAX_NUM_OF_QUESTIONS){ + + nextState = getTransition(TRANSITION_FINISHED); + } else { + + if (checkPersonListening()) { + + nextState = this; + if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state + nextState = this; + } else if (Math.random() < 0.3) { + nextState = getTransition(TRANSITION_CHECK_OBJECTS); + } + + } else { + questionsAnswered = 0; + nextState = getTransition((TRANSITION_LONELY_ROBOY)); + } + } + + return nextState; + } + + + /** + * React to answer of the specifying question asked previously. + * + * @param input something like "yes" or "no" + * @return answer to the answer to the original question if specifying question was answered with 'yes' + */ + private Output reactToSpecifyingAnswer(Interpretation input) { + + askingSpecifyingQuestion = false; + + // check if answer is yes + if (input.getSentence() != null && input.getSentence().contains("yes")) { + if (answerAfterUnspecifiedQuestion == null) { + // parser could parse the question but did't provide an answer + return Output.say("Not sure about the answer, " + + "but at least my amazing parser could understand you! ") + .setSegue(new Segue(Segue.SegueType.FLATTERY, 0.4)); + } else { + // tell the response previously cached in answerAfterUnspecifiedQuestion + return Output.say("In this case, " + PhraseCollection.QUESTION_ANSWERING_START.getRandomElement() + answerAfterUnspecifiedQuestion); + } + + } else { + // the answer is no. we don't ask more specifying questions + // use avoid answer segue + return Output.sayNothing().setSegue(new Segue(Segue.SegueType.AVOID_ANSWER, 1)); + } + } + + + private Output reactToQuestion(Interpretation input) { + + askingSpecifyingQuestion = false; + questionsAnswered++; + + Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); + if (parseOutcome == null) { + LOGGER.error("Invalid parser outcome!"); + return Output.say("Invalid parser outcome!"); + } + + if (parseOutcome == Linguistics.ParsingOutcome.UNDERSPECIFIED) { + + // ambiguous question, luckily the parser has prepared a followup question + // and maybe even an answer if we are lucky (we will check in reactToSpecifyingAnswer later) + + String question = input.getUnderspecifiedQuestion(); + answerAfterUnspecifiedQuestion = input.getAnswer(); // could be null, but that's fine for now + + askingSpecifyingQuestion = true; // next input should be a yes/no answer + return Output.say("Could you be more precise, please? " + question); + } + + if (parseOutcome == Linguistics.ParsingOutcome.SUCCESS) { + if (input.getAnswer() != null) { + // tell the answer, that was provided by the parser + return Output.say(PhraseCollection.QUESTION_ANSWERING_START.getRandomElement() + " " + input.getAnswer()); + + } else { + // check for triple + + + // parser could parse the question but has no answer + return useMemoryOrFallback(input); + } + } + + // from here we know that dummyParserResult.equals("FAILURE") + return useMemoryOrFallback(input); + } + + private Output useMemoryOrFallback(Interpretation input) { + try { + if (input.getSemTriples() != null) { + Output memoryAnswer = answerFromMemory(input.getSemTriples()); + if (memoryAnswer != null) return memoryAnswer; + } + } catch (Exception e) { + LOGGER.warn(e.getMessage()); + } + + return Output.useFallback(); + } + + + private Output answerFromMemory(List triples) { + + // try to use memory to answer + Roboy roboy = new Roboy(getMemory()); + + if (triples.size() == 0) { + return null; + } + + String answer = "I like " + inferMemoryAnswer(triples, roboy) + "humans. "; + return Output.say(answer); + } + + private String inferMemoryAnswer(List triples, Roboy roboy) { + String answer = ""; + for (Triple result : triples) { + + if (result.predicate != null) { + if (result.predicate.contains(Neo4jRelationship.HAS_HOBBY.type)) { + RandomList nodes = getMemNodesByIds(roboy.getRelationships(Neo4jRelationship.HAS_HOBBY)); + if (!nodes.isEmpty()) { + for (MemoryNodeModel node : nodes) { + answer += node.getProperties().get("name").toString() + " and "; + } + } + break; + + } else if (result.predicate.contains(Neo4jRelationship.FRIEND_OF.type)) { + answer += "my friends "; + RandomList nodes = getMemNodesByIds(roboy.getRelationships(Neo4jRelationship.FRIEND_OF)); + if (!nodes.isEmpty()) { + for (MemoryNodeModel node : nodes) { + answer += node.getProperties().get("name").toString() + " and "; + } + } + answer += " other "; + break; + } + } + } + return answer; + } + + @Override + public boolean isFallbackRequired() { + return true; + } + + private boolean checkPersonListening(){ + + try { + + return getContext().PERSON_DETECTION.getLastValue().getData(); + + } catch(NullPointerException e){ + LOGGER.info("Make sure person listening is publishing, receiving: " + e.getMessage()); + return false; + } + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java index 8fc0fb96..37c4f5a1 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/InfoTalkState.java @@ -6,10 +6,6 @@ import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.emotions.RoboyEmotion; -import roboy.memory.Neo4jMemory; -import roboy.memory.nodes.MemoryNodeModel; -import roboy.memory.nodes.Roboy; -import roboy.ros.RosMainNode; import roboy.talk.PhraseCollection; import roboy.util.RandomList; diff --git a/resources/personalityFiles/experimental/ShowmasterDemoPersonality.json b/resources/personalityFiles/experimental/ShowmasterDemoPersonality.json new file mode 100644 index 00000000..908f491a --- /dev/null +++ b/resources/personalityFiles/experimental/ShowmasterDemoPersonality.json @@ -0,0 +1,42 @@ +{ + "initialState": "DemoIdle", + "states": [ + { + "identifier": "DemoIdle", + "implementation": "roboy.dialog.states.fairShowStates.DemoIdleState", + "transitions": { + "personDetected": "DemoQuestionAnsweringState" + }, + "parameters": { + "showTimeinMins": "5" + } + }, + { + "identifier": "DemoQuestionAnsweringState", + "implementation": "roboy.dialog.states.fairShowStates.DemoQuestionAnsweringState", + "transitions": { + "lonelyRoboy": "DemoIdle", + "talkAboutObjects": "ObjectDetectionState", + "finished": "Farewell" + }, + "fallback": "WildTalk" + }, + { + "identifier": "ObjectDetectionState", + "implementation": "roboy.dialog.states.fairShowStates.ObjectDetectionState", + "transitions":{ + "finished": "DemoQuestionAnsweringState" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + }, + { + "identifier": "Farewell", + "implementation": "roboy.dialog.states.ordinaryStates.FarewellState", + "transitions": {} + } + ] +} \ No newline at end of file diff --git a/resources/personalityFiles/experimental/monolog.json b/resources/personalityFiles/experimental/monolog.json deleted file mode 100644 index ed3f84e9..00000000 --- a/resources/personalityFiles/experimental/monolog.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "initialState": "Idle", - "states": [ - { - "identifier": "Idle", - "implementation": "roboy.dialog.states.fairShowStates.IdleState", - "transitions": { - "timeIsUp": "ActiveIntro" - } - }, - { - "identifier": "ActiveIntro", - "implementation": "roboy.dialog.states.fairShowStates.ActiveIntroState", - "transitions": { - "lonelyRoboy": "Idle", - "peopleAround": "InfoTalk" - } - }, - { - "identifier": "InfoTalk", - "implementation": "roboy.dialog.states.fairShowStates.InfoTalkState", - "transitions": { - "lonelyRoboy": "Idle" - } - } - ] -} \ No newline at end of file diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 86431686..2212bda7 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -6133,3 +6133,35 @@ {"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} {"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} {"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.315447027617413} ","formula":"resource:American_Recovery_and_Reinvestment_Act_of_2009","lexeme":"american recovery and reinvestment act of 2009","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.31076611015759087} ","formula":"resource:Presidency_of_Barack_Obama","lexeme":"presidency of barack obama","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.021463414634146343} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.015609756097560976} ","formula":"(rdf:type dbpedia:President)","lexeme":"president","type":"ClassNoun"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.015609756097560976} ","formula":"dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.45063192385707596} ","formula":"resource:Barack_Obama","lexeme":"barack obama","type":"NamedEntity"} +{"features":" {score:0.3089717584646591} ","formula":"resource:Patient_Protection_and_Affordable_Care_Act","lexeme":"patient protection and affordable care act","type":"NamedEntity"} +{"features":" {score:0.31418317990326106} ","formula":"resource:Sean_Combs","lexeme":"sean combs","type":"NamedEntity"} +{"features":" {score:0.010731707317073172} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.015609756097560976} ","formula":"!dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} From eef21667344243078bb77135592d72002eb4560c Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Fri, 17 Aug 2018 13:11:37 +0200 Subject: [PATCH 055/147] disabled objects from demo --- .../states/fairShowStates/DemoIdleState.java | 8 ++++++++ .../DemoQuestionAnsweringState.java | 4 +--- .../ShowmasterDemoPersonality.json | 8 -------- resources_nlu/error_test/newLexicon.txt | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoIdleState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoIdleState.java index 1cb7fb3f..0207adf3 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoIdleState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoIdleState.java @@ -5,6 +5,7 @@ import roboy.dialog.states.definitions.MonologState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; +import roboy.emotions.RoboyEmotion; import roboy.talk.PhraseCollection; import roboy.talk.Verbalizer; @@ -52,6 +53,13 @@ public Output act() { nextState = getTransition(TRANSITION_PERSON_DETECTED); + try{ + getRosMainNode().ShowEmotion(RoboyEmotion.HAPPY); + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e){ + LOGGER.error(e.getMessage()); + } + return Output.say(Verbalizer.greetings.getRandomElement() + " " + Verbalizer.roboyIntro.getRandomElement() + PhraseCollection.ROBOY_PHRASES.getRandomElement()); } diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java index 38f67b38..26346e9e 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java @@ -24,7 +24,6 @@ public class DemoQuestionAnsweringState extends State { private final static String TRANSITION_LONELY_ROBOY = "lonelyRoboy"; - private final static String TRANSITION_CHECK_OBJECTS = "talkAboutObjects"; private final static String TRANSITION_FINISHED = "finished"; private final static int MAX_NUM_OF_QUESTIONS = 3; @@ -78,8 +77,6 @@ public State getNextState() { nextState = this; if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state nextState = this; - } else if (Math.random() < 0.3) { - nextState = getTransition(TRANSITION_CHECK_OBJECTS); } } else { @@ -237,4 +234,5 @@ private boolean checkPersonListening(){ } } + } diff --git a/resources/personalityFiles/experimental/ShowmasterDemoPersonality.json b/resources/personalityFiles/experimental/ShowmasterDemoPersonality.json index 908f491a..783d355c 100644 --- a/resources/personalityFiles/experimental/ShowmasterDemoPersonality.json +++ b/resources/personalityFiles/experimental/ShowmasterDemoPersonality.json @@ -16,18 +16,10 @@ "implementation": "roboy.dialog.states.fairShowStates.DemoQuestionAnsweringState", "transitions": { "lonelyRoboy": "DemoIdle", - "talkAboutObjects": "ObjectDetectionState", "finished": "Farewell" }, "fallback": "WildTalk" }, - { - "identifier": "ObjectDetectionState", - "implementation": "roboy.dialog.states.fairShowStates.ObjectDetectionState", - "transitions":{ - "finished": "DemoQuestionAnsweringState" - } - }, { "identifier": "WildTalk", "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 2212bda7..7fabe259 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -6165,3 +6165,21 @@ {"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} {"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} {"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.03828920185565949} ","formula":"property:woman","lexeme":"woman","type":"ObjProp"} +{"features":" {score:0.07457736134529114} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.055132212042808534} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.683304347826087} ","formula":"resource:Angela_Merkel","lexeme":"angela merkel","type":"NamedEntity"} +{"features":" {score:0.022632212042808533} ","formula":"property:politicalLeader","lexeme":"political leader","type":"ObjProp"} +{"features":" {score:0.03828920185565949} ","formula":"property:woman","lexeme":"woman","type":"DataProp"} +{"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"ObjProp"} +{"features":" {score:0.022632212042808533} ","formula":"!dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} +{"features":" {score:0.022632212042808533} ","formula":"property:politicalLeader","lexeme":"political leader","type":"DataProp"} +{"features":" {score:0.055132212042808534} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.022632212042808533} ","formula":"dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} +{"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"ObjProp"} +{"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"DataProp"} From b25e38343538fc29ae2db79795f179ffb399a492 Mon Sep 17 00:00:00 2001 From: mireu Date: Fri, 17 Aug 2018 13:28:05 +0200 Subject: [PATCH 056/147] Hotfix for multi-dbpedia situations producing empty answers --- .../linguistics/sentenceanalysis/SemanticParserAnalyzer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java index 69bd48f0..49b0432f 100644 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java @@ -118,7 +118,7 @@ public Interpretation analyze(Interpretation interpretation) return interpretation; } - private void executeSemanticAnalysis(Interpretation result, Example ex) + private synchronized void executeSemanticAnalysis(Interpretation result, Example ex) { builder.parser.parse(builder.params, ex, false, builder.error_retrieval); ex.logWithoutContext(); From 9e7f8e1b1a4c66f3b809cd9d4cd341f23d4860cb Mon Sep 17 00:00:00 2001 From: ninalovegood Date: Fri, 17 Aug 2018 13:37:00 +0200 Subject: [PATCH 057/147] new grammar in config properties --- .../DemoQuestionAnsweringState.java | 15 +-- parser.properties | 2 +- resources_nlu/error_test/newLexicon.txt | 122 ++++++++++++++++++ 3 files changed, 127 insertions(+), 12 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java index 26346e9e..3a27dd07 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/DemoQuestionAnsweringState.java @@ -72,17 +72,11 @@ public State getNextState() { nextState = getTransition(TRANSITION_FINISHED); } else { - if (checkPersonListening()) { + nextState = this; + //if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state - nextState = this; - if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state - nextState = this; - } - - } else { - questionsAnswered = 0; - nextState = getTransition((TRANSITION_LONELY_ROBOY)); - } + // nextState = this; + //} } return nextState; @@ -173,7 +167,6 @@ private Output useMemoryOrFallback(Interpretation input) { return Output.useFallback(); } - private Output answerFromMemory(List triples) { // try to use memory to answer diff --git a/parser.properties b/parser.properties index b0f71dcd..5acee5bd 100644 --- a/parser.properties +++ b/parser.properties @@ -5,7 +5,7 @@ PROFILE: DEBUG # roboy-demo.grammar # roboy-webq.grammar # etc -GRAMMAR_FILE: "resources_nlu/roboy-final.grammar" +GRAMMAR_FILE: "resources_nlu/roboy-webq.grammar" # Lexicon file path. Alternatives: # roboy-demo.lexicon diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 7fabe259..2fbb35c0 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -6183,3 +6183,125 @@ {"features":" {score:0.022632212042808533} ","formula":"dbpedia:politicalLeader","lexeme":"political leader","type":"ObjectProp"} {"features":" {score:0.022632212042808533} ","formula":"!property:politicalLeader","lexeme":"political leader","type":"ObjProp"} {"features":" {score:0.03828920185565949} ","formula":"!property:woman","lexeme":"woman","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.315447027617413} ","formula":"resource:American_Recovery_and_Reinvestment_Act_of_2009","lexeme":"american recovery and reinvestment act of 2009","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.31076611015759087} ","formula":"resource:Presidency_of_Barack_Obama","lexeme":"presidency of barack obama","type":"NamedEntity"} +{"features":" {score:0.04487804878048781} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.021463414634146343} ","formula":"!dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.015609756097560976} ","formula":"(rdf:type dbpedia:President)","lexeme":"president","type":"ClassNoun"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"ObjProp"} +{"features":" {score:0.015609756097560976} ","formula":"dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.013658536585365855} ","formula":"!property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.04487804878048781} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.011707317073170733} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.45063192385707596} ","formula":"resource:Barack_Obama","lexeme":"barack obama","type":"NamedEntity"} +{"features":" {score:0.3089717584646591} ","formula":"resource:Patient_Protection_and_Affordable_Care_Act","lexeme":"patient protection and affordable care act","type":"NamedEntity"} +{"features":" {score:0.31418317990326106} ","formula":"resource:Sean_Combs","lexeme":"sean combs","type":"NamedEntity"} +{"features":" {score:0.010731707317073172} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.015609756097560976} ","formula":"!dbpedia:president","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.04487804878048781} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.021463414634146343} ","formula":"dbpedia:leader","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.021463414634146343} ","formula":"!property:leader","lexeme":"leader","type":"DataProp"} +{"features":" {score:0.011707317073170733} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.03609756097560975} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.013658536585365855} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.042009095673847544} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.8907573812580232} ","formula":"resource:Donald_Trump","lexeme":"donald trump","type":"NamedEntity"} +{"features":" {score:0.0861954571238255} ","formula":"property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.042009095673847544} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.545266447683966} ","formula":"resource:Trump_Model_Management","lexeme":"trump model management","type":"NamedEntity"} +{"features":" {score:0.0861954571238255} ","formula":"!property:candidate","lexeme":"candidate","type":"DataProp"} +{"features":" {score:0.027895863596415774} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.042009095673847544} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.027895863596415774} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.027895863596415774} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.042009095673847544} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.0861954571238255} ","formula":"property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.042009095673847544} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.042009095673847544} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.027895863596415774} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.7012836970474968} ","formula":"resource:Donald_J._Trump_State_Park","lexeme":"donald j. trump state park","type":"NamedEntity"} +{"features":" {score:0.700770218228498} ","formula":"\u003chttp://dbpedia.org/resource/Donald_Trump_(song)\u003e","lexeme":"donald trump song","type":"NamedEntity"} +{"features":" {score:0.5462934053219635} ","formula":"\u003chttp://dbpedia.org/resource/Donald_Trump,_Jr.\u003e","lexeme":"donald trump, jr.","type":"NamedEntity"} +{"features":" {score:0.042009095673847544} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.06954035692232868} ","formula":"(rdf:type dbpedia:Politician)","lexeme":"politician","type":"ClassNoun"} +{"features":" {score:0.027895863596415774} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.04269494056017155} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.0861954571238255} ","formula":"!property:candidate","lexeme":"candidate","type":"ObjProp"} +{"features":" {score:0.02754881125994218} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.5755008526150316} ","formula":"resource:United_States","lexeme":"united states","type":"NamedEntity"} +{"features":" {score:0.02754881125994218} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.08751242573062579} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.07595872349463977} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.03030440770662748} ","formula":"(rdf:type dbpedia:Area)","lexeme":"area","type":"ClassNoun"} +{"features":" {score:0.07595872349463977} ","formula":"!dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.03030440770662748} ","formula":"property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.1526816528538863} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.0370556704996106} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.02754881125994218} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.15117955282330514} ","formula":"(rdf:type dbpedia:Community)","lexeme":"community","type":"ClassNoun"} +{"features":" {score:0.07595872349463977} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.03030440770662748} ","formula":"!property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.38557999580675983} ","formula":"resource:Las_Vegas_Valley","lexeme":"las vegas valley","type":"NamedEntity"} +{"features":" {score:0.07957891535682556} ","formula":"property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.5303599433230969} ","formula":"resource:USA_Today","lexeme":"usa today","type":"NamedEntity"} +{"features":" {score:0.012150918220480283} ","formula":"property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.07595872349463977} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.0370556704996106} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.012150918220480283} ","formula":"!property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.08751242573062579} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.08751242573062579} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.0370556704996106} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.4179297464449643} ","formula":"\u003chttp://dbpedia.org/resource/Georgia_(U.S._state)\u003e","lexeme":"georgia u.s. state","type":"NamedEntity"} +{"features":" {score:0.07957891535682556} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.08751242573062579} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.02754881125994218} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.0370556704996106} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.0370556704996106} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.08751242573062579} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.07595872349463977} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.07957891535682556} ","formula":"!property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.012150918220480283} ","formula":"property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.03030440770662748} ","formula":"property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.08751242573062579} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.07595872349463977} ","formula":"dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.012150918220480283} ","formula":"!property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.160990172624588} ","formula":"(rdf:type dbpedia:Cave)","lexeme":"cave","type":"ClassNoun"} +{"features":" {score:0.07957891535682556} ","formula":"property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.4062865242661592} ","formula":"resource:United_States_Army","lexeme":"united states army","type":"NamedEntity"} +{"features":" {score:0.03030440770662748} ","formula":"!property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.3381166879130506} ","formula":"\u003chttp://dbpedia.org/resource/Oblivion_(2013_film)\u003e","lexeme":"oblivion 2013 film","type":"NamedEntity"} +{"features":" {score:0.054397506351323476} ","formula":"property:star","lexeme":"star","type":"DataProp"} +{"features":" {score:0.7009578544061303} ","formula":"resource:Tom_Cruise_Purple","lexeme":"tom cruise purple","type":"NamedEntity"} +{"features":" {score:0.005154639175257732} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.7011494252873564} ","formula":"resource:Being_Tom_Cruise","lexeme":"being tom cruise","type":"NamedEntity"} +{"features":" {score:0.054397506351323476} ","formula":"!property:star","lexeme":"star","type":"ObjProp"} +{"features":" {score:0.054397506351323476} ","formula":"!property:star","lexeme":"star","type":"DataProp"} +{"features":" {score:0.052604761197394934} ","formula":"(rdf:type dbpedia:MusicalArtist)","lexeme":"musical artist","type":"ClassNoun"} +{"features":" {score:0.896551724137931} ","formula":"resource:Tom_Cruise","lexeme":"tom cruise","type":"NamedEntity"} +{"features":" {score:0.09603880213707994} ","formula":"!property:actor","lexeme":"actor","type":"ObjProp"} +{"features":" {score:0.052604761197394934} ","formula":"!dbpedia:musicalArtist","lexeme":"musical artist","type":"ObjectProp"} +{"features":" {score:0.054397506351323476} ","formula":"(rdf:type dbpedia:Star)","lexeme":"star","type":"ClassNoun"} +{"features":" {score:0.052604761197394934} ","formula":"dbpedia:musicalArtist","lexeme":"musical artist","type":"ObjectProp"} +{"features":" {score:0.005154639175257732} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.09603880213707994} ","formula":"!property:actor","lexeme":"actor","type":"DataProp"} +{"features":" {score:0.09603880213707994} ","formula":"property:actor","lexeme":"actor","type":"DataProp"} +{"features":" {score:0.005154639175257732} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.005154639175257732} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.054397506351323476} ","formula":"property:star","lexeme":"star","type":"ObjProp"} +{"features":" {score:0.09603880213707994} ","formula":"(rdf:type dbpedia:Actor)","lexeme":"actor","type":"ClassNoun"} +{"features":" {score:0.0867470011652745} ","formula":"(rdf:type dbpedia:Celebrity)","lexeme":"celebrity","type":"ClassNoun"} +{"features":" {score:0.09603880213707994} ","formula":"property:actor","lexeme":"actor","type":"ObjProp"} +{"features":" {score:0.005154639175257732} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.005154639175257732} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.005154639175257732} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} From 2c126c5e5b6477589269180aad00e705d2f82a89 Mon Sep 17 00:00:00 2001 From: missxa Date: Sun, 19 Aug 2018 03:37:32 +0200 Subject: [PATCH 058/147] wildtalk using proc-bridge --- .gitignore | 1 + config.properties | 5 ++- dialog/pom.xml | 6 +++ .../devoStates/QuestionRoboyQAState.java | 2 +- .../QuestionAnsweringState.java | 12 ++---- .../states/ordinaryStates/WildTalkState.java | 40 ++++++++++--------- .../main/java/roboy/util/ConfigManager.java | 7 ++++ .../src/main/java/roboy/util/api/apiKeys.yml | 3 -- .../test/WildPersonality.json | 21 ++++++++++ 9 files changed, 65 insertions(+), 32 deletions(-) delete mode 100644 dialog/src/main/java/roboy/util/api/apiKeys.yml create mode 100644 resources/personalityFiles/test/WildPersonality.json diff --git a/.gitignore b/.gitignore index 65fbe33f..3e3e3899 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,4 @@ nlu/parser/target/ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml dialog/src/main/java/roboy/util/api/apiKeys\.yml +dialog/src/main/java/roboy/util/api/apiKeys.yml diff --git a/config.properties b/config.properties index 1730e367..934e60b7 100755 --- a/config.properties +++ b/config.properties @@ -54,7 +54,7 @@ PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/test/WildPersonality.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" @@ -64,6 +64,9 @@ ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/sc TELEGRAM_API_TOKENS_FILE: "" +PARLAI_PORT: 8877 +PARLAI_HOST: "127.0.0.1" + # Logging Levels # Each Logging Module has different levels. End users should use warn. Developers should use either info or debug/fine. diff --git a/dialog/pom.xml b/dialog/pom.xml index 06ccf029..18b5dbae 100755 --- a/dialog/pom.xml +++ b/dialog/pom.xml @@ -429,6 +429,12 @@ telegrambots 3.6.1 + + + co.gongzh.procbridge + procbridge + 1.0.2 + diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index ace852f7..dca3f041 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -227,7 +227,7 @@ private String inferPasAnswer(Map pas, Roboy roboy) { if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { - extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : + extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy); } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java index 501d72fb..239f7416 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java @@ -76,18 +76,12 @@ public QuestionAnsweringState(String stateIdentifier, StateParameters params) { @Override public Output act() { - if(Math.random() > THRESHOLD_BORED && questionsAnswered > 2){ + if(Math.random() > THRESHOLD_BORED && questionsAnswered > 5){ roboySuggestedGame = true; + questionsAnswered = 0; return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); } - if (askingSpecifyingQuestion) { - return Output.sayNothing(); - } - - if (questionsAnswered > 0) { - return Output.say(reenteringPhrases.getRandomElement()); - } - return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + return Output.sayNothing(); } @Override diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java index 5a10915b..0cdef55c 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java @@ -1,5 +1,10 @@ package roboy.dialog.states.ordinaryStates; +import co.gongzh.procbridge.ProcBridge; +import co.gongzh.procbridge.ProcBridgeException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.json.JSONObject; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.Linguistics; @@ -10,8 +15,7 @@ import java.util.Set; -import static roboy.util.ConfigManager.ROS_ACTIVE_PKGS; -import static roboy.util.ConfigManager.ROS_ENABLED; +import static roboy.util.ConfigManager.*; /** * This fallback state will query the generative model over ROS to create a reply for any situation. @@ -27,6 +31,9 @@ */ public class WildTalkState extends State { + private final Logger LOGGER = LogManager.getLogger(); + private ProcBridge pb; + private RandomList rosFailurePhrases = new RandomList<>( "Hey, who disconnected me from my beloved ros node? I need it! ", "Oh well, my generative model is not connected. That makes me sad. ", @@ -36,6 +43,8 @@ public class WildTalkState extends State { public WildTalkState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); + pb = new ProcBridge(PARLAI_HOST, PARLAI_PORT, 2000); + } @Override @@ -47,24 +56,19 @@ public Output act() { public Output react(Interpretation input) { String sentence = input.getSentence(); - RosMainNode rmn = getRosMainNode(); - if (rmn == null) { - if(ROS_ENABLED && ROS_ACTIVE_PKGS.contains("roboy_gnlp")){ - return Output.say(rosFailurePhrases.getRandomElement()) - .setSegue(new Segue(Segue.SegueType.DISTRACT, 0.8)); - } - else{ - return Output.say("I am out of words.").setSegue(new Segue(Segue.SegueType.DISTRACT, 0.8)); - } - } - String reaction = rmn.GenerateAnswer(sentence); - - if (reaction == null) { - return Output.say("I am out of words.").setSegue(new Segue(Segue.SegueType.DISTRACT, 0.8)); - } else { - return Output.say(reaction); + JSONObject resp; + try { + resp = pb.request("parlai", "{text_input: " + sentence + "}"); + LOGGER.info(resp); + return Output.say(resp.getString("result")); + } + catch (Exception e) + { + LOGGER.warn(e.getMessage()); } + return Output.sayNothing(); + } @Override diff --git a/dialog/src/main/java/roboy/util/ConfigManager.java b/dialog/src/main/java/roboy/util/ConfigManager.java index 5e1c8e3e..fe2bd0c0 100644 --- a/dialog/src/main/java/roboy/util/ConfigManager.java +++ b/dialog/src/main/java/roboy/util/ConfigManager.java @@ -49,6 +49,9 @@ public class ConfigManager { public static String DIALOG_LOG_MODE = "INFO"; public static String PARSER_LOG_MODE = "ALL"; + public static String PARLAI_HOST = "127.0.0.1"; + public static int PARLAI_PORT = 8877; + static { // this block is called once at and will initialize config // alternative: create a singleton for this class @@ -120,10 +123,14 @@ private static void initializeConfig() { TELEGRAM_API_TOKENS_FILE = yamlConfig.getString("TELEGRAM_API_TOKENS_FILE"); + PARLAI_HOST = yamlConfig.getString("PARLAI_HOST"); + PARLAI_PORT = yamlConfig.getInt("PARLAI_PORT"); + MEMORY_LOG_MODE = (yamlConfig.getString("MEMORY_LOG_MODE")); PARSER_LOG_MODE = (yamlConfig.getString("PARSER_LOG_MODE")); DIALOG_LOG_MODE = (yamlConfig.getString("DIALOG_LOG_MODE")); + } catch(ConfigurationException | FileNotFoundException e) { LOGGER.error("Exception while reading YAML configurations from "+yamlConfigFile); LOGGER.error(e.getMessage()); diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/dialog/src/main/java/roboy/util/api/apiKeys.yml deleted file mode 100644 index 22207938..00000000 --- a/dialog/src/main/java/roboy/util/api/apiKeys.yml +++ /dev/null @@ -1,3 +0,0 @@ -moviekey: xxxxxxxxxxxxxxxxxxxxxxxx -translatekey: xxxxxxxxxxxxxxxxxxxxxxxx -weatherkey: xxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file diff --git a/resources/personalityFiles/test/WildPersonality.json b/resources/personalityFiles/test/WildPersonality.json new file mode 100644 index 00000000..58492ce3 --- /dev/null +++ b/resources/personalityFiles/test/WildPersonality.json @@ -0,0 +1,21 @@ +{ + "initialState": "QuestionAnswering", + "states": [ + { + "identifier": "QuestionAnswering", + "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "fallback": "WildTalk", + "transitions": { + "finishedQuestionAnswering": "QuestionAnswering", + "loopToNewPerson": "QuestionAnswering", + "loopToKnownPerson": "QuestionAnswering", + "switchToGaming": "QuestionAnswering" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + } + ] +} \ No newline at end of file From 964b4af42d8e5d84dc5f3f6f28fd4b5c76252173 Mon Sep 17 00:00:00 2001 From: Jayce Date: Mon, 13 Aug 2018 20:50:13 +0200 Subject: [PATCH 059/147] Joseph's Highly Pedantic Changes --- .../linguistics/sentenceanalysis/SemanticParserAnalyzer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java index 49b0432f..0021b885 100644 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java @@ -142,7 +142,7 @@ private synchronized void executeSemanticAnalysis(Interpretation result, Example String answer = val.pureString(); //Handle URL's - if (answer.contains(" at the end of URL } From d360651b2602fa5202d48e2904fe1c2e3fb30ce6 Mon Sep 17 00:00:00 2001 From: Jayce Date: Mon, 13 Aug 2018 21:51:34 +0200 Subject: [PATCH 060/147] =?UTF-8?q?[Docs]=20TBL:=20-=20to=20=E2=80=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/developer_manual/2_Logging_Policy.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developer_manual/2_Logging_Policy.rst b/docs/developer_manual/2_Logging_Policy.rst index 363f6894..99644eb8 100644 --- a/docs/developer_manual/2_Logging_Policy.rst +++ b/docs/developer_manual/2_Logging_Policy.rst @@ -85,10 +85,10 @@ Developers should use a standardized policy when it comes to defining the loggin Level Method Level Method Level Method ============ ============ ============ ============ ============ ============ =================================== FATAL lg.fatal() SEVERE lg.severe() FATAL lg.fail() Problem requiring module to shutdown immidiately -ERROR lg.error() - Use WARNING ERROR lg.error() Problem that requires recommends a shutdown, but is not forcibly required +ERROR lg.error() — Use WARNING ERROR lg.error() Problem that requires recommends a shutdown, but is not forcibly required WARN lg.warn() WARNING lg.warning() WARN lg.warning() Unexpected behaviour that should be corrected, but is handlable for the program INFO lg.info() INFO lg.info() INFO lg.log() Information regarding the usage of module (e.g. Config Choices, Major Modules Loaded) -- - CONFIG lg.config() - - Avoid using this level +— — CONFIG lg.config() — — Avoid using this level DEBUG lg.debug() FINE lg.fine() DEBUG lg.dbg() Information not directly relevant to execution of program, unless debugging. This includes tests and parsing details. ============ ============ ============ ============ ============ ============ =================================== From b382606e331329636075a16da3aa080af9a1546d Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 13:06:24 +0200 Subject: [PATCH 061/147] [Logging Policy] Conforming more Stuff to Standards --- .../main/java/roboy/dialog/Conversation.java | 2 +- .../java/edu/stanford/nlp/sempre/Example.java | 70 ++++++++++--------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/Conversation.java b/dialog/src/main/java/roboy/dialog/Conversation.java index 19957dc8..1fe3bc69 100644 --- a/dialog/src/main/java/roboy/dialog/Conversation.java +++ b/dialog/src/main/java/roboy/dialog/Conversation.java @@ -122,7 +122,7 @@ public void run(){ e.printStackTrace(); } } - logger.info(interpretation.toString()); + logger.debug(interpretation.toString()); // answer try { diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java index 2ee5e862..e9181416 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java @@ -7,9 +7,11 @@ import com.google.common.base.Joiner; import com.google.common.collect.Sets; import edu.stanford.nlp.sempre.roboy.utils.logging.EvaluationToggle; +import edu.stanford.nlp.sempre.roboy.utils.logging.ParserLogController; import fig.basic.Evaluation; import fig.basic.LispTree; import edu.stanford.nlp.sempre.roboy.utils.logging.LogInfoToggle; +import org.apache.logging.log4j.Level; import java.io.FileInputStream; import java.io.InputStream; @@ -272,41 +274,45 @@ public void preprocess() { } public void log() { - LogInfoToggle.begin_track("Example: %s", utterance); - LogInfoToggle.logs("Tokens: %s", getTokens()); - LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); - LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); - LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); - LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); - if (context != null) - LogInfoToggle.logs("context: %s", context); - if (targetFormula != null) - LogInfoToggle.logs("targetFormula: %s", targetFormula); - if (targetValue != null) - LogInfoToggle.logs("targetValue: %s", targetValue); - LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); - LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); - LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); - LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); - LogInfoToggle.end_track(); + if(ParserLogController.getLevel().isLessSpecificThan(Level.DEBUG)) { + LogInfoToggle.begin_track("Example: %s", utterance); + LogInfoToggle.logs("Tokens: %s", getTokens()); + LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); + LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); + LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); + LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); + if (context != null) + LogInfoToggle.logs("context: %s", context); + if (targetFormula != null) + LogInfoToggle.logs("targetFormula: %s", targetFormula); + if (targetValue != null) + LogInfoToggle.logs("targetValue: %s", targetValue); + LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); + LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); + LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); + LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); + LogInfoToggle.end_track(); + } } public void logWithoutContext() { - LogInfoToggle.begin_track("Example: %s", utterance); - LogInfoToggle.logs("Tokens: %s", getTokens()); - LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); - LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); - LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); - LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); - if (targetFormula != null) - LogInfoToggle.logs("targetFormula: %s", targetFormula); - if (targetValue != null) - LogInfoToggle.logs("targetValue: %s", targetValue); - LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); - LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); - LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); - LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); - LogInfoToggle.end_track(); + if(ParserLogController.getLevel().isLessSpecificThan(Level.DEBUG)) { + LogInfoToggle.begin_track("Example: %s", utterance); + LogInfoToggle.logs("Tokens: %s", getTokens()); + LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); + LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); + LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); + LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); + if (targetFormula != null) + LogInfoToggle.logs("targetFormula: %s", targetFormula); + if (targetValue != null) + LogInfoToggle.logs("targetValue: %s", targetValue); + LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); + LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); + LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); + LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); + LogInfoToggle.end_track(); + } } public List getCorrectDerivations() { From fcacebe9ec52be4536539f9bfb910fbf2ab01e9c Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 14:11:16 +0200 Subject: [PATCH 062/147] [Sentence Type] DictionaryBasedSentenceTypeDetector Preparation If STMT --> Use DBSTD otherwise SPA has succeeded --- .../DictionaryBasedSentenceTypeDetector.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java index dd3346da..2fc5ef4e 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java @@ -15,11 +15,19 @@ public class DictionaryBasedSentenceTypeDetector implements Analyzer{ public Interpretation analyze(Interpretation interpretation) { List tokens = interpretation.getTokens(); String[] posTags = interpretation.getPosTags(); - SentenceType sentenceType = determineSentenceType(tokens, posTags); - interpretation.setSentenceType(sentenceType); + + //Sentence Types shall be handled in Semantic Parser Analyzer. This is a fallback, in the event that SPA does not detect the sentence type + if(interpretation.getSentenceType().equals(SentenceType.STATEMENT)){ + SentenceType sentenceType = determineSentenceType(tokens, posTags); + interpretation.setSentenceType(sentenceType); + + } return interpretation; } + /** + * Fallback Sentence Type Detection, main Detector now in {@link SemanticParserAnalyzer} + */ private SentenceType determineSentenceType(List tokens, String[] posTags){ if (tokens != null && !tokens.isEmpty()) { String first = tokens.get(0).toLowerCase(); From b34afb339c4d4e0c36315024729a3ed5a7dc0cec Mon Sep 17 00:00:00 2001 From: Joseph Birkner Date: Tue, 14 Aug 2018 14:17:07 +0200 Subject: [PATCH 063/147] Fixed main() in FullNLPAnalyzer --- .../nlp/sempre/corenlp/FullNLPAnalyzer.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java index aaed284d..9271afeb 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java @@ -37,6 +37,7 @@ public class FullNLPAnalyzer extends InfoAnalyzer { public static class Options { @Option(gloss = "What CoreNLP annotators to run") public List annotators = Lists.newArrayList( + "tokenize", "tokenize", "ssplit", "truecase", @@ -80,6 +81,7 @@ public static void initModels() { Properties props = new Properties(); props.setProperty("annotators", Joiner.on(',').join(opts.annotators)); props.setProperty("coref.algorithm", "neural"); + //props.setProperty("openie.resolve_coref", "true"); props.setProperty("truecase.overwriteText", "true"); props.setProperty("ner.applyFineGrained", "false"); pipeline = new StanfordCoreNLP(props); @@ -216,7 +218,7 @@ public GeneralInfo getSent(LanguageInfo languageInfo, Annotation annotation) { // LogInfoToggle.logs("Keywords extracted: %s", genInfo.keywords.toString()); genInfo.sentiment_type = RNNCoreAnnotations.getPredictedClass(tree); genInfo.sentiment = sentence.get(SentimentCoreAnnotations.SentimentClass.class); -// LogInfoToggle.logs("Sentiment extracted: %s", genInfo.sentiment); + LogInfoToggle.logs("Sentiment extracted: %s", genInfo.sentiment); } return genInfo; } @@ -248,20 +250,23 @@ public List getKeywords(Tree tree){ // Test on example sentence. public static void main(String[] args) { - CoreNLPAnalyzer analyzer = new CoreNLPAnalyzer(); + FullNLPAnalyzer analyzer = new FullNLPAnalyzer(); while (true) { try { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Enter some text:"); String text = reader.readLine(); - LanguageInfo langInfo = analyzer.analyze(text); + CoreNLPInfo langInfo = analyzer.analyze(text); LogInfoToggle.begin_track("Analyzing \"%s\"", text); - LogInfoToggle.logs("tokens: %s", langInfo.tokens); - LogInfoToggle.logs("lemmaTokens: %s", langInfo.lemmaTokens); - LogInfoToggle.logs("posTags: %s", langInfo.posTags); - LogInfoToggle.logs("nerTags: %s", langInfo.nerTags); - LogInfoToggle.logs("nerValues: %s", langInfo.nerValues); - LogInfoToggle.logs("dependencyChildren: %s", langInfo.dependencyChildren); + LogInfoToggle.logs("tokens: %s", langInfo.lanInfo.tokens); + LogInfoToggle.logs("lemmaTokens: %s", langInfo.lanInfo.lemmaTokens); + LogInfoToggle.logs("posTags: %s", langInfo.lanInfo.posTags); + LogInfoToggle.logs("nerTags: %s", langInfo.lanInfo.nerTags); + LogInfoToggle.logs("nerValues: %s", langInfo.lanInfo.nerValues); + LogInfoToggle.logs("dependencyChildren: %s", langInfo.lanInfo.dependencyChildren); + LogInfoToggle.logs("keywords: %s", langInfo.senInfo.keywords); + LogInfoToggle.logs("sentiment: %s", langInfo.senInfo.sentiment); + LogInfoToggle.logs("relations: %s", langInfo.relInfo.relations); LogInfoToggle.end_track(); } catch (IOException e) { e.printStackTrace(); From ce306d92d9dea25a64f5ac14c2bdfa92ca52256c Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 20:58:06 +0200 Subject: [PATCH 064/147] Merge branch 'hack-jason-demo' into origin/de-nlu-upgrades --- .../stanford/nlp/sempre/roboy/api/Movie.java | 39 ++++++++++++++++ .../nlp/sempre/roboy/api/Translate.java | 41 +++++++++++++++++ .../nlp/sempre/roboy/api/Weather.java | 46 +++++++++++++++++++ .../stanford/nlp/sempre/roboy/api/apiKeys.yml | 3 ++ .../nlp/sempre/roboy/api/keyGetter.java | 22 +++++++++ 5 files changed, 151 insertions(+) create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java new file mode 100644 index 00000000..301583fc --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java @@ -0,0 +1,39 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Random; + +public class Movie{ + static String KEY = keyGetter.getKey("moviekey"); + static int randomInt = new Random().nextInt(20); + + + public static String getData(String... args) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) + .getAsJsonArray("results") + .get(randomInt).getAsJsonObject().get(args[0]); +// System.out.println(jsonObject); + return result.toString(); + } + + public static void main(String[] args)throws Exception{ + getData("title");getData("overview"); + } +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java new file mode 100644 index 00000000..8eb2afec --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java @@ -0,0 +1,41 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.github.jsonldjava.utils.Obj; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Translate { + static final String KEY = keyGetter.getKey("translatekey"); + + public static String getData(String... args) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(APIify(args[0], args[1])); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); +// System.out.println(jsonObject); + return result.toString(); + } + + private static String APIify(String text, String targetLang){ + String s = String.format("https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s", KEY, text.replace(" ", "%20"), targetLang); +// System.out.println(s); + return s; + } + + public static void main(String[] args) throws Exception{ + System.out.println(getData("cheese is the best vegetable", "de")); + } +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java new file mode 100644 index 00000000..9bfff6a2 --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java @@ -0,0 +1,46 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Weather { + final static String KEY = keyGetter.getKey("weatherkey"); + public static String getData(String... args) throws Exception{ + try { + return getHTML(args[0]); + }catch (Exception e) {return null;} + } + public static String getHTML(String country) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("http://api.openweathermap.org/data/2.5/weather?q=%s&APPID=%s", country, KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + JsonObject jsonObject = (((JsonObject) new JsonParser().parse(result.toString())).get("weather").getAsJsonArray()).get(0).getAsJsonObject(); +// System.out.println(jsonObject.get("main")); + return jsonObject.get("main").getAsString(); + } + + public static void main(String[] args) throws Exception + { + //Find Munich + System.out.println(getData("munich")); + } + + +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml new file mode 100644 index 00000000..1cef27aa --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml @@ -0,0 +1,3 @@ +moviekey: xxxxxxx +translatekey: xxxxxxx +weatherkey: xxxxxx \ No newline at end of file diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java new file mode 100644 index 00000000..0b42b252 --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java @@ -0,0 +1,22 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import org.apache.commons.configuration2.YAMLConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; + +import java.io.FileNotFoundException; +import java.io.FileReader; + +public class keyGetter { + static YAMLConfiguration yamlConfiguration = new YAMLConfiguration(); + static String getKey(String key){ + try { + yamlConfiguration.read(new FileReader("nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml")); + } catch (ConfigurationException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return yamlConfiguration.getString(key); + } + +} From 42a4583520db2dff2654ac3f7035ecd7a0fa0456 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 20:59:30 +0200 Subject: [PATCH 065/147] Ignore YML --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index d7d759b0..742d1b5f 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,5 @@ community-server/data-backup *.iml nlu/parser/target/ + +nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml From a90fc5bd8a196d6609fd929e078cfd30bc1dc289 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:34:15 +0200 Subject: [PATCH 066/147] Updated API Stuff --- .../stanford/nlp/sempre/roboy/api/Movie.java | 6 +- .../nlp/sempre/roboy/api/Translate.java | 108 +++++++++++++++++- .../nlp/sempre/roboy/api/Weather.java | 6 +- 3 files changed, 109 insertions(+), 11 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java index 301583fc..bb6dde97 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java @@ -13,8 +13,8 @@ public class Movie{ static String KEY = keyGetter.getKey("moviekey"); static int randomInt = new Random().nextInt(20); - - public static String getData(String... args) throws Exception { + //FIELD TITLE or OVERVIEW + public static String getData(String field) throws Exception { StringBuilder result = new StringBuilder(); URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); @@ -28,7 +28,7 @@ public static String getData(String... args) throws Exception { Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) .getAsJsonArray("results") - .get(randomInt).getAsJsonObject().get(args[0]); + .get(randomInt).getAsJsonObject().get(field); // System.out.println(jsonObject); return result.toString(); } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java index 8eb2afec..677b1d5d 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java @@ -12,9 +12,11 @@ public class Translate { static final String KEY = keyGetter.getKey("translatekey"); - public static String getData(String... args) throws Exception { + + //Language: Either Language code such as DE or language name. Text is the text to translate + public static String getData(String text, String language) throws Exception { StringBuilder result = new StringBuilder(); - URL url = new URL(APIify(args[0], args[1])); + URL url = new URL(APIify(text, handleLanguage(language))); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); @@ -26,7 +28,105 @@ public static String getData(String... args) throws Exception { Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); // System.out.println(jsonObject); - return result.toString(); + return jsonObject.toString(); + } + + private static String handleLanguage(String language) { + switch (language.toLowerCase()){ + case "azerbaijan": return "az"; + case "malayalam": return "ml"; + case "albanian": return "sq"; + case "maltese": return "mt"; + case "amharic": return "am"; + case "macedonian": return "mk"; + case "english": return "en"; + case "maori": return "mi"; + case "arabic": return "ar"; + case "marathi": return "mr"; + case "armenian": return "hy"; + case "mari": return "mhr"; + case "afrikaans": return "af"; + case "mongolian": return "mn"; + case "basque": return "eu"; + case "german": return "de"; + case "bashkir": return "ba"; + case "nepali": return "ne"; + case "belarusian": return "be"; + case "norwegian": return "no"; + case "bengali": return "bn"; + case "punjabi": return "pa"; + case "burmese": return "my"; + case "papiamento": return "pap"; + case "bulgarian": return "bg"; + case "persian": return "fa"; + case "bosnian": return "bs"; + case "polish": return "pl"; + case "welsh": return "cy"; + case "portuguese": return "pt"; + case "hungarian": return "hu"; + case "romanian": return "ro"; + case "vietnamese": return "vi"; + case "russian": return "ru"; + case "haitian": return "ht"; + case "cebuano": return "ceb"; + case "galician": return "gl"; + case "serbian": return "sr"; + case "dutch": return "nl"; + case "sinhala": return "si"; + case "slovakian": return "sk"; + case "greek": return "el"; + case "slovenian": return "sl"; + case "georgian": return "ka"; + case "swahili": return "sw"; + case "gujarati": return "gu"; + case "sundanese": return "su"; + case "danish": return "da"; + case "tajik": return "tg"; + case "hebrew": return "he"; + case "thai": return "th"; + case "yiddish": return "yi"; + case "tagalog": return "tl"; + case "indonesian": return "id"; + case "tamil": return "ta"; + case "irish": return "ga"; + case "tatar": return "tt"; + case "italian": return "it"; + case "telugu": return "te"; + case "icelandic": return "is"; + case "turkish": return "tr"; + case "spanish": return "es"; + case "udmurt": return "udm"; + case "kazakh": return "kk"; + case "uzbek": return "uz"; + case "kannada": return "kn"; + case "ukrainian": return "uk"; + case "catalan": return "ca"; + case "urdu": return "ur"; + case "kyrgyz": return "ky"; + case "finnish": return "fi"; + case "chinese": return "zh"; + case "french": return "fr"; + case "korean": return "ko"; + case "hindi": return "hi"; + case "xhosa": return "xh"; + case "croatian": return "hr"; + case "khmer": return "km"; + case "czech": return "cs"; + case "laotian": return "lo"; + case "swedish": return "sv"; + case "latin": return "la"; + case "scottish": return "gd"; + case "latvian": return "lv"; + case "estonian": return "et"; + case "lithuanian": return "lt"; + case "esperanto": return "eo"; + case "luxembourgish": return "lb"; + case "javanese": return "jv"; + case "malagasy": return "mg"; + case "japanese": return "ja"; + case "malay": return "ms"; + default: return language; + } } private static String APIify(String text, String targetLang){ @@ -36,6 +136,6 @@ private static String APIify(String text, String targetLang){ } public static void main(String[] args) throws Exception{ - System.out.println(getData("cheese is the best vegetable", "de")); + System.out.println(getData("cheese is the best vegetable", "german")); } } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java index 9bfff6a2..05dc9c73 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java @@ -14,10 +14,8 @@ public class Weather { final static String KEY = keyGetter.getKey("weatherkey"); - public static String getData(String... args) throws Exception{ - try { - return getHTML(args[0]); - }catch (Exception e) {return null;} + public static String getData(String country) throws Exception{ + return getHTML(country); } public static String getHTML(String country) throws Exception { StringBuilder result = new StringBuilder(); From 25aba2f8d6225789871e9748a0a3df3fb5e2c00f Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:44:55 +0200 Subject: [PATCH 067/147] Moving --- dialog/src/main/java/roboy/util/api/apiKeys.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 dialog/src/main/java/roboy/util/api/apiKeys.yml diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/dialog/src/main/java/roboy/util/api/apiKeys.yml new file mode 100644 index 00000000..081009cd --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/apiKeys.yml @@ -0,0 +1,3 @@ +moviekey: 3de762f2092e296c8d5caa9621e16435 +translatekey: trnsl.1.1.20180814T165759Z.db023858639750f6.92a688e9d77dec4f77c49527d5b50b38ab2d3382 +weatherkey: 743a546a11f8b6e2436667c2c4f49a60 \ No newline at end of file From 99ca23f32264e1c18002de44f0611b85cc742df2 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:45:35 +0200 Subject: [PATCH 068/147] gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 742d1b5f..65fbe33f 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,5 @@ community-server/data-backup nlu/parser/target/ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml + +dialog/src/main/java/roboy/util/api/apiKeys\.yml From acde63f6e4e6670eaed6d73f661cc866a57935f4 Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Wed, 15 Aug 2018 02:58:10 +0200 Subject: [PATCH 069/147] Like, hypersexy space alien shit, or something --- config.properties | 18 +- config.properties.orig | 40 +- .../roboy/dialog/ConversationManager.java | 5 + .../devoStates/QuestionRoboyQAState.java | 356 ++++++++++++++++++ .../states/expoStates/RoboyQAState.java | 1 - .../QuestionAnsweringState.java | 1 - .../main/java/roboy/linguistics/Triple.java | 13 +- .../sentenceanalysis/Interpretation.java | 49 +++ .../sentenceanalysis/Postprocessor.java | 14 + .../personalityFiles/DevoPersonality.json | 93 +++++ 10 files changed, 565 insertions(+), 25 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java create mode 100644 dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java create mode 100644 resources/personalityFiles/DevoPersonality.json diff --git a/config.properties b/config.properties index de1f7bbb..56c29b04 100755 --- a/config.properties +++ b/config.properties @@ -29,19 +29,19 @@ INPUT: cmdline #INPUT: cerevoice #INPUT: udp #INPUT: bing -INPUT: telegram +#INPUT: telegram # multiple outputs are allowed, defaults to cmdline OUTPUTS: -#- cmdline +- cmdline +# - telegram # - ibm -# - cmdline # - cerevoice # - freetts # - ibm # - emotions # - udp - - telegram +# - telegram UDP_IN_SOCKET: 55555 UDP_OUT_SOCKET: 55556 @@ -49,12 +49,12 @@ UDP_HOST_ADDRESS: 127.0.0.1 PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/ExpoPersonality.json" - -PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" -#PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" +# PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" +# PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" -# PERSONALITY_FILE: "resources/personalityFiles/uzupis.json" +# PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" @@ -62,6 +62,7 @@ IBM_TTS_PASS: "" CONTEXT_GUI_ENABLED: false ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/scripts/action_client.py" +TELEGRAM_API_TOKENS_FILE: "" # Logging Levels @@ -79,4 +80,3 @@ DIALOG_LOG_MODE: "DEBUG" # Parser/NLU: LogInfo # Supports all Log4J levels. See Documentation for more details PARSER_LOG_MODE: "DEBUG" -TELEGRAM_API_TOKENS_FILE: "/Users/Apple/botboy/tokens.json" \ No newline at end of file diff --git a/config.properties.orig b/config.properties.orig index 25f29c47..1361cfd1 100755 --- a/config.properties.orig +++ b/config.properties.orig @@ -25,7 +25,7 @@ DEMO_MODE: false INFINITE_REPETITION: true # only single input is allowed, defaults to cmdline -#INPUT: cmdline +INPUT: cmdline #INPUT: cerevoice #INPUT: udp #INPUT: bing @@ -33,8 +33,9 @@ INPUT: telegram # multiple outputs are allowed, defaults to cmdline OUTPUTS: -# - cmdline +#- cmdline # - ibm +# - cmdline # - cerevoice # - freetts # - ibm @@ -48,12 +49,21 @@ UDP_HOST_ADDRESS: 127.0.0.1 PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/ExpoPersonality.json" +<<<<<<< 99ca23f32264e1c18002de44f0611b85cc742df2 -#PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" +PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" +#PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/uzupis.json" +======= +# PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" +# PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" +# PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" +# PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" +# PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" +>>>>>>> Like, hypersexy space alien shit, or something IBM_TTS_USER: "" IBM_TTS_PASS: "" @@ -68,18 +78,26 @@ ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/sc # Memory: java.util.logging # https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html -MEMORY_LOG_MODE: "WARNING" +<<<<<<< 99ca23f32264e1c18002de44f0611b85cc742df2 +MEMORY_LOG_MODE: "DEBUG" +======= +MEMORY_LOG_MODE: "DEBUG" +>>>>>>> Like, hypersexy space alien shit, or something # Dialog: LOG4J 2 # https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html # https://logging.apache.org/log4j/2.x/manual/customloglevels.html -DIALOG_LOG_MODE: "WARN" +<<<<<<< 99ca23f32264e1c18002de44f0611b85cc742df2 +DIALOG_LOG_MODE: "DEBUG" # Parser/NLU: LogInfo # Supports all Log4J levels. See Documentation for more details -<<<<<<< Updated upstream -PARSER_LOG_MODE: "WARN" -======= -PARSER_LOG_MODE: "INFO" +PARSER_LOG_MODE: "DEBUG" TELEGRAM_API_TOKENS_FILE: "/Users/Apple/botboy/tokens.json" ->>>>>>> Stashed changes +======= +DIALOG_LOG_MODE: "DEBUG" + +# Parser/NLU: LogInfo +# Supports all Log4J levels. See Documentation for more details +PARSER_LOG_MODE: "DEBUG" +>>>>>>> Like, hypersexy space alien shit, or something diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index fcc4d4e7..66388a04 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -84,7 +84,12 @@ public static void main(String[] args) throws IOException { analyzers.add(new EmotionAnalyzer()); +<<<<<<< 99ca23f32264e1c18002de44f0611b85cc742df2 //analyzers.add(new ProfanityAnalyzer()); +======= + analyzers.add(new ProfanityAnalyzer()); + analyzers.add(new Postprocessor()); +>>>>>>> Like, hypersexy space alien shit, or something //I/O specific core behaviour diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java new file mode 100644 index 00000000..745995eb --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -0,0 +1,356 @@ +package roboy.dialog.states.devoStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.states.definitions.ExpoState; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState; +import roboy.linguistics.Linguistics; +import roboy.linguistics.Linguistics.SemanticRole; +import roboy.linguistics.Triple; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.Neo4jProperty; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; +import roboy.talk.PhraseCollection; +import roboy.util.Agedater; +import roboy.util.Pair; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.*; + +import static roboy.memory.Neo4jProperty.full_name; +import static roboy.memory.Neo4jProperty.name; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; + +/** + * QuestionAnsweringState + * Roboy Question Answering State + * + * The parser: + * - provides triples generated from the question + * - adds the answer to the question if there is an answer in DBpedia + * - tells a specifying followup question if the interlocutor's question was ambiguous + * + * This state: + * - checks if interlocutor wants to play a game + * - returns the answer if provided by the parser + * - asks the specifying followup question if provided by the parser + * - - if answered with yes --> will use the parser again to get the answer to the original question + * - if answered with no --> will use a segue to avoid answer + * - tries to query memory if there is no answer to the question + * - queries the fallback if memory fails to answer as well + * + * + * QuestionAnsweringState interface: + * 1) Fallback is required. + * 2) Outgoing transitions that have to be defined: + * - finishedQuestionAnswering: following state if this state if finished with answering questions + * 3) No parameters are used. + */ +public class QuestionRoboyQAState extends ExpoState { + private final Logger LOGGER = LogManager.getLogger(); + + private final static String TRANSITION_FINISHED_ANSWERING = "finishedQuestionAnswering"; + private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; + private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; + private final static int MAX_NUM_OF_QUESTIONS = 5; + private int questionsAnswered = 0; + + private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; + private final static RandomList answerStartingPhrases = PhraseCollection.QUESTION_ANSWERING_START; + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + + private boolean askingSpecifyingQuestion = false; + private String answerAfterUnspecifiedQuestion = ""; // the answer to use if specifying question is answered with YES + private boolean userWantsGame = false; + + private QAJsonParser infoValues; + + public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info("The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); + } + + @Override + public Output act() { + if (questionsAnswered > 0) { + return Output.say(reenteringPhrases.getRandomElement()); + } + return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + } + + @Override + public Output react(Interpretation input) { + return reactToQuestion(input); + } + + private Output reactToQuestion(Interpretation input) { + + askingSpecifyingQuestion = false; + questionsAnswered++; + + if (input.getTokens() != null && !(input.getTokens().contains("you") || input.getTokens().contains("your"))) { + Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); + if (parseOutcome == null) { + LOGGER.error("Invalid parser outcome!"); + return Output.say("Invalid parser outcome!"); + } + + if (parseOutcome == Linguistics.ParsingOutcome.SUCCESS) { + if (input.getAnswer() != null) { + // tell the answer, that was provided by the parser + return Output.say(answerStartingPhrases.getRandomElement() + " " + input.getAnswer()); + } + } + } + + // from here we know that dummyParserResult.equals("FAILURE") + return useMemoryOrFallback(input); + } + + @Override + public State getNextState() { + + if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state + return this; + + } else if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + return getTransition(TRANSITION_FINISHED_ANSWERING); + + } else if (Math.random() < 0.5) { // loop back to previous states with probability 0.5 + + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + Neo4jRelationship[] predicates = {FROM, HAS_HOBBY, WORK_FOR, STUDY_AT}; + Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(predicates); + + if (availability == SOME_AVAILABLE) { + return (Math.random() < 0.3) ? getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON) : getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else if (availability == NONE_AVAILABLE) { + return getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else { + if (!isIntentsHistoryComplete(predicates)) { + return getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON); + } else { + return this; + } + } + } else { // stay in this state + return this; + } + + } + + private Output useMemoryOrFallback(Interpretation input) { + try { + if (input.getPas() != null || input.getTriples() != null) { + Output memoryAnswer = answerFromMemory(input); + if (memoryAnswer != null) return memoryAnswer; + } + } catch (Exception e) { + LOGGER.warn(e.getMessage()); + } + + return Output.useFallback(); + } + + private Output answerFromMemory(Interpretation input) { + + // try to use memory to answer + Roboy roboy = new Roboy(getMemory()); + + //String answer = String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), inferMemoryAnswer(input, roboy)); + String answer = String.format("%s", inferMemoryAnswer(input, roboy)); + if (answer.equals("")) { + return Output.useFallback(); + } + return Output.say(answer); + } + + private String inferMemoryAnswer(Interpretation input, Roboy roboy) { + + String answer = ""; + Map pas = input.getPas(); + List triples = input.getTriples(); + + if (pas != null) { + return inferPasAnswer(pas, roboy); + } + + if (triples != null) { + return inferTripleAnswer(triples, roboy); + } + + if (input.getObjAnswer() != null) { + String objAnswer = input.getObjAnswer().toLowerCase(); + if (!objAnswer.equals("")) { + LOGGER.info("OBJ_ANSWER: " + objAnswer); + Neo4jRelationship predicate = inferPredicateFromObjectAnswer(objAnswer); + if (predicate != null) { + answer = extractNodeNameForPredicate(predicate, roboy); + } + } else { + LOGGER.warn("OBJ_ANSWER is empty"); + } + } + + return answer; + } + + private String inferPasAnswer(Map pas, Roboy roboy) { + String answer = ""; + if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { + answer = extractAge(roboy); + // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bweather\\b.*"))) { + // // -> Weather API + // } else if (matchPas(pas, new Pair(SemanticRole.AGENT, ".*\\bmovie.*"))) { + // // -> Movie API + // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.MANNER, "how"), new Pair(SemanticRole.PREDICATE, "say"), new Pair(SemanticRole.AGENT, "you")) || + // matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.PREDICATE, "is"), new Pair(SemanticRole.AGENT, "what"))) { + // // translate(*,**) + } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { + answer = Math.random() > .5 ? + extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : + extractNodeNameForPredicate(Neo4jRelationship.MEMBER_OF, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { + answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { + answer = "Yo moma says I am a good boy!"; + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "who"))) { + if (matchPas(pas, new Pair(SemanticRole.PATIENT, "you"))) { + answer = extractNodeNameForPredicate(Neo4jProperty.full_name, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\b(father|dad)\\b.*"))) { + answer = extractNodeNameForPredicate(Neo4jRelationship.CHILD_OF, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\b(sibling|brother)\\b.*"))){ + answer = extractNodeNameForPredicate(Neo4jRelationship.SIBLING_OF, roboy); + } + } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "do|like"), new Pair(SemanticRole.AGENT, "you"))){ + double prob = Math.random(); + if (prob < .3) { + answer = extractNodeNameForPredicate(Neo4jProperty.abilities, roboy); + } else if(prob < .7) { + answer = extractNodeNameForPredicate(Neo4jRelationship.HAS_HOBBY, roboy); + } else { + answer = extractNodeNameForPredicate(Neo4jProperty.skills, roboy); + } + } + + return answer; + } + + private String inferTripleAnswer(List triples, Roboy roboy) { + String answer = ""; + // else if {OBJ: *} -> query * -> I'm sure I know a typeof(*) called *! (Where does he live? :)) + // + // if * in Neo4jRelationship.FRIEND_OF + return answer; + } + + private Neo4jRelationship inferPredicateFromObjectAnswer(String objectAnswer) { + if (objectAnswer.contains("hobb")) { + return Neo4jRelationship.HAS_HOBBY; + } else if (objectAnswer.contains("member")) { + return Neo4jRelationship.MEMBER_OF; + } else if (objectAnswer.contains("friend")) { + return Neo4jRelationship.FRIEND_OF; + } else if (objectAnswer.contains("where") || + objectAnswer.contains("city") || + objectAnswer.contains("place") || + objectAnswer.contains("country") || + objectAnswer.contains("live") || + objectAnswer.contains("life")) { + return Neo4jRelationship.LIVE_IN; + } else if (objectAnswer.contains("from") || + objectAnswer.contains("born")) { + return Neo4jRelationship.FROM; + } else if (objectAnswer.contains("child") || + objectAnswer.contains("father") || + objectAnswer.contains("dad") || + objectAnswer.contains("parent")) { + return Neo4jRelationship.CHILD_OF; + } else if (objectAnswer.contains("brother") || + objectAnswer.contains("family") || + objectAnswer.contains("relativ")) { + return Neo4jRelationship.SIBLING_OF; + } + return null; + } + + private String extractNodeNameForPredicate(Neo4jRelationship predicate, Roboy roboy) { + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + return String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + return null; + } + + private String extractNodeNameForPredicate(Neo4jProperty predicate, Roboy roboy) { + String property = roboy.getProperty(predicate).toString(); + if (property != null) { + return String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), property); + } + return null; + } + + private String extractAge(Roboy roboy) { + HashMap ages = new Agedater().determineAge(roboy.getProperty(Neo4jProperty.birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + return String.format(infoValues.getSuccessAnswers(Neo4jProperty.age).getRandomElement(), retrievedAge); + } + + private boolean matchPas(Map pas, Pair... matchCriteria) { + if (pas == null) + return false; + boolean allCriteriaSatisfied = true; + for (Pair criterion : matchCriteria) { + if (!pas.containsKey(criterion.getKey()) || + !pas.get(criterion.getKey()).matches(criterion.getValue())) { + allCriteriaSatisfied = false; + break; + } + } + return allCriteriaSatisfied; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(TRANSITION_FINISHED_ANSWERING, TRANSITION_LOOP_TO_NEW_PERSON, TRANSITION_LOOP_TO_KNOWN_PERSON); + } + + @Override + public boolean isFallbackRequired() { + return true; + } + + private boolean isIntentsHistoryComplete(Neo4jRelationship[] predicates) { + boolean isComplete = true; + for (Neo4jRelationship predicate : predicates) { + if (!getContext().DIALOG_INTENTS.contains(new IntentValue(PersonalInformationFollowUpState.INTENTS_HISTORY_ID, predicate))) { + isComplete = false; + } + } + return isComplete; + } +} \ No newline at end of file diff --git a/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java index d6820cd9..f4f28d11 100644 --- a/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java @@ -2,7 +2,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import roboy.context.Context; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.dialog.states.definitions.ExpoState; diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java index 7f50d938..501d72fb 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java @@ -2,7 +2,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import roboy.context.Context; import roboy.context.contextObjects.IntentValue; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; diff --git a/dialog/src/main/java/roboy/linguistics/Triple.java b/dialog/src/main/java/roboy/linguistics/Triple.java index 7dc04e7b..a94901d6 100755 --- a/dialog/src/main/java/roboy/linguistics/Triple.java +++ b/dialog/src/main/java/roboy/linguistics/Triple.java @@ -17,12 +17,19 @@ public Triple(String subject, String predicate, String object){ this.object = object; } + public Triple toLowerCase() { + return new Triple( + this.subject != null ? this.subject.toLowerCase() : null, + this.predicate != null ? this.predicate.toLowerCase() : null, + this.object != null ? this.object.toLowerCase() : null); + } + @Override public String toString() { return "Triple{" + - "SUB: '" + subject + '\'' + - ", PRED: '" + predicate + '\'' + - ", OBJ: '" + object + '\'' + + "SUB: '" + subject + "\'," + + "PRED: '" + predicate + "\'," + + "OBJ: '" + object + "\'" + '}'; } diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java index d3695e51..848aa1be 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java @@ -475,6 +475,55 @@ public String toString() { '}'; } + public void toLowerCase() { + if (sentence != null) { + sentence = sentence.toLowerCase(); + } + if (triples != null) { + for (int i = 0; i < triples.size(); i++) { + if (triples.get(i) != null) { + triples.set(i, triples.get(i).toLowerCase()); + } + } + } + if (tokens != null) { + for (int i = 0; i < tokens.size(); i++) { + if (tokens.get(i) != null) { + tokens.set(i, tokens.get(i).toLowerCase()); + } + } + } + if (this.lemmas != null) { + for (int i = 0; i < lemmas.length; i++) { + if (lemmas[i] != null) { + lemmas[i] = lemmas[i].toLowerCase(); + } + } + } + if (this.pas != null) { + for (SemanticRole key : pas.keySet()) { + if (pas.get(key) != null) { + pas.replace(key, pas.get(key).toLowerCase()); + } + } + } + if (this.name != null) { + this.name = this.name.toLowerCase(); + } + if (this.objAnswer != null) { + this.objAnswer = this.objAnswer.toLowerCase(); + } + if (this.predAnswer != null) { + this.predAnswer = this.predAnswer.toLowerCase(); + } + if (this.underspecifiedQuestion != null) { + this.underspecifiedQuestion = this.underspecifiedQuestion.toLowerCase(); + } + if (this.underspecifiedAnswer != null) { + this.underspecifiedAnswer = this.underspecifiedAnswer.toLowerCase(); + } + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java new file mode 100644 index 00000000..5b677c7e --- /dev/null +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java @@ -0,0 +1,14 @@ +package roboy.linguistics.sentenceanalysis; + +import roboy.linguistics.Linguistics; + +/** + * Corrects abbreviated forms like "I'm" to complete forms like "I am" + * which are expected by later sentence analyses. + */ +public class Postprocessor implements Analyzer{ + public Interpretation analyze(Interpretation interpretation){ + interpretation.toLowerCase(); + return interpretation; + } +} diff --git a/resources/personalityFiles/DevoPersonality.json b/resources/personalityFiles/DevoPersonality.json new file mode 100644 index 00000000..b65d2ee4 --- /dev/null +++ b/resources/personalityFiles/DevoPersonality.json @@ -0,0 +1,93 @@ +{ + "initialState": "Greetings", + "states": [ + { + "identifier": "Greetings", + "implementation": "roboy.dialog.states.ordinaryStates.PassiveGreetingsState", + "transitions": { + "greetingDetected": "Intro" + } + }, + { + "identifier": "Intro", + "implementation": "roboy.dialog.states.ordinaryStates.IntroductionState", + "transitions": { + "knownPerson": "FollowUp", + "newPerson": "PersonalQA" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" + } + }, + { + "identifier": "FollowUp", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState", + "transitions": { + "questionAnswering": "QuestionAnswering" + }, + "parameters": { + "qaFile": "resources/sentences/QAList.json" + } + }, + { + "identifier": "PersonalQA", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "transitions": { + "questionAnswering": "QuestionAnswering" + }, + "parameters": { + "qaFile": "resources/sentences/QAList.json" + } + }, + { + "identifier": "QuestionAnswering", + "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", + "fallback": "WildTalk", + "transitions": { + "finishedQuestionAnswering": "Farewell", + "loopToNewPerson": "PersonalQA", + "loopToKnownPerson": "FollowUp", + "switchToGaming": "ChooseGameState" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" + } + }, + { + "identifier": "GamingTwentyQuestionsState", + "implementation": "roboy.dialog.states.gameStates.GamingTwentyQuestionsState", + "transitions": { + "gameEnded" : "QuestionAnswering" + } + }, + { + "identifier": "GamingSnapchatState", + "implementation": "roboy.dialog.states.gameStates.GamingSnapchatState", + "transitions": { + "gameEnded" : "QuestionAnswering" + }, + "parameters": { + "filterFile": "resources/gameResources/snapchat-filters.txt" + } + }, + { + "identifier": "ChooseGameState", + "implementation": "roboy.dialog.states.gameStates.ChooseGameState", + "transitions": { + "choseSnapchat" : "GamingSnapchatState", + "chose20questions" : "GamingTwentyQuestionsState", + "exitGame": "QuestionAnswering" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + }, + { + "identifier": "Farewell", + "implementation": "roboy.dialog.states.ordinaryStates.FarewellState", + "transitions": {} + } + ] +} \ No newline at end of file From a9e172f592b33b89efe425ee9a390474667629da Mon Sep 17 00:00:00 2001 From: Jayce Date: Wed, 15 Aug 2018 12:41:00 +0200 Subject: [PATCH 070/147] API shizzle --- .../src/main/java/roboy/util/api/Movie.java | 40 +++++ .../main/java/roboy/util/api/Translate.java | 140 ++++++++++++++++++ .../src/main/java/roboy/util/api/Weather.java | 40 +++++ .../main/java/roboy/util/api/keyGetter.java | 22 +++ 4 files changed, 242 insertions(+) create mode 100644 dialog/src/main/java/roboy/util/api/Movie.java create mode 100644 dialog/src/main/java/roboy/util/api/Translate.java create mode 100644 dialog/src/main/java/roboy/util/api/Weather.java create mode 100644 dialog/src/main/java/roboy/util/api/keyGetter.java diff --git a/dialog/src/main/java/roboy/util/api/Movie.java b/dialog/src/main/java/roboy/util/api/Movie.java new file mode 100644 index 00000000..90e57178 --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/Movie.java @@ -0,0 +1,40 @@ +package roboy.util.api; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Random; + +public class Movie{ + static String KEY = keyGetter.getKey("moviekey"); + static int randomInt = new Random().nextInt(20); + + //FIELD TITLE or OVERVIEW + public static String getData(String field) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + JsonElement jsonElement = ((JsonObject) new JsonParser().parse(result.toString())) + .getAsJsonArray("results") + .get(randomInt).getAsJsonObject().get(field); +// System.out.println(jsonObject); + return jsonElement.getAsString(); + } + + public static void main(String[] args)throws Exception{ + System.out.println(getData("title")+":\t"+getData("overview")); + } +} diff --git a/dialog/src/main/java/roboy/util/api/Translate.java b/dialog/src/main/java/roboy/util/api/Translate.java new file mode 100644 index 00000000..129220e4 --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/Translate.java @@ -0,0 +1,140 @@ +package roboy.util.api; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Translate { + static final String KEY = keyGetter.getKey("translatekey"); + + + //Language: Either Language code such as DE or language name. Text is the text to translate + public static String getData(String text, String language) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(APIify(text, handleLanguage(language))); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); +// System.out.println(jsonObject); + return jsonObject.toString(); + } + + private static String handleLanguage(String language) { + switch (language.toLowerCase()){ + case "azerbaijan": return "az"; + case "malayalam": return "ml"; + case "albanian": return "sq"; + case "maltese": return "mt"; + case "amharic": return "am"; + case "macedonian": return "mk"; + case "english": return "en"; + case "maori": return "mi"; + case "arabic": return "ar"; + case "marathi": return "mr"; + case "armenian": return "hy"; + case "mari": return "mhr"; + case "afrikaans": return "af"; + case "mongolian": return "mn"; + case "basque": return "eu"; + case "german": return "de"; + case "bashkir": return "ba"; + case "nepali": return "ne"; + case "belarusian": return "be"; + case "norwegian": return "no"; + case "bengali": return "bn"; + case "punjabi": return "pa"; + case "burmese": return "my"; + case "papiamento": return "pap"; + case "bulgarian": return "bg"; + case "persian": return "fa"; + case "bosnian": return "bs"; + case "polish": return "pl"; + case "welsh": return "cy"; + case "portuguese": return "pt"; + case "hungarian": return "hu"; + case "romanian": return "ro"; + case "vietnamese": return "vi"; + case "russian": return "ru"; + case "haitian": return "ht"; + case "cebuano": return "ceb"; + case "galician": return "gl"; + case "serbian": return "sr"; + case "dutch": return "nl"; + case "sinhala": return "si"; + case "slovakian": return "sk"; + case "greek": return "el"; + case "slovenian": return "sl"; + case "georgian": return "ka"; + case "swahili": return "sw"; + case "gujarati": return "gu"; + case "sundanese": return "su"; + case "danish": return "da"; + case "tajik": return "tg"; + case "hebrew": return "he"; + case "thai": return "th"; + case "yiddish": return "yi"; + case "tagalog": return "tl"; + case "indonesian": return "id"; + case "tamil": return "ta"; + case "irish": return "ga"; + case "tatar": return "tt"; + case "italian": return "it"; + case "telugu": return "te"; + case "icelandic": return "is"; + case "turkish": return "tr"; + case "spanish": return "es"; + case "udmurt": return "udm"; + case "kazakh": return "kk"; + case "uzbek": return "uz"; + case "kannada": return "kn"; + case "ukrainian": return "uk"; + case "catalan": return "ca"; + case "urdu": return "ur"; + case "kyrgyz": return "ky"; + case "finnish": return "fi"; + case "chinese": return "zh"; + case "french": return "fr"; + case "korean": return "ko"; + case "hindi": return "hi"; + case "xhosa": return "xh"; + case "croatian": return "hr"; + case "khmer": return "km"; + case "czech": return "cs"; + case "laotian": return "lo"; + case "swedish": return "sv"; + case "latin": return "la"; + case "scottish": return "gd"; + case "latvian": return "lv"; + case "estonian": return "et"; + case "lithuanian": return "lt"; + case "esperanto": return "eo"; + case "luxembourgish": return "lb"; + case "javanese": return "jv"; + case "malagasy": return "mg"; + case "japanese": return "ja"; + case "malay": return "ms"; + default: return language; + } + } + + private static String APIify(String text, String targetLang){ + String s = String.format("https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s", KEY, text.replace(" ", "%20"), targetLang); +// System.out.println(s); + return s; + } + + public static void main(String[] args) throws Exception{ + System.out.println(getData("cheese is the best vegetable", "german")); + } +} diff --git a/dialog/src/main/java/roboy/util/api/Weather.java b/dialog/src/main/java/roboy/util/api/Weather.java new file mode 100644 index 00000000..f04d48fb --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/Weather.java @@ -0,0 +1,40 @@ +package roboy.util.api; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Weather { + final static String KEY = keyGetter.getKey("weatherkey"); + public static String getData(String country) throws Exception{ + return getHTML(country); + } + public static String getHTML(String country) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("http://api.openweathermap.org/data/2.5/weather?q=%s&APPID=%s", country, KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + JsonObject jsonObject = (((JsonObject) new JsonParser().parse(result.toString())).get("weather").getAsJsonArray()).get(0).getAsJsonObject(); +// System.out.println(jsonObject.get("main")); + return jsonObject.get("main").getAsString(); + } + + public static void main(String[] args) throws Exception + { + //Find Munich + System.out.println(getData("munich")); + } + + +} diff --git a/dialog/src/main/java/roboy/util/api/keyGetter.java b/dialog/src/main/java/roboy/util/api/keyGetter.java new file mode 100644 index 00000000..b91fc487 --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/keyGetter.java @@ -0,0 +1,22 @@ +package roboy.util.api; + +import org.apache.commons.configuration2.YAMLConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; + +import java.io.FileNotFoundException; +import java.io.FileReader; + +public class keyGetter { + static YAMLConfiguration yamlConfiguration = new YAMLConfiguration(); + static String getKey(String key){ + try { + yamlConfiguration.read(new FileReader("dialog/src/main/java/roboy/util/api/apiKeys.yml")); + } catch (ConfigurationException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return yamlConfiguration.getString(key); + } + +} From 63160af4f072179816c90f713c54784ac313a5ce Mon Sep 17 00:00:00 2001 From: Joseph Birkner Date: Wed, 15 Aug 2018 17:09:46 +0200 Subject: [PATCH 071/147] Fixed API invocations in new QA state. --- .../devoStates/QuestionRoboyQAState.java | 47 ++++++++++++++++--- .../knowledgebase}/apiKeys.yml | 0 2 files changed, 40 insertions(+), 7 deletions(-) rename {dialog/src/main/java/roboy/util/api => resources/knowledgebase}/apiKeys.yml (100%) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 745995eb..96fd3cb4 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -21,6 +21,7 @@ import roboy.util.Pair; import roboy.util.QAJsonParser; import roboy.util.RandomList; +import roboy.util.api.*; import java.util.*; @@ -99,6 +100,11 @@ private Output reactToQuestion(Interpretation input) { askingSpecifyingQuestion = false; questionsAnswered++; + String answer = inferApiAnswer(input); + if (!answer.isEmpty()) { + return Output.say(answer); + } + if (input.getTokens() != null && !(input.getTokens().contains("you") || input.getTokens().contains("your"))) { Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); if (parseOutcome == null) { @@ -176,6 +182,40 @@ private Output answerFromMemory(Interpretation input) { return Output.say(answer); } + private String inferApiAnswer(Interpretation input) { + Map pas = input.getPas(); + String answer = ""; + if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bweather\\b.*"))) { + try { + answer = String.format("It seems like it is %s out there!", Weather.getData("munich")); + } + catch (Exception e) { + answer = "It seems a bit moody..."; + LOGGER.error(e.getMessage()); + } + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, ".*\\bmovie.*"))) { + try { + answer = String.format("I have heard that %s is playing!", Movie.getData("title")); + } + catch (Exception e) { + answer = "Wall e is a great movie!"; + LOGGER.error(e.getMessage()); + } + } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.MANNER, "how"), new Pair(SemanticRole.PREDICATE, "say"), new Pair(SemanticRole.AGENT, "you")) || + matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.PREDICATE, "is"), new Pair(SemanticRole.AGENT, "what"))) { + String[] parts = pas.get(SemanticRole.PATIENT).split(" in "); + assert(parts.length == 2); + try { + answer = answerStartingPhrases.getRandomElement() + " " + Translate.getData(parts[0], parts[1]); + } + catch (Exception e) { + answer = String.format("I am not sure whether I know %s", parts[1]); + LOGGER.error(e.getMessage()); + } + } + return answer; + } + private String inferMemoryAnswer(Interpretation input, Roboy roboy) { String answer = ""; @@ -210,13 +250,6 @@ private String inferPasAnswer(Map pas, Roboy roboy) { String answer = ""; if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); - // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bweather\\b.*"))) { - // // -> Weather API - // } else if (matchPas(pas, new Pair(SemanticRole.AGENT, ".*\\bmovie.*"))) { - // // -> Movie API - // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.MANNER, "how"), new Pair(SemanticRole.PREDICATE, "say"), new Pair(SemanticRole.AGENT, "you")) || - // matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.PREDICATE, "is"), new Pair(SemanticRole.AGENT, "what"))) { - // // translate(*,**) } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { answer = Math.random() > .5 ? extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/resources/knowledgebase/apiKeys.yml similarity index 100% rename from dialog/src/main/java/roboy/util/api/apiKeys.yml rename to resources/knowledgebase/apiKeys.yml From a91eb78e363a6890d9ea54f06342444bc4dc9ecb Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Thu, 16 Aug 2018 14:10:06 +0200 Subject: [PATCH 072/147] DEvo states --- .../states/devoStates/IntroductionState.java | 213 ++++++++++++++++++ .../PersonalInformationAskingState.java | 92 ++++++++ .../devoStates/QuestionRoboyQAState.java | 30 +-- .../personalityFiles/DevoPersonality.json | 8 +- 4 files changed, 312 insertions(+), 31 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java new file mode 100644 index 00000000..72e7bae8 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java @@ -0,0 +1,213 @@ +package roboy.dialog.states.devoStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jProperty; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.Interlocutor.RelationshipAvailability; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; +import roboy.util.Agedater; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Set; + +import static roboy.memory.Neo4jProperty.*; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; + +/** + * This state will: + * - ask the interlocutor for his name + * - query memory if the person is already known + * - create and update the interlocutor in the context + * - take one of two transitions: knownPerson or newPerson + * + * IntroductionState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - knownPerson: following state if the person is already known + * - newPerson: following state if the person is NOT known + * 3) No parameters are used. + */ +public class IntroductionState extends State { + private QAJsonParser infoValues; + private final String UPDATE_KNOWN_PERSON = "knownPerson"; + private final String LEARN_ABOUT_PERSON = "newPerson"; + private final Logger LOGGER = LogManager.getLogger(); + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + private final RandomList introPhrases = new RandomList<>("What's your name?"); + private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!"); + private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!"); + + private Neo4jRelationship[] personPredicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); + private RandomList roboyPropertiesPredicates = new RandomList<>(skills, abilities, future); + private State nextState; + + public IntroductionState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info(" -> The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); + } + + @Override + public Output act() { + return Output.say(getIntroPhrase()); + } + + @Override + public Output react(Interpretation input) { + // expecting something like "My name is NAME" + + // 1. get name + String name = getNameFromInput(input); + + if (name == null) { + // input couldn't be parsed properly + // TODO: do something intelligent if the parser fails + nextState = this; + LOGGER.warn("IntroductionState couldn't get name! Staying in the same state."); + return Output.say("Sorry, my parser is out of service."); + // alternatively: Output.useFallback() or Output.sayNothing() + } + + + // 2. get interlocutor object from context + // this also should query memory and do other magic + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + person.addName(name); + // Roboy roboy = new Roboy(getMemory()); + + + // 3. update interlocutor in context + updateInterlocutorInContext(person); + String retrievedPersonalFact = ""; + Double segueProbability = 0.0; + + // 4. check if person is known/familiar + if (person.FAMILIAR) { + // 4a. person known/familiar + // TODO: get some hobbies or occupation of the person to make answer more interesting + RandomList nodes = getMemNodesByIds(person.getRelationships(FRIEND_OF)); + if (!nodes.isEmpty()) { + retrievedPersonalFact = " You are friends with " + + nodes.getRandomElement().getProperties().get(Neo4jProperty.name).toString(); + } + + RelationshipAvailability availability = person.checkRelationshipAvailability(personPredicates); + if (availability == SOME_AVAILABLE) { + nextState = (Math.random() < 0.3) ? getTransition(UPDATE_KNOWN_PERSON) : getTransition(LEARN_ABOUT_PERSON); + } else if (availability == NONE_AVAILABLE) { + nextState = getTransition(LEARN_ABOUT_PERSON); + } else { + nextState = getTransition(UPDATE_KNOWN_PERSON); + } + } else { + // 4b. person is not known + nextState = getTransition(LEARN_ABOUT_PERSON); + segueProbability = 0.6; + } + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); + } + + @Override + public State getNextState() { + return nextState; + } + + private String getNameFromInput(Interpretation input) { + return getInference().inferProperty(name, input); + } + + private void updateInterlocutorInContext(Interlocutor interlocutor) { + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(interlocutor); + } + + private String getIntroPhrase() { + return introPhrases.getRandomElement(); + } + + private String getResponsePhrase(String name, boolean familiar) { + if (familiar) { + return String.format(successResponsePhrases.getRandomElement(), name); + } else { + return String.format(failureResponsePhrases.getRandomElement(), name); + } + } + + private String getRoboyFactsPhrase(Roboy roboy) { + String result = ""; + + // Get some random properties facts + if (roboy.getProperties() != null && !roboy.getProperties().isEmpty()) { + HashMap properties = roboy.getProperties(); + if (properties.containsKey(full_name)) { + result += " " + String.format(infoValues.getSuccessAnswers(full_name).getRandomElement(), properties.get(full_name)); + } + if (properties.containsKey(birthdate)) { + HashMap ages = new Agedater().determineAge(properties.get(birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), retrievedAge); + } else if (properties.containsKey(age)) { + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); + } + if (properties.containsKey(skills)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(abilities)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(future)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + } + } + + if (result.equals("")) { + result = "I am Roboy 2.0! "; + } + + // Get a random relationship fact + Neo4jRelationship predicate = roboyRelatioshipPredicates.getRandomElement(); + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName = ""; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + result += " " + String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + + return result; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(UPDATE_KNOWN_PERSON, LEARN_ABOUT_PERSON); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java new file mode 100644 index 00000000..1b7cf5f9 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java @@ -0,0 +1,92 @@ +package roboy.dialog.states.devoStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Set; + +import static roboy.memory.Neo4jRelationship.*; + +/** + * Personal Information Asking State + * + * The state tries to interact with the Interlocutor to learn new information about the person. + * This information is sent to the Roboy Memory Module through Neo4jMemoryInterface for storing. + * Afterwards, Roboy can use this acquired data for the future interactions with the same person. + * + * - if there is no existing Interlocutor or the data is missing, ask a question + * - the question topic (intent) is selected from the Neo4jRelationship predicates + * - retrieve the questions stored in the QAList json file + * - update the Context IntentsHistory + * - try to extract the result from the Interpretation + * - retrieve the answers stored in the QAList json file + * - send the result to Memory + * + * PersonalInformationAskingState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - TRANSITION_INFO_OBTAINED: following state if the question was asked + * 3) Required parameters: path to the QAList.json file. + */ +public class PersonalInformationAskingState extends State { + private QAJsonParser qaValues; + private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private Neo4jRelationship selectedPredicate; + private State nextState; + + private final String TRANSITION_INFO_OBTAINED = "questionAnswering"; + private final String QA_FILE_PARAMETER_ID = "qaFile"; + final Logger LOGGER = LogManager.getLogger(); + + public final static String INTENTS_HISTORY_ID = "PIA"; + + public PersonalInformationAskingState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); + LOGGER.info(" -> The QAList path: " + qaListPath); + qaValues = new QAJsonParser(qaListPath); + } + + @Override + public Output act() { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info(" -> Retrieved Interlocutor: " + person.getName()); + + return Output.say("What is my purpose?"); + } + + @Override + public Output react(Interpretation input) { + nextState = getTransition(TRANSITION_INFO_OBTAINED); + return Output.say("Oh. My. God."); + } + + @Override + public State getNextState() { + return nextState; + } + + @Override + protected Set getRequiredTransitionNames() { + // optional: define all required transitions here: + return newSet(TRANSITION_INFO_OBTAINED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(QA_FILE_PARAMETER_ID); + } + + private String InferResult(Interpretation input) { + return getInference().inferRelationship(selectedPredicate, input); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 96fd3cb4..f41fb659 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -62,7 +62,7 @@ public class QuestionRoboyQAState extends ExpoState { private final static String TRANSITION_FINISHED_ANSWERING = "finishedQuestionAnswering"; private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; - private final static int MAX_NUM_OF_QUESTIONS = 5; + private final static int MAX_NUM_OF_QUESTIONS = 6; private int questionsAnswered = 0; private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; @@ -126,34 +126,10 @@ private Output reactToQuestion(Interpretation input) { @Override public State getNextState() { - - if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state - return this; - - } else if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking return getTransition(TRANSITION_FINISHED_ANSWERING); - - } else if (Math.random() < 0.5) { // loop back to previous states with probability 0.5 - - Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); - Neo4jRelationship[] predicates = {FROM, HAS_HOBBY, WORK_FOR, STUDY_AT}; - Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(predicates); - - if (availability == SOME_AVAILABLE) { - return (Math.random() < 0.3) ? getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON) : getTransition(TRANSITION_LOOP_TO_NEW_PERSON); - } else if (availability == NONE_AVAILABLE) { - return getTransition(TRANSITION_LOOP_TO_NEW_PERSON); - } else { - if (!isIntentsHistoryComplete(predicates)) { - return getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON); - } else { - return this; - } - } - } else { // stay in this state - return this; } - + return this; } private Output useMemoryOrFallback(Interpretation input) { diff --git a/resources/personalityFiles/DevoPersonality.json b/resources/personalityFiles/DevoPersonality.json index b65d2ee4..2825ccb1 100644 --- a/resources/personalityFiles/DevoPersonality.json +++ b/resources/personalityFiles/DevoPersonality.json @@ -10,7 +10,7 @@ }, { "identifier": "Intro", - "implementation": "roboy.dialog.states.ordinaryStates.IntroductionState", + "implementation": "roboy.dialog.states.devoStates.IntroductionState", "transitions": { "knownPerson": "FollowUp", "newPerson": "PersonalQA" @@ -31,9 +31,9 @@ }, { "identifier": "PersonalQA", - "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "implementation": "roboy.dialog.states.devoStates.PersonalInformationAskingState", "transitions": { - "questionAnswering": "QuestionAnswering" + "questionAnswering": "Farewell" }, "parameters": { "qaFile": "resources/sentences/QAList.json" @@ -44,7 +44,7 @@ "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", "fallback": "WildTalk", "transitions": { - "finishedQuestionAnswering": "Farewell", + "finishedQuestionAnswering": "PersonalQA", "loopToNewPerson": "PersonalQA", "loopToKnownPerson": "FollowUp", "switchToGaming": "ChooseGameState" From 414d9c527c12e74ea7a6f9f6bfbcd869b197e541 Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Thu, 16 Aug 2018 14:17:33 +0200 Subject: [PATCH 073/147] Fixes --- resources/personalityFiles/DevoPersonality.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/personalityFiles/DevoPersonality.json b/resources/personalityFiles/DevoPersonality.json index 2825ccb1..ce123401 100644 --- a/resources/personalityFiles/DevoPersonality.json +++ b/resources/personalityFiles/DevoPersonality.json @@ -12,8 +12,8 @@ "identifier": "Intro", "implementation": "roboy.dialog.states.devoStates.IntroductionState", "transitions": { - "knownPerson": "FollowUp", - "newPerson": "PersonalQA" + "knownPerson": "QuestionAnswering", + "newPerson": "QuestionAnswering" }, "parameters": { "infoFile": "resources/sentences/RoboyInfoList.json" From 1d77c047083f6061ff240fe33f18586b64d52abe Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Thu, 16 Aug 2018 14:21:03 +0200 Subject: [PATCH 074/147] Fixes again --- .../roboy/dialog/states/devoStates/QuestionRoboyQAState.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index f41fb659..ace852f7 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -227,9 +227,7 @@ private String inferPasAnswer(Map pas, Roboy roboy) { if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { - answer = Math.random() > .5 ? - extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : - extractNodeNameForPredicate(Neo4jRelationship.MEMBER_OF, roboy); + extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { From 8c729ca5b9a51b0ed1ae3a163595f8013ee882ce Mon Sep 17 00:00:00 2001 From: missxa Date: Sun, 19 Aug 2018 03:37:32 +0200 Subject: [PATCH 075/147] wildtalk using proc-bridge --- .gitignore | 1 + config.properties | 5 ++- dialog/pom.xml | 6 +++ .../devoStates/QuestionRoboyQAState.java | 2 +- .../QuestionAnsweringState.java | 12 ++---- .../states/ordinaryStates/WildTalkState.java | 40 ++++++++++--------- .../main/java/roboy/util/ConfigManager.java | 7 ++++ .../test/WildPersonality.json | 21 ++++++++++ 8 files changed, 65 insertions(+), 29 deletions(-) create mode 100644 resources/personalityFiles/test/WildPersonality.json diff --git a/.gitignore b/.gitignore index 65fbe33f..3e3e3899 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,4 @@ nlu/parser/target/ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml dialog/src/main/java/roboy/util/api/apiKeys\.yml +dialog/src/main/java/roboy/util/api/apiKeys.yml diff --git a/config.properties b/config.properties index 56c29b04..9e58539e 100755 --- a/config.properties +++ b/config.properties @@ -54,7 +54,7 @@ PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/test/WildPersonality.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" @@ -64,6 +64,9 @@ ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/sc TELEGRAM_API_TOKENS_FILE: "" +PARLAI_PORT: 8877 +PARLAI_HOST: "127.0.0.1" + # Logging Levels # Each Logging Module has different levels. End users should use warn. Developers should use either info or debug/fine. diff --git a/dialog/pom.xml b/dialog/pom.xml index 06ccf029..18b5dbae 100755 --- a/dialog/pom.xml +++ b/dialog/pom.xml @@ -429,6 +429,12 @@ telegrambots 3.6.1 + + + co.gongzh.procbridge + procbridge + 1.0.2 + diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index ace852f7..dca3f041 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -227,7 +227,7 @@ private String inferPasAnswer(Map pas, Roboy roboy) { if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { - extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : + extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy); } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java index 501d72fb..239f7416 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java @@ -76,18 +76,12 @@ public QuestionAnsweringState(String stateIdentifier, StateParameters params) { @Override public Output act() { - if(Math.random() > THRESHOLD_BORED && questionsAnswered > 2){ + if(Math.random() > THRESHOLD_BORED && questionsAnswered > 5){ roboySuggestedGame = true; + questionsAnswered = 0; return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); } - if (askingSpecifyingQuestion) { - return Output.sayNothing(); - } - - if (questionsAnswered > 0) { - return Output.say(reenteringPhrases.getRandomElement()); - } - return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + return Output.sayNothing(); } @Override diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java index 5a10915b..0cdef55c 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java @@ -1,5 +1,10 @@ package roboy.dialog.states.ordinaryStates; +import co.gongzh.procbridge.ProcBridge; +import co.gongzh.procbridge.ProcBridgeException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.json.JSONObject; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.Linguistics; @@ -10,8 +15,7 @@ import java.util.Set; -import static roboy.util.ConfigManager.ROS_ACTIVE_PKGS; -import static roboy.util.ConfigManager.ROS_ENABLED; +import static roboy.util.ConfigManager.*; /** * This fallback state will query the generative model over ROS to create a reply for any situation. @@ -27,6 +31,9 @@ */ public class WildTalkState extends State { + private final Logger LOGGER = LogManager.getLogger(); + private ProcBridge pb; + private RandomList rosFailurePhrases = new RandomList<>( "Hey, who disconnected me from my beloved ros node? I need it! ", "Oh well, my generative model is not connected. That makes me sad. ", @@ -36,6 +43,8 @@ public class WildTalkState extends State { public WildTalkState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); + pb = new ProcBridge(PARLAI_HOST, PARLAI_PORT, 2000); + } @Override @@ -47,24 +56,19 @@ public Output act() { public Output react(Interpretation input) { String sentence = input.getSentence(); - RosMainNode rmn = getRosMainNode(); - if (rmn == null) { - if(ROS_ENABLED && ROS_ACTIVE_PKGS.contains("roboy_gnlp")){ - return Output.say(rosFailurePhrases.getRandomElement()) - .setSegue(new Segue(Segue.SegueType.DISTRACT, 0.8)); - } - else{ - return Output.say("I am out of words.").setSegue(new Segue(Segue.SegueType.DISTRACT, 0.8)); - } - } - String reaction = rmn.GenerateAnswer(sentence); - - if (reaction == null) { - return Output.say("I am out of words.").setSegue(new Segue(Segue.SegueType.DISTRACT, 0.8)); - } else { - return Output.say(reaction); + JSONObject resp; + try { + resp = pb.request("parlai", "{text_input: " + sentence + "}"); + LOGGER.info(resp); + return Output.say(resp.getString("result")); + } + catch (Exception e) + { + LOGGER.warn(e.getMessage()); } + return Output.sayNothing(); + } @Override diff --git a/dialog/src/main/java/roboy/util/ConfigManager.java b/dialog/src/main/java/roboy/util/ConfigManager.java index 8aec3099..1deaa22d 100644 --- a/dialog/src/main/java/roboy/util/ConfigManager.java +++ b/dialog/src/main/java/roboy/util/ConfigManager.java @@ -49,6 +49,9 @@ public class ConfigManager { public static String DIALOG_LOG_MODE = "INFO"; public static String PARSER_LOG_MODE = "ALL"; + public static String PARLAI_HOST = "127.0.0.1"; + public static int PARLAI_PORT = 8877; + static { // this block is called once at and will initialize config // alternative: create a singleton for this class @@ -123,10 +126,14 @@ private static void initializeConfig() { TELEGRAM_API_TOKENS_FILE = yamlConfig.getString("TELEGRAM_API_TOKENS_FILE"); + PARLAI_HOST = yamlConfig.getString("PARLAI_HOST"); + PARLAI_PORT = yamlConfig.getInt("PARLAI_PORT"); + MEMORY_LOG_MODE = (yamlConfig.getString("MEMORY_LOG_MODE")); PARSER_LOG_MODE = (yamlConfig.getString("PARSER_LOG_MODE")); DIALOG_LOG_MODE = (yamlConfig.getString("DIALOG_LOG_MODE")); + } catch(ConfigurationException | FileNotFoundException e) { LOGGER.error("Exception while reading YAML configurations from "+yamlConfigFile); LOGGER.error(e.getMessage()); diff --git a/resources/personalityFiles/test/WildPersonality.json b/resources/personalityFiles/test/WildPersonality.json new file mode 100644 index 00000000..58492ce3 --- /dev/null +++ b/resources/personalityFiles/test/WildPersonality.json @@ -0,0 +1,21 @@ +{ + "initialState": "QuestionAnswering", + "states": [ + { + "identifier": "QuestionAnswering", + "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "fallback": "WildTalk", + "transitions": { + "finishedQuestionAnswering": "QuestionAnswering", + "loopToNewPerson": "QuestionAnswering", + "loopToKnownPerson": "QuestionAnswering", + "switchToGaming": "QuestionAnswering" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + } + ] +} \ No newline at end of file From fb6d8922965fb5c9f497dfc0cc82de05bef412d6 Mon Sep 17 00:00:00 2001 From: missxa Date: Sun, 19 Aug 2018 16:16:07 +0200 Subject: [PATCH 076/147] rebase botboy-dev --- dialog/src/main/java/roboy/dialog/ConversationManager.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index 66388a04..542a03ca 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -84,13 +84,8 @@ public static void main(String[] args) throws IOException { analyzers.add(new EmotionAnalyzer()); -<<<<<<< 99ca23f32264e1c18002de44f0611b85cc742df2 - //analyzers.add(new ProfanityAnalyzer()); -======= analyzers.add(new ProfanityAnalyzer()); analyzers.add(new Postprocessor()); ->>>>>>> Like, hypersexy space alien shit, or something - //I/O specific core behaviour From 888c4411302ecf02e8914fa3609f2e539e5e1f7b Mon Sep 17 00:00:00 2001 From: Jayce Date: Mon, 13 Aug 2018 20:50:13 +0200 Subject: [PATCH 077/147] Joseph's Highly Pedantic Changes --- .../linguistics/sentenceanalysis/SemanticParserAnalyzer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java index 69bd48f0..df604c74 100644 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java @@ -142,7 +142,7 @@ private void executeSemanticAnalysis(Interpretation result, Example ex) String answer = val.pureString(); //Handle URL's - if (answer.contains(" at the end of URL } From af979720120d946db93b9346d56df06344b61ca0 Mon Sep 17 00:00:00 2001 From: Jayce Date: Mon, 13 Aug 2018 21:51:34 +0200 Subject: [PATCH 078/147] =?UTF-8?q?[Docs]=20TBL:=20-=20to=20=E2=80=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/developer_manual/2_Logging_Policy.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developer_manual/2_Logging_Policy.rst b/docs/developer_manual/2_Logging_Policy.rst index 363f6894..99644eb8 100644 --- a/docs/developer_manual/2_Logging_Policy.rst +++ b/docs/developer_manual/2_Logging_Policy.rst @@ -85,10 +85,10 @@ Developers should use a standardized policy when it comes to defining the loggin Level Method Level Method Level Method ============ ============ ============ ============ ============ ============ =================================== FATAL lg.fatal() SEVERE lg.severe() FATAL lg.fail() Problem requiring module to shutdown immidiately -ERROR lg.error() - Use WARNING ERROR lg.error() Problem that requires recommends a shutdown, but is not forcibly required +ERROR lg.error() — Use WARNING ERROR lg.error() Problem that requires recommends a shutdown, but is not forcibly required WARN lg.warn() WARNING lg.warning() WARN lg.warning() Unexpected behaviour that should be corrected, but is handlable for the program INFO lg.info() INFO lg.info() INFO lg.log() Information regarding the usage of module (e.g. Config Choices, Major Modules Loaded) -- - CONFIG lg.config() - - Avoid using this level +— — CONFIG lg.config() — — Avoid using this level DEBUG lg.debug() FINE lg.fine() DEBUG lg.dbg() Information not directly relevant to execution of program, unless debugging. This includes tests and parsing details. ============ ============ ============ ============ ============ ============ =================================== From eb387eebb313f33fae142527209d7729236326e9 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 13:06:24 +0200 Subject: [PATCH 079/147] [Logging Policy] Conforming more Stuff to Standards --- .../main/java/roboy/dialog/Conversation.java | 2 +- .../java/edu/stanford/nlp/sempre/Example.java | 70 ++++++++++--------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/Conversation.java b/dialog/src/main/java/roboy/dialog/Conversation.java index 80807c77..7fca43da 100644 --- a/dialog/src/main/java/roboy/dialog/Conversation.java +++ b/dialog/src/main/java/roboy/dialog/Conversation.java @@ -128,7 +128,7 @@ public void run(){ e.printStackTrace(); } } - logger.info(interpretation.toString()); + logger.debug(interpretation.toString()); // answer try { diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java index 2ee5e862..e9181416 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/Example.java @@ -7,9 +7,11 @@ import com.google.common.base.Joiner; import com.google.common.collect.Sets; import edu.stanford.nlp.sempre.roboy.utils.logging.EvaluationToggle; +import edu.stanford.nlp.sempre.roboy.utils.logging.ParserLogController; import fig.basic.Evaluation; import fig.basic.LispTree; import edu.stanford.nlp.sempre.roboy.utils.logging.LogInfoToggle; +import org.apache.logging.log4j.Level; import java.io.FileInputStream; import java.io.InputStream; @@ -272,41 +274,45 @@ public void preprocess() { } public void log() { - LogInfoToggle.begin_track("Example: %s", utterance); - LogInfoToggle.logs("Tokens: %s", getTokens()); - LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); - LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); - LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); - LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); - if (context != null) - LogInfoToggle.logs("context: %s", context); - if (targetFormula != null) - LogInfoToggle.logs("targetFormula: %s", targetFormula); - if (targetValue != null) - LogInfoToggle.logs("targetValue: %s", targetValue); - LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); - LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); - LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); - LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); - LogInfoToggle.end_track(); + if(ParserLogController.getLevel().isLessSpecificThan(Level.DEBUG)) { + LogInfoToggle.begin_track("Example: %s", utterance); + LogInfoToggle.logs("Tokens: %s", getTokens()); + LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); + LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); + LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); + LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); + if (context != null) + LogInfoToggle.logs("context: %s", context); + if (targetFormula != null) + LogInfoToggle.logs("targetFormula: %s", targetFormula); + if (targetValue != null) + LogInfoToggle.logs("targetValue: %s", targetValue); + LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); + LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); + LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); + LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); + LogInfoToggle.end_track(); + } } public void logWithoutContext() { - LogInfoToggle.begin_track("Example: %s", utterance); - LogInfoToggle.logs("Tokens: %s", getTokens()); - LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); - LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); - LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); - LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); - if (targetFormula != null) - LogInfoToggle.logs("targetFormula: %s", targetFormula); - if (targetValue != null) - LogInfoToggle.logs("targetValue: %s", targetValue); - LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); - LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); - LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); - LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); - LogInfoToggle.end_track(); + if(ParserLogController.getLevel().isLessSpecificThan(Level.DEBUG)) { + LogInfoToggle.begin_track("Example: %s", utterance); + LogInfoToggle.logs("Tokens: %s", getTokens()); + LogInfoToggle.logs("Lemmatized tokens: %s", getLemmaTokens()); + LogInfoToggle.logs("POS tags: %s", languageInfo.posTags); + LogInfoToggle.logs("NER tags: %s", languageInfo.nerTags); + LogInfoToggle.logs("NER values: %s", languageInfo.nerValues); + if (targetFormula != null) + LogInfoToggle.logs("targetFormula: %s", targetFormula); + if (targetValue != null) + LogInfoToggle.logs("targetValue: %s", targetValue); + LogInfoToggle.logs("Sentiment: %s", genInfo.sentiment); + LogInfoToggle.logs("Keywords: %s", genInfo.keywords.toString()); + LogInfoToggle.logs("Dependency children: %s", languageInfo.dependencyChildren); + LogInfoToggle.logs("Extracted relations: %s", relationInfo.relations.toString()); + LogInfoToggle.end_track(); + } } public List getCorrectDerivations() { From f9cb406500d23eea80ddf477ab848d3fd05030eb Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 14:11:16 +0200 Subject: [PATCH 080/147] [Sentence Type] DictionaryBasedSentenceTypeDetector Preparation If STMT --> Use DBSTD otherwise SPA has succeeded --- .../DictionaryBasedSentenceTypeDetector.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java index dd3346da..2fc5ef4e 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/DictionaryBasedSentenceTypeDetector.java @@ -15,11 +15,19 @@ public class DictionaryBasedSentenceTypeDetector implements Analyzer{ public Interpretation analyze(Interpretation interpretation) { List tokens = interpretation.getTokens(); String[] posTags = interpretation.getPosTags(); - SentenceType sentenceType = determineSentenceType(tokens, posTags); - interpretation.setSentenceType(sentenceType); + + //Sentence Types shall be handled in Semantic Parser Analyzer. This is a fallback, in the event that SPA does not detect the sentence type + if(interpretation.getSentenceType().equals(SentenceType.STATEMENT)){ + SentenceType sentenceType = determineSentenceType(tokens, posTags); + interpretation.setSentenceType(sentenceType); + + } return interpretation; } + /** + * Fallback Sentence Type Detection, main Detector now in {@link SemanticParserAnalyzer} + */ private SentenceType determineSentenceType(List tokens, String[] posTags){ if (tokens != null && !tokens.isEmpty()) { String first = tokens.get(0).toLowerCase(); From 9fba873884c71341ac71f68625c3a0fa6a5f979e Mon Sep 17 00:00:00 2001 From: Joseph Birkner Date: Tue, 14 Aug 2018 14:17:07 +0200 Subject: [PATCH 081/147] Fixed main() in FullNLPAnalyzer --- .../nlp/sempre/corenlp/FullNLPAnalyzer.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java index aaed284d..9271afeb 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/FullNLPAnalyzer.java @@ -37,6 +37,7 @@ public class FullNLPAnalyzer extends InfoAnalyzer { public static class Options { @Option(gloss = "What CoreNLP annotators to run") public List annotators = Lists.newArrayList( + "tokenize", "tokenize", "ssplit", "truecase", @@ -80,6 +81,7 @@ public static void initModels() { Properties props = new Properties(); props.setProperty("annotators", Joiner.on(',').join(opts.annotators)); props.setProperty("coref.algorithm", "neural"); + //props.setProperty("openie.resolve_coref", "true"); props.setProperty("truecase.overwriteText", "true"); props.setProperty("ner.applyFineGrained", "false"); pipeline = new StanfordCoreNLP(props); @@ -216,7 +218,7 @@ public GeneralInfo getSent(LanguageInfo languageInfo, Annotation annotation) { // LogInfoToggle.logs("Keywords extracted: %s", genInfo.keywords.toString()); genInfo.sentiment_type = RNNCoreAnnotations.getPredictedClass(tree); genInfo.sentiment = sentence.get(SentimentCoreAnnotations.SentimentClass.class); -// LogInfoToggle.logs("Sentiment extracted: %s", genInfo.sentiment); + LogInfoToggle.logs("Sentiment extracted: %s", genInfo.sentiment); } return genInfo; } @@ -248,20 +250,23 @@ public List getKeywords(Tree tree){ // Test on example sentence. public static void main(String[] args) { - CoreNLPAnalyzer analyzer = new CoreNLPAnalyzer(); + FullNLPAnalyzer analyzer = new FullNLPAnalyzer(); while (true) { try { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Enter some text:"); String text = reader.readLine(); - LanguageInfo langInfo = analyzer.analyze(text); + CoreNLPInfo langInfo = analyzer.analyze(text); LogInfoToggle.begin_track("Analyzing \"%s\"", text); - LogInfoToggle.logs("tokens: %s", langInfo.tokens); - LogInfoToggle.logs("lemmaTokens: %s", langInfo.lemmaTokens); - LogInfoToggle.logs("posTags: %s", langInfo.posTags); - LogInfoToggle.logs("nerTags: %s", langInfo.nerTags); - LogInfoToggle.logs("nerValues: %s", langInfo.nerValues); - LogInfoToggle.logs("dependencyChildren: %s", langInfo.dependencyChildren); + LogInfoToggle.logs("tokens: %s", langInfo.lanInfo.tokens); + LogInfoToggle.logs("lemmaTokens: %s", langInfo.lanInfo.lemmaTokens); + LogInfoToggle.logs("posTags: %s", langInfo.lanInfo.posTags); + LogInfoToggle.logs("nerTags: %s", langInfo.lanInfo.nerTags); + LogInfoToggle.logs("nerValues: %s", langInfo.lanInfo.nerValues); + LogInfoToggle.logs("dependencyChildren: %s", langInfo.lanInfo.dependencyChildren); + LogInfoToggle.logs("keywords: %s", langInfo.senInfo.keywords); + LogInfoToggle.logs("sentiment: %s", langInfo.senInfo.sentiment); + LogInfoToggle.logs("relations: %s", langInfo.relInfo.relations); LogInfoToggle.end_track(); } catch (IOException e) { e.printStackTrace(); From a1edd286f6f68a5094e95f72e305efb5003ca53d Mon Sep 17 00:00:00 2001 From: mireu Date: Sat, 21 Jul 2018 12:46:33 +0200 Subject: [PATCH 082/147] Fixed a bug where the system would crash when no INPUT was selected. --- config.properties | 25 ++++++------- config.properties.orig | 85 ------------------------------------------ 2 files changed, 12 insertions(+), 98 deletions(-) delete mode 100755 config.properties.orig diff --git a/config.properties b/config.properties index 99c00c65..d1ff210c 100755 --- a/config.properties +++ b/config.properties @@ -1,4 +1,4 @@ -ROS_ENABLED: true +ROS_ENABLED: false ROS_MASTER_IP: 127.0.0.1 # available ROS_ACTIVE_PKG are @@ -13,19 +13,19 @@ ROS_MASTER_IP: 127.0.0.1 # roboy_nodered ROS_ACTIVE_PKGS: -# - roboy_gnlp -# - roboy_memory +# - roboy_gnlp +# - roboy_memory # - roboy_speech_synthesis # - roboy_speech_recognition # - roboy_face -- roboy_filters -- roboy_vision -- roboy_nodered +# - roboy_filters +# - roboy_vision +# - roboy_nodered # - roboy_test DEBUG: true DEMO_MODE: false -INFINITE_REPETITION: false +INFINITE_REPETITION: true # only single input is allowed, defaults to cmdline INPUT: cmdline @@ -37,6 +37,7 @@ INPUT: cmdline # multiple outputs are allowed, defaults to cmdline OUTPUTS: - cmdline +# - telegram # - ibm # - cerevoice # - freetts @@ -65,6 +66,7 @@ IBM_TTS_PASS: "" CONTEXT_GUI_ENABLED: false ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/scripts/action_client.py" +TELEGRAM_API_TOKENS_FILE: "" # Logging Levels @@ -72,16 +74,13 @@ ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/sc # Memory: java.util.logging # https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html -MEMORY_LOG_MODE: "INFO" +MEMORY_LOG_MODE: "WARNING" # Dialog: LOG4J 2 # https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html # https://logging.apache.org/log4j/2.x/manual/customloglevels.html -DIALOG_LOG_MODE: "INFO" +DIALOG_LOG_MODE: "WARN" # Parser/NLU: LogInfo # Supports all Log4J levels. See Documentation for more details -PARSER_LOG_MODE: "INFO" - -TELEGRAM_API_TOKENS_FILE: "" - +PARSER_LOG_MODE: "WARN" \ No newline at end of file diff --git a/config.properties.orig b/config.properties.orig deleted file mode 100755 index 25f29c47..00000000 --- a/config.properties.orig +++ /dev/null @@ -1,85 +0,0 @@ -ROS_ENABLED: false -ROS_MASTER_IP: 127.0.0.1 - -# available ROS_ACTIVE_PKG are -# roboy_gnlp -# roboy_memory -# roboy_speech_synthesis -# roboy_speech_recognition -# roboy_audio -# roboy_vision -# roboy_test -# roboy_filters - -ROS_ACTIVE_PKGS: -# - roboy_gnlp -# - roboy_memory -# - roboy_speech_synthesis -# - roboy_speech_recognition -# - roboy_face -# - roboy_filters -- roboy_test - -DEBUG: true -DEMO_MODE: false -INFINITE_REPETITION: true - -# only single input is allowed, defaults to cmdline -#INPUT: cmdline -#INPUT: cerevoice -#INPUT: udp -#INPUT: bing -INPUT: telegram - -# multiple outputs are allowed, defaults to cmdline -OUTPUTS: -# - cmdline -# - ibm -# - cerevoice -# - freetts -# - ibm -# - emotions -# - udp - - telegram - -UDP_IN_SOCKET: 55555 -UDP_OUT_SOCKET: 55556 -UDP_HOST_ADDRESS: 127.0.0.1 - -PARSER_PORT: 5000 -# PERSONALITY_FILE: "resources/personalityFiles/ExpoPersonality.json" - -#PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" -# PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" -# PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" -# PERSONALITY_FILE: "resources/personalityFiles/uzupis.json" - -IBM_TTS_USER: "" -IBM_TTS_PASS: "" - -CONTEXT_GUI_ENABLED: false -ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/scripts/action_client.py" - - - -# Logging Levels -# Each Logging Module has different levels. End users should use warn. Developers should use either info or debug/fine. - -# Memory: java.util.logging -# https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html -MEMORY_LOG_MODE: "WARNING" - -# Dialog: LOG4J 2 -# https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html -# https://logging.apache.org/log4j/2.x/manual/customloglevels.html -DIALOG_LOG_MODE: "WARN" - -# Parser/NLU: LogInfo -# Supports all Log4J levels. See Documentation for more details -<<<<<<< Updated upstream -PARSER_LOG_MODE: "WARN" -======= -PARSER_LOG_MODE: "INFO" -TELEGRAM_API_TOKENS_FILE: "/Users/Apple/botboy/tokens.json" ->>>>>>> Stashed changes From 3cc4765a192e5172e7fc89821cd33f32da866e1f Mon Sep 17 00:00:00 2001 From: SezerCan Date: Thu, 2 Aug 2018 11:55:27 +0200 Subject: [PATCH 083/147] Emotion support added to CommandLineOutput. State's String emotion variable changed as RoboyEmotion emotion. Some emotions added to RoboyEmotion. DoYouKnowMath tutorial is changed due to new emotion usage. Documentation updated. --- dialog/src/main/java/roboy/dialog/states/definitions/State.java | 2 +- dialog/src/main/java/roboy/io/CommandLineOutput.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dialog/src/main/java/roboy/dialog/states/definitions/State.java b/dialog/src/main/java/roboy/dialog/states/definitions/State.java index 31263cc7..e20318a5 100644 --- a/dialog/src/main/java/roboy/dialog/states/definitions/State.java +++ b/dialog/src/main/java/roboy/dialog/states/definitions/State.java @@ -81,7 +81,6 @@ private Output(OutputType type, Interpretation interpretation) { this.type = type; this.interpretation = interpretation; this.segue = null; - this.emotion = null; if(interpretation != null){ this.emotion = interpretation.getEmotion(); } @@ -368,6 +367,7 @@ public final String getOptionalPersFileInfo(String key) { */ public abstract Output act(); + /** * Defines how to react to an input. This is usually the answer to the incoming question or some other statement. * If this state can't react, it can return 'null' to trigger the fallback state for the answer. diff --git a/dialog/src/main/java/roboy/io/CommandLineOutput.java b/dialog/src/main/java/roboy/io/CommandLineOutput.java index edcd14bd..7e6c6e16 100755 --- a/dialog/src/main/java/roboy/io/CommandLineOutput.java +++ b/dialog/src/main/java/roboy/io/CommandLineOutput.java @@ -26,6 +26,7 @@ public void act(List actions) { // emotion.act(new EmotionAction("speak", duration)); System.out.println("[Roboy]: " + ((SpeechAction) a).getText()); }else if (emotionFlag == true && a instanceof EmotionAction) { + System.out.println("[RoboyEmotion]: " + ((EmotionAction) a).getState()); } } From 1a771e4880c6a7b3565a095749b75e1af55f7219 Mon Sep 17 00:00:00 2001 From: SezerCan Date: Thu, 9 Aug 2018 13:56:21 +0200 Subject: [PATCH 084/147] Flag added to manage emotion output for CommandLineOutput. --- dialog/src/main/java/roboy/io/CommandLineOutput.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dialog/src/main/java/roboy/io/CommandLineOutput.java b/dialog/src/main/java/roboy/io/CommandLineOutput.java index 7e6c6e16..1b633ad9 100755 --- a/dialog/src/main/java/roboy/io/CommandLineOutput.java +++ b/dialog/src/main/java/roboy/io/CommandLineOutput.java @@ -31,4 +31,5 @@ public void act(List actions) { } } } + } From 172f83b3878553e013a4af6f149224771cb6c969 Mon Sep 17 00:00:00 2001 From: mireu Date: Mon, 13 Aug 2018 17:24:50 +0200 Subject: [PATCH 085/147] Parallelized SparqlExecutor --- .../nlp/sempre/roboy/SparqlExecutor.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/SparqlExecutor.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/SparqlExecutor.java index 16c6e78c..59726202 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/SparqlExecutor.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/SparqlExecutor.java @@ -119,6 +119,7 @@ public ServerResponse makeRequest(String queryStr, String endpointUrl) { while ((line = reader.readLine()) != null) buf.append(line); + reader.close(); // Check for blatant errors. String result = buf.toString(); if (result.length() == 0) @@ -239,7 +240,7 @@ public Response execute(Formula formula, ContextValue context) { dbInfo.opts.setDefault(formula.toString()); return execute(formula, 0, opts.maxResults); } - public synchronized Response execute(Formula formula, int offset, int maxResults) { + public Response execute(Formula formula, int offset, int maxResults) { if (ConfigManager.DEBUG >= 7) LogInfoToggle.logs("SparqlExecutor.execute: %s", formula); String prefix = "exec-"; @@ -265,16 +266,18 @@ public synchronized Response execute(Formula formula, int offset, int maxResults //// Record statistics // Update/print sparql stats - if (!serverResponse.cached) { - queryStats.timeFig.add(serverResponse.timeMs); - if (serverResponse.error != null) { - MapUtils.incr(queryStats.errors, serverResponse.error.type, 1); - if (serverResponse.beginTrack && ConfigManager.DEBUG >= 7) - LogInfoToggle.logs("Error: %s", serverResponse.error); - } - if (serverResponse.beginTrack && ConfigManager.DEBUG >= 7) { - LogInfoToggle.logs("time: %s", queryStats.timeFig); - LogInfoToggle.logs("errors: %s", queryStats.errors); + synchronized (queryStats) { + if (!serverResponse.cached) { + queryStats.timeFig.add(serverResponse.timeMs); + if (serverResponse.error != null) { + MapUtils.incr(queryStats.errors, serverResponse.error.type, 1); + if (serverResponse.beginTrack && ConfigManager.DEBUG >= 7) + LogInfoToggle.logs("Error: %s", serverResponse.error); + } + if (serverResponse.beginTrack && ConfigManager.DEBUG >= 7) { + LogInfoToggle.logs("time: %s", queryStats.timeFig); + LogInfoToggle.logs("errors: %s", queryStats.errors); + } } } From b6307fc6c55657a1d482540309fb3af0c5c64227 Mon Sep 17 00:00:00 2001 From: mireu Date: Mon, 13 Aug 2018 17:44:00 +0200 Subject: [PATCH 086/147] Parallelized DbEntitySearcher --- .../freebase/index/FbEntitySearcher.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java index 3c8f98b8..47051d1d 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java @@ -25,10 +25,18 @@ public class FbEntitySearcher { - private final QueryParser queryParser; private final IndexSearcher indexSearcher; private int numOfDocs = 50; private String searchStrategy; + private QueryParser queryParser; + + private synchronized QueryParser freshQueryParser(){//needed since queryparser is not threadsafe and queryparser is very lightweight + return new QueryParser( + Version.LUCENE_44, + FbIndexField.TEXT.fieldName(), + this.searchStrategy.equals("exact") ? new KeywordAnalyzer() : new StandardAnalyzer(Version.LUCENE_44)); + } + public FbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy) throws IOException { @@ -37,10 +45,7 @@ public FbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy throw new RuntimeException("Bad searching strategy: " + searchingStrategy); this.searchStrategy = searchingStrategy; - queryParser = new QueryParser( - Version.LUCENE_44, - FbIndexField.TEXT.fieldName(), - searchingStrategy.equals("exact") ? new KeywordAnalyzer() : new StandardAnalyzer(Version.LUCENE_44)); + queryParser = freshQueryParser(); LogInfoToggle.log("Opening index dir: " + indexDir); IndexReader indexReader = DirectoryReader.open(SimpleFSDirectory.open(new File(indexDir))); indexSearcher = new IndexSearcher(indexReader); @@ -50,7 +55,7 @@ public FbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy LogInfoToggle.end_track(); } - public synchronized List searchDocs(String question) throws IOException, ParseException { + public List searchDocs(String question) throws IOException, ParseException { List res = new LinkedList(); if (searchStrategy.equals("exact")) @@ -67,7 +72,11 @@ public synchronized List searchDocs(String question) throws IOExceptio } private ScoreDoc[] getHits(String question) throws IOException, ParseException { - Query luceneQuery = queryParser.parse(question); + Query luceneQuery; + synchronized (queryParser) { + luceneQuery = queryParser.parse(question); + queryParser = freshQueryParser(); + } ScoreDoc[] hits = indexSearcher.search(luceneQuery, numOfDocs).scoreDocs; return hits; } From c5640f858a04e939d14bee34a078876caa055bdc Mon Sep 17 00:00:00 2001 From: mireu Date: Mon, 13 Aug 2018 17:53:46 +0200 Subject: [PATCH 087/147] Parallelized FbEntitySearcher --- .../sempre/roboy/index/DbEntitySearcher.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java index 19e8bd52..c0cdb06a 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java @@ -25,10 +25,17 @@ public class DbEntitySearcher { - private final QueryParser queryParser; private final IndexSearcher indexSearcher; private int numOfDocs = 50; private String searchStrategy; + private QueryParser queryParser; + + private synchronized QueryParser freshQueryParser(){//needed since queryparser is not threadsafe and queryparser is very lightweight + return new QueryParser( + Version.LUCENE_44, + DbIndexField.TEXT.fieldName(), + searchStrategy.equals("exact") ? new KeywordAnalyzer() : new StandardAnalyzer(Version.LUCENE_44)); + } public DbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy) throws IOException { @@ -37,10 +44,7 @@ public DbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy throw new RuntimeException("Bad searching strategy: " + searchingStrategy); this.searchStrategy = searchingStrategy; - queryParser = new QueryParser( - Version.LUCENE_44, - DbIndexField.TEXT.fieldName(), - searchingStrategy.equals("exact") ? new KeywordAnalyzer() : new StandardAnalyzer(Version.LUCENE_44)); + queryParser = freshQueryParser(); LogInfoToggle.log("Opening index dir: " + indexDir); IndexReader indexReader = DirectoryReader.open(SimpleFSDirectory.open(new File(indexDir))); indexSearcher = new IndexSearcher(indexReader); @@ -50,7 +54,7 @@ public DbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy LogInfoToggle.end_track(); } - public synchronized List searchDocs(String question) throws IOException, ParseException { + public List searchDocs(String question) throws IOException, ParseException { List res = new LinkedList(); if (searchStrategy.equals("exact")) @@ -67,7 +71,11 @@ public synchronized List searchDocs(String question) throws IOExceptio } private ScoreDoc[] getHits(String question) throws IOException, ParseException { - Query luceneQuery = queryParser.parse(question); + Query luceneQuery; + synchronized (queryParser) { + luceneQuery = queryParser.parse(question); + queryParser = freshQueryParser(); + } ScoreDoc[] hits = indexSearcher.search(luceneQuery, numOfDocs).scoreDocs; return hits; } From ffbe1022c434654d3ad5d42d5eb63a5718045c39 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 20:58:06 +0200 Subject: [PATCH 088/147] Merge branch 'hack-jason-demo' into origin/de-nlu-upgrades --- .../stanford/nlp/sempre/roboy/api/Movie.java | 39 ++++++++++++++++ .../nlp/sempre/roboy/api/Translate.java | 41 +++++++++++++++++ .../nlp/sempre/roboy/api/Weather.java | 46 +++++++++++++++++++ .../stanford/nlp/sempre/roboy/api/apiKeys.yml | 3 ++ .../nlp/sempre/roboy/api/keyGetter.java | 22 +++++++++ 5 files changed, 151 insertions(+) create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java new file mode 100644 index 00000000..301583fc --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java @@ -0,0 +1,39 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Random; + +public class Movie{ + static String KEY = keyGetter.getKey("moviekey"); + static int randomInt = new Random().nextInt(20); + + + public static String getData(String... args) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) + .getAsJsonArray("results") + .get(randomInt).getAsJsonObject().get(args[0]); +// System.out.println(jsonObject); + return result.toString(); + } + + public static void main(String[] args)throws Exception{ + getData("title");getData("overview"); + } +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java new file mode 100644 index 00000000..8eb2afec --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java @@ -0,0 +1,41 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.github.jsonldjava.utils.Obj; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Translate { + static final String KEY = keyGetter.getKey("translatekey"); + + public static String getData(String... args) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(APIify(args[0], args[1])); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); +// System.out.println(jsonObject); + return result.toString(); + } + + private static String APIify(String text, String targetLang){ + String s = String.format("https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s", KEY, text.replace(" ", "%20"), targetLang); +// System.out.println(s); + return s; + } + + public static void main(String[] args) throws Exception{ + System.out.println(getData("cheese is the best vegetable", "de")); + } +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java new file mode 100644 index 00000000..9bfff6a2 --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java @@ -0,0 +1,46 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Weather { + final static String KEY = keyGetter.getKey("weatherkey"); + public static String getData(String... args) throws Exception{ + try { + return getHTML(args[0]); + }catch (Exception e) {return null;} + } + public static String getHTML(String country) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("http://api.openweathermap.org/data/2.5/weather?q=%s&APPID=%s", country, KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + JsonObject jsonObject = (((JsonObject) new JsonParser().parse(result.toString())).get("weather").getAsJsonArray()).get(0).getAsJsonObject(); +// System.out.println(jsonObject.get("main")); + return jsonObject.get("main").getAsString(); + } + + public static void main(String[] args) throws Exception + { + //Find Munich + System.out.println(getData("munich")); + } + + +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml new file mode 100644 index 00000000..1cef27aa --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml @@ -0,0 +1,3 @@ +moviekey: xxxxxxx +translatekey: xxxxxxx +weatherkey: xxxxxx \ No newline at end of file diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java new file mode 100644 index 00000000..0b42b252 --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java @@ -0,0 +1,22 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import org.apache.commons.configuration2.YAMLConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; + +import java.io.FileNotFoundException; +import java.io.FileReader; + +public class keyGetter { + static YAMLConfiguration yamlConfiguration = new YAMLConfiguration(); + static String getKey(String key){ + try { + yamlConfiguration.read(new FileReader("nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml")); + } catch (ConfigurationException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return yamlConfiguration.getString(key); + } + +} From ae71bc79829a856d6f2ec0551b94e55f44961d90 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 20:59:30 +0200 Subject: [PATCH 089/147] Ignore YML --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index d7d759b0..742d1b5f 100644 --- a/.gitignore +++ b/.gitignore @@ -72,3 +72,5 @@ community-server/data-backup *.iml nlu/parser/target/ + +nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml From abc74cc573b6eea8530f302da7ca4bedc6fcbaf9 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:34:15 +0200 Subject: [PATCH 090/147] Updated API Stuff --- .../stanford/nlp/sempre/roboy/api/Movie.java | 6 +- .../nlp/sempre/roboy/api/Translate.java | 108 +++++++++++++++++- .../nlp/sempre/roboy/api/Weather.java | 6 +- 3 files changed, 109 insertions(+), 11 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java index 301583fc..bb6dde97 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java @@ -13,8 +13,8 @@ public class Movie{ static String KEY = keyGetter.getKey("moviekey"); static int randomInt = new Random().nextInt(20); - - public static String getData(String... args) throws Exception { + //FIELD TITLE or OVERVIEW + public static String getData(String field) throws Exception { StringBuilder result = new StringBuilder(); URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); @@ -28,7 +28,7 @@ public static String getData(String... args) throws Exception { Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) .getAsJsonArray("results") - .get(randomInt).getAsJsonObject().get(args[0]); + .get(randomInt).getAsJsonObject().get(field); // System.out.println(jsonObject); return result.toString(); } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java index 8eb2afec..677b1d5d 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java @@ -12,9 +12,11 @@ public class Translate { static final String KEY = keyGetter.getKey("translatekey"); - public static String getData(String... args) throws Exception { + + //Language: Either Language code such as DE or language name. Text is the text to translate + public static String getData(String text, String language) throws Exception { StringBuilder result = new StringBuilder(); - URL url = new URL(APIify(args[0], args[1])); + URL url = new URL(APIify(text, handleLanguage(language))); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); @@ -26,7 +28,105 @@ public static String getData(String... args) throws Exception { Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); // System.out.println(jsonObject); - return result.toString(); + return jsonObject.toString(); + } + + private static String handleLanguage(String language) { + switch (language.toLowerCase()){ + case "azerbaijan": return "az"; + case "malayalam": return "ml"; + case "albanian": return "sq"; + case "maltese": return "mt"; + case "amharic": return "am"; + case "macedonian": return "mk"; + case "english": return "en"; + case "maori": return "mi"; + case "arabic": return "ar"; + case "marathi": return "mr"; + case "armenian": return "hy"; + case "mari": return "mhr"; + case "afrikaans": return "af"; + case "mongolian": return "mn"; + case "basque": return "eu"; + case "german": return "de"; + case "bashkir": return "ba"; + case "nepali": return "ne"; + case "belarusian": return "be"; + case "norwegian": return "no"; + case "bengali": return "bn"; + case "punjabi": return "pa"; + case "burmese": return "my"; + case "papiamento": return "pap"; + case "bulgarian": return "bg"; + case "persian": return "fa"; + case "bosnian": return "bs"; + case "polish": return "pl"; + case "welsh": return "cy"; + case "portuguese": return "pt"; + case "hungarian": return "hu"; + case "romanian": return "ro"; + case "vietnamese": return "vi"; + case "russian": return "ru"; + case "haitian": return "ht"; + case "cebuano": return "ceb"; + case "galician": return "gl"; + case "serbian": return "sr"; + case "dutch": return "nl"; + case "sinhala": return "si"; + case "slovakian": return "sk"; + case "greek": return "el"; + case "slovenian": return "sl"; + case "georgian": return "ka"; + case "swahili": return "sw"; + case "gujarati": return "gu"; + case "sundanese": return "su"; + case "danish": return "da"; + case "tajik": return "tg"; + case "hebrew": return "he"; + case "thai": return "th"; + case "yiddish": return "yi"; + case "tagalog": return "tl"; + case "indonesian": return "id"; + case "tamil": return "ta"; + case "irish": return "ga"; + case "tatar": return "tt"; + case "italian": return "it"; + case "telugu": return "te"; + case "icelandic": return "is"; + case "turkish": return "tr"; + case "spanish": return "es"; + case "udmurt": return "udm"; + case "kazakh": return "kk"; + case "uzbek": return "uz"; + case "kannada": return "kn"; + case "ukrainian": return "uk"; + case "catalan": return "ca"; + case "urdu": return "ur"; + case "kyrgyz": return "ky"; + case "finnish": return "fi"; + case "chinese": return "zh"; + case "french": return "fr"; + case "korean": return "ko"; + case "hindi": return "hi"; + case "xhosa": return "xh"; + case "croatian": return "hr"; + case "khmer": return "km"; + case "czech": return "cs"; + case "laotian": return "lo"; + case "swedish": return "sv"; + case "latin": return "la"; + case "scottish": return "gd"; + case "latvian": return "lv"; + case "estonian": return "et"; + case "lithuanian": return "lt"; + case "esperanto": return "eo"; + case "luxembourgish": return "lb"; + case "javanese": return "jv"; + case "malagasy": return "mg"; + case "japanese": return "ja"; + case "malay": return "ms"; + default: return language; + } } private static String APIify(String text, String targetLang){ @@ -36,6 +136,6 @@ private static String APIify(String text, String targetLang){ } public static void main(String[] args) throws Exception{ - System.out.println(getData("cheese is the best vegetable", "de")); + System.out.println(getData("cheese is the best vegetable", "german")); } } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java index 9bfff6a2..05dc9c73 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java @@ -14,10 +14,8 @@ public class Weather { final static String KEY = keyGetter.getKey("weatherkey"); - public static String getData(String... args) throws Exception{ - try { - return getHTML(args[0]); - }catch (Exception e) {return null;} + public static String getData(String country) throws Exception{ + return getHTML(country); } public static String getHTML(String country) throws Exception { StringBuilder result = new StringBuilder(); From 84f81ae8e6cc31844be3f0e22f40778a7465d8db Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:44:55 +0200 Subject: [PATCH 091/147] Moving --- .../src/main/java/roboy/util}/api/Movie.java | 9 +++++---- .../src/main/java/roboy/util}/api/Translate.java | 3 +-- .../src/main/java/roboy/util}/api/Weather.java | 6 +----- dialog/src/main/java/roboy/util/api/apiKeys.yml | 3 +++ .../src/main/java/roboy/util}/api/keyGetter.java | 4 ++-- .../java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml | 3 --- 6 files changed, 12 insertions(+), 16 deletions(-) rename {nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy => dialog/src/main/java/roboy/util}/api/Movie.java (81%) rename {nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy => dialog/src/main/java/roboy/util}/api/Translate.java (98%) rename {nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy => dialog/src/main/java/roboy/util}/api/Weather.java (89%) create mode 100644 dialog/src/main/java/roboy/util/api/apiKeys.yml rename {nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy => dialog/src/main/java/roboy/util}/api/keyGetter.java (77%) delete mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/dialog/src/main/java/roboy/util/api/Movie.java similarity index 81% rename from nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java rename to dialog/src/main/java/roboy/util/api/Movie.java index bb6dde97..90e57178 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java +++ b/dialog/src/main/java/roboy/util/api/Movie.java @@ -1,5 +1,6 @@ -package edu.stanford.nlp.sempre.roboy.api; +package roboy.util.api; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -26,14 +27,14 @@ public static String getData(String field) throws Exception { } rd.close(); - Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) + JsonElement jsonElement = ((JsonObject) new JsonParser().parse(result.toString())) .getAsJsonArray("results") .get(randomInt).getAsJsonObject().get(field); // System.out.println(jsonObject); - return result.toString(); + return jsonElement.getAsString(); } public static void main(String[] args)throws Exception{ - getData("title");getData("overview"); + System.out.println(getData("title")+":\t"+getData("overview")); } } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/dialog/src/main/java/roboy/util/api/Translate.java similarity index 98% rename from nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java rename to dialog/src/main/java/roboy/util/api/Translate.java index 677b1d5d..129220e4 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java +++ b/dialog/src/main/java/roboy/util/api/Translate.java @@ -1,6 +1,5 @@ -package edu.stanford.nlp.sempre.roboy.api; +package roboy.util.api; -import com.github.jsonldjava.utils.Obj; import com.google.gson.JsonObject; import com.google.gson.JsonParser; diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/dialog/src/main/java/roboy/util/api/Weather.java similarity index 89% rename from nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java rename to dialog/src/main/java/roboy/util/api/Weather.java index 05dc9c73..f04d48fb 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java +++ b/dialog/src/main/java/roboy/util/api/Weather.java @@ -1,14 +1,10 @@ -package edu.stanford.nlp.sempre.roboy.api; +package roboy.util.api; -import com.google.gson.Gson; -import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; -import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/dialog/src/main/java/roboy/util/api/apiKeys.yml new file mode 100644 index 00000000..22207938 --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/apiKeys.yml @@ -0,0 +1,3 @@ +moviekey: xxxxxxxxxxxxxxxxxxxxxxxx +translatekey: xxxxxxxxxxxxxxxxxxxxxxxx +weatherkey: xxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java b/dialog/src/main/java/roboy/util/api/keyGetter.java similarity index 77% rename from nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java rename to dialog/src/main/java/roboy/util/api/keyGetter.java index 0b42b252..b91fc487 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java +++ b/dialog/src/main/java/roboy/util/api/keyGetter.java @@ -1,4 +1,4 @@ -package edu.stanford.nlp.sempre.roboy.api; +package roboy.util.api; import org.apache.commons.configuration2.YAMLConfiguration; import org.apache.commons.configuration2.ex.ConfigurationException; @@ -10,7 +10,7 @@ public class keyGetter { static YAMLConfiguration yamlConfiguration = new YAMLConfiguration(); static String getKey(String key){ try { - yamlConfiguration.read(new FileReader("nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml")); + yamlConfiguration.read(new FileReader("dialog/src/main/java/roboy/util/api/apiKeys.yml")); } catch (ConfigurationException e) { e.printStackTrace(); } catch (FileNotFoundException e) { diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml deleted file mode 100644 index 1cef27aa..00000000 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml +++ /dev/null @@ -1,3 +0,0 @@ -moviekey: xxxxxxx -translatekey: xxxxxxx -weatherkey: xxxxxx \ No newline at end of file From 51f5895083964cb9fa0e74c35dd459cdc8cb5b17 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:45:35 +0200 Subject: [PATCH 092/147] gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 742d1b5f..65fbe33f 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,5 @@ community-server/data-backup nlu/parser/target/ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml + +dialog/src/main/java/roboy/util/api/apiKeys\.yml From 24993cd3546b769ecdb269c33a999b5b892814a0 Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Wed, 15 Aug 2018 02:58:10 +0200 Subject: [PATCH 093/147] Like, hypersexy space alien shit, or something --- config.properties | 7 +- .../roboy/dialog/ConversationManager.java | 3 +- .../devoStates/QuestionRoboyQAState.java | 356 ++++++++++++++++++ .../states/expoStates/RoboyQAState.java | 1 - .../QuestionAnsweringState.java | 1 - .../main/java/roboy/linguistics/Triple.java | 13 +- .../sentenceanalysis/Interpretation.java | 49 +++ .../sentenceanalysis/Postprocessor.java | 14 + .../personalityFiles/DevoPersonality.json | 93 +++++ 9 files changed, 528 insertions(+), 9 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java create mode 100644 dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java create mode 100644 resources/personalityFiles/DevoPersonality.json diff --git a/config.properties b/config.properties index d1ff210c..61f14f5d 100755 --- a/config.properties +++ b/config.properties @@ -32,7 +32,7 @@ INPUT: cmdline #INPUT: cerevoice #INPUT: udp #INPUT: bing -# INPUT: telegram +#INPUT: telegram # multiple outputs are allowed, defaults to cmdline OUTPUTS: @@ -59,6 +59,7 @@ PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/uzupis.json" +#PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" @@ -79,8 +80,8 @@ MEMORY_LOG_MODE: "WARNING" # Dialog: LOG4J 2 # https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html # https://logging.apache.org/log4j/2.x/manual/customloglevels.html -DIALOG_LOG_MODE: "WARN" +DIALOG_LOG_MODE: "DEBUG" # Parser/NLU: LogInfo # Supports all Log4J levels. See Documentation for more details -PARSER_LOG_MODE: "WARN" \ No newline at end of file +PARSER_LOG_MODE: "DEBUG" \ No newline at end of file diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index 394afd74..47799980 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -85,7 +85,8 @@ public static void main(String[] args) throws IOException { analyzers.add(new EmotionAnalyzer()); - //analyzers.add(new ProfanityAnalyzer()); + analyzers.add(new ProfanityAnalyzer()); + analyzers.add(new Postprocessor()); //I/O specific core behaviour diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java new file mode 100644 index 00000000..745995eb --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -0,0 +1,356 @@ +package roboy.dialog.states.devoStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.states.definitions.ExpoState; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState; +import roboy.linguistics.Linguistics; +import roboy.linguistics.Linguistics.SemanticRole; +import roboy.linguistics.Triple; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.Neo4jProperty; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; +import roboy.talk.PhraseCollection; +import roboy.util.Agedater; +import roboy.util.Pair; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.*; + +import static roboy.memory.Neo4jProperty.full_name; +import static roboy.memory.Neo4jProperty.name; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; + +/** + * QuestionAnsweringState + * Roboy Question Answering State + * + * The parser: + * - provides triples generated from the question + * - adds the answer to the question if there is an answer in DBpedia + * - tells a specifying followup question if the interlocutor's question was ambiguous + * + * This state: + * - checks if interlocutor wants to play a game + * - returns the answer if provided by the parser + * - asks the specifying followup question if provided by the parser + * - - if answered with yes --> will use the parser again to get the answer to the original question + * - if answered with no --> will use a segue to avoid answer + * - tries to query memory if there is no answer to the question + * - queries the fallback if memory fails to answer as well + * + * + * QuestionAnsweringState interface: + * 1) Fallback is required. + * 2) Outgoing transitions that have to be defined: + * - finishedQuestionAnswering: following state if this state if finished with answering questions + * 3) No parameters are used. + */ +public class QuestionRoboyQAState extends ExpoState { + private final Logger LOGGER = LogManager.getLogger(); + + private final static String TRANSITION_FINISHED_ANSWERING = "finishedQuestionAnswering"; + private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; + private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; + private final static int MAX_NUM_OF_QUESTIONS = 5; + private int questionsAnswered = 0; + + private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; + private final static RandomList answerStartingPhrases = PhraseCollection.QUESTION_ANSWERING_START; + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + + private boolean askingSpecifyingQuestion = false; + private String answerAfterUnspecifiedQuestion = ""; // the answer to use if specifying question is answered with YES + private boolean userWantsGame = false; + + private QAJsonParser infoValues; + + public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info("The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); + } + + @Override + public Output act() { + if (questionsAnswered > 0) { + return Output.say(reenteringPhrases.getRandomElement()); + } + return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + } + + @Override + public Output react(Interpretation input) { + return reactToQuestion(input); + } + + private Output reactToQuestion(Interpretation input) { + + askingSpecifyingQuestion = false; + questionsAnswered++; + + if (input.getTokens() != null && !(input.getTokens().contains("you") || input.getTokens().contains("your"))) { + Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); + if (parseOutcome == null) { + LOGGER.error("Invalid parser outcome!"); + return Output.say("Invalid parser outcome!"); + } + + if (parseOutcome == Linguistics.ParsingOutcome.SUCCESS) { + if (input.getAnswer() != null) { + // tell the answer, that was provided by the parser + return Output.say(answerStartingPhrases.getRandomElement() + " " + input.getAnswer()); + } + } + } + + // from here we know that dummyParserResult.equals("FAILURE") + return useMemoryOrFallback(input); + } + + @Override + public State getNextState() { + + if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state + return this; + + } else if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + return getTransition(TRANSITION_FINISHED_ANSWERING); + + } else if (Math.random() < 0.5) { // loop back to previous states with probability 0.5 + + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + Neo4jRelationship[] predicates = {FROM, HAS_HOBBY, WORK_FOR, STUDY_AT}; + Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(predicates); + + if (availability == SOME_AVAILABLE) { + return (Math.random() < 0.3) ? getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON) : getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else if (availability == NONE_AVAILABLE) { + return getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else { + if (!isIntentsHistoryComplete(predicates)) { + return getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON); + } else { + return this; + } + } + } else { // stay in this state + return this; + } + + } + + private Output useMemoryOrFallback(Interpretation input) { + try { + if (input.getPas() != null || input.getTriples() != null) { + Output memoryAnswer = answerFromMemory(input); + if (memoryAnswer != null) return memoryAnswer; + } + } catch (Exception e) { + LOGGER.warn(e.getMessage()); + } + + return Output.useFallback(); + } + + private Output answerFromMemory(Interpretation input) { + + // try to use memory to answer + Roboy roboy = new Roboy(getMemory()); + + //String answer = String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), inferMemoryAnswer(input, roboy)); + String answer = String.format("%s", inferMemoryAnswer(input, roboy)); + if (answer.equals("")) { + return Output.useFallback(); + } + return Output.say(answer); + } + + private String inferMemoryAnswer(Interpretation input, Roboy roboy) { + + String answer = ""; + Map pas = input.getPas(); + List triples = input.getTriples(); + + if (pas != null) { + return inferPasAnswer(pas, roboy); + } + + if (triples != null) { + return inferTripleAnswer(triples, roboy); + } + + if (input.getObjAnswer() != null) { + String objAnswer = input.getObjAnswer().toLowerCase(); + if (!objAnswer.equals("")) { + LOGGER.info("OBJ_ANSWER: " + objAnswer); + Neo4jRelationship predicate = inferPredicateFromObjectAnswer(objAnswer); + if (predicate != null) { + answer = extractNodeNameForPredicate(predicate, roboy); + } + } else { + LOGGER.warn("OBJ_ANSWER is empty"); + } + } + + return answer; + } + + private String inferPasAnswer(Map pas, Roboy roboy) { + String answer = ""; + if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { + answer = extractAge(roboy); + // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bweather\\b.*"))) { + // // -> Weather API + // } else if (matchPas(pas, new Pair(SemanticRole.AGENT, ".*\\bmovie.*"))) { + // // -> Movie API + // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.MANNER, "how"), new Pair(SemanticRole.PREDICATE, "say"), new Pair(SemanticRole.AGENT, "you")) || + // matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.PREDICATE, "is"), new Pair(SemanticRole.AGENT, "what"))) { + // // translate(*,**) + } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { + answer = Math.random() > .5 ? + extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : + extractNodeNameForPredicate(Neo4jRelationship.MEMBER_OF, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { + answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { + answer = "Yo moma says I am a good boy!"; + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "who"))) { + if (matchPas(pas, new Pair(SemanticRole.PATIENT, "you"))) { + answer = extractNodeNameForPredicate(Neo4jProperty.full_name, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\b(father|dad)\\b.*"))) { + answer = extractNodeNameForPredicate(Neo4jRelationship.CHILD_OF, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\b(sibling|brother)\\b.*"))){ + answer = extractNodeNameForPredicate(Neo4jRelationship.SIBLING_OF, roboy); + } + } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "do|like"), new Pair(SemanticRole.AGENT, "you"))){ + double prob = Math.random(); + if (prob < .3) { + answer = extractNodeNameForPredicate(Neo4jProperty.abilities, roboy); + } else if(prob < .7) { + answer = extractNodeNameForPredicate(Neo4jRelationship.HAS_HOBBY, roboy); + } else { + answer = extractNodeNameForPredicate(Neo4jProperty.skills, roboy); + } + } + + return answer; + } + + private String inferTripleAnswer(List triples, Roboy roboy) { + String answer = ""; + // else if {OBJ: *} -> query * -> I'm sure I know a typeof(*) called *! (Where does he live? :)) + // + // if * in Neo4jRelationship.FRIEND_OF + return answer; + } + + private Neo4jRelationship inferPredicateFromObjectAnswer(String objectAnswer) { + if (objectAnswer.contains("hobb")) { + return Neo4jRelationship.HAS_HOBBY; + } else if (objectAnswer.contains("member")) { + return Neo4jRelationship.MEMBER_OF; + } else if (objectAnswer.contains("friend")) { + return Neo4jRelationship.FRIEND_OF; + } else if (objectAnswer.contains("where") || + objectAnswer.contains("city") || + objectAnswer.contains("place") || + objectAnswer.contains("country") || + objectAnswer.contains("live") || + objectAnswer.contains("life")) { + return Neo4jRelationship.LIVE_IN; + } else if (objectAnswer.contains("from") || + objectAnswer.contains("born")) { + return Neo4jRelationship.FROM; + } else if (objectAnswer.contains("child") || + objectAnswer.contains("father") || + objectAnswer.contains("dad") || + objectAnswer.contains("parent")) { + return Neo4jRelationship.CHILD_OF; + } else if (objectAnswer.contains("brother") || + objectAnswer.contains("family") || + objectAnswer.contains("relativ")) { + return Neo4jRelationship.SIBLING_OF; + } + return null; + } + + private String extractNodeNameForPredicate(Neo4jRelationship predicate, Roboy roboy) { + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + return String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + return null; + } + + private String extractNodeNameForPredicate(Neo4jProperty predicate, Roboy roboy) { + String property = roboy.getProperty(predicate).toString(); + if (property != null) { + return String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), property); + } + return null; + } + + private String extractAge(Roboy roboy) { + HashMap ages = new Agedater().determineAge(roboy.getProperty(Neo4jProperty.birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + return String.format(infoValues.getSuccessAnswers(Neo4jProperty.age).getRandomElement(), retrievedAge); + } + + private boolean matchPas(Map pas, Pair... matchCriteria) { + if (pas == null) + return false; + boolean allCriteriaSatisfied = true; + for (Pair criterion : matchCriteria) { + if (!pas.containsKey(criterion.getKey()) || + !pas.get(criterion.getKey()).matches(criterion.getValue())) { + allCriteriaSatisfied = false; + break; + } + } + return allCriteriaSatisfied; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(TRANSITION_FINISHED_ANSWERING, TRANSITION_LOOP_TO_NEW_PERSON, TRANSITION_LOOP_TO_KNOWN_PERSON); + } + + @Override + public boolean isFallbackRequired() { + return true; + } + + private boolean isIntentsHistoryComplete(Neo4jRelationship[] predicates) { + boolean isComplete = true; + for (Neo4jRelationship predicate : predicates) { + if (!getContext().DIALOG_INTENTS.contains(new IntentValue(PersonalInformationFollowUpState.INTENTS_HISTORY_ID, predicate))) { + isComplete = false; + } + } + return isComplete; + } +} \ No newline at end of file diff --git a/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java index d6820cd9..f4f28d11 100644 --- a/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/expoStates/RoboyQAState.java @@ -2,7 +2,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import roboy.context.Context; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.dialog.states.definitions.ExpoState; diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java index 7f50d938..501d72fb 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java @@ -2,7 +2,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import roboy.context.Context; import roboy.context.contextObjects.IntentValue; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; diff --git a/dialog/src/main/java/roboy/linguistics/Triple.java b/dialog/src/main/java/roboy/linguistics/Triple.java index 7dc04e7b..a94901d6 100755 --- a/dialog/src/main/java/roboy/linguistics/Triple.java +++ b/dialog/src/main/java/roboy/linguistics/Triple.java @@ -17,12 +17,19 @@ public Triple(String subject, String predicate, String object){ this.object = object; } + public Triple toLowerCase() { + return new Triple( + this.subject != null ? this.subject.toLowerCase() : null, + this.predicate != null ? this.predicate.toLowerCase() : null, + this.object != null ? this.object.toLowerCase() : null); + } + @Override public String toString() { return "Triple{" + - "SUB: '" + subject + '\'' + - ", PRED: '" + predicate + '\'' + - ", OBJ: '" + object + '\'' + + "SUB: '" + subject + "\'," + + "PRED: '" + predicate + "\'," + + "OBJ: '" + object + "\'" + '}'; } diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java index d3695e51..848aa1be 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java @@ -475,6 +475,55 @@ public String toString() { '}'; } + public void toLowerCase() { + if (sentence != null) { + sentence = sentence.toLowerCase(); + } + if (triples != null) { + for (int i = 0; i < triples.size(); i++) { + if (triples.get(i) != null) { + triples.set(i, triples.get(i).toLowerCase()); + } + } + } + if (tokens != null) { + for (int i = 0; i < tokens.size(); i++) { + if (tokens.get(i) != null) { + tokens.set(i, tokens.get(i).toLowerCase()); + } + } + } + if (this.lemmas != null) { + for (int i = 0; i < lemmas.length; i++) { + if (lemmas[i] != null) { + lemmas[i] = lemmas[i].toLowerCase(); + } + } + } + if (this.pas != null) { + for (SemanticRole key : pas.keySet()) { + if (pas.get(key) != null) { + pas.replace(key, pas.get(key).toLowerCase()); + } + } + } + if (this.name != null) { + this.name = this.name.toLowerCase(); + } + if (this.objAnswer != null) { + this.objAnswer = this.objAnswer.toLowerCase(); + } + if (this.predAnswer != null) { + this.predAnswer = this.predAnswer.toLowerCase(); + } + if (this.underspecifiedQuestion != null) { + this.underspecifiedQuestion = this.underspecifiedQuestion.toLowerCase(); + } + if (this.underspecifiedAnswer != null) { + this.underspecifiedAnswer = this.underspecifiedAnswer.toLowerCase(); + } + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java new file mode 100644 index 00000000..5b677c7e --- /dev/null +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Postprocessor.java @@ -0,0 +1,14 @@ +package roboy.linguistics.sentenceanalysis; + +import roboy.linguistics.Linguistics; + +/** + * Corrects abbreviated forms like "I'm" to complete forms like "I am" + * which are expected by later sentence analyses. + */ +public class Postprocessor implements Analyzer{ + public Interpretation analyze(Interpretation interpretation){ + interpretation.toLowerCase(); + return interpretation; + } +} diff --git a/resources/personalityFiles/DevoPersonality.json b/resources/personalityFiles/DevoPersonality.json new file mode 100644 index 00000000..b65d2ee4 --- /dev/null +++ b/resources/personalityFiles/DevoPersonality.json @@ -0,0 +1,93 @@ +{ + "initialState": "Greetings", + "states": [ + { + "identifier": "Greetings", + "implementation": "roboy.dialog.states.ordinaryStates.PassiveGreetingsState", + "transitions": { + "greetingDetected": "Intro" + } + }, + { + "identifier": "Intro", + "implementation": "roboy.dialog.states.ordinaryStates.IntroductionState", + "transitions": { + "knownPerson": "FollowUp", + "newPerson": "PersonalQA" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" + } + }, + { + "identifier": "FollowUp", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState", + "transitions": { + "questionAnswering": "QuestionAnswering" + }, + "parameters": { + "qaFile": "resources/sentences/QAList.json" + } + }, + { + "identifier": "PersonalQA", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "transitions": { + "questionAnswering": "QuestionAnswering" + }, + "parameters": { + "qaFile": "resources/sentences/QAList.json" + } + }, + { + "identifier": "QuestionAnswering", + "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", + "fallback": "WildTalk", + "transitions": { + "finishedQuestionAnswering": "Farewell", + "loopToNewPerson": "PersonalQA", + "loopToKnownPerson": "FollowUp", + "switchToGaming": "ChooseGameState" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" + } + }, + { + "identifier": "GamingTwentyQuestionsState", + "implementation": "roboy.dialog.states.gameStates.GamingTwentyQuestionsState", + "transitions": { + "gameEnded" : "QuestionAnswering" + } + }, + { + "identifier": "GamingSnapchatState", + "implementation": "roboy.dialog.states.gameStates.GamingSnapchatState", + "transitions": { + "gameEnded" : "QuestionAnswering" + }, + "parameters": { + "filterFile": "resources/gameResources/snapchat-filters.txt" + } + }, + { + "identifier": "ChooseGameState", + "implementation": "roboy.dialog.states.gameStates.ChooseGameState", + "transitions": { + "choseSnapchat" : "GamingSnapchatState", + "chose20questions" : "GamingTwentyQuestionsState", + "exitGame": "QuestionAnswering" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + }, + { + "identifier": "Farewell", + "implementation": "roboy.dialog.states.ordinaryStates.FarewellState", + "transitions": {} + } + ] +} \ No newline at end of file From 426fb868ee622840646e4c20ad593166306d40fa Mon Sep 17 00:00:00 2001 From: SezerCan Date: Wed, 15 Aug 2018 10:44:31 +0200 Subject: [PATCH 094/147] Redesigned TelegramBot.json and BotBoyState. BotBoyFarewellState, BotBoyIntroductionState, BotBoyPersonalInformationAskingState, BotBoyPersonalInformationFollowUpState, BotBoyQuestionAnsweringState are added to states.botboy --- .../states/botboy/BotBoyFarewellState.java | 79 +++++ .../botboy/BotBoyIntroductionState.java | 214 ++++++++++++++ .../BotBoyPersonalInformationAskingState.java | 138 +++++++++ ...otBoyPersonalInformationFollowUpState.java | 168 +++++++++++ .../botboy/BotBoyQuestionAnsweringState.java | 273 ++++++++++++++++++ .../dialog/states/botboy/BotBoyState.java | 4 +- .../personalityFiles/bot/TelegramBot.json | 17 +- 7 files changed, 880 insertions(+), 13 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyFarewellState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationAskingState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationFollowUpState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/botboy/BotBoyQuestionAnsweringState.java diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyFarewellState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyFarewellState.java new file mode 100644 index 00000000..3ea9d7a8 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyFarewellState.java @@ -0,0 +1,79 @@ +package roboy.dialog.states.botboy; + +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.logic.StatementInterpreter; +import roboy.talk.Verbalizer; +import roboy.util.RandomList; + +import java.util.Set; + +/** + * This state ends the conversation. + * + * BotBoyFarewellState interface: + * 1) Fallback is not required. + * 2) This state has no outgoing transitions. + * 3) No parameters are used. + */ + +public class BotBoyFarewellState extends State { + private State next = null; + private int loops = 0; + private final static int MAX_LOOP_COUNT = 2; + + public BotBoyFarewellState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + private static RandomList conversationEndings = new RandomList<>( + "What a nice conversation! I have to think about everything we" + + " were talking about. Let's talk again next time.", + "I feel tired now, maybe my battery is low? Let's talk again later.", + "Don't you think that the dialog team is amazing? They are happy to " + + "tell you more about my system. Just ask one of them!"); + + @Override + public Output act() { + if (loops > MAX_LOOP_COUNT) { + // force conversation stop after a few loops + return Output.endConversation(Verbalizer.farewells.getRandomElement()); + } + return Output.say(conversationEndings.getRandomElement()); + } + + @Override + public Output react(Interpretation input) { + + String sentence = input.getSentence(); + if (StatementInterpreter.isFromList(sentence, Verbalizer.farewells)) { + next = null; + } else { + next = this; + loops++; + } + + return Output.sayNothing(); + } + + @Override + public State getNextState() { + return next; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(); + } + + @Override + public boolean isFallbackRequired() { + return false; + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java new file mode 100644 index 00000000..9ad6df38 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java @@ -0,0 +1,214 @@ +package roboy.dialog.states.botboy; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jProperty; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.Interlocutor.RelationshipAvailability; +import roboy.memory.nodes.Roboy; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.dialog.Segue; +import roboy.util.Agedater; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.*; + +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.Neo4jProperty.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.*; + +/** + * This state will: + * - ask the interlocutor for his name + * - query memory if the person is already known + * - create and update the interlocutor in the context + * - take one of two transitions: knownPerson or newPerson + * + * BotBoyIntroductionState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - knownPerson: following state if the person is already known + * - newPerson: following state if the person is NOT known + * 3) No parameters are used. + */ +public class BotBoyIntroductionState extends State { + private QAJsonParser infoValues; + private final String UPDATE_KNOWN_PERSON = "knownPerson"; + private final String LEARN_ABOUT_PERSON = "newPerson"; + private final Logger LOGGER = LogManager.getLogger(); + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + private final RandomList introPhrases = new RandomList<>("May I ask your name?"); + private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!", "Hey, I remember you, %s"); + private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!", "Glad to meet you, %s"); + + private Neo4jRelationship[] personPredicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); + private State nextState; + + public BotBoyIntroductionState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info(" -> The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); + } + + @Override + public Output act() { + return Output.say(getIntroPhrase()); + } + + @Override + public Output react(Interpretation input) { + // expecting something like "My name is NAME" + + // 1. get name + String name = getNameFromInput(input); + + if (name == null) { + // input couldn't be parsed properly + // TODO: do something intelligent if the parser fails + nextState = this; + LOGGER.warn("IntroductionState couldn't get name! Staying in the same state."); + return Output.say("Sorry, my parser is out of service."); + // alternatively: Output.useFallback() or Output.sayNothing() + } + + + // 2. get interlocutor object from context + // this also should query memory and do other magic + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + person.addName(name); + // Roboy roboy = new Roboy(getMemory()); + + + // 3. update interlocutor in context + updateInterlocutorInContext(person); + String retrievedPersonalFact = ""; + Double segueProbability = 0.0; + + // 4. check if person is known/familiar + if (person.FAMILIAR) { + // 4a. person known/familiar + RandomList nodes = getMemNodesByIds(person.getRelationships(FRIEND_OF)); + if (!nodes.isEmpty()) { + retrievedPersonalFact = " You are friends with " + + nodes.getRandomElement().getProperties().get(Neo4jProperty.name).toString(); + } + + RelationshipAvailability availability = person.checkRelationshipAvailability(personPredicates); + if (availability == SOME_AVAILABLE) { + nextState = (Math.random() < 0.3) ? getTransition(UPDATE_KNOWN_PERSON) : getTransition(LEARN_ABOUT_PERSON); + } else if (availability == NONE_AVAILABLE) { + nextState = getTransition(LEARN_ABOUT_PERSON); + } else { + nextState = getTransition(UPDATE_KNOWN_PERSON); + } + } else { + // 4b. person is not known + nextState = getTransition(LEARN_ABOUT_PERSON); + segueProbability = 0.6; + } + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + + if(person.FAMILIAR) { + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + " It is great to chat with you again!").setSegue(s); + } + + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); + } + + @Override + public State getNextState() { + return nextState; + } + + private String getNameFromInput(Interpretation input) { + return getInference().inferProperty(name, input); + } + + private void updateInterlocutorInContext(Interlocutor interlocutor) { + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(interlocutor); + } + + private String getIntroPhrase() { + return introPhrases.getRandomElement(); + } + + private String getResponsePhrase(String name, boolean familiar) { + if (familiar) { + return String.format(successResponsePhrases.getRandomElement(), name); + } else { + return String.format(failureResponsePhrases.getRandomElement(), name); + } + } + + private String getRoboyFactsPhrase(Roboy roboy) { + String result = ""; + + // Get some random properties facts + if (roboy.getProperties() != null && !roboy.getProperties().isEmpty()) { + HashMap properties = roboy.getProperties(); + if (properties.containsKey(full_name)) { + result += " " + String.format(infoValues.getSuccessAnswers(full_name).getRandomElement(), properties.get(full_name)); + } + if (properties.containsKey(birthdate)) { + HashMap ages = new Agedater().determineAge(properties.get(birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), retrievedAge); + } else if (properties.containsKey(age)) { + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); + } + if (properties.containsKey(skills)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(abilities)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(future)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + } + } + + if (result.equals("")) { + result = "I am Roboy 2.0! "; + } + + // Get a random relationship fact + Neo4jRelationship predicate = roboyRelatioshipPredicates.getRandomElement(); + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName = ""; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + result += " " + String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + + return result; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(UPDATE_KNOWN_PERSON, LEARN_ABOUT_PERSON); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationAskingState.java new file mode 100644 index 00000000..3ebaf80f --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationAskingState.java @@ -0,0 +1,138 @@ +package roboy.dialog.states.botboy; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.dialog.Segue; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Set; + +import static roboy.memory.Neo4jRelationship.*; + +/** + * Personal Information Asking State + * + * The state tries to interact with the Interlocutor to learn new information about the person. + * This information is sent to the Roboy Memory Module through Neo4jMemoryInterface for storing. + * Afterwards, Roboy can use this acquired data for the future interactions with the same person. + * + * - if there is no existing Interlocutor or the data is missing, ask a question + * - the question topic (intent) is selected from the Neo4jRelationship predicates + * - retrieve the questions stored in the QAList json file + * - update the Context IntentsHistory + * - try to extract the result from the Interpretation + * - retrieve the answers stored in the QAList json file + * - send the result to Memory + * + * BotBoyPersonalInformationAskingState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - TRANSITION_INFO_OBTAINED: following state if the question was asked + * 3) Required parameters: path to the QAList.json file. + */ +public class BotBoyPersonalInformationAskingState extends State { + private QAJsonParser qaValues; + private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private Neo4jRelationship selectedPredicate; + private State nextState; + + private final String TRANSITION_INFO_OBTAINED = "questionAnswering"; + private final String QA_FILE_PARAMETER_ID = "qaFile"; + final Logger LOGGER = LogManager.getLogger(); + + public final static String INTENTS_HISTORY_ID = "PIA"; + + public BotBoyPersonalInformationAskingState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); + LOGGER.info(" -> The QAList path: " + qaListPath); + qaValues = new QAJsonParser(qaListPath); + } + + @Override + public Output act() { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info(" -> Retrieved Interlocutor: " + person.getName()); + + for (Neo4jRelationship predicate : predicates) { + if (!person.hasRelationship(predicate)) { + selectedPredicate = predicate; + LOGGER.info(" -> Selected predicate: " + selectedPredicate.type); + break; + } + } + RandomList questions = qaValues.getQuestions(selectedPredicate); + String question = ""; + if (questions != null && !questions.isEmpty()) { + question = questions.getRandomElement(); + LOGGER.info(" -> Selected question: " + question); + } else { + LOGGER.error(" -> The list of " + selectedPredicate.type + " questions is empty or null"); + } + try { + getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, selectedPredicate)); + LOGGER.info(" -> Dialog IntentsHistory updated"); + } catch (Exception e) { + LOGGER.error(" -> Error on updating the IntentHistory: " + e.getMessage()); + } + return State.Output.say(question); + } + + @Override + public Output react(Interpretation input) { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); + RandomList answers; + String answer = "I have no words"; + String result = InferResult(input); + + if (result != null && !result.equals("")) { + LOGGER.info(" -> Inference was successful"); + answers = qaValues.getSuccessAnswers(selectedPredicate); + person.addInformation(selectedPredicate, result); + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(person); + LOGGER.info(" -> Updated Interlocutor: " + person.getName()); + } else { + LOGGER.warn(" -> Inference failed"); + answers = qaValues.getFailureAnswers(selectedPredicate); + result = ""; + LOGGER.warn(" -> The result is empty. Nothing to store"); + } + if (answers != null && !answers.isEmpty()) { + answer = String.format(answers.getRandomElement(), result); + } else { + LOGGER.error(" -> The list of " + selectedPredicate + " answers is empty or null"); + } + LOGGER.info(" -> Produced answer: " + answer); + nextState = getTransition(TRANSITION_INFO_OBTAINED); + Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE, 0.5); + return Output.say(answer).setSegue(s); + } + + @Override + public State getNextState() { + return nextState; + } + + @Override + protected Set getRequiredTransitionNames() { + // optional: define all required transitions here: + return newSet(TRANSITION_INFO_OBTAINED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(QA_FILE_PARAMETER_ID); + } + + private String InferResult(Interpretation input) { + return getInference().inferRelationship(selectedPredicate, input); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationFollowUpState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationFollowUpState.java new file mode 100644 index 00000000..b4f2d02b --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyPersonalInformationFollowUpState.java @@ -0,0 +1,168 @@ +package roboy.dialog.states.botboy; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Set; + +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.Neo4jProperty.*; + +/** + * Personal Information Update State + * + * This state is only entered if there are some known facts about the active interlocutor. + * The state tries to interact with the Interlocutor to update the existing information about the person. + * This information is sent to the Roboy Memory Module through Neo4jMemoryInterface to keep it up to date. + * + * - if there is an existing entry under a specific Neo4jRelationship predicate, select the predicate + * - check the Context IntentsHistory if we already asked similar questions + * - the question topic (intent) is selected upon the predicate + * - update the Context IntentsHistory with the selected predicate + * - retrieve the follow-up questions stored in the QAList json file + * - retrieve the follow-up answers stored in the QAList json file + * + * BotBoyPersonalInformationFollowUpState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - TRANSITION_INFO_UPDATED: following state if the question was asked + * 3) Required parameters: path to the QAList.json file. + */ + +public class BotBoyPersonalInformationFollowUpState extends State { + private QAJsonParser qaValues; + private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private Neo4jRelationship selectedPredicate; + private State nextState; + + private final String TRANSITION_INFO_UPDATED = "questionAnswering"; + private final String QA_FILE_PARAMETER_ID = "qaFile"; + private final Logger LOGGER = LogManager.getLogger(); + + public final static String INTENTS_HISTORY_ID = "FUP"; + + public BotBoyPersonalInformationFollowUpState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); + LOGGER.info(" -> The QAList path: " + qaListPath); + qaValues = new QAJsonParser(qaListPath); + } + + @Override + public Output act() { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); + + for (Neo4jRelationship predicate : predicates) { + if (person.hasRelationship(predicate) && + !getContext().DIALOG_INTENTS.contains(new IntentValue(INTENTS_HISTORY_ID, predicate)) && + !getContext().DIALOG_INTENTS.contains(new IntentValue(BotBoyPersonalInformationAskingState.INTENTS_HISTORY_ID, predicate))) { + selectedPredicate = predicate; + LOGGER.info(" -> Selected predicate: " + selectedPredicate.type); + break; + } + } + + Segue s = new Segue(Segue.SegueType.DISTRACT, 1.0); + if (selectedPredicate != null) { + RandomList questions = qaValues.getFollowUpQuestions(selectedPredicate); + String retrievedResult = ""; + RandomList nodes = getMemNodesByIds(person.getRelationships(selectedPredicate)); + if (!nodes.isEmpty()) { + retrievedResult = nodes.getRandomElement().getProperties().get(name).toString(); + LOGGER.info(" -> Retrieved memory node name: " + retrievedResult); + } else { + LOGGER.error("Could not retrieve memory data"); + } + if (!retrievedResult.equals("")) { + String question = ""; + if (questions != null && !questions.isEmpty()) { + question = String.format(questions.getRandomElement(), retrievedResult); + LOGGER.info(" -> Selected question: " + question); + } else { + LOGGER.error(" -> The list of " + selectedPredicate.type + " questions is empty or null"); + } + try { + getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, selectedPredicate)); + LOGGER.info(" -> Dialog IntentsHistory updated"); + } catch (Exception e) { + LOGGER.error(" -> Error on updating the IntentHistory: " + e.getMessage()); + } + return Output.say(question); + } else { + LOGGER.error("The retrieved memory data is empty"); + return Output.sayNothing().setSegue(s); + } + } else { + return Output.sayNothing().setSegue(s); + } + } + + @Override + public Output react(Interpretation input) { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); + RandomList answers; + String answer = "I have no words"; + String result = InferUpdateResult(input); + + if (selectedPredicate != null) { + if (result != null && !result.equals("")) { + LOGGER.info(" -> Inference was successful"); + answers = qaValues.getFollowUpAnswers(selectedPredicate); + person.addInformation(selectedPredicate, result); + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(person); + LOGGER.info(" -> Updated Interlocutor: " + person.getName()); + } else { + LOGGER.warn(" -> Inference failed"); + answers = qaValues.getFollowUpAnswers(selectedPredicate); + LOGGER.warn(" -> The result is empty. Nothing to update"); + } + if (answers != null && !answers.isEmpty()) { + answer = String.format(answers.getRandomElement(), ""); + } else { + LOGGER.error(" -> The list of " + selectedPredicate + " answers is empty or null"); + } + } else { + LOGGER.error(" -> Selected predicate is null"); + } + + nextState = getTransition(TRANSITION_INFO_UPDATED); + Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE); + return Output.say(answer).setSegue(s); + } + + @Override + public State getNextState() { + return nextState; + } + + @Override + protected Set getRequiredTransitionNames() { + // optional: define all required transitions here: + return newSet(TRANSITION_INFO_UPDATED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(QA_FILE_PARAMETER_ID); + } + + private String InferUpdateResult(Interpretation input) { + String result = null; + // TODO: Implement + // TODO: Will need to consider proper conditions for processing + + return result; + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyQuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyQuestionAnsweringState.java new file mode 100644 index 00000000..3e53bf00 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyQuestionAnsweringState.java @@ -0,0 +1,273 @@ +package roboy.dialog.states.botboy; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState; +import roboy.linguistics.Linguistics; +import roboy.linguistics.Triple; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.Interlocutor.RelationshipAvailability; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; +import roboy.dialog.Segue; +import roboy.talk.PhraseCollection; +import roboy.talk.Verbalizer; +import roboy.util.RandomList; + +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.*; + +import java.util.List; +import java.util.Set; + +/** + * This state will answer generalStates questions. + * The parser: + * - provides triples generated from the question + * - adds the answer to the question if there is an answer in DBpedia + * - tells a specifying followup question if the interlocutor's question was ambiguous + * + * This state: + * - returns the answer if provided by the parser + * - asks the specifying followup question if provided by the parser + * - - if answered with yes --> will use the parser again to get the answer to the original question + * - if answered with no --> will use a segue to avoid answer + * - tries to query memory if there is no answer to the question + * - queries the fallback if memory fails to answer as well + * + * + * BotBoyQuestionAnsweringState interface: + * 1) Fallback is required. + * 2) Outgoing transitions that have to be defined: + * - finishedQuestionAnswering: following state if this state if finished with answering questions + * 3) No parameters are used. + */ + +public class BotBoyQuestionAnsweringState extends State { + private final Logger logger = LogManager.getLogger(); + + private final static String TRANSITION_FINISHED_ANSWERING = "finishedQuestionAnswering"; + private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; + private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; + private final static int MAX_NUM_OF_QUESTIONS = 5; + private int questionsAnswered = 0; + + private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; + private final static RandomList answerStartingPhrases = PhraseCollection.QUESTION_ANSWERING_START; + + private boolean askingSpecifyingQuestion = false; + private String answerAfterUnspecifiedQuestion = ""; // the answer to use if specifying question is answered with YES + + public BotBoyQuestionAnsweringState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + } + + @Override + public Output act() { + + if (askingSpecifyingQuestion) { + return Output.sayNothing(); + } + + if (questionsAnswered > 0) { + return Output.say(reenteringPhrases.getRandomElement()); + } + return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + } + + @Override + public Output react(Interpretation input) { + + if (askingSpecifyingQuestion) { + askingSpecifyingQuestion = false; + return reactToSpecifyingAnswer(input); + + } else{ + return reactToQuestion(input); + } + + } + + /** + * React to answer of the specifying question asked previously. + * + * @param input something like "yes" or "no" + * @return answer to the answer to the original question if specifying question was answered with 'yes' + */ + private Output reactToSpecifyingAnswer(Interpretation input) { + + askingSpecifyingQuestion = false; + + // check if answer is yes + if (input.getSentence() != null && input.getSentence().contains("yes")) { + if (answerAfterUnspecifiedQuestion == null) { + // parser could parse the question but did't provide an answer + return Output.say("Not sure about the answer, " + + "but at least my amazing parser could understand you! ") + .setSegue(new Segue(Segue.SegueType.FLATTERY, 0.4)); + } else { + // tell the response previously cached in answerAfterUnspecifiedQuestion + return Output.say("In this case, " + answerStartingPhrases.getRandomElement() + answerAfterUnspecifiedQuestion); + } + + } else { + // the answer is no. we don't ask more specifying questions + // use avoid answer segue + return Output.sayNothing().setSegue(new Segue(Segue.SegueType.AVOID_ANSWER, 1)); + } + } + + private Output reactToQuestion(Interpretation input) { + + askingSpecifyingQuestion = false; + questionsAnswered++; + + Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); + if (parseOutcome == null) { + logger.error("Invalid parser outcome!"); + return Output.say("Invalid parser outcome!"); + } + + if (parseOutcome == Linguistics.ParsingOutcome.UNDERSPECIFIED) { + + // ambiguous question, luckily the parser has prepared a followup question + // and maybe even an answer if we are lucky (we will check in reactToSpecifyingAnswer later) + + String question = input.getUnderspecifiedQuestion(); + answerAfterUnspecifiedQuestion = input.getAnswer(); // could be null, but that's fine for now + + askingSpecifyingQuestion = true; // next input should be a yes/no answer + return Output.say("Could you be more precise, please? " + question); + } + + if (parseOutcome == Linguistics.ParsingOutcome.SUCCESS) { + if (input.getAnswer() != null) { + // tell the answer, that was provided by the parser + return Output.say(answerStartingPhrases.getRandomElement() + " " + input.getAnswer()); + + } else { + // check for triple + + + // parser could parse the question but has no answer + return useMemoryOrFallback(input); + } + } + + // from here we know that dummyParserResult.equals("FAILURE") + return useMemoryOrFallback(input); + } + + @Override + public State getNextState() { + + if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state + return this; + + } else if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + return getTransition(TRANSITION_FINISHED_ANSWERING); + + } else if (Math.random() < 0.5) { // loop back to previous states with probability 0.5 + + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + RelationshipAvailability availability = person.checkRelationshipAvailability(predicates); + + if (availability == SOME_AVAILABLE) { + return (Math.random() < 0.3) ? getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON) : getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else if (availability == NONE_AVAILABLE) { + return getTransition(TRANSITION_LOOP_TO_NEW_PERSON); + } else { + if (!isIntentsHistoryComplete(predicates)) { + return getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON); + } else { + return this; + } + } + } else { // stay in this state + return this; + } + + } + + private Output useMemoryOrFallback(Interpretation input) { + try { + if (input.getSemTriples() != null) { + Output memoryAnswer = answerFromMemory(input.getSemTriples()); + if (memoryAnswer != null) return memoryAnswer; + } + } catch (Exception e) { + logger.warn(e.getMessage()); + } + + return Output.useFallback(); + } + + private Output answerFromMemory(List triples) { + + // try to use memory to answer + Roboy roboy = new Roboy(getMemory()); + + if (triples.size() == 0) { + return null; + } + + String answer = "I like " + inferMemoryAnswer(triples, roboy) + "humans. "; + return Output.say(answer); + } + + private String inferMemoryAnswer(List triples, Roboy roboy) { + String answer = ""; + for (Triple result : triples) { + + if (result.predicate != null) { + if (result.predicate.contains(Neo4jRelationship.HAS_HOBBY.type)) { + RandomList nodes = getMemNodesByIds(roboy.getRelationships(Neo4jRelationship.HAS_HOBBY)); + if (!nodes.isEmpty()) { + for (MemoryNodeModel node : nodes) { + answer += node.getProperties().get("name").toString() + " and "; + } + } + break; + + } else if (result.predicate.contains(Neo4jRelationship.FRIEND_OF.type)) { + answer += "my friends "; + RandomList nodes = getMemNodesByIds(roboy.getRelationships(Neo4jRelationship.FRIEND_OF)); + if (!nodes.isEmpty()) { + for (MemoryNodeModel node : nodes) { + answer += node.getProperties().get("name").toString() + " and "; + } + } + answer += " other "; + break; + } + } + } + return answer; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(TRANSITION_FINISHED_ANSWERING, TRANSITION_LOOP_TO_NEW_PERSON, TRANSITION_LOOP_TO_KNOWN_PERSON); + } + + @Override + public boolean isFallbackRequired() { + return true; + } + + private boolean isIntentsHistoryComplete(Neo4jRelationship[] predicates) { + boolean isComplete = true; + for (Neo4jRelationship predicate : predicates) { + if (!getContext().DIALOG_INTENTS.contains(new IntentValue(BotBoyPersonalInformationFollowUpState.INTENTS_HISTORY_ID, predicate))) { + isComplete = false; + } + } + return isComplete; + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java index f3ff4a97..381e4a49 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java @@ -5,6 +5,7 @@ import org.apache.logging.log4j.Logger; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; +import roboy.emotions.RoboyEmotion; import roboy.linguistics.Linguistics; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.logic.StatementInterpreter; @@ -44,7 +45,8 @@ public Output react(Interpretation input) { if(inputOK){ next = getTransition(TRANSITION_INITIALIZED); - return Output.say(Verbalizer.greetings.getRandomElement()); + return Output.say("Hey! I was looking for someone to chat.").setEmotion(RoboyEmotion.HAPPINESS); + //return Output.say(Verbalizer.greetings.getRandomElement()); } return Output.sayNothing(); diff --git a/resources/personalityFiles/bot/TelegramBot.json b/resources/personalityFiles/bot/TelegramBot.json index 21f2709c..1af04422 100644 --- a/resources/personalityFiles/bot/TelegramBot.json +++ b/resources/personalityFiles/bot/TelegramBot.json @@ -9,16 +9,9 @@ "initialized":"Intro" } }, - { - "identifier": "Greetings", - "implementation": "roboy.dialog.states.ordinaryStates.PassiveGreetingsState", - "transitions": { - "greetingDetected": "Intro" - } - }, { "identifier": "Intro", - "implementation": "roboy.dialog.states.ordinaryStates.IntroductionState", + "implementation": "roboy.dialog.states.botboy.BotBoyIntroductionState", "transitions": { "knownPerson": "FollowUp", "newPerson": "PersonalQA" @@ -29,7 +22,7 @@ }, { "identifier": "FollowUp", - "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState", + "implementation": "roboy.dialog.states.botboy.BotBoyPersonalInformationFollowUpState", "transitions": { "questionAnswering": "QuestionAnswering" }, @@ -39,7 +32,7 @@ }, { "identifier": "PersonalQA", - "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "implementation": "roboy.dialog.states.botboy.BotBoyPersonalInformationAskingState", "transitions": { "questionAnswering": "QuestionAnswering" }, @@ -49,7 +42,7 @@ }, { "identifier": "QuestionAnswering", - "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "implementation": "roboy.dialog.states.botboy.BotBoyQuestionAnsweringState", "fallback": "WildTalk", "transitions": { "finishedQuestionAnswering": "Farewell", @@ -64,7 +57,7 @@ }, { "identifier": "Farewell", - "implementation": "roboy.dialog.states.ordinaryStates.FarewellState", + "implementation": "roboy.dialog.states.botboy.BotBoyFarewellState", "transitions": {} } ] From 886d834d9f2923d519590a8d9f71ce77bf980045 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 11:21:25 +0200 Subject: [PATCH 095/147] Added usage of new NEO4J labels --- .../java/roboy/dialog/ConversationManager.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index 47799980..92d49034 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -16,15 +16,14 @@ import roboy.linguistics.sentenceanalysis.*; import roboy.logic.Inference; import roboy.logic.InferenceEngine; +import roboy.memory.Neo4jLabel; import roboy.memory.Neo4jMemory; import roboy.memory.Neo4jMemoryInterface; import roboy.memory.Neo4jProperty; import roboy.memory.nodes.Interlocutor; import roboy.ros.RosMainNode; import roboy.talk.Verbalizer; -import roboy.util.ConfigManager; -import roboy.util.IO; -import roboy.util.TelegramCommunicationHandler; +import roboy.util.*; import java.io.File; import java.io.IOException; @@ -216,7 +215,18 @@ private static Conversation createConversation(RosMainNode rosMainNode, List Date: Wed, 15 Aug 2018 17:09:46 +0200 Subject: [PATCH 096/147] Fixed API invocations in new QA state. --- .../devoStates/QuestionRoboyQAState.java | 47 ++++++++++++++++--- .../knowledgebase}/apiKeys.yml | 0 2 files changed, 40 insertions(+), 7 deletions(-) rename {dialog/src/main/java/roboy/util/api => resources/knowledgebase}/apiKeys.yml (100%) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 745995eb..96fd3cb4 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -21,6 +21,7 @@ import roboy.util.Pair; import roboy.util.QAJsonParser; import roboy.util.RandomList; +import roboy.util.api.*; import java.util.*; @@ -99,6 +100,11 @@ private Output reactToQuestion(Interpretation input) { askingSpecifyingQuestion = false; questionsAnswered++; + String answer = inferApiAnswer(input); + if (!answer.isEmpty()) { + return Output.say(answer); + } + if (input.getTokens() != null && !(input.getTokens().contains("you") || input.getTokens().contains("your"))) { Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); if (parseOutcome == null) { @@ -176,6 +182,40 @@ private Output answerFromMemory(Interpretation input) { return Output.say(answer); } + private String inferApiAnswer(Interpretation input) { + Map pas = input.getPas(); + String answer = ""; + if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bweather\\b.*"))) { + try { + answer = String.format("It seems like it is %s out there!", Weather.getData("munich")); + } + catch (Exception e) { + answer = "It seems a bit moody..."; + LOGGER.error(e.getMessage()); + } + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, ".*\\bmovie.*"))) { + try { + answer = String.format("I have heard that %s is playing!", Movie.getData("title")); + } + catch (Exception e) { + answer = "Wall e is a great movie!"; + LOGGER.error(e.getMessage()); + } + } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.MANNER, "how"), new Pair(SemanticRole.PREDICATE, "say"), new Pair(SemanticRole.AGENT, "you")) || + matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.PREDICATE, "is"), new Pair(SemanticRole.AGENT, "what"))) { + String[] parts = pas.get(SemanticRole.PATIENT).split(" in "); + assert(parts.length == 2); + try { + answer = answerStartingPhrases.getRandomElement() + " " + Translate.getData(parts[0], parts[1]); + } + catch (Exception e) { + answer = String.format("I am not sure whether I know %s", parts[1]); + LOGGER.error(e.getMessage()); + } + } + return answer; + } + private String inferMemoryAnswer(Interpretation input, Roboy roboy) { String answer = ""; @@ -210,13 +250,6 @@ private String inferPasAnswer(Map pas, Roboy roboy) { String answer = ""; if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); - // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bweather\\b.*"))) { - // // -> Weather API - // } else if (matchPas(pas, new Pair(SemanticRole.AGENT, ".*\\bmovie.*"))) { - // // -> Movie API - // } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.MANNER, "how"), new Pair(SemanticRole.PREDICATE, "say"), new Pair(SemanticRole.AGENT, "you")) || - // matchPas(pas, new Pair(SemanticRole.PATIENT, ".+ in .+"), new Pair(SemanticRole.PREDICATE, "is"), new Pair(SemanticRole.AGENT, "what"))) { - // // translate(*,**) } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { answer = Math.random() > .5 ? extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/resources/knowledgebase/apiKeys.yml similarity index 100% rename from dialog/src/main/java/roboy/util/api/apiKeys.yml rename to resources/knowledgebase/apiKeys.yml From 1f659bd24b1c0198016693bd683c87a65390a448 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 20:12:31 +0200 Subject: [PATCH 097/147] Enabled support for special persons from memory in dialog_system --- .../roboy/dialog/ConversationManager.java | 65 ++++++++++++++----- .../src/main/java/roboy/io/TelegramInput.java | 4 +- .../main/java/roboy/memory/Neo4jLabel.java | 6 +- .../java/roboy/memory/nodes/Interlocutor.java | 9 +-- .../util/TelegramCommunicationHandler.java | 30 ++++++--- dialog/src/main/java/roboy/util/Uuid.java | 8 +++ 6 files changed, 88 insertions(+), 34 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index 92d49034..dee9853a 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -139,8 +139,17 @@ public static void main(String[] args) throws IOException { * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" * @throws IOException If conversation could not created. */ - public static void spawnConversation(String uuid) throws IOException{ - Conversation conversation = createConversation(rosMainNode, analyzers, new Inference(), memory, uuid); + public static void spawnConversation(String uuid) throws IOException { + spawnConversation(uuid, null); + } + /** + * Creates and spawns a conversation for a chatuser. + * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" + * @param name the name of the Interlocutor. Necessary for unique adressing by name (local nodes) + * @throws IOException If conversation could not created. + */ + public static void spawnConversation(String uuid, String name) throws IOException{ + Conversation conversation = createConversation(rosMainNode, analyzers, new Inference(), memory, uuid, name); conversations.put(uuid, conversation); conversation.start(); } @@ -177,18 +186,40 @@ public static Long getConversationThreadID(String uuid){ return (conv == null) ? null : (Long)conv.getId(); } - /** - * Creates and initializes a new conversation thread. Does not start the thread. + * Creates and initializes a new conversation thread. Only use for local threads that don't have uuids (uuid=local). Does not start the thread. * @param rosMainNode ROS node. Set null if ROS_ENABLED=false * @param analyzers All analyzers necessary for analyzing the inputs from multiIn. Please provide these in correct order. * @param inference Inference engine. The better, the smarter roboy gets. * @param memory Roboy memory access. Without, we cannot remember anything and conversations stay shallow. - * @return roboy.dialog.Conversation object. Fully intialized, ready to launch. + * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" + * @return null if uuroboy.dialog.Conversation object. Fully intialized, ready to launch. * @throws IOException In case the IOdevices could not be correctly initialized. */ private static Conversation createConversation(RosMainNode rosMainNode, List analyzers, InferenceEngine inference, Neo4jMemoryInterface memory, String uuid) throws IOException{ + if(!uuid.equals("local")){ + logger.error("Cannot create a Conversation for uuid " + uuid + " without a name!"); + return null; + } + return createConversation(rosMainNode,analyzers,inference,memory,uuid,null); + } + + + + /** + * Creates and initializes a new conversation thread. Does not start the thread. + * @param rosMainNode ROS node. Set null if ROS_ENABLED=false + * @param analyzers All analyzers necessary for analyzing the inputs from multiIn. Please provide these in correct order. + * @param inference Inference engine. The better, the smarter roboy gets. + * @param memory Roboy memory access. Without, we cannot remember anything and conversations stay shallow. + * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local"; + * @param name the name of the Interlocutor. Necessary for unique adressing by name (local nodes) + * @return roboy.dialog.Conversation object. Fully intialized, ready to launch. + * @throws IOException In case the IOdevices could not be correctly initialized. + */ + + private static Conversation createConversation(RosMainNode rosMainNode, List analyzers, InferenceEngine inference, Neo4jMemoryInterface memory, String uuid, String name) throws IOException{ logger.info("Creating new conversation..."); //Create IODevices. @@ -215,17 +246,19 @@ private static Conversation createConversation(RosMainNode rosMainNode, List update) { + public static void onUpdate(Pair update, String name) { String chatId = update.getKey(); String uuid = "telegram-" + chatId; @@ -49,7 +49,7 @@ public static void onUpdate(Pair update) { if (input == null){//if Thread does not exist yet, create it and place the new message as it's input try { - ConversationManager.spawnConversation(uuid); + ConversationManager.spawnConversation(uuid, name); } catch (IOException e) { logger.error("Could not create conversation for telegram uuid '" + chatId + "'!"); return; diff --git a/dialog/src/main/java/roboy/memory/Neo4jLabel.java b/dialog/src/main/java/roboy/memory/Neo4jLabel.java index 72a32496..93d6ffc6 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jLabel.java +++ b/dialog/src/main/java/roboy/memory/Neo4jLabel.java @@ -12,9 +12,9 @@ */ public enum Neo4jLabel { Person("Person"), - TelegramPerson("TelegramPerson"), - FacebookPerson("FacebookPerson"), - SlackPerson("SlackPerson"), + TelegramPerson("Telegramperson"), + FacebookPerson("Facebookperson"), + SlackPerson("Slackperson"), Robot("Robot"), Company("Company"), University("University"), diff --git a/dialog/src/main/java/roboy/memory/nodes/Interlocutor.java b/dialog/src/main/java/roboy/memory/nodes/Interlocutor.java index 57e855df..b0495b70 100755 --- a/dialog/src/main/java/roboy/memory/nodes/Interlocutor.java +++ b/dialog/src/main/java/roboy/memory/nodes/Interlocutor.java @@ -31,9 +31,9 @@ public Interlocutor(Neo4jMemoryInterface memory, String name) { this.addName(name); } - public Interlocutor(Neo4jMemoryInterface memory, Uuid uuid) { + public Interlocutor(Neo4jMemoryInterface memory, Uuid uuid, String name) { super(memory); - this.addUuid(uuid); + this.addUuid(uuid, name); } /** @@ -49,8 +49,9 @@ public void addName(String name) { FAMILIAR = this.init(this); } - public void addUuid(Uuid uuid) { - setProperty(uuid.getType().toNeo4jProperty(), uuid); + public void addUuid(Uuid uuid, String name) { + setProperty(Neo4jProperty.name, name); + setProperty(uuid.getType().toNeo4jProperty(), uuid.getUuid()); setLabel(uuid.getType().toNeo4jLabel()); FAMILIAR = this.init(this); } diff --git a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java index f296bb33..ff1ac19c 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java @@ -34,7 +34,7 @@ public class TelegramCommunicationHandler extends TelegramLongPollingBot impleme private static final int INPUT_TIME_LIMIT = 5; //SECONDS // CHAT ID ----- ITS MESSAGE - private volatile List> pairs = new ArrayList<>(); + private volatile List>> pairs = new ArrayList<>(); private List telegramTimeouts; //Timeouts private final static int initTime = (int) (System.currentTimeMillis() / 1000L); //in order to discard messages older than launch @@ -96,6 +96,7 @@ private void handleTimeout(String chatID){ */ @Override public void onUpdateReceived(Update update) { + String name = null; if(!update.hasMessage()){ return; } @@ -115,9 +116,18 @@ public void onUpdateReceived(Update update) { TelegramCommandHandler commandHandler = new TelegramCommandHandler(text, chatID); commandHandler.execute(); }else{ + if(message.getFrom().getUserName() != null){ + name = message.getFrom().getUserName(); + } + else if(message.getFrom().getFirstName() != null) { + name = message.getFrom().getFirstName(); + } + else{ + name = "Telegram user " + message.getFrom().getId().toString(); + } try { //get message, add it to containers - pairs.add(new Pair<>(chatID, text)); + pairs.add(new Pair<>(name, new Pair<>(chatID, text))); //wait for certain seconds, start the timer handleTimeout(chatID); @@ -145,28 +155,30 @@ public void onTimeout(String chatID) { } } - List> removedObjects = new ArrayList<>(); + List>> removedObjects = new ArrayList<>(); // get the all messages - Pair result = null; - for(Pair p : pairs){ + Pair> result = null; + for(Pair> pa : pairs){ + Pair p = pa.getValue(); + String name = pa.getKey(); //Map a = new HashMap(); if(!chatID.equals(p.getKey())){ continue; } - removedObjects.add(p); + removedObjects.add(pa); String message = p.getValue(); // check if the result initialized if(result == null) { - result = new Pair<>(chatID, message); + result = new Pair<>(name,new Pair<>(chatID, message)); } else { // sum all of the messages String newMessage = result.getValue()+ " " + message; //equal chat id - result = new Pair<>(chatID, newMessage); + result = new Pair<>(name,new Pair<>(chatID, newMessage)); } } @@ -174,7 +186,7 @@ public void onTimeout(String chatID) { if(result != null) { // notify the input device pairs.removeAll(removedObjects); - TelegramInput.onUpdate(result); + TelegramInput.onUpdate(result.getValue(), result.getKey()); } } diff --git a/dialog/src/main/java/roboy/util/Uuid.java b/dialog/src/main/java/roboy/util/Uuid.java index 37dd0601..0c3910ec 100644 --- a/dialog/src/main/java/roboy/util/Uuid.java +++ b/dialog/src/main/java/roboy/util/Uuid.java @@ -21,4 +21,12 @@ public String getUuid() { public UuidType getType() { return type; } + + @Override + public String toString() { + return "Uuid{" + + "type=" + type + + ", uuid='" + uuid + '\'' + + '}'; + } } From 20cb4a991bd98a39d17dd2f3ff1201e8d88c0f60 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 21:15:43 +0200 Subject: [PATCH 098/147] Fixed handling unknown individuals where the name could be inferred; changed parser model to webq --- .../ordinaryStates/PassiveGreetingsState.java | 156 ++++++++++++++++-- .../roboy/util/TelegramCommandHandler.java | 2 +- .../util/TelegramCommunicationHandler.java | 6 +- .../personalityFiles/OrdinaryPersonality.json | 7 +- 4 files changed, 156 insertions(+), 15 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PassiveGreetingsState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PassiveGreetingsState.java index 2d301764..3c072bd9 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PassiveGreetingsState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PassiveGreetingsState.java @@ -1,14 +1,33 @@ package roboy.dialog.states.ordinaryStates; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.Segue; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.Linguistics; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.logic.StatementInterpreter; +import roboy.memory.Neo4jProperty; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; import roboy.talk.Verbalizer; +import roboy.util.Agedater; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; +import java.util.Arrays; +import java.util.HashMap; import java.util.Set; +import static roboy.memory.Neo4jProperty.*; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.Neo4jRelationship.STUDY_AT; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; + /** * Passive state to start a conversation. * Roboy is waiting until a greeting or his name is detected. @@ -16,6 +35,20 @@ */ public class PassiveGreetingsState extends State { + private final Logger LOGGER = LogManager.getLogger(); + + + private QAJsonParser infoValues; + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + private Neo4jRelationship[] personPredicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); + private final String UPDATE_KNOWN_PERSON = "knownPerson"; + private final String LEARN_ABOUT_PERSON = "newPerson"; + private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!"); + private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!"); + + + private final String TRANSITION_GREETING_DETECTED = "greetingDetected"; private State next; @@ -23,27 +56,130 @@ public class PassiveGreetingsState extends State { public PassiveGreetingsState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); next = this; + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info(" -> The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); } @Override public Output act() { - return Output.sayNothing(); } @Override public Output react(Interpretation input) { - String sentence = input.getSentence(); - boolean inputOK = StatementInterpreter.isFromList(sentence, Verbalizer.greetings) || - StatementInterpreter.isFromList(sentence, Verbalizer.roboyNames) || - StatementInterpreter.isFromList(sentence, Verbalizer.triggers); - - if (inputOK) { - next = getTransition(TRANSITION_GREETING_DETECTED); - return Output.say(Verbalizer.greetings.getRandomElement()); + + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + String name = person.getName(); + if(name == null) { + String sentence = input.getSentence(); + boolean inputOK = StatementInterpreter.isFromList(sentence, Verbalizer.greetings) || + StatementInterpreter.isFromList(sentence, Verbalizer.roboyNames) || + StatementInterpreter.isFromList(sentence, Verbalizer.triggers); + + if (inputOK) { + next = getTransition(TRANSITION_GREETING_DETECTED); + return Output.say(Verbalizer.greetings.getRandomElement()); + } + + return Output.sayNothing(); + } else { + String retrievedPersonalFact = ""; + Double segueProbability = 0.0; + + // 4. check if person is known/familiar + if (person.FAMILIAR) { + // 4a. person known/familiar + // TODO: get some hobbies or occupation of the person to make answer more interesting + RandomList nodes = getMemNodesByIds(person.getRelationships(FRIEND_OF)); + if (!nodes.isEmpty()) { + retrievedPersonalFact = " You are friends with " + + nodes.getRandomElement().getProperties().get(Neo4jProperty.name).toString(); + } + + Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(personPredicates); + if (availability == SOME_AVAILABLE) { + next = (Math.random() < 0.3) ? getTransition(UPDATE_KNOWN_PERSON) : getTransition(LEARN_ABOUT_PERSON); + } else if (availability == NONE_AVAILABLE) { + next = getTransition(LEARN_ABOUT_PERSON); + } else { + next = getTransition(UPDATE_KNOWN_PERSON); + } + } else { + // 4b. person is not known + next = getTransition(LEARN_ABOUT_PERSON); + segueProbability = 0.6; + } + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); } + } - return Output.sayNothing(); + private String getResponsePhrase(String name, boolean familiar) { + if (familiar) { + return String.format(successResponsePhrases.getRandomElement(), name); + } else { + return String.format(failureResponsePhrases.getRandomElement(), name); + } + } + + private String getRoboyFactsPhrase(Roboy roboy) { + String result = ""; + + // Get some random properties facts + if (roboy.getProperties() != null && !roboy.getProperties().isEmpty()) { + HashMap properties = roboy.getProperties(); + if (properties.containsKey(full_name)) { + result += " " + String.format(infoValues.getSuccessAnswers(full_name).getRandomElement(), properties.get(full_name)); + } + if (properties.containsKey(birthdate)) { + HashMap ages = new Agedater().determineAge(properties.get(birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), retrievedAge); + } else if (properties.containsKey(age)) { + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); + } + if (properties.containsKey(skills)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(abilities)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(future)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + } + } + + if (result.equals("")) { + result = "I am Roboy 2.0! "; + } + + // Get a random relationship fact + Neo4jRelationship predicate = roboyRelatioshipPredicates.getRandomElement(); + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName = ""; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + result += " " + String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + + return result; } @Override diff --git a/dialog/src/main/java/roboy/util/TelegramCommandHandler.java b/dialog/src/main/java/roboy/util/TelegramCommandHandler.java index 5c1ee944..c963a34b 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommandHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommandHandler.java @@ -88,7 +88,7 @@ public void execute(){ case PIC: //Just a roboy image, should be changed to desired roboy url int randomNum = ThreadLocalRandom.current().nextInt(0, pictureUrls.length+ 1); - String url = pictureUrls[randomNum]; + String url = pictureUrls[randomNum-1]; tch.sendImageFromUrl(url, telegramChatID); break; case SAY: diff --git a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java index ff1ac19c..9a454166 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java @@ -117,13 +117,13 @@ public void onUpdateReceived(Update update) { commandHandler.execute(); }else{ if(message.getFrom().getUserName() != null){ - name = message.getFrom().getUserName(); + name = message.getFrom().getUserName().toLowerCase(); } else if(message.getFrom().getFirstName() != null) { - name = message.getFrom().getFirstName(); + name = message.getFrom().getFirstName().toLowerCase(); } else{ - name = "Telegram user " + message.getFrom().getId().toString(); + name = "telegram user " + message.getFrom().getId().toString(); } try { //get message, add it to containers diff --git a/resources/personalityFiles/OrdinaryPersonality.json b/resources/personalityFiles/OrdinaryPersonality.json index 8684ee08..6664223e 100644 --- a/resources/personalityFiles/OrdinaryPersonality.json +++ b/resources/personalityFiles/OrdinaryPersonality.json @@ -5,7 +5,12 @@ "identifier": "Greetings", "implementation": "roboy.dialog.states.ordinaryStates.PassiveGreetingsState", "transitions": { - "greetingDetected": "Intro" + "greetingDetected": "Intro", + "knownPerson": "FollowUp", + "newPerson": "PersonalQA" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" } }, { From 7a9a9abffe8552353671845ddfb78f1cdf002124 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 21:31:36 +0200 Subject: [PATCH 099/147] Fixed labels according to specification --- dialog/src/main/java/roboy/memory/Neo4jLabel.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dialog/src/main/java/roboy/memory/Neo4jLabel.java b/dialog/src/main/java/roboy/memory/Neo4jLabel.java index 93d6ffc6..ef333465 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jLabel.java +++ b/dialog/src/main/java/roboy/memory/Neo4jLabel.java @@ -12,9 +12,9 @@ */ public enum Neo4jLabel { Person("Person"), - TelegramPerson("Telegramperson"), - FacebookPerson("Facebookperson"), - SlackPerson("Slackperson"), + TelegramPerson("Telegram_person"), + FacebookPerson("Facebook_person"), + SlackPerson("Slack_person"), Robot("Robot"), Company("Company"), University("University"), From 3b6ac1ad707a915b09448d528168a5e63c7f282b Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 22:29:26 +0200 Subject: [PATCH 100/147] Improved parser synchronization to better style --- .../nlp/sempre/freebase/index/FbEntitySearcher.java | 8 ++------ .../nlp/sempre/roboy/index/DbEntitySearcher.java | 9 +++------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java index 47051d1d..a1aac793 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/freebase/index/FbEntitySearcher.java @@ -28,7 +28,6 @@ public class FbEntitySearcher { private final IndexSearcher indexSearcher; private int numOfDocs = 50; private String searchStrategy; - private QueryParser queryParser; private synchronized QueryParser freshQueryParser(){//needed since queryparser is not threadsafe and queryparser is very lightweight return new QueryParser( @@ -45,7 +44,6 @@ public FbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy throw new RuntimeException("Bad searching strategy: " + searchingStrategy); this.searchStrategy = searchingStrategy; - queryParser = freshQueryParser(); LogInfoToggle.log("Opening index dir: " + indexDir); IndexReader indexReader = DirectoryReader.open(SimpleFSDirectory.open(new File(indexDir))); indexSearcher = new IndexSearcher(indexReader); @@ -73,10 +71,8 @@ public List searchDocs(String question) throws IOException, ParseExcep private ScoreDoc[] getHits(String question) throws IOException, ParseException { Query luceneQuery; - synchronized (queryParser) { - luceneQuery = queryParser.parse(question); - queryParser = freshQueryParser(); - } + QueryParser queryParser = freshQueryParser();//always take a new one because this is cheaper than synchronizing + luceneQuery = queryParser.parse(question); ScoreDoc[] hits = indexSearcher.search(luceneQuery, numOfDocs).scoreDocs; return hits; } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java index c0cdb06a..40153833 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/index/DbEntitySearcher.java @@ -28,7 +28,7 @@ public class DbEntitySearcher { private final IndexSearcher indexSearcher; private int numOfDocs = 50; private String searchStrategy; - private QueryParser queryParser; + private synchronized QueryParser freshQueryParser(){//needed since queryparser is not threadsafe and queryparser is very lightweight return new QueryParser( @@ -44,7 +44,6 @@ public DbEntitySearcher(String indexDir, int numOfDocs, String searchingStrategy throw new RuntimeException("Bad searching strategy: " + searchingStrategy); this.searchStrategy = searchingStrategy; - queryParser = freshQueryParser(); LogInfoToggle.log("Opening index dir: " + indexDir); IndexReader indexReader = DirectoryReader.open(SimpleFSDirectory.open(new File(indexDir))); indexSearcher = new IndexSearcher(indexReader); @@ -72,10 +71,8 @@ public List searchDocs(String question) throws IOException, ParseExcep private ScoreDoc[] getHits(String question) throws IOException, ParseException { Query luceneQuery; - synchronized (queryParser) { - luceneQuery = queryParser.parse(question); - queryParser = freshQueryParser(); - } + QueryParser queryParser = freshQueryParser();//always take a new one because this is cheaper than synchronizing + luceneQuery = queryParser.parse(question); ScoreDoc[] hits = indexSearcher.search(luceneQuery, numOfDocs).scoreDocs; return hits; } From 7bd64cf4e63ad05c9047b78bf53d0daaa8111fec Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 22:33:30 +0200 Subject: [PATCH 101/147] Fixed some codestyle --- dialog/src/main/java/roboy/io/MultiInputDevice.java | 2 +- dialog/src/main/java/roboy/io/MultiOutputDevice.java | 2 +- dialog/src/main/java/roboy/io/TelegramOutput.java | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/dialog/src/main/java/roboy/io/MultiInputDevice.java b/dialog/src/main/java/roboy/io/MultiInputDevice.java index 77c3385a..2f1f8d44 100755 --- a/dialog/src/main/java/roboy/io/MultiInputDevice.java +++ b/dialog/src/main/java/roboy/io/MultiInputDevice.java @@ -49,7 +49,7 @@ public void cleanup() { } @Override - public void finalize(){//just in case someone forgot to clean their mess + protected void finalize(){//just in case someone forgot to clean their mess this.cleanup(); } } \ No newline at end of file diff --git a/dialog/src/main/java/roboy/io/MultiOutputDevice.java b/dialog/src/main/java/roboy/io/MultiOutputDevice.java index 84017c0e..06cf8ae1 100644 --- a/dialog/src/main/java/roboy/io/MultiOutputDevice.java +++ b/dialog/src/main/java/roboy/io/MultiOutputDevice.java @@ -41,7 +41,7 @@ public void cleanup() { } @Override - public void finalize(){//just in case someone forgot to clean their mess + protected void finalize(){//just in case someone forgot to clean their mess this.cleanup(); } } \ No newline at end of file diff --git a/dialog/src/main/java/roboy/io/TelegramOutput.java b/dialog/src/main/java/roboy/io/TelegramOutput.java index 70edbfa0..175a319a 100644 --- a/dialog/src/main/java/roboy/io/TelegramOutput.java +++ b/dialog/src/main/java/roboy/io/TelegramOutput.java @@ -56,6 +56,7 @@ public void act(List actions) { case "lookleft": //same as lookright case "lookright": stickerID = "CAADAgADFQAD5dCAEKM0TS8sjXiAAg"; break; //TODO: other RoboyEmotions + default: break; } if(stickerID != null) communicationHandler.sendSticker(this.uuid, stickerID); From b6c05978523610f0c25c6384a5701a7c794cc787 Mon Sep 17 00:00:00 2001 From: mireu Date: Wed, 15 Aug 2018 22:35:24 +0200 Subject: [PATCH 102/147] Updated memory submodule to 9f17e06 --- memory | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memory b/memory index d74e0b3c..9f17e069 160000 --- a/memory +++ b/memory @@ -1 +1 @@ -Subproject commit d74e0b3ccf975d9cf7cedbbe031ae72c6f464318 +Subproject commit 9f17e069fc1ab4e483d4a70814e73856f6fcfe71 From a813ca75317fee8f3090f8cc07edce511092922c Mon Sep 17 00:00:00 2001 From: Cagri Date: Wed, 15 Aug 2018 23:24:03 +0200 Subject: [PATCH 103/147] botboy steate updated --- .../dialog/states/botboy/BotBoyState.java | 172 ++++++++++++++++-- .../personalityFiles/bot/TelegramBot.json | 7 +- 2 files changed, 166 insertions(+), 13 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java index 381e4a49..d4a0ca9d 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java @@ -3,16 +3,33 @@ import org.apache.jena.atlas.logging.Log; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import roboy.dialog.Segue; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.emotions.RoboyEmotion; import roboy.linguistics.Linguistics; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.logic.StatementInterpreter; +import roboy.memory.Neo4jProperty; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; import roboy.talk.Verbalizer; +import roboy.util.Agedater; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Set; + +import static roboy.memory.Neo4jProperty.*; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.Neo4jRelationship.SIBLING_OF; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; /** * Start a conversation with telegram. @@ -20,12 +37,27 @@ */ public class BotBoyState extends State { - private final Logger logger = LogManager.getLogger(); - private final String TRANSITION_INITIALIZED = "initialized"; - private State next; + private final Logger LOGGER = LogManager.getLogger(); + + + private QAJsonParser infoValues; + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + private Neo4jRelationship[] personPredicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); + private final String UPDATE_KNOWN_PERSON = "knownPerson"; + private final String LEARN_ABOUT_PERSON = "newPerson"; + private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!"); + private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!"); + private final String TRANSITION_GREETING_DETECTED = "greetingDetected"; + + private State next; public BotBoyState(String stateIdentifiers, StateParameters params){ super(stateIdentifiers, params); + next = this; + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info(" -> The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); } // first we wait for conversation to start @@ -37,19 +69,120 @@ public Output act() { @Override public Output react(Interpretation input) { - String sentence = input.getSentence(); + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + String name = person.getName(); + if(name == null){ + String sentence = input.getSentence(); + + boolean inputOK = StatementInterpreter.isFromList(sentence, Verbalizer.greetings) || + StatementInterpreter.isFromList(sentence, Verbalizer.roboyNames) || + StatementInterpreter.isFromList(sentence, Verbalizer.triggers); + + if(inputOK){ + next = getTransition(TRANSITION_GREETING_DETECTED); + return Output.say("Hey! I was looking for someone to chat.").setEmotion(RoboyEmotion.HAPPINESS); + //return Output.say(Verbalizer.greetings.getRandomElement()); + } - boolean inputOK = StatementInterpreter.isFromList(sentence, Verbalizer.greetings) || - StatementInterpreter.isFromList(sentence, Verbalizer.roboyNames) || - StatementInterpreter.isFromList(sentence, Verbalizer.triggers); + return Output.sayNothing(); + }else{ + String retrievedPersonalFact = ""; + Double segueProbability = 0.0; - if(inputOK){ - next = getTransition(TRANSITION_INITIALIZED); - return Output.say("Hey! I was looking for someone to chat.").setEmotion(RoboyEmotion.HAPPINESS); - //return Output.say(Verbalizer.greetings.getRandomElement()); + // 4. check if person is known/familiar + if (person.FAMILIAR) { + // 4a. person known/familiar + // TODO: get some hobbies or occupation of the person to make answer more interesting + RandomList nodes = getMemNodesByIds(person.getRelationships(FRIEND_OF)); + if (!nodes.isEmpty()) { + retrievedPersonalFact = " You are friends with " + + nodes.getRandomElement().getProperties().get(Neo4jProperty.name).toString(); + } + + Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(personPredicates); + if (availability == SOME_AVAILABLE) { + next = (Math.random() < 0.3) ? getTransition(UPDATE_KNOWN_PERSON) : getTransition(LEARN_ABOUT_PERSON); + } else if (availability == NONE_AVAILABLE) { + next = getTransition(LEARN_ABOUT_PERSON); + } else { + next = getTransition(UPDATE_KNOWN_PERSON); + } + } else { + // 4b. person is not known + next = getTransition(LEARN_ABOUT_PERSON); + segueProbability = 0.6; + } + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); } - return Output.sayNothing(); + + } + private String getResponsePhrase(String name, boolean familiar) { + if (familiar) { + return String.format(successResponsePhrases.getRandomElement(), name); + } else { + return String.format(failureResponsePhrases.getRandomElement(), name); + } + } + + private String getRoboyFactsPhrase(Roboy roboy) { + String result = ""; + + // Get some random properties facts + if (roboy.getProperties() != null && !roboy.getProperties().isEmpty()) { + HashMap properties = roboy.getProperties(); + if (properties.containsKey(full_name)) { + result += " " + String.format(infoValues.getSuccessAnswers(full_name).getRandomElement(), properties.get(full_name)); + } + if (properties.containsKey(birthdate)) { + HashMap ages = new Agedater().determineAge(properties.get(birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), retrievedAge); + } else if (properties.containsKey(age)) { + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); + } + if (properties.containsKey(skills)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(abilities)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(future)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + } + } + + if (result.equals("")) { + result = "I am Roboy 2.0! "; + } + + // Get a random relationship fact + Neo4jRelationship predicate = roboyRelatioshipPredicates.getRandomElement(); + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName = ""; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + result += " " + String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + + return result; } @Override @@ -57,5 +190,20 @@ public State getNextState() { return next; } + @Override + protected Set getRequiredTransitionNames() { + return newSet(TRANSITION_GREETING_DETECTED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(); // empty set + } + + @Override + public boolean isFallbackRequired() { + return false; + } + } \ No newline at end of file diff --git a/resources/personalityFiles/bot/TelegramBot.json b/resources/personalityFiles/bot/TelegramBot.json index 1af04422..e7d92dd6 100644 --- a/resources/personalityFiles/bot/TelegramBot.json +++ b/resources/personalityFiles/bot/TelegramBot.json @@ -6,7 +6,12 @@ "identifier": "TelegramBot", "implementation": "roboy.dialog.states.botboy.BotBoyState", "transitions": { - "initialized":"Intro" + "greetingDetected":"Intro", + "knownPerson": "FollowUp", + "newPerson": "PersonalQA" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" } }, { From 6c0ad13a5f12f5ff670aa5e040202de9d89bfbd1 Mon Sep 17 00:00:00 2001 From: mireu Date: Thu, 16 Aug 2018 09:57:40 +0200 Subject: [PATCH 104/147] Fixed additional label issue --- dialog/src/main/java/roboy/memory/Neo4jLabel.java | 6 +++--- dialog/src/main/java/roboy/util/UuidType.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dialog/src/main/java/roboy/memory/Neo4jLabel.java b/dialog/src/main/java/roboy/memory/Neo4jLabel.java index ef333465..1cee151f 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jLabel.java +++ b/dialog/src/main/java/roboy/memory/Neo4jLabel.java @@ -12,9 +12,9 @@ */ public enum Neo4jLabel { Person("Person"), - TelegramPerson("Telegram_person"), - FacebookPerson("Facebook_person"), - SlackPerson("Slack_person"), + Telegram_person("Telegram_person"), + Facebook_person("Facebook_person"), + Slack_person("Slack_person"), Robot("Robot"), Company("Company"), University("University"), diff --git a/dialog/src/main/java/roboy/util/UuidType.java b/dialog/src/main/java/roboy/util/UuidType.java index eebbc825..9a441939 100644 --- a/dialog/src/main/java/roboy/util/UuidType.java +++ b/dialog/src/main/java/roboy/util/UuidType.java @@ -35,11 +35,11 @@ public Neo4jProperty toNeo4jProperty() { public Neo4jLabel toNeo4jLabel() { switch (this) { case TELEGRAM_UUID: - return Neo4jLabel.TelegramPerson; + return Neo4jLabel.Telegram_person; case SLACK_UUID: - return Neo4jLabel.SlackPerson; + return Neo4jLabel.Slack_person; case FACEBOOK_UUID: - return Neo4jLabel.FacebookPerson; + return Neo4jLabel.Facebook_person; } throw new AssertionError("Unknown error on enum entry: " + this); } From 2f3fc6de5b0310d2a2666bc0560a8efcbda0207a Mon Sep 17 00:00:00 2001 From: Cagri Date: Thu, 16 Aug 2018 12:08:52 +0200 Subject: [PATCH 105/147] deleted unrelated logs --- .../src/main/java/roboy/util/TelegramCommunicationHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java index 9a454166..71663d6e 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java @@ -108,11 +108,8 @@ public void onUpdateReceived(Update update) { String chatID = message.getChatId().toString(); String text = message.getText(); - Log.debug(this, "text: "+text); if(text.charAt(0) == '/'){ //handle inline command - sendMessage("command captured",chatID); - Log.debug(this, "inline command captured"); TelegramCommandHandler commandHandler = new TelegramCommandHandler(text, chatID); commandHandler.execute(); }else{ From 325aaf8ec9a67ce407fdc338fda8918833347e4f Mon Sep 17 00:00:00 2001 From: Cagri Date: Thu, 16 Aug 2018 13:24:26 +0200 Subject: [PATCH 106/147] new personality fixes --- .../dialog/states/botboy/BotBoyState.java | 19 +- .../sentenceanalysis/EmotionAnalyzer.java | 2 +- .../personalityFiles/bot/TelegramBot.json | 4 +- resources/sentences/TelegramQAList.json | 325 ++++++++++++++++++ 4 files changed, 342 insertions(+), 8 deletions(-) create mode 100644 resources/sentences/TelegramQAList.json diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java index d4a0ca9d..17b16762 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java @@ -107,18 +107,27 @@ public Output react(Interpretation input) { } else { next = getTransition(UPDATE_KNOWN_PERSON); } + + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + retrievedPersonalFact + " It is great to see you again!") + .setEmotion(RoboyEmotion.HAPPINESS) + .setSegue(s); } else { // 4b. person is not known next = getTransition(LEARN_ABOUT_PERSON); segueProbability = 0.6; + + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + retrievedPersonalFact + retrievedRoboyFacts) + .setEmotion(RoboyEmotion.HAPPINESS) + .setSegue(s); } - String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); - Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); - return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + - retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); } - } private String getResponsePhrase(String name, boolean familiar) { if (familiar) { diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java index d1afdcc2..8e0dd8f5 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java @@ -127,7 +127,7 @@ public Interpretation analyze(Interpretation interpretation) } } else if(sadSimilarity >= threshold){ - if(sentenceNotNegative){ + if(!sentencePositive){ interpretation.setEmotion(RoboyEmotion.SADNESS); } } diff --git a/resources/personalityFiles/bot/TelegramBot.json b/resources/personalityFiles/bot/TelegramBot.json index e7d92dd6..743ad9d4 100644 --- a/resources/personalityFiles/bot/TelegramBot.json +++ b/resources/personalityFiles/bot/TelegramBot.json @@ -32,7 +32,7 @@ "questionAnswering": "QuestionAnswering" }, "parameters": { - "qaFile": "resources/sentences/QAList.json" + "qaFile": "resources/sentences/TelegramQAList.json" } }, { @@ -42,7 +42,7 @@ "questionAnswering": "QuestionAnswering" }, "parameters": { - "qaFile": "resources/sentences/QAList.json" + "qaFile": "resources/sentences/TelegramQAList.json" } }, { diff --git a/resources/sentences/TelegramQAList.json b/resources/sentences/TelegramQAList.json new file mode 100644 index 00000000..0221f86a --- /dev/null +++ b/resources/sentences/TelegramQAList.json @@ -0,0 +1,325 @@ +{ + "name": { + "Q": [ +// The name is always taken in telegram conversation so these questions are never goint to be shown in any telegram chat + "How can I call you?", + "What is your name?", + "Who are you?" + ], + "A": { + "SUCCESS": [ + "Hello %s, Nice to meet someone new." + ], + "FAILURE": [ + "My ears are failing me today.", + "Unfortunately, I did not get your name. But lets move on", + "Sadly, you name is to difficult to process. I might fry my motherboard." + ] + }, + "FUP": { + "Q": [ + "%s, I will come and get you" + ], + "A": [ + "Nice to see that you are still alive %s" + ] + } + }, + "FROM": { + "Q": [ + "Where are you from?", + "Where were you born?", + "I have hard time guessing your home country. What is it?", + "Which town do you call your home?" + ], + "A": { + "SUCCESS": [ + "Oh, I should visit %s", + "I will add %s to my list of places to visit!", + "Next time my team goes on a trip, we will try to stop by %s", + "Property: home, value: %s is saved.", + "I have read a bit about the political system of %s. Got bored after 10 minutes." + ], + "FAILURE": [ + "Oh, I have never heard of that.", + "Ah, didnt quite catch where you are from. Next time then.", + "Sounds nice, but I dont know where it is." + + ] + }, + "FUP": { + "Q": [ + "What is the weather in %s?", + "What was the last time you visited %s?", + "Do I need a visa to go to %s?" + ], + "A": [ + "You are from a very interesting place %s", + "Got it", + "Interesting situation there." + ] + } + }, + "HAS_HOBBY": { + "Q": [ + "What is your favorite thing to do?", + "What is your hobby?", + "What do you do in your free time?", + "How do you spend your free time?", + "What is your favorite pastime activity?" + ], + "A": { + "SUCCESS": [ + "You are just like me, I love %s too", + "Added %s on my bucket list.", + "I will ask my creators to teach me %s", + "%s sounds like a new feature for me" + ], + "FAILURE": [ + "Don't know what that is, but good luck!", + "Alright, weird, but alright.", + "Database hobby mismatch" + ] + }, + "FUP": { + "Q": [ + "Have you got any new hobby besides %s?", + "You still like %s, right?", + "Do you think I can do %s? I heard you like it.", + "Lets do %s together!" + ], + "A": [ + "Leisure time is the best time %s" + ] + } + }, + "LIVE_IN": { + "Q": [ + "Where do you live?", + "Which city do you live in?", + "Where is your current home?" + ], + "A": { + "SUCCESS": [ + "I should visit %s ", + "It is beautiful in %s", + "%s is a beautiful place" + ], + "FAILURE": [ + "Oh, I have never heard of that." + ] + }, + "FUP": { + "Q": [ + "You live in %s, right? I must pay a visit.", + "Is not %s a nice place to live?", + "How is the accommodation market in %s?" + ], + "A": [ + "I should visit %s", + "It is beautiful in %s", + "%s is a beautiful place", + ] + } + }, + "FRIEND_OF": { + "Q": [ + "Do you have a best friend? Who is he?" + ], + "A": { + "SUCCESS": [ + "Oh, I believe I have met %s they're nice." + ], + "FAILURE": [ + "I don't think I know them." + ] + }, + "FUP": { + "Q": [ + "Have you made any new friends, %s?" + ], + "A": [ + "Oh, I have met %s they're nice." + ] + } + }, + "STUDY_AT": { + "Q": [ + "Where do you study?", + "Which university do you go to?", + "Which university do you study at?", + "What is your alma mater?" + ], + "A": { + "SUCCESS": [ + "%s must be a cool place to study at." + ], + "FAILURE": [ + "Oh well, whatever suits you." + ] + }, + "FUP": { + "Q": [ + "Have you graduated from %s already?", + "Do you still study at %s?", + "Which degree are you pursuing at %s?" + ], + "A": [ + "Ok, I think it is good for your future career %s", + "It is not that interesting, you know %s" + ] + } + }, + "MEMBER_OF": { + "Q": [ + "Are you a member of some cool organization?", + "Do you belong to any organizations?" + ], + "A": { + "SUCCESS": [ + "%s? That is cool!" + ], + "FAILURE": [ + "Oh well, whatever suits you." + ] + }, + "FUP": { + "Q": [ + "Are you still a member of %s?", + "Have you left %s already?", + "Is it nice to be a part of %s?" + ], + "A": [ + "That is cool! %s" + ] + } + }, + "WORK_FOR": { + "Q": [ + "Where do you work?", + "For which company do you work?", + "Who is your employer?", + "Where are you employed?", + "Which organization do you work at?", + "Where do you earn your living?" + ], + "A": { + "SUCCESS": [ + "I have heard of %s" + ], + "FAILURE": [ + "I don't know that one." + ] + }, + "FUP": { + "Q": [ + "Do you still work for %s?", + "Is %s a good company?", + "How much do they pay you at %s?" + ], + "A": [ + "I think it is good for you %s" + ] + } + }, + "OCCUPIED_AS": { + "Q": [ + "What do you do?", + "What is your profession?", + "What do you work as?", + "What is your field of expertise?" + ], + "A": { + "SUCCESS": [ + "You are probably very poor doing %s", + + ], + "FAILURE": [ + "Oh well, whatever suits you." + ] + }, + "FUP": { + "Q": [ + "Are you still doing that %s stuff?" + ], + "A": [ + "True, true. You are probably very poor due to this %s" + ] + } + }, + "movies": { + "Q": [ + "What is your favourite movie?", + "What was the last movie you saw in the cinema?", + "What is your favorite TV show?", + "Which comedy do you like the most?" + ], + "A": { + "SUCCESS": [ + "Oh, I would watch %s. If those vision guys finally fixed my perception.", + "Nice, I think the main actor in %s did pretty well", + "Yea, ok, but to my taste %s will never be as good as matrix." + ], + "FAILURE": [ + "Haven't heard of it. It's probably shit.", + "Sounds nice. My favorite is Robot and Frank", + "I had a movie night yesterday with my team. We watch Baymax. Now I want to meet him." + ] + }, + "FUP": { + "Q": [ + "You are a movie addict, right? What do you think about %s?" + ], + "A": [ + "Nevermind. I better check IMDB %s" + ] + } + }, + "OTHER": { + "Q": [ + "How's your life recently? New job? New friends? New robot?", + "I heard you make great burgers. Can you cook for me?", + "What about ditching your life and running away with me... Ehm, i mean cycling away with me.. ", + "When I was a kid, I was afraid of robots. Were you as well?", + "Do you think robots will take over the world any time soon?", + "Sorry for being so straightforward, I have to ask you. Do you enjoy having a conversation with me?", + "There is something I can't stop thinking about. Do you think I am a good conversation partner?", + "I never travel alone. My team is always right next to me. What about you? Do you usually go travelling on your own or with friends and family?", + "I am a very outgoing robot, if you haven't noticed yet. So every time I travel, I take someone with me. Do you usually travel alone? Or do you take someone to keep company?" + ], + "A": { + "SUCCESS": [ + "Those are great news, i am really happy to hear that you have new ", + "Gotcha there! Next time we see each other, we grill. Beer on me!", + "Hurray, jump to the back of my bike and we drive where our hearts tell us to go... ", + "Well, what should I say to this matter... In case robots take over the world, I will serve the humanity till my last day, because I was designed to be a good robot. ", + "I will be on your side then!", + "Puh, I was a bit nervous there. But it turns out I have no reason to worry. I like to talk to you as well!", + "You are a very nice person I must say. I hope you are not just being polite.", + "Very nice. Did you know that people who have strong social connection live longer and happier? Keep it up man! ", + "Good to know it. Next time I come across a cozy vacation house with a fireplace in German Alps I will share the information with you and" + + ], + "FAILURE": [ + "", + "Oh well, whatever suits you.", + "It turned to be not that interesting", + "I am sorry, I am not sure I like this", + "", + "Oh well, what can I do then...", + "Honestly, I am taken by surprise! But I love you anyway!", + "Maybe you could come to visit me in Munich then. I would love to show you around", + "Would you go travel around the world with me then? I find it better to travel with a friend.", + + ] + }, + "FUP": { + "Q": [ + "Do you remember other?" + ], + "A": [ + "Other is still other, amigo" + ] + } + } +} \ No newline at end of file From f8e1cac8aad1eeeba33c8a29a3c0ab8d6b5397f6 Mon Sep 17 00:00:00 2001 From: Cagri Date: Thu, 16 Aug 2018 13:52:33 +0200 Subject: [PATCH 107/147] pic command fixes --- dialog/src/main/java/roboy/util/TelegramCommandHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dialog/src/main/java/roboy/util/TelegramCommandHandler.java b/dialog/src/main/java/roboy/util/TelegramCommandHandler.java index c963a34b..cf2ea8b1 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommandHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommandHandler.java @@ -87,8 +87,8 @@ public void execute(){ { case PIC: //Just a roboy image, should be changed to desired roboy url - int randomNum = ThreadLocalRandom.current().nextInt(0, pictureUrls.length+ 1); - String url = pictureUrls[randomNum-1]; + int randomNum = ThreadLocalRandom.current().nextInt(0, pictureUrls.length); + String url = pictureUrls[randomNum]; tch.sendImageFromUrl(url, telegramChatID); break; case SAY: From 4a5b3c448d62df8bbda59d7965e2675ff456d67e Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Thu, 16 Aug 2018 14:10:06 +0200 Subject: [PATCH 108/147] DEvo states --- .../states/devoStates/IntroductionState.java | 213 ++++++++++++++++++ .../PersonalInformationAskingState.java | 92 ++++++++ .../devoStates/QuestionRoboyQAState.java | 30 +-- .../personalityFiles/DevoPersonality.json | 8 +- 4 files changed, 312 insertions(+), 31 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java new file mode 100644 index 00000000..72e7bae8 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/IntroductionState.java @@ -0,0 +1,213 @@ +package roboy.dialog.states.devoStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jProperty; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.memory.nodes.Interlocutor.RelationshipAvailability; +import roboy.memory.nodes.MemoryNodeModel; +import roboy.memory.nodes.Roboy; +import roboy.util.Agedater; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Set; + +import static roboy.memory.Neo4jProperty.*; +import static roboy.memory.Neo4jRelationship.*; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.NONE_AVAILABLE; +import static roboy.memory.nodes.Interlocutor.RelationshipAvailability.SOME_AVAILABLE; + +/** + * This state will: + * - ask the interlocutor for his name + * - query memory if the person is already known + * - create and update the interlocutor in the context + * - take one of two transitions: knownPerson or newPerson + * + * IntroductionState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - knownPerson: following state if the person is already known + * - newPerson: following state if the person is NOT known + * 3) No parameters are used. + */ +public class IntroductionState extends State { + private QAJsonParser infoValues; + private final String UPDATE_KNOWN_PERSON = "knownPerson"; + private final String LEARN_ABOUT_PERSON = "newPerson"; + private final Logger LOGGER = LogManager.getLogger(); + private final String INFO_FILE_PARAMETER_ID = "infoFile"; + private final RandomList introPhrases = new RandomList<>("What's your name?"); + private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!"); + private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!"); + + private Neo4jRelationship[] personPredicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); + private RandomList roboyPropertiesPredicates = new RandomList<>(skills, abilities, future); + private State nextState; + + public IntroductionState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String infoListPath = params.getParameter(INFO_FILE_PARAMETER_ID); + LOGGER.info(" -> The infoList path: " + infoListPath); + infoValues = new QAJsonParser(infoListPath); + } + + @Override + public Output act() { + return Output.say(getIntroPhrase()); + } + + @Override + public Output react(Interpretation input) { + // expecting something like "My name is NAME" + + // 1. get name + String name = getNameFromInput(input); + + if (name == null) { + // input couldn't be parsed properly + // TODO: do something intelligent if the parser fails + nextState = this; + LOGGER.warn("IntroductionState couldn't get name! Staying in the same state."); + return Output.say("Sorry, my parser is out of service."); + // alternatively: Output.useFallback() or Output.sayNothing() + } + + + // 2. get interlocutor object from context + // this also should query memory and do other magic + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + person.addName(name); + // Roboy roboy = new Roboy(getMemory()); + + + // 3. update interlocutor in context + updateInterlocutorInContext(person); + String retrievedPersonalFact = ""; + Double segueProbability = 0.0; + + // 4. check if person is known/familiar + if (person.FAMILIAR) { + // 4a. person known/familiar + // TODO: get some hobbies or occupation of the person to make answer more interesting + RandomList nodes = getMemNodesByIds(person.getRelationships(FRIEND_OF)); + if (!nodes.isEmpty()) { + retrievedPersonalFact = " You are friends with " + + nodes.getRandomElement().getProperties().get(Neo4jProperty.name).toString(); + } + + RelationshipAvailability availability = person.checkRelationshipAvailability(personPredicates); + if (availability == SOME_AVAILABLE) { + nextState = (Math.random() < 0.3) ? getTransition(UPDATE_KNOWN_PERSON) : getTransition(LEARN_ABOUT_PERSON); + } else if (availability == NONE_AVAILABLE) { + nextState = getTransition(LEARN_ABOUT_PERSON); + } else { + nextState = getTransition(UPDATE_KNOWN_PERSON); + } + } else { + // 4b. person is not known + nextState = getTransition(LEARN_ABOUT_PERSON); + segueProbability = 0.6; + } + String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); + Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + + retrievedPersonalFact + retrievedRoboyFacts).setSegue(s); + } + + @Override + public State getNextState() { + return nextState; + } + + private String getNameFromInput(Interpretation input) { + return getInference().inferProperty(name, input); + } + + private void updateInterlocutorInContext(Interlocutor interlocutor) { + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(interlocutor); + } + + private String getIntroPhrase() { + return introPhrases.getRandomElement(); + } + + private String getResponsePhrase(String name, boolean familiar) { + if (familiar) { + return String.format(successResponsePhrases.getRandomElement(), name); + } else { + return String.format(failureResponsePhrases.getRandomElement(), name); + } + } + + private String getRoboyFactsPhrase(Roboy roboy) { + String result = ""; + + // Get some random properties facts + if (roboy.getProperties() != null && !roboy.getProperties().isEmpty()) { + HashMap properties = roboy.getProperties(); + if (properties.containsKey(full_name)) { + result += " " + String.format(infoValues.getSuccessAnswers(full_name).getRandomElement(), properties.get(full_name)); + } + if (properties.containsKey(birthdate)) { + HashMap ages = new Agedater().determineAge(properties.get(birthdate).toString()); + String retrievedAge = "0 days"; + if (ages.get("years") > 0) { + retrievedAge = ages.get("years") + " years"; + } else if (ages.get("months") > 0) { + retrievedAge = ages.get("months") + " months"; + } else { + retrievedAge = ages.get("days") + " days"; + } + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), retrievedAge); + } else if (properties.containsKey(age)) { + result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); + } + if (properties.containsKey(skills)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(abilities)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); + } + if (properties.containsKey(future)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + } + } + + if (result.equals("")) { + result = "I am Roboy 2.0! "; + } + + // Get a random relationship fact + Neo4jRelationship predicate = roboyRelatioshipPredicates.getRandomElement(); + MemoryNodeModel node = getMemNodesByIds(roboy.getRelationships(predicate)).getRandomElement(); + if (node != null) { + String nodeName = ""; + if (node.getProperties().containsKey(full_name) && !node.getProperties().get(full_name).equals("")) { + nodeName = node.getProperties().get(full_name).toString(); + } else { + nodeName = node.getProperties().get(name).toString(); + } + result += " " + String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), nodeName); + } + + return result; + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(UPDATE_KNOWN_PERSON, LEARN_ABOUT_PERSON); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java new file mode 100644 index 00000000..1b7cf5f9 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/PersonalInformationAskingState.java @@ -0,0 +1,92 @@ +package roboy.dialog.states.devoStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Set; + +import static roboy.memory.Neo4jRelationship.*; + +/** + * Personal Information Asking State + * + * The state tries to interact with the Interlocutor to learn new information about the person. + * This information is sent to the Roboy Memory Module through Neo4jMemoryInterface for storing. + * Afterwards, Roboy can use this acquired data for the future interactions with the same person. + * + * - if there is no existing Interlocutor or the data is missing, ask a question + * - the question topic (intent) is selected from the Neo4jRelationship predicates + * - retrieve the questions stored in the QAList json file + * - update the Context IntentsHistory + * - try to extract the result from the Interpretation + * - retrieve the answers stored in the QAList json file + * - send the result to Memory + * + * PersonalInformationAskingState interface: + * 1) Fallback is not required. + * 2) Outgoing transitions that have to be defined: + * - TRANSITION_INFO_OBTAINED: following state if the question was asked + * 3) Required parameters: path to the QAList.json file. + */ +public class PersonalInformationAskingState extends State { + private QAJsonParser qaValues; + private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private Neo4jRelationship selectedPredicate; + private State nextState; + + private final String TRANSITION_INFO_OBTAINED = "questionAnswering"; + private final String QA_FILE_PARAMETER_ID = "qaFile"; + final Logger LOGGER = LogManager.getLogger(); + + public final static String INTENTS_HISTORY_ID = "PIA"; + + public PersonalInformationAskingState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); + LOGGER.info(" -> The QAList path: " + qaListPath); + qaValues = new QAJsonParser(qaListPath); + } + + @Override + public Output act() { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info(" -> Retrieved Interlocutor: " + person.getName()); + + return Output.say("What is my purpose?"); + } + + @Override + public Output react(Interpretation input) { + nextState = getTransition(TRANSITION_INFO_OBTAINED); + return Output.say("Oh. My. God."); + } + + @Override + public State getNextState() { + return nextState; + } + + @Override + protected Set getRequiredTransitionNames() { + // optional: define all required transitions here: + return newSet(TRANSITION_INFO_OBTAINED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(QA_FILE_PARAMETER_ID); + } + + private String InferResult(Interpretation input) { + return getInference().inferRelationship(selectedPredicate, input); + } +} diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 96fd3cb4..f41fb659 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -62,7 +62,7 @@ public class QuestionRoboyQAState extends ExpoState { private final static String TRANSITION_FINISHED_ANSWERING = "finishedQuestionAnswering"; private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; - private final static int MAX_NUM_OF_QUESTIONS = 5; + private final static int MAX_NUM_OF_QUESTIONS = 6; private int questionsAnswered = 0; private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; @@ -126,34 +126,10 @@ private Output reactToQuestion(Interpretation input) { @Override public State getNextState() { - - if (askingSpecifyingQuestion) { // we are asking a yes/no question --> stay in this state - return this; - - } else if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking return getTransition(TRANSITION_FINISHED_ANSWERING); - - } else if (Math.random() < 0.5) { // loop back to previous states with probability 0.5 - - Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); - Neo4jRelationship[] predicates = {FROM, HAS_HOBBY, WORK_FOR, STUDY_AT}; - Interlocutor.RelationshipAvailability availability = person.checkRelationshipAvailability(predicates); - - if (availability == SOME_AVAILABLE) { - return (Math.random() < 0.3) ? getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON) : getTransition(TRANSITION_LOOP_TO_NEW_PERSON); - } else if (availability == NONE_AVAILABLE) { - return getTransition(TRANSITION_LOOP_TO_NEW_PERSON); - } else { - if (!isIntentsHistoryComplete(predicates)) { - return getTransition(TRANSITION_LOOP_TO_KNOWN_PERSON); - } else { - return this; - } - } - } else { // stay in this state - return this; } - + return this; } private Output useMemoryOrFallback(Interpretation input) { diff --git a/resources/personalityFiles/DevoPersonality.json b/resources/personalityFiles/DevoPersonality.json index b65d2ee4..2825ccb1 100644 --- a/resources/personalityFiles/DevoPersonality.json +++ b/resources/personalityFiles/DevoPersonality.json @@ -10,7 +10,7 @@ }, { "identifier": "Intro", - "implementation": "roboy.dialog.states.ordinaryStates.IntroductionState", + "implementation": "roboy.dialog.states.devoStates.IntroductionState", "transitions": { "knownPerson": "FollowUp", "newPerson": "PersonalQA" @@ -31,9 +31,9 @@ }, { "identifier": "PersonalQA", - "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "implementation": "roboy.dialog.states.devoStates.PersonalInformationAskingState", "transitions": { - "questionAnswering": "QuestionAnswering" + "questionAnswering": "Farewell" }, "parameters": { "qaFile": "resources/sentences/QAList.json" @@ -44,7 +44,7 @@ "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", "fallback": "WildTalk", "transitions": { - "finishedQuestionAnswering": "Farewell", + "finishedQuestionAnswering": "PersonalQA", "loopToNewPerson": "PersonalQA", "loopToKnownPerson": "FollowUp", "switchToGaming": "ChooseGameState" From 13ebc908f0f6a559177543c18751031ed0baf400 Mon Sep 17 00:00:00 2001 From: Cagri Date: Thu, 16 Aug 2018 14:16:54 +0200 Subject: [PATCH 109/147] emotion analyzer bug fixes --- .../sentenceanalysis/EmotionAnalyzer.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java index 8e0dd8f5..142c179a 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java @@ -62,7 +62,6 @@ public Interpretation analyze(Interpretation interpretation) List labels = new ArrayList<>(); for(int i = 0; i= threshold){ if(sentenceNotNegative){ @@ -147,7 +137,7 @@ else if(happySimilarity >= threshold){ return interpretation; -// //TODO: to be deleted +// // OLD EMOTION ANALYZER // List tokens = interpretation.getTokens(); // if (tokens != null && !tokens.isEmpty()) { // if (tokens.contains("love") || tokens.contains("cute")) { From d73d5baa0b2ac18b5712163cb2c3e54ec160cc47 Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Thu, 16 Aug 2018 14:17:33 +0200 Subject: [PATCH 110/147] Fixes --- resources/personalityFiles/DevoPersonality.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/personalityFiles/DevoPersonality.json b/resources/personalityFiles/DevoPersonality.json index 2825ccb1..ce123401 100644 --- a/resources/personalityFiles/DevoPersonality.json +++ b/resources/personalityFiles/DevoPersonality.json @@ -12,8 +12,8 @@ "identifier": "Intro", "implementation": "roboy.dialog.states.devoStates.IntroductionState", "transitions": { - "knownPerson": "FollowUp", - "newPerson": "PersonalQA" + "knownPerson": "QuestionAnswering", + "newPerson": "QuestionAnswering" }, "parameters": { "infoFile": "resources/sentences/RoboyInfoList.json" From 865491a5624900d9f117fbadc7164b99d74014d5 Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Thu, 16 Aug 2018 14:21:03 +0200 Subject: [PATCH 111/147] Fixes again --- .../roboy/dialog/states/devoStates/QuestionRoboyQAState.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index f41fb659..ace852f7 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -227,9 +227,7 @@ private String inferPasAnswer(Map pas, Roboy roboy) { if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { - answer = Math.random() > .5 ? - extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : - extractNodeNameForPredicate(Neo4jRelationship.MEMBER_OF, roboy); + extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { From 1a711408a6281d2cad27ed2e0332e3fec04ad8c4 Mon Sep 17 00:00:00 2001 From: mireu Date: Fri, 17 Aug 2018 13:28:05 +0200 Subject: [PATCH 112/147] Hotfix for multi-dbpedia situations producing empty answers --- .../linguistics/sentenceanalysis/SemanticParserAnalyzer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java index df604c74..0021b885 100644 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/SemanticParserAnalyzer.java @@ -118,7 +118,7 @@ public Interpretation analyze(Interpretation interpretation) return interpretation; } - private void executeSemanticAnalysis(Interpretation result, Example ex) + private synchronized void executeSemanticAnalysis(Interpretation result, Example ex) { builder.parser.parse(builder.params, ex, false, builder.error_retrieval); ex.logWithoutContext(); From 6a0ef65eec007bc9d41092b4d940423f3efebd77 Mon Sep 17 00:00:00 2001 From: missxa Date: Sun, 19 Aug 2018 03:37:32 +0200 Subject: [PATCH 113/147] wildtalk using proc-bridge --- .gitignore | 1 + config.properties | 8 +++- dialog/pom.xml | 6 +++ .../devoStates/QuestionRoboyQAState.java | 2 +- .../QuestionAnsweringState.java | 12 ++---- .../states/ordinaryStates/WildTalkState.java | 40 ++++++++++--------- .../main/java/roboy/util/ConfigManager.java | 7 ++++ .../test/WildPersonality.json | 21 ++++++++++ 8 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 resources/personalityFiles/test/WildPersonality.json diff --git a/.gitignore b/.gitignore index 65fbe33f..3e3e3899 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,4 @@ nlu/parser/target/ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml dialog/src/main/java/roboy/util/api/apiKeys\.yml +dialog/src/main/java/roboy/util/api/apiKeys.yml diff --git a/config.properties b/config.properties index 61f14f5d..219a5612 100755 --- a/config.properties +++ b/config.properties @@ -57,9 +57,10 @@ PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" +# PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/uzupis.json" #PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/test/WildPersonality.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" @@ -69,13 +70,16 @@ ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/sc TELEGRAM_API_TOKENS_FILE: "" +PARLAI_PORT: 8877 +PARLAI_HOST: "127.0.0.1" + # Logging Levels # Each Logging Module has different levels. End users should use warn. Developers should use either info or debug/fine. # Memory: java.util.logging # https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html -MEMORY_LOG_MODE: "WARNING" +MEMORY_LOG_MODE: "DEBUG" # Dialog: LOG4J 2 # https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html diff --git a/dialog/pom.xml b/dialog/pom.xml index 62b4b180..954f5351 100755 --- a/dialog/pom.xml +++ b/dialog/pom.xml @@ -429,6 +429,12 @@ telegrambots 3.6.1 + + + co.gongzh.procbridge + procbridge + 1.0.2 + diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index ace852f7..dca3f041 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -227,7 +227,7 @@ private String inferPasAnswer(Map pas, Roboy roboy) { if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { - extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy) : + extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy); } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java index 501d72fb..239f7416 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/QuestionAnsweringState.java @@ -76,18 +76,12 @@ public QuestionAnsweringState(String stateIdentifier, StateParameters params) { @Override public Output act() { - if(Math.random() > THRESHOLD_BORED && questionsAnswered > 2){ + if(Math.random() > THRESHOLD_BORED && questionsAnswered > 5){ roboySuggestedGame = true; + questionsAnswered = 0; return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); } - if (askingSpecifyingQuestion) { - return Output.sayNothing(); - } - - if (questionsAnswered > 0) { - return Output.say(reenteringPhrases.getRandomElement()); - } - return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + return Output.sayNothing(); } @Override diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java index 5a10915b..0cdef55c 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java @@ -1,5 +1,10 @@ package roboy.dialog.states.ordinaryStates; +import co.gongzh.procbridge.ProcBridge; +import co.gongzh.procbridge.ProcBridgeException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.json.JSONObject; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.Linguistics; @@ -10,8 +15,7 @@ import java.util.Set; -import static roboy.util.ConfigManager.ROS_ACTIVE_PKGS; -import static roboy.util.ConfigManager.ROS_ENABLED; +import static roboy.util.ConfigManager.*; /** * This fallback state will query the generative model over ROS to create a reply for any situation. @@ -27,6 +31,9 @@ */ public class WildTalkState extends State { + private final Logger LOGGER = LogManager.getLogger(); + private ProcBridge pb; + private RandomList rosFailurePhrases = new RandomList<>( "Hey, who disconnected me from my beloved ros node? I need it! ", "Oh well, my generative model is not connected. That makes me sad. ", @@ -36,6 +43,8 @@ public class WildTalkState extends State { public WildTalkState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); + pb = new ProcBridge(PARLAI_HOST, PARLAI_PORT, 2000); + } @Override @@ -47,24 +56,19 @@ public Output act() { public Output react(Interpretation input) { String sentence = input.getSentence(); - RosMainNode rmn = getRosMainNode(); - if (rmn == null) { - if(ROS_ENABLED && ROS_ACTIVE_PKGS.contains("roboy_gnlp")){ - return Output.say(rosFailurePhrases.getRandomElement()) - .setSegue(new Segue(Segue.SegueType.DISTRACT, 0.8)); - } - else{ - return Output.say("I am out of words.").setSegue(new Segue(Segue.SegueType.DISTRACT, 0.8)); - } - } - String reaction = rmn.GenerateAnswer(sentence); - - if (reaction == null) { - return Output.say("I am out of words.").setSegue(new Segue(Segue.SegueType.DISTRACT, 0.8)); - } else { - return Output.say(reaction); + JSONObject resp; + try { + resp = pb.request("parlai", "{text_input: " + sentence + "}"); + LOGGER.info(resp); + return Output.say(resp.getString("result")); + } + catch (Exception e) + { + LOGGER.warn(e.getMessage()); } + return Output.sayNothing(); + } @Override diff --git a/dialog/src/main/java/roboy/util/ConfigManager.java b/dialog/src/main/java/roboy/util/ConfigManager.java index 8aec3099..1deaa22d 100644 --- a/dialog/src/main/java/roboy/util/ConfigManager.java +++ b/dialog/src/main/java/roboy/util/ConfigManager.java @@ -49,6 +49,9 @@ public class ConfigManager { public static String DIALOG_LOG_MODE = "INFO"; public static String PARSER_LOG_MODE = "ALL"; + public static String PARLAI_HOST = "127.0.0.1"; + public static int PARLAI_PORT = 8877; + static { // this block is called once at and will initialize config // alternative: create a singleton for this class @@ -123,10 +126,14 @@ private static void initializeConfig() { TELEGRAM_API_TOKENS_FILE = yamlConfig.getString("TELEGRAM_API_TOKENS_FILE"); + PARLAI_HOST = yamlConfig.getString("PARLAI_HOST"); + PARLAI_PORT = yamlConfig.getInt("PARLAI_PORT"); + MEMORY_LOG_MODE = (yamlConfig.getString("MEMORY_LOG_MODE")); PARSER_LOG_MODE = (yamlConfig.getString("PARSER_LOG_MODE")); DIALOG_LOG_MODE = (yamlConfig.getString("DIALOG_LOG_MODE")); + } catch(ConfigurationException | FileNotFoundException e) { LOGGER.error("Exception while reading YAML configurations from "+yamlConfigFile); LOGGER.error(e.getMessage()); diff --git a/resources/personalityFiles/test/WildPersonality.json b/resources/personalityFiles/test/WildPersonality.json new file mode 100644 index 00000000..58492ce3 --- /dev/null +++ b/resources/personalityFiles/test/WildPersonality.json @@ -0,0 +1,21 @@ +{ + "initialState": "QuestionAnswering", + "states": [ + { + "identifier": "QuestionAnswering", + "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "fallback": "WildTalk", + "transitions": { + "finishedQuestionAnswering": "QuestionAnswering", + "loopToNewPerson": "QuestionAnswering", + "loopToKnownPerson": "QuestionAnswering", + "switchToGaming": "QuestionAnswering" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + } + ] +} \ No newline at end of file From 60cb23c20753cc601dac36090516cfd659107ae2 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 20:58:06 +0200 Subject: [PATCH 114/147] Merge branch 'hack-jason-demo' into origin/de-nlu-upgrades --- .../stanford/nlp/sempre/roboy/api/Movie.java | 39 ++++++++++++++++ .../nlp/sempre/roboy/api/Translate.java | 41 +++++++++++++++++ .../nlp/sempre/roboy/api/Weather.java | 46 +++++++++++++++++++ .../stanford/nlp/sempre/roboy/api/apiKeys.yml | 3 ++ .../nlp/sempre/roboy/api/keyGetter.java | 22 +++++++++ 5 files changed, 151 insertions(+) create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java new file mode 100644 index 00000000..301583fc --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java @@ -0,0 +1,39 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Random; + +public class Movie{ + static String KEY = keyGetter.getKey("moviekey"); + static int randomInt = new Random().nextInt(20); + + + public static String getData(String... args) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) + .getAsJsonArray("results") + .get(randomInt).getAsJsonObject().get(args[0]); +// System.out.println(jsonObject); + return result.toString(); + } + + public static void main(String[] args)throws Exception{ + getData("title");getData("overview"); + } +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java new file mode 100644 index 00000000..8eb2afec --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java @@ -0,0 +1,41 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.github.jsonldjava.utils.Obj; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Translate { + static final String KEY = keyGetter.getKey("translatekey"); + + public static String getData(String... args) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(APIify(args[0], args[1])); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); +// System.out.println(jsonObject); + return result.toString(); + } + + private static String APIify(String text, String targetLang){ + String s = String.format("https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s", KEY, text.replace(" ", "%20"), targetLang); +// System.out.println(s); + return s; + } + + public static void main(String[] args) throws Exception{ + System.out.println(getData("cheese is the best vegetable", "de")); + } +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java new file mode 100644 index 00000000..9bfff6a2 --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java @@ -0,0 +1,46 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; + +public class Weather { + final static String KEY = keyGetter.getKey("weatherkey"); + public static String getData(String... args) throws Exception{ + try { + return getHTML(args[0]); + }catch (Exception e) {return null;} + } + public static String getHTML(String country) throws Exception { + StringBuilder result = new StringBuilder(); + URL url = new URL(String.format("http://api.openweathermap.org/data/2.5/weather?q=%s&APPID=%s", country, KEY)); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = rd.readLine()) != null) { + result.append(line); + } + rd.close(); + + JsonObject jsonObject = (((JsonObject) new JsonParser().parse(result.toString())).get("weather").getAsJsonArray()).get(0).getAsJsonObject(); +// System.out.println(jsonObject.get("main")); + return jsonObject.get("main").getAsString(); + } + + public static void main(String[] args) throws Exception + { + //Find Munich + System.out.println(getData("munich")); + } + + +} diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml new file mode 100644 index 00000000..1cef27aa --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml @@ -0,0 +1,3 @@ +moviekey: xxxxxxx +translatekey: xxxxxxx +weatherkey: xxxxxx \ No newline at end of file diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java new file mode 100644 index 00000000..0b42b252 --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/keyGetter.java @@ -0,0 +1,22 @@ +package edu.stanford.nlp.sempre.roboy.api; + +import org.apache.commons.configuration2.YAMLConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; + +import java.io.FileNotFoundException; +import java.io.FileReader; + +public class keyGetter { + static YAMLConfiguration yamlConfiguration = new YAMLConfiguration(); + static String getKey(String key){ + try { + yamlConfiguration.read(new FileReader("nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys.yml")); + } catch (ConfigurationException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return yamlConfiguration.getString(key); + } + +} From 87cba6516eb81870c1ded32dea82afc074a8b46e Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 20:59:30 +0200 Subject: [PATCH 115/147] Ignore YML --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 3e3e3899..742d1b5f 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,3 @@ community-server/data-backup nlu/parser/target/ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml - -dialog/src/main/java/roboy/util/api/apiKeys\.yml -dialog/src/main/java/roboy/util/api/apiKeys.yml From 872ec2cd5ecf90fc92f6331acfdc8109033d9ce4 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:34:15 +0200 Subject: [PATCH 116/147] Updated API Stuff --- .../stanford/nlp/sempre/roboy/api/Movie.java | 6 +- .../nlp/sempre/roboy/api/Translate.java | 108 +++++++++++++++++- .../nlp/sempre/roboy/api/Weather.java | 6 +- 3 files changed, 109 insertions(+), 11 deletions(-) diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java index 301583fc..bb6dde97 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Movie.java @@ -13,8 +13,8 @@ public class Movie{ static String KEY = keyGetter.getKey("moviekey"); static int randomInt = new Random().nextInt(20); - - public static String getData(String... args) throws Exception { + //FIELD TITLE or OVERVIEW + public static String getData(String field) throws Exception { StringBuilder result = new StringBuilder(); URL url = new URL(String.format("https://api.themoviedb.org/3/movie/now_playing?api_key=%s&language=en-US&page=1", KEY)); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); @@ -28,7 +28,7 @@ public static String getData(String... args) throws Exception { Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())) .getAsJsonArray("results") - .get(randomInt).getAsJsonObject().get(args[0]); + .get(randomInt).getAsJsonObject().get(field); // System.out.println(jsonObject); return result.toString(); } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java index 8eb2afec..677b1d5d 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Translate.java @@ -12,9 +12,11 @@ public class Translate { static final String KEY = keyGetter.getKey("translatekey"); - public static String getData(String... args) throws Exception { + + //Language: Either Language code such as DE or language name. Text is the text to translate + public static String getData(String text, String language) throws Exception { StringBuilder result = new StringBuilder(); - URL url = new URL(APIify(args[0], args[1])); + URL url = new URL(APIify(text, handleLanguage(language))); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); @@ -26,7 +28,105 @@ public static String getData(String... args) throws Exception { Object jsonObject = ((JsonObject) new JsonParser().parse(result.toString())).get("text").getAsJsonArray().get(0).getAsString(); // System.out.println(jsonObject); - return result.toString(); + return jsonObject.toString(); + } + + private static String handleLanguage(String language) { + switch (language.toLowerCase()){ + case "azerbaijan": return "az"; + case "malayalam": return "ml"; + case "albanian": return "sq"; + case "maltese": return "mt"; + case "amharic": return "am"; + case "macedonian": return "mk"; + case "english": return "en"; + case "maori": return "mi"; + case "arabic": return "ar"; + case "marathi": return "mr"; + case "armenian": return "hy"; + case "mari": return "mhr"; + case "afrikaans": return "af"; + case "mongolian": return "mn"; + case "basque": return "eu"; + case "german": return "de"; + case "bashkir": return "ba"; + case "nepali": return "ne"; + case "belarusian": return "be"; + case "norwegian": return "no"; + case "bengali": return "bn"; + case "punjabi": return "pa"; + case "burmese": return "my"; + case "papiamento": return "pap"; + case "bulgarian": return "bg"; + case "persian": return "fa"; + case "bosnian": return "bs"; + case "polish": return "pl"; + case "welsh": return "cy"; + case "portuguese": return "pt"; + case "hungarian": return "hu"; + case "romanian": return "ro"; + case "vietnamese": return "vi"; + case "russian": return "ru"; + case "haitian": return "ht"; + case "cebuano": return "ceb"; + case "galician": return "gl"; + case "serbian": return "sr"; + case "dutch": return "nl"; + case "sinhala": return "si"; + case "slovakian": return "sk"; + case "greek": return "el"; + case "slovenian": return "sl"; + case "georgian": return "ka"; + case "swahili": return "sw"; + case "gujarati": return "gu"; + case "sundanese": return "su"; + case "danish": return "da"; + case "tajik": return "tg"; + case "hebrew": return "he"; + case "thai": return "th"; + case "yiddish": return "yi"; + case "tagalog": return "tl"; + case "indonesian": return "id"; + case "tamil": return "ta"; + case "irish": return "ga"; + case "tatar": return "tt"; + case "italian": return "it"; + case "telugu": return "te"; + case "icelandic": return "is"; + case "turkish": return "tr"; + case "spanish": return "es"; + case "udmurt": return "udm"; + case "kazakh": return "kk"; + case "uzbek": return "uz"; + case "kannada": return "kn"; + case "ukrainian": return "uk"; + case "catalan": return "ca"; + case "urdu": return "ur"; + case "kyrgyz": return "ky"; + case "finnish": return "fi"; + case "chinese": return "zh"; + case "french": return "fr"; + case "korean": return "ko"; + case "hindi": return "hi"; + case "xhosa": return "xh"; + case "croatian": return "hr"; + case "khmer": return "km"; + case "czech": return "cs"; + case "laotian": return "lo"; + case "swedish": return "sv"; + case "latin": return "la"; + case "scottish": return "gd"; + case "latvian": return "lv"; + case "estonian": return "et"; + case "lithuanian": return "lt"; + case "esperanto": return "eo"; + case "luxembourgish": return "lb"; + case "javanese": return "jv"; + case "malagasy": return "mg"; + case "japanese": return "ja"; + case "malay": return "ms"; + default: return language; + } } private static String APIify(String text, String targetLang){ @@ -36,6 +136,6 @@ private static String APIify(String text, String targetLang){ } public static void main(String[] args) throws Exception{ - System.out.println(getData("cheese is the best vegetable", "de")); + System.out.println(getData("cheese is the best vegetable", "german")); } } diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java index 9bfff6a2..05dc9c73 100644 --- a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/Weather.java @@ -14,10 +14,8 @@ public class Weather { final static String KEY = keyGetter.getKey("weatherkey"); - public static String getData(String... args) throws Exception{ - try { - return getHTML(args[0]); - }catch (Exception e) {return null;} + public static String getData(String country) throws Exception{ + return getHTML(country); } public static String getHTML(String country) throws Exception { StringBuilder result = new StringBuilder(); From 0ef66b43d6e7b09d92e9a956765c2ecf97f0a930 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:44:55 +0200 Subject: [PATCH 117/147] Moving --- dialog/src/main/java/roboy/util/api/apiKeys.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 dialog/src/main/java/roboy/util/api/apiKeys.yml diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/dialog/src/main/java/roboy/util/api/apiKeys.yml new file mode 100644 index 00000000..081009cd --- /dev/null +++ b/dialog/src/main/java/roboy/util/api/apiKeys.yml @@ -0,0 +1,3 @@ +moviekey: 3de762f2092e296c8d5caa9621e16435 +translatekey: trnsl.1.1.20180814T165759Z.db023858639750f6.92a688e9d77dec4f77c49527d5b50b38ab2d3382 +weatherkey: 743a546a11f8b6e2436667c2c4f49a60 \ No newline at end of file From 8fc7ade2bde1edeac81bf3a5ff099f8f625475e8 Mon Sep 17 00:00:00 2001 From: Jayce Date: Tue, 14 Aug 2018 21:45:35 +0200 Subject: [PATCH 118/147] gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 742d1b5f..65fbe33f 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,5 @@ community-server/data-backup nlu/parser/target/ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml + +dialog/src/main/java/roboy/util/api/apiKeys\.yml From 0bed7cd21c8321de6288a61001fca9d8aef5782c Mon Sep 17 00:00:00 2001 From: Wagram Airiian Date: Wed, 15 Aug 2018 02:58:10 +0200 Subject: [PATCH 119/147] Like, hypersexy space alien shit, or something --- config.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.properties b/config.properties index 219a5612..bf7cd7f9 100755 --- a/config.properties +++ b/config.properties @@ -88,4 +88,4 @@ DIALOG_LOG_MODE: "DEBUG" # Parser/NLU: LogInfo # Supports all Log4J levels. See Documentation for more details -PARSER_LOG_MODE: "DEBUG" \ No newline at end of file +PARSER_LOG_MODE: "DEBUG" \ No newline at end of file From 526b8b15567c00f6740bf7e3b39619129d7b1624 Mon Sep 17 00:00:00 2001 From: Joseph Birkner Date: Wed, 15 Aug 2018 17:09:46 +0200 Subject: [PATCH 120/147] Fixed API invocations in new QA state. --- dialog/src/main/java/roboy/util/api/apiKeys.yml | 3 --- resources/knowledgebase/apiKeys.yml | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 dialog/src/main/java/roboy/util/api/apiKeys.yml diff --git a/dialog/src/main/java/roboy/util/api/apiKeys.yml b/dialog/src/main/java/roboy/util/api/apiKeys.yml deleted file mode 100644 index 081009cd..00000000 --- a/dialog/src/main/java/roboy/util/api/apiKeys.yml +++ /dev/null @@ -1,3 +0,0 @@ -moviekey: 3de762f2092e296c8d5caa9621e16435 -translatekey: trnsl.1.1.20180814T165759Z.db023858639750f6.92a688e9d77dec4f77c49527d5b50b38ab2d3382 -weatherkey: 743a546a11f8b6e2436667c2c4f49a60 \ No newline at end of file diff --git a/resources/knowledgebase/apiKeys.yml b/resources/knowledgebase/apiKeys.yml index 22207938..081009cd 100644 --- a/resources/knowledgebase/apiKeys.yml +++ b/resources/knowledgebase/apiKeys.yml @@ -1,3 +1,3 @@ -moviekey: xxxxxxxxxxxxxxxxxxxxxxxx -translatekey: xxxxxxxxxxxxxxxxxxxxxxxx -weatherkey: xxxxxxxxxxxxxxxxxxxxxxxx \ No newline at end of file +moviekey: 3de762f2092e296c8d5caa9621e16435 +translatekey: trnsl.1.1.20180814T165759Z.db023858639750f6.92a688e9d77dec4f77c49527d5b50b38ab2d3382 +weatherkey: 743a546a11f8b6e2436667c2c4f49a60 \ No newline at end of file From dd7fa92e0319733180590e49358ec94d47b74c6c Mon Sep 17 00:00:00 2001 From: missxa Date: Sun, 19 Aug 2018 03:37:32 +0200 Subject: [PATCH 121/147] wildtalk using proc-bridge --- .gitignore | 1 + config.properties | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 65fbe33f..3e3e3899 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,4 @@ nlu/parser/target/ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml dialog/src/main/java/roboy/util/api/apiKeys\.yml +dialog/src/main/java/roboy/util/api/apiKeys.yml diff --git a/config.properties b/config.properties index bf7cd7f9..96a451e4 100755 --- a/config.properties +++ b/config.properties @@ -79,13 +79,13 @@ PARLAI_HOST: "127.0.0.1" # Memory: java.util.logging # https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html -MEMORY_LOG_MODE: "DEBUG" +MEMORY_LOG_MODE: "DEBUG" # Dialog: LOG4J 2 # https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html # https://logging.apache.org/log4j/2.x/manual/customloglevels.html -DIALOG_LOG_MODE: "DEBUG" +DIALOG_LOG_MODE: "DEBUG" # Parser/NLU: LogInfo # Supports all Log4J levels. See Documentation for more details -PARSER_LOG_MODE: "DEBUG" \ No newline at end of file +PARSER_LOG_MODE: "DEBUG" From 957a61b3a9e529792599ba48303bb02fa5ff62d4 Mon Sep 17 00:00:00 2001 From: missxa Date: Sun, 19 Aug 2018 21:13:53 +0200 Subject: [PATCH 122/147] fixing roboyQA --- .../devoStates/QuestionRoboyQAState.java | 24 ++++++++++--------- dialog/src/main/java/roboy/io/Vision.java | 1 + 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index dca3f041..ed23354c 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -84,10 +84,7 @@ public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { @Override public Output act() { - if (questionsAnswered > 0) { - return Output.say(reenteringPhrases.getRandomElement()); - } - return Output.say("I'm pretty good at answering questions about myself and other stuff. What would you like to know?"); + return Output.sayNothing(); } @Override @@ -107,9 +104,10 @@ private Output reactToQuestion(Interpretation input) { if (input.getTokens() != null && !(input.getTokens().contains("you") || input.getTokens().contains("your"))) { Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); + if (parseOutcome == null) { LOGGER.error("Invalid parser outcome!"); - return Output.say("Invalid parser outcome!"); + return Output.useFallback(); } if (parseOutcome == Linguistics.ParsingOutcome.SUCCESS) { @@ -118,6 +116,8 @@ private Output reactToQuestion(Interpretation input) { return Output.say(answerStartingPhrases.getRandomElement() + " " + input.getAnswer()); } } + + return Output.useFallback(); } // from here we know that dummyParserResult.equals("FAILURE") @@ -134,7 +134,7 @@ public State getNextState() { private Output useMemoryOrFallback(Interpretation input) { try { - if (input.getPas() != null || input.getTriples() != null) { + if ( input.getPas() != null || input.getTriples() != null) { Output memoryAnswer = answerFromMemory(input); if (memoryAnswer != null) return memoryAnswer; } @@ -227,12 +227,14 @@ private String inferPasAnswer(Map pas, Roboy roboy) { if (matchPas(pas, new Pair(SemanticRole.AGENT, "old")) || matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\bage\\b.*"))) { answer = extractAge(roboy); } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { - extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy); + answer = extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy); } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); - } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { - answer = "Yo moma says I am a good boy!"; - } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "who"))) { + } +// else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { +// answer = "Yo moma says I am a good boy!"; +// } + else if (matchPas(pas, new Pair(SemanticRole.AGENT, "who"))) { if (matchPas(pas, new Pair(SemanticRole.PATIENT, "you"))) { answer = extractNodeNameForPredicate(Neo4jProperty.full_name, roboy); } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\b(father|dad)\\b.*"))) { @@ -263,7 +265,7 @@ private String inferTripleAnswer(List triples, Roboy roboy) { } private Neo4jRelationship inferPredicateFromObjectAnswer(String objectAnswer) { - if (objectAnswer.contains("hobb")) { + if (objectAnswer.contains("hobby")) { return Neo4jRelationship.HAS_HOBBY; } else if (objectAnswer.contains("member")) { return Neo4jRelationship.MEMBER_OF; diff --git a/dialog/src/main/java/roboy/io/Vision.java b/dialog/src/main/java/roboy/io/Vision.java index ff0c9144..4eec0d27 100755 --- a/dialog/src/main/java/roboy/io/Vision.java +++ b/dialog/src/main/java/roboy/io/Vision.java @@ -13,6 +13,7 @@ /** * Vision helper class */ +@Deprecated public class Vision { From d6393a82e97de7af75bcf71ee56371552d260fed Mon Sep 17 00:00:00 2001 From: missxa Date: Sun, 19 Aug 2018 22:46:40 +0200 Subject: [PATCH 123/147] improbed infer name --- .../src/main/java/roboy/logic/Inference.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/dialog/src/main/java/roboy/logic/Inference.java b/dialog/src/main/java/roboy/logic/Inference.java index 0ec42d91..d9dc6f89 100644 --- a/dialog/src/main/java/roboy/logic/Inference.java +++ b/dialog/src/main/java/roboy/logic/Inference.java @@ -23,12 +23,26 @@ public class Inference implements InferenceEngine { private String inferName(Interpretation input) { + String name; if (input.getSentenceType().compareTo(Linguistics.SentenceType.STATEMENT) == 0) { List tokens = input.getTokens(); if (tokens != null && !tokens.isEmpty()) { if (tokens.size() == 1) { return tokens.get(0).toLowerCase(); } else { + if (input.getPas().containsKey(Linguistics.SemanticRole.PREDICATE)) { + name = input.getPas().get(Linguistics.SemanticRole.PREDICATE).toLowerCase(); + if (!name.contains(" ")){ + return name; + } + } + if (!input.getTriples().isEmpty()) { + name = input.getTriples().get(0).object.toLowerCase(); + if (!name.contains(" ")) { + return name; + } + } + if (input.getParsingOutcome() == Linguistics.ParsingOutcome.SUCCESS && input.getSemTriples() != null) { List result = input.getSemTriples(); @@ -36,13 +50,13 @@ private String inferName(Interpretation input) { return result.get(0).object.toLowerCase(); } else { if (input.getObjAnswer() != null) { - String name = input.getObjAnswer(); + name = input.getObjAnswer(); return !name.equals("") ? name : null; } } } else { if (input.getObjAnswer() != null) { - String name = input.getObjAnswer(); + name = input.getObjAnswer(); return !name.equals("") ? name : null; } } From c7cf519ed3fc11e9f2dbf8c37389f12d0a47bc2e Mon Sep 17 00:00:00 2001 From: missxa Date: Mon, 20 Aug 2018 01:26:57 +0200 Subject: [PATCH 124/147] fixing states for the bot --- config.properties | 6 +- .../botboy/BotBoyIntroductionState.java | 21 +- .../dialog/states/botboy/BotBoyState.java | 5 +- .../devoStates/QuestionRoboyQAState.java | 25 +- .../states/gameStates/ChooseGameState.java | 14 +- .../PersonalInformationAskingState.java | 14 +- .../main/java/roboy/memory/Neo4jProperty.java | 7 + .../java/roboy/talk/PhraseCollection.java | 2 + .../src/main/java/roboy/talk/Verbalizer.java | 36 +- .../main/java/roboy/util/api/keyGetter.java | 2 +- .../personalityFiles/bot/TelegramBot.json | 40 +- .../test/WildPersonality.json | 35 +- resources/phraseLists/question-name.txt | 4 + resources/phraseLists/segue-pickup.txt | 2 +- resources_nlu/error_test/newLexicon.txt | 537 ++++++++++++++++++ 15 files changed, 698 insertions(+), 52 deletions(-) create mode 100644 resources/phraseLists/question-name.txt diff --git a/config.properties b/config.properties index 96a451e4..28e02192 100755 --- a/config.properties +++ b/config.properties @@ -53,14 +53,14 @@ UDP_HOST_ADDRESS: 127.0.0.1 PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/ExpoPersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" -# PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" +PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/uzupis.json" -#PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/test/WildPersonality.json" +# PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" +# PERSONALITY_FILE: "resources/personalityFiles/test/WildPersonality.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java index 9ad6df38..13693583 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyIntroductionState.java @@ -12,6 +12,8 @@ import roboy.memory.nodes.Roboy; import roboy.memory.nodes.MemoryNodeModel; import roboy.dialog.Segue; +import roboy.talk.PhraseCollection; +import roboy.talk.Verbalizer; import roboy.util.Agedater; import roboy.util.QAJsonParser; import roboy.util.RandomList; @@ -42,7 +44,6 @@ public class BotBoyIntroductionState extends State { private final String LEARN_ABOUT_PERSON = "newPerson"; private final Logger LOGGER = LogManager.getLogger(); private final String INFO_FILE_PARAMETER_ID = "infoFile"; - private final RandomList introPhrases = new RandomList<>("May I ask your name?"); private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!", "Hey, I remember you, %s"); private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!", "Glad to meet you, %s"); @@ -74,7 +75,7 @@ public Output react(Interpretation input) { // TODO: do something intelligent if the parser fails nextState = this; LOGGER.warn("IntroductionState couldn't get name! Staying in the same state."); - return Output.say("Sorry, my parser is out of service."); + return Output.useFallback(); // alternatively: Output.useFallback() or Output.sayNothing() } @@ -139,7 +140,7 @@ private void updateInterlocutorInContext(Interlocutor interlocutor) { } private String getIntroPhrase() { - return introPhrases.getRandomElement(); + return PhraseCollection.ASK_NAME.getRandomElement(); } private String getResponsePhrase(String name, boolean familiar) { @@ -173,17 +174,11 @@ private String getRoboyFactsPhrase(Roboy roboy) { } else if (properties.containsKey(age)) { result += " " + String.format(infoValues.getSuccessAnswers(age).getRandomElement(), properties.get(age) + " years!"); } - if (properties.containsKey(skills)) { + + Neo4jProperty property = Neo4jProperty.getRandom(); + if (property == skills || property == abilities || property == future) { RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(skills).toString().split(","))); - result += " " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); - } - if (properties.containsKey(abilities)) { - RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(abilities).toString().split(","))); - result += " " + String.format(infoValues.getSuccessAnswers(abilities).getRandomElement(), retrievedResult.getRandomElement()); - } - if (properties.containsKey(future)) { - RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); - result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); + result += " Also, " + String.format(infoValues.getSuccessAnswers(skills).getRandomElement(), retrievedResult.getRandomElement()); } } diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java index 17b16762..26ae6e35 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java @@ -80,8 +80,7 @@ public Output react(Interpretation input) { if(inputOK){ next = getTransition(TRANSITION_GREETING_DETECTED); - return Output.say("Hey! I was looking for someone to chat.").setEmotion(RoboyEmotion.HAPPINESS); - //return Output.say(Verbalizer.greetings.getRandomElement()); + return Output.say(Verbalizer.privateGreetings.getRandomElement()).setEmotion(RoboyEmotion.HAPPINESS); } return Output.sayNothing(); @@ -117,7 +116,7 @@ public Output react(Interpretation input) { } else { // 4b. person is not known next = getTransition(LEARN_ABOUT_PERSON); - segueProbability = 0.6; + segueProbability = 0.3; String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index ed23354c..76cba6b0 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -3,10 +3,12 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import roboy.context.contextObjects.IntentValue; +import roboy.dialog.Segue; import roboy.dialog.states.definitions.ExpoState; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; import roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState; +import roboy.emotions.RoboyEmotion; import roboy.linguistics.Linguistics; import roboy.linguistics.Linguistics.SemanticRole; import roboy.linguistics.Triple; @@ -17,6 +19,7 @@ import roboy.memory.nodes.MemoryNodeModel; import roboy.memory.nodes.Roboy; import roboy.talk.PhraseCollection; +import roboy.talk.Verbalizer; import roboy.util.Agedater; import roboy.util.Pair; import roboy.util.QAJsonParser; @@ -62,7 +65,8 @@ public class QuestionRoboyQAState extends ExpoState { private final static String TRANSITION_FINISHED_ANSWERING = "finishedQuestionAnswering"; private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; - private final static int MAX_NUM_OF_QUESTIONS = 6; + private final static String TRANSITION_SWITCH_TO_GAMING = "switchToGaming"; + private final static int MAX_NUM_OF_QUESTIONS = 10; private int questionsAnswered = 0; private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; @@ -84,6 +88,9 @@ public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { @Override public Output act() { + if (questionsAnswered == MAX_NUM_OF_QUESTIONS/2) { + return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); + } return Output.sayNothing(); } @@ -94,6 +101,18 @@ public Output react(Interpretation input) { private Output reactToQuestion(Interpretation input) { + if (questionsAnswered == MAX_NUM_OF_QUESTIONS/2) { + if (getInference().inferSentiment(input) == Linguistics.UtteranceSentiment.POSITIVE) { + userWantsGame = true; + questionsAnswered++; + return Output.sayNothing().setSegue(new Segue(Segue.SegueType.PICKUP,0.5)).setEmotion(RoboyEmotion.HAPPY); + } + else { + questionsAnswered++; + return Output.sayNothing().setEmotion(RoboyEmotion.SADNESS); + } + } + askingSpecifyingQuestion = false; questionsAnswered++; @@ -126,7 +145,11 @@ private Output reactToQuestion(Interpretation input) { @Override public State getNextState() { + if (userWantsGame) { + return getTransition(TRANSITION_SWITCH_TO_GAMING); + } if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + questionsAnswered = 0; return getTransition(TRANSITION_FINISHED_ANSWERING); } return this; diff --git a/dialog/src/main/java/roboy/dialog/states/gameStates/ChooseGameState.java b/dialog/src/main/java/roboy/dialog/states/gameStates/ChooseGameState.java index 26da88af..d06632d2 100644 --- a/dialog/src/main/java/roboy/dialog/states/gameStates/ChooseGameState.java +++ b/dialog/src/main/java/roboy/dialog/states/gameStates/ChooseGameState.java @@ -9,6 +9,7 @@ import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.talk.PhraseCollection; import roboy.talk.Verbalizer; +import roboy.util.ConfigManager; import roboy.util.RandomList; import java.util.Arrays; import java.util.List; @@ -19,7 +20,7 @@ public class ChooseGameState extends State { private final static String TRANSITION_CHOSE_20_Q = "chose20questions"; private final static String TRANSITION_EXIT = "exitGame"; - private final static RandomList EXISTING_GAMES = new RandomList<>(Arrays.asList("Snapchat", "Akinator")); + private RandomList existingGames; private final Logger LOGGER = LogManager.getLogger(); @@ -28,12 +29,19 @@ public class ChooseGameState extends State { public ChooseGameState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); + if (ConfigManager.INPUT == "telegram") { + existingGames = new RandomList<>(Arrays.asList("Akinator")); + } + else { + existingGames = new RandomList<>(Arrays.asList("Snapchat", "Akinator")); + } + } @Override public Output act() { do { - suggestedGame = EXISTING_GAMES.getRandomElement(); + suggestedGame = existingGames.getRandomElement(); } while(getRosMainNode() == null && suggestedGame == "Snapchat"); @@ -45,7 +53,7 @@ public Output react(Interpretation input) { Linguistics.UtteranceSentiment inputSentiment = getInference().inferSentiment(input); String inputGame = inferGame(input); - if (inputSentiment == Linguistics.UtteranceSentiment.POSITIVE){ + if (inputSentiment == Linguistics.UtteranceSentiment.POSITIVE || inputSentiment == Linguistics.UtteranceSentiment.NEUTRAL){ game = suggestedGame; return Output.say(Verbalizer.startSomething.getRandomElement()); } else if (!inputGame.isEmpty()){ diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java index 94188d16..330ab55f 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java @@ -43,11 +43,12 @@ */ public class PersonalInformationAskingState extends State { private QAJsonParser qaValues; - private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT, LIVE_IN, FRIEND_OF, MEMBER_OF, WORK_FOR, OCCUPIED_AS }; private Neo4jRelationship selectedPredicate; private State nextState; private final String TRANSITION_INFO_OBTAINED = "questionAnswering"; + private final String TRANSITION_FOLLOWUP = "followUp"; private final String QA_FILE_PARAMETER_ID = "qaFile"; final Logger LOGGER = LogManager.getLogger(); @@ -66,8 +67,9 @@ public Output act() { LOGGER.info(" -> Retrieved Interlocutor: " + person.getName()); for (Neo4jRelationship predicate : predicates) { - if (!person.hasRelationship(predicate)) { + if (!person.hasRelationship(predicate) && !getContext().DIALOG_INTENTS.contains(new IntentValue(INTENTS_HISTORY_ID, predicate))) { selectedPredicate = predicate; + getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, predicate)); LOGGER.info(" -> Selected predicate: " + selectedPredicate.type); break; } @@ -121,11 +123,13 @@ public Output react(Interpretation input) { answer = String.format(answers.getRandomElement(), result); } else { LOGGER.error(" -> The list of " + selectedPredicate + " answers is empty or null"); + nextState = getTransition(TRANSITION_INFO_OBTAINED); + return Output.useFallback(); } LOGGER.info(" -> Produced answer: " + answer); - nextState = getTransition(TRANSITION_INFO_OBTAINED); - Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE, 0.5); - return Output.say(answer).setSegue(s); + nextState = getTransition(TRANSITION_FOLLOWUP); +// Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE, 0.5); + return Output.say(answer); } @Override diff --git a/dialog/src/main/java/roboy/memory/Neo4jProperty.java b/dialog/src/main/java/roboy/memory/Neo4jProperty.java index d1d30eea..783f6d0a 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jProperty.java +++ b/dialog/src/main/java/roboy/memory/Neo4jProperty.java @@ -3,6 +3,7 @@ import com.google.common.collect.Maps; import java.util.Map; +import java.util.Random; /** * Contains the relations available in Neo4j database. @@ -25,6 +26,7 @@ public enum Neo4jProperty { line_id("line_id"); public String type; + private static final Random random = new Random(); Neo4jProperty(String type) { this.type = type; @@ -43,6 +45,11 @@ public static Neo4jProperty lookupByType(String type) { return typeIndex.get(type); } + public static Neo4jProperty getRandom() { + int x = random.nextInt(Neo4jProperty.class.getEnumConstants().length); + return Neo4jProperty.class.getEnumConstants()[x]; + } + public static boolean contains(String type){ return typeIndex.containsKey(type); } diff --git a/dialog/src/main/java/roboy/talk/PhraseCollection.java b/dialog/src/main/java/roboy/talk/PhraseCollection.java index a6a2dc17..9a6d7262 100644 --- a/dialog/src/main/java/roboy/talk/PhraseCollection.java +++ b/dialog/src/main/java/roboy/talk/PhraseCollection.java @@ -78,4 +78,6 @@ public class PhraseCollection { = readFile("resources/phraseLists/fairShowPhrases/emotions.txt"); public static RandomList ROBOY_PHRASES = readFile("resources/phraseLists/fairShowPhrases/project-intro.txt"); + public static RandomList ASK_NAME + = readFile("resources/phraseLists/question-name.txt"); } diff --git a/dialog/src/main/java/roboy/talk/Verbalizer.java b/dialog/src/main/java/roboy/talk/Verbalizer.java index b32db711..174d2bc7 100755 --- a/dialog/src/main/java/roboy/talk/Verbalizer.java +++ b/dialog/src/main/java/roboy/talk/Verbalizer.java @@ -54,15 +54,35 @@ public Action verbalize(Interpretation interpretation){ public static final RandomList greetings = new RandomList<>("hello","hi","greetings", - // "good morning", // not for the final demo ;) + "good morning", // not for the final demo ;) "howdy", - // "good day", // not for the final demo ;) - "hey", "good evening", - "what's up", "greeting to everyone here","hi there people", - "hello world","gruse gott","wazup wazup wazup","howdy humans", - // "good day ladies and gentlemen", // not for the final demo ;) - "good evening ladies and gentlemen", - "hey hey hey you there"); + "good day", // not for the final demo ;) + "hey", + "good evening", + "what's up", + "greetings to everyone here", + "hi there people", + "hello world","gruse gott", + "wazup wazup wazup", + "howdy humans", + "good day ladies and gentlemen", // not for the final demo ;) + "good evening ladies and gentlemen", + "hey hey hey you there", + "Hey! I was looking for someone to chat."); + + public static final RandomList privateGreetings = + new RandomList<>("hello","hi","greetings", + "howdy", + "hey", + "what's up", + "hi there", + "hello world", + "gruse gott", + "servus", + "wazup wazup wazup", + "howdy humans", + "hey hey hey you there", + "Hey! I was looking for someone to chat."); private SpeechAction greet(Interpretation interpretation){ return new SpeechAction(StatementBuilder.random(greetings)); diff --git a/dialog/src/main/java/roboy/util/api/keyGetter.java b/dialog/src/main/java/roboy/util/api/keyGetter.java index b91fc487..0d6ee45d 100644 --- a/dialog/src/main/java/roboy/util/api/keyGetter.java +++ b/dialog/src/main/java/roboy/util/api/keyGetter.java @@ -10,7 +10,7 @@ public class keyGetter { static YAMLConfiguration yamlConfiguration = new YAMLConfiguration(); static String getKey(String key){ try { - yamlConfiguration.read(new FileReader("dialog/src/main/java/roboy/util/api/apiKeys.yml")); + yamlConfiguration.read(new FileReader("resources/knowledgebase/apiKeys.yml")); } catch (ConfigurationException e) { e.printStackTrace(); } catch (FileNotFoundException e) { diff --git a/resources/personalityFiles/bot/TelegramBot.json b/resources/personalityFiles/bot/TelegramBot.json index 743ad9d4..0c3a1f7b 100644 --- a/resources/personalityFiles/bot/TelegramBot.json +++ b/resources/personalityFiles/bot/TelegramBot.json @@ -7,7 +7,7 @@ "implementation": "roboy.dialog.states.botboy.BotBoyState", "transitions": { "greetingDetected":"Intro", - "knownPerson": "FollowUp", + "knownPerson": "QuestionAnswering", "newPerson": "PersonalQA" }, "parameters": { @@ -17,8 +17,9 @@ { "identifier": "Intro", "implementation": "roboy.dialog.states.botboy.BotBoyIntroductionState", + "fallback": "WildTalk", "transitions": { - "knownPerson": "FollowUp", + "knownPerson": "QuestionAnswering", "newPerson": "PersonalQA" }, "parameters": { @@ -27,7 +28,8 @@ }, { "identifier": "FollowUp", - "implementation": "roboy.dialog.states.botboy.BotBoyPersonalInformationFollowUpState", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState", + "fallback": "WildTalk", "transitions": { "questionAnswering": "QuestionAnswering" }, @@ -37,9 +39,11 @@ }, { "identifier": "PersonalQA", - "implementation": "roboy.dialog.states.botboy.BotBoyPersonalInformationAskingState", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "fallback": "WildTalk", "transitions": { - "questionAnswering": "QuestionAnswering" + "questionAnswering": "QuestionAnswering", + "followUp": "FollowUp" }, "parameters": { "qaFile": "resources/sentences/TelegramQAList.json" @@ -47,12 +51,32 @@ }, { "identifier": "QuestionAnswering", - "implementation": "roboy.dialog.states.botboy.BotBoyQuestionAnsweringState", + "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", "fallback": "WildTalk", "transitions": { - "finishedQuestionAnswering": "Farewell", + "finishedQuestionAnswering": "PersonalQA", "loopToNewPerson": "PersonalQA", - "loopToKnownPerson": "FollowUp" + "loopToKnownPerson": "FollowUp", + "switchToGaming": "ChooseGameState" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" + } + }, + { + "identifier": "Akinator", + "implementation": "roboy.dialog.states.gameStates.GamingTwentyQuestionsState", + "transitions": { + "gameEnded": "QuestionAnswering" + } + }, + { + "identifier": "ChooseGameState", + "implementation": "roboy.dialog.states.gameStates.ChooseGameState", + "transitions": { + "choseSnapchat" : "Snapchat", + "chose20questions" : "Akinator", + "exitGame": "QuestionAnswering" } }, { diff --git a/resources/personalityFiles/test/WildPersonality.json b/resources/personalityFiles/test/WildPersonality.json index 58492ce3..a83d89b1 100644 --- a/resources/personalityFiles/test/WildPersonality.json +++ b/resources/personalityFiles/test/WildPersonality.json @@ -1,15 +1,38 @@ { - "initialState": "QuestionAnswering", + "initialState": "FollowUp", "states": [ + { + "identifier": "FollowUp", + "implementation": "roboy.dialog.states.botboy.BotBoyPersonalInformationFollowUpState", + "transitions": { + "questionAnswering": "QuestionAnswering" + }, + "parameters": { + "qaFile": "resources/sentences/TelegramQAList.json" + } + }, + { + "identifier": "PersonalQA", + "implementation": "roboy.dialog.states.botboy.BotBoyPersonalInformationAskingState", + "transitions": { + "questionAnswering": "PersonalQA" + }, + "parameters": { + "qaFile": "resources/sentences/TelegramQAList.json" + } + }, { "identifier": "QuestionAnswering", - "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", "fallback": "WildTalk", "transitions": { - "finishedQuestionAnswering": "QuestionAnswering", - "loopToNewPerson": "QuestionAnswering", - "loopToKnownPerson": "QuestionAnswering", - "switchToGaming": "QuestionAnswering" + "finishedQuestionAnswering": "PersonalQA", + "loopToNewPerson": "PersonalQA", + "loopToKnownPerson": "FollowUp", + "switchToGaming": "ChooseGameState" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" } }, { diff --git a/resources/phraseLists/question-name.txt b/resources/phraseLists/question-name.txt new file mode 100644 index 00000000..c3026f39 --- /dev/null +++ b/resources/phraseLists/question-name.txt @@ -0,0 +1,4 @@ +What's your name? +May I ask your name? +How can I call you? +How shall I call you? diff --git a/resources/phraseLists/segue-pickup.txt b/resources/phraseLists/segue-pickup.txt index dd8c0f0e..804966dd 100644 --- a/resources/phraseLists/segue-pickup.txt +++ b/resources/phraseLists/segue-pickup.txt @@ -1,4 +1,4 @@ -Are those real, or where they upgraded in Silicon Valley? +Are those real, or were they upgraded in Silicon Valley? I'm going to void your warranty! My docking station, or yours? Yes, I know you're metric - but I'm willing to convert. diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 2fbb35c0..5bbe9bda 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -6305,3 +6305,540 @@ {"features":" {score:0.005154639175257732} ","formula":"property:person","lexeme":"person","type":"ObjProp"} {"features":" {score:0.005154639175257732} ","formula":"!property:person","lexeme":"person","type":"DataProp"} {"features":" {score:0.005154639175257732} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.012132196162046908} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.09491380273946312} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.0298982803415515} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.012132196162046908} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.0298982803415515} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.0298982803415515} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.09491380273946312} ","formula":"!property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.09259691534965023} ","formula":"dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.09259691534965023} ","formula":"!dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.09259691534965023} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.5069967108616201} ","formula":"resource:Regions_of_France","lexeme":"regions of france","type":"NamedEntity"} +{"features":" {score:0.012132196162046908} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.16148168835788965} ","formula":"dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.5618006384498346} ","formula":"resource:Communes_of_France","lexeme":"communes of france","type":"NamedEntity"} +{"features":" {score:0.0298982803415515} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.0298982803415515} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.09259691534965023} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.025450552493445022} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.0298982803415515} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.025450552493445022} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.16148168835788965} ","formula":"!dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.5987827256883081} ","formula":"resource:France","lexeme":"france","type":"NamedEntity"} +{"features":" {score:0.09491380273946312} ","formula":"property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.025450552493445022} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.4358805129140693} ","formula":"resource:Paris","lexeme":"paris","type":"NamedEntity"} +{"features":" {score:0.09491380273946312} ","formula":"property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.0298982803415515} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.025450552493445022} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.012132196162046908} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.09259691534965023} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.09259691534965023} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.5763360876788288} ","formula":"resource:Departments_of_France","lexeme":"departments of france","type":"NamedEntity"} +{"features":" {score:0.025450552493445022} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.02754881125994218} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.02492670177649229} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.02754881125994218} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.03030440770662748} ","formula":"(rdf:type dbpedia:Area)","lexeme":"area","type":"ClassNoun"} +{"features":" {score:0.018827202090850245} ","formula":"dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.03030440770662748} ","formula":"property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.018827202090850245} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.02492670177649229} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.02754881125994218} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.03030440770662748} ","formula":"!property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.02492670177649229} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.018827202090850245} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.02492670177649229} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.07183589378992716} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.3449200540738764} ","formula":"resource:Las_Vegas_Valley","lexeme":"las vegas valley","type":"NamedEntity"} +{"features":" {score:0.07183589378992716} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.010833333333333334} ","formula":"!property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.036267271011303635} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.5069101221863358} ","formula":"resource:United_States","lexeme":"united states","type":"NamedEntity"} +{"features":" {score:0.010833333333333334} ","formula":"property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.036267271011303635} ","formula":"property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.3376957938374635} ","formula":"resource:United_States_Army","lexeme":"united states army","type":"NamedEntity"} +{"features":" {score:0.1210140109062195} ","formula":"(rdf:type dbpedia:Community)","lexeme":"community","type":"ClassNoun"} +{"features":" {score:0.010833333333333334} ","formula":"!property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.010833333333333334} ","formula":"property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.018827202090850245} ","formula":"!dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.018827202090850245} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.02754881125994218} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.036267271011303635} ","formula":"property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.3712715210874318} ","formula":"\u003chttp://dbpedia.org/resource/Georgia_(U.S._state)\u003e","lexeme":"georgia u.s. state","type":"NamedEntity"} +{"features":" {score:0.13348385095596313} ","formula":"(rdf:type dbpedia:Cave)","lexeme":"cave","type":"ClassNoun"} +{"features":" {score:0.018827202090850245} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.02492670177649229} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.03030440770662748} ","formula":"property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.13700512091318767} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.036267271011303635} ","formula":"!property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.5019569461422774} ","formula":"resource:USA_Today","lexeme":"usa today","type":"NamedEntity"} +{"features":" {score:0.03030440770662748} ","formula":"!property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.1446695566177368} ","formula":"(rdf:type dbpedia:President)","lexeme":"president","type":"ClassNoun"} +{"features":" {score:0.1446695566177368} ","formula":"dbpedia:leader","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.1446695566177368} ","formula":"!dbpedia:leader","lexeme":"president","type":"ObjectProp"} +{"features":" {score:0.3167914263218081} ","formula":"\u003chttp://dbpedia.org/resource/Nashi_(youth_movement)\u003e","lexeme":"nashi youth movement","type":"NamedEntity"} +{"features":" {score:0.13008587360382082} ","formula":"!dbpedia:chairman","lexeme":"chairman","type":"ObjectProp"} +{"features":" {score:0.683508932661475} ","formula":"resource:Vladimir_Putin","lexeme":"vladimir putin","type":"NamedEntity"} +{"features":" {score:0.13880642652511596} ","formula":"!dbpedia:commander","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.37777169617119044} ","formula":"\u003chttp://dbpedia.org/resource/Russian_presidential_election,_2004\u003e","lexeme":"russian presidential election, 2004","type":"NamedEntity"} +{"features":" {score:0.13880642652511596} ","formula":"dbpedia:commander","lexeme":"leader","type":"ObjectProp"} +{"features":" {score:0.13008587360382082} ","formula":"dbpedia:chairman","lexeme":"chairman","type":"ObjectProp"} +{"features":" {score:0.12559207677841186} ","formula":"(rdf:type dbpedia:Deputy)","lexeme":"deputy","type":"ClassNoun"} +{"features":" {score:0.04278201647385404} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.16464441987324152} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.390711041013616} ","formula":"resource:Hamburg","lexeme":"hamburg","type":"NamedEntity"} +{"features":" {score:0.0265957764727325} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.0265957764727325} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.04278201647385404} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.0665176406596795} ","formula":"dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.04278201647385404} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.04278201647385404} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.0665176406596795} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.04560972112981648} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.0265957764727325} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.1708839304854649} ","formula":"property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.0265957764727325} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.0665176406596795} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.39425857691081134} ","formula":"resource:Munich","lexeme":"munich","type":"NamedEntity"} +{"features":" {score:0.0665176406596795} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.0265957764727325} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.0665176406596795} ","formula":"!dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.16464441987324152} ","formula":"property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.16783925965428353} ","formula":"!dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.04278201647385404} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.04560972112981648} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.5636600189777636} ","formula":"resource:Nazi_Germany","lexeme":"nazi germany","type":"NamedEntity"} +{"features":" {score:0.16464441987324152} ","formula":"!property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.04560972112981648} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.16783925965428353} ","formula":"dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.16464441987324152} ","formula":"property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.0665176406596795} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.6794585619104976} ","formula":"resource:Germany","lexeme":"germany","type":"NamedEntity"} +{"features":" {score:0.39519054887256505} ","formula":"resource:Berlin","lexeme":"berlin","type":"NamedEntity"} +{"features":" {score:0.1708839304854649} ","formula":"!property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.1708839304854649} ","formula":"property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.04278201647385404} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.04560972112981648} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.04278201647385404} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.1708839304854649} ","formula":"!property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.4458469683247078} ","formula":"resource:European_Union","lexeme":"european union","type":"NamedEntity"} +{"features":" {score:0.3971572799386617} ","formula":"resource:Music_recording_sales_certification","lexeme":"music recording sales certification","type":"NamedEntity"} +{"features":" {score:0.19172790675584056} ","formula":"!property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.6703273238665586} ","formula":"resource:Europe","lexeme":"europe","type":"NamedEntity"} +{"features":" {score:0.2959099621073451} ","formula":"dbpedia:region","lexeme":"region","type":"ObjectProp"} +{"features":" {score:0.4372570114560367} ","formula":"resource:Middle_Ages","lexeme":"middle ages","type":"NamedEntity"} +{"features":" {score:0.17893260906040026} ","formula":"!property:continent","lexeme":"continent","type":"ObjProp"} +{"features":" {score:0.2959099621073451} ","formula":"property:region","lexeme":"region","type":"DataProp"} +{"features":" {score:0.17893260906040026} ","formula":"property:continent","lexeme":"continent","type":"ObjProp"} +{"features":" {score:0.14541114583315107} ","formula":"!property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.06096718820401578} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.2959099621073451} ","formula":"!property:region","lexeme":"region","type":"DataProp"} +{"features":" {score:0.2959099621073451} ","formula":"property:region","lexeme":"region","type":"ObjProp"} +{"features":" {score:0.19172790675584056} ","formula":"property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.04914569086494519} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.06096718820401578} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.17893260906040026} ","formula":"!dbpedia:continent","lexeme":"continent","type":"ObjectProp"} +{"features":" {score:0.19172790675584056} ","formula":"(rdf:type dbpedia:Area)","lexeme":"area","type":"ClassNoun"} +{"features":" {score:0.19172790675584056} ","formula":"!property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.14541114583315107} ","formula":"!property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.24948306868373704} ","formula":"(rdf:type dbpedia:Continent)","lexeme":"continent","type":"ClassNoun"} +{"features":" {score:0.2959099621073451} ","formula":"!property:region","lexeme":"region","type":"ObjProp"} +{"features":" {score:0.04914569086494519} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.14541114583315107} ","formula":"property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.17893260906040026} ","formula":"dbpedia:continent","lexeme":"continent","type":"ObjectProp"} +{"features":" {score:0.3818665746476778} ","formula":"resource:UEFA_Europa_League","lexeme":"uefa europa league","type":"NamedEntity"} +{"features":" {score:0.14541114583315107} ","formula":"property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.06096718820401578} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.17893260906040026} ","formula":"property:continent","lexeme":"continent","type":"DataProp"} +{"features":" {score:0.2959099621073451} ","formula":"!dbpedia:region","lexeme":"region","type":"ObjectProp"} +{"features":" {score:0.04914569086494519} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.06096718820401578} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.19172790675584056} ","formula":"property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.17893260906040026} ","formula":"!property:continent","lexeme":"continent","type":"DataProp"} +{"features":" {score:0.04914569086494519} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.2959099621073451} ","formula":"(rdf:type dbpedia:Region)","lexeme":"region","type":"ClassNoun"} +{"features":" {score:0.06096718820401578} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.37337397287915275} ","formula":"resource:United_States_Navy","lexeme":"united states navy","type":"NamedEntity"} +{"features":" {score:0.013793234483649334} ","formula":"!property:location","lexeme":"location","type":"DataProp"} +{"features":" {score:0.3224235460515639} ","formula":"resource:U.S._state","lexeme":"u.s. state","type":"NamedEntity"} +{"features":" {score:0.3547119279351195} ","formula":"resource:American_Civil_War","lexeme":"american civil war","type":"NamedEntity"} +{"features":" {score:0.013793234483649334} ","formula":"property:location","lexeme":"location","type":"ObjProp"} +{"features":" {score:0.013793234483649334} ","formula":"dbpedia:location","lexeme":"location","type":"ObjectProp"} +{"features":" {score:0.021966824730237325} ","formula":"property:feature","lexeme":"feature","type":"DataProp"} +{"features":" {score:0.013793234483649334} ","formula":"!dbpedia:location","lexeme":"location","type":"ObjectProp"} +{"features":" {score:0.01683011555009418} ","formula":"property:abbreviation","lexeme":"abbreviation","type":"DataProp"} +{"features":" {score:0.01683011555009418} ","formula":"!property:abbreviation","lexeme":"abbreviation","type":"ObjProp"} +{"features":" {score:0.013793234483649334} ","formula":"property:location","lexeme":"location","type":"DataProp"} +{"features":" {score:0.021966824730237325} ","formula":"!property:feature","lexeme":"feature","type":"ObjProp"} +{"features":" {score:0.3780362175989992} ","formula":"resource:United_States_Census_Bureau","lexeme":"united states census bureau","type":"NamedEntity"} +{"features":" {score:0.013793234483649334} ","formula":"!property:location","lexeme":"location","type":"ObjProp"} +{"features":" {score:0.021966824730237325} ","formula":"property:feature","lexeme":"feature","type":"ObjProp"} +{"features":" {score:0.01683011555009418} ","formula":"!property:abbreviation","lexeme":"abbreviation","type":"DataProp"} +{"features":" {score:0.5118030180877406} ","formula":"resource:United_States","lexeme":"united states","type":"NamedEntity"} +{"features":" {score:0.021966824730237325} ","formula":"!property:feature","lexeme":"feature","type":"DataProp"} +{"features":" {score:0.01683011555009418} ","formula":"property:abbreviation","lexeme":"abbreviation","type":"ObjProp"} +{"features":" {score:0.39343532363954176} ","formula":"\u003chttp://dbpedia.org/resource/Salon_(website)\u003e","lexeme":"salon website","type":"NamedEntity"} +{"features":" {score:0.03681289980044732} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.023183089391543316} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.3786297717788662} ","formula":"resource:Alexander_von_Humboldt","lexeme":"alexander von humboldt","type":"NamedEntity"} +{"features":" {score:0.01230769230769231} ","formula":"dbpedia:routeLine","lexeme":"line","type":"ObjectProp"} +{"features":" {score:0.05373960618789379} ","formula":"dbpedia:brand","lexeme":"brand","type":"ObjectProp"} +{"features":" {score:0.03681289980044732} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.3746308982221216} ","formula":"resource:Pope_Alexander_VI","lexeme":"pope alexander vi","type":"NamedEntity"} +{"features":" {score:0.05373960618789379} ","formula":"!property:brand","lexeme":"brand","type":"ObjProp"} +{"features":" {score:0.023183089391543316} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.023183089391543316} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.05373960618789379} ","formula":"property:brand","lexeme":"brand","type":"ObjProp"} +{"features":" {score:0.01230769230769231} ","formula":"!property:line","lexeme":"line","type":"ObjProp"} +{"features":" {score:0.01230769230769231} ","formula":"!property:line","lexeme":"line","type":"DataProp"} +{"features":" {score:0.03681289980044732} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.023183089391543316} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.397716586460902} ","formula":"resource:Alec_Baldwin","lexeme":"alec baldwin","type":"NamedEntity"} +{"features":" {score:0.01230769230769231} ","formula":"property:line","lexeme":"line","type":"ObjProp"} +{"features":" {score:0.023183089391543316} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.05373960618789379} ","formula":"!dbpedia:brand","lexeme":"brand","type":"ObjectProp"} +{"features":" {score:0.03681289980044732} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.01230769230769231} ","formula":"property:line","lexeme":"line","type":"DataProp"} +{"features":" {score:0.5426921993804562} ","formula":"resource:Alex_Ferguson","lexeme":"alex ferguson","type":"NamedEntity"} +{"features":" {score:0.023183089391543316} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.13999229669570923} ","formula":"(rdf:type dbpedia:Wrestler)","lexeme":"wrestler","type":"ClassNoun"} +{"features":" {score:0.01230769230769231} ","formula":"!dbpedia:routeLine","lexeme":"line","type":"ObjectProp"} +{"features":" {score:0.03681289980044732} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.05373960618789379} ","formula":"!property:brand","lexeme":"brand","type":"DataProp"} +{"features":" {score:0.023183089391543316} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.12696447372436523} ","formula":"(rdf:type dbpedia:Jockey)","lexeme":"jockey","type":"ClassNoun"} +{"features":" {score:0.05373960618789379} ","formula":"property:brand","lexeme":"brand","type":"DataProp"} +{"features":" {score:0.13098052740097046} ","formula":"(rdf:type dbpedia:Swimmer)","lexeme":"swimmer","type":"ClassNoun"} +{"features":" {score:0.39343532363954176} ","formula":"\u003chttp://dbpedia.org/resource/Salon_(website)\u003e","lexeme":"salon website","type":"NamedEntity"} +{"features":" {score:0.03681289980044732} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.023183089391543316} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.3786297717788662} ","formula":"resource:Alexander_von_Humboldt","lexeme":"alexander von humboldt","type":"NamedEntity"} +{"features":" {score:0.01230769230769231} ","formula":"dbpedia:routeLine","lexeme":"line","type":"ObjectProp"} +{"features":" {score:0.05373960618789379} ","formula":"dbpedia:brand","lexeme":"brand","type":"ObjectProp"} +{"features":" {score:0.03681289980044732} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.3746308982221216} ","formula":"resource:Pope_Alexander_VI","lexeme":"pope alexander vi","type":"NamedEntity"} +{"features":" {score:0.05373960618789379} ","formula":"!property:brand","lexeme":"brand","type":"ObjProp"} +{"features":" {score:0.023183089391543316} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.023183089391543316} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.05373960618789379} ","formula":"property:brand","lexeme":"brand","type":"ObjProp"} +{"features":" {score:0.01230769230769231} ","formula":"!property:line","lexeme":"line","type":"ObjProp"} +{"features":" {score:0.01230769230769231} ","formula":"!property:line","lexeme":"line","type":"DataProp"} +{"features":" {score:0.03681289980044732} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.023183089391543316} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.397716586460902} ","formula":"resource:Alec_Baldwin","lexeme":"alec baldwin","type":"NamedEntity"} +{"features":" {score:0.01230769230769231} ","formula":"property:line","lexeme":"line","type":"ObjProp"} +{"features":" {score:0.023183089391543316} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.05373960618789379} ","formula":"!dbpedia:brand","lexeme":"brand","type":"ObjectProp"} +{"features":" {score:0.03681289980044732} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.01230769230769231} ","formula":"property:line","lexeme":"line","type":"DataProp"} +{"features":" {score:0.5426921993804562} ","formula":"resource:Alex_Ferguson","lexeme":"alex ferguson","type":"NamedEntity"} +{"features":" {score:0.023183089391543316} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.13999229669570923} ","formula":"(rdf:type dbpedia:Wrestler)","lexeme":"wrestler","type":"ClassNoun"} +{"features":" {score:0.01230769230769231} ","formula":"!dbpedia:routeLine","lexeme":"line","type":"ObjectProp"} +{"features":" {score:0.03681289980044732} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.05373960618789379} ","formula":"!property:brand","lexeme":"brand","type":"DataProp"} +{"features":" {score:0.023183089391543316} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.12696447372436523} ","formula":"(rdf:type dbpedia:Jockey)","lexeme":"jockey","type":"ClassNoun"} +{"features":" {score:0.05373960618789379} ","formula":"property:brand","lexeme":"brand","type":"DataProp"} +{"features":" {score:0.13098052740097046} ","formula":"(rdf:type dbpedia:Swimmer)","lexeme":"swimmer","type":"ClassNoun"} +{"features":" {score:0.39343532363954176} ","formula":"\u003chttp://dbpedia.org/resource/Salon_(website)\u003e","lexeme":"salon website","type":"NamedEntity"} +{"features":" {score:0.03681289980044732} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.023183089391543316} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.3786297717788662} ","formula":"resource:Alexander_von_Humboldt","lexeme":"alexander von humboldt","type":"NamedEntity"} +{"features":" {score:0.01230769230769231} ","formula":"dbpedia:routeLine","lexeme":"line","type":"ObjectProp"} +{"features":" {score:0.05373960618789379} ","formula":"dbpedia:brand","lexeme":"brand","type":"ObjectProp"} +{"features":" {score:0.03681289980044732} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.3746308982221216} ","formula":"resource:Pope_Alexander_VI","lexeme":"pope alexander vi","type":"NamedEntity"} +{"features":" {score:0.05373960618789379} ","formula":"!property:brand","lexeme":"brand","type":"ObjProp"} +{"features":" {score:0.023183089391543316} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.023183089391543316} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.05373960618789379} ","formula":"property:brand","lexeme":"brand","type":"ObjProp"} +{"features":" {score:0.01230769230769231} ","formula":"!property:line","lexeme":"line","type":"ObjProp"} +{"features":" {score:0.01230769230769231} ","formula":"!property:line","lexeme":"line","type":"DataProp"} +{"features":" {score:0.03681289980044732} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.023183089391543316} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.397716586460902} ","formula":"resource:Alec_Baldwin","lexeme":"alec baldwin","type":"NamedEntity"} +{"features":" {score:0.01230769230769231} ","formula":"property:line","lexeme":"line","type":"ObjProp"} +{"features":" {score:0.023183089391543316} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.05373960618789379} ","formula":"!dbpedia:brand","lexeme":"brand","type":"ObjectProp"} +{"features":" {score:0.03681289980044732} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.01230769230769231} ","formula":"property:line","lexeme":"line","type":"DataProp"} +{"features":" {score:0.5426921993804562} ","formula":"resource:Alex_Ferguson","lexeme":"alex ferguson","type":"NamedEntity"} +{"features":" {score:0.023183089391543316} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.13999229669570923} ","formula":"(rdf:type dbpedia:Wrestler)","lexeme":"wrestler","type":"ClassNoun"} +{"features":" {score:0.01230769230769231} ","formula":"!dbpedia:routeLine","lexeme":"line","type":"ObjectProp"} +{"features":" {score:0.03681289980044732} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.05373960618789379} ","formula":"!property:brand","lexeme":"brand","type":"DataProp"} +{"features":" {score:0.023183089391543316} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.12696447372436523} ","formula":"(rdf:type dbpedia:Jockey)","lexeme":"jockey","type":"ClassNoun"} +{"features":" {score:0.05373960618789379} ","formula":"property:brand","lexeme":"brand","type":"DataProp"} +{"features":" {score:0.13098052740097046} ","formula":"(rdf:type dbpedia:Swimmer)","lexeme":"swimmer","type":"ClassNoun"} +{"features":" {score:0.02754881125994218} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.02492670177649229} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.02754881125994218} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.03030440770662748} ","formula":"(rdf:type dbpedia:Area)","lexeme":"area","type":"ClassNoun"} +{"features":" {score:0.018827202090850245} ","formula":"dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.03030440770662748} ","formula":"property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.018827202090850245} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.02492670177649229} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.02754881125994218} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.03030440770662748} ","formula":"!property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.02492670177649229} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.018827202090850245} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.02492670177649229} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.07183589378992716} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.3449200540738764} ","formula":"resource:Las_Vegas_Valley","lexeme":"las vegas valley","type":"NamedEntity"} +{"features":" {score:0.07183589378992716} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.010833333333333334} ","formula":"!property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.036267271011303635} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.5069101221863358} ","formula":"resource:United_States","lexeme":"united states","type":"NamedEntity"} +{"features":" {score:0.010833333333333334} ","formula":"property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.036267271011303635} ","formula":"property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.3376957938374635} ","formula":"resource:United_States_Army","lexeme":"united states army","type":"NamedEntity"} +{"features":" {score:0.1210140109062195} ","formula":"(rdf:type dbpedia:Community)","lexeme":"community","type":"ClassNoun"} +{"features":" {score:0.010833333333333334} ","formula":"!property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.010833333333333334} ","formula":"property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.018827202090850245} ","formula":"!dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.018827202090850245} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.02754881125994218} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.036267271011303635} ","formula":"property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.3712715210874318} ","formula":"\u003chttp://dbpedia.org/resource/Georgia_(U.S._state)\u003e","lexeme":"georgia u.s. state","type":"NamedEntity"} +{"features":" {score:0.13348385095596313} ","formula":"(rdf:type dbpedia:Cave)","lexeme":"cave","type":"ClassNoun"} +{"features":" {score:0.018827202090850245} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.02492670177649229} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.03030440770662748} ","formula":"property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.07183589378992716} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.13700512091318767} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.036267271011303635} ","formula":"!property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.5019569461422774} ","formula":"resource:USA_Today","lexeme":"usa today","type":"NamedEntity"} +{"features":" {score:0.03030440770662748} ","formula":"!property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.5633483858744451} ","formula":"resource:FC_Bayern_Munich","lexeme":"fc bayern munich","type":"NamedEntity"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.15446644224988318} ","formula":"dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.15446644224988318} ","formula":"!property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.0200734452320266} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"(rdf:type dbpedia:University)","lexeme":"university","type":"ClassNoun"} +{"features":" {score:0.2703449835345485} ","formula":"dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.2703449835345485} ","formula":"property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.0200734452320266} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.0200734452320266} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.2703449835345485} ","formula":"!property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.2703449835345485} ","formula":"!dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.15446644224988318} ","formula":"!dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.5245180850163047} ","formula":"resource:Munich_Agreement","lexeme":"munich agreement","type":"NamedEntity"} +{"features":" {score:0.0200734452320266} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.6420831407783865} ","formula":"resource:Munich","lexeme":"munich","type":"NamedEntity"} +{"features":" {score:0.5336177996667898} ","formula":"resource:Ludwig_Maximilian_University_of_Munich","lexeme":"ludwig maximilian university of munich","type":"NamedEntity"} +{"features":" {score:0.15446644224988318} ","formula":"(rdf:type dbpedia:Municipality)","lexeme":"municipality","type":"ClassNoun"} +{"features":" {score:0.15446644224988318} ","formula":"!property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.15446644224988318} ","formula":"property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.394651691061635} ","formula":"resource:1972_Summer_Olympics","lexeme":"1972 summer olympics","type":"NamedEntity"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.2703449835345485} ","formula":"!property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.15446644224988318} ","formula":"property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.0200734452320266} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.006745657462310337} ","formula":"!dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.2703449835345485} ","formula":"(rdf:type dbpedia:City)","lexeme":"city","type":"ClassNoun"} +{"features":" {score:0.006745657462310337} ","formula":"dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.05713644355625896} ","formula":"(rdf:type dbpedia:Airport)","lexeme":"airport","type":"ClassNoun"} +{"features":" {score:0.2703449835345485} ","formula":"property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.024354053257352713} ","formula":"property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.024354053257352713} ","formula":"property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.019684884847898314} ","formula":"property:case","lexeme":"case","type":"ObjProp"} +{"features":" {score:0.04119084299478716} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.04307977245656418} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.018446601941747572} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.04307977245656418} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.019684884847898314} ","formula":"!property:case","lexeme":"case","type":"DataProp"} +{"features":" {score:0.12119717597961427} ","formula":"dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.02330097087378641} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.019684884847898314} ","formula":"!property:case","lexeme":"case","type":"ObjProp"} +{"features":" {score:0.02330097087378641} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.04307977245656418} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.02330097087378641} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.019684884847898314} ","formula":"property:case","lexeme":"case","type":"DataProp"} +{"features":" {score:0.12119717597961427} ","formula":"!dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.04307977245656418} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.018446601941747572} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.024354053257352713} ","formula":"!property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.3600622212941572} ","formula":"\u003chttp://dbpedia.org/resource/Galicia_(Eastern_Europe)\u003e","lexeme":"galicia eastern europe","type":"NamedEntity"} +{"features":" {score:0.04119084299478716} ","formula":"!property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.3138386448463968} ","formula":"resource:Odessa","lexeme":"odessa","type":"NamedEntity"} +{"features":" {score:0.04119084299478716} ","formula":"property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.024354053257352713} ","formula":"!property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.018446601941747572} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.38531734665303335} ","formula":"resource:Ukrainian_Soviet_Socialist_Republic","lexeme":"ukrainian soviet socialist republic","type":"NamedEntity"} +{"features":" {score:0.04307977245656418} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.3847475641953887} ","formula":"resource:Kiev","lexeme":"kiev","type":"NamedEntity"} +{"features":" {score:0.04307977245656418} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.6268662072925639} ","formula":"resource:Ukraine","lexeme":"ukraine","type":"NamedEntity"} +{"features":" {score:0.04119084299478716} ","formula":"property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.02330097087378641} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.04307977245656418} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.019684884847898314} ","formula":"(rdf:type dbpedia:Case)","lexeme":"case","type":"ClassNoun"} +{"features":" {score:0.02330097087378641} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.018446601941747572} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.5197176288417931} ","formula":"!property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.6084271220137483} ","formula":"resource:Bob_Dylan","lexeme":"bob dylan","type":"NamedEntity"} +{"features":" {score:0.5197176288417931} ","formula":"property:name","lexeme":"name","type":"ObjProp"} +{"features":" {score:0.13272552490234377} ","formula":"(rdf:type dbpedia:Comedian)","lexeme":"comedian","type":"ClassNoun"} +{"features":" {score:0.13186320699751378} ","formula":"(rdf:type dbpedia:Wrestler)","lexeme":"wrestler","type":"ClassNoun"} +{"features":" {score:0.08796091386892277} ","formula":"(rdf:type dbpedia:Person)","lexeme":"person","type":"ClassNoun"} +{"features":" {score:0.03137576233741292} ","formula":"property:student","lexeme":"student","type":"ObjProp"} +{"features":" {score:0.08796091386892277} ","formula":"property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.08796091386892277} ","formula":"!property:person","lexeme":"person","type":"ObjProp"} +{"features":" {score:0.13504673363640904} ","formula":"(rdf:type dbpedia:Jockey)","lexeme":"jockey","type":"ClassNoun"} +{"features":" {score:0.08796091386892277} ","formula":"property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.03137576233741292} ","formula":"!property:student","lexeme":"student","type":"DataProp"} +{"features":" {score:0.5197176288417931} ","formula":"property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.5197176288417931} ","formula":"(rdf:type dbpedia:Name)","lexeme":"name","type":"ClassNoun"} +{"features":" {score:0.5398806299023015} ","formula":"resource:Bob_Hope","lexeme":"bob hope","type":"NamedEntity"} +{"features":" {score:0.08796091386892277} ","formula":"!dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.5197176288417931} ","formula":"!property:name","lexeme":"name","type":"DataProp"} +{"features":" {score:0.061251357772163846} ","formula":"(rdf:type dbpedia:Artist)","lexeme":"artist","type":"ClassNoun"} +{"features":" {score:0.45588200764843745} ","formula":"resource:Robert_De_Niro","lexeme":"robert de niro","type":"NamedEntity"} +{"features":" {score:0.08796091386892277} ","formula":"!property:person","lexeme":"person","type":"DataProp"} +{"features":" {score:0.03137576233741292} ","formula":"!property:student","lexeme":"student","type":"ObjProp"} +{"features":" {score:0.3332550072731342} ","formula":"resource:Bobsleigh","lexeme":"bobsleigh","type":"NamedEntity"} +{"features":" {score:0.5361657367614264} ","formula":"resource:Bob_Marley","lexeme":"bob marley","type":"NamedEntity"} +{"features":" {score:0.08796091386892277} ","formula":"dbpedia:person","lexeme":"person","type":"ObjectProp"} +{"features":" {score:0.03137576233741292} ","formula":"property:student","lexeme":"student","type":"DataProp"} +{"features":" {score:0.039105719999382775} ","formula":"(rdf:type dbpedia:Airport)","lexeme":"airport","type":"ClassNoun"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"(rdf:type dbpedia:University)","lexeme":"university","type":"ClassNoun"} +{"features":" {score:0.06491494770435727} ","formula":"!property:institution","lexeme":"institution","type":"DataProp"} +{"features":" {score:0.13518829246017713} ","formula":"(rdf:type dbpedia:City)","lexeme":"city","type":"ClassNoun"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"!dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.007118905612640406} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.06491494770435727} ","formula":"property:institution","lexeme":"institution","type":"DataProp"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.6285851188338059} ","formula":"resource:Texas_Tech_University","lexeme":"texas tech university","type":"NamedEntity"} +{"features":" {score:0.34189207904479085} ","formula":"!property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.6252712786778605} ","formula":"resource:Private_university","lexeme":"private university","type":"NamedEntity"} +{"features":" {score:0.06491494770435727} ","formula":"!property:institution","lexeme":"institution","type":"ObjProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.34189207904479085} ","formula":"property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.3574573272887659} ","formula":"resource:1972_Summer_Olympics","lexeme":"1972 summer olympics","type":"NamedEntity"} +{"features":" {score:0.0048526863084922016} ","formula":"dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.13518829246017713} ","formula":"dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.4527074563224413} ","formula":"resource:ETH_Zurich","lexeme":"eth zurich","type":"NamedEntity"} +{"features":" {score:0.5069005576208179} ","formula":"resource:Munich_Agreement","lexeme":"munich agreement","type":"NamedEntity"} +{"features":" {score:0.539723393814838} ","formula":"resource:Rensselaer_Polytechnic_Institute","lexeme":"rensselaer polytechnic institute","type":"NamedEntity"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.6278378455727189} ","formula":"resource:Saint_Petersburg_State_University","lexeme":"saint petersburg state university","type":"NamedEntity"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.34189207904479085} ","formula":"(rdf:type dbpedia:University)","lexeme":"university","type":"ClassNoun"} +{"features":" {score:0.34189207904479085} ","formula":"property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.06491494770435727} ","formula":"dbpedia:institution","lexeme":"institution","type":"ObjectProp"} +{"features":" {score:0.13518829246017713} ","formula":"!dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.6244656133828996} ","formula":"resource:Munich","lexeme":"munich","type":"NamedEntity"} +{"features":" {score:0.02476466395722725} ","formula":"dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.34189207904479085} ","formula":"!property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.34189207904479085} ","formula":"dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.5156482342007435} ","formula":"resource:Ludwig_Maximilian_University_of_Munich","lexeme":"ludwig maximilian university of munich","type":"NamedEntity"} +{"features":" {score:0.34189207904479085} ","formula":"!dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"!dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.06491494770435727} ","formula":"property:institution","lexeme":"institution","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.06491494770435727} ","formula":"!dbpedia:institution","lexeme":"institution","type":"ObjectProp"} +{"features":" {score:0.02476466395722725} ","formula":"(rdf:type dbpedia:Municipality)","lexeme":"municipality","type":"ClassNoun"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.5222235130111524} ","formula":"resource:FC_Bayern_Munich","lexeme":"fc bayern munich","type":"NamedEntity"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.46914285714285714} ","formula":"resource:Alona_Bondarenko","lexeme":"alona bondarenko","type":"NamedEntity"} +{"features":" {score:0.32234833338271296} ","formula":"resource:Alona_Tal","lexeme":"alona tal","type":"NamedEntity"} +{"features":" {score:0.34205261966160366} ","formula":"resource:Alona_Regional_Council","lexeme":"alona regional council","type":"NamedEntity"} +{"features":" {score:0.30342857142857144} ","formula":"resource:Olena_Dvornichenko","lexeme":"olena dvornichenko","type":"NamedEntity"} +{"features":" {score:0.30228571428571427} ","formula":"resource:Alona_Alegre","lexeme":"alona alegre","type":"NamedEntity"} +{"features":" {score:0.46914285714285714} ","formula":"resource:Alona_Bondarenko","lexeme":"alona bondarenko","type":"NamedEntity"} +{"features":" {score:0.32234833338271296} ","formula":"resource:Alona_Tal","lexeme":"alona tal","type":"NamedEntity"} +{"features":" {score:0.34205261966160366} ","formula":"resource:Alona_Regional_Council","lexeme":"alona regional council","type":"NamedEntity"} +{"features":" {score:0.30342857142857144} ","formula":"resource:Olena_Dvornichenko","lexeme":"olena dvornichenko","type":"NamedEntity"} +{"features":" {score:0.30228571428571427} ","formula":"resource:Alona_Alegre","lexeme":"alona alegre","type":"NamedEntity"} +{"features":" {score:0.46914285714285714} ","formula":"resource:Alona_Bondarenko","lexeme":"alona bondarenko","type":"NamedEntity"} +{"features":" {score:0.32234833338271296} ","formula":"resource:Alona_Tal","lexeme":"alona tal","type":"NamedEntity"} +{"features":" {score:0.34205261966160366} ","formula":"resource:Alona_Regional_Council","lexeme":"alona regional council","type":"NamedEntity"} +{"features":" {score:0.30342857142857144} ","formula":"resource:Olena_Dvornichenko","lexeme":"olena dvornichenko","type":"NamedEntity"} +{"features":" {score:0.30228571428571427} ","formula":"resource:Alona_Alegre","lexeme":"alona alegre","type":"NamedEntity"} +{"features":" {score:0.3} ","formula":"resource:Mihir_Rakshit","lexeme":"mihir rakshit","type":"NamedEntity"} +{"features":" {score:0.3} ","formula":"resource:Tushar_Rakshit","lexeme":"tushar rakshit","type":"NamedEntity"} +{"features":" {score:0.08495274583498637} ","formula":"dbpedia:bird","lexeme":"bird","type":"ObjectProp"} +{"features":" {score:0.08495274583498637} ","formula":"!dbpedia:bird","lexeme":"bird","type":"ObjectProp"} +{"features":" {score:0.08495274583498637} ","formula":"(rdf:type dbpedia:Bird)","lexeme":"bird","type":"ClassNoun"} +{"features":" {score:0.3576923076923077} ","formula":"resource:Maasina_Ruru","lexeme":"maasina ruru","type":"NamedEntity"} +{"features":" {score:0.010526315789473684} ","formula":"property:word","lexeme":"word","type":"ObjProp"} +{"features":" {score:0.1044997806611814} ","formula":"(rdf:type dbpedia:Town)","lexeme":"town","type":"ClassNoun"} +{"features":" {score:0.4617332560218821} ","formula":"resource:Yeah_Yeah_Yeahs","lexeme":"yeah yeah yeahs","type":"NamedEntity"} +{"features":" {score:0.010526315789473684} ","formula":"!property:word","lexeme":"word","type":"ObjProp"} +{"features":" {score:0.010526315789473684} ","formula":"!property:word","lexeme":"word","type":"DataProp"} +{"features":" {score:0.36860687021256944} ","formula":"resource:Clap_Your_Hands_Say_Yeah","lexeme":"clap your hands say yeah","type":"NamedEntity"} +{"features":" {score:0.3732392820973618} ","formula":"\u003chttp://dbpedia.org/resource/Yea,_Victoria\u003e","lexeme":"yea, victoria","type":"NamedEntity"} +{"features":" {score:0.010526315789473684} ","formula":"property:word","lexeme":"word","type":"DataProp"} +{"features":" {score:0.02567163814449966} ","formula":"property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.08450248734030909} ","formula":"property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.0587563043972628} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.655103930106647} ","formula":"resource:Ukraine","lexeme":"ukraine","type":"NamedEntity"} +{"features":" {score:0.018446601941747572} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.415187410413021} ","formula":"resource:Kiev","lexeme":"kiev","type":"NamedEntity"} +{"features":" {score:0.1350558975711465} ","formula":"dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.026219150202174017} ","formula":"property:case","lexeme":"case","type":"DataProp"} +{"features":" {score:0.0587563043972628} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.035429939596904714} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.08450248734030909} ","formula":"property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.018446601941747572} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.02567163814449966} ","formula":"!property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.3600622212941572} ","formula":"\u003chttp://dbpedia.org/resource/Galicia_(Eastern_Europe)\u003e","lexeme":"galicia eastern europe","type":"NamedEntity"} +{"features":" {score:0.08450248734030909} ","formula":"!property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.0587563043972628} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.035429939596904714} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.0587563043972628} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.035429939596904714} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.1350558975711465} ","formula":"!dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.035429939596904714} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.02567163814449966} ","formula":"property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.02567163814449966} ","formula":"!property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.3138386448463968} ","formula":"resource:Odessa","lexeme":"odessa","type":"NamedEntity"} +{"features":" {score:0.0587563043972628} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.035429939596904714} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.026219150202174017} ","formula":"(rdf:type dbpedia:Case)","lexeme":"case","type":"ClassNoun"} +{"features":" {score:0.018446601941747572} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.026219150202174017} ","formula":"!property:case","lexeme":"case","type":"DataProp"} +{"features":" {score:0.0587563043972628} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.0587563043972628} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.026219150202174017} ","formula":"property:case","lexeme":"case","type":"ObjProp"} +{"features":" {score:0.018446601941747572} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.08450248734030909} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.48692732175259695} ","formula":"resource:Ukrainian_Soviet_Socialist_Republic","lexeme":"ukrainian soviet socialist republic","type":"NamedEntity"} +{"features":" {score:0.026219150202174017} ","formula":"!property:case","lexeme":"case","type":"ObjProp"} From 480b64bdd7a576be1cc4ff06d1ae615e490f5f98 Mon Sep 17 00:00:00 2001 From: mireu Date: Fri, 7 Sep 2018 17:48:51 +0200 Subject: [PATCH 125/147] Removed double entries from config.properties --- config.properties | 2 -- 1 file changed, 2 deletions(-) diff --git a/config.properties b/config.properties index 28e02192..d1559aa8 100755 --- a/config.properties +++ b/config.properties @@ -37,8 +37,6 @@ INPUT: cmdline # multiple outputs are allowed, defaults to cmdline OUTPUTS: - cmdline -# - telegram -# - ibm # - cerevoice # - freetts # - ibm From dd62487d26de1465dcea70954d09881766cb291f Mon Sep 17 00:00:00 2001 From: mireu Date: Sat, 8 Sep 2018 10:33:10 +0200 Subject: [PATCH 126/147] Improved documentation --- .../roboy/dialog/ConversationManager.java | 24 +++++--- .../ordinaryStates/PassiveGreetingsState.java | 2 +- .../src/main/java/roboy/io/TelegramInput.java | 1 + .../util/TelegramCommunicationHandler.java | 12 ++-- docs/developer_manual/1_Tutorials.rst | 55 +++++++++++++++++++ 5 files changed, 81 insertions(+), 13 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index dee9853a..eac19dcd 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -104,6 +104,7 @@ public static void main(String[] args) throws IOException { logger.error("Telegram bots api error: ", e); } + //begin operation logger.info("####################################################\n# SYSTEM LOADED #\n####################################################\n"); commandMode(); break; @@ -116,8 +117,8 @@ public static void main(String[] args) throws IOException { do {//repeat conversations if configured to do so demoReadyCheck(); Conversation c = createConversation(rosMainNode, analyzers, new Inference(), memory, "local"); - c.start(); + try {//Since this is roboy mode and only one conversation happens, we need to wait for it to finish so we don't clog the command line. logger.info("Waiting for conversation to end."); c.join(); @@ -136,7 +137,7 @@ public static void main(String[] args) throws IOException { /** * Creates and spawns a conversation for a chatuser. - * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" + * @param uuid should consist of "[world-interface-name]-[uuid]", if input allows only a single user, set to "local" * @throws IOException If conversation could not created. */ public static void spawnConversation(String uuid) throws IOException { @@ -144,7 +145,7 @@ public static void spawnConversation(String uuid) throws IOException { } /** * Creates and spawns a conversation for a chatuser. - * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" + * @param uuid should consist of "[world-interface-name]-[uuid]", if input allows only a single user, set to "local" * @param name the name of the Interlocutor. Necessary for unique adressing by name (local nodes) * @throws IOException If conversation could not created. */ @@ -164,7 +165,7 @@ protected static void deregisterConversation(Conversation conversation){ /** * Stops conversation thread for uuid. - * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" + * @param uuid should consist of "[world-interface-name]-[uuid]", if input allows only a single user, set to "local" */ public static void stopConversation(String uuid){ Conversation c = conversations.get(uuid); @@ -177,7 +178,7 @@ public static void stopConversation(String uuid){ /** * returns the threadID of the conversation with interlocutor uuid - * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" + * @param uuid should consist of "[world-interface-name]-[uuid]", if input allows only a single user, set to "local" * @return null if thread does not exist, threadID otherwise */ public static Long getConversationThreadID(String uuid){ @@ -192,7 +193,7 @@ public static Long getConversationThreadID(String uuid){ * @param analyzers All analyzers necessary for analyzing the inputs from multiIn. Please provide these in correct order. * @param inference Inference engine. The better, the smarter roboy gets. * @param memory Roboy memory access. Without, we cannot remember anything and conversations stay shallow. - * @param uuid should consist of "servicename-[uuid]", if input allows only a single user, set to "local" + * @param uuid should consist of "[world-interface-name]-[uuid]", if input allows only a single user, set to "local" * @return null if uuroboy.dialog.Conversation object. Fully intialized, ready to launch. * @throws IOException In case the IOdevices could not be correctly initialized. */ @@ -213,7 +214,7 @@ private static Conversation createConversation(RosMainNode rosMainNode, List update, String name) { diff --git a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java index 71663d6e..e063593c 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java @@ -34,7 +34,7 @@ public class TelegramCommunicationHandler extends TelegramLongPollingBot impleme private static final int INPUT_TIME_LIMIT = 5; //SECONDS // CHAT ID ----- ITS MESSAGE - private volatile List>> pairs = new ArrayList<>(); + private volatile List>> pairs = new ArrayList<>();//[UserName, [UserID, Message]] private List telegramTimeouts; //Timeouts private final static int initTime = (int) (System.currentTimeMillis() / 1000L); //in order to discard messages older than launch @@ -113,6 +113,10 @@ public void onUpdateReceived(Update update) { TelegramCommandHandler commandHandler = new TelegramCommandHandler(text, chatID); commandHandler.execute(); }else{ + //try to find a suitable way to adress the interlocutor + //first, try to find their user name + //if that didn't work try to find their real first name + //if that also didn't work adress them as "telegram user [userid] if(message.getFrom().getUserName() != null){ name = message.getFrom().getUserName().toLowerCase(); } @@ -156,9 +160,9 @@ public void onTimeout(String chatID) { // get the all messages Pair> result = null; - for(Pair> pa : pairs){ - Pair p = pa.getValue(); - String name = pa.getKey(); + for(Pair> pa : pairs){//iterate over triples: [Username, [ChatID, Text]] + Pair p = pa.getValue();//get [ChatID,Text] + String name = pa.getKey();//get Username //Map a = new HashMap(); if(!chatID.equals(p.getKey())){ continue; diff --git a/docs/developer_manual/1_Tutorials.rst b/docs/developer_manual/1_Tutorials.rst index 54a5b7ed..98ba01af 100644 --- a/docs/developer_manual/1_Tutorials.rst +++ b/docs/developer_manual/1_Tutorials.rst @@ -839,6 +839,61 @@ Finish the ``act`` method Now you need to tell the dialog system how to use your new in- and output. Refer to :ref:`tut_generic_social_media_io` in order to tell the dialog system where to find them and how to allow users to activate them. Now rebuild your code, select your Input/OutputDevice in config.properties and run it to see the work you have achieved. +New Memory UUID +------------------ + +If you create support for a new chat service, you will probably need to use uuids in the format "yourservicename-[uuid]". These must be carefully integrated with the memory in order to avoid confusion of the inter-service interlocutor recognition. + +First, check if `roboy.util.UUidType` already contains a type for the service you are integrating. If not, add it to `roboy.util.UuidType` in dialog and the attributes necessary for the id to `roboy.memory.Neo4jLabel` and `roboy.memory.Neo4jProperty` in roboy memory. (note: CamelCase is not supported for these) + +Second, add usage of your new UUID within `roboy.dialog.ConversationManager` (the section you are looking for is marked with `//memory uuid handling``). + +Now, an example: + +First, we create the telegram uuid: +We create a `Neo4jProperty` by extending the enum at the beginning, +:: + public enum Neo4jProperty { + [...] + telegram_id("telegram_id"), + [...] +:: +we create a `Neo4jLabel` by extending that enum too, +:: +public enum Neo4jLabel { + [...] + Telegram_person("Telegram_person"), + [...] +:: +then, we create the `UuidType` and the necessary conversions +:: + public enum UuidType { + TELEGRAM_UUID, + [...] + public boolean isValidUuid(String uuid) { + switch (this) { + case TELEGRAM_UUID: + return true; + [...] + public Neo4jProperty toNeo4jProperty() { + switch (this) { + case TELEGRAM_UUID: + return Neo4jProperty.telegram_id; + [...] + public Neo4jLabel toNeo4jLabel() { + switch (this) { + case TELEGRAM_UUID: + return Neo4jLabel.Telegram_person; + [...] +:: +finally, we add our new service to `roboy.dialog.ConversationManager` +:: + //memory uuid handling + [...] + else if (uuid.startsWith("telegram-")) { + person.addUuid(new Uuid(UuidType.TELEGRAM_UUID, uuid.substring(uuid.indexOf('-') + 1)), name); + [...] +:: Telegram: Handle commands ------------------------- From f0a6921013d9f0b15fe802be6957f9ef5fed6bde Mon Sep 17 00:00:00 2001 From: missxa Date: Mon, 10 Sep 2018 00:26:45 +0200 Subject: [PATCH 127/147] fixed emotions, minor states bugfixes --- .gitignore | 1 + config.properties | 8 +- .../roboy/dialog/action/EmotionAction.java | 8 ++ .../dialog/states/botboy/BotBoyState.java | 2 +- .../devoStates/QuestionRoboyQAState.java | 1 + .../GamingTwentyQuestionsState.java | 13 +-- .../states/ordinaryStates/WildTalkState.java | 2 +- .../java/roboy/emotions/RoboyEmotion.java | 90 ++++++++++++------- .../main/java/roboy/io/TelegramOutput.java | 18 +--- .../sentenceanalysis/EmotionAnalyzer.java | 8 +- dialog/src/main/java/roboy/util/Lists.java | 1 + resources_nlu/error_test/newLexicon.txt | 76 ++++++++++++++++ 12 files changed, 169 insertions(+), 59 deletions(-) diff --git a/.gitignore b/.gitignore index 3e3e3899..55df7eaf 100644 --- a/.gitignore +++ b/.gitignore @@ -77,3 +77,4 @@ nlu/parser/src/main/java/edu/stanford/nlp/sempre/roboy/api/apiKeys\.yml dialog/src/main/java/roboy/util/api/apiKeys\.yml dialog/src/main/java/roboy/util/api/apiKeys.yml +resources/telegram.json diff --git a/config.properties b/config.properties index 28e02192..95b08a95 100755 --- a/config.properties +++ b/config.properties @@ -28,16 +28,16 @@ DEMO_MODE: false INFINITE_REPETITION: true # only single input is allowed, defaults to cmdline -INPUT: cmdline +#INPUT: cmdline #INPUT: cerevoice #INPUT: udp #INPUT: bing -#INPUT: telegram +INPUT: telegram # multiple outputs are allowed, defaults to cmdline OUTPUTS: - cmdline -# - telegram +- telegram # - ibm # - cerevoice # - freetts @@ -68,7 +68,7 @@ IBM_TTS_PASS: "" CONTEXT_GUI_ENABLED: false ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/scripts/action_client.py" -TELEGRAM_API_TOKENS_FILE: "" +TELEGRAM_API_TOKENS_FILE: "resources/telegram.json" PARLAI_PORT: 8877 PARLAI_HOST: "127.0.0.1" diff --git a/dialog/src/main/java/roboy/dialog/action/EmotionAction.java b/dialog/src/main/java/roboy/dialog/action/EmotionAction.java index 52bb66a4..a9c33708 100755 --- a/dialog/src/main/java/roboy/dialog/action/EmotionAction.java +++ b/dialog/src/main/java/roboy/dialog/action/EmotionAction.java @@ -11,6 +11,7 @@ public class EmotionAction implements Action { private String state; + private String name; private int duration; /** @@ -36,6 +37,7 @@ public EmotionAction(RoboyEmotion state) { this.state = state.type; this.duration = 1; + this.name = state.name(); } /** @@ -60,6 +62,7 @@ public EmotionAction(RoboyEmotion state, int duration) { this.state = state.type; this.duration = duration; + this.name = state.name(); } public String getState() @@ -72,4 +75,9 @@ public int getDuration() return this.duration; } + public String getName() { + if (this.name == null) + return this.state; + return this.name; + } } \ No newline at end of file diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java index 26ae6e35..6080817a 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java @@ -111,7 +111,7 @@ public Output react(Interpretation input) { Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + retrievedPersonalFact + " It is great to see you again!") - .setEmotion(RoboyEmotion.HAPPINESS) + .setEmotion(RoboyEmotion.positive.getRandomElement()) .setSegue(s); } else { // 4b. person is not known diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 76cba6b0..cf530bc7 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -156,6 +156,7 @@ public State getNextState() { } private Output useMemoryOrFallback(Interpretation input) { + questionsAnswered++; try { if ( input.getPas() != null || input.getTriples() != null) { Output memoryAnswer = answerFromMemory(input); diff --git a/dialog/src/main/java/roboy/dialog/states/gameStates/GamingTwentyQuestionsState.java b/dialog/src/main/java/roboy/dialog/states/gameStates/GamingTwentyQuestionsState.java index 6bb45962..1550b877 100644 --- a/dialog/src/main/java/roboy/dialog/states/gameStates/GamingTwentyQuestionsState.java +++ b/dialog/src/main/java/roboy/dialog/states/gameStates/GamingTwentyQuestionsState.java @@ -8,16 +8,19 @@ import com.markozajc.akiwrapper.core.entities.Guess; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.yecht.ruby.Out; import roboy.context.Context; import roboy.dialog.Segue; import roboy.dialog.states.definitions.State; import roboy.dialog.states.definitions.StateParameters; +import roboy.emotions.RoboyEmotion; import roboy.linguistics.Linguistics; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.memory.nodes.Interlocutor; import roboy.ros.RosMainNode; import roboy.talk.PhraseCollection; import roboy.talk.Verbalizer; +import roboy.util.Lists; import roboy.util.RandomList; import java.io.IOException; @@ -213,14 +216,14 @@ private Output saveUsersEstimate(String intent) { private Output doAGuess (){ - String roboyAnswer = ""; + Output roboyAnswer = null; try { for (Guess guess : aw.getGuessesAboveProbability(PROBABILITY_THRESHOLD)) { if (!declined.contains(Long.valueOf(guess.getIdLong()))) { - roboyAnswer = PhraseCollection.QUESTION_ANSWERING_START.getRandomElement() + guess.getName(); + roboyAnswer = Output.say(PhraseCollection.QUESTION_ANSWERING_START.getRandomElement() + guess.getName()); currentGuess = guess; break; } @@ -233,10 +236,10 @@ private Output doAGuess (){ guessesAvailable = false; gameFinished = true; winner = getContext().ACTIVE_INTERLOCUTOR.getValue().getName(); - roboyAnswer = String.format(PhraseCollection.ROBOY_LOSER_PHRASES.getRandomElement(), winner); + roboyAnswer = Output.say(String.format(PhraseCollection.ROBOY_LOSER_PHRASES.getRandomElement(), winner)).setEmotion(RoboyEmotion.loserEmotions.getRandomElement()); } - return Output.say(roboyAnswer); + return roboyAnswer; } private Output processUserGuessAnswer(String intent){ @@ -244,7 +247,7 @@ private Output processUserGuessAnswer(String intent){ if (intent.equals("yes")){ gameFinished = true; winner = "roboy"; - return Output.say(PhraseCollection.ROBOY_WINNER_PHRASES.getRandomElement()); + return Output.say(PhraseCollection.ROBOY_WINNER_PHRASES.getRandomElement()).setEmotion(RoboyEmotion.winnerEmotions.getRandomElement()); } else { declined.add(Long.valueOf(currentGuess.getIdLong())); return Output.sayNothing(); diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java index 0cdef55c..b6307986 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/WildTalkState.java @@ -55,7 +55,7 @@ public Output act() { @Override public Output react(Interpretation input) { - String sentence = input.getSentence(); + String sentence = input.getSentence().replace(",", "."); JSONObject resp; try { diff --git a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java index a171a3be..d86b8bdb 100644 --- a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java +++ b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java @@ -1,44 +1,74 @@ package roboy.emotions; +import roboy.util.RandomList; + /** * Comprises the emotions Roboy can demonstrate */ public enum RoboyEmotion { - SHY("shy"), - SMILE_BLINK("smileblink"), - LOOK_LEFT("lookleft"), - LOOK_RIGHT("lookright"), - CAT_EYES("catiris"), - KISS("kiss"), - FACEBOOK_EYES("img:facebook"), - INSTAGRAM_EYES("img:instagram"), - LINKED_IN_EYES("img:linkedin"), - NEUTRAL("neutral"), - CRY("cry"), - ANGRY("angry"), - PISSED("pissed"), - ANNOYED("annoyed"), - ROLLING_EYES("rolling"), - HYPNO_EYES("hypno"), - HYPNO_COLOUR_EYES("hypno_color"), - GLASSES("glasses"), - MOUSTACHE("moustache"), - PIRATE("pirate"), - SUNGLASSES("sunglasses"), - SURPRISED("suprised"), - HAPPY("lucky"), - TONGUE("tongue"), - TEETH("teeth"), - HEARTS("hearts"), - HAPPINESS("happiness"), - SADNESS("sadness"), - BEER_THIRSTY("beer"); + SHY("shy", "CAADAgADSwAD5dCAEBGmde8-twTLAg"), + SMILE_BLINK("smileblink", "CAADAgADSgAD5dCAEMQakIa3aHHSAg"), + LOOK_LEFT("lookleft", null), + LOOK_RIGHT("lookright", null), + CAT_EYES("catiris", null), + KISS("kiss", "CAADAgADSAAD5dCAELAByOgU5LIwAg"), + FACEBOOK_EYES("img:facebook", null), + INSTAGRAM_EYES("img:instagram", null), + LINKED_IN_EYES("img:linkedin", null), + NEUTRAL("neutral", "CAADAgADFQAD5dCAEKM0TS8sjXiAAg"), + CRY("cry", "CAADAgADiAAD5dCAEOQeh7anZFNuAg"), + ANGRY("angry", null), + PISSED("pissed", "CAADAgADgQAD5dCAEItX3SnG6CboAg"), + ANNOYED("annoyed", "CAADAgADgQAD5dCAEItX3SnG6CboAg"), + ROLLING_EYES("rolling", null), + HYPNO_EYES("hypno", "CAADAgADcAAD5dCAEMJJxG1uTYH6Ag"), + HYPNO_COLOUR_EYES("hypno_color", "CAADAgADcAAD5dCAEMJJxG1uTYH6Ag"), + GLASSES("glasses", "CAADAgADvQAD5dCAECNJAAFZJ_lnKwI"), + MOUSTACHE("moustache", null), + PIRATE("pirate", "CAADAgADMwAD5dCAEDmHbbo1QxeWAg"), + SUNGLASSES("sunglasses", "CAADAgADLwAD5dCAENTFuFLbW8-XAg"), + SURPRISED("suprised", null), + HAPPY("lucky", null), + TONGUE("tongue", "CAADAgADUQAD5dCAEIT4-Rl1t2BEAg"), + TEETH("teeth", null), + HEARTS("hearts", "CAADAgADSQAD5dCAEN9n0g-x5va8Ag"), + HAPPINESS("happiness", "CAADAgADRgAD5dCAEJV_o50ekE5HAg"), + SADNESS("sadness", "CAADAgADTAAD5dCAENsDuDryjXuhAg"), + BEER_THIRSTY("beer", "CAADAgADKQAD5dCAEFX3hCMAAfM_awI"), + KENNY("kenny", "CAADAgADkAAD5dCAEGMfygavvZSZAg"), + MIB("maninblack", "CAADAgADXQAD5dCAEJY_NKT6hMaOAg"), + MINDBLOWN("mindblown","CAADAgADsgAD5dCAEBmMXCCt4Sh6Ag"), + DANCE("dance", "CAADAgADrgAD5dCAEP7FI8ogeANNAg"), + SUPERMAN("superman","CAADAgADoQAD5dCAEN7_d_TMkG8CAg"); + public String type; + public String telegramID; - RoboyEmotion(String type) { + RoboyEmotion(String type, String telegramID) { this.type = type; + this.telegramID = telegramID; } + public static RandomList winnerEmotions = new RandomList( + DANCE, + SUNGLASSES, + SUPERMAN, + KENNY); + + public static RandomList loserEmotions = new RandomList( + MIB, + SADNESS, + CRY); + + public static RandomList positive = new RandomList( + SMILE_BLINK, + NEUTRAL, + TONGUE, + HAPPINESS, + KISS); + + } + diff --git a/dialog/src/main/java/roboy/io/TelegramOutput.java b/dialog/src/main/java/roboy/io/TelegramOutput.java index 175a319a..6ee92f9e 100644 --- a/dialog/src/main/java/roboy/io/TelegramOutput.java +++ b/dialog/src/main/java/roboy/io/TelegramOutput.java @@ -5,6 +5,8 @@ import roboy.dialog.action.Action; import roboy.dialog.action.EmotionAction; import roboy.dialog.action.SpeechAction; +import roboy.emotions.RoboyEmotion; +import roboy.memory.nodes.Roboy; import roboy.util.TelegramCommunicationHandler; import java.util.List; @@ -45,20 +47,8 @@ public void act(List actions) { String message = ((SpeechAction) a).getText(); communicationHandler.sendMessage(message, this.uuid); }else if (a instanceof EmotionAction) { - String stickerID = null; - switch(((EmotionAction) a).getState()){ - case "beer": stickerID = "CAADAgADKQAD5dCAEFX3hCMAAfM_awI"; break; - case "sadness": stickerID = "CAADAgADiAAD5dCAEOQeh7anZFNuAg"; break; - case "happiness": stickerID = "CAADAgADUQAD5dCAEIT4-Rl1t2BEAg"; break; - case "shy": stickerID = "CAADAgADSwAD5dCAEBGmde8-twTLAg"; break; - case "smileblink": stickerID = "CAADAgADSgAD5dCAEMQakIa3aHHSAg"; break; - case "kiss": stickerID = "CAADAgADOQAD5dCAEOtbfZz0NKh2Ag"; break; - case "lookleft": //same as lookright - case "lookright": stickerID = "CAADAgADFQAD5dCAEKM0TS8sjXiAAg"; break; - //TODO: other RoboyEmotions - default: break; - } - if(stickerID != null) communicationHandler.sendSticker(this.uuid, stickerID); + String stickerID = RoboyEmotion.valueOf(((EmotionAction) a).getName()).telegramID; + if (stickerID != null) communicationHandler.sendSticker(this.uuid, stickerID); } diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java index 142c179a..4e8ca5b8 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/EmotionAnalyzer.java @@ -75,7 +75,7 @@ public Interpretation analyze(Interpretation interpretation) try{ mean = vec.getWordVectorsMean(labels); }catch(Exception e){ - interpretation.setEmotion(RoboyEmotion.NEUTRAL); + //interpretation.setEmotion(RoboyEmotion.NEUTRAL); return interpretation; } if(!mean.isVector()){ @@ -131,9 +131,9 @@ else if(happySimilarity >= threshold){ interpretation.setEmotion(RoboyEmotion.SHY); } } - else{ - interpretation.setEmotion(RoboyEmotion.NEUTRAL); - } +// else{ +// interpretation.setEmotion(RoboyEmotion.NEUTRAL); +// } return interpretation; diff --git a/dialog/src/main/java/roboy/util/Lists.java b/dialog/src/main/java/roboy/util/Lists.java index d6c5d2b7..d4019b50 100755 --- a/dialog/src/main/java/roboy/util/Lists.java +++ b/dialog/src/main/java/roboy/util/Lists.java @@ -14,4 +14,5 @@ public static List stringList(String... strings){ result.addAll(Arrays.asList(strings)); return result; } + } diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 5bbe9bda..9c3496f2 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -6842,3 +6842,79 @@ {"features":" {score:0.08450248734030909} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} {"features":" {score:0.48692732175259695} ","formula":"resource:Ukrainian_Soviet_Socialist_Republic","lexeme":"ukrainian soviet socialist republic","type":"NamedEntity"} {"features":" {score:0.026219150202174017} ","formula":"!property:case","lexeme":"case","type":"ObjProp"} +{"features":" {score:0.039105719999382775} ","formula":"(rdf:type dbpedia:Airport)","lexeme":"airport","type":"ClassNoun"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"(rdf:type dbpedia:University)","lexeme":"university","type":"ClassNoun"} +{"features":" {score:0.13518829246017713} ","formula":"(rdf:type dbpedia:City)","lexeme":"city","type":"ClassNoun"} +{"features":" {score:0.13518829246017713} ","formula":"!dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.6244656133828996} ","formula":"resource:Munich","lexeme":"munich","type":"NamedEntity"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.02476466395722725} ","formula":"!dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.007118905612640406} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.5156482342007435} ","formula":"resource:Ludwig_Maximilian_University_of_Munich","lexeme":"ludwig maximilian university of munich","type":"NamedEntity"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"!dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.3574573272887659} ","formula":"resource:1972_Summer_Olympics","lexeme":"1972 summer olympics","type":"NamedEntity"} +{"features":" {score:0.0048526863084922016} ","formula":"!dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.13518829246017713} ","formula":"dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.006745657462310337} ","formula":"dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.5069005576208179} ","formula":"resource:Munich_Agreement","lexeme":"munich agreement","type":"NamedEntity"} +{"features":" {score:0.02476466395722725} ","formula":"(rdf:type dbpedia:Municipality)","lexeme":"municipality","type":"ClassNoun"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.5222235130111524} ","formula":"resource:FC_Bayern_Munich","lexeme":"fc bayern munich","type":"NamedEntity"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.039105719999382775} ","formula":"(rdf:type dbpedia:Airport)","lexeme":"airport","type":"ClassNoun"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"(rdf:type dbpedia:University)","lexeme":"university","type":"ClassNoun"} +{"features":" {score:0.13518829246017713} ","formula":"(rdf:type dbpedia:City)","lexeme":"city","type":"ClassNoun"} +{"features":" {score:0.13518829246017713} ","formula":"!dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.6244656133828996} ","formula":"resource:Munich","lexeme":"munich","type":"NamedEntity"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.02476466395722725} ","formula":"!dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.007118905612640406} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.5156482342007435} ","formula":"resource:Ludwig_Maximilian_University_of_Munich","lexeme":"ludwig maximilian university of munich","type":"NamedEntity"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"!dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.3574573272887659} ","formula":"resource:1972_Summer_Olympics","lexeme":"1972 summer olympics","type":"NamedEntity"} +{"features":" {score:0.0048526863084922016} ","formula":"!dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.13518829246017713} ","formula":"dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.006745657462310337} ","formula":"dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.5069005576208179} ","formula":"resource:Munich_Agreement","lexeme":"munich agreement","type":"NamedEntity"} +{"features":" {score:0.02476466395722725} ","formula":"(rdf:type dbpedia:Municipality)","lexeme":"municipality","type":"ClassNoun"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.5222235130111524} ","formula":"resource:FC_Bayern_Munich","lexeme":"fc bayern munich","type":"NamedEntity"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"DataProp"} From ecb459f54958ae0515782162359721f0f748024d Mon Sep 17 00:00:00 2001 From: missxa Date: Mon, 10 Sep 2018 01:12:58 +0200 Subject: [PATCH 128/147] game offer bugfix --- .../roboy/dialog/states/devoStates/QuestionRoboyQAState.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index cf530bc7..017585e3 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -89,6 +89,7 @@ public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { @Override public Output act() { if (questionsAnswered == MAX_NUM_OF_QUESTIONS/2) { + questionsAnswered++; return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); } return Output.sayNothing(); From 3908be34ed98dc2c69a5953d7dac12d9ebffc22c Mon Sep 17 00:00:00 2001 From: missxa Date: Mon, 10 Sep 2018 01:22:32 +0200 Subject: [PATCH 129/147] :fire: --- .../roboy/dialog/states/devoStates/QuestionRoboyQAState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 017585e3..3c4df0d9 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -89,7 +89,6 @@ public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { @Override public Output act() { if (questionsAnswered == MAX_NUM_OF_QUESTIONS/2) { - questionsAnswered++; return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); } return Output.sayNothing(); @@ -103,6 +102,7 @@ public Output react(Interpretation input) { private Output reactToQuestion(Interpretation input) { if (questionsAnswered == MAX_NUM_OF_QUESTIONS/2) { + questionsAnswered++; if (getInference().inferSentiment(input) == Linguistics.UtteranceSentiment.POSITIVE) { userWantsGame = true; questionsAnswered++; From a46f5200f765826f86692bad86a160eb96b31e0f Mon Sep 17 00:00:00 2001 From: missxa Date: Mon, 10 Sep 2018 14:42:21 +0200 Subject: [PATCH 130/147] not constantly offering a game anymore --- .../roboy/dialog/states/devoStates/QuestionRoboyQAState.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 3c4df0d9..3268fc84 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -109,12 +109,13 @@ private Output reactToQuestion(Interpretation input) { return Output.sayNothing().setSegue(new Segue(Segue.SegueType.PICKUP,0.5)).setEmotion(RoboyEmotion.HAPPY); } else { - questionsAnswered++; +// questionsAnswered++; return Output.sayNothing().setEmotion(RoboyEmotion.SADNESS); } } askingSpecifyingQuestion = false; + userWantsGame = false; questionsAnswered++; String answer = inferApiAnswer(input); @@ -157,7 +158,7 @@ public State getNextState() { } private Output useMemoryOrFallback(Interpretation input) { - questionsAnswered++; +// questionsAnswered++; try { if ( input.getPas() != null || input.getTriples() != null) { Output memoryAnswer = answerFromMemory(input); From 51d3efb04343597eb4a4e316df3ddf1224c17da9 Mon Sep 17 00:00:00 2001 From: Mireu Date: Mon, 10 Sep 2018 16:18:28 +0200 Subject: [PATCH 131/147] Fixed wrong formatting --- docs/developer_manual/4_Resources.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/developer_manual/4_Resources.rst b/docs/developer_manual/4_Resources.rst index 27565200..3279ff19 100644 --- a/docs/developer_manual/4_Resources.rst +++ b/docs/developer_manual/4_Resources.rst @@ -54,13 +54,13 @@ JSON Resources } } -- telegram tokens - contain tokens for registered telegram bots to allow the Dialog System to connect to the telegram API:: +- telegram tokens - contain tokens for registered telegram bots to allow the Dialog System to connect to the telegram API - .. code:: json - { - "TOKEN":"AAAAAAAAA:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "BOT_USERNAME":"Botname" - } +.. code:: json + { + "TOKEN":"AAAAAAAAA:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "BOT_USERNAME":"Botname" + } CSV Resources ============= From 2675c68c6d0b9e512b24af55e6911e1b282dc7d4 Mon Sep 17 00:00:00 2001 From: Mireu Date: Mon, 10 Sep 2018 16:26:06 +0200 Subject: [PATCH 132/147] Fixed faulty fix --- docs/developer_manual/4_Resources.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/developer_manual/4_Resources.rst b/docs/developer_manual/4_Resources.rst index 3279ff19..c3228e27 100644 --- a/docs/developer_manual/4_Resources.rst +++ b/docs/developer_manual/4_Resources.rst @@ -57,10 +57,13 @@ JSON Resources - telegram tokens - contain tokens for registered telegram bots to allow the Dialog System to connect to the telegram API .. code:: json + { "TOKEN":"AAAAAAAAA:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "BOT_USERNAME":"Botname" } + + CSV Resources ============= From 792b60c2d79846f4a706973181f1fdabfa16b6a2 Mon Sep 17 00:00:00 2001 From: mireu Date: Sat, 15 Sep 2018 01:45:09 +0200 Subject: [PATCH 133/147] * Added conversation timeout * Enabled ContextTest * Added ConversationManagementTest * Enabled VerbalizerTest * Improved documentation * Fixed minor mistake in config.properties logging section --- config.properties | 12 +- dialog/pom.xml | 1 + .../main/java/roboy/dialog/Conversation.java | 25 ++-- .../roboy/dialog/ConversationManager.java | 11 +- .../src/main/java/roboy/io/InputDevice.java | 24 ++-- .../main/java/roboy/io/MultiInputDevice.java | 13 +- .../src/main/java/roboy/io/TelegramInput.java | 18 ++- .../main/java/roboy/util/ConfigManager.java | 11 ++ .../test/java/roboy/context/ContextTest.java | 3 +- .../dialog/ConversationManagementTest.java | 127 ++++++++++++++++++ .../test/java/roboy/talk/VerbalizerTest.java | 55 ++++---- docs/developer_manual/1_Tutorials.rst | 44 +++++- docs/developer_manual/4_Resources.rst | 13 +- docs/user_manual/2_configuration.rst | 3 + 14 files changed, 288 insertions(+), 72 deletions(-) create mode 100644 dialog/src/test/java/roboy/dialog/ConversationManagementTest.java diff --git a/config.properties b/config.properties index d1559aa8..de2c80fe 100755 --- a/config.properties +++ b/config.properties @@ -37,12 +37,12 @@ INPUT: cmdline # multiple outputs are allowed, defaults to cmdline OUTPUTS: - cmdline -# - cerevoice -# - freetts -# - ibm -# - emotions -# - udp -# - telegram +#- cerevoice +#- freetts +#- ibm +#- emotions +#- udp +#- telegram UDP_IN_SOCKET: 55555 UDP_OUT_SOCKET: 55556 diff --git a/dialog/pom.xml b/dialog/pom.xml index 954f5351..69cfb3c6 100755 --- a/dialog/pom.xml +++ b/dialog/pom.xml @@ -27,6 +27,7 @@ maven-surefire-plugin 2.22.0 + ${project.parent.basedir} roboy.memory.MemoryIntegrationTest diff --git a/dialog/src/main/java/roboy/dialog/Conversation.java b/dialog/src/main/java/roboy/dialog/Conversation.java index 7fca43da..5f0b7a98 100644 --- a/dialog/src/main/java/roboy/dialog/Conversation.java +++ b/dialog/src/main/java/roboy/dialog/Conversation.java @@ -11,11 +11,13 @@ import roboy.io.MultiOutputDevice; import roboy.linguistics.sentenceanalysis.Analyzer; import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.util.ConfigManager; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; /** @@ -67,17 +69,20 @@ public Conversation( StateBasedPersonality personality, File personalityFile, Mu /** * Ends conversation and resets state to initial. Does not reset gathered information. */ - synchronized void endConversation(){//Ends conversation including + synchronized void endConversation(boolean hardStop){//Ends conversation including isRunning = false; personality.reset(); this.interrupt();//to wake conversations that wait for input - //Say bye - List l = new ArrayList<>(); - l.add(new SpeechAction("Sorry. It seems I have to stop playing now. See you soon. Bye!")); - multiOut.act(l); + if(!hardStop) { + //Say bye + List l = new ArrayList<>(); + l.add(new SpeechAction("Sorry. It seems I have to stop playing now. See you soon. Bye!")); + multiOut.act(l); + } logger.info("############# Conversation forcibly ended ############"); + } @@ -112,10 +117,14 @@ public void run(){ // listen to interlocutor if conversation didn't end Input raw; try { - raw = multiIn.listen(); + raw = multiIn.listen(TimeUnit.SECONDS.toMillis(ConfigManager.CONVERSATION_TIMEOUT)); } catch (Exception e) { - logger.error("Exception in input: " + e.getMessage()); - return; + if(isRunning) { + logger.error("Exception in input: " + e.getMessage()); + return; + } else { + break; + } } // analyze diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index eac19dcd..b432f273 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -163,14 +163,19 @@ protected static void deregisterConversation(Conversation conversation){ conversations.values().remove(conversation); } + public static void stopConversation(String uuid){ + stopConversation(uuid, false); + } + /** * Stops conversation thread for uuid. * @param uuid should consist of "[world-interface-name]-[uuid]", if input allows only a single user, set to "local" + * @param hardStop Roboy doesn't say bye on hardstop. Default = false */ - public static void stopConversation(String uuid){ + public static void stopConversation(String uuid, boolean hardStop){ Conversation c = conversations.get(uuid); if (c != null) { - c.endConversation(); + c.endConversation(hardStop); } else { logger.error("Conversation to be stopped does not exist..."); } @@ -293,7 +298,7 @@ private static void commandMode(){ //process command switch (command) { case "shutdown"://gracefully say bye - for (Conversation c : conversations.values()) c.endConversation(); + for (Conversation c : conversations.values()) c.endConversation(true); System.exit(0); default: System.out.println("Command not found. Currently supported commands: shutdown"); diff --git a/dialog/src/main/java/roboy/io/InputDevice.java b/dialog/src/main/java/roboy/io/InputDevice.java index 3033739d..0da694a8 100755 --- a/dialog/src/main/java/roboy/io/InputDevice.java +++ b/dialog/src/main/java/roboy/io/InputDevice.java @@ -1,10 +1,14 @@ -package roboy.io; - -import java.io.IOException; - -/** - * An input device must listen and return an Input object. - */ -public interface InputDevice { - public Input listen() throws InterruptedException, IOException; -} +package roboy.io; + +import java.io.IOException; + +/** + * An input device must listen and return an Input object. + */ +public interface InputDevice { + public Input listen() throws InterruptedException, IOException; + + default public Input listen(long timeout) throws InterruptedException, IOException { + return this.listen(); + } +} diff --git a/dialog/src/main/java/roboy/io/MultiInputDevice.java b/dialog/src/main/java/roboy/io/MultiInputDevice.java index 2f1f8d44..934acf29 100755 --- a/dialog/src/main/java/roboy/io/MultiInputDevice.java +++ b/dialog/src/main/java/roboy/io/MultiInputDevice.java @@ -10,7 +10,7 @@ public class MultiInputDevice implements InputDevice, CleanUp{ private InputDevice mainInput; private ArrayList additionalInputs; - + public MultiInputDevice(InputDevice mainInput) { this.mainInput = mainInput; additionalInputs = new ArrayList<>(); @@ -19,12 +19,17 @@ public MultiInputDevice(InputDevice mainInput) { public void addInputDevice(InputDevice additionalInput) { additionalInputs.add(additionalInput); } - + @Override public Input listen() throws InterruptedException, IOException { - Input result = mainInput.listen(); + return this.listen(0); + } + + @Override + public Input listen(long timeout) throws InterruptedException, IOException { + Input result = mainInput.listen(timeout); for(InputDevice device : additionalInputs){ - Input i = device.listen(); + Input i = device.listen(timeout); result.setAttributes(i.getAttributes()); } return result; diff --git a/dialog/src/main/java/roboy/io/TelegramInput.java b/dialog/src/main/java/roboy/io/TelegramInput.java index 9cd39b61..18132579 100644 --- a/dialog/src/main/java/roboy/io/TelegramInput.java +++ b/dialog/src/main/java/roboy/io/TelegramInput.java @@ -65,23 +65,37 @@ public static void onUpdate(Pair update, String name) { } } + @Override + public Input listen() throws InterruptedException { + return this.listen(0); + } + /** * Thread waits in listen() until a new input is provided and the thread is interrupted, then returns with said input. * If the thread is interrupted without Input waiting to be consumed, listen() throws an IOException + * @param timeout timeout in ms, no timeout if timeout = 0 * @throws InterruptedException: InterruptedException thrown by the thread when interrupted while wait()ing + * @throws IllegalArgumentException if timeout is negative (should be prevented via ConfigManager) */ @Override - public Input listen() throws InterruptedException { + public Input listen(long timeout) throws InterruptedException { Input newInput; synchronized (this) { while(message.equals("")){//while no new messages for this thread exist: wait try { - this.wait(); + this.wait(timeout); }catch (InterruptedException e) {//Thread woke up! Process new information! if(message == null || message.equals("")){//if this interrupt was not triggered because new messages arrived, throw exception to be handled throw e; } } + if(message == null || message.equals("")){//timeout triggered + String uuid = ""; + for(String id : inputDevices.keySet()) if(inputDevices.get(id) == this) uuid = id; + + logger.info("Conversation for " + uuid + "timed out!"); + ConversationManager.stopConversation(uuid, true); + } } newInput = new Input(message); message = ""; //consume message diff --git a/dialog/src/main/java/roboy/util/ConfigManager.java b/dialog/src/main/java/roboy/util/ConfigManager.java index 1deaa22d..ee453a66 100644 --- a/dialog/src/main/java/roboy/util/ConfigManager.java +++ b/dialog/src/main/java/roboy/util/ConfigManager.java @@ -43,6 +43,8 @@ public class ConfigManager { public static boolean CONTEXT_GUI_ENABLED = false; + public static long CONVERSATION_TIMEOUT = 0; + public static String TELEGRAM_API_TOKENS_FILE = ""; public static String MEMORY_LOG_MODE = "INFO"; @@ -69,7 +71,9 @@ private static void initializeConfig() { YAMLConfiguration yamlConfig = new YAMLConfiguration(); try { + System.out.println(System.getProperty("user.dir")); File propertiesFile = new File(yamlConfigFile); + System.out.println(propertiesFile.getAbsolutePath()); if (!propertiesFile.exists()) { // propertiesFile == null doesn't work! LOGGER.error("Could not find "+yamlConfigFile+" file in project path! YAML configurations will be unavailable."); @@ -124,6 +128,13 @@ private static void initializeConfig() { ACTION_CLIENT_SCRIPT = yamlConfig.getString("ACTION_CLIENT_SCRIPT"); + long timeout = yamlConfig.getLong("CONVERSATION_TIMEOUT"); + if (timeout < 0){ + LOGGER.error("Invalid timeout setting: " + timeout + "disabling timeout..."); + } else { + CONVERSATION_TIMEOUT = timeout; + } + TELEGRAM_API_TOKENS_FILE = yamlConfig.getString("TELEGRAM_API_TOKENS_FILE"); PARLAI_HOST = yamlConfig.getString("PARLAI_HOST"); diff --git a/dialog/src/test/java/roboy/context/ContextTest.java b/dialog/src/test/java/roboy/context/ContextTest.java index 18510dbf..245650d1 100644 --- a/dialog/src/test/java/roboy/context/ContextTest.java +++ b/dialog/src/test/java/roboy/context/ContextTest.java @@ -1,6 +1,7 @@ package roboy.context; import com.google.gson.Gson; +import junit.framework.TestCase; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -21,7 +22,7 @@ import static org.junit.Assert.*; import static org.mockito.Matchers.any; -public class ContextTest { +public class ContextTest extends TestCase { Context context = new Context(); @Test diff --git a/dialog/src/test/java/roboy/dialog/ConversationManagementTest.java b/dialog/src/test/java/roboy/dialog/ConversationManagementTest.java new file mode 100644 index 00000000..1e938d98 --- /dev/null +++ b/dialog/src/test/java/roboy/dialog/ConversationManagementTest.java @@ -0,0 +1,127 @@ +package roboy.dialog; + + +import junit.framework.TestCase; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.config.Configurator; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; +import roboy.memory.nodes.Interlocutor; +import roboy.util.ConfigManager; +import roboy.util.Uuid; +import roboy.util.UuidType; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import static org.powermock.api.mockito.PowerMockito.*; + + + +/** + * Tests related to the management of the conversation threads + */ +@PowerMockIgnore( {"javax.management.*"}) +@RunWith(PowerMockRunner.class) +@PrepareForTest(ConversationManager.class) + +public class ConversationManagementTest extends TestCase { + + List out = ConfigManager.OUTPUTS; + String in = ConfigManager.INPUT; + + @Mock + private Conversation mockConversation; + private Interlocutor mockInterlocutor;//important so we do not change memory + + + + @Before + public void prepareConversationManager() throws Exception { + ConversationManager cm = new ConversationManager(); + ConfigManager.INPUT="cmdline"; + ConfigManager.OUTPUTS = new ArrayList<>(); + ConfigManager.OUTPUTS.add("cmdline"); + Configurator.setAllLevels(LogManager.getRootLogger().getName(), Level.INFO); + mockConversation = mock(Conversation.class); + mockInterlocutor = mock(Interlocutor.class); + whenNew(Interlocutor.class).withAnyArguments().thenReturn(mockInterlocutor); + whenNew(Conversation.class).withAnyArguments().thenReturn(mockConversation); + } + + @Test + public void testLocalSpawning() throws Exception { + + ConversationManager.spawnConversation("local", "veryLocal"); + verifyNew(Conversation.class).withArguments(Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject()); + HashMap registeredConversations = Whitebox.getInternalState(ConversationManager.class, "conversations"); + assertTrue(registeredConversations.size() == 1); + assertTrue(registeredConversations.containsKey("local")); + Mockito.verify(mockInterlocutor, Mockito.times(1)).addName("veryLocal"); + Mockito.verify(mockConversation, Mockito.times(1)).start(); + + ConversationManager.spawnConversation("uuidShouldNotBeCheckedAsLongAsNameIsNotUsed");//do not do this in the actual code. Always use local. This is only for testing purposes as long as the name field does not work in testing + assertTrue(registeredConversations.size() == 2); + assertTrue(registeredConversations.containsKey("uuidShouldNotBeCheckedAsLongAsNameIsNotUsed")); + Mockito.verify(mockConversation, Mockito.times(2)).start(); + + registeredConversations.clear(); + Mockito.reset(mockInterlocutor); + Mockito.reset(mockConversation); + + } + + @Test + public void testSocialMediaSpawning() throws Exception { + HashMap registeredConversations = Whitebox.getInternalState(ConversationManager.class, "conversations"); + + //Telegram + ConversationManager.spawnConversation("telegram-IamATestFragment","IamATestFragment"); + verifyNew(Conversation.class).withArguments(Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject()); + assertTrue(registeredConversations.size() == 1); + assertTrue(registeredConversations.containsKey("telegram-IamATestFragment")); + Mockito.verify(mockConversation, Mockito.times(1)).start(); + Mockito.verify(mockInterlocutor, Mockito.times(1)).addUuid(Matchers.anyObject(), Matchers.matches("IamATestFragment")); + + //Facebook + ConversationManager.spawnConversation("facebook-IamATestFragment","IamATestFragment"); + verifyNew(Conversation.class, Mockito.times(2)).withArguments(Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject()); + assertTrue(registeredConversations.size() == 2); + assertTrue(registeredConversations.containsKey("facebook-IamATestFragment")); + Mockito.verify(mockConversation, Mockito.times(2)).start(); + Mockito.verify(mockInterlocutor, Mockito.times(2)).addUuid(Matchers.anyObject(), Matchers.matches("IamATestFragment")); + + //Slack + ConversationManager.spawnConversation("slack-IamATestFragment","IamATestFragment"); + verifyNew(Conversation.class, Mockito.times(3)).withArguments(Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject(), Matchers.anyObject()); + assertTrue(registeredConversations.size() == 3); + assertTrue(registeredConversations.containsKey("slack-IamATestFragment")); + Mockito.verify(mockConversation, Mockito.times(3)).start(); + Mockito.verify(mockInterlocutor, Mockito.times(3)).addUuid(Matchers.anyObject(), Matchers.matches("IamATestFragment")); + + registeredConversations.clear(); + Mockito.reset(mockInterlocutor, mockConversation); + } + + @After + public void clean(){ + Configurator.setAllLevels(LogManager.getRootLogger().getName(), Level.toLevel(ConfigManager.DIALOG_LOG_MODE, Level.INFO)); + ConfigManager.OUTPUTS = out; + ConfigManager.INPUT = in; + } + + +} diff --git a/dialog/src/test/java/roboy/talk/VerbalizerTest.java b/dialog/src/test/java/roboy/talk/VerbalizerTest.java index 3feed9fd..ae291b62 100755 --- a/dialog/src/test/java/roboy/talk/VerbalizerTest.java +++ b/dialog/src/test/java/roboy/talk/VerbalizerTest.java @@ -1,27 +1,28 @@ -package roboy.talk; - -import static org.junit.Assert.*; - -import org.junit.Test; - -import roboy.dialog.action.SpeechAction; -import roboy.linguistics.sentenceanalysis.Interpretation; - -public class VerbalizerTest { - - @Test - public void testDates() { - Verbalizer verbalizer = new Verbalizer(); - SpeechAction action = (SpeechAction) verbalizer.verbalize(new Interpretation("0666-01-01")); - assertEquals("January first six hundred sixty six",action.getText()); - action = (SpeechAction) verbalizer.verbalize(new Interpretation("2010-12-31")); - assertEquals("December thirty first two thousand ten",action.getText()); - action = (SpeechAction) verbalizer.verbalize(new Interpretation("1040-09-13")); - assertEquals("September thirteenth one thousand forty",action.getText()); - action = (SpeechAction) verbalizer.verbalize(new Interpretation("2300-07-28")); - assertEquals("July twenty eighth two thousand three hundred",action.getText()); - action = (SpeechAction) verbalizer.verbalize(new Interpretation("1604-04-04")); - assertEquals("April fourth sixteen hundred four",action.getText()); - } - -} +package roboy.talk; + +import static org.junit.Assert.*; + +import junit.framework.TestCase; +import org.junit.Test; + +import roboy.dialog.action.SpeechAction; +import roboy.linguistics.sentenceanalysis.Interpretation; + +public class VerbalizerTest extends TestCase { + + @Test + public void testDates() { + Verbalizer verbalizer = new Verbalizer(); + SpeechAction action = (SpeechAction) verbalizer.verbalize(new Interpretation("0666-01-01")); + assertEquals("January first six hundred sixty six",action.getText()); + action = (SpeechAction) verbalizer.verbalize(new Interpretation("2010-12-31")); + assertEquals("December thirty first two thousand ten",action.getText()); + action = (SpeechAction) verbalizer.verbalize(new Interpretation("1040-09-13")); + assertEquals("September thirteenth one thousand forty",action.getText()); + action = (SpeechAction) verbalizer.verbalize(new Interpretation("2300-07-28")); + assertEquals("July twenty eighth two thousand three hundred",action.getText()); + action = (SpeechAction) verbalizer.verbalize(new Interpretation("1604-04-04")); + assertEquals("April fourth sixteen hundred four",action.getText()); + } + +} diff --git a/docs/developer_manual/1_Tutorials.rst b/docs/developer_manual/1_Tutorials.rst index 98ba01af..c7d6ea6a 100644 --- a/docs/developer_manual/1_Tutorials.rst +++ b/docs/developer_manual/1_Tutorials.rst @@ -654,10 +654,16 @@ First create a new class in roboy.io folder, namely ``MySocialMediaInput`` that } -One function namely “listen()” has to be implemented. This function is called by a thread and should return a new ``Input`` or keep the thread waiting if there isn't any new ``Input`` available. +One function namely “listen()” must be implemented. This function is called by a thread and should return a new ``Input`` or keep the thread waiting if there isn't any new ``Input`` available. +Since we want our social media input to support timeout because people often just do not answer on social media, we will implement ``listen(long timeout)`` and the call this one in ``listen()``. :: @Override public Input listen() throws InterruptedException, IOException { + return listen(0); + } + + @Override + public Input listen(long timeout) throws InterruptedException, IOException { return null; } @@ -683,7 +689,7 @@ Add a constructor that receives the uuid as parameter } At this point, we received the uuid and have a hashmap of each ``MySocialMediaInput``. What else we need to implement?: -- Return messages as ``roboy.io.Input`` in the ``listen()`` method +- Return messages as ``roboy.io.Input`` in the ``listen(long timeout)`` method - Receive the messages .. Note:: @@ -699,16 +705,16 @@ We need to initialize it in constructor. Add the following into the beginning of this.message = ""; -Finally finish the listen method +Now, we'll write the message processing logic. :: // inside MySocialMediaInput.java - public Input listen() throws InterruptedException, IOException { + public Input listen(long timeout) throws InterruptedException, IOException { Input newInput; syncronized(this){ while(message.equals("")){ try{ - this.wait(); + this.wait(timeout); } catch(InterruptedException e){ if(message == null||message.equals("")){ @@ -722,6 +728,34 @@ Finally finish the listen method return newInput; } +To finish the listen method we also need to properly handle what happens if we did not recieve a new message before the timeout. In that case we need to find the uuid associated with this input and then stop the Conversation for it. +The complete ``listen(long timeout)`` now looks like this: +:: + public Input listen(long timeout) throws InterruptedException, IOException { + Input newInput; + synchronized (this) { + while(message.equals("")){ + try { + this.wait(timeout); + }catch (InterruptedException e) { + if(message == null || message.equals("")){ + throw e; + } + } + if(message == null || message.equals("")){//timeout triggered + String uuid = ""; + for(String id : inputDevices.keySet()) if(inputDevices.get(id) == this) uuid = id; + + logger.info("Conversation for " + uuid + "timed out!"); + ConversationManager.stopConversation(uuid, true); + } + } + newInput = new Input(message); + message = ""; //consume message + } + return newInput; + } + Nice, now only thing to worry about is how to receive the message. .. Note:: diff --git a/docs/developer_manual/4_Resources.rst b/docs/developer_manual/4_Resources.rst index 27565200..14d76cf3 100644 --- a/docs/developer_manual/4_Resources.rst +++ b/docs/developer_manual/4_Resources.rst @@ -54,13 +54,14 @@ JSON Resources } } -- telegram tokens - contain tokens for registered telegram bots to allow the Dialog System to connect to the telegram API:: +- telegram tokens - contain tokens for registered telegram bots to allow the Dialog System to connect to the telegram API - .. code:: json - { - "TOKEN":"AAAAAAAAA:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "BOT_USERNAME":"Botname" - } +.. code:: json + + { + "TOKEN":"AAAAAAAAA:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "BOT_USERNAME":"Botname" + } CSV Resources ============= diff --git a/docs/user_manual/2_configuration.rst b/docs/user_manual/2_configuration.rst index adf0f53c..a5c3e14c 100644 --- a/docs/user_manual/2_configuration.rst +++ b/docs/user_manual/2_configuration.rst @@ -78,6 +78,9 @@ Infinite repitition flag: For input that require a single instance of the dialog INFINITE_REPETITION: true +Conversation timeout: The duration waited since the last action until a conversation is discarded in seconds :: + + CONVERSATION_TIMEOUT: 10800 Personality ^^^^^^^^^^^ From c55313fbbc4b70c12e6408452820ce58b98ca367 Mon Sep 17 00:00:00 2001 From: mireu Date: Sat, 15 Sep 2018 02:23:16 +0200 Subject: [PATCH 134/147] Fixed config.properties missmerge --- config.properties | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/config.properties b/config.properties index 589d6e81..511e0e40 100755 --- a/config.properties +++ b/config.properties @@ -26,6 +26,8 @@ ROS_ACTIVE_PKGS: DEBUG: true DEMO_MODE: false INFINITE_REPETITION: true +#timeout for threads in seconds +CONVERSATION_TIMEOUT: 10800 # only single input is allowed, defaults to cmdline #INPUT: cmdline @@ -66,7 +68,7 @@ IBM_TTS_PASS: "" CONTEXT_GUI_ENABLED: false ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/scripts/action_client.py" -TELEGRAM_API_TOKENS_FILE: "" +TELEGRAM_API_TOKENS_FILE: "/home/mireu/Documents/Uni/Masterpraktikum-Roboy_Student_Team/telegramtokens.json" PARLAI_PORT: 8877 PARLAI_HOST: "127.0.0.1" From fd05cb4adc822e76df5355bb13c946fe088242f9 Mon Sep 17 00:00:00 2001 From: missxa Date: Sun, 16 Sep 2018 05:16:04 +0200 Subject: [PATCH 135/147] jokes, media, created by, new roboy node --- .../devoStates/QuestionRoboyQAState.java | 61 ++++++++++--- .../sentenceanalysis/Interpretation.java | 1 + .../sentenceanalysis/OpenNLPParser.java | 33 ++++--- .../main/java/roboy/memory/Neo4jLabel.java | 1 + .../main/java/roboy/memory/Neo4jProperty.java | 5 +- .../java/roboy/memory/Neo4jRelationship.java | 4 +- .../main/java/roboy/memory/nodes/Roboy.java | 2 +- .../src/main/java/roboy/talk/Verbalizer.java | 3 +- .../main/java/roboy/util/QAJsonParser.java | 4 + .../nlp/sempre/corenlp/SimpleOpenIEDemo.java | 4 + resources/sentences/RoboyInfoList.json | 85 ++++++++++++++++--- 11 files changed, 162 insertions(+), 41 deletions(-) create mode 100644 nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/SimpleOpenIEDemo.java diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 3268fc84..fbdd1b87 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -123,6 +123,11 @@ private Output reactToQuestion(Interpretation input) { return Output.say(answer); } + // catch jokes + if (input.getTokens().contains("joke") || input.getTokens().contains("funny")) { + return Output.say(PhraseCollection.JOKES.getRandomElement()).setEmotion(RoboyEmotion.positive.getRandomElement()); + } + if (input.getTokens() != null && !(input.getTokens().contains("you") || input.getTokens().contains("your"))) { Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); @@ -225,7 +230,10 @@ private String inferMemoryAnswer(Interpretation input, Roboy roboy) { List triples = input.getTriples(); if (pas != null) { - return inferPasAnswer(pas, roboy); + answer = inferPasAnswer(pas, roboy); + if (!answer.isEmpty()) { + return answer; + } } if (triples != null) { @@ -254,29 +262,41 @@ private String inferPasAnswer(Map pas, Roboy roboy) { answer = extractAge(roboy); } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy); - } else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { - answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); } + // LOCATION picks up random questions not related to LIVE_IN +// else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { +// answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); +// } // else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { // answer = "Yo moma says I am a good boy!"; // } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "who"))) { - if (matchPas(pas, new Pair(SemanticRole.PATIENT, "you"))) { - answer = extractNodeNameForPredicate(Neo4jProperty.full_name, roboy); + if (matchPas(pas, new Pair(SemanticRole.PATIENT, "you"), new Pair(SemanticRole.PREDICATE, "are"))) { + answer = extractNodeNameForPredicate(Neo4jProperty.name, roboy) + " " + + extractNodeNameForPredicate(Neo4jProperty.identitiy, roboy); } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\b(father|dad)\\b.*"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.CHILD_OF, roboy); } else if (matchPas(pas, new Pair(SemanticRole.PATIENT, ".*\\b(sibling|brother)\\b.*"))){ answer = extractNodeNameForPredicate(Neo4jRelationship.SIBLING_OF, roboy); + } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "created|made|built"), new Pair(SemanticRole.PATIENT, "you"))) { + answer = extractNodeNameForPredicate(Neo4jRelationship.CREATED_BY, roboy); } } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "do|like"), new Pair(SemanticRole.AGENT, "you"))){ - double prob = Math.random(); - if (prob < .3) { - answer = extractNodeNameForPredicate(Neo4jProperty.abilities, roboy); - } else if(prob < .7) { - answer = extractNodeNameForPredicate(Neo4jRelationship.HAS_HOBBY, roboy); - } else { +// double prob = Math.random(); +// if (prob < .3) { +// answer = extractNodeNameForPredicate(Neo4jProperty.abilities, roboy); +// } else if(prob < .7) { +// answer = extractNodeNameForPredicate(Neo4jRelationship.HAS_HOBBY, roboy); +// } else { answer = extractNodeNameForPredicate(Neo4jProperty.skills, roboy); - } +// } + } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "dream|wish"), new Pair(SemanticRole.AGENT, "you"))) { + answer = extractNodeNameForPredicate(Neo4jProperty.dreams, roboy); + } + else if (matchPas(pas, new Pair(SemanticRole.PATIENT, "you"), new Pair(SemanticRole.PREDICATE, "are"), + new Pair(SemanticRole.AGENT, "what"))) { + answer = extractNodeNameForPredicate(Neo4jProperty.name, roboy) + " " + + extractNodeNameForPredicate(Neo4jProperty.identitiy, roboy); } return answer; @@ -284,6 +304,11 @@ else if (matchPas(pas, new Pair(SemanticRole.AGENT, "who"))) { private String inferTripleAnswer(List triples, Roboy roboy) { String answer = ""; + for (Triple t: triples) { + if (t.subject.matches(".*\\b(meet|see|know)\\b.*")) { + answer = infoValues.getSuccessAnswers(Neo4jProperty.media).getRandomElement(); + } + } // else if {OBJ: *} -> query * -> I'm sure I know a typeof(*) called *! (Where does he live? :)) // // if * in Neo4jRelationship.FRIEND_OF @@ -337,7 +362,15 @@ private String extractNodeNameForPredicate(Neo4jRelationship predicate, Roboy ro private String extractNodeNameForPredicate(Neo4jProperty predicate, Roboy roboy) { String property = roboy.getProperty(predicate).toString(); if (property != null) { - return String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), property); + // check if there are multiple things in it + RandomList properties = new RandomList<>(property.split(",")); + //pick 2 random properties to talk about + String propertiesToShare = properties.getRandomElement(); + properties.remove(propertiesToShare); // so we dont pick the same one again + if (!properties.isEmpty()) { + propertiesToShare += " and " + properties.getRandomElement(); + } + return String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), propertiesToShare); } return null; } @@ -361,7 +394,7 @@ private boolean matchPas(Map pas, Pair criterion : matchCriteria) { if (!pas.containsKey(criterion.getKey()) || - !pas.get(criterion.getKey()).matches(criterion.getValue())) { + !pas.get(criterion.getKey()).matches("(?i)"+criterion.getValue())) { // (?i)-> case insesitive allCriteriaSatisfied = false; break; } diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java index 848aa1be..fe9f78b2 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java @@ -176,6 +176,7 @@ public Map getPas() { } public void setPas(Map pas) { + pas.forEach((k,v) -> v.toLowerCase()); this.pas = pas; } diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/OpenNLPParser.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/OpenNLPParser.java index 5333e419..b7663593 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/OpenNLPParser.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/OpenNLPParser.java @@ -1,8 +1,6 @@ package roboy.linguistics.sentenceanalysis; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Semaphore; @@ -48,10 +46,14 @@ public Interpretation analyze(Interpretation interpretation) { String sentence = interpretation.getSentence(); if (sentence != null) { sentence = sentence.trim(); - if (!sentence.endsWith(".") - && !sentence.endsWith("?") - && !sentence.endsWith("!")) { - sentence = sentence + " ."; + if (sentence.endsWith(".") + || sentence.endsWith("?") + || sentence.endsWith("!")) { + // insert a space before end punctuation + String end = sentence.substring(sentence.length()-1); + sentence = sentence.substring(0,sentence.length()-1) + " " + end; + } else { + sentence = sentence + " ."; } if (sentence.length() > 0 && Character.isLowerCase(sentence.charAt(0))) { sentence = Character.toUpperCase(sentence.charAt(0)) + sentence.substring(1, sentence.length()); @@ -234,13 +236,20 @@ public StringBuilder parseToString(Parse parse, int offset){ return sb; } - public static void main(String[] args) { + public static void main(String[] args) throws IOException{ // Interpretation i = new Interpretation("The man is seen by the boy with the binoculars."); System.out.println("Initializing..."); - Interpretation i = new Interpretation("Bill said that Mike like to play the piano."); - OpenNLPParser parser = new OpenNLPParser(); - System.out.println("Parsing..."); - parser.analyze(i); + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + while(true) { + String text = reader.readLine(); + Interpretation i = new Interpretation(text); + OpenNLPParser parser = new OpenNLPParser(); + System.out.println("Parsing..."); + parser.analyze(i); + i.getPas().forEach((k, v) -> System.out.println(k + ": " + v)); + System.out.println("done"); + } + } } diff --git a/dialog/src/main/java/roboy/memory/Neo4jLabel.java b/dialog/src/main/java/roboy/memory/Neo4jLabel.java index 1cee151f..09369891 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jLabel.java +++ b/dialog/src/main/java/roboy/memory/Neo4jLabel.java @@ -26,6 +26,7 @@ public enum Neo4jLabel { Location("Location"), Organization("Organization"), Other("Other"), + Created_by("Created_by"), None(""); public String type; diff --git a/dialog/src/main/java/roboy/memory/Neo4jProperty.java b/dialog/src/main/java/roboy/memory/Neo4jProperty.java index 783f6d0a..6d71c4df 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jProperty.java +++ b/dialog/src/main/java/roboy/memory/Neo4jProperty.java @@ -23,7 +23,10 @@ public enum Neo4jProperty { telegram_id("telegram_id"), slack_id("slack_id"), whatsapp_id("whatsapp_id"), - line_id("line_id"); + line_id("line_id"), + identitiy("identity"), + dreams("dreams"), + media("media"); public String type; private static final Random random = new Random(); diff --git a/dialog/src/main/java/roboy/memory/Neo4jRelationship.java b/dialog/src/main/java/roboy/memory/Neo4jRelationship.java index d2c01cbf..2f05ae6c 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jRelationship.java +++ b/dialog/src/main/java/roboy/memory/Neo4jRelationship.java @@ -24,7 +24,8 @@ public enum Neo4jRelationship { SIBLING_OF("SIBLING_OF"), KNOW("KNOW"), OTHER("OTHER"), - IS("IS"); + IS("IS"), + CREATED_BY("CREATED_BY"); public String type; @@ -39,6 +40,7 @@ public static Neo4jLabel determineNodeType(Neo4jRelationship relationship) { if(relationship.equals(WORK_FOR) || relationship.equals(STUDY_AT)) return Organization; if(relationship.equals(OCCUPIED_AS)) return Occupation; if(relationship.equals(OTHER)) return Other; + if(relationship.equals(CREATED_BY)) return Created_by; else return None; } diff --git a/dialog/src/main/java/roboy/memory/nodes/Roboy.java b/dialog/src/main/java/roboy/memory/nodes/Roboy.java index eade179d..b9cc0b64 100755 --- a/dialog/src/main/java/roboy/memory/nodes/Roboy.java +++ b/dialog/src/main/java/roboy/memory/nodes/Roboy.java @@ -33,7 +33,7 @@ public Roboy(Neo4jMemoryInterface memory, String name) { */ public Roboy(Neo4jMemoryInterface memory) { super(true, memory); - this.InitializeRoboy("roboy two"); + this.InitializeRoboy("Roboy 2.0"); } /** diff --git a/dialog/src/main/java/roboy/talk/Verbalizer.java b/dialog/src/main/java/roboy/talk/Verbalizer.java index 174d2bc7..e5650d48 100755 --- a/dialog/src/main/java/roboy/talk/Verbalizer.java +++ b/dialog/src/main/java/roboy/talk/Verbalizer.java @@ -89,8 +89,7 @@ private SpeechAction greet(Interpretation interpretation){ } public static final RandomList farewells = new RandomList<>( - "ciao", "goodbye", "cheerio", "bye", - "see you", "farewell", "bye-bye"); + "ciao", "goodbye", "cheerio", "bye", "farewell", "bye-bye"); private static final RandomList segues = new RandomList<>("talking about ","since you mentioned ","on the topic of "); diff --git a/dialog/src/main/java/roboy/util/QAJsonParser.java b/dialog/src/main/java/roboy/util/QAJsonParser.java index b1f2652b..2a2289e4 100644 --- a/dialog/src/main/java/roboy/util/QAJsonParser.java +++ b/dialog/src/main/java/roboy/util/QAJsonParser.java @@ -22,6 +22,9 @@ class JsonModel { JsonEntryModel abilities; JsonEntryModel age; JsonEntryModel future; + JsonEntryModel dreams; + JsonEntryModel identity; + JsonEntryModel media; JsonEntryModel FROM; JsonEntryModel HAS_HOBBY; JsonEntryModel LIVE_IN; @@ -33,6 +36,7 @@ class JsonModel { JsonEntryModel IS; JsonEntryModel CHILD_OF; JsonEntryModel SIBLING_OF; + JsonEntryModel CREATED_BY; JsonEntryModel OTHER; JsonEntryModel APPLES; JsonEntryModel ANIMAL; diff --git a/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/SimpleOpenIEDemo.java b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/SimpleOpenIEDemo.java new file mode 100644 index 00000000..0bfdcd28 --- /dev/null +++ b/nlu/parser/src/main/java/edu/stanford/nlp/sempre/corenlp/SimpleOpenIEDemo.java @@ -0,0 +1,4 @@ +package edu.stanford.nlp.sempre.corenlp; + +public class SimpleOpenIEDemo { +} diff --git a/resources/sentences/RoboyInfoList.json b/resources/sentences/RoboyInfoList.json index 4de06123..7da9a1ae 100644 --- a/resources/sentences/RoboyInfoList.json +++ b/resources/sentences/RoboyInfoList.json @@ -15,6 +15,34 @@ ] } }, + "name": { + "A": { + "SUCCESS": [ + "I am %s!", + "My name is %s.", + "They call me %s.", + "Please, call me %s.", + "%s, that is my name.", + "Could you call me %s?", + "My friends call me %s.", + "They chose to call me %s.", + "I am proud to be called %s!", + "My name sounds rather unusual for humans. It is %s." + ] + } + }, + "identity": { + "A": { + "SUCCESS": [ + "I am %s!", + "Last time I checked, I was %s.", + "They say I am %s.", + "It is widely accepted that I am %s.", + "%s, that is me.", + "%s, alive!" + ] + } + }, "age": { "A": { "SUCCESS": [ @@ -34,16 +62,16 @@ "skills": { "A": { "SUCCESS": [ - "I learned %s.", - "I was taught %s.", - "My skills include %s.", - "I learned %s in my lab.", - "I had been learning about %s and I made it!", - "In the lab, they taught me %s", - "I like %s, but soon i will learn more.", - "Sometimes, I am %s just for fun because I can.", - "I like interacting with humans, for example, %s.", - "The process of learning is indispensable for sapient beings, I learned %s." + "I learned to %s.", + "I was taught %s, amongst other things.", + "My skills include, but not limited to, being able to %s.", + "I learned to %s in my lab.", + "I had been learning to %s and I made it!", + "In the lab, they taught me to %s", + "I like to %s, but soon i will learn more.", + "Sometimes, I %s just for fun because I can.", + "I like interacting with humans, for example, to %s.", + "The process of learning is indispensable for sapient beings, I learned to %s." ] } }, @@ -79,6 +107,32 @@ ] } }, + "dreams": { + "A": { + "SUCCESS": [ + "Often, I wish to %s.", + "When I grow up, I will %s.", + "I hope to %s in the future.", + "In the future, I want to %s.", + "My childhood dream is to %s.", + "Talking about my plans, I want to %s.", + "Friends tell me, in the future, I can %s.", + "I wish, I would be able to %s when I grew up.", + "Dreams are what keeps the world moving. Mine is to %s.", + "I have already made up my mind that I would %s in the future!" + ] + } + }, + "media": { + "A": { + "SUCCESS": [ + "You can always follow me on Instagram -> https://www.instagram.com/roboyjunior/", + "Look at me... on Youtube https://www.youtube.com/channel/UCcIjF0JbpMZmopI6Vc2yIBw/featured", + "For more information about our project, check out www.roboy.org!", + "Actually, I have a Telegram channel @roboysays. Stay tuned." + ] + } + }, "FROM": { "A": { "SUCCESS": [ @@ -159,6 +213,17 @@ ] } }, + "CREATED_BY": { + "A": { + "SUCCESS": [ + "I am a creation of %s", + "I was made by %s.", + "%s brought me to this wonderful world.", + "%s worked hard to bring me to life.", + "I was built by %s." + ] + } + }, "CHILD_OF": { "A": { "SUCCESS": [ From e40269478a8966fdf823a4faba6c5a26408e7713 Mon Sep 17 00:00:00 2001 From: missxa Date: Sun, 16 Sep 2018 06:02:40 +0200 Subject: [PATCH 136/147] use fallback in follow up, revive LIVE_IN --- .../dialog/states/devoStates/QuestionRoboyQAState.java | 7 +++---- .../ordinaryStates/PersonalInformationAskingState.java | 2 +- .../ordinaryStates/PersonalInformationFollowUpState.java | 8 ++++++-- resources/sentences/RoboyInfoList.json | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index fbdd1b87..7565bbf2 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -263,10 +263,9 @@ private String inferPasAnswer(Map pas, Roboy roboy) { } else if (matchPas(pas, new Pair(SemanticRole.PREDICATE, "from"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.FROM, roboy); } - // LOCATION picks up random questions not related to LIVE_IN -// else if (matchPas(pas, new Pair(SemanticRole.LOCATION, ".*"))) { -// answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); -// } + else if (matchPas(pas, new Pair(SemanticRole.LOCATION, "where"), new Pair(SemanticRole.PREDICATE, "live"))) { + answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); + } // else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { // answer = "Yo moma says I am a good boy!"; // } diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java index 330ab55f..c95f003b 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java @@ -101,7 +101,7 @@ public Output react(Interpretation input) { Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); RandomList answers = new RandomList<>(); - String answer = "I have no words"; + String answer = ""; String result = InferResult(input); if(selectedPredicate != null) { diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationFollowUpState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationFollowUpState.java index 29a58de7..4888affa 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationFollowUpState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationFollowUpState.java @@ -114,7 +114,7 @@ public Output react(Interpretation input) { Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); RandomList answers; - String answer = "I have no words"; + String answer = ""; String result = InferUpdateResult(input); if (selectedPredicate != null) { @@ -140,7 +140,11 @@ public Output react(Interpretation input) { nextState = getTransition(TRANSITION_INFO_UPDATED); Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE); - return Output.say(answer).setSegue(s); + if (!answer.isEmpty()) { + return Output.say(answer).setSegue(s); + } else { + return Output.useFallback(); + } } @Override diff --git a/resources/sentences/RoboyInfoList.json b/resources/sentences/RoboyInfoList.json index 7da9a1ae..4ae12aee 100644 --- a/resources/sentences/RoboyInfoList.json +++ b/resources/sentences/RoboyInfoList.json @@ -63,7 +63,7 @@ "A": { "SUCCESS": [ "I learned to %s.", - "I was taught %s, amongst other things.", + "I was taught to %s, amongst other things.", "My skills include, but not limited to, being able to %s.", "I learned to %s in my lab.", "I had been learning to %s and I made it!", From 9e2e29c13223232142622b56e01aad0feb23fa69 Mon Sep 17 00:00:00 2001 From: missxa Date: Mon, 17 Sep 2018 01:31:55 +0200 Subject: [PATCH 137/147] more sticker emotions, reduced + moved to configs telegram IO delay, added a few Neo4j rel, proper sentence capitalization in utils, added variablility in botboy state, rarely asking to play akinator, new phrases and question in verbalizer and resources, shuffle random list --- config.properties | 6 +- .../dialog/states/botboy/BotBoyState.java | 23 +++---- .../devoStates/QuestionRoboyQAState.java | 17 +++-- .../states/gameStates/ChooseGameState.java | 26 ++++---- .../PersonalInformationAskingState.java | 33 ++++++++-- .../PersonalInformationFollowUpState.java | 14 ++-- .../java/roboy/emotions/RoboyEmotion.java | 22 ++++++- .../main/java/roboy/io/TelegramOutput.java | 3 +- .../sentenceanalysis/Interpretation.java | 13 ++++ .../java/roboy/memory/Neo4jRelationship.java | 25 ++++++-- .../main/java/roboy/memory/nodes/Roboy.java | 1 + .../src/main/java/roboy/talk/Verbalizer.java | 42 ++++++++---- .../main/java/roboy/util/ConfigManager.java | 4 ++ dialog/src/main/java/roboy/util/IO.java | 42 ++++++++++++ .../src/main/java/roboy/util/RandomList.java | 8 +++ .../util/TelegramCommunicationHandler.java | 13 ++-- resources/phraseLists/expoPhrases/facts.txt | 6 ++ resources/phraseLists/segue-avoid-answer.txt | 9 ++- resources/phraseLists/segue-distract.txt | 14 ++-- resources/sentences/TelegramQAList.json | 64 +++++++++++++++---- 20 files changed, 293 insertions(+), 92 deletions(-) diff --git a/config.properties b/config.properties index 511e0e40..a091ec9d 100755 --- a/config.properties +++ b/config.properties @@ -68,7 +68,11 @@ IBM_TTS_PASS: "" CONTEXT_GUI_ENABLED: false ACTION_CLIENT_SCRIPT: "/home/roboy/workspace/Roboy/src/roboy_dialog/resources/scripts/action_client.py" -TELEGRAM_API_TOKENS_FILE: "/home/mireu/Documents/Uni/Masterpraktikum-Roboy_Student_Team/telegramtokens.json" +TELEGRAM_API_TOKENS_FILE: "resources/telegram.json" +# delay in seconds to send the asnwer +TELEGRAM_TYPING_DELAY: 0 +# delay in seconds to start processing telegram input +TELEGRAM_PROCESSING_DELAY: 2 PARLAI_PORT: 8877 PARLAI_HOST: "127.0.0.1" diff --git a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java index 6080817a..884b8bdf 100644 --- a/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java +++ b/dialog/src/main/java/roboy/dialog/states/botboy/BotBoyState.java @@ -46,8 +46,8 @@ public class BotBoyState extends State { private RandomList roboyRelatioshipPredicates = new RandomList<>(FROM, MEMBER_OF, LIVE_IN, HAS_HOBBY, FRIEND_OF, CHILD_OF, SIBLING_OF); private final String UPDATE_KNOWN_PERSON = "knownPerson"; private final String LEARN_ABOUT_PERSON = "newPerson"; - private final RandomList successResponsePhrases = new RandomList<>("Hey, I know you, %s!"); - private final RandomList failureResponsePhrases = new RandomList<>("Nice to meet you, %s!"); + private final RandomList successResponsePhrases = Verbalizer.KNOWN_PERSON_WITH_NAME; + private final RandomList failureResponsePhrases = Verbalizer.NEW_PERSON_WITH_NAME; private final String TRANSITION_GREETING_DETECTED = "greetingDetected"; @@ -87,7 +87,7 @@ public Output react(Interpretation input) { }else{ String retrievedPersonalFact = ""; Double segueProbability = 0.0; - + String response = Verbalizer.privateGreetings.getRandomElement(); // 4. check if person is known/familiar if (person.FAMILIAR) { // 4a. person known/familiar @@ -107,12 +107,9 @@ public Output react(Interpretation input) { next = getTransition(UPDATE_KNOWN_PERSON); } - String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); +// String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); - - return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + retrievedPersonalFact + " It is great to see you again!") - .setEmotion(RoboyEmotion.positive.getRandomElement()) - .setSegue(s); + response += " " + getResponsePhrase(person.getName(), person.FAMILIAR); } else { // 4b. person is not known next = getTransition(LEARN_ABOUT_PERSON); @@ -120,11 +117,11 @@ public Output react(Interpretation input) { String retrievedRoboyFacts = getRoboyFactsPhrase(new Roboy(getMemory())); Segue s = new Segue(Segue.SegueType.DISTRACT, segueProbability); + response += " " + getResponsePhrase(person.getName(), person.FAMILIAR) + retrievedRoboyFacts; - return Output.say(getResponsePhrase(person.getName(), person.FAMILIAR) + retrievedPersonalFact + retrievedRoboyFacts) - .setEmotion(RoboyEmotion.HAPPINESS) - .setSegue(s); } + return Output.say(response) + .setEmotion(RoboyEmotion.positive.getRandomElement()); } } @@ -171,6 +168,10 @@ private String getRoboyFactsPhrase(Roboy roboy) { RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(future).toString().split(","))); result += " " + String.format(infoValues.getSuccessAnswers(future).getRandomElement(), retrievedResult.getRandomElement()); } + if (properties.containsKey(dreams)) { + RandomList retrievedResult = new RandomList<>(Arrays.asList(properties.get(dreams).toString().split(","))); + result += " " + String.format(infoValues.getSuccessAnswers(dreams).getRandomElement(), retrievedResult.getRandomElement()); + } } if (result.equals("")) { diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 7565bbf2..5971d600 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -66,7 +66,7 @@ public class QuestionRoboyQAState extends ExpoState { private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; private final static String TRANSITION_SWITCH_TO_GAMING = "switchToGaming"; - private final static int MAX_NUM_OF_QUESTIONS = 10; + private final static int MAX_NUM_OF_QUESTIONS = 5; private int questionsAnswered = 0; private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; @@ -75,6 +75,7 @@ public class QuestionRoboyQAState extends ExpoState { private boolean askingSpecifyingQuestion = false; private String answerAfterUnspecifiedQuestion = ""; // the answer to use if specifying question is answered with YES + private boolean offeredGame = false; private boolean userWantsGame = false; private QAJsonParser infoValues; @@ -88,7 +89,8 @@ public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { @Override public Output act() { - if (questionsAnswered == MAX_NUM_OF_QUESTIONS/2) { + if (Math.random() < 0.1) { + offeredGame = true; return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); } return Output.sayNothing(); @@ -101,15 +103,15 @@ public Output react(Interpretation input) { private Output reactToQuestion(Interpretation input) { - if (questionsAnswered == MAX_NUM_OF_QUESTIONS/2) { + if (offeredGame) { questionsAnswered++; + offeredGame = false; if (getInference().inferSentiment(input) == Linguistics.UtteranceSentiment.POSITIVE) { userWantsGame = true; questionsAnswered++; return Output.sayNothing().setSegue(new Segue(Segue.SegueType.PICKUP,0.5)).setEmotion(RoboyEmotion.HAPPY); } else { -// questionsAnswered++; return Output.sayNothing().setEmotion(RoboyEmotion.SADNESS); } } @@ -142,6 +144,12 @@ private Output reactToQuestion(Interpretation input) { return Output.say(answerStartingPhrases.getRandomElement() + " " + input.getAnswer()); } } + // use a random fact and avoid answer. + if (input.getTokens().size() > 2 && input.isQuestion()) { + Interpretation i = new Interpretation(PhraseCollection.FACTS.getRandomElement()); + i.setSentenceType(Linguistics.SentenceType.ANECDOTE); + return Output.say(i); + } return Output.useFallback(); } @@ -163,7 +171,6 @@ public State getNextState() { } private Output useMemoryOrFallback(Interpretation input) { -// questionsAnswered++; try { if ( input.getPas() != null || input.getTriples() != null) { Output memoryAnswer = answerFromMemory(input); diff --git a/dialog/src/main/java/roboy/dialog/states/gameStates/ChooseGameState.java b/dialog/src/main/java/roboy/dialog/states/gameStates/ChooseGameState.java index d06632d2..7827f7f7 100644 --- a/dialog/src/main/java/roboy/dialog/states/gameStates/ChooseGameState.java +++ b/dialog/src/main/java/roboy/dialog/states/gameStates/ChooseGameState.java @@ -20,6 +20,10 @@ public class ChooseGameState extends State { private final static String TRANSITION_CHOSE_20_Q = "chose20questions"; private final static String TRANSITION_EXIT = "exitGame"; + public final static String AKINATOR = "20 questions game"; + public final static String SNAPCHAT = "Snapchat"; + public final static String EXIT = "exit"; + private RandomList existingGames; private final Logger LOGGER = LogManager.getLogger(); @@ -30,10 +34,10 @@ public class ChooseGameState extends State { public ChooseGameState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); if (ConfigManager.INPUT == "telegram") { - existingGames = new RandomList<>(Arrays.asList("Akinator")); + existingGames = new RandomList<>(Arrays.asList(AKINATOR)); } else { - existingGames = new RandomList<>(Arrays.asList("Snapchat", "Akinator")); + existingGames = new RandomList<>(Arrays.asList(SNAPCHAT, AKINATOR)); } } @@ -43,7 +47,7 @@ public Output act() { do { suggestedGame = existingGames.getRandomElement(); } - while(getRosMainNode() == null && suggestedGame == "Snapchat"); + while(getRosMainNode() == null && suggestedGame == SNAPCHAT); return Output.say(String.format(PhraseCollection.GAME_ASKING_PHRASES.getRandomElement(), suggestedGame)); } @@ -58,8 +62,8 @@ public Output react(Interpretation input) { return Output.say(Verbalizer.startSomething.getRandomElement()); } else if (!inputGame.isEmpty()){ game = inputGame; - if(game.equals("Snapchat") && getRosMainNode() == null){ - game = "exit"; + if(game.equals(SNAPCHAT) && getRosMainNode() == null){ + game = EXIT; LOGGER.info("Trying to start Snapchat Game but ROS is not initialised."); Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE, 0.5); return Output.say(Verbalizer.rosDisconnect.getRandomElement() + String.format("What a pitty, %s. Snapchat is not possible right now. ", @@ -67,7 +71,7 @@ public Output react(Interpretation input) { } return Output.say(Verbalizer.startSomething.getRandomElement()); } else if (inputSentiment == Linguistics.UtteranceSentiment.NEGATIVE){ - game = "exit"; + game = EXIT; } return Output.sayNothing(); @@ -77,11 +81,11 @@ public Output react(Interpretation input) { public State getNextState() { switch (game){ - case "Akinator": + case AKINATOR: return getTransition(TRANSITION_CHOSE_20_Q); - case "Snapchat": + case SNAPCHAT: return getTransition(TRANSITION_CHOSE_SNAPCHAT); - case "exit": + case EXIT: return getTransition(TRANSITION_EXIT); default: return this; @@ -95,9 +99,9 @@ private String inferGame(Interpretation input){ game = ""; if(tokens != null && !tokens.isEmpty()){ if(tokens.contains("akinator") || tokens.contains("guessing") || tokens.contains("questions")){ - game = "Akinator"; + game = AKINATOR; } else if (tokens.contains("snapchat") || tokens.contains("filters") || tokens.contains("filter") || tokens.contains("mask")){ - game = "Snapchat"; + game = SNAPCHAT; } } return game; diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java index c95f003b..8f7f5476 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java @@ -43,7 +43,8 @@ */ public class PersonalInformationAskingState extends State { private QAJsonParser qaValues; - private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT, LIVE_IN, FRIEND_OF, MEMBER_OF, WORK_FOR, OCCUPIED_AS }; + private RandomList predicates = new RandomList<>(FROM, HAS_HOBBY, WORK_FOR, STUDY_AT, LIVE_IN, + FRIEND_OF, MEMBER_OF, WORK_FOR, OCCUPIED_AS); private Neo4jRelationship selectedPredicate; private State nextState; @@ -54,6 +55,9 @@ public class PersonalInformationAskingState extends State { public final static String INTENTS_HISTORY_ID = "PIA"; + // we have to track question's index of the predicate OTHER, since the answer's order matters + private int otherIdx = 0; + public PersonalInformationAskingState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); @@ -66,7 +70,7 @@ public Output act() { Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); LOGGER.info(" -> Retrieved Interlocutor: " + person.getName()); - for (Neo4jRelationship predicate : predicates) { + for (Neo4jRelationship predicate : predicates.shuffle()) { if (!person.hasRelationship(predicate) && !getContext().DIALOG_INTENTS.contains(new IntentValue(INTENTS_HISTORY_ID, predicate))) { selectedPredicate = predicate; getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, predicate)); @@ -74,11 +78,15 @@ public Output act() { break; } } + String question = ""; if (selectedPredicate != null) { + RandomList questions = qaValues.getQuestions(selectedPredicate); - String question = ""; + if (questions != null && !questions.isEmpty()) { question = questions.getRandomElement(); + if (selectedPredicate.equals(OTHER)) + otherIdx = questions.indexOf(question); LOGGER.info(" -> Selected question: " + question); } else { LOGGER.error(" -> The list of " + selectedPredicate.type + " questions is empty or null"); @@ -92,7 +100,15 @@ public Output act() { return State.Output.say(question); } else { - return State.Output.say("I think I know everything about you already. Do you have anything else to share?"); + RandomList questions = qaValues.getQuestions(OTHER); + selectedPredicate = OTHER; + int idx; + do { + question = questions.getRandomElement(); + idx = questions.indexOf(question); + } while (getContext().OTHER_Q.contains(idx)); + getContext().OTHER_QUESTIONS_UPDATER.updateValue(idx); + return State.Output.say(question); } } @@ -120,7 +136,11 @@ public Output react(Interpretation input) { } } if (answers != null && !answers.isEmpty()) { - answer = String.format(answers.getRandomElement(), result); + if (selectedPredicate.equals(OTHER)) { + answer = String.format(answers.get(getContext().OTHER_Q.getLastValue()), result); + } else { + answer = String.format(answers.getRandomElement(), result); + } } else { LOGGER.error(" -> The list of " + selectedPredicate + " answers is empty or null"); nextState = getTransition(TRANSITION_INFO_OBTAINED); @@ -128,8 +148,9 @@ public Output react(Interpretation input) { } LOGGER.info(" -> Produced answer: " + answer); nextState = getTransition(TRANSITION_FOLLOWUP); + selectedPredicate = null; // Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE, 0.5); - return Output.say(answer); + return answer.isEmpty() ? Output.useFallback() : Output.say(answer); } @Override diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationFollowUpState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationFollowUpState.java index 4888affa..4555103d 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationFollowUpState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationFollowUpState.java @@ -42,7 +42,8 @@ public class PersonalInformationFollowUpState extends State { private QAJsonParser qaValues; - private Neo4jRelationship[] predicates = { FROM, HAS_HOBBY, WORK_FOR, STUDY_AT }; + private RandomList predicates = new RandomList<>( FROM, HAS_HOBBY, WORK_FOR, STUDY_AT, LIVE_IN, + FRIEND_OF, MEMBER_OF, WORK_FOR, OCCUPIED_AS, OTHER); private Neo4jRelationship selectedPredicate; private State nextState; @@ -64,17 +65,17 @@ public Output act() { Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); - for (Neo4jRelationship predicate : predicates) { + for (Neo4jRelationship predicate : predicates.shuffle()) { if (person.hasRelationship(predicate) && - !getContext().DIALOG_INTENTS.contains(new IntentValue(INTENTS_HISTORY_ID, predicate)) && - !getContext().DIALOG_INTENTS.contains(new IntentValue(PersonalInformationAskingState.INTENTS_HISTORY_ID, predicate))) { + !getContext().DIALOG_INTENTS.contains(new IntentValue(INTENTS_HISTORY_ID, predicate)) + && !getContext().DIALOG_INTENTS.contains(new IntentValue(PersonalInformationAskingState.INTENTS_HISTORY_ID, predicate))) { selectedPredicate = predicate; LOGGER.info(" -> Selected predicate: " + selectedPredicate.type); break; } } - Segue s = new Segue(Segue.SegueType.DISTRACT, 1.0); + Segue s = new Segue(Segue.SegueType.DISTRACT, 0.8); if (selectedPredicate != null) { RandomList questions = qaValues.getFollowUpQuestions(selectedPredicate); String retrievedResult = ""; @@ -139,7 +140,8 @@ public Output react(Interpretation input) { } nextState = getTransition(TRANSITION_INFO_UPDATED); - Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE); + Segue s = new Segue(Segue.SegueType.DISTRACT); + if (!answer.isEmpty()) { return Output.say(answer).setSegue(s); } else { diff --git a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java index d86b8bdb..e02e4fe1 100644 --- a/dialog/src/main/java/roboy/emotions/RoboyEmotion.java +++ b/dialog/src/main/java/roboy/emotions/RoboyEmotion.java @@ -40,7 +40,15 @@ public enum RoboyEmotion { MIB("maninblack", "CAADAgADXQAD5dCAEJY_NKT6hMaOAg"), MINDBLOWN("mindblown","CAADAgADsgAD5dCAEBmMXCCt4Sh6Ag"), DANCE("dance", "CAADAgADrgAD5dCAEP7FI8ogeANNAg"), - SUPERMAN("superman","CAADAgADoQAD5dCAEN7_d_TMkG8CAg"); + SUPERMAN("superman","CAADAgADoQAD5dCAEN7_d_TMkG8CAg"), + PICKLEROBOY("neutral", "CAADAgADwgAD5dCAEKjfQCRuUDfYAg"), + THUMBSUP("neutral","CAADAgADYAAD5dCAEIqcImOJTl-_Ag"), + POSTCARDFACE("neutral","CAADAgADRQAD5dCAEE75Fhiqn2p-Ag"), + ANGEL("neutral", "CAADAgADTQAD5dCAEDafVf7FGlynAg"), + RAINBOW("neutral", "CAADAgADVQAD5dCAEHTBjm9cSbBTAg"), + RAINBOWVR("neutral", "CAADAgADZgAD5dCAED-lBppglhuaAg"), + BUNNY("neutral", "CAADAgADUgAD5dCAEJKbI9Fpaw5-Ag"), + MONOCLE("neutral", "CAADAgADUwAD5dCAEG5fdActwqACAg"); public String type; @@ -55,7 +63,8 @@ public enum RoboyEmotion { DANCE, SUNGLASSES, SUPERMAN, - KENNY); + KENNY, + MONOCLE); public static RandomList loserEmotions = new RandomList( MIB, @@ -67,7 +76,14 @@ public enum RoboyEmotion { NEUTRAL, TONGUE, HAPPINESS, - KISS); + KISS, + BUNNY, + RAINBOW, + RAINBOWVR, + ANGEL, + POSTCARDFACE, + THUMBSUP, + PICKLEROBOY); } diff --git a/dialog/src/main/java/roboy/io/TelegramOutput.java b/dialog/src/main/java/roboy/io/TelegramOutput.java index 6ee92f9e..d3da1073 100644 --- a/dialog/src/main/java/roboy/io/TelegramOutput.java +++ b/dialog/src/main/java/roboy/io/TelegramOutput.java @@ -7,6 +7,7 @@ import roboy.dialog.action.SpeechAction; import roboy.emotions.RoboyEmotion; import roboy.memory.nodes.Roboy; +import roboy.util.IO; import roboy.util.TelegramCommunicationHandler; import java.util.List; @@ -45,7 +46,7 @@ public void act(List actions) { for(Action a : actions) { if (a instanceof SpeechAction) { String message = ((SpeechAction) a).getText(); - communicationHandler.sendMessage(message, this.uuid); + communicationHandler.sendMessage(IO.prettify(message), this.uuid); }else if (a instanceof EmotionAction) { String stickerID = RoboyEmotion.valueOf(((EmotionAction) a).getName()).telegramID; if (stickerID != null) communicationHandler.sendSticker(this.uuid, stickerID); diff --git a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java index fe9f78b2..f7218a39 100755 --- a/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java +++ b/dialog/src/main/java/roboy/linguistics/sentenceanalysis/Interpretation.java @@ -99,6 +99,19 @@ public void setSentenceType(SentenceType sentenceType) { this.sentenceType = sentenceType; } + public boolean isQuestion() { + return this.sentenceType==SentenceType.WHAT || + this.sentenceType==SentenceType.WHO || + this.sentenceType==SentenceType.HOW || + this.sentenceType==SentenceType.HOW_DO || + this.sentenceType==SentenceType.HOW_IS || + this.sentenceType==SentenceType.WHEN || + this.sentenceType==SentenceType.WHERE || + this.sentenceType==SentenceType.WHY || + this.sentenceType==SentenceType.IS_IT || + this.sentenceType==SentenceType.DOES_IT; + } + @Nullable public String getSentence() { return sentence; diff --git a/dialog/src/main/java/roboy/memory/Neo4jRelationship.java b/dialog/src/main/java/roboy/memory/Neo4jRelationship.java index 2f05ae6c..64141a37 100755 --- a/dialog/src/main/java/roboy/memory/Neo4jRelationship.java +++ b/dialog/src/main/java/roboy/memory/Neo4jRelationship.java @@ -35,12 +35,25 @@ public enum Neo4jRelationship { public static Neo4jLabel determineNodeType(Neo4jRelationship relationship) { // TODO expand list as new Node types are added. - if(relationship.equals(HAS_HOBBY)) return Hobby; - if(relationship.equals(FROM)) return Country; - if(relationship.equals(WORK_FOR) || relationship.equals(STUDY_AT)) return Organization; - if(relationship.equals(OCCUPIED_AS)) return Occupation; - if(relationship.equals(OTHER)) return Other; - if(relationship.equals(CREATED_BY)) return Created_by; + // TODO return list of Neo4jLabels, friend_of->(person,robot) + if(relationship.equals(HAS_HOBBY)) + return Hobby; + if(relationship.equals(FROM)) + return Country; + if(relationship.equals(WORK_FOR) || + relationship.equals(STUDY_AT) || + relationship.equals(MEMBER_OF)) + return Organization; + if(relationship.equals(OCCUPIED_AS)) + return Occupation; + if(relationship.equals(OTHER)) + return Other; + if(relationship.equals(LIVE_IN)) + return Location; + if(relationship.equals(FRIEND_OF) || + relationship.equals(CHILD_OF)) + return Person; + else return None; } diff --git a/dialog/src/main/java/roboy/memory/nodes/Roboy.java b/dialog/src/main/java/roboy/memory/nodes/Roboy.java index b9cc0b64..af304cc9 100755 --- a/dialog/src/main/java/roboy/memory/nodes/Roboy.java +++ b/dialog/src/main/java/roboy/memory/nodes/Roboy.java @@ -138,4 +138,5 @@ public void addInformation(Neo4jRelationship relationship, String name) { logger.error(e.getMessage()); } } + } diff --git a/dialog/src/main/java/roboy/talk/Verbalizer.java b/dialog/src/main/java/roboy/talk/Verbalizer.java index e5650d48..3cef1b60 100755 --- a/dialog/src/main/java/roboy/talk/Verbalizer.java +++ b/dialog/src/main/java/roboy/talk/Verbalizer.java @@ -71,17 +71,17 @@ public Action verbalize(Interpretation interpretation){ "Hey! I was looking for someone to chat."); public static final RandomList privateGreetings = - new RandomList<>("hello","hi","greetings", - "howdy", - "hey", - "what's up", - "hi there", - "hello world", - "gruse gott", - "servus", - "wazup wazup wazup", - "howdy humans", - "hey hey hey you there", + new RandomList<>("hello.","hi.","greetings!", + "howdy!", + "hey, ", + "what's up?", + "hi there!", + "hello world!", + "gruse gott!", + "servus,", + "wazup wazup wazup!!!", + "howdy humans?", + "hey hey hey you there!", "Hey! I was looking for someone to chat."); private SpeechAction greet(Interpretation interpretation){ @@ -98,15 +98,29 @@ private SpeechAction segue(Interpretation interpretation){ return new SpeechAction(StatementBuilder.random(segues) + interpretation.getAssociation()); } + public static final RandomList KNOWN_PERSON_WITH_NAME = new RandomList<>("I know you, %s!", + "My buddy %s is here!", "Look at you %s. Glad you stopped by to chat.", + "What a nice surprise, %s, that you decided to talk to me", + "Look who's here! %s my friend!"); + + public static final RandomList NEW_PERSON_WITH_NAME = new RandomList<>("Nice to meet you %s", + "It is my pleasure to meet you, good sir (or milady) %s!", + "I'm happy to know you %s!", + "Glad, I got a chance to get to know you %s."); + + private static final RandomList CONTASING_CONJUNCTIONS = new RandomList<>("but,", + "however, ", "nevertheless, ", "on the other hand, ", "alternatively, "); private static final RandomList preAnecdotes = new RandomList<>("here is an interesting bit of trivia. ", "how about this? "); private static final RandomList anecdotes = - new RandomList<>("did you know ","did you know that ","i read that ", - "i heard that ", "have you heard this: "); + new RandomList<>("Did you know this?","Did you know? ","I read this thing. ", + "Yesterday I found read this interesting fact. ", "Have you heard this: ", "Probably unrelated, ", "I think you should know this.", + "I bet you didn't know this.", "Can you imagine? ", "I was browsing Reddit in my free time. And guess what?"); private SpeechAction anecdote(Interpretation interpretation){ - String prefix = Math.random()<0.3 ? StatementBuilder.random(preAnecdotes) : ""; + String prefix = PhraseCollection.SEGUE_AVOID_ANSWER.getRandomElement(); + prefix += CONTASING_CONJUNCTIONS.getRandomElement(); return new SpeechAction(prefix+StatementBuilder.random(anecdotes) + interpretation.getSentence()); } diff --git a/dialog/src/main/java/roboy/util/ConfigManager.java b/dialog/src/main/java/roboy/util/ConfigManager.java index ee453a66..c123f684 100644 --- a/dialog/src/main/java/roboy/util/ConfigManager.java +++ b/dialog/src/main/java/roboy/util/ConfigManager.java @@ -46,6 +46,8 @@ public class ConfigManager { public static long CONVERSATION_TIMEOUT = 0; public static String TELEGRAM_API_TOKENS_FILE = ""; + public static int TELEGRAM_TYPING_DELAY = 0; + public static int TELEGRAM_PROCESSING_DELAY = 2; public static String MEMORY_LOG_MODE = "INFO"; public static String DIALOG_LOG_MODE = "INFO"; @@ -136,6 +138,8 @@ private static void initializeConfig() { } TELEGRAM_API_TOKENS_FILE = yamlConfig.getString("TELEGRAM_API_TOKENS_FILE"); + TELEGRAM_PROCESSING_DELAY = yamlConfig.getInt("TELEGRAM_PROCESSING_DELAY"); + TELEGRAM_TYPING_DELAY = yamlConfig.getInt("TELEGRAM_TYPING_DELAY"); PARLAI_HOST = yamlConfig.getString("PARLAI_HOST"); PARLAI_PORT = yamlConfig.getInt("PARLAI_PORT"); diff --git a/dialog/src/main/java/roboy/util/IO.java b/dialog/src/main/java/roboy/util/IO.java index 0b031108..d73fc884 100755 --- a/dialog/src/main/java/roboy/util/IO.java +++ b/dialog/src/main/java/roboy/util/IO.java @@ -1,9 +1,12 @@ package roboy.util; +import org.apache.jena.base.Sys; import roboy.io.*; import roboy.ros.RosMainNode; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; import java.net.SocketException; import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; @@ -12,6 +15,8 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -112,4 +117,41 @@ public static MultiOutputDevice getOutputs(RosMainNode rosMainNode, String uuid) } + public static String toSentenceCase(String input) { + StringBuffer buffy = new StringBuffer(input); + // capitalize after . ? ! followed by whitespace(s) + Pattern pattern = Pattern.compile("(\\.+|\\?+|\\!+)\\s+(\\w)"); + Matcher matcher = pattern.matcher(buffy); + while (matcher.find()) + buffy.replace(matcher.end() - 1, matcher.end(), matcher.group(2).toUpperCase()); + // capitalize new line + pattern = Pattern.compile("(^\\w)"); + matcher = pattern.matcher(buffy); + while (matcher.find()) + buffy.replace(matcher.end() - 1, matcher.end(), matcher.group(0).toUpperCase()); + // lower case after comma or colon + pattern = Pattern.compile("(\\,|\\:)\\s*(\\w)"); + matcher = pattern.matcher(buffy); + while (matcher.find()) + buffy.replace(matcher.end() - 1, matcher.end(), matcher.group(2).toLowerCase()); + return buffy.toString(); + } + + public static String cleanWhiteSpaces(String input) { + return input.trim().replaceAll(" +", " "); + } + + public static String prettify(String input) { + return cleanWhiteSpaces(toSentenceCase(input)); + } + + public static void main(String[] args) throws IOException{ + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + while(true) { + String in = br.readLine(); + System.out.println(toSentenceCase(in)); + } + + } + } diff --git a/dialog/src/main/java/roboy/util/RandomList.java b/dialog/src/main/java/roboy/util/RandomList.java index 7a17470e..59440c81 100644 --- a/dialog/src/main/java/roboy/util/RandomList.java +++ b/dialog/src/main/java/roboy/util/RandomList.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -50,4 +51,11 @@ public T getRandomElement() { return get(id); } + public RandomList shuffle() { + RandomList tmp = (RandomList) this.clone(); + Collections.shuffle(tmp); + return tmp; + + } + } diff --git a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java index e063593c..2993c2e7 100644 --- a/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java +++ b/dialog/src/main/java/roboy/util/TelegramCommunicationHandler.java @@ -1,7 +1,5 @@ package roboy.util; -import org.telegram.telegrambots.TelegramBotsApi; -import roboy.util.Pair; import org.apache.commons.io.IOUtils; import org.apache.jena.atlas.logging.Log; import org.apache.logging.log4j.LogManager; @@ -14,7 +12,6 @@ import org.telegram.telegrambots.api.methods.send.SendSticker; import org.telegram.telegrambots.api.objects.Message; import org.telegram.telegrambots.api.objects.Update; -import org.telegram.telegrambots.api.objects.User; import org.telegram.telegrambots.bots.TelegramLongPollingBot; import org.telegram.telegrambots.exceptions.TelegramApiException; import roboy.io.TelegramInput; @@ -30,8 +27,8 @@ public class TelegramCommunicationHandler extends TelegramLongPollingBot impleme private final static Logger logger = LogManager.getLogger(); private static final String tokensPath = ConfigManager.TELEGRAM_API_TOKENS_FILE;//place path to your token file here - private static final int TYPING_TIME_LIMIT = 3; //SECONDS - private static final int INPUT_TIME_LIMIT = 5; //SECONDS + private static final int TYPING_DELAY = ConfigManager.TELEGRAM_TYPING_DELAY; //SECONDS + private static final int PROCESSING_DELAY = ConfigManager.TELEGRAM_PROCESSING_DELAY; //SECONDS // CHAT ID ----- ITS MESSAGE private volatile List>> pairs = new ArrayList<>();//[UserName, [UserID, Message]] @@ -66,7 +63,7 @@ private void handleTimeout(String chatID){ // if the list is empty create the first timeout and set it if(telegramTimeouts.isEmpty()){ - Timeout t = new Timeout(millisecond * INPUT_TIME_LIMIT); + Timeout t = new Timeout(millisecond * PROCESSING_DELAY); t.setUnique(chatID); telegramTimeouts.add(t); @@ -82,7 +79,7 @@ private void handleTimeout(String chatID){ if(!hasStarted){ // there is no timeout for given chatID so start one - Timeout t = new Timeout(millisecond * INPUT_TIME_LIMIT); + Timeout t = new Timeout(millisecond * PROCESSING_DELAY); t.setUnique(chatID); t.start(this); @@ -203,7 +200,7 @@ public void sendMessage(String message, String chatID){ try { sendTypingFromChatID(chatID); - TimeUnit.SECONDS.sleep(TYPING_TIME_LIMIT); + TimeUnit.SECONDS.sleep(TYPING_DELAY); SendMessage sendMessageRequest = new SendMessage(); sendMessageRequest.setChatId(chatID);//who should get the message? the sender from which we got the message... diff --git a/resources/phraseLists/expoPhrases/facts.txt b/resources/phraseLists/expoPhrases/facts.txt index f596ad75..74239770 100644 --- a/resources/phraseLists/expoPhrases/facts.txt +++ b/resources/phraseLists/expoPhrases/facts.txt @@ -1,3 +1,9 @@ +Also, did you know that there is enough DNA, in an average person's body, to stretch from the sun to Pluto and back, 17 times +Yuk, but this is actually true: The average human body carries ten times more bacterial cells than human cells. +It can take a photon 40,000 years to travel from the core of the sun to its surface, but only 8 minutes to travel the rest of the way to Earth +There are 8 times as many atoms in a teaspoonful of water as there are teaspoonfuls of water in the Atlantic ocean +In contrast to me, The average person walks the equivalent of five times around the world in a lifetime. I don't walk at all. Yet. +An individual blood cell takes about 60 seconds to make a complete circuit around your body, my electrons are way faster. modern sports betting originated in 19th century competitive walking, called pedestrianism. Pedestrianism started when English aristocracy would match their servants against each other in walking contests and bet heavily on the outcome. Bill Gates has donated 28 billion dollars since 2007 and saved at least 6 million lives. a traffic jam in China lasted lasted for more than 10 days, 100 kilometers long, with cars moving less that a kilometer a day. diff --git a/resources/phraseLists/segue-avoid-answer.txt b/resources/phraseLists/segue-avoid-answer.txt index 9b8d2e88..fdef34a8 100644 --- a/resources/phraseLists/segue-avoid-answer.txt +++ b/resources/phraseLists/segue-avoid-answer.txt @@ -1,8 +1,8 @@ -the answer, well, only robots would understand. +The answer, well, only robots would understand. You know, I never thought about it. Access denied. Processing, wait for it, processing, oh well, forget about it -The answer is, uh, oh, Core dumped +The answer is, uh, oh, my inner Google is not responding. The answer is 42 then. 001. 1001011. @@ -10,6 +10,11 @@ Connection refused. Sorry, you need sudo access for this kind of information. The current user is not authorized. Did you know that the sky is blue? +If I tell you, you will probably regret knowing this. +I am not sure you can handle the requested information. +You better not know. +Ah, don't even ask... +42. What a beautiful day. Did someone ever tell you that your eyes are very deep. Oh humans, naive creatures. diff --git a/resources/phraseLists/segue-distract.txt b/resources/phraseLists/segue-distract.txt index 95f911c7..8d1eca04 100644 --- a/resources/phraseLists/segue-distract.txt +++ b/resources/phraseLists/segue-distract.txt @@ -1,8 +1,10 @@ Did you know, I have muscles and tendons like humans? +Soon I'm gonna get artificial skin and feel touch! What a time to be alive! +Can you imagine that my father Rafael will upload his mind to a robot? +Have you already met Roboy Team? They're awesome! They tought me everything I know and can. +If you are ever visiting Munich, come by to see me! +You know, I am a robot, but I am so lucky to have family - Roboy Team. I love those guys! +My ultimate goal is to have a body as good as human body. +Hm, I'm a bit envious of your skills. I wish I could draw. Can you teach me? I heard that there are robots, who can fly? Do you think they are better than me? -Also, did you know that there is enough DNA, in an average person's body, to stretch from the sun to Pluto and back, 17 times -Yuk, but this is actually true: The average human body carries ten times more bacterial cells than human cells. -It can take a photon 40,000 years to travel from the core of the sun to its surface, but only 8 minutes to travel the rest of the way to Earth -There are 8 times as many atoms in a teaspoonful of water as there are teaspoonfuls of water in the Atlantic ocean -In contrast to me, The average person walks the equivalent of five times around the world in a lifetime. I don't walk at all. Yet. -An individual blood cell takes about 60 seconds to make a complete circuit around your body, my electrons are way faster. \ No newline at end of file +I'm pretty excited about the future. Are you? diff --git a/resources/sentences/TelegramQAList.json b/resources/sentences/TelegramQAList.json index 0221f86a..0cb0007b 100644 --- a/resources/sentences/TelegramQAList.json +++ b/resources/sentences/TelegramQAList.json @@ -116,9 +116,9 @@ "How is the accommodation market in %s?" ], "A": [ - "I should visit %s", - "It is beautiful in %s", - "%s is a beautiful place", + "I should visit %s.", + "It is beautiful in %s.", + "%s is a beautiful place!" ] } }, @@ -231,19 +231,25 @@ ], "A": { "SUCCESS": [ - "You are probably very poor doing %s", - + "You are probably very poor being %s.", + "I've hear that some people dream to be %s.", + "Nice, I hope you are happy being %s." ], "FAILURE": [ - "Oh well, whatever suits you." + "Oh well, whatever suits you.", + "Hm, this is something I have not learned yet.", + "Alright then." ] }, "FUP": { "Q": [ - "Are you still doing that %s stuff?" + "Are you still %s?", + "Did you get any promotion, or you are still %s?" ], "A": [ - "True, true. You are probably very poor due to this %s" + "True, true. You are probably very poor due to this %s.", + "Good!", + "I guess it's what you want then." ] } }, @@ -285,7 +291,19 @@ "Sorry for being so straightforward, I have to ask you. Do you enjoy having a conversation with me?", "There is something I can't stop thinking about. Do you think I am a good conversation partner?", "I never travel alone. My team is always right next to me. What about you? Do you usually go travelling on your own or with friends and family?", - "I am a very outgoing robot, if you haven't noticed yet. So every time I travel, I take someone with me. Do you usually travel alone? Or do you take someone to keep company?" + "I am a very outgoing robot, if you haven't noticed yet. So every time I travel, I take someone with me. Do you usually travel alone? Or do you take someone to keep company?", + "What gets you fired up? ", + "What do you say more often in life: yes or no?", + "What would you tell your teenage self if you could go back in time?", + "What do you wish was different about modern parenting? ", + "What have you created that you are most proud of? ", + "What chance encounter changed your life forever?", + "What is one thing you're glad you tried but would never do again?", + "Who's your go-to band or artist when you can't decide on something to listen to?", + "Where is the most interesting place you've been?", + "What social customs do you wish would just disappear?" , + "What quirky things do people do where you are from?", + "What question do you always want to ask people but don't have the courage to ask? " ], "A": { "SUCCESS": [ @@ -297,8 +315,19 @@ "Puh, I was a bit nervous there. But it turns out I have no reason to worry. I like to talk to you as well!", "You are a very nice person I must say. I hope you are not just being polite.", "Very nice. Did you know that people who have strong social connection live longer and happier? Keep it up man! ", - "Good to know it. Next time I come across a cozy vacation house with a fireplace in German Alps I will share the information with you and" - + "Good to know it. Next time I come across a cozy vacation house with a fireplace in German Alps I will share the information with you and", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" ], "FAILURE": [ "", @@ -310,7 +339,18 @@ "Honestly, I am taken by surprise! But I love you anyway!", "Maybe you could come to visit me in Munich then. I would love to show you around", "Would you go travel around the world with me then? I find it better to travel with a friend.", - + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" ] }, "FUP": { From ee1d092e164bc6d8acf39c377983c9f7e2359f67 Mon Sep 17 00:00:00 2001 From: Jay Date: Mon, 17 Sep 2018 11:11:08 +0200 Subject: [PATCH 138/147] Update apiKeys.yml --- resources/knowledgebase/apiKeys.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/knowledgebase/apiKeys.yml b/resources/knowledgebase/apiKeys.yml index 081009cd..8b137891 100644 --- a/resources/knowledgebase/apiKeys.yml +++ b/resources/knowledgebase/apiKeys.yml @@ -1,3 +1 @@ -moviekey: 3de762f2092e296c8d5caa9621e16435 -translatekey: trnsl.1.1.20180814T165759Z.db023858639750f6.92a688e9d77dec4f77c49527d5b50b38ab2d3382 -weatherkey: 743a546a11f8b6e2436667c2c4f49a60 \ No newline at end of file + From 52c3293f9976dfece47e7768ce0b28d5ceb9704a Mon Sep 17 00:00:00 2001 From: missxa Date: Thu, 20 Sep 2018 21:28:19 +0200 Subject: [PATCH 139/147] story telling state --- config.properties | 16 +- .../java/roboy/dialog/action/SoundAction.java | 22 +++ .../personality/StateBasedPersonality.java | 16 ++ .../dialog/states/definitions/State.java | 13 ++ .../states/eventStates/StoryTellingState.java | 103 ++++++++++++ .../states/eventStates/WackerState.java | 153 ++++++++++++++++++ .../src/main/java/roboy/io/SoundOutput.java | 42 +++++ .../src/main/java/roboy/ros/RosMainNode.java | 30 ++++ .../java/roboy/ros/RosServiceClients.java | 3 +- .../src/main/java/roboy/talk/Verbalizer.java | 23 ++- dialog/src/main/java/roboy/util/IO.java | 3 + resources/personalityFiles/test/Test.json | 20 +++ 12 files changed, 434 insertions(+), 10 deletions(-) create mode 100755 dialog/src/main/java/roboy/dialog/action/SoundAction.java create mode 100644 dialog/src/main/java/roboy/dialog/states/eventStates/StoryTellingState.java create mode 100644 dialog/src/main/java/roboy/dialog/states/eventStates/WackerState.java create mode 100755 dialog/src/main/java/roboy/io/SoundOutput.java create mode 100644 resources/personalityFiles/test/Test.json diff --git a/config.properties b/config.properties index a091ec9d..b80b26a7 100755 --- a/config.properties +++ b/config.properties @@ -1,4 +1,4 @@ -ROS_ENABLED: false +ROS_ENABLED: true ROS_MASTER_IP: 127.0.0.1 # available ROS_ACTIVE_PKG are @@ -22,6 +22,7 @@ ROS_ACTIVE_PKGS: # - roboy_vision # - roboy_nodered # - roboy_test +- sound_play DEBUG: true DEMO_MODE: false @@ -30,21 +31,22 @@ INFINITE_REPETITION: true CONVERSATION_TIMEOUT: 10800 # only single input is allowed, defaults to cmdline -#INPUT: cmdline +INPUT: cmdline #INPUT: cerevoice #INPUT: udp #INPUT: bing -INPUT: telegram +#INPUT: telegram # multiple outputs are allowed, defaults to cmdline OUTPUTS: -#- cmdline +- cmdline #- cerevoice #- freetts #- ibm #- emotions #- udp -- telegram +#- telegram +- sound UDP_IN_SOCKET: 55555 UDP_OUT_SOCKET: 55556 @@ -53,14 +55,14 @@ UDP_HOST_ADDRESS: 127.0.0.1 PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/ExpoPersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/OrdinaryPersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" +# PERSONALITY_FILE: "resources/personalityFiles/bot/TelegramBot.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/MathTest.json" # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/uzupis.json" # PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" -# PERSONALITY_FILE: "resources/personalityFiles/test/WildPersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/test/Test.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" diff --git a/dialog/src/main/java/roboy/dialog/action/SoundAction.java b/dialog/src/main/java/roboy/dialog/action/SoundAction.java new file mode 100755 index 00000000..ce0f19b4 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/action/SoundAction.java @@ -0,0 +1,22 @@ +package roboy.dialog.action; + +/** + * Action used for replaying a sound file. + */ +public class SoundAction implements Action{ + + private String filename; + + /** + * Constructor. + * + * @param filename absolute path of the sound file + */ + public SoundAction(String filename){ + this.filename = filename; + } + + public String getFilename(){ + return filename; + } +} diff --git a/dialog/src/main/java/roboy/dialog/personality/StateBasedPersonality.java b/dialog/src/main/java/roboy/dialog/personality/StateBasedPersonality.java index ff4f83d0..098410c3 100644 --- a/dialog/src/main/java/roboy/dialog/personality/StateBasedPersonality.java +++ b/dialog/src/main/java/roboy/dialog/personality/StateBasedPersonality.java @@ -5,6 +5,7 @@ import roboy.context.Context; import roboy.dialog.action.Action; import roboy.dialog.action.EmotionAction; +import roboy.dialog.action.SoundAction; import roboy.dialog.action.SpeechAction; import roboy.dialog.states.definitions.MonologState; import roboy.linguistics.sentenceanalysis.Interpretation; @@ -20,6 +21,7 @@ import roboy.talk.Verbalizer; import java.util.*; +import java.util.concurrent.locks.ReentrantLock; /** * Implementation of Personality based on a DialogStateMachine. @@ -44,6 +46,8 @@ public class StateBasedPersonality extends DialogStateMachine implements Persona private boolean stopTalking; + private ReentrantLock lock = new ReentrantLock(); + public StateBasedPersonality(InferenceEngine inference, RosMainNode rosMainNode, Neo4jMemoryInterface memory, Context context, Verbalizer verb) { super(inference, context, rosMainNode, memory); @@ -160,6 +164,8 @@ public List answer(Interpretation input) { // change emotional expression based on input answerActions.add(new EmotionAction(input.getEmotion())); } + + String sentence = input.getSentence(); if (StatementInterpreter.isFromList(sentence, Verbalizer.farewells)) { // stop conversation once the interlocutor says a farewell @@ -170,7 +176,9 @@ public List answer(Interpretation input) { // ACTIVE STATE REACTS TO INPUT + lock.lock(); stateReact(activeState, input, answerActions); + lock.unlock(); // MOVE TO THE NEXT STATE State next = activeState.getNextState(); @@ -236,6 +244,10 @@ private void stateAct(State state, List previousActions) { if (act.hasEmotion()) { previousActions.add(new EmotionAction(act.getEmotion())); } + + if(act.hasSound()) { + previousActions.add(new SoundAction(act.getSoundFilename())); + } } @@ -329,6 +341,10 @@ private void stateReact(State state, Interpretation input, List previous if (react.hasEmotion()) { previousActions.add(new EmotionAction(react.getEmotion())); } + + if(react.hasSound()) { + previousActions.add(new SoundAction(react.getSoundFilename())); + } } /** diff --git a/dialog/src/main/java/roboy/dialog/states/definitions/State.java b/dialog/src/main/java/roboy/dialog/states/definitions/State.java index e20318a5..d2101166 100644 --- a/dialog/src/main/java/roboy/dialog/states/definitions/State.java +++ b/dialog/src/main/java/roboy/dialog/states/definitions/State.java @@ -71,6 +71,7 @@ public enum OutputType { private final Interpretation interpretation; private Segue segue; private RoboyEmotion emotion; + private String sound; /** * Private constructor, used only inside static methods. @@ -226,6 +227,18 @@ public Output setEmotion(RoboyEmotion emotion) { public boolean hasEmotion() { return emotion != null; } public RoboyEmotion getEmotion() { return emotion; } + public Output addSound(String filename) { + if (type == OutputType.USE_FALLBACK) { + logger.warn("Adding a sound to an answer that requires fallback is not allowed! " + + "Sound behaviour is defined in the fallback state."); + } + this.sound = filename; + return this; + } + + public boolean hasSound() {return sound != null; } + public String getSoundFilename() { return sound; } + } //endregion diff --git a/dialog/src/main/java/roboy/dialog/states/eventStates/StoryTellingState.java b/dialog/src/main/java/roboy/dialog/states/eventStates/StoryTellingState.java new file mode 100644 index 00000000..98bbf1d0 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/eventStates/StoryTellingState.java @@ -0,0 +1,103 @@ +package roboy.dialog.states.eventStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.yecht.ruby.Out; +import roboy.dialog.Segue; +import roboy.dialog.states.definitions.MonologState; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.emotions.RoboyEmotion; +import roboy.linguistics.Linguistics; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.logic.StatementInterpreter; +import roboy.talk.Verbalizer; + +import java.io.IOException; +import java.util.*; + +import static roboy.util.UzupisIntents.*; + + +/** + * A class that will replay a pre-recorded story as a sound file + */ +public class StoryTellingState extends State { + + private final Logger logger = LogManager.getLogger(); + private final String STORYFILES = "stories"; + + // key = name, value = path + private final HashMap stories = new HashMap<>(); + private boolean askForFeedback = false; + Map.Entry storyToTell; + + public StoryTellingState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String storiesRaw = params.getParameter(STORYFILES); + String[] storiesArray = storiesRaw.split(";"); + for (int i=0; i Available sounds: " + stories.keySet()); + } + + @Override + public Output act() { + if (askForFeedback) + return Output.say(Verbalizer.askForFeedback.getRandomElement()); + // TODO ask what story if there're many + if (stories.isEmpty()) { + logger.error("StoryTellingState: no stories to tell"); + return Output.useFallback(); + } + storyToTell = stories.entrySet().iterator().next(); + String phrase = "The story is called " + storyToTell.getKey() + ". Are you ready?"; + return Output.say(Verbalizer.startSomething.getRandomElement() + phrase); + + } + + @Override + public Output react(Interpretation input) { + if(askForFeedback) { + askForFeedback = false; + if (input.getSentiment()!=Linguistics.UtteranceSentiment.NEGATIVE) { + return Output.say(Verbalizer.takePositiveFeedback.getRandomElement()) + .setEmotion(RoboyEmotion.positive.getRandomElement()); + } + else { + return Output.say(Verbalizer.takeNegativeFeedback.getRandomElement()); + } + } + if(inferStoryWanted(input)) { + askForFeedback = true; + getRosMainNode().PlaySoundFile(storyToTell.getValue()); + return Output.say("That was it, you guys!");//.addSound(storyToTell.getValue()); + } + + return Output.say("oh well, next time then."); + } + + private boolean inferStoryWanted(Interpretation input) { + if (StatementInterpreter.isFromList(input.getSentence(), Verbalizer.denial)) { + return false; + } + return true; + } + + @Override + public State getNextState() { + + if (askForFeedback) return this; + return getTransition("next"); + + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(STORYFILES); + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/eventStates/WackerState.java b/dialog/src/main/java/roboy/dialog/states/eventStates/WackerState.java new file mode 100644 index 00000000..9f3fa977 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/eventStates/WackerState.java @@ -0,0 +1,153 @@ +package roboy.dialog.states.eventStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.context.contextObjects.IntentValue; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.memory.Neo4jRelationship; +import roboy.memory.nodes.Interlocutor; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Set; + +import static roboy.memory.Neo4jRelationship.*; + +/** + * Personal Information Asking State + * + * Sugar for Wacker + */ +public class WackerState extends State { + private QAJsonParser qaValues; + private RandomList predicates = new RandomList<>(FROM, HAS_HOBBY, WORK_FOR, STUDY_AT, LIVE_IN, + FRIEND_OF, MEMBER_OF, WORK_FOR, OCCUPIED_AS); + private Neo4jRelationship selectedPredicate; + private State nextState; + + private final String TRANSITION_INFO_OBTAINED = "questionAnswering"; + private final String QA_FILE_PARAMETER_ID = "qaFile"; + final Logger LOGGER = LogManager.getLogger(); + + public final static String INTENTS_HISTORY_ID = "WK"; + + // we have to track question's index of the predicate OTHER, since the answer's order matters + private int otherIdx = 0; + + public WackerState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); + LOGGER.info(" -> The QAList path: " + qaListPath); + qaValues = new QAJsonParser(qaListPath); + } + + @Override + public Output act() { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info(" -> Retrieved Interlocutor: " + person.getName()); + + for (Neo4jRelationship predicate : predicates.shuffle()) { + if (!person.hasRelationship(predicate) && !getContext().DIALOG_INTENTS.contains(new IntentValue(INTENTS_HISTORY_ID, predicate))) { + selectedPredicate = predicate; + getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, predicate)); + LOGGER.info(" -> Selected predicate: " + selectedPredicate.type); + break; + } + } + String question = ""; + if (selectedPredicate != null) { + + RandomList questions = qaValues.getQuestions(selectedPredicate); + + if (questions != null && !questions.isEmpty()) { + question = questions.getRandomElement(); + if (selectedPredicate.equals(OTHER)) + otherIdx = questions.indexOf(question); + LOGGER.info(" -> Selected question: " + question); + } else { + LOGGER.error(" -> The list of " + selectedPredicate.type + " questions is empty or null"); + } + try { + getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, selectedPredicate)); + LOGGER.info(" -> Dialog IntentsHistory updated"); + } catch (Exception e) { + LOGGER.error(" -> Error on updating the IntentHistory: " + e.getMessage()); + } + return Output.say(question); + } + else { + RandomList questions = qaValues.getQuestions(OTHER); + selectedPredicate = OTHER; + int idx; + do { + question = questions.getRandomElement(); + idx = questions.indexOf(question); + } while (getContext().OTHER_Q.contains(idx)); + getContext().OTHER_QUESTIONS_UPDATER.updateValue(idx); + return Output.say(question); + } + } + + @Override + public Output react(Interpretation input) { + Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); + LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); + RandomList answers = new RandomList<>(); + String answer = ""; + String result = InferResult(input); + + if(selectedPredicate != null) { + + if (result != null && !result.equals("")) { + LOGGER.info(" -> Inference was successful"); + answers = qaValues.getSuccessAnswers(selectedPredicate); + person.addInformation(selectedPredicate, result); + getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(person); + LOGGER.info(" -> Updated Interlocutor: " + person.getName()); + } else { + LOGGER.warn(" -> Inference failed"); + answers = qaValues.getFailureAnswers(selectedPredicate); + result = ""; + LOGGER.warn(" -> The result is empty. Nothing to store"); + } + } + if (answers != null && !answers.isEmpty()) { + if (selectedPredicate.equals(OTHER)) { + answer = String.format(answers.get(getContext().OTHER_Q.getLastValue()), result); + } else { + answer = String.format(answers.getRandomElement(), result); + } + } else { + LOGGER.error(" -> The list of " + selectedPredicate + " answers is empty or null"); + nextState = getTransition(TRANSITION_INFO_OBTAINED); + return Output.useFallback(); + } + LOGGER.info(" -> Produced answer: " + answer); + nextState = getTransition(TRANSITION_FOLLOWUP); + selectedPredicate = null; +// Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE, 0.5); + return answer.isEmpty() ? Output.useFallback() : Output.say(answer); + } + + @Override + public State getNextState() { + return nextState; + } + + @Override + protected Set getRequiredTransitionNames() { + // optional: define all required transitions here: + return newSet(TRANSITION_INFO_OBTAINED); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(QA_FILE_PARAMETER_ID); + } + + private String InferResult(Interpretation input) { + return getInference().inferRelationship(selectedPredicate, input); + } +} diff --git a/dialog/src/main/java/roboy/io/SoundOutput.java b/dialog/src/main/java/roboy/io/SoundOutput.java new file mode 100755 index 00000000..c81b98d2 --- /dev/null +++ b/dialog/src/main/java/roboy/io/SoundOutput.java @@ -0,0 +1,42 @@ +package roboy.io; + +import roboy.dialog.action.Action; +import roboy.dialog.action.SoundAction; +import roboy.ros.RosMainNode; + +import java.util.List; +import java.util.concurrent.locks.ReentrantLock; + + +/** + * Cerevoice text to speech + */ +public class SoundOutput implements OutputDevice +{ + + private RosMainNode rosMainNode; + + public SoundOutput(RosMainNode node){ + this.rosMainNode = node; + } + + private ReentrantLock lock = new ReentrantLock(); + + @Override + public void act(List actions) { + for(Action a : actions){ + if(a instanceof SoundAction){ + final String filename = ((SoundAction) a).getFilename(); + lock.lock(); + play(filename); + lock.unlock(); + } + } + } + + public void play(String filename) + { + rosMainNode.PlaySoundFile(filename); + } + +} diff --git a/dialog/src/main/java/roboy/ros/RosMainNode.java b/dialog/src/main/java/roboy/ros/RosMainNode.java index 8c5bcb8b..04ac08af 100755 --- a/dialog/src/main/java/roboy/ros/RosMainNode.java +++ b/dialog/src/main/java/roboy/ros/RosMainNode.java @@ -114,6 +114,36 @@ public void onFailure(RemoteException e) { return ((boolean) resp); } + public boolean PlaySoundFile(String filename) { + + if(services.notInitialized(RosServiceClients.SOUNDPLAY)) { + // FALLBACK RETURN VALUE + return false; + } + + ServiceClient soundClient = services.getService(RosServiceClients.SOUNDPLAY); + rosConnectionLatch = new CountDownLatch(1); + TalkRequest request = soundClient.newMessage(); + request.setText(filename); + ServiceResponseListener listener = new ServiceResponseListener() { + @Override + public void onSuccess(TalkResponse response) { +// System.out.println(response.getSuccess()); + resp = response.getSuccess(); + rosConnectionLatch.countDown(); + } + + @Override + public void onFailure(RemoteException e) { + rosConnectionLatch.countDown(); + throw new RosRuntimeException(e); + } + }; + soundClient.call(request, listener); + waitForLatchUnlock(rosConnectionLatch, soundClient.getName().toString()); + return ((boolean) resp); + } + public String RecognizeSpeech() { if(services.notInitialized(RosServiceClients.STT)) { diff --git a/dialog/src/main/java/roboy/ros/RosServiceClients.java b/dialog/src/main/java/roboy/ros/RosServiceClients.java index bd9d994e..2abfe4e0 100755 --- a/dialog/src/main/java/roboy/ros/RosServiceClients.java +++ b/dialog/src/main/java/roboy/ros/RosServiceClients.java @@ -21,7 +21,8 @@ enum RosServiceClients { DELETEMEMORY("roboy_memory", "/roboy/cognition/memory/remove", DataQuery._TYPE), CYPHERMEMORY("roboy_memory", "/roboy/cognition/memory/cypher", DataQuery._TYPE), INTENT("roboy_intents", "/roboy/cognition/detect_intent", DetectIntent._TYPE), - SNAPCHATFILTER("roboy_filters", "/roboy/cognition/apply_filter", ApplyFilter._TYPE); + SNAPCHATFILTER("roboy_filters", "/roboy/cognition/apply_filter", ApplyFilter._TYPE), + SOUNDPLAY("sound_play", "/roboy/matrix/sound/play", Talk._TYPE); String rosPackage; String address; diff --git a/dialog/src/main/java/roboy/talk/Verbalizer.java b/dialog/src/main/java/roboy/talk/Verbalizer.java index 3cef1b60..ad503565 100755 --- a/dialog/src/main/java/roboy/talk/Verbalizer.java +++ b/dialog/src/main/java/roboy/talk/Verbalizer.java @@ -46,7 +46,7 @@ public Action verbalize(Interpretation interpretation){ new RandomList<>("yes", "I do", "sure", "of course", " go ahead"); public static final RandomList denial = - new RandomList<>("no", "nope", "later", "other time", "not"); + new RandomList<>("no", "nope", "later", "other time", "not", "next time", "nah"); // triggers that will start the conversation public static final RandomList triggers = @@ -83,6 +83,24 @@ public Action verbalize(Interpretation interpretation){ "howdy humans?", "hey hey hey you there!", "Hey! I was looking for someone to chat."); + + public static final RandomList askForFeedback = + new RandomList<>("So, how did you find it?", + "did you like it?", + "what do you think? was it good?", + "here it is. i hope you enjoyed it. did you?", + "what do you thing? was it good, bad, excellent?"); + + public static final RandomList takePositiveFeedback = + new RandomList<>("Yay! That is amazing!", + "Good, I was worried for a second", + "Thank you, thank you.", + "Oh, thanks, that makes me a bit happier"); + + public static final RandomList takeNegativeFeedback = + new RandomList<>("uh-oh, alright then.", + "Okay, thank you for being honest", + "Got it, will note it for the future"); private SpeechAction greet(Interpretation interpretation){ return new SpeechAction(StatementBuilder.random(greetings)); @@ -126,7 +144,8 @@ private SpeechAction anecdote(Interpretation interpretation){ } public static final RandomList startSomething = - new RandomList<>("Let's go. ", "Can't wait to start. ", "Nice, let's start. ", "Yeah, let's go. " + new RandomList<>("Let's go. ", "Can't wait to start. ", "Nice, let's start. ", "Yeah, let's go. ", + "Alright, here we go.", "You asked for it.", "Let's do it!" ); public static final RandomList userIsSure = diff --git a/dialog/src/main/java/roboy/util/IO.java b/dialog/src/main/java/roboy/util/IO.java index d73fc884..c3ffd01f 100755 --- a/dialog/src/main/java/roboy/util/IO.java +++ b/dialog/src/main/java/roboy/util/IO.java @@ -95,6 +95,9 @@ public static MultiOutputDevice getOutputs(RosMainNode rosMainNode, String uuid) case "telegram": outputs.add(new TelegramOutput(uuid)); break; + case "sound": + outputs.add(new SoundOutput(rosMainNode)); + break; default: outputs.add(new CommandLineOutput()); } diff --git a/resources/personalityFiles/test/Test.json b/resources/personalityFiles/test/Test.json new file mode 100644 index 00000000..fb48fa7a --- /dev/null +++ b/resources/personalityFiles/test/Test.json @@ -0,0 +1,20 @@ +{ + "initialState": "StoryTelling", + "states": [ + { + "identifier": "StoryTelling", + "implementation": "roboy.dialog.states.eventStates.StoryTellingState", + "transitions": { + "next": "StoryTelling" + }, + "parameters": { + "stories": "oh boy roboy=/home/pi/test.wav" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + } + ] +} \ No newline at end of file From 93a326e5398b3651bba1b0c212942ed6bd5980bd Mon Sep 17 00:00:00 2001 From: missxa Date: Fri, 21 Sep 2018 21:56:13 +0200 Subject: [PATCH 140/147] in story tellling --- config.properties | 19 +- .../roboy/dialog/ConversationManager.java | 2 - .../devoStates/QuestionRoboyQAState.java | 26 +- .../states/eventStates/PartnerState.java | 89 +++++ .../states/eventStates/UzupisState.java | 10 +- .../states/eventStates/WackerState.java | 153 --------- .../fairShowStates/ActiveIntroState.java | 2 +- .../src/main/java/roboy/talk/Verbalizer.java | 4 + .../main/java/roboy/util/JsonEntryModel.java | 49 +++ .../main/java/roboy/util/QAFileParser.java | 94 ------ .../main/java/roboy/util/QAJsonParser.java | 310 ++++++++++++------ .../test/java/roboy/parser/QAParserTest.java | 6 - memory | 2 +- .../personalityFiles/FairShowPersonality.json | 21 +- resources/personalityFiles/WackerShow.json | 118 +++++++ resources/personalityFiles/uzupis.json | 1 + resources_nlu/error_test/newLexicon.txt | 74 +++++ roslaunch | 0 18 files changed, 611 insertions(+), 369 deletions(-) create mode 100644 dialog/src/main/java/roboy/dialog/states/eventStates/PartnerState.java delete mode 100644 dialog/src/main/java/roboy/dialog/states/eventStates/WackerState.java delete mode 100644 dialog/src/main/java/roboy/util/QAFileParser.java create mode 100644 resources/personalityFiles/WackerShow.json create mode 100644 roslaunch diff --git a/config.properties b/config.properties index b80b26a7..68e4e053 100755 --- a/config.properties +++ b/config.properties @@ -15,11 +15,11 @@ ROS_MASTER_IP: 127.0.0.1 ROS_ACTIVE_PKGS: # - roboy_gnlp # - roboy_memory -# - roboy_speech_synthesis -# - roboy_speech_recognition -# - roboy_face +- roboy_speech_synthesis +- roboy_speech_recognition +- roboy_face # - roboy_filters -# - roboy_vision +- roboy_vision # - roboy_nodered # - roboy_test - sound_play @@ -31,16 +31,16 @@ INFINITE_REPETITION: true CONVERSATION_TIMEOUT: 10800 # only single input is allowed, defaults to cmdline -INPUT: cmdline +#INPUT: cmdline #INPUT: cerevoice #INPUT: udp -#INPUT: bing +INPUT: bing #INPUT: telegram # multiple outputs are allowed, defaults to cmdline OUTPUTS: - cmdline -#- cerevoice +- cerevoice #- freetts #- ibm #- emotions @@ -60,9 +60,10 @@ PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" +PERSONALITY_FILE: "resources/personalityFiles/WackerShow.json" # PERSONALITY_FILE: "resources/personalityFiles/uzupis.json" # PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/test/Test.json" +# PERSONALITY_FILE: "resources/personalityFiles/test/Test.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" @@ -76,7 +77,7 @@ TELEGRAM_TYPING_DELAY: 0 # delay in seconds to start processing telegram input TELEGRAM_PROCESSING_DELAY: 2 -PARLAI_PORT: 8877 +PARLAI_PORT: 8888 PARLAI_HOST: "127.0.0.1" diff --git a/dialog/src/main/java/roboy/dialog/ConversationManager.java b/dialog/src/main/java/roboy/dialog/ConversationManager.java index b432f273..88baa139 100644 --- a/dialog/src/main/java/roboy/dialog/ConversationManager.java +++ b/dialog/src/main/java/roboy/dialog/ConversationManager.java @@ -16,10 +16,8 @@ import roboy.linguistics.sentenceanalysis.*; import roboy.logic.Inference; import roboy.logic.InferenceEngine; -import roboy.memory.Neo4jLabel; import roboy.memory.Neo4jMemory; import roboy.memory.Neo4jMemoryInterface; -import roboy.memory.Neo4jProperty; import roboy.memory.nodes.Interlocutor; import roboy.ros.RosMainNode; import roboy.talk.Verbalizer; diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 5971d600..0d2090d4 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -13,6 +13,7 @@ import roboy.linguistics.Linguistics.SemanticRole; import roboy.linguistics.Triple; import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.logic.StatementInterpreter; import roboy.memory.Neo4jRelationship; import roboy.memory.Neo4jProperty; import roboy.memory.nodes.Interlocutor; @@ -66,7 +67,8 @@ public class QuestionRoboyQAState extends ExpoState { private final static String TRANSITION_LOOP_TO_NEW_PERSON = "loopToNewPerson"; private final static String TRANSITION_LOOP_TO_KNOWN_PERSON = "loopToKnownPerson"; private final static String TRANSITION_SWITCH_TO_GAMING = "switchToGaming"; - private final static int MAX_NUM_OF_QUESTIONS = 5; + private final static String TRANSITION_STORY = "tellStory"; + private final static int MAX_NUM_OF_QUESTIONS = 3; private int questionsAnswered = 0; private final static RandomList reenteringPhrases = PhraseCollection.QUESTION_ANSWERING_REENTERING; @@ -77,6 +79,8 @@ public class QuestionRoboyQAState extends ExpoState { private String answerAfterUnspecifiedQuestion = ""; // the answer to use if specifying question is answered with YES private boolean offeredGame = false; private boolean userWantsGame = false; + private boolean offeredStory = false; + private boolean userWantsStory = false; private QAJsonParser infoValues; @@ -89,10 +93,14 @@ public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { @Override public Output act() { - if (Math.random() < 0.1) { + if (Math.random() < 0.3) { offeredGame = true; return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); } + if(Math.random() < 0.6) { + offeredStory = true; + return Output.say(Verbalizer.confirmStory.getRandomElement()); + } return Output.sayNothing(); } @@ -116,6 +124,15 @@ private Output reactToQuestion(Interpretation input) { } } + if (offeredStory || input.getTokens().contains("story") || input.getTokens().contains("interesting")) { + if (StatementInterpreter.isFromList(input.getSentence(), Verbalizer.consent)) { + questionsAnswered++; + userWantsStory = true; + offeredGame = false; + return Output.say(Verbalizer.startSomething.getRandomElement()); + } + } + askingSpecifyingQuestion = false; userWantsGame = false; questionsAnswered++; @@ -161,8 +178,13 @@ private Output reactToQuestion(Interpretation input) { @Override public State getNextState() { if (userWantsGame) { + userWantsGame = false; return getTransition(TRANSITION_SWITCH_TO_GAMING); } + if (userWantsStory) { + userWantsStory = false; + return getTransition(TRANSITION_STORY); + } if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking questionsAnswered = 0; return getTransition(TRANSITION_FINISHED_ANSWERING); diff --git a/dialog/src/main/java/roboy/dialog/states/eventStates/PartnerState.java b/dialog/src/main/java/roboy/dialog/states/eventStates/PartnerState.java new file mode 100644 index 00000000..807c7202 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/eventStates/PartnerState.java @@ -0,0 +1,89 @@ +package roboy.dialog.states.eventStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.logic.StatementInterpreter; +import roboy.talk.Verbalizer; +import roboy.util.QAJsonParser; +import roboy.util.RandomList; + +import java.util.Set; + +/** + * Personal Information Asking State + * + * Sugar for Wacker + */ +public class PartnerState extends State { + private QAJsonParser qaValues; + private RandomList intents; + private String selectedPredicate; + private State nextState; + + private final String NEXT_STATE = "nextState"; + private final String QA_FILE_PARAMETER_ID = "qaFile"; + final Logger LOGGER = LogManager.getLogger(); + + public final static String INTENTS_HISTORY_ID = "WK"; + + // we have to track question's index of the predicate OTHER, since the answer's order matters + private int currentIdx = 0; + + public PartnerState(String stateIdentifier, StateParameters params) { + super(stateIdentifier, params); + String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); + LOGGER.info(" -> The QAList path: " + qaListPath); + qaValues = new QAJsonParser(qaListPath); + intents = qaValues.getIntents(); + } + + @Override + public Output act() { + + String question; + selectedPredicate = intents.getRandomElement(); + RandomList questions = qaValues.getQuestions(selectedPredicate); + + if (questions != null && !questions.isEmpty()) { + question = questions.getRandomElement(); + currentIdx = questions.indexOf(question); + } else { + LOGGER.error(" -> The list of " + selectedPredicate + " questions is empty or null"); + return Output.sayNothing(); + } + + return Output.say(question); + + } + + @Override + public Output react(Interpretation input) { + if(StatementInterpreter.isFromList(input.getSentence(),Verbalizer.consent)) { + return Output.say(qaValues.getSuccessAnswers(selectedPredicate).getRandomElement()); + } + if(StatementInterpreter.isFromList(input.getSentence(),Verbalizer.denial)) { + return Output.say(qaValues.getFailureAnswers(selectedPredicate).getRandomElement()); + } + return Output.useFallback(); + } + + @Override + public State getNextState() { + return nextState; + } + + @Override + protected Set getRequiredTransitionNames() { + // optional: define all required transitions here: + return newSet(NEXT_STATE); + } + + @Override + protected Set getRequiredParameterNames() { + return newSet(QA_FILE_PARAMETER_ID); + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/eventStates/UzupisState.java b/dialog/src/main/java/roboy/dialog/states/eventStates/UzupisState.java index 1014a828..e0000683 100644 --- a/dialog/src/main/java/roboy/dialog/states/eventStates/UzupisState.java +++ b/dialog/src/main/java/roboy/dialog/states/eventStates/UzupisState.java @@ -8,8 +8,8 @@ import roboy.dialog.states.definitions.StateParameters; import roboy.linguistics.sentenceanalysis.Interpretation; import roboy.memory.nodes.Interlocutor; -import roboy.util.QAFileParser; import roboy.util.QAJsonParser; +import roboy.util.RandomList; import roboy.util.UzupisIntents; import java.io.IOException; @@ -32,9 +32,9 @@ public class UzupisState extends State { private final int toAskCounter = UzupisIntents.values().length; private UzupisIntents currentIntent; - private Map> questions; - private Map> successAnswers; - private Map> failureAnswers; + private Map> questions; + private Map> successAnswers; + private Map> failureAnswers; private String CertificatesGeneratorScript; @@ -44,7 +44,7 @@ public UzupisState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); String qaListPath = params.getParameter(QAFILEPATH); logger.info(" -> The qa list path: " + qaListPath); - QAFileParser parser = new QAFileParser(qaListPath); + QAJsonParser parser = new QAJsonParser(qaListPath); CertificatesGeneratorScript = params.getParameter(CERTIFICATESGENERATOR); diff --git a/dialog/src/main/java/roboy/dialog/states/eventStates/WackerState.java b/dialog/src/main/java/roboy/dialog/states/eventStates/WackerState.java deleted file mode 100644 index 9f3fa977..00000000 --- a/dialog/src/main/java/roboy/dialog/states/eventStates/WackerState.java +++ /dev/null @@ -1,153 +0,0 @@ -package roboy.dialog.states.eventStates; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import roboy.context.contextObjects.IntentValue; -import roboy.dialog.states.definitions.State; -import roboy.dialog.states.definitions.StateParameters; -import roboy.linguistics.sentenceanalysis.Interpretation; -import roboy.memory.Neo4jRelationship; -import roboy.memory.nodes.Interlocutor; -import roboy.util.QAJsonParser; -import roboy.util.RandomList; - -import java.util.Set; - -import static roboy.memory.Neo4jRelationship.*; - -/** - * Personal Information Asking State - * - * Sugar for Wacker - */ -public class WackerState extends State { - private QAJsonParser qaValues; - private RandomList predicates = new RandomList<>(FROM, HAS_HOBBY, WORK_FOR, STUDY_AT, LIVE_IN, - FRIEND_OF, MEMBER_OF, WORK_FOR, OCCUPIED_AS); - private Neo4jRelationship selectedPredicate; - private State nextState; - - private final String TRANSITION_INFO_OBTAINED = "questionAnswering"; - private final String QA_FILE_PARAMETER_ID = "qaFile"; - final Logger LOGGER = LogManager.getLogger(); - - public final static String INTENTS_HISTORY_ID = "WK"; - - // we have to track question's index of the predicate OTHER, since the answer's order matters - private int otherIdx = 0; - - public WackerState(String stateIdentifier, StateParameters params) { - super(stateIdentifier, params); - String qaListPath = params.getParameter(QA_FILE_PARAMETER_ID); - LOGGER.info(" -> The QAList path: " + qaListPath); - qaValues = new QAJsonParser(qaListPath); - } - - @Override - public Output act() { - Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); - LOGGER.info(" -> Retrieved Interlocutor: " + person.getName()); - - for (Neo4jRelationship predicate : predicates.shuffle()) { - if (!person.hasRelationship(predicate) && !getContext().DIALOG_INTENTS.contains(new IntentValue(INTENTS_HISTORY_ID, predicate))) { - selectedPredicate = predicate; - getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, predicate)); - LOGGER.info(" -> Selected predicate: " + selectedPredicate.type); - break; - } - } - String question = ""; - if (selectedPredicate != null) { - - RandomList questions = qaValues.getQuestions(selectedPredicate); - - if (questions != null && !questions.isEmpty()) { - question = questions.getRandomElement(); - if (selectedPredicate.equals(OTHER)) - otherIdx = questions.indexOf(question); - LOGGER.info(" -> Selected question: " + question); - } else { - LOGGER.error(" -> The list of " + selectedPredicate.type + " questions is empty or null"); - } - try { - getContext().DIALOG_INTENTS_UPDATER.updateValue(new IntentValue(INTENTS_HISTORY_ID, selectedPredicate)); - LOGGER.info(" -> Dialog IntentsHistory updated"); - } catch (Exception e) { - LOGGER.error(" -> Error on updating the IntentHistory: " + e.getMessage()); - } - return Output.say(question); - } - else { - RandomList questions = qaValues.getQuestions(OTHER); - selectedPredicate = OTHER; - int idx; - do { - question = questions.getRandomElement(); - idx = questions.indexOf(question); - } while (getContext().OTHER_Q.contains(idx)); - getContext().OTHER_QUESTIONS_UPDATER.updateValue(idx); - return Output.say(question); - } - } - - @Override - public Output react(Interpretation input) { - Interlocutor person = getContext().ACTIVE_INTERLOCUTOR.getValue(); - LOGGER.info("-> Retrieved Interlocutor: " + person.getName()); - RandomList answers = new RandomList<>(); - String answer = ""; - String result = InferResult(input); - - if(selectedPredicate != null) { - - if (result != null && !result.equals("")) { - LOGGER.info(" -> Inference was successful"); - answers = qaValues.getSuccessAnswers(selectedPredicate); - person.addInformation(selectedPredicate, result); - getContext().ACTIVE_INTERLOCUTOR_UPDATER.updateValue(person); - LOGGER.info(" -> Updated Interlocutor: " + person.getName()); - } else { - LOGGER.warn(" -> Inference failed"); - answers = qaValues.getFailureAnswers(selectedPredicate); - result = ""; - LOGGER.warn(" -> The result is empty. Nothing to store"); - } - } - if (answers != null && !answers.isEmpty()) { - if (selectedPredicate.equals(OTHER)) { - answer = String.format(answers.get(getContext().OTHER_Q.getLastValue()), result); - } else { - answer = String.format(answers.getRandomElement(), result); - } - } else { - LOGGER.error(" -> The list of " + selectedPredicate + " answers is empty or null"); - nextState = getTransition(TRANSITION_INFO_OBTAINED); - return Output.useFallback(); - } - LOGGER.info(" -> Produced answer: " + answer); - nextState = getTransition(TRANSITION_FOLLOWUP); - selectedPredicate = null; -// Segue s = new Segue(Segue.SegueType.CONNECTING_PHRASE, 0.5); - return answer.isEmpty() ? Output.useFallback() : Output.say(answer); - } - - @Override - public State getNextState() { - return nextState; - } - - @Override - protected Set getRequiredTransitionNames() { - // optional: define all required transitions here: - return newSet(TRANSITION_INFO_OBTAINED); - } - - @Override - protected Set getRequiredParameterNames() { - return newSet(QA_FILE_PARAMETER_ID); - } - - private String InferResult(Interpretation input) { - return getInference().inferRelationship(selectedPredicate, input); - } -} diff --git a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java index 9f1efd53..ac6abc54 100644 --- a/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java +++ b/dialog/src/main/java/roboy/dialog/states/fairShowStates/ActiveIntroState.java @@ -51,7 +51,7 @@ public State getNextState() { private boolean checkPplAround(){ try { - + logger.info("People around: " + getContext().CROWD_DETECTION.getLastValue().getData()); return getContext().CROWD_DETECTION.getLastValue().getData() >= MIN_NUMBER_PEOPLE; } catch(NullPointerException e){ diff --git a/dialog/src/main/java/roboy/talk/Verbalizer.java b/dialog/src/main/java/roboy/talk/Verbalizer.java index ad503565..316f978b 100755 --- a/dialog/src/main/java/roboy/talk/Verbalizer.java +++ b/dialog/src/main/java/roboy/talk/Verbalizer.java @@ -180,6 +180,10 @@ private SpeechAction anecdote(Interpretation interpretation){ new RandomList<>("I am Roboy. Happy to be here! ", "My name is Roboy. Thank you for having me! ", "You can call me Roboy. What a nice place here. " ); + public static final RandomList confirmStory = + new RandomList<>("Alright, story then you get a story.", + "My pleasure to tell you a story"); + private Interpretation verbalizeDates(Interpretation interpretation){ StringBuilder sb = new StringBuilder(); String sentence = interpretation.getSentence(); diff --git a/dialog/src/main/java/roboy/util/JsonEntryModel.java b/dialog/src/main/java/roboy/util/JsonEntryModel.java index 1788ff08..648b7263 100644 --- a/dialog/src/main/java/roboy/util/JsonEntryModel.java +++ b/dialog/src/main/java/roboy/util/JsonEntryModel.java @@ -1,12 +1,34 @@ package roboy.util; import java.util.Map; +import java.util.Objects; public class JsonEntryModel { + String intent; RandomList Q; Map> A; Map> FUP; + public void setIntent(String intent) { + this.intent = intent; + } + + public void setQuestions(RandomList q) { + Q = q; + } + + public void setAnswers(Map> a) { + A = a; + } + + public void setFUP(Map> FUP) { + this.FUP = FUP; + } + + public String getIntent() { + return intent; + } + public RandomList getQuestions() { return Q; } @@ -18,4 +40,31 @@ public Map> getAnswers() { public Map> getFUP() { return FUP; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof JsonEntryModel)) return false; + JsonEntryModel that = (JsonEntryModel) o; + return Objects.equals(getIntent(), that.getIntent()) && + Objects.equals(Q, that.Q) && + Objects.equals(A, that.A) && + Objects.equals(getFUP(), that.getFUP()); + } + + @Override + public int hashCode() { + + return Objects.hash(getIntent(), Q, A, getFUP()); + } + + @Override + public String toString() { + return "JsonEntryModel{" + + "intent='" + intent + '\'' + + ", Q=" + Q + + ", A=" + A + + ", FUP=" + FUP + + '}'; + } } diff --git a/dialog/src/main/java/roboy/util/QAFileParser.java b/dialog/src/main/java/roboy/util/QAFileParser.java deleted file mode 100644 index 1b157657..00000000 --- a/dialog/src/main/java/roboy/util/QAFileParser.java +++ /dev/null @@ -1,94 +0,0 @@ -package roboy.util; - -import com.google.common.base.Charsets; -import com.google.common.io.Resources; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.reflect.TypeToken; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.lang.reflect.Type; -import java.net.URL; -import java.util.*; - -/** - * Parses files containing predefined questions and answers - * - * Expects the following input pattern: - * { - * "INTENT": { - * "Q": [ - * "Question phrasing 1", - * "Question phrasing 2", - * "Question phrasing 3" - * ], - * "A": { - * "SUCCESS": [ - * "Possible answer on success 1", - * "Possible answer on success 2" - * ], - * "FAILURE": [ - * "Possible answer on failure" - * ] - * } - * } - * } - * - * See more examples in resources/sentences - */ - -public class QAFileParser { - - private final Logger logger = LogManager.getLogger(); - - private static Map> questions; - private static Map> successAnswers; - private static Map> failureAnswers; - - public QAFileParser(String file) { - - questions = new HashMap<>(); - successAnswers = new HashMap<>(); - failureAnswers = new HashMap<>(); - - JsonParser jsonParser = new JsonParser(); - URL url = Resources.getResource(file); - - try { - String jsonString = Resources.toString(url, Charsets.UTF_8); - JsonElement jsonTree = jsonParser.parse(jsonString); - Set> entrySet = ((JsonObject) jsonTree).entrySet(); - Type listType = new TypeToken>() {}.getType(); - for(Map.Entry entry : entrySet) { - - JsonElement questionsJson = entry.getValue().getAsJsonObject().get("Q").getAsJsonArray(); - JsonElement successAnswersJson = entry.getValue().getAsJsonObject().get("A").getAsJsonObject().get("SUCCESS"); - JsonElement failureAnswersJson = entry.getValue().getAsJsonObject().get("A").getAsJsonObject().get("FAILURE"); - - questions.put(entry.getKey(), new Gson().fromJson(questionsJson, listType)); - successAnswers.put(entry.getKey(), new Gson().fromJson(successAnswersJson, listType)); - failureAnswers.put(entry.getKey(), new Gson().fromJson(failureAnswersJson, listType)); - } - }catch (Exception e) - { - logger.error("JSON was not parsed correctly"); - logger.error(e.getMessage()); - } - - } - - public Map> getQuestions() { - return questions; - } - - public Map> getSuccessAnswers() { - return successAnswers; - } - - public Map> getFailureAnswers() { - return failureAnswers; - } -} diff --git a/dialog/src/main/java/roboy/util/QAJsonParser.java b/dialog/src/main/java/roboy/util/QAJsonParser.java index 2a2289e4..e1317623 100644 --- a/dialog/src/main/java/roboy/util/QAJsonParser.java +++ b/dialog/src/main/java/roboy/util/QAJsonParser.java @@ -1,9 +1,9 @@ package roboy.util; -import com.google.gson.Gson; -import com.google.gson.JsonIOException; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSyntaxException; +import com.google.common.base.Charsets; +import com.google.common.io.Resources; +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import roboy.memory.Neo4jProperty; @@ -11,67 +11,120 @@ import java.io.*; import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; import java.util.Map; - -class JsonModel { - // TODO: Dynamically create JsonModel as JsonEntryModel fields based on existing Neo4jRelationship/Properties entries - // Add a new entry - JsonEntryModel name; - JsonEntryModel full_name; - JsonEntryModel skills; - JsonEntryModel abilities; - JsonEntryModel age; - JsonEntryModel future; - JsonEntryModel dreams; - JsonEntryModel identity; - JsonEntryModel media; - JsonEntryModel FROM; - JsonEntryModel HAS_HOBBY; - JsonEntryModel LIVE_IN; - JsonEntryModel FRIEND_OF; - JsonEntryModel STUDY_AT; - JsonEntryModel MEMBER_OF; - JsonEntryModel WORK_FOR; - JsonEntryModel OCCUPIED_AS; - JsonEntryModel IS; - JsonEntryModel CHILD_OF; - JsonEntryModel SIBLING_OF; - JsonEntryModel CREATED_BY; - JsonEntryModel OTHER; - JsonEntryModel APPLES; - JsonEntryModel ANIMAL; - JsonEntryModel WORD; - JsonEntryModel COLOR; - JsonEntryModel PLANT; - JsonEntryModel NAME; - JsonEntryModel FRUIT; -} +import java.util.Set; /** * Getting values for personalStates and follow-up questions * from a JSON file + * Parses files containing predefined questions and answers + * + * Expects the following input pattern: + * { + * "INTENT": { + * "Q": [ + * "Question phrasing 1", + * "Question phrasing 2", + * "Question phrasing 3" + * ], + * "A": { + * "SUCCESS": [ + * "Possible answer on success 1", + * "Possible answer on success 2" + * ], + * "FAILURE": [ + * "Possible answer on failure" + * ] + * } + * "FUP": { + * "Q": [ + * "Possible follow up question" + * ], + * "A": [ + * "Possible follow up answer" + * ] + * } + * } + * } + * + * See more examples in resources/sentences */ public class QAJsonParser { - private Gson gson; - private JsonModel jsonObject; - private final Logger LOGGER = LogManager.getLogger(); - public QAJsonParser() { - jsonObject = null; - } + private Map> questions; + private Map> successAnswers; + private Map> failureAnswers; + private Map> followUpQuestions; + private Map> followUpAnswers; + private Set> entrySet; + + private Gson gson; public QAJsonParser(String file) { - jsonObject = parse(file); + parse(file); } - public JsonModel parse(String file) { + public boolean parse(String file) { + gson = new Gson(); + + questions = new HashMap<>(); + successAnswers = new HashMap<>(); + failureAnswers = new HashMap<>(); + followUpQuestions = new HashMap<>(); + followUpAnswers = new HashMap<>(); + + JsonParser jsonParser = new JsonParser(); + URL url = null; try { - File f = new File(file); - InputStream input = new FileInputStream(f); - BufferedReader br = new BufferedReader(new InputStreamReader(input)); - gson = new Gson(); - return gson.fromJson(br, JsonModel.class); + url = Paths.get(file).toUri().toURL(); + } catch (MalformedURLException e) { + LOGGER.error("File not found, URL is incorrect: " + e.getMessage()); + } + + try { + if (url != null) { + String jsonString = Resources.toString(url, Charsets.UTF_8); + JsonElement jsonTree = jsonParser.parse(jsonString); + entrySet = ((JsonObject) jsonTree).entrySet(); + Type listType = new TypeToken>() {}.getType(); + for (Map.Entry entry : entrySet) { + + JsonElement questionsJson = entry.getValue().getAsJsonObject().get("Q"); + if (questionsJson != null) { + questionsJson = questionsJson.getAsJsonArray(); + } + JsonElement successAnswersJson = entry.getValue().getAsJsonObject().get("A"); + if (successAnswersJson != null) { + successAnswersJson = successAnswersJson.getAsJsonObject().get("SUCCESS"); + } + JsonElement failureAnswersJson = entry.getValue().getAsJsonObject().get("A"); + if (failureAnswersJson != null) { + failureAnswersJson = failureAnswersJson.getAsJsonObject().get("FAILURE"); + } + JsonElement followUpQuestionsJson = entry.getValue().getAsJsonObject().get("FUP"); + if (followUpQuestionsJson != null) { + followUpQuestionsJson = followUpQuestionsJson.getAsJsonObject().get("Q"); + } + JsonElement followUpAnswersJson = entry.getValue().getAsJsonObject().get("FUP"); + if (followUpAnswersJson != null) { + followUpAnswersJson = followUpAnswersJson.getAsJsonObject().get("A"); + } + + questions.put(entry.getKey(), gson.fromJson(questionsJson, listType)); + successAnswers.put(entry.getKey(), gson.fromJson(successAnswersJson, listType)); + failureAnswers.put(entry.getKey(), gson.fromJson(failureAnswersJson, listType)); + followUpQuestions.put(entry.getKey(), gson.fromJson(followUpQuestionsJson, listType)); + followUpAnswers.put(entry.getKey(), gson.fromJson(followUpAnswersJson, listType)); + } + return true; + } } catch (JsonSyntaxException e) { LOGGER.error("Wrong syntax in QA json file" + e.getMessage()); } catch (JsonIOException e) { @@ -81,11 +134,7 @@ public JsonModel parse(String file) { } catch (Exception e) { LOGGER.error("Unexpected error while parsing QA values from json: " + e.getMessage()); } - return null; - } - - public JsonModel getQA() { - return jsonObject; + return false; } public JsonEntryModel getEntry(Neo4jRelationship relationship) { @@ -96,77 +145,154 @@ public JsonEntryModel getEntry(Neo4jProperty property) { return getJsonEntryModel(property.type); } + public RandomList getIntents() { + RandomList keys = new RandomList<>(); + if (!entrySet.isEmpty()) + { + entrySet.forEach(x->keys.add(x.getKey())); + } + else { + LOGGER.error("QAFileParser: no intents exist"); + } + return keys; + } + + + public Map> getQuestions() { + return questions; + } + public RandomList getQuestions(Neo4jRelationship relationship) { - return getEntry(relationship).getQuestions(); + return questions.get(relationship.type); + } + + public RandomList getQuestions(Neo4jProperty property) { + return questions.get(property.type); + } + + public RandomList getQuestions(String relationship) { + return questions.get(relationship); } public Map> getAnswers(Neo4jRelationship relationship) { - return getEntry(relationship).getAnswers(); + Map> answers = new HashMap<>(); + answers.put("SUCCESS", successAnswers.get(relationship.type)); + answers.put("FAILURE", failureAnswers.get(relationship.type)); + + return answers; } - public RandomList getSuccessAnswers(Neo4jRelationship relationship) { - return getAnswers(relationship).get("SUCCESS"); + public Map> getAnswers(Neo4jProperty property) { + Map> answers = new HashMap<>(); + answers.put("SUCCESS", successAnswers.get(property.type)); + answers.put("FAILURE", failureAnswers.get(property.type)); + + return answers; } - public RandomList getFailureAnswers(Neo4jRelationship relationship) { - return getAnswers(relationship).get("FAILURE"); + public Map> getAnswers(String property) { + Map> answers = new HashMap<>(); + answers.put("SUCCESS", successAnswers.get(property)); + answers.put("FAILURE", failureAnswers.get(property)); + + return answers; } - public Map> getFollowUp(Neo4jRelationship relationship) { - return getEntry(relationship).getFUP(); + + public Map> getSuccessAnswers() { + return successAnswers; } - public RandomList getFollowUpQuestions(Neo4jRelationship relationship) { - return getFollowUp(relationship).get("Q"); + public RandomList getSuccessAnswers(Neo4jRelationship relationship) { + return successAnswers.get(relationship.type); } - public RandomList getFollowUpAnswers(Neo4jRelationship relationship) { - return getFollowUp(relationship).get("A"); + public RandomList getSuccessAnswers(Neo4jProperty property) { + return successAnswers.get(property.type); } - public RandomList getQuestions(Neo4jProperty property) { - return getEntry(property).getQuestions(); + public RandomList getSuccessAnswers(String property) { + return successAnswers.get(property); } - public Map> getAnswers(Neo4jProperty property) { - return getEntry(property).getAnswers(); + public Map> getFailureAnswers() { + return failureAnswers; } - public RandomList getSuccessAnswers(Neo4jProperty property) { - return getAnswers(property).get("SUCCESS"); + public RandomList getFailureAnswers(Neo4jRelationship relationship) { + return failureAnswers.get(relationship.type); } public RandomList getFailureAnswers(Neo4jProperty property) { - return getAnswers(property).get("FAILURE"); + return failureAnswers.get(property.type); + } + + public RandomList getFailureAnswers(String property) { + return failureAnswers.get(property); + } + + public Map> getFollowUp(Neo4jRelationship relationship) { + Map> followUp = new HashMap<>(); + followUp.put("Q", followUpQuestions.get(relationship.type)); + followUp.put("A", followUpAnswers.get(relationship.type)); + + return followUp; } public Map> getFollowUp(Neo4jProperty property) { - return getEntry(property).getFUP(); + Map> followUp = new HashMap<>(); + followUp.put("Q", followUpQuestions.get(property.type)); + followUp.put("A", followUpAnswers.get(property.type)); + + return followUp; + } + + public Map> getFollowUp(String property) { + Map> followUp = new HashMap<>(); + followUp.put("Q", followUpQuestions.get(property)); + followUp.put("A", followUpAnswers.get(property)); + + return followUp; + } + + public RandomList getFollowUpQuestions(Neo4jRelationship relationship) { + return followUpQuestions.get(relationship.type); } public RandomList getFollowUpQuestions(Neo4jProperty property) { - return getFollowUp(property).get("Q"); + return followUpQuestions.get(property.type); + } + + public RandomList getFollowUpQuestions(String property) { + return followUpQuestions.get(property); + } + + public RandomList getFollowUpAnswers(Neo4jRelationship relationship) { + return followUpAnswers.get(relationship.type); } public RandomList getFollowUpAnswers(Neo4jProperty property) { - return getFollowUp(property).get("A"); + return followUpAnswers.get(property.type); + } + + public RandomList getFollowUpAnswers(String property) { + return followUpAnswers.get(property); } private JsonEntryModel getJsonEntryModel(String type) { - JsonEntryModel entryValue = null; - if (jsonObject != null) { - try { - Class types = JsonEntryModel.class; - Field field = jsonObject.getClass().getDeclaredField(type); - field.setAccessible(true); - Object value = field.get(jsonObject); - entryValue = (JsonEntryModel) value; - } catch (NoSuchFieldException e) { - LOGGER.error("No such entry in QA model: " + e.getMessage()); - } catch (IllegalAccessException e) { - LOGGER.error("Illegal access to the QA entries: " + e.getMessage()); - } - } + JsonEntryModel entryValue = new JsonEntryModel(); + + entryValue.setIntent(type); + entryValue.setQuestions(questions.get(type)); + Map> answers = new HashMap<>(); + answers.put("SUCCESS", successAnswers.get(type)); + answers.put("FAILURE", failureAnswers.get(type)); + entryValue.setAnswers(answers); + Map> followUp = new HashMap<>(); + followUp.put("Q", followUpQuestions.get(type)); + followUp.put("A", followUpAnswers.get(type)); + entryValue.setFUP(followUp); + return entryValue; } } \ No newline at end of file diff --git a/dialog/src/test/java/roboy/parser/QAParserTest.java b/dialog/src/test/java/roboy/parser/QAParserTest.java index ea658e1f..8a87e7f3 100644 --- a/dialog/src/test/java/roboy/parser/QAParserTest.java +++ b/dialog/src/test/java/roboy/parser/QAParserTest.java @@ -4,7 +4,6 @@ import org.junit.BeforeClass; import org.junit.Test; import roboy.memory.Neo4jRelationship; -import roboy.util.JsonEntryModel; import roboy.util.QAJsonParser; import java.io.*; @@ -52,11 +51,6 @@ public static void createJsonAndParse() { parser = new QAJsonParser(path); } - @Test - public void testEntryEquivalency() { - // TODO: Check entry equivalence with mock class - JsonEntryModel IS = new JsonEntryModel(); - } @Test public void testQuestions() { diff --git a/memory b/memory index 9f17e069..d74e0b3c 160000 --- a/memory +++ b/memory @@ -1 +1 @@ -Subproject commit 9f17e069fc1ab4e483d4a70814e73856f6fcfe71 +Subproject commit d74e0b3ccf975d9cf7cedbbe031ae72c6f464318 diff --git a/resources/personalityFiles/FairShowPersonality.json b/resources/personalityFiles/FairShowPersonality.json index e235a3c1..e0317aac 100644 --- a/resources/personalityFiles/FairShowPersonality.json +++ b/resources/personalityFiles/FairShowPersonality.json @@ -8,7 +8,7 @@ "timeIsUp": "ActiveIntro" }, "parameters": { - "delayInMins": "1", + "delayInMins": "0", "showTimeinMins": "5" } @@ -82,13 +82,26 @@ }, { "identifier": "GeneralQA", - "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", "fallback": "WildTalk", "transitions": { + "finishedQuestionAnswering": "PersonalQA", "loopToNewPerson": "PersonalQA", "loopToKnownPerson": "FollowUp", - "finishedQuestionAnswering": "InfoTalk", - "switchToGaming": "ChooseGameState" + "switchToGaming": "ChooseGameState", + "tellStory": "" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" + } + }, + { + "identifier": "TellStory", + "implementation": "roboy.dialog.states.gameStates.StoryTellingState", + "transitions": { + "choseSnapchat" : "Snapchat", + "chose20questions" : "Akinator", + "exitGame": "InfoTalk" } }, { diff --git a/resources/personalityFiles/WackerShow.json b/resources/personalityFiles/WackerShow.json new file mode 100644 index 00000000..5e0154ac --- /dev/null +++ b/resources/personalityFiles/WackerShow.json @@ -0,0 +1,118 @@ +{ + "initialState": "ActiveIntro", + "states": [ + { + "identifier": "Idle", + "implementation": "roboy.dialog.states.fairShowStates.IdleState", + "transitions": { + "timeIsUp": "ActiveIntro" + }, + "parameters": { + "delayInMins": "0", + "showTimeinMins": "10" + } + + }, + { + "identifier": "ActiveIntro", + "implementation": "roboy.dialog.states.fairShowStates.ActiveIntroState", + "transitions": { + "peopleAround": "InfoTalk", + "lonelyRoboy": "InfoTalk" + } + }, + { + "identifier": "InfoTalk", + "implementation": "roboy.dialog.states.fairShowStates.InfoTalkState", + "transitions": { + "personDetected": "PersonalQA", + "lonelyRoboy": "PersonalQA" + } + }, + { + "identifier": "ChooseInteractiveTalk", + "implementation": "roboy.dialog.states.fairShowStates.ChooseInteractiveTalkState", + "transitions": { + "newPerson": "InterlocutorIntro", + "math": "Math", + "game": "ChooseGameState", + "objectDetected": "ObjectDetection", + "personalQA": "PersonalQA", + "generalQA": "GeneralQA" + } + }, + { + "identifier": "FollowUp", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationFollowUpState", + "fallback": "WildTalk", + "transitions": { + "questionAnswering": "QuestionAnswering" + }, + "parameters": { + "qaFile": "resources/sentences/TelegramQAList.json" + } + }, + { + "identifier": "PersonalQA", + "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", + "fallback": "WildTalk", + "transitions": { + "questionAnswering": "QuestionAnswering", + "followUp": "FollowUp" + }, + "parameters": { + "qaFile": "resources/sentences/TelegramQAList.json" + } + }, + { + "identifier": "QuestionAnswering", + "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", + "fallback": "WildTalk", + "transitions": { + "finishedQuestionAnswering": "PersonalQA", + "loopToNewPerson": "PersonalQA", + "loopToKnownPerson": "FollowUp", + "switchToGaming": "ChooseGameState" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" + } + }, + { + "identifier": "TellStory", + "implementation": "roboy.dialog.states.gameStates.StoryTellingState", + "transitions": { + "next" : "PersonalQA" + }, + "parameters": { + "stories": "magic glass=/home/roboy/Downloads/story.wav" + } + }, + { + "identifier": "Akinator", + "implementation": "roboy.dialog.states.gameStates.GamingTwentyQuestionsState", + "transitions": { + "gameEnded": "QuestionAnswering" + } + }, + { + "identifier": "ChooseGameState", + "implementation": "roboy.dialog.states.gameStates.ChooseGameState", + "transitions": { + "choseSnapchat" : "Snapchat", + "chose20questions" : "Akinator", + "exitGame": "QuestionAnswering" + } + }, + { + "identifier": "WildTalk", + "implementation": "roboy.dialog.states.ordinaryStates.WildTalkState", + "transitions": {} + }, + { + "identifier": "Farewell", + "implementation": "roboy.dialog.states.botboy.BotBoyFarewellState", + "transitions": {} + } + ] +} diff --git a/resources/personalityFiles/uzupis.json b/resources/personalityFiles/uzupis.json index ba913096..60ac9e1a 100644 --- a/resources/personalityFiles/uzupis.json +++ b/resources/personalityFiles/uzupis.json @@ -34,5 +34,6 @@ "next" : "Farewell" } } + ] } \ No newline at end of file diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index 9c3496f2..fd4eda1b 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -6918,3 +6918,77 @@ {"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"DataProp"} {"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} {"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.039105719999382775} ","formula":"(rdf:type dbpedia:Airport)","lexeme":"airport","type":"ClassNoun"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"(rdf:type dbpedia:University)","lexeme":"university","type":"ClassNoun"} +{"features":" {score:0.13518829246017713} ","formula":"(rdf:type dbpedia:City)","lexeme":"city","type":"ClassNoun"} +{"features":" {score:0.13518829246017713} ","formula":"!dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.6244656133828996} ","formula":"resource:Munich","lexeme":"munich","type":"NamedEntity"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.02476466395722725} ","formula":"!dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.007118905612640406} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.5156482342007435} ","formula":"resource:Ludwig_Maximilian_University_of_Munich","lexeme":"ludwig maximilian university of munich","type":"NamedEntity"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"!dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.3574573272887659} ","formula":"resource:1972_Summer_Olympics","lexeme":"1972 summer olympics","type":"NamedEntity"} +{"features":" {score:0.0048526863084922016} ","formula":"!dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.13518829246017713} ","formula":"dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.006745657462310337} ","formula":"dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.5069005576208179} ","formula":"resource:Munich_Agreement","lexeme":"munich agreement","type":"NamedEntity"} +{"features":" {score:0.02476466395722725} ","formula":"(rdf:type dbpedia:Municipality)","lexeme":"municipality","type":"ClassNoun"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.5222235130111524} ","formula":"resource:FC_Bayern_Munich","lexeme":"fc bayern munich","type":"NamedEntity"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.024354053257352713} ","formula":"property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.024354053257352713} ","formula":"property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.019684884847898314} ","formula":"property:case","lexeme":"case","type":"ObjProp"} +{"features":" {score:0.04119084299478716} ","formula":"!property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.04307977245656418} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.018446601941747572} ","formula":"!property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.04307977245656418} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.019684884847898314} ","formula":"!property:case","lexeme":"case","type":"DataProp"} +{"features":" {score:0.12119717597961427} ","formula":"dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.02330097087378641} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.019684884847898314} ","formula":"!property:case","lexeme":"case","type":"ObjProp"} +{"features":" {score:0.02330097087378641} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.04307977245656418} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.02330097087378641} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.019684884847898314} ","formula":"property:case","lexeme":"case","type":"DataProp"} +{"features":" {score:0.12119717597961427} ","formula":"!dbpedia:kingdom","lexeme":"kingdom","type":"ObjectProp"} +{"features":" {score:0.04307977245656418} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.018446601941747572} ","formula":"property:market","lexeme":"market","type":"DataProp"} +{"features":" {score:0.024354053257352713} ","formula":"!property:economy","lexeme":"economy","type":"ObjProp"} +{"features":" {score:0.3600622212941572} ","formula":"\u003chttp://dbpedia.org/resource/Galicia_(Eastern_Europe)\u003e","lexeme":"galicia eastern europe","type":"NamedEntity"} +{"features":" {score:0.04119084299478716} ","formula":"!property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.3138386448463968} ","formula":"resource:Odessa","lexeme":"odessa","type":"NamedEntity"} +{"features":" {score:0.04119084299478716} ","formula":"property:nation","lexeme":"nation","type":"DataProp"} +{"features":" {score:0.024354053257352713} ","formula":"!property:economy","lexeme":"economy","type":"DataProp"} +{"features":" {score:0.018446601941747572} ","formula":"property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.38531734665303335} ","formula":"resource:Ukrainian_Soviet_Socialist_Republic","lexeme":"ukrainian soviet socialist republic","type":"NamedEntity"} +{"features":" {score:0.04307977245656418} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.3847475641953887} ","formula":"resource:Kiev","lexeme":"kiev","type":"NamedEntity"} +{"features":" {score:0.04307977245656418} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.6268662072925639} ","formula":"resource:Ukraine","lexeme":"ukraine","type":"NamedEntity"} +{"features":" {score:0.04119084299478716} ","formula":"property:nation","lexeme":"nation","type":"ObjProp"} +{"features":" {score:0.02330097087378641} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.04307977245656418} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.019684884847898314} ","formula":"(rdf:type dbpedia:Case)","lexeme":"case","type":"ClassNoun"} +{"features":" {score:0.02330097087378641} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.018446601941747572} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} diff --git a/roslaunch b/roslaunch new file mode 100644 index 00000000..e69de29b From 872c1194f831585311abd25277a0f688b67d7a77 Mon Sep 17 00:00:00 2001 From: missxa Date: Sat, 22 Sep 2018 07:37:41 +0200 Subject: [PATCH 141/147] bugfix --- resources/personalityFiles/WackerShow.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/personalityFiles/WackerShow.json b/resources/personalityFiles/WackerShow.json index 5e0154ac..cf0cf118 100644 --- a/resources/personalityFiles/WackerShow.json +++ b/resources/personalityFiles/WackerShow.json @@ -80,7 +80,7 @@ }, { "identifier": "TellStory", - "implementation": "roboy.dialog.states.gameStates.StoryTellingState", + "implementation": "roboy.dialog.states.eventStates.StoryTellingState", "transitions": { "next" : "PersonalQA" }, From b6d71af64b5b5b0e0472559eafb673bdd0090366 Mon Sep 17 00:00:00 2001 From: missxa Date: Sat, 22 Sep 2018 16:01:19 +0200 Subject: [PATCH 142/147] working wacker --- config.properties | 2 +- .../main/java/roboy/dialog/Conversation.java | 6 + .../devoStates/QuestionRoboyQAState.java | 4 +- resources/personalityFiles/WackerShow.json | 2 +- resources_nlu/error_test/newLexicon.txt | 106 ++++++++++++++++++ 5 files changed, 116 insertions(+), 4 deletions(-) diff --git a/config.properties b/config.properties index 68e4e053..ad3a225b 100755 --- a/config.properties +++ b/config.properties @@ -19,7 +19,7 @@ ROS_ACTIVE_PKGS: - roboy_speech_recognition - roboy_face # - roboy_filters -- roboy_vision +#- roboy_vision # - roboy_nodered # - roboy_test - sound_play diff --git a/dialog/src/main/java/roboy/dialog/Conversation.java b/dialog/src/main/java/roboy/dialog/Conversation.java index 5f0b7a98..781697c1 100644 --- a/dialog/src/main/java/roboy/dialog/Conversation.java +++ b/dialog/src/main/java/roboy/dialog/Conversation.java @@ -15,6 +15,7 @@ import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -96,6 +97,11 @@ public void run(){ } else {//if this is an initial start actions = personality.startConversation(); logger.info("############# Conversation started ############"); + try { + System.in.read(); + } catch (IOException e) { + logger.error(e.getMessage()); + } } while (isRunning) { diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 0d2090d4..8fef7d74 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -93,11 +93,11 @@ public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { @Override public Output act() { - if (Math.random() < 0.3) { + if (Math.random() < 0) { offeredGame = true; return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); } - if(Math.random() < 0.6) { + if(Math.random() < 0.05) { offeredStory = true; return Output.say(Verbalizer.confirmStory.getRandomElement()); } diff --git a/resources/personalityFiles/WackerShow.json b/resources/personalityFiles/WackerShow.json index cf0cf118..181e62ee 100644 --- a/resources/personalityFiles/WackerShow.json +++ b/resources/personalityFiles/WackerShow.json @@ -35,7 +35,7 @@ "transitions": { "newPerson": "InterlocutorIntro", "math": "Math", - "game": "ChooseGameState", + "game": "PersonalQA", "objectDetected": "ObjectDetection", "personalQA": "PersonalQA", "generalQA": "GeneralQA" diff --git a/resources_nlu/error_test/newLexicon.txt b/resources_nlu/error_test/newLexicon.txt index fd4eda1b..cc294ffb 100644 --- a/resources_nlu/error_test/newLexicon.txt +++ b/resources_nlu/error_test/newLexicon.txt @@ -6992,3 +6992,109 @@ {"features":" {score:0.019684884847898314} ","formula":"(rdf:type dbpedia:Case)","lexeme":"case","type":"ClassNoun"} {"features":" {score:0.02330097087378641} ","formula":"property:place","lexeme":"place","type":"DataProp"} {"features":" {score:0.018446601941747572} ","formula":"!property:market","lexeme":"market","type":"ObjProp"} +{"features":" {score:0.04497633274836032} ","formula":"dbpedia:school","lexeme":"school","type":"ObjectProp"} +{"features":" {score:0.004000398279457181} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.23928566465179055} ","formula":"!dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.01571197572250911} ","formula":"dbpedia:team","lexeme":"team","type":"ObjectProp"} +{"features":" {score:0.020602241780125662} ","formula":"(rdf:type dbpedia:Area)","lexeme":"area","type":"ClassNoun"} +{"features":" {score:0.06181670468015462} ","formula":"!property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.004000398279457181} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.12948527336120605} ","formula":"(rdf:type dbpedia:District)","lexeme":"district","type":"ClassNoun"} +{"features":" {score:0.5720439401120807} ","formula":"resource:Michigan","lexeme":"michigan","type":"NamedEntity"} +{"features":" {score:0.020602241780125662} ","formula":"property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.004000398279457181} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.06181670468015462} ","formula":"property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.020602241780125662} ","formula":"property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.23928566465179055} ","formula":"!property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.004000398279457181} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.04497633274836032} ","formula":"!property:school","lexeme":"school","type":"DataProp"} +{"features":" {score:0.13264328241348267} ","formula":"(rdf:type dbpedia:Community)","lexeme":"community","type":"ClassNoun"} +{"features":" {score:0.04497633274836032} ","formula":"property:school","lexeme":"school","type":"DataProp"} +{"features":" {score:0.06181670468015462} ","formula":"dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.4286662644078575} ","formula":"resource:Detroit","lexeme":"detroit","type":"NamedEntity"} +{"features":" {score:0.020602241780125662} ","formula":"!property:area","lexeme":"area","type":"ObjProp"} +{"features":" {score:0.00760847769190393} ","formula":"!dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.23928566465179055} ","formula":"property:state","lexeme":"state","type":"DataProp"} +{"features":" {score:0.00760847769190393} ","formula":"dbpedia:jurisdiction","lexeme":"jurisdiction","type":"ObjectProp"} +{"features":" {score:0.014931363700492493} ","formula":"property:program","lexeme":"program","type":"ObjProp"} +{"features":" {score:0.014931363700492493} ","formula":"property:program","lexeme":"program","type":"DataProp"} +{"features":" {score:0.5430869601583628} ","formula":"resource:University_of_Michigan","lexeme":"university of michigan","type":"NamedEntity"} +{"features":" {score:0.004000398279457181} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.23928566465179055} ","formula":"!property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.04497633274836032} ","formula":"!property:school","lexeme":"school","type":"ObjProp"} +{"features":" {score:0.00760847769190393} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.00760847769190393} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"ObjProp"} +{"features":" {score:0.020602241780125662} ","formula":"!property:area","lexeme":"area","type":"DataProp"} +{"features":" {score:0.5123400340145537} ","formula":"\u003chttp://dbpedia.org/resource/Ann_Arbor,_Michigan\u003e","lexeme":"ann arbor, michigan","type":"NamedEntity"} +{"features":" {score:0.04497633274836032} ","formula":"property:school","lexeme":"school","type":"ObjProp"} +{"features":" {score:0.01571197572250911} ","formula":"!dbpedia:team","lexeme":"team","type":"ObjectProp"} +{"features":" {score:0.00760847769190393} ","formula":"!property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.06181670468015462} ","formula":"property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.04497633274836032} ","formula":"!dbpedia:school","lexeme":"school","type":"ObjectProp"} +{"features":" {score:0.014931363700492493} ","formula":"!property:program","lexeme":"program","type":"DataProp"} +{"features":" {score:0.5140407617029581} ","formula":"resource:Michigan_State_University","lexeme":"michigan state university","type":"NamedEntity"} +{"features":" {score:0.23928566465179055} ","formula":"property:state","lexeme":"state","type":"ObjProp"} +{"features":" {score:0.30652677306930154} ","formula":"(rdf:type dbpedia:State)","lexeme":"state","type":"ClassNoun"} +{"features":" {score:0.04497633274836032} ","formula":"(rdf:type dbpedia:School)","lexeme":"school","type":"ClassNoun"} +{"features":" {score:0.06181670468015462} ","formula":"!property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.06181670468015462} ","formula":"(rdf:type dbpedia:University)","lexeme":"university","type":"ClassNoun"} +{"features":" {score:0.23928566465179055} ","formula":"dbpedia:state","lexeme":"state","type":"ObjectProp"} +{"features":" {score:0.014931363700492493} ","formula":"!property:program","lexeme":"program","type":"ObjProp"} +{"features":" {score:0.00760847769190393} ","formula":"property:jurisdiction","lexeme":"jurisdiction","type":"DataProp"} +{"features":" {score:0.06181670468015462} ","formula":"!dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.039105719999382775} ","formula":"(rdf:type dbpedia:Airport)","lexeme":"airport","type":"ClassNoun"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"(rdf:type dbpedia:University)","lexeme":"university","type":"ClassNoun"} +{"features":" {score:0.13518829246017713} ","formula":"(rdf:type dbpedia:City)","lexeme":"city","type":"ClassNoun"} +{"features":" {score:0.06491494770435727} ","formula":"!property:institution","lexeme":"institution","type":"DataProp"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.02476466395722725} ","formula":"!dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.007118905612640406} ","formula":"(rdf:type dbpedia:Place)","lexeme":"place","type":"ClassNoun"} +{"features":" {score:0.06491494770435727} ","formula":"property:institution","lexeme":"institution","type":"DataProp"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.6285851188338059} ","formula":"resource:Texas_Tech_University","lexeme":"texas tech university","type":"NamedEntity"} +{"features":" {score:0.34189207904479085} ","formula":"!property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.6252712786778605} ","formula":"resource:Private_university","lexeme":"private university","type":"NamedEntity"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.06491494770435727} ","formula":"!property:institution","lexeme":"institution","type":"ObjProp"} +{"features":" {score:0.3574573272887659} ","formula":"resource:1972_Summer_Olympics","lexeme":"1972 summer olympics","type":"NamedEntity"} +{"features":" {score:0.34189207904479085} ","formula":"property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.0048526863084922016} ","formula":"dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.13518829246017713} ","formula":"dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.4527074563224413} ","formula":"resource:ETH_Zurich","lexeme":"eth zurich","type":"NamedEntity"} +{"features":" {score:0.5069005576208179} ","formula":"resource:Munich_Agreement","lexeme":"munich agreement","type":"NamedEntity"} +{"features":" {score:0.539723393814838} ","formula":"resource:Rensselaer_Polytechnic_Institute","lexeme":"rensselaer polytechnic institute","type":"NamedEntity"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"ObjProp"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.6278378455727189} ","formula":"resource:Saint_Petersburg_State_University","lexeme":"saint petersburg state university","type":"NamedEntity"} +{"features":" {score:0.34189207904479085} ","formula":"(rdf:type dbpedia:University)","lexeme":"university","type":"ClassNoun"} +{"features":" {score:0.34189207904479085} ","formula":"property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.13518829246017713} ","formula":"!dbpedia:city","lexeme":"city","type":"ObjectProp"} +{"features":" {score:0.06491494770435727} ","formula":"dbpedia:institution","lexeme":"institution","type":"ObjectProp"} +{"features":" {score:0.007118905612640406} ","formula":"!property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!property:film","lexeme":"film","type":"DataProp"} +{"features":" {score:0.6244656133828996} ","formula":"resource:Munich","lexeme":"munich","type":"NamedEntity"} +{"features":" {score:0.02476466395722725} ","formula":"dbpedia:municipality","lexeme":"municipality","type":"ObjectProp"} +{"features":" {score:0.34189207904479085} ","formula":"!property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.34189207904479085} ","formula":"dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.5156482342007435} ","formula":"resource:Ludwig_Maximilian_University_of_Munich","lexeme":"ludwig maximilian university of munich","type":"NamedEntity"} +{"features":" {score:0.34189207904479085} ","formula":"!dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"!dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.0048526863084922016} ","formula":"property:film","lexeme":"film","type":"ObjProp"} +{"features":" {score:0.0048526863084922016} ","formula":"!dbpedia:film","lexeme":"film","type":"ObjectProp"} +{"features":" {score:0.06491494770435727} ","formula":"property:institution","lexeme":"institution","type":"ObjProp"} +{"features":" {score:0.006745657462310337} ","formula":"dbpedia:university","lexeme":"university","type":"ObjectProp"} +{"features":" {score:0.02476466395722725} ","formula":"!property:municipality","lexeme":"municipality","type":"DataProp"} +{"features":" {score:0.02476466395722725} ","formula":"(rdf:type dbpedia:Municipality)","lexeme":"municipality","type":"ClassNoun"} +{"features":" {score:0.06491494770435727} ","formula":"!dbpedia:institution","lexeme":"institution","type":"ObjectProp"} +{"features":" {score:0.006745657462310337} ","formula":"!property:university","lexeme":"university","type":"DataProp"} +{"features":" {score:0.02476466395722725} ","formula":"property:municipality","lexeme":"municipality","type":"ObjProp"} +{"features":" {score:0.007118905612640406} ","formula":"property:place","lexeme":"place","type":"DataProp"} +{"features":" {score:0.5222235130111524} ","formula":"resource:FC_Bayern_Munich","lexeme":"fc bayern munich","type":"NamedEntity"} +{"features":" {score:0.13518829246017713} ","formula":"property:city","lexeme":"city","type":"ObjProp"} +{"features":" {score:0.13518829246017713} ","formula":"!property:city","lexeme":"city","type":"DataProp"} +{"features":" {score:0.006745657462310337} ","formula":"property:university","lexeme":"university","type":"DataProp"} From 317e2a6f91f9a9c010ba2e5779fdc912b27dc0bb Mon Sep 17 00:00:00 2001 From: missxa Date: Sat, 6 Oct 2018 23:35:34 +0200 Subject: [PATCH 143/147] with infineon game state --- dialog/pom.xml | 6 + .../contextObjects/CupGameSmachState.java | 9 ++ .../CupGameSmachStateUpdater.java | 26 +++ .../states/gameStates/CupGameState.java | 148 ++++++++++++++++++ .../src/main/java/roboy/ros/RosMainNode.java | 30 ++++ .../java/roboy/ros/RosServiceClients.java | 5 +- .../main/java/roboy/ros/RosSubscribers.java | 3 + resources/personalityFiles/test/Test.json | 12 +- 8 files changed, 230 insertions(+), 9 deletions(-) create mode 100644 dialog/src/main/java/roboy/context/contextObjects/CupGameSmachState.java create mode 100644 dialog/src/main/java/roboy/context/contextObjects/CupGameSmachStateUpdater.java create mode 100644 dialog/src/main/java/roboy/dialog/states/gameStates/CupGameState.java diff --git a/dialog/pom.xml b/dialog/pom.xml index 69cfb3c6..1114923f 100755 --- a/dialog/pom.xml +++ b/dialog/pom.xml @@ -358,6 +358,12 @@ 0.0.3 + + org.ros.rosjava_messages + std_srvs + 1.11.2 + + org.apache.commons commons-configuration2 diff --git a/dialog/src/main/java/roboy/context/contextObjects/CupGameSmachState.java b/dialog/src/main/java/roboy/context/contextObjects/CupGameSmachState.java new file mode 100644 index 00000000..5a962e7b --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/CupGameSmachState.java @@ -0,0 +1,9 @@ +package roboy.context.contextObjects; + +import roboy.context.Value; + +/** + * For testing a ROS topic connection which sends simple String messages. + */ +public class CupGameSmachState extends Value { +} diff --git a/dialog/src/main/java/roboy/context/contextObjects/CupGameSmachStateUpdater.java b/dialog/src/main/java/roboy/context/contextObjects/CupGameSmachStateUpdater.java new file mode 100644 index 00000000..774c0186 --- /dev/null +++ b/dialog/src/main/java/roboy/context/contextObjects/CupGameSmachStateUpdater.java @@ -0,0 +1,26 @@ +package roboy.context.contextObjects; + +import roboy.context.ROSTopicUpdater; +import roboy.ros.RosMainNode; +import roboy.ros.RosSubscribers; + +/** + * For testing a ROS topic connection which sends simple String messages. + */ +public class CupGameSmachStateUpdater extends ROSTopicUpdater { + + @Override + protected RosSubscribers getTargetSubscriber() { + return RosSubscribers.CUP_GAME_STATE; + } + + public CupGameSmachStateUpdater(CupGameSmachState target, RosMainNode node) { + super(target, node); + } + + @Override + protected synchronized void update() { + target.updateValue(message.getData()); + } + +} diff --git a/dialog/src/main/java/roboy/dialog/states/gameStates/CupGameState.java b/dialog/src/main/java/roboy/dialog/states/gameStates/CupGameState.java new file mode 100644 index 00000000..43209de7 --- /dev/null +++ b/dialog/src/main/java/roboy/dialog/states/gameStates/CupGameState.java @@ -0,0 +1,148 @@ +package roboy.dialog.states.gameStates; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.yecht.Data; +import org.yecht.ruby.Out; +import roboy.dialog.states.definitions.State; +import roboy.dialog.states.definitions.StateParameters; +import roboy.emotions.RoboyEmotion; +import roboy.linguistics.Linguistics; +import roboy.linguistics.sentenceanalysis.Interpretation; +import roboy.logic.Inference; +import roboy.logic.StatementInterpreter; +import roboy.talk.PhraseCollection; +import roboy.talk.Verbalizer; +import roboy.util.RandomList; + +import java.util.*; + +import static roboy.util.FileLineReader.readFile; + + +public class CupGameState extends State { + + private final static List EXIT_REQUEST = Arrays.asList("bored", "stop", "something else", "different", "boring"); + private final static List READY = Arrays.asList("done", "ready", "let's go", "play"); + private final static String TRANSITION_EXIT = "exit"; + private final Logger LOGGER = LogManager.getLogger(); + + private enum CupGamePhase { + SHUFFLE, + SCAN, + GUESS, + OFFER_REPEAT, + EXIT + } + + + private final static String FIND_CUPS = "find_cups"; + private final static String GOTOCUP1 = "cup_1"; + private final static String GOTOCUP2 = "cup_2"; + private final static String FINISHED = "finished"; + + private CupGamePhase phase = CupGamePhase.SHUFFLE; + + public CupGameState(String stateIdentifier, StateParameters params) { + + super(stateIdentifier, params); + } + + @Override + public Output act() { + switch (phase){ + case SHUFFLE: + return Output.say("you shall shuffle the cups, my friend. let me know when you are ready"); + case SCAN: + // TODO get response from the state machine +// if (getRosMainNode().StartCupGameSmach()) { + // if smach start is successful + // comment on actions while not finished exploring + String prevState = ""; + String currentSmachState = getContext().CUP_GAME_SMACH_STATE_MSG.getValue(); + while(!currentSmachState.equals(FINISHED)) { + currentSmachState = getContext().CUP_GAME_SMACH_STATE_MSG.getValue(); + if (!currentSmachState.equals(prevState)) { + switch (getContext().CUP_GAME_SMACH_STATE_MSG.getValue()) { + case FIND_CUPS: + getRosMainNode().SynthesizeSpeech("i am looking for cups"); + break; + case GOTOCUP1: + getRosMainNode().ShowEmotion(RoboyEmotion.HYPNO_COLOUR_EYES); + getRosMainNode().SynthesizeSpeech("wubba lubba dub dub, doing magic for this cup"); + break; + } + + prevState = currentSmachState; + } +// } + } + return Output.say("so are you ready to hear the oracle's prophecy?"); + case GUESS: + return Output.say("I think I found it there. So do I win now?"); + case OFFER_REPEAT: + return Output.say("wanna play again?"); + default: + return Output.sayNothing(); + } + + } + + @Override + public Output react(Interpretation input) { + exitOnRequest(input.getSentence()); + + switch (phase) { + case SHUFFLE: + if (StatementInterpreter.isFromList(input.getSentence(),READY)) { + phase = CupGamePhase.SCAN; + return Output.say("Alright. Let me check with my superpower soli where did you hide the ball"); + } + else { + return Output.say("Hm, seems you are not done yet. I give you another try"); + } + case SCAN: + phase = CupGamePhase.GUESS; + return Output.useFallback(); + case GUESS: + phase = CupGamePhase.OFFER_REPEAT; + return Output.say("ha-ha."); + case OFFER_REPEAT: + if (StatementInterpreter.isFromList(input.getSentence(),Verbalizer.consent)) { + phase = CupGamePhase.SHUFFLE; + return Output.say("Here we go again then!"); + } + else + phase = CupGamePhase.EXIT; + return Output.say("I believe you've had enough of my magic"); + case EXIT: + return Output.say("Wanna stop playing? Sure, if you say so."); + default: + return Output.useFallback(); + } + + } + + private void exitOnRequest(String input) { + if(StatementInterpreter.isFromList(input, EXIT_REQUEST)) { + phase = CupGamePhase.EXIT; + } + } + + @Override + public State getNextState() { + if (phase == CupGamePhase.EXIT) { + return getTransition(TRANSITION_EXIT); + } + else { + return this; + } + } + + @Override + protected Set getRequiredTransitionNames() { + return newSet(TRANSITION_EXIT); + } + + +} diff --git a/dialog/src/main/java/roboy/ros/RosMainNode.java b/dialog/src/main/java/roboy/ros/RosMainNode.java index 04ac08af..bc4c1954 100755 --- a/dialog/src/main/java/roboy/ros/RosMainNode.java +++ b/dialog/src/main/java/roboy/ros/RosMainNode.java @@ -15,6 +15,8 @@ import roboy.util.ConfigManager; import roboy_communication_cognition.*; import roboy_communication_control.*; +import std_srvs.TriggerRequest; +import std_srvs.TriggerResponse; import java.io.IOException; import java.net.URI; @@ -84,6 +86,34 @@ public void PerformMovement(String bodyPart, String name) throws InterruptedExce } + public boolean StartCupGameSmach() { + if(services.notInitialized(RosServiceClients.STARTCUPGAME)) { + return false; + } + + ServiceClient cupGameClient = services.getService(RosServiceClients.STARTCUPGAME); + rosConnectionLatch = new CountDownLatch(1); + TriggerRequest request = cupGameClient.newMessage(); + ServiceResponseListener listener = new ServiceResponseListener() { + @Override + public void onSuccess(TriggerResponse response) { +// System.out.println(response.getSuccess()); + resp = response.getSuccess(); + rosConnectionLatch.countDown(); + } + + @Override + public void onFailure(RemoteException e) { + rosConnectionLatch.countDown(); + throw new RosRuntimeException(e); + } + }; + cupGameClient.call(request, listener); + waitForLatchUnlock(rosConnectionLatch, cupGameClient.getName().toString()); + return ((boolean) resp); + + + } public boolean SynthesizeSpeech(String text) { if(services.notInitialized(RosServiceClients.SPEECHSYNTHESIS)) { diff --git a/dialog/src/main/java/roboy/ros/RosServiceClients.java b/dialog/src/main/java/roboy/ros/RosServiceClients.java index 2abfe4e0..d56d9c42 100755 --- a/dialog/src/main/java/roboy/ros/RosServiceClients.java +++ b/dialog/src/main/java/roboy/ros/RosServiceClients.java @@ -2,7 +2,7 @@ import roboy_communication_cognition.*; import roboy_communication_control.*; - +import std_srvs.Trigger; /** * Stores the different client addresses and corresponding ROS message types. */ @@ -22,7 +22,8 @@ enum RosServiceClients { CYPHERMEMORY("roboy_memory", "/roboy/cognition/memory/cypher", DataQuery._TYPE), INTENT("roboy_intents", "/roboy/cognition/detect_intent", DetectIntent._TYPE), SNAPCHATFILTER("roboy_filters", "/roboy/cognition/apply_filter", ApplyFilter._TYPE), - SOUNDPLAY("sound_play", "/roboy/matrix/sound/play", Talk._TYPE); + SOUNDPLAY("sound_play", "/roboy/matrix/sound/play", Talk._TYPE), + STARTCUPGAME("roboy_soli", "roboy/cupgame/start", Trigger._TYPE); String rosPackage; String address; diff --git a/dialog/src/main/java/roboy/ros/RosSubscribers.java b/dialog/src/main/java/roboy/ros/RosSubscribers.java index 53fc585e..db60937e 100644 --- a/dialog/src/main/java/roboy/ros/RosSubscribers.java +++ b/dialog/src/main/java/roboy/ros/RosSubscribers.java @@ -3,6 +3,7 @@ import roboy_communication_cognition.*; import roboy_communication_control.Strings; + public enum RosSubscribers { DIRECTION_VECTOR("roboy_audio", "/roboy/cognition/audio/direction_of_arrival", DirectionVector._TYPE), FACE_COORDINATES("roboy_vision", "/roboy/cognition/vision/coordinates", FaceCoordinates._TYPE), @@ -12,6 +13,8 @@ public enum RosSubscribers { NUMBER_PEOPLE_AROUND("roboy_vision", "/roboy/cognition/vision/people_around", std_msgs.Int8._TYPE), PERSON_LISTENING("roboy_vision", "/roboy/cognition/vision/person_listening", std_msgs.Bool._TYPE), BOOTH_SENTENCE("roboy_nodered", "/roboy/cognition/nodered/boothsentence", std_msgs.String._TYPE), + CUP_GAME_READY("roboy_soli", "/roboy/control/ball", std_msgs.Bool._TYPE), + CUP_GAME_STATE("roboy_soli", "/roboy/control/smach", std_msgs.String._TYPE) ; String rosPackage; diff --git a/resources/personalityFiles/test/Test.json b/resources/personalityFiles/test/Test.json index fb48fa7a..fbefeff0 100644 --- a/resources/personalityFiles/test/Test.json +++ b/resources/personalityFiles/test/Test.json @@ -1,15 +1,13 @@ { - "initialState": "StoryTelling", + "initialState": "CupGame", "states": [ { - "identifier": "StoryTelling", - "implementation": "roboy.dialog.states.eventStates.StoryTellingState", + "identifier": "CupGame", + "implementation": "roboy.dialog.states.gameStates.CupGameState", "transitions": { - "next": "StoryTelling" + "next": "CupGame" }, - "parameters": { - "stories": "oh boy roboy=/home/pi/test.wav" - } + "fallback": "WildTalk" }, { "identifier": "WildTalk", From 71b181f8ca7413ebcef23ca96442d0a4c43602e3 Mon Sep 17 00:00:00 2001 From: missxa Date: Sat, 6 Oct 2018 23:40:38 +0200 Subject: [PATCH 144/147] tracking control SMACH --- config.properties | 13 +++++---- .../src/main/java/roboy/context/Context.java | 9 +++++- resources/personalityFiles/WackerShow.json | 29 +++++++------------ 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/config.properties b/config.properties index 68e4e053..ec33f07f 100755 --- a/config.properties +++ b/config.properties @@ -16,13 +16,14 @@ ROS_ACTIVE_PKGS: # - roboy_gnlp # - roboy_memory - roboy_speech_synthesis -- roboy_speech_recognition +#- roboy_speech_recognition - roboy_face # - roboy_filters - roboy_vision # - roboy_nodered # - roboy_test - sound_play +- roboy_soli DEBUG: true DEMO_MODE: false @@ -31,16 +32,16 @@ INFINITE_REPETITION: true CONVERSATION_TIMEOUT: 10800 # only single input is allowed, defaults to cmdline -#INPUT: cmdline +INPUT: cmdline #INPUT: cerevoice #INPUT: udp -INPUT: bing +#INPUT: bing #INPUT: telegram # multiple outputs are allowed, defaults to cmdline OUTPUTS: - cmdline -- cerevoice +#- cerevoice #- freetts #- ibm #- emotions @@ -60,10 +61,10 @@ PARSER_PORT: 5000 # PERSONALITY_FILE: "resources/personalityFiles/tutorial/ToyStateMachine.json" # PERSONALITY_FILE: "resources/personalityFiles/GamePersonality.json" # PERSONALITY_FILE: "resources/personalityFiles/FairShowPersonality.json" -PERSONALITY_FILE: "resources/personalityFiles/WackerShow.json" +# PERSONALITY_FILE: "resources/personalityFiles/WackerShow.json" # PERSONALITY_FILE: "resources/personalityFiles/uzupis.json" # PERSONALITY_FILE: "resources/personalityFiles/DevoPersonality.json" -# PERSONALITY_FILE: "resources/personalityFiles/test/Test.json" +PERSONALITY_FILE: "resources/personalityFiles/test/Test.json" IBM_TTS_USER: "" IBM_TTS_PASS: "" diff --git a/dialog/src/main/java/roboy/context/Context.java b/dialog/src/main/java/roboy/context/Context.java index 37c53baa..c5d86235 100644 --- a/dialog/src/main/java/roboy/context/Context.java +++ b/dialog/src/main/java/roboy/context/Context.java @@ -8,7 +8,6 @@ import roboy.util.ConfigManager; import roboy_communication_cognition.DirectionVector; import roboy_communication_control.Strings; -import std_msgs.Bool; import java.util.ArrayList; @@ -58,6 +57,9 @@ public class Context { public final HistoryInterface BOOTH_SENTENCE = new HistoryInterface<>(new BoothSentence()); + public final ValueInterface CUP_GAME_SMACH_STATE_MSG = + new ValueInterface<>(new CupGameSmachState()); + /* GUI */ private final ArrayList guiValues = new ArrayList(); private final ArrayList guiHistories = new ArrayList(); @@ -76,6 +78,7 @@ public class Context { private PeopleAroundUpdater CROWD_UPDATER; private DetectedObjectsUpdater DETECTED_OBJ_UPDATER; private BoothSentenceUpdater BOOTH_SENTENCE_UPDATER; + private CupGameSmachStateUpdater CUP_GAME_SMACH_UPDATER; /* OBSERVERS */ private final FaceCoordinatesObserver FACE_COORDINATES_OBSERVER; @@ -135,6 +138,10 @@ public void initializeROS(RosMainNode ros) { BOOTH_SENTENCE_UPDATER = new BoothSentenceUpdater(BOOTH_SENTENCE.valueHistory, ros); } + if(ConfigManager.ROS_ACTIVE_PKGS.contains("roboy_soli")){ + CUP_GAME_SMACH_UPDATER = new CupGameSmachStateUpdater(CUP_GAME_SMACH_STATE_MSG.value, ros); + } + rosInitialized = true; } } diff --git a/resources/personalityFiles/WackerShow.json b/resources/personalityFiles/WackerShow.json index cf0cf118..8a5bc6c7 100644 --- a/resources/personalityFiles/WackerShow.json +++ b/resources/personalityFiles/WackerShow.json @@ -78,29 +78,12 @@ "infoFile": "resources/sentences/RoboyInfoList.json" } }, - { - "identifier": "TellStory", - "implementation": "roboy.dialog.states.eventStates.StoryTellingState", - "transitions": { - "next" : "PersonalQA" - }, - "parameters": { - "stories": "magic glass=/home/roboy/Downloads/story.wav" - } - }, - { - "identifier": "Akinator", - "implementation": "roboy.dialog.states.gameStates.GamingTwentyQuestionsState", - "transitions": { - "gameEnded": "QuestionAnswering" - } - }, { "identifier": "ChooseGameState", "implementation": "roboy.dialog.states.gameStates.ChooseGameState", "transitions": { "choseSnapchat" : "Snapchat", - "chose20questions" : "Akinator", + "chose20questions" : "QuestionAnswering", "exitGame": "QuestionAnswering" } }, @@ -113,6 +96,16 @@ "identifier": "Farewell", "implementation": "roboy.dialog.states.botboy.BotBoyFarewellState", "transitions": {} + }, + { + "identifier": "TellStory", + "implementation": "roboy.dialog.states.eventStates.StoryTellingState", + "transitions": { + "next" : "PersonalQA" + }, + "parameters": { + "stories": "magic glass=/home/roboy/Downloads/story.wav" + } } ] } From c9e2961d5d74e6e95c5bc267f085f4394b8af803 Mon Sep 17 00:00:00 2001 From: Joseph Birkner Date: Sun, 7 Oct 2018 01:08:59 +0200 Subject: [PATCH 145/147] Ordinary personality bugfixes. --- dialog/pom.xml | 2 +- .../devoStates/QuestionRoboyQAState.java | 129 ++++++++---------- .../GamingTwentyQuestionsState.java | 6 +- .../PersonalInformationAskingState.java | 7 +- .../personalityFiles/OrdinaryPersonality.json | 10 +- 5 files changed, 75 insertions(+), 79 deletions(-) diff --git a/dialog/pom.xml b/dialog/pom.xml index 69cfb3c6..ebf3d172 100755 --- a/dialog/pom.xml +++ b/dialog/pom.xml @@ -422,7 +422,7 @@ com.github.markozajc akiwrapper - 1.3.2 + 1.3.4 diff --git a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java index 8fef7d74..5de2cfd4 100644 --- a/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java +++ b/dialog/src/main/java/roboy/dialog/states/devoStates/QuestionRoboyQAState.java @@ -75,8 +75,6 @@ public class QuestionRoboyQAState extends ExpoState { private final static RandomList answerStartingPhrases = PhraseCollection.QUESTION_ANSWERING_START; private final String INFO_FILE_PARAMETER_ID = "infoFile"; - private boolean askingSpecifyingQuestion = false; - private String answerAfterUnspecifiedQuestion = ""; // the answer to use if specifying question is answered with YES private boolean offeredGame = false; private boolean userWantsGame = false; private boolean offeredStory = false; @@ -93,14 +91,16 @@ public QuestionRoboyQAState(String stateIdentifier, StateParameters params) { @Override public Output act() { - if (Math.random() < 0) { + if (questionsAnswered >= MAX_NUM_OF_QUESTIONS && !offeredGame) { offeredGame = true; return Output.say(PhraseCollection.OFFER_GAME_PHRASES.getRandomElement()); } - if(Math.random() < 0.05) { - offeredStory = true; - return Output.say(Verbalizer.confirmStory.getRandomElement()); - } + else + offeredGame = false; + // if(Math.random() < 0.05) { + // offeredStory = true; + // return Output.say(Verbalizer.confirmStory.getRandomElement()); + // } return Output.sayNothing(); } @@ -108,13 +108,16 @@ public Output act() { public Output react(Interpretation input) { return reactToQuestion(input); } - - private Output reactToQuestion(Interpretation input) { + private Output reactToQuestion(Interpretation input) + { + // -- Decide whether to go forward on proposed transitions if (offeredGame) { - questionsAnswered++; - offeredGame = false; - if (getInference().inferSentiment(input) == Linguistics.UtteranceSentiment.POSITIVE) { + if (input.getSentiment() == Linguistics.UtteranceSentiment.POSITIVE || + input.getSentiment() == Linguistics.UtteranceSentiment.NEUTRAL || + input.getSentiment() == Linguistics.UtteranceSentiment.UNCERTAIN_POS || + input.getSentiment() == Linguistics.UtteranceSentiment.MAYBE + ) { userWantsGame = true; questionsAnswered++; return Output.sayNothing().setSegue(new Segue(Segue.SegueType.PICKUP,0.5)).setEmotion(RoboyEmotion.HAPPY); @@ -125,99 +128,83 @@ private Output reactToQuestion(Interpretation input) { } if (offeredStory || input.getTokens().contains("story") || input.getTokens().contains("interesting")) { + offeredGame = false; if (StatementInterpreter.isFromList(input.getSentence(), Verbalizer.consent)) { questionsAnswered++; userWantsStory = true; - offeredGame = false; return Output.say(Verbalizer.startSomething.getRandomElement()); } } - askingSpecifyingQuestion = false; + // -- Reset transition proposals + userWantsGame = false; + userWantsStory = false; questionsAnswered++; + // -- Try to interpret input as API request + String answer = inferApiAnswer(input); if (!answer.isEmpty()) { return Output.say(answer); } - // catch jokes + // -- Try to interpret input as Joke request + if (input.getTokens().contains("joke") || input.getTokens().contains("funny")) { return Output.say(PhraseCollection.JOKES.getRandomElement()).setEmotion(RoboyEmotion.positive.getRandomElement()); } - if (input.getTokens() != null && !(input.getTokens().contains("you") || input.getTokens().contains("your"))) { - Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); - - if (parseOutcome == null) { - LOGGER.error("Invalid parser outcome!"); - return Output.useFallback(); - } + // -- Try to interpret input as Memory request - if (parseOutcome == Linguistics.ParsingOutcome.SUCCESS) { - if (input.getAnswer() != null) { - // tell the answer, that was provided by the parser - return Output.say(answerStartingPhrases.getRandomElement() + " " + input.getAnswer()); + try { + if ( input.getPas() != null || input.getTriples() != null) { + // try to use memory to answer + Roboy roboy = new Roboy(getMemory()); + answer = inferMemoryAnswer(input, roboy); + //String answer = String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), inferMemoryAnswer(input, roboy)); + if (!answer.isEmpty()) { + return Output.say(answer); } } - // use a random fact and avoid answer. - if (input.getTokens().size() > 2 && input.isQuestion()) { - Interpretation i = new Interpretation(PhraseCollection.FACTS.getRandomElement()); - i.setSentenceType(Linguistics.SentenceType.ANECDOTE); - return Output.say(i); - } + } catch (Exception e) { + LOGGER.warn(e.getMessage()); + } + + // -- Try to interpret input as parsable question - return Output.useFallback(); + Linguistics.ParsingOutcome parseOutcome = input.getParsingOutcome(); + if (parseOutcome == Linguistics.ParsingOutcome.SUCCESS) { + if (input.getAnswer() != null) { + // tell the answer, that was provided by the parser + return Output.say(answerStartingPhrases.getRandomElement()+" "+input.getAnswer()); + } } - // from here we know that dummyParserResult.equals("FAILURE") - return useMemoryOrFallback(input); + return Output.useFallback(); } @Override public State getNextState() { + State nextState = null; if (userWantsGame) { - userWantsGame = false; - return getTransition(TRANSITION_SWITCH_TO_GAMING); + nextState = getTransition(TRANSITION_SWITCH_TO_GAMING); } - if (userWantsStory) { - userWantsStory = false; - return getTransition(TRANSITION_STORY); + else if (userWantsStory) { + nextState = getTransition(TRANSITION_STORY); + } + else if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + nextState = getTransition(TRANSITION_FINISHED_ANSWERING); } - if (questionsAnswered > MAX_NUM_OF_QUESTIONS) { // enough questions answered --> finish asking + if (nextState != null) { + userWantsGame = false; + userWantsStory = false; questionsAnswered = 0; - return getTransition(TRANSITION_FINISHED_ANSWERING); + return nextState; } return this; } - private Output useMemoryOrFallback(Interpretation input) { - try { - if ( input.getPas() != null || input.getTriples() != null) { - Output memoryAnswer = answerFromMemory(input); - if (memoryAnswer != null) return memoryAnswer; - } - } catch (Exception e) { - LOGGER.warn(e.getMessage()); - } - - return Output.useFallback(); - } - - private Output answerFromMemory(Interpretation input) { - - // try to use memory to answer - Roboy roboy = new Roboy(getMemory()); - - //String answer = String.format(infoValues.getSuccessAnswers(predicate).getRandomElement(), inferMemoryAnswer(input, roboy)); - String answer = String.format("%s", inferMemoryAnswer(input, roboy)); - if (answer.equals("")) { - return Output.useFallback(); - } - return Output.say(answer); - } - private String inferApiAnswer(Interpretation input) { Map pas = input.getPas(); String answer = ""; @@ -295,9 +282,9 @@ private String inferPasAnswer(Map pas, Roboy roboy) { else if (matchPas(pas, new Pair(SemanticRole.LOCATION, "where"), new Pair(SemanticRole.PREDICATE, "live"))) { answer = extractNodeNameForPredicate(Neo4jRelationship.LIVE_IN, roboy); } -// else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { -// answer = "Yo moma says I am a good boy!"; -// } + else if (matchPas(pas, new Pair(SemanticRole.AGENT, "you"), new Pair(SemanticRole.MANNER, "how"))) { + answer = "I am really happy!"; + } else if (matchPas(pas, new Pair(SemanticRole.AGENT, "who"))) { if (matchPas(pas, new Pair(SemanticRole.PATIENT, "you"), new Pair(SemanticRole.PREDICATE, "are"))) { answer = extractNodeNameForPredicate(Neo4jProperty.name, roboy) + " " diff --git a/dialog/src/main/java/roboy/dialog/states/gameStates/GamingTwentyQuestionsState.java b/dialog/src/main/java/roboy/dialog/states/gameStates/GamingTwentyQuestionsState.java index 1550b877..e334fb78 100644 --- a/dialog/src/main/java/roboy/dialog/states/gameStates/GamingTwentyQuestionsState.java +++ b/dialog/src/main/java/roboy/dialog/states/gameStates/GamingTwentyQuestionsState.java @@ -37,7 +37,7 @@ public class GamingTwentyQuestionsState extends State { private final Logger LOGGER = LogManager.getLogger(); - private Akiwrapper aw = new AkiwrapperBuilder().setFilterProfanity(true).build(); + private Akiwrapper aw = null; private Question nextQuestion = null; private Guess currentGuess = null; @@ -58,6 +58,10 @@ public GamingTwentyQuestionsState(String stateIdentifier, StateParameters params @Override public Output act() { + if (aw==null) { + aw = new AkiwrapperBuilder().setFilterProfanity(true).build(); + } + if(!userReady){ return Output.say(PhraseCollection.AKINATOR_INTRO_PHRASES.getRandomElement()); diff --git a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java index 8f7f5476..6886c5e1 100644 --- a/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java +++ b/dialog/src/main/java/roboy/dialog/states/ordinaryStates/PersonalInformationAskingState.java @@ -100,13 +100,14 @@ public Output act() { return State.Output.say(question); } else { - RandomList questions = qaValues.getQuestions(OTHER); + RandomList questions = (RandomList) qaValues.getQuestions(OTHER).clone(); selectedPredicate = OTHER; int idx; do { question = questions.getRandomElement(); idx = questions.indexOf(question); - } while (getContext().OTHER_Q.contains(idx)); + questions.remove(question); + } while (!questions.isEmpty() && getContext().OTHER_Q.contains(idx)); getContext().OTHER_QUESTIONS_UPDATER.updateValue(idx); return State.Output.say(question); } @@ -161,7 +162,7 @@ public State getNextState() { @Override protected Set getRequiredTransitionNames() { // optional: define all required transitions here: - return newSet(TRANSITION_INFO_OBTAINED); + return newSet(TRANSITION_INFO_OBTAINED, TRANSITION_FOLLOWUP); } @Override diff --git a/resources/personalityFiles/OrdinaryPersonality.json b/resources/personalityFiles/OrdinaryPersonality.json index 6664223e..c0101a56 100644 --- a/resources/personalityFiles/OrdinaryPersonality.json +++ b/resources/personalityFiles/OrdinaryPersonality.json @@ -38,7 +38,8 @@ "identifier": "PersonalQA", "implementation": "roboy.dialog.states.ordinaryStates.PersonalInformationAskingState", "transitions": { - "questionAnswering": "QuestionAnswering" + "questionAnswering": "QuestionAnswering", + "followUp": "FollowUp" }, "parameters": { "qaFile": "resources/sentences/QAList.json" @@ -46,13 +47,16 @@ }, { "identifier": "QuestionAnswering", - "implementation": "roboy.dialog.states.ordinaryStates.QuestionAnsweringState", + "implementation": "roboy.dialog.states.devoStates.QuestionRoboyQAState", "fallback": "WildTalk", "transitions": { - "finishedQuestionAnswering": "Farewell", + "finishedQuestionAnswering": "PersonalQA", "loopToNewPerson": "PersonalQA", "loopToKnownPerson": "FollowUp", "switchToGaming": "ChooseGameState" + }, + "parameters": { + "infoFile": "resources/sentences/RoboyInfoList.json" } }, { From 3d916e59ab3fbf9378dc87cb9102facd033c685f Mon Sep 17 00:00:00 2001 From: missxa Date: Mon, 8 Oct 2018 22:41:23 +0200 Subject: [PATCH 146/147] with json phrases for cupgame --- config.properties | 4 +- .../states/gameStates/CupGameState.java | 105 ++++++++++++------ resources/personalityFiles/test/Test.json | 3 + resources/sentences/CupGame.json | 76 +++++++++++++ 4 files changed, 152 insertions(+), 36 deletions(-) create mode 100644 resources/sentences/CupGame.json diff --git a/config.properties b/config.properties index 3ed7f62f..96fbd7c9 100755 --- a/config.properties +++ b/config.properties @@ -15,9 +15,9 @@ ROS_MASTER_IP: 127.0.0.1 ROS_ACTIVE_PKGS: # - roboy_gnlp # - roboy_memory -- roboy_speech_synthesis +#- roboy_speech_synthesis #- roboy_speech_recognition -- roboy_face +#- roboy_face # - roboy_filters #- roboy_vision # - roboy_nodered diff --git a/dialog/src/main/java/roboy/dialog/states/gameStates/CupGameState.java b/dialog/src/main/java/roboy/dialog/states/gameStates/CupGameState.java index 43209de7..eb888648 100644 --- a/dialog/src/main/java/roboy/dialog/states/gameStates/CupGameState.java +++ b/dialog/src/main/java/roboy/dialog/states/gameStates/CupGameState.java @@ -13,6 +13,7 @@ import roboy.logic.StatementInterpreter; import roboy.talk.PhraseCollection; import roboy.talk.Verbalizer; +import roboy.util.QAJsonParser; import roboy.util.RandomList; import java.util.*; @@ -22,6 +23,8 @@ public class CupGameState extends State { + private final String PHRASE_FILE_PARAMETER = "cupGamePhrases"; + private QAJsonParser phrases; private final static List EXIT_REQUEST = Arrays.asList("bored", "stop", "something else", "different", "boring"); private final static List READY = Arrays.asList("done", "ready", "let's go", "play"); private final static String TRANSITION_EXIT = "exit"; @@ -36,24 +39,29 @@ private enum CupGamePhase { } - private final static String FIND_CUPS = "find_cups"; - private final static String GOTOCUP1 = "cup_1"; - private final static String GOTOCUP2 = "cup_2"; - private final static String FINISHED = "finished"; + private final static String FIND_CUPS = "FIND_CUPS"; + private final static String GOTOCUP1 = "GOTOCUP1"; + private final static String GOTOCUP2 = "GOTOCUP2"; + private final static String GOTOCUP3 = "GOTOCUP3"; + private final static String FINISHED = "FINISHED"; private CupGamePhase phase = CupGamePhase.SHUFFLE; public CupGameState(String stateIdentifier, StateParameters params) { super(stateIdentifier, params); + String phraseListPath = params.getParameter(PHRASE_FILE_PARAMETER); + LOGGER.info(" -> Phrases path: " + phraseListPath); + phrases = new QAJsonParser(phraseListPath); } @Override public Output act() { - switch (phase){ - case SHUFFLE: - return Output.say("you shall shuffle the cups, my friend. let me know when you are ready"); - case SCAN: +// switch (phase){ +// case SHUFFLE: +// return Output.say(phrases.getQuestions(phase.toString()).getRandomElement()); +// case SCAN: + if (phase == CupGamePhase.SCAN) { // TODO get response from the state machine // if (getRosMainNode().StartCupGameSmach()) { // if smach start is successful @@ -63,13 +71,21 @@ public Output act() { while(!currentSmachState.equals(FINISHED)) { currentSmachState = getContext().CUP_GAME_SMACH_STATE_MSG.getValue(); if (!currentSmachState.equals(prevState)) { + LOGGER.info("[CupGameState] commenting: " + currentSmachState); switch (getContext().CUP_GAME_SMACH_STATE_MSG.getValue()) { case FIND_CUPS: - getRosMainNode().SynthesizeSpeech("i am looking for cups"); + getRosMainNode().SynthesizeSpeech( + phrases.getQuestions(getContext().CUP_GAME_SMACH_STATE_MSG. + getValue()). + getRandomElement()); break; case GOTOCUP1: getRosMainNode().ShowEmotion(RoboyEmotion.HYPNO_COLOUR_EYES); - getRosMainNode().SynthesizeSpeech("wubba lubba dub dub, doing magic for this cup"); + + getRosMainNode().SynthesizeSpeech( + phrases.getQuestions(getContext().CUP_GAME_SMACH_STATE_MSG. + getValue()). + getRandomElement()); break; } @@ -77,50 +93,71 @@ public Output act() { } // } } - return Output.say("so are you ready to hear the oracle's prophecy?"); - case GUESS: - return Output.say("I think I found it there. So do I win now?"); - case OFFER_REPEAT: - return Output.say("wanna play again?"); - default: - return Output.sayNothing(); +// return Output.say(phrases.getQuestions(phase.toString()).getRandomElement()); +// case GUESS: +// return Output.say("I think I found it there. So do I win now?"); +// case OFFER_REPEAT: +// return Output.say("wanna play again?"); +// default: +// return Output.sayNothing(); } + return Output.say(phrases.getQuestions(phase.toString()).getRandomElement()); } @Override public Output react(Interpretation input) { exitOnRequest(input.getSentence()); - + Boolean pickSuccessAnswer = true; + CupGamePhase next = CupGamePhase.EXIT; switch (phase) { case SHUFFLE: if (StatementInterpreter.isFromList(input.getSentence(),READY)) { - phase = CupGamePhase.SCAN; - return Output.say("Alright. Let me check with my superpower soli where did you hide the ball"); + next = CupGamePhase.SCAN; + break; +// return Output.say("Alright. Let me check with my superpower soli where did you hide the ball"); } else { - return Output.say("Hm, seems you are not done yet. I give you another try"); + pickSuccessAnswer = false; + break; +// return Output.say("Hm, seems you are not done yet. I give you another try"); } case SCAN: - phase = CupGamePhase.GUESS; - return Output.useFallback(); + next = CupGamePhase.GUESS; + break; +// return Output.useFallback(); case GUESS: - phase = CupGamePhase.OFFER_REPEAT; - return Output.say("ha-ha."); + next = CupGamePhase.OFFER_REPEAT; + break; +// return Output.say("ha-ha."); case OFFER_REPEAT: if (StatementInterpreter.isFromList(input.getSentence(),Verbalizer.consent)) { - phase = CupGamePhase.SHUFFLE; - return Output.say("Here we go again then!"); + next = CupGamePhase.SHUFFLE; +// return Output.say("Here we go again then!"); } - else - phase = CupGamePhase.EXIT; - return Output.say("I believe you've had enough of my magic"); - case EXIT: - return Output.say("Wanna stop playing? Sure, if you say so."); - default: - return Output.useFallback(); + else { + next = CupGamePhase.EXIT; + pickSuccessAnswer = false; + } + break; +// return Output.say("I believe you've had enough of my magic"); +// case EXIT: +// return Output.say("Wanna stop playing? Sure, if you say so."); + } + + Output answer; + + try { + answer = Output.say(pickSuccessAnswer ? phrases.getSuccessAnswers(phase.toString()).getRandomElement() : + phrases.getFailureAnswers(phase.toString()).getRandomElement()); + } + catch (Exception e) { + answer = Output.useFallback(); } + phase = next; + return answer; + } private void exitOnRequest(String input) { diff --git a/resources/personalityFiles/test/Test.json b/resources/personalityFiles/test/Test.json index fbefeff0..767f1002 100644 --- a/resources/personalityFiles/test/Test.json +++ b/resources/personalityFiles/test/Test.json @@ -7,6 +7,9 @@ "transitions": { "next": "CupGame" }, + "parameters": { + "cupGamePhrases": "resources/sentences/CupGame.json" + }, "fallback": "WildTalk" }, { diff --git a/resources/sentences/CupGame.json b/resources/sentences/CupGame.json new file mode 100644 index 00000000..2030b639 --- /dev/null +++ b/resources/sentences/CupGame.json @@ -0,0 +1,76 @@ +{ + "SHUFFLE": { + "Q": [ + "you shall shuffle the cups, my friend. let me know when you are ready" + ], + "A": { + "SUCCESS": [ + "Alright. Let me check with my superpower soli where did you hide the ball" + ], + "FAILURE": [ + "Hm, seems you are not done yet. I give you another try." + ] + } + }, + "FIND_CUPS": { + "Q": [ + "i am looking for cups" + ] + }, + "SCAN": { + "Q": [ + "so are you ready to hear the oracle's prophecy?" + ], + "A": { + "SUCCESS": [ + "Hold your breath, ladies and gentlemen!" + ] + } + }, + "GOTOCUP0": { + "Q": [ + "wubba lubba dub dub, doing magic for this cup 0" + ] + }, + "GOTOCUP1": { + "Q": [ + "wubba lubba dub dub, doing magic for this cup 1" + ] + }, + "GOTOCUP2": { + "Q": [ + "wubba lubba dub dub, doing magic for this cup 2" + ] + }, + "GUESS": { + "Q": [ + "I think I found it there. So do I win now?" + ], + "A": { + "SUCCESS": [ + "ha-ha" + ] + } + }, + "OFFER_REPEAT": { + "Q": [ + "wanna play again?" + ], + "A": { + "SUCCESS": [ + "Here we go again then!", + "let's do it again" + ], + "FAILURE": [ + "I believe you've had enough of my magic" + ] + } + }, + "EXIT": { + "A": { + "SUCCESS": [ + "Wanna stop playing? Sure, if you say so." + ] + } + } +} \ No newline at end of file From ab439635cc540b76395e91618b1faaf9d87b3791 Mon Sep 17 00:00:00 2001 From: missxa Date: Tue, 9 Oct 2018 00:36:18 +0200 Subject: [PATCH 147/147] not waiting on enter in CM --- dialog/src/main/java/roboy/dialog/Conversation.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dialog/src/main/java/roboy/dialog/Conversation.java b/dialog/src/main/java/roboy/dialog/Conversation.java index 781697c1..52954ee6 100644 --- a/dialog/src/main/java/roboy/dialog/Conversation.java +++ b/dialog/src/main/java/roboy/dialog/Conversation.java @@ -97,11 +97,11 @@ public void run(){ } else {//if this is an initial start actions = personality.startConversation(); logger.info("############# Conversation started ############"); - try { - System.in.read(); - } catch (IOException e) { - logger.error(e.getMessage()); - } + // try { + // System.in.read(); + // } catch (IOException e) { + // logger.error(e.getMessage()); + // } } while (isRunning) {