creatorrr / pyAIML

PyAIML -- The Python AIML Interpreter
166 stars 74 forks source link

Maximum recursion depth exceed for "learn.aiml" examples #2

Open mertyildiran opened 8 years ago

mertyildiran commented 8 years ago

Hey @creatorrr , thanks for this great library!

I'm facing with a problem while trying to use these learn.aiml files with your library. Mitsuku: http://www.square-bear.co.uk/aiml/learn.zip ALICE: http://alicebot.wikidot.com/learn-aiml (WRONG/OUTDATED)

It's trapping in to an infinite loop, how can I solve that? This is the error.log from the beginning to KeyboardInterrupt.

stderr:

WARNING: maximum recursion depth exceeded (input='xlearnfact')WARNING: maximum recursion depth exceeded (input='XEDUCATE WHAT IS .........
........XSPLIT a language XSPLIT')WARNING: maximum recursion depth exceeded (input='xlearnfact')Traceback (most recent call last):
  File "main2.py", line 5, in <module>
    print kernel.respond("Learn the sun is hot")
  File "/usr/local/lib/python2.7/dist-packages/aiml/Kernel.py", line 329, in respond
    response = self._respond(s, sessionID)
  File "/usr/local/lib/python2.7/dist-packages/aiml/Kernel.py", line 394, in _respond
    response += self._processElement(elem, sessionID).strip()
  File "/usr/local/lib/python2.7/dist-packages/aiml/Kernel.py", line 425, in _processElement
    return handlerFunc(elem, sessionID)
  File "/usr/local/lib/python2.7/dist-packages/aiml/Kernel.py", line 928, in _processTemplate
    response += self._processElement(e, sessionID)
  File "/usr/local/lib/python2.7/dist-packages/aiml/Kernel.py", line 425, in _processElement
    return handlerFunc(elem, sessionID)
.
.
.
.
    return handlerFunc(elem, sessionID)
  File "/usr/local/lib/python2.7/dist-packages/aiml/Kernel.py", line 871, in _processStar
    response = self._brain.star("star", input, that, topic, index)
  File "/usr/local/lib/python2.7/dist-packages/aiml/PatternMgr.py", line 181, in star
    patMatch, template = self._match(input.split(), thatInput.split(), topicInput.split(), self._root)
  File "/usr/local/lib/python2.7/dist-packages/aiml/PatternMgr.py", line 325, in _match
    pattern, template = self._match(suf, thatWords, topicWords, root[self._STAR])
  File "/usr/local/lib/python2.7/dist-packages/aiml/PatternMgr.py", line 307, in _match
    pattern, template = self._match(suffix, thatWords, topicWords, root[first])
  File "/usr/local/lib/python2.7/dist-packages/aiml/PatternMgr.py", line 325, in _match
    pattern, template = self._match(suf, thatWords, topicWords, root[self._STAR])
  File "/usr/local/lib/python2.7/dist-packages/aiml/PatternMgr.py", line 320, in _match
    if root.has_key(self._STAR):
KeyboardInterrupt

With these usage attempts both of them has same problem:

import aiml

kernel = aiml.Kernel()
kernel.learn("learn.aiml")
print kernel.respond("Learn the sun is hot")
import aiml

kernel = aiml.Kernel()
sessionId = 12345
kernel.getSessionData(sessionId)
kernel.learn("learn.aiml")
print kernel.respond("Learn the sun is hot")
cyberyu commented 7 years ago

I have the same issue. But on Pandorabots.com it seems okay. They use LISP AIML parser though.

seth7743 commented 7 years ago

Also ran into the same issue, but fixed it by using a .brn file instead for learning, however that also means you start off in a clean file. If that's what you wanna do then it would be your best bet.

mertyildiran commented 7 years ago

@cyberyu I never considered using AIML with LISP but it's seems a reasonable solution right now.

@seth7743 What do you mean with .brn file? could you explain a little bit?

By the way I believe @cdwfs is the creator and maintainer of the PyAIML: https://github.com/cdwfs/pyaiml

Proof: http://www.alicebot.org/downloads/programs.html

and this issue must be discussed under that page instead of this page: https://github.com/cdwfs/pyaiml/issues/1

I'll do my best to investigate this issue when I have a chance, but at this point your guess may be as good as mine. - Cort Danger Stratton

seth7743 commented 7 years ago

Your .brn will act as the learn.aiml file, it stores and retrieves the bot's learned responses. At least this is what I think you wish to achieve so here's a simple code snippet:

You can use the kernel.setSessionData() and get as well on the .brn file

startup.txt

mertyildiran commented 7 years ago

@seth7743 Could you provide the file assigned at this line: bot_brain = "aiml/bot_brain.brn"

Is that the file: https://github.com/cyface/pyaiml-test/blob/master/bot_brain.brn

Could you explain the process at startup.txt?

cdwfs commented 7 years ago

By the way I believe @cdwfs is the creator and maintainer of the PyAIML: https://github.com/cdwfs/pyaiml Proof: http://www.alicebot.org/downloads/programs.html

Yup, that's me! Glad to see the project is still alive and (allegedly) useful. Alas, I haven't written a non-trivial Python script in close to ten years, so I wouldn't expect too much active development in my fork of the repo.

seth7743 commented 7 years ago

@mertyildiran The file is automatically created by this line (29) _"kernel.saveBrain(botbrain)" if it does not exist.

The program is to initiate a chat, I'll start from line (13), the top is fairly simple I believe: line(13) - Declaring the directory of the bot properties file, you can find this in your Pandorabots files line(17) > line(23) - Loops through the properties in the above file and sets the bot predicate for there kernel, these are default bot properties for pyaiml, much like saving to .brn file line(27) > line(33) - Checks if your bot already has a .brn file, if not, it'll create it with the name and directory specified in line(5) line(35) > line(47) - Requests input from the user to interact with the bot Typing "quit" exits Typing "save" stores everything learnt to the brain Typing "load aiml b" reloads aiml files if you made changes to them Typing anything else chats with the bot and generates a response

I hope that's what you were hoping to achieve @mertyildiran

@cdwfs It is (supposedly) quiet useful. Thanks for developing it!

mertyildiran commented 7 years ago

@seth7743 hmm, I understand thx!

creatorrr commented 7 years ago

Hey @mertyildiran, sorry for the late reply. I was travelling. Anyhow, were you able to get the file working? I tried testing the learn.aiml file and I ran into the following:

My initial thoughts are that the aiml file probably had errors which I need to investigate but if you were able to get it to work with another aiml implementation then I guess there's a bug in this one. Please let me know.

mertyildiran commented 7 years ago

No @creatorrr. learn.aiml file is a legit AIML file.

Mitsuku is a Chatterbot created from AIML technology by Steve Worswick. Mitsuku won the 2013 and 2016 Loebner prize.

https://en.wikipedia.org/wiki/Mitsuku http://www.mitsuku.com/

It's working perfectly well with Program-O though, maybe examining Program-O's algorithm can help to resolve the issue with pyAIML.

We are pretty sure that learn.aiml file is working well because in the university we made a virtual assistant that using it: https://github.com/mertyildiran/Dragonfire

Video as proof: https://youtu.be/ujmRtqf2nxQ

By the way don't irritate when you see "Teachable AI" term because it's the result of the stupidity of some academician. Replace "Teachable AI" with "AIML" term in your mind :smile:

cdwfs commented 7 years ago

Hi @mertyildiran -- I've just come out of PyAIML retirement long enough to investigate this bug report. I think I see the problem -- the learn.aiml file includes a <learn> tag whose child is a <category> to be learned. However, as specified in the AIML 1.0.1 spec, the contents of a <learn> tag are meant to evaluate to a URI to be loaded (e.g. a URL or filename); inline AIML tags would not be valid, according to this interpretation.

It looks like the specification of the <learn> tag was expanded in the AIML 2.0 working spec to allow inline AIML, and I agree that would certainly be an awesome feature. But PyAIML was very specifically written against the 1.0.1 spec. I don't have a wikidot account, but if I did I'd suggest an edit to the learn.aiml page to add a "version=2.0" to the <aiml> tag.

I haven't looked at Program O, but if it processes this file correctly, it must either be targeting the 2.0 spec, or a relaxed interpretation of the 1.0.1 spec. To emulate this behavior in a 1.0.1-compliant interpreter like PyAIML, you could probably replace the inline AIML inside in the <learn> tag with a <system> tag that writes the same inline AIML to a temporary file, and then returns the name of that file. Or something like that.

mertyildiran commented 7 years ago

Hi @cdwfs. I'm glad you come back from the retirement. :smile:

Adding version="2.0" to <aiml> tag <aiml version="2.0"> made no difference.

Unique feature of learn.aiml is being recursive and I believe AimlParser.py is not able to parse recursively. But I'm not capable to understand or fix the issue, I'm just guessing. You @cdwfs should fix it.

By the way this link of learn.aiml is WRONG and/or OUTDATED

Correct link is this: http://www.square-bear.co.uk/aiml/learn.zip

I forgot to mention that; on May 1st 2016, I reached out to Steve Worswick via email and this is the email dump:

Me:

When I try to use learn.aiml file with https://pypi.python.org/pypi/aiml/0.8.6 I'm facing with maximum recursion depth problem.

The only problematic file is learn.aiml. How can I solve this issue.

Steve Worswick:

Does your interpreter support and tags? Even if it does, inputs like "Harry is taller than John but smaller than Fred" will set up dozens of categories. You may need to increase your recursion depth.

Me:

I'm using this Python library to get responses: https://pypi.python.org/pypi/aiml/0.8.6 https://github.com/creatorrr/pyAIML

Do you think the issue is related with this library?

Also, please checkout the issue that I opened: https://github.com/creatorrr/pyAIML/issues/2 You can see more detailed explanation from this issue entry.

Steve Worswick:

Sorry but that’s not an interpreter I’ve ever used. My learn.aiml file is valid AIML used by hundreds of people and so I can only assume the problem lies with your interpreter. Hopefully, the author will provide some support for you.

mertyildiran commented 7 years ago

@cdwfs and @creatorrr I also forgot to mention that or this just newly happened to me;

When I try to load the learn.aiml file, it's giving me tons of PARSE ERROR:s

>>> import aiml
>>> kernel = aiml.Kernel()
>>> kernel.learn("learn.aiml")
PARSE ERROR: Unexpected <category> tag (line 172, column 1)
PARSE ERROR: Unexpected </learn> tag (line 180, column 3)
PARSE ERROR: Unexpected </template> tag (line 192, column 1)
PARSE ERROR: Unexpected </category> tag (line 193, column 0)
PARSE ERROR: Unexpected <category> tag (line 200, column 1)
PARSE ERROR: Unexpected </learn> tag (line 208, column 3)
PARSE ERROR: Unexpected </template> tag (line 210, column 1)
PARSE ERROR: Unexpected </category> tag (line 211, column 0)
PARSE ERROR: Unexpected <category> tag (line 218, column 1)
PARSE ERROR: Unexpected </learn> tag (line 226, column 3)
PARSE ERROR: Unexpected </template> tag (line 238, column 1)
PARSE ERROR: Unexpected </category> tag (line 239, column 0)
Loading learn.aiml... done (0.05 seconds)
>>>
cdwfs commented 7 years ago

Adding version="2.0" to tag made no difference.

I wouldn't expect it to make a difference with PyAIML, which (as I said) does not support the AIML 2.0 spec. I don't even think there was a working 2.0 draft of the spec when I last worked on PyAIML. Adding the version attribute would just be a handy way to indicate that 2.0-level interpreter functionality is required to parse the file.

Unique feature of learn.aiml is being recursive and I believe AimlParser.py is not able to parse recursively.

I assure you that AimlParser.py can definitely parse recursively; several other tags rely on this functionality. I'm virtually certain the problem is what I described above. See the _processLearn() function in Kernel.py, which is called when a <learn> element is encountered: it evaluates the element, treats the result as a filename, and attempts to load and learn() the contents of that file. This the behavior dictated in the 1.0.1 AIML spec, and there's no way it could possibly handle inline AIML correctly. I can't explain why it's failing the way it is, but I don't think the problem is with PyAIML; the problem is feeding (valid) 2.0 AIML data into a (valid) 1.0.1-level interpreter.

But I'm not capable to understand or fix the issue, I'm just guessing. You @cdwfs should fix it.

While I truly appreciate the continued interest in PyAIML, the fact is that I haven't worked on it in nearly ten years; while nothing is certain, I wouldn't count on any further updates from my end. But consider this: it was the first non-trivial Python project I wrote. With a bit of effort, it wouldn't take you long at all to learn as much Python as I knew when I wrote PyAIML!

mertyildiran commented 7 years ago

@cdwfs OK. I will try to upgrade PyAIML to AIML 2.0 in near future. It would be much easier for you to fix it but never mind I will try. If I will be successful I'll send Pull requests to both of yours and this repository. Thanks for your attention! :+1: :smile:

cdwfs commented 7 years ago

It would be much easier for you to fix it

I think you're overestimating how much I remember about either Python, AIML, or PyAIML after ~10 years; I would effectively be approaching a completely unfamiliar codebase at this point. I don't think it would be terribly easy for either of us :)

