Search code examples
pythonaiml

Use variables for input and output PyAIML


I have included the below source which is my full project at the moment. What I have working so far is a terminal interface where I input a phrase and it then takes the response (from the AIML database), takes each letter and one-by-one plays the .mp3 sound for that letter to make a BASIC translator (R2D2 here). There are a couple of problems. The first is that it works fine for the first time I enter in a phrase (in that it translates the output perfectly), but then encounters an Index error and the terminal closes. (see figure 1) I don't know what is wrong with it, but suspect it may be something faulty with my while loop.

The other issue I have is that I plan to use this with a speech interface, so I say something, it's run through a STT engine which then outputs what I said as a string. I want that string to then be given as the input to PyAIML to then get a response from and translate it as it does in this program. The problem I have is how to make a variable which can then be used as input to PyAIML. Any ideas how I'd do this?

import aiml
import os
import time

def translate():
    if char == 'a':
        os.system("start a.mp3")
    elif char == 'b':
        os.system("start b.mp3")
    #This continues for all the letters of the alphabet - you get the idea
    else:
        time.sleep(0.1),


k = aiml.Kernel()
k.learn("std-startup.xml")
k.respond("load aiml b")
while True: 
    string = k.respond(raw_input("> "))
    input = string.lower()
    numChar = len(input)
    n = 0
    m = 0
    char = input[n]
    while m < numChar:
        translate()
        time.sleep(0.25),
        n = n + 1
        char = input[n]
        m = m + 1

figure 1 Note: the response does work; it comes up with this error after the output has been translated.


Solution

  • Your code is stepping through each character individually, when you should just step through the string (and it will return back each character).

    Python is a bit different in that traditional "find the length, set a counter to 0, until count is less than the length, fetch by the counter" pattern is not required.

    You can also optimize your code a bit:

    import aiml
    import os
    import time
    
    character_mappings = {'a': 'a.mp3', 'b': 'b.mp3'}
    
    def speak(char):
        out = character_mappings.get(char)
        if out:
             os.system('start {}'.format(out))
        else:
             time.sleep(0.1)
    
    k = aiml.Kernel()
    k.learn("std-startup.xml")
    k.respond("load aiml b")
    while True: 
        text = k.respond(raw_input("> ")) # "string" is a built-in
        for char in text.lower():
            speak(char) # translate is also a built-in
            time.sleep(0.25)