Note: Deprecated!

No, this post doesn’t explain what AICI is, check here to read more about that topic. Today, I’m attempting to explain how to add the functionality to AICI so that it can respond to the statement ‘What’.

As previously mentioned, there are a number of stagesimage that we need to get through to go from input to output. The first is the scan phase, which translates the letters into words, numbers and signs. When this is done, we try to find sentence constructs, like the subject, verb,…. This is matched to a frame, which determines the action that needs to be triggered. Finally, the action might also activate an attribute, but this is out of this post’s scope. So let’s make our network respond to ‘what’.

Recap:
First check if the flows can parse the statement: both scanner and grammar. Next comes the frame and finally the action and attribute.

Scanner

image This stage will transform the letters into a single word ‘what’, when it reaches the ‘Sentence’ flow. The result of this stage is a cluster, with the meaning ‘Sentence’ (the same as the name of the flow that produced the result). The child will be a textneuron, representing ‘what’

‘What’ is a simple word, which is already handled by the scanner, so no worries there. If you are wondering how words are parsed, take a look at the preceding image, which is the flow for a word. Underlined words are references to other flows,  words that aren’t underlined represent static values. Curley brackets mean a repetition, strait ones define an option. If a conditional has a vertical line after it’s first bracket, a selection is required, this is valid for both repetitions and loops. This basic syntax was inspired by parser generator languages like Coco/R, Lex and Yacc.

So in the above example, a word can start with number (a sub flow), letters or capital letters. A word must always have at least 1 letter or capital, may have middle numbers and can end with a number or an alpha numeric.

Note: at the time of writing, there is still a little optimization required to get words with many mixed digits and letters working properly.

Grammar

Moving on to the grammar section. This is also defined in a flow editor, called ‘English grammar’. So open this (in the ‘Flows’ folder) and immediately select the ‘Interrogative pronouns’ (if you are, like me, not that very fluent in English grammar, and could use a mental aid now and then, there are plenty of resources on the net, check out Google dictionary, the English club, Wikipedia,…). As you can see, our ‘what’ is already in the ‘Interrogative pronouns’ flow.  So perhaps no extra work for the grammar stage as well? As it turns out, this will be the case. For those who want some more details though, here goes:

If we  look more closely to the flow name itself (on the first picture), we can see there is an overlay ‘FL’, which is short for flow-code. If you hover over the ‘FL’, you get a tooltip with more info. This says ‘References code that is executed when the item is recognized in a data flow’. This means that the flow does something when it is recognized in an input stream. Usually, it formats the recognized data in such a way that the next stage knows what type of sentence part it was. If there is no ‘FL’ overlay, it means that the data will be recognized in the input stream, but no extra actions are taken, when found. image So the input is simply copied over to the result which leaves it unrecognizable. The ‘Reflective pronouns’ are a good example of a flow without overlays.

But what to do in such a case? Before you start to code, first see who uses the flow anyway, maybe they do something with it.

Tip:
Use F8 to browse all relationships of a neuron.

If you select the ‘Reflective pronouns’ Flow (click 2 times, the first time we automatically focus on the editor) and press F8, you can see which clusters it belongs to (and some other stuff too, not important for now). In this case it’s only 1 cluster: a conditional part (we need flows), so if we drill down a bit further, until we eventually get to the ‘Object flow’. This is used to find the object of a sentence. These flows do have an overlay (in the editor), and tag the recognized data. Usually, this is enough. Only when you need to tag this sub result as well, do you need to add some code, which is generally not the case.

Anyway, to get back to our ‘Interrogative pronouns’, lets see what the attached code does, and open the code editor (right-mouse button on the flow, and select ‘View code’).image 3 Most often, as with this flow, it simply duplicates the content of the ‘Result’ variable (which always references a cluster at this stage), and removes all outgoing links on this duplicate (sometimes, result clusters can link to some extra data which we don’t want,  but is used by the algorithm) and stores this duplicate back into the result cluster.

To better explain what this actually means, lets take the following input stream: ‘you are here’. After the scan stage, we have a result that looks like image 5: a cluster with meaning ‘sentence’ and 3 text neurons as children. Once the grammar stage is done transforming this dataset, it looks more like image 6: a cluster with meaning ‘statement’  and 3 children again, but with some more info. The first 2 represent the agent (sentence subject) and the verb, both flows use the previously described transformation code. The last child is the object representation of the textneuron ‘here’. It is the result of an adverb that was recognized somewhere in a flow, which didn’t transform the data, so content simply got copied to the final result.

image 4

image 5


AICI:
When a flow has been recognized, the ‘flow-code’ callback of the flow is executed. The ‘Result’ variable will contain a cluster with the flow as it’s meaning and the recognized data as it’s children.

AICI:
Use the ‘TransformFlowResultCallback’ cluster as a default callback for flows so the result can be recognized by the frames.

Frames

Up until now, not much had to be done, with the frames though, this will change, here we actually need to do something to get it working. Frames can be seen as the conduit between the front (scanner/grammar) and back (actions/attributes). A frame defines which sentence parts it can contain and their order. Multiple orders can be defined, so that you can have the same sentence parts to form a statement or a question. You can also have optional parts, to make frames even more flexible. Each order is defined in a frame sequence. This is also able to render itself back as output, completing the circle.

Just like for the scanner and grammar, the network is already capable to extract the correct frame sequence, based on the set of already defined frames and their sequences (so if it’s not yet defined, the network can’t recognize it). Once, the sequence is found, the framework performs some calls to attached code that you have to provide so that the network also knows what to do with the input statement. The following code blocks can/should be attached to a frame sequence:

  • ExtractAction: this code block is called to determine which action(s) the frame should trigger. Multiple actions are allowed, in which case each will be triggered in the order as they were returned. This is done through the variable ‘ExtractedActions’.  The attachment is required.
  • ConvToKnowledge: this code block should transform the result data of the grammar parse, into the input data for the actions and return this cluster through the variable ‘KnowledgeConv’. (edit 11/July/2010) The attachment is required. This attachment is optional. If you define a value for the new column ‘ResultType’ in the frame editor and the ‘role’ neuron has a ‘ConvToKnowledge’ code cluster, the network can automatically generate the result cluster for an entire frame sequence, and so this code is no longer required. You can override the auto rendering by defining this code cluster.
  • RenderCode: This code block is called by an action to render output according to the structure of the frame. The output to render is found in the ‘CurrentFrom’ system variable. The format of the data is the same as that of ‘ConvToKnowledge’. The attachment should only be defined if there is an action able to call it is output. This is not always the case, for instance, frames that deal with ‘unknown’ word types, don’t need to be generated.

Recap:
A frame determines the action to execute, provides the data for the action and is able to render data provided by an action.

As previously mentioned, a frame needs to prepare the data for the action. This should be a cluster without meaning (it will automatically be assigned, once the correct frame sequence is found, and will eventually indicate that the cluster is an input statement). The content of this cluster needs to be well defined, so that the action can handle it correctly. In theory, you can use any type of structure that you want, as long as the action uses the same. In practice, it’s best to use a predetermined structure, shared by all the actions and frames, for easy sharing of default actions. So here’s a small overview of the possible content:

  • The first child neuron should indicate the time value: current, passed or future. Though most actions don’t specifically expect it on the first pos, all current frames use this.
  • The child list can also contain a ‘not’ neuron, to indicate that the statement should be interpreted as a negation.
  • The sentence agent should be stored in a cluster with meaning ‘who’
  • You can store the sentence object in a cluster with meaning ‘what’ or ‘value’, depending on the situation. Sometimes, ‘what’ can be extracted, from ‘who’, a previous statement or the ‘value’.
  • a cluster with meaning ‘verb’ can be used for sentences that a verb. Originally, this wasn’t done for the basic verbs like ‘to be, ‘to have’, since it can be inferred from the action that is triggered. However, it can always be useful to take the actual verb that was used to the action, in case it needs to do some analysis on the ‘subject’ indicator of the word. For instance, ‘am’ is usually for ‘I’.

Frames can play a little bit with these structures: fill in missing data, switch who, what and value,… Though most of the code in the current frame sequences is shared: if there is an agent in the sentence, 9 out of 10 times it is transformed in the same way, so lots of copy paste (or drag drop) possibilities here. Also perhaps for future automatic learning.
(Update 11/July/2010) In the new version, it is no longer required to provide this code for each frame. It is moved to the level of the ‘role’ (as defined in the frame element), usually these are the flows like ‘agent’ or ‘be verb’,…

The translation results for the input ‘i am jan’. In the final stage, ‘what’ is filled in by the frame.image

For our example, we will have to create a new frame to handle the input ‘what’. Since this is a sentence that only contains an interrogative pronoun, we should probably best put it in the ‘Pronouns’ frame editor together with all the other pronouns (for easy lookup later on). So open up this editor (double click on the editor’s name in the project view), or create a new one if it doesn’t yet exist (the button that looks like a rectangle, you know ‘frame’).

To create a new frame, click on the button with the square, on the editor (tooltip: Create a new frame) or press Ctrl+Shift+F and provide a name for the new frame. Lets call it ‘what frame’. To quickly build the frame, you can drag neurons from the toolbox, thesaurus, flow,… and drop them on the frame editor. To start with, find an ‘Interrogative pronoun (to get it in the explorer, press ‘F4’),  and drop it somewhere in the top part to create a new frame element. This indicates that the sentence should contain an ‘interrogative pronoun’ sentence part.

Tip:
To quickly sync the explorer with the currently selected item, press F4 from anywhere in the application.

image

Make this element an evoker. Only evoker elements are used to find all possible frame candidates. This is a small optimization for the search algorithm. Each frame should have 1 evoker element. Usually, this is the verb, but in this case there isn’t one so we use what’s available.

At this point, we have a frame that will be activated for all sentences that contain an interrogative pronoun, like: what, who, where, when,… We need to further specify that we only want to respond to ‘what’. This is done by adding a filter to the frame element. So make certain that the element is selected, and from the thesaurus, drag ‘what’ to the bottom part of the frame editor and drop it there. this will automatically create a thesaurus filter for the currently selected relationship. So if ‘what’ had one or more children in the thesaurus, these would also be valid for the filter. In this case we don’t have that, so the relationship field could have been left empty.

Also notice the ‘RestrictionMofidierInclude’ in front of the filter. This is to indicate that input values that contain the filter value are allowed. If this was set to ‘RestrictionModifierExclude’, only sentences that wouldn’t contain ‘what’ would be allowed (so, where, who, when,..).

Finally, there is also the small button. When this is checked, the content of the sentence part should only contain what is defined in the filter, and no other words. If not checked, other words may still be present. This is an important little property which I almost got wrong starting out this post. Do we want to handle sentences like ‘what color’, ‘what time’, what the hell’,  ‘what in the name of sweet Jesus’, or only ‘what’. If you go back to the very first image, you can see that it’s allowed to put some words after the pronoun. This is to allow correct recognition of sentences like ‘what size are you’ where ‘you’  is the subject. This means that the grammar will also recognize ‘what color’ as an interrogative pronoun. It turns out this is actually ok for us (see frame sequence code). So we leave this not checked to allow other words in the flow result.

The Frame sequence

Now that the frame has been defined, lets move on to the sequence. To create this, press the ‘Add frame sequence button’, or ‘Shift+Ctrl+S’ and provide a name for the sequence (make certain that the frame editor is active when pressing the button, otherwise it won’t be active). Lets call it ‘What statement’. You create the sequence by moving the frame elements from the left part to the right part of the editor. You can use the arrow buttons for this. Multiple elements can be moved at the same time. The up and down can be used to change the order.

image

All pretty strait forward. The cool part comes in the code editor. To open this, select the frame sequence in the editor (or somewhere else, like in the explorer), open the context menu and select ‘view code’. First, lets make certain that this new code editor is also available from the project. All you have to do is open the context menu on the bottom tab items of the code editor, and press the ‘Show in project’ menu item. This will add the neuron to the currently selected project folder (or root if there is non selected). So, when you do this, it’s best that the correct folder is selected first. If you forgot to select the one you wanted, you can always still move it later on.

Tip:
To add a code editor to the project view, right click on the bottom tab items and select ‘Show in project’. The item will be added to the currently selected project folder.

By default, there are only a limited number of pages available in the code editor. The rules and actions pages are always available (though the code clusters are only created when you actually drop something on them). But not the ones that we need. Those will have to be added manually. So open the context menu, again on the bottom tab items, and select the required pages listed under ‘add new code page’. We need ‘ExractAction’, ‘ConvToKnowledge’ and ‘RenderCode’.

Tip:
You can add any type of code page to a code editor, make certain that the required neuron is tagged as ‘a default meaning neuron’ in the explorer. Open the context menu on the bottom tab items of the code editor and select the new page from the ‘Add new page’ menu item.

Frame sequence code

RenderCode: The render code for the ‘what’ statement as displayed in the above picture is very simple, but not completely correct (see below), we basically write “what?”. I added the question mark, just to show a little trick of the text sins: When you send them multiple neurons, by default, each one will be rendered on it’s own line. To group neurons together, use the ‘BeginTextBlock’ and ‘EndTextBlock’ neurons.  These are recognized by the text sin as special formatting tokens.

We use the ‘output’ statement to send data to a sensory interface. The fastest way to declare this expression, is by dragging it from the toolbox. This has 2 pages: one for common expressions like clusters, assignments and commonly used neurons, and a second page, exclusively for all the instructions.

Tip:
You can quickly expand or collapse all toolbox items from their context menu. All instructions display a tooltip with a short description, the expected parameters and output.

The first argument to all the output statements is always the same: ‘OutputSin’. This is a global that is filled in by the framework and points to the sensory interface to which the output should be sent. You can also hardcode which sensory interface it needs to be sent to, but that is less flexible. This way, you can actually have multiple text-sins in 1 network and have multiple users chat at the same time. As a small side note: because the output statement can take any number of arguments, we could have written it shorter: in 1 statement. This wasn’t done because I forgot, before taking the screenshot ;-)

Also, if you look closely, some of the statements appear to have a double border, while others don’t. This is to indicate that it is used multiple times. This is important to keep in mind, if you modify these statements, you are also changing them in some other part of the code. When dragging code around, it is not like text that you duplicate. When you drag and drop, there is no deep copy, only a new reference made. This can keep the code size pretty compact, allows for some deep future analysis and most importantly should allow for easy auto generation later on. But it is something to keep in mind while changing code.

Caution:
Statements with a double border are used multiple times, be careful while modifying these.

The complete render code looks something more like the following image. This is able to handle not only ‘what’, but also ‘what color’, ‘what on earth’,… Looks scary? Don’t worry, it’s actually very simple, and most of the code is copied over from other parts anyway.image

The second statement, the big yellow monster, is actually a query, who’s result is stored in the ‘what’ variable. ‘Get children filtered’ returns all the child neurons of a cluster that meet a specified filter. In this case, we only want neuron clusters that have a cluster-meaning equal to ‘sg:What’, in other words, we want to retrieve the ‘what’ part from the input. (no surprise there).
The next statement is an ‘if’ construct: if we found something (count(what) > 0), render the contents of the ‘what’ variable, using the ‘Render object’ code block. If there is no cluster found, simply render ‘what?’. The ‘what’ variable isn’t passed over to the ‘Render object’. This is not possible and not required: a code block doesn’t have it’s own variable space, so all the variables maintain their value, hence, the ‘what’ variable is passed along implicitly.

And thus, you have mastered your third little peace of code already ;-)

ConvToKnowledge: (update 11/July/2010: this code cluster is no longer required, but is still allowed) The transformation for ‘what’ is also fairly strait forward. This  type of attached code tends to have a imagefairly similar structure across frame sequences. In this one, we check if the interrogative pronoun contained anything other than ‘what’. We do this by checking if it has more than 1 child. When this is the case, we create a new cluster, assign it the meaning ‘sg:what’ (this is a tag operation) and we copy all the children, except the first, from the cluster that we found to the newly created one. Finally, we add this new cluster to our result. We don’t copy the first child, since that is the the ‘what’. We presume this, if you know any situation in which it is not the case, the code needs to be updated to something more secure (remove the actual ‘what’ neuron).

ExtractAction: Lastly, we also need to provide some code that returns the action we want to execute. Before we can do this, we actually need to know which are the possible actions that can be performed.

So lets try and come up with a few possible dialogs, so we can analyze the different possibilities. Here’s what I came up with on short notice:

PC: I have hair
You: what
PC: I have hair –> this is a simple repetition of what was last said.

PC: I am in the black room
You: what color
PC: black-> return the first value that was found through an ‘is a’ relationship (black is a color), from any of the words of the prev statement.
You what room
PC: the room of your house –> return more relationship info on the actual result of ‘the black room’, if there is any. In this case, we know the owner of the house.

You: what the fuck
PC: No swearing please –> catch a special case.

So Basically, I have 3 different groups of the conversations (if you can think of more, le me know). In the first case, when the user simply asks ‘what’, we return the last output statement. The 3th conversation, when the user wants to express surprise/disagreement through an insult, we return a standard message to keep it clean. Finally, in the middle example, some analysis is done on the previous statements, to find a proper match. We can check the actual words, see if there is an ‘is a’ relationship to be found. In this  case, the user might have forgotten the actual value, but still remembered the attribute. The user could also be requesting more info about something, in which case we need to return some more links if there are any.