Is the AIML 2.0 spec fairly stable and well-supported at this point? I'd hate for you (or anybody) to put a lot of work into supporting a draft specification, and end up subtly incompatible with other interpreters.

athuldevin commented 7 years ago

friends i have developed support for learn tag can i share here

creatorrr commented 7 years ago

Sure thing. PRs welcome!

On Sat, Jul 22, 2017 at 2:00 AM athuldevin notifications@github.com wrote:

friends i have developed support for learn tag can i share here

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/creatorrr/pyAIML/issues/2#issuecomment-317168683, or mute the thread https://github.com/notifications/unsubscribe-auth/AA44LyZwdUk0ZTx5SDy1kn14NykAjsfuks5sQbo-gaJpZM4IUKxM .

athuldevin commented 7 years ago

https://github.com/athuldevin/learn

the complete pyaiml files and learn.aiml is available here i have made changes to parser and kernel from pyaiml 0.9.0 changes made

ability to save bot predicates which set dynamically and restore also added learn tag changed previous learn to load added eval tag

problem if bot learn something to brain there is a problem in debugging output, not in response

also developed support for javascript tag but not included in this kernel because it require one additional package , if you like i will share

mertyildiran commented 7 years ago

@athuldevin after a while I realized that learn.aiml of Steve Worswick is a little bit overrated. So recently I wrote this script which has superior capabilities then the combination of an AIML interpreter and learn.aiml file.

In general, state-of-the-art NLP techniques (like spaCy) pretty much made AIML redundant.

athuldevin commented 7 years ago

@mertyildiran can you say where should i go for learn more about advanced stuff like this i am a student

11sm11 commented 6 years ago

An easy way for the pyaiml bot to "learn" is to create a separate py "file writing" script that you send through args the information you want your ai to learn. Then reload the aiml file it wrote to. Example: `

* ARE *
<template>
        OK, I will remember that <star index="1"/> are <star index="2"/>.
        <system>scripts/are_learning.py "<get name="name"/>" "<star index="1"/>" "<star index="2"/>"</system>
        <learn>learned.aiml</learn>
</template>

`

a short example of my are_learning.py file: ` name = sys.argv[1:] star1 = name[1].upper() star2 = name[2].upper() xml = [] xml.append('') xml.append('%s ARE %s' % (star1, star2)) xml.append('') xml.append('') xml.append('') xml.append('') xml.append('')

str = join(xml,'\n')

filename = "./learned.aiml"
with open(filename, 'r') as f:
  text = f.read()
text = text.replace('</aiml>', str)
with open(filename, 'w') as f:
  f.write(text)`

I hope this helps