Search code examples
artificial-intelligenceaiml

How can I get a key_value from a specific mapped_value in AIML?


I'm starting to learn some AIML and I'm quite lost at this point.

I'm working with maps but I can't think of an algorithm to solve this problem. Let's say I have a map in which I'm storing my friends' hair color. Something like Markus:brown.

Now let's say I want to get all the names whose hair color is brown. Something like:

Human: Could you tell me the names of my friends whose hair color is brown?

Robot: Markus Kevin Thomas

Edit: Doing some research I found that many users create a the oposite map, I mean, person:hair, hair:person. But if I have different people with the same color, would the map return the first one? How could I get all of them?

How could I do that?

Thanks in advance.


Solution

  • You can't really do this using maps unless you set up a map like this:

    [
        ["brown", "Markus, David, Thomas"], 
        ["black", "Stephen, Paul"], 
        ["blonde", "Simon"]
    ]
    

    This could be a lot of manual work and not really practical. When I work with simple databases like this, I set up each entry in its own category:

    <category>
        <pattern>XFRIEND 1</pattern>
        <template>
            <think>
                <set name="friend">Markus</set>
                <set name="hair">brown</set>
                <set name="eyes">blue</set>
                <set name="likes">pizza</set>
            </think>
        </template>
    </category>
    
    <category>
        <pattern>XFRIEND 2</pattern>
        <template>
            <think>
                <set name="friend">Kevin</set>
                <set name="hair">black</set>
                <set name="eyes">brown</set>
                <set name="likes">burgers</set>
            </think>
        </template>
    </category>
    
    <category>
        <pattern>XFRIEND 3</pattern>
        <template>
            <think>
                <set name="friend">Thomas</set>
                <set name="hair">brown</set>
                <set name="eyes">green</set>
                <set name="likes">burgers</set>
            </think>
        </template>
    </category>
    
    <category>
        <pattern>XFRIEND 4</pattern>
        <template>
            <think>
                <set name="friend">David</set>
                <set name="hair">black</set>
                <set name="eyes">blue</set>
                <set name="likes">burgers</set>
            </think>
        </template>
    </category>
    

    And then create a category which will scan and check each entry:

    <category>
        <pattern>XSCANFRIENDSDATABASE</pattern>
        <template>
            <think>
                <set name="list">Results:<br/></set>
                <srai>XFRIEND 1</srai>
                <srai>XCHECKMATCH</srai>
                <srai>XFRIEND 2</srai>
                <srai>XCHECKMATCH</srai>
                <srai>XFRIEND 3</srai>
                <srai>XCHECKMATCH</srai>
                <srai>XFRIEND 4</srai>
                <srai>XCHECKMATCH</srai>
            </think>
            <get name="list"/>
        </template>
    </category>
    

    Now we have our database set up, let's see how we can use it. I want to know, "Who has (whatever coloured) hair". We can do this with this category:

    <category>
        <pattern>WHO HAS * HAIR</pattern>
        <template>
            <think>
                <set name="searchfor"><star/></set>
    
                <learn> 
                <category>   
                <pattern>XCHECKMATCH</pattern>   
                <template>
                    <condition name="hair">
                        <li><value><get name="searchfor"/></value>
                        <set name="list"><get name="list"/><br/><get name="friend"/></set>
                        </li>
                    </condition>     
                </template> 
                </category> 
                </learn>
    
            </think>
            <srai>XSCANFRIENDSDATABASE</srai>
        </template>
    </category>
    

    So in your query, "Who has brown hair", the predicate "searchfor" is set to "brown", as that is what we are searching for.

    We then use the <learn> tag to set up a temporary category called "XCHECKMATCH" which looks at the value of "hair" in each of the entries in our database and compares it to "searchfor". If it matches, add it to the list.

    Once set up, we scan the database and display the results.

    Human - Who has brown hair?
    Bot - Results:
    Markus
    Thomas

    As an advanced use of this, we can also check for more than one item. For example, "Who has black hair and likes burgers?"

    <category>
        <pattern>WHO HAS * HAIR AND LIKES *</pattern>
        <template>
            <think>
                <set name="searchfor"><star/> <star index="2"/></set>
    
                <learn> 
                <category>   
                <pattern>XCHECKMATCH</pattern>   
                <template>
                    <think><set name="found"><get name="hair"/> <get name="likes"/></set></think>
                    <condition name="found">
                        <li><value><get name="searchfor"/></value>
                        <set name="list"><get name="list"/><br/><get name="friend"/></set>
                        </li>
                    </condition>     
                </template> 
                </category> 
                </learn>
    
            </think>
            <srai>XSCANFRIENDSDATABASE</srai>
        </template>
    </category>
    

    In this example, "searchfor" becomes "black burgers". We set up a new predicate called "found" (what the database has found). This is made up of "<get name="hair"/> <get name="likes"/>" and once again we scan the database to see what matches:

    Human - "Who has black hair and likes burgers?"
    Bot - Results: Kevin
    David

    I use this database method regularly for answering crazy questions like "Is a train faster than a snail?". There's no point in creating categories for this one example and so a database method is far more useful and easier to maintain.

    If this is beyond the level of what you are needing, you will need to use a map and a category like this:

    [
        ["brown", "Markus, David, Thomas"],
        ["black", "Stephen, Paul"], 
        ["blonde", "Simon"]
    ]
    
    <category>
        <pattern>WHO HAS * HAIR</pattern>
        <template>
            <map name="hair"><star/></map>
        </template>
    </category>
    

    However, this has nowhere near the flexibility of using a database style structure.

    Human - Who has brown hair?

    Bot - Markus, David, Thomas

    If you are planning on doing that though, you might as well just do:

    <category>
        <pattern>WHO HAS BROWN HAIR</pattern>
        <template>
            Markus, David, Thomas.
        </template>
    </category>
    

    Hope that makes sense. Happy to clarify anything if you need me to.