Exactly how you pour this information into actions, is a bit up to you. Me, I would go for 3 different actions. In fact, I would imagehandle the last conversation type (aka: ‘what the xxx’) as a special case in a different frame, so we can filter on these specific word groups. I guess that would be a good exercise for you. The first and second should be handled by this frame, so these are 2 new actions that should be returned by our frame sequence. To determine the exact action that needs to be returned, we can use a similar ‘if’ construct as in the ‘ConvToKnowledge’ code cluster: when there is more than a ‘what’ in the input data, use ‘Find Prev out statement’, which does the heavy searching. If there is only ‘what’ in the input data, use the light weight ‘Return last out statement’. To return the action we want to execute, simply assign it to the ‘ExtractActions’ variable, like in the statements to the right.

Recap:
Return your actions in the ‘ExtractedActions’ variable.

Actions

Rejoice, the end of this post is almost in sight: Actions, the final step. As already mentioned, we are going to need 2 actions, though to keep the post a bit within the limits of sanity, I am going to restrict the explanations to the simplest action. The more complex search algorithm needs another one of these posts to explain it all. In fact, I still have to finish it myself. Perhaps, I’ll leave it like it is, as an exercise for you ;-)

Before we start to create our action though, perhaps a small word about actions in general. These are actually nothing more then regular neurons with 2 different types of code clusters attached. The first type contains code that is called when the action is executed. You can specify a different code cluster for all the different states that the action needs specific responses for. The image default state is ‘Normal state’, which is currently the only one defined, but you can create and set as many of your own states as you want. The current state of the network is defined as a link between the text sin using the meaning ‘state’ to the current value (see image). This means that you can have as many concurrent network states as communication channels. Also, when an action doesn’t have an implementation for the current state, or when the text-sin doesn’t define a state, the fallback ‘Normal state’ is used.

The second type of code clusters that are attached to actions, are used during the conversation, to check for and handle possible responses to questions. That is, some actions require some sort of response. These types of actions need to check if a response is valid, determine if an action is a valid response action and can also specify extra ‘response’ code. This though is again far outside the scope of this post, so lets leave  it at that.

Back to our example, we still need to create the action. Since this is just a neuron, there are many different ways of doing this. If you are already in the correct project folder, a quick way is to use the toolbar button above the project overview, called ‘Create a new neuron with attached code’. This will create a neuron, open it’s code editor and add it to the project. If you press F2, you can change the name (make certain the project node has keyboard focus). To add the ‘Normal state’ code page, just do the same as with the frame sequences: open the context menu on the bottom tab items, select ‘add new code page’ and click on ‘Normal state’.

imageAnd that’s how the action should eventually look like. It’s a nice bit of code to end with, with just a little bit more meat to look at. Though in the end, it’s still very strait forward. Before we delve into the specifics of the code, perhaps first a small word about the conversation log, since that’s our primary data source in this action.

The conversation log is a cluster, attached to the text sin for which it is keeping track of the previous statements made by the network and the user of the text sin. This means that the network has a log cluster for each active user. It keeps track of a 1 to 1 conversation. A Part of the content of the log consists out of the clusters that we created in the frame sequence, in the ‘ConvToKnowledge’ code. These have a cluster-meaning of ‘in’. The other part consists out of the clusters that were generated in the actions, as output.  These are labeled ‘out’. Both ‘in’ and ‘out’ children still have a link to the action(s) that was/were executed so we know what they triggered.

When we translate this information to our action, we get something like the previous picture. Basically, we try to retrieve the log from the ‘OutputSin’ global. We have already encountered this global.  It is the one that is always pointing to the Text-sin for whom we are currently processing, remember. If this doesn’t have a log, something is wrong, so we show a message to the user, log it as an error (this is useful for the debugger) and exit the link. We exit the link and not the neuron or the entire processor, since there might still be other actions that need to be executed.
If there is a log file, we walk through each log entry, from back to front, using a counter and the ‘GetChildAt’ instructions. You can do this in different ways (using the reverse instruction combined with 1 or more selects, for instance). I choose this way, since I think it’s the fastest solution for this situation.
If we find an item, with a cluster meaning of ‘out’, we simply push it back on the stack and exit the loop. By putting the cluster back on the stack, we actually let the network execute the action again, since it is still linked to the data. Note that we decrease the counter each time that we don’t have an item with meaning ‘out’. The ‘-‘ instruction might be written a bit strange at first. You can probably best think of it as a polish notation. This is actually a result of the fact that ‘-‘ is just an instruction and at present, all instructions have the same UI input format. And that’s it.

Ok, slowly breed in, and out. You’ve just reached the top of the Himalayas (or something comparable). It’s done, you’ve absorbed all the info, and your still alive. Time now to let it all breed a little, let it digest, and sleep on it a bit. Don’t worry about it, it will come to you too.

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

   
© 2012 Neural Network Design blog Suffusion theme by Sayontan Sinha