An Emotional Machine: Emotives and Mood

The emotives field in the GDF is used to give the agent emotional data. It is used for automatic goal-setting, reinforcement learning, and determining the desirability of an outcome. Examples of emotional data would be cost and time. In order for your agent to learn emotional data you have to populate the emotive field in the GDF with the name of the emotive, and then give it a value; emotives accept non-vector numbers, positive or negative.

Furthermore, emotives can be used to help solve multivariate problems. Let’s start by using one emotive, then later on in the tutorial we will show you how solve problems with multiple emotives.

If starting from here, lets initialize the agent

[1]:
from ia.gaius.agent_client import AgentClient
agent_info = {'api_key': 'ABCD-1234',
              'name': '',
              'domain': 'gaius-api:80',
              'secure': False}

agent = AgentClient(agent_info)
agent.connect()
agent

# Let's use only one node
ingress_nodes = ['P1']
query_nodes   = ['P1']

agent.set_ingress_nodes(ingress_nodes)
agent.set_query_nodes(query_nodes)
[1]:
[{'id': 'p46b6b076c', 'name': 'P1'}]
[ ]:

[2]:
agent.clear_all_memory(nodes=ingress_nodes)
[2]:
'all-cleared'
[3]:
sequence_1 = [{"strings": ["hello"], "vectors": [], "emotives": {'utility': 10}},
              {"strings": ["world"], "vectors": [], "emotives": {}}]

sequence_2 = [{"strings": ["goodbye"], "vectors": [], "emotives": {'utility': -10}},
              {"strings": ["cruel"], "vectors": [], "emotives": {'utility': -40}},
              {"strings": ["world"], "vectors": [], "emotives": {}}]

If we decide that the two sequences above are polar opposites in sentiment, and each have their own magnitude in value, we can encode that information as a “emotives” value in the GDF. In the above sequences we have named the emotive, “utility”.

For people, the two sequences provided above have very different emotional context around them. “hello world” may be a happy or neutral sentiment. “goodbye cruel world”, however, has a very negative connotation to it.

NOTE: the positioning of the emotives values within the sequence is irrelevant. We could have just as easily put them in the last event of the sequence, or even created a new event just to supply a emotive value:

[4]:
sequence_1 = [{"strings": ["hello"], "vectors": [], "emotives": {}},
              {"strings": ["world"], "vectors": [], "emotives": {'utility': 10}}]

sequence_2 = [{"strings": ["goodbye"], "vectors": [], "emotives": {}},
              {"strings": ["cruel"], "vectors": [], "emotives": {}},
              {"strings": ["world"], "vectors": [], "emotives": {'utility': -50}}]

# or

sequence_1 = [{"strings": ["hello"], "vectors": [], "emotives": {}},
              {"strings": ["world"], "vectors": [], "emotives": {}},
              {"strings": [], "vectors": [], "emotives": {'utility': 10}}]

sequence_2 = [{"strings": ["goodbye"], "vectors": [], "emotives": {}},
              {"strings": ["cruel"], "vectors": [], "emotives": {}},
              {"strings": ["world"], "vectors": [], "emotives": {}},
              {"strings": [], "vectors": [], "emotives": {'utility': -50}}]
[5]:
agent.show_status(nodes=ingress_nodes)
[5]:
{'PREDICT': True,
 'SLEEPING': False,
 'emotives': {},
 'last_learned_model_name': '',
 'models_kb': '{KB| objects: 0}',
 'name': 'P1',
 'size_WM': 0,
 'target': '',
 'time': 0,
 'vectors_kb': '{KB| objects: 0}'}
[6]:
# Learn the 1st sequence
for event in sequence_1:
    agent.observe(data=event,nodes=ingress_nodes)

agent.learn(nodes=ingress_nodes)
[6]:
'MODEL|7d0678ba6305341ce0d25133ab086208656a562f'
[7]:
# Learn the 2nd sequence
for event in sequence_2:
    agent.observe(data=event,nodes=ingress_nodes)

agent.learn(nodes=ingress_nodes)
[7]:
'MODEL|3b5c9cdc4424988308922d2ec8c7bc06b7c6ac21'
[8]:
# Let's observe the single event with "hello" in the strings section to get a prediction
[9]:
agent.observe({"strings": ["hello"], "vectors": [], "emotives": {}})
[9]:
'observed'
[10]:
agent.get_predictions(nodes=query_nodes)
[10]:
[{'confidence': 1,
  'confluence': 0.4,
  'emotives': {'utility': 10},
  'entropy': 0.464385629,
  'evidence': 0.5,
  'extras': [],
  'fragmentation': 0,
  'frequency': 1,
  'future': [['world']],
  'grand_hamiltonian': 0.232192814,
  'hamiltonian': 0,
  'itfdf_similarity': 1,
  'matches': ['hello'],
  'missing': [],
  'name': '7d0678ba6305341ce0d25133ab086208656a562f',
  'past': [],
  'potential': 3.5,
  'present': [['hello']],
  'similarity': 0.666666687,
  'snr': 1,
  'type': 'prototypical'}]

The get_predictions command gave back one sequence as a prediction. This sequence has an emotive with the name of “utility” of value 10 in its prediction object.

[11]:
agent.get_predictions(nodes=query_nodes)[0]['emotives']
[11]:
{'utility': 10}

NOTE: Emotives allow room for decision making based on emotions. Humans make decisions based on emotions all the time but the outcome depends on their mood. A user can set a mood for each emotive in order to give them weights, which will affect the overall utility. More on this later when we create a recommendation engine based on different emotions.

[ ]: