Code Monkey home page Code Monkey logo

rivescript-python's Introduction

RiveScript-Python

Build Status Read the docs PyPI

Introduction

This is a RiveScript interpreter for the Python programming language. RiveScript is a scripting language for chatterbots, making it easy to write trigger/response pairs for building up a bot's intelligence.

Python 2 EOL Notice

Historically, this library supported both Python 2 and Python 3 until the day that Python 2 entered end-of-life status which happened on January 1, 2020.

The final version with Python 2 support is v1.14.9 which you may still install from PyPI if you need to support a Python2 environment. Going forward, RiveScript releases will target modern, supported releases of the Python 3 language. Today, this means Python 3.6 and newer.

# Python2 last supported version of RiveScript is 1.14.9
pip install rivescript==1.14.9

Documentation

Module documentation is available at http://rivescript.readthedocs.org/

Also check out the RiveScript Community Wiki for common design patterns and tips & tricks for RiveScript.

Installation

This module is available on PyPI and can be installed via pip:

pip install rivescript

To install manually, download or clone the git repository and run python setup.py install

Examples

There are examples available in the eg/ directory of this project on GitHub that show how to interface with a RiveScript bot in a variety of ways--such as through the Twilio SMS API--and other code snippets and useful tricks.

Usage

The rivescript module can be executed as a stand-alone Python script, or included in other Python code. When executed directly, it launches an interactive chat session:

python rivescript ./eg/brain

In case running RiveScript as a script is inconvenient (for example, when it's installed as a system module) you can use the shell.py script as an alias:

python shell.py eg/brain

When used as a library, the synopsis is as follows:

from rivescript import RiveScript

bot = RiveScript()
bot.load_directory("./eg/brain")
bot.sort_replies()

while True:
    msg = raw_input('You> ')
    if msg == '/quit':
        quit()

    reply = bot.reply("localuser", msg)
    print 'Bot>', reply

The scripts example.py and example3.py provide simple examples for using RiveScript as a library for Python 2 and 3, respectively.

UTF-8 Support

RiveScript supports Unicode but it is not enabled by default. Enable it by passing a True value for the utf8 option in the constructor, or by using the --utf8 argument to the standalone interactive mode.

In UTF-8 mode, most characters in a user's message are left intact, except for certain metacharacters like backslashes and common punctuation characters like /[.,!?;:]/.

If you want to override the punctuation regexp, you can provide a new one by assigning the unicode_punctuation attribute of the bot object after initialization. Example:

import re
bot = RiveScript(utf8=True)
bot.unicode_punctuation = re.compile(r'[.,!?;:]')

Regardless of whether UTF-8 mode is on, all input messages given to the bot are converted (if needed) to Python's unicode data type. So, while it's good practice to make sure you're providing Unicode strings to the bot, the library will have you covered if you forget.

JSON Mode

The rivescript package, when run stand-alone, supports "JSON Mode", where you communicate with the bot using JSON. This is useful for third-party programs that want to use RiveScript but don't have an interpreter in their native language.

Just run it like: python rivescript --json /path/to/brain

Print a JSON encoded data structure into the standard input. The format should look like this:

{ "username": "localuser", "message": "Hello bot!", "vars": { "name": "Aiden" } }

After sending this, you can send an EOF signal and the bot will respond with a JSON response and then exit. Or, you can keep the session open, by sending the string __END__ on a line by itself after your input. The bot will do the same when it responds, so you can reuse the same pipe for multiple interactions.

The bot's response will be formatted like so:

{ "status": "ok", "reply": "Hello, human!", "vars": { "name": "Aiden" } }

The status will be ok on success, or error if there was an error. The reply is the bot's response (or an error message on error).

Contributors

License

The MIT License (MIT)

Copyright (c) 2020 Noah Petherbridge

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

SEE ALSO

The official RiveScript website, http://www.rivescript.com/

rivescript-python's People

Contributors

arashsa avatar dbrgn avatar dinever avatar flogiston avatar fujimakoto avatar htdinh avatar kirsle avatar snoopyjc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rivescript-python's Issues

Adding and getting dynamic triggers

Is it possible to getand add triggers dynamically ?
For example from a redis store.
To be able to add triggers without restarting the bot.

routes = {
    "topic=domath": {
        "math": {
            "triggers": getTriggersFromRedis,
            "args": "<star1> <star2>",
            "handler": doMath
        },
        "wildcard": {
            "triggers": ["*"],
            "args": "<star>",
            "handler": wildcardHandler
        }
    }
}

This way i can also let the bot add new triggers by itself, based on the wildcard message for a topic.
It will search for certain keywords like action verbs, question verbs etc... in the wildcard message, then determine where to create the new trigger.

problem with default matching using [_]

Creating a very simple template like 'more [_]' causes a TypeError because of an incorrect matching.

Here is the full steps to repeat the problem:

$ cat begin.rive
! version = 2.0

+ *
- I know nothing...

+ more [_]
- more <star>
$ python rivescript-python/rivescript ./
      .   .
     .:...::      RiveScript Interpreter (Python)
    .::   ::.     Library Version: v1.14.2
 ..:;;. ' .;;:..
    .  '''  .     Type '/quit' to quit.
     :;,:,;:      Type '/help' for more options.
     :     :

Using the RiveScript bot found in: ./
Type a message to the bot and press Return to send it.

You> help
Bot> I know nothing...
You> more thing
Bot> more thing
You> more
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.12_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/local/Cellar/python/2.7.12_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/rive-test/rivescript-python/rivescript/__main__.py", line 27, in <module>
    interactive_mode()
  File "/rive-test/rivescript-python/rivescript/interactive.py", line 260, in interactive_mode
    reply = bot.reply("localuser", msg)
  File "/rive-test/rivescript-python/rivescript/rivescript.py", line 999, in reply
    return self._brain.reply(user, msg, errors_as_replies)
  File "/rive-test/rivescript-python/rivescript/brain.py", line 83, in reply
    reply = self._getreply(user, msg, ignore_object_errors=errors_as_replies)
  File "/rive-test/rivescript-python/rivescript/brain.py", line 416, in _getreply
    reply = self.process_tags(user, msg, reply, stars, thatstars, step, ignore_object_errors)
  File "/rive-test/rivescript-python/rivescript/brain.py", line 579, in process_tags
    reply = reply.replace('<star>', stars[1])
TypeError: coercing to Unicode: need string or buffer, NoneType found

Add an __init__.py file

Hello,
Can you add an init file like in this fork kevlened@3d556d3 please ?
I have the same problem, I import rivescript as a submodule in my app so to use it as a library, I need an init file in the package.
(As I don't know if it's a good practice, if you think it's not, close this issue, I will fork it for my own usage :) )

Thanks !

ValueError: number of bits must be greater than zero from time to time

I can't always reproduce this error, but it seems to happen from time to time when using get and set in .rive files. This is the last time I got the error message:

Traceback (most recent call last):
File "/Users/arashsaidi/Work/chatbot/bot/python/lib/python3.5/random.py", line 253, in choice
i = self._randbelow(len(seq))
File "/Users/arashsaidi/Work/chatbot/bot/python/lib/python3.5/random.py", line 230, in _randbelow
r = getrandbits(k) # 0 <= r < 2**k
ValueError: number of bits must be greater than zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "run.py", line 14, in
reply = bot.reply("localuser", msg)
File "/Users/arashsaidi/Work/chatbot/bot/python/lib/python3.5/site-packages/rivescript/rivescript.py", line 999, in reply
return self._brain.reply(user, msg, errors_as_replies)
File "/Users/arashsaidi/Work/chatbot/bot/python/lib/python3.5/site-packages/rivescript/brain.py", line 82, in reply
reply = self._getreply(user, msg, ignore_object_errors=errors_as_replies)
File "/Users/arashsaidi/Work/chatbot/bot/python/lib/python3.5/site-packages/rivescript/brain.py", line 387, in _getreply
reply = random.choice(bucket)
File "/Users/arashsaidi/Work/chatbot/bot/python/lib/python3.5/random.py", line 255, in choice
raise IndexError('Cannot choose from an empty sequence')
IndexError: Cannot choose from an empty sequence

_substitute has bug?

using example.py

input: you are haha
somtimes output: oh, I are haha?
which should be "oh, I am haha?"

UnicodeDecodeError

Hi.
I report again similar issue about unicode.

I got error as below when unicode output at return of object
UnicodeDecodeError: 'ascii' codec can't decode byte 0xeb in position 0: ordinal not in range(128)

I can fix this issue to add a line at rivescript.py(about 2232 line)

       output = output.decode('utf8')    #<<<<<<------- add this line
        reply = reply.replace('<call>{match}</call>'.format(match=match), output)

bug in matching "<input1>"?

Add the following setences into begin.rive

+

  • == => repeat 1 and 2
  • repeat

run the example.py
input the string of "abc" and "abc" again and again
the output of "repeat" or "repeat 1 and 2" was never seen.

Adding global NER models

Hello Noah,

I am trying to use https://spacy.io NLP library with rivescript to get entities from the user's input

> object getEntities python
    import spacy
    en_nlp = spacy.load('en')
    return en_nlp(input, entities) /* Example */

The issue is that Spacy or any other NLP programs takes a few seconds to load the model, which delays the output of rivescript.

Is it possible to load all the models during initialization of rivescript and set en_nlp as a global variable, accessible in all python functions?

How to use the Rivescript.deparse() method

From the source code:

Dump the in-memory RiveScript brain as a Python data structure.

This would be useful, for example, to develop a user interface for
editing RiveScript replies without having to edit the RiveScript
source code directly.

I've just started looking into the source code of the project, and I'm trying to get my head around this method. I see that it parses everything to a python object, but how can you edit replies, and then load it back into Rivescript again?

Caching RiveScript Brain for a Web Application

Hello!

Thank you so much for this library - I've been using it quite a bit for the last few months.

My question is about the contents of the Brain. I have a large set of RiveScript files and I'm wrapping this library with a Flask web server so that clients can make HTTP requests and respond based on the user calling in. Unfortunately on each reply, loading the Brain takes quite a while.

Question: Has anyone solved for a means of caching the parsed content in memory for a large set of RiveScript files (~ 130 files, 500 - 1000 lines each)?

Examples:

I tried to cache a lot of the RiveScript class's private variables (_global, _var, etc) in Redis as JSON-encoded strings and load them using json.loads but the parsing process from string to dictionary is rather expensive.

I also tried MongoDB, but the _sorted dictionary of sort buffers exceeds a document's maximum size of 16MB.

Another data point - every private dictionary in RiveScript (minus _handlers and _regexc stored as one large JSON object in a file is about 200MB.

Any feedback, either potential solutions or commentary on any relevant architecture decisions, is much appreciated.

possibility in using Haxe?

i see that rivescript has a lot of client support, have you considered using Haxe as the single parser and export to different clients? The language is based off of ECMA / AS3 and designed to be translated to other languages: http://haxe.org/

Unable to reply with complex html

I want the bot to respond with small html bits when needed. But when i give it a few complex tags rivescript throws errors like
[ERR: Math couldn't 'div' to value 'undefined' etc...
Its json encoded aswell

Buggy regexp generation when using optionals

When requesting a reply from the rivescript script, when using nested optionals a buggy regular expression is created by rivescript, which causes the re library to throw an exception.

The python traceback prints the following:

Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/easyirc/event/__init__.py", line 14, in putln
    consumed = handler(connection, message)
  File "/usr/lib/python2.7/site-packages/easyirc/event/__init__.py", line 109, in __call__
    return self.job(connection, message)
  File "/usr/lib/python2.7/site-packages/easyirc/event/__init__.py", line 144, in job
    return self.job_func(connection, msgline.sender, *util.msgsplit(message)[2:])
  File "IEChatBot.py", line 237, in on_privmsg
    botreply = self.rs.reply(nick, message)
  File "/usr/lib/python2.7/site-packages/rivescript/rivescript.py", line 1469, in reply
    reply = self._getreply(user, msg)
  File "/usr/lib/python2.7/site-packages/rivescript/rivescript.py", line 1651, in _getreply
    match = re.match(r'^' + regexp + r'$', msg)
  File "/usr/lib64/python2.7/re.py", line 141, in match
    return _compile(pattern, flags).match(string)
  File "/usr/lib64/python2.7/re.py", line 251, in _compile
    raise error, v # invalid expression

By inserting a print statement in rivescript/rivescript.py line 1650 I was able to see the buggy generated regex:

tell (me|us) more(?:\s*(about (it\s*|\s*ie\s*|\s*)\s*|\s*about [the\s*|\s*)intel exchange)]

As you can see, the problem is just after the optional "the": Insted of processing the parantheses, they were skipped by the code generating the regexes, which I traced down to rivescript/rivescript.py lines 1858-1869.

A minimal example for replicating the issue:

In a python file

import rivescript

rs = rivescript.RiveScript()
rs.load_file("bugreport.rive")
rs.sort_replies()
rs.reply("test", "anything_here")

In bugreport.rive:

! version = 2.0

+ tell (me|us) more [(about (it|ie|)|about [the] intel exchange)]
- proof

Short discussions don't work with line breaking

Using a slightly modified example from the documentation (with an added newline):

+ knock knock
- Who's \n
^ there?

+ *
% who * there
- <star> who?

+ *
% * who
- LOL! <star>! That's funny!

If I now follow the script, the final statement (LOL ...) is never reached. I suspect it is probably due to how the regex matching is being done here https://github.com/aichaos/rivescript-python/blob/master/rivescript/brain.py#L503. Adding the re.DOTALL flag would most likely fix this issue, but not sure if that is the correct answer here (I'm relatively new to rivescript). Any thoughts?

UTF-8 and Optionals

This might be related to rivescript-js#147. The following test case produces the problem:

+ *
- Häää?

+ [*] (überrasch mich|empfiehl mir was|empfehl mir was|was gibts neues für mich|empfehlung) [*]
- recommendation

The words with umlauts in them make the second trigger unmatchable.

In rivescript-js#147 I found Python wasn't affected by the Chinese symbols but may be having problems with these umlauts for some reason.

Fuzzy sentence/commands detection

Is it possible to make a fuzzy sentence detection and commands joining system in Rivescript?
Then split each sentence/command individually for triggers and process each.
Eg. Usecases:
"Tell John there is a meeting tomorrow at 2pm, then check what's the weather"
"Get my last note and order my fav pizza"

Joiners like "and" "then" can be used as split points. Also fuzzy sentence detection like ". " dot space, ". Abc" dot space Uppercase letter etc...

Python converter for aiml2rs

Why did you not make the aiml2rs converter in python rather than perl ?
Perl is a dead language and hardly anyone uses it.
One would not have to download such a large dependancy just to convert aiml files to .rive and never use it for anything else.

I'm not going to download perl.
Is there an online aiml2rs converter ?

Grouping to topics in router stream controllers

Do you have an idea of how we can group a set of triggers in a topic in the Router controllers ?
This is the last Rivescript feature that will make working with the whole application better.

#Maybe like this, i dont know...
replies = {
    "name": {
        "topic-confusify": {
            "reverse": {
                "triggers": [
                    "say * in reverse",
                    "say * to me (backward|backwards|in reverse|reversed)",
                    "reverse *"
                ],
                "args": "<star1>",
                "handler": revFunc
            },
            "wildcard": {
                "triggers": ["*"],
                "args": "<star>",
                "handler": doWild
            }
        }
    }
    #...
}
# Current python example Router stream controllers
from rivescript import RiveScript

bot = RiveScript()

def revFunc(rs, args):
    text = " ".join(args)
    reversed = text[::-1]
    return reversed

def doWild(rs, args):
    text = " ".join(args)
    return "No reply for this. "+text

replies = {
    "reverse": {
        "triggers": [
            "say * in reverse",
            "say * to me (backward|backwards|in reverse|reversed)",
            "reverse *"
        ],
        "args": "<star1>",
        "handler": revFunc
    },
    "wildcard": {
        "triggers": ["*"],
        "args": "<star>",
        "handler": doWild
    }
}

# load router streams
for name, keys in replies.items():
    # Map the trigger texts to the `<call>` command for the callable.
    for trig in keys["triggers"]:
        bot.stream("+ " + trig + "\n" + "- <call>" + name + " " + keys["args"] + "</call>\n")
    # Register the JavaScript object macro.
    bot.set_subroutine(name, keys["handler"])

bot.load_directory("./rives")
bot.sort_replies()

while True:
    msg = input('You> ')
    if msg == '/q':
        quit()

    reply = bot.reply("Userx", msg)
    print('Bot>', reply)

Gracefully handle python objects that don't return

If you write a Python object in your RiveScript code, and you don't return a string from it (i.e. because you don't want the object to have any output, so you just don't include a return line), this crashes rivescript.py when it tries to substitute the result into the message.

When the object call returns None, replace it with the empty string instead.

No alphabetical sort for triggers of same type and number of words

According to the sorting of triggers,

For multiple triggers with the same amount of words, sort them by length, and then alphabetically if there are still matches in length.

However, it seems that the sort by character-length and alphabetical order are not yet implemented.

An example set of triggers, this can be evaluated from Try RiveScript Online:

+ * you *
- you_reply
+ * are *
- are_reply

Both of them would match the user input "how are you doing" but the RiveScript answer will be you_reply, the first occurrence in the .rive file (because the triggers are stored as list). Change the order of triggers and you will find it matches the first occurrence. The dependence on ordering of templates in such cases violates the sorting rule stated earlier (in alphabetical order).

Another example of atomic triggers which requires activation of the RS debug mode by setting rs = RiveScript(debug = True) to see the sort order of triggers:

+ hi
- hi there
+ hello
- hello there

The sort order should be: hello then hi because:

  1. Length in terms of characters (len("hello")=5, len("hi")=2)

  2. Alphabetical order.

However, the order search information shows that sorted list of triggers places hi before hello

You> hello
[RS] Get reply to [localuser] hello
[RS] Checking topic random for any %Previous's.
[RS] There is a %Previous in this topic!
[RS] lastReply: undefined
[RS] Try to match u'hello' against u'hi' (u'^hi$')
[RS] Try to match u'hello' against u'hello' (u'^hello$')
[RS] Found a match!
[RS] Reply: hello there
Bot> hello there

Issue running unit test

Hi,

When I'm trying to run de unit test, for all of them I receive AssertionError and the message = "[ERR: No default topic 'random' was found!]", example:

Failure
Traceback (most recent call last):
  File "/Users/fuvio/Documents/jarvis/jarvis/tests/test_script.py", line 30, in test_no_begin_block
    self.reply("Hello bot", "Hello human.")
  File "/Users/fuvio/Documents/jarvis/jarvis/tests/config.py", line 35, in reply
    self.assertEqual(reply, expected)
AssertionError: "[ERR: No default topic 'random' was found!]" != u'Hello human.'

I'm running in python 2.7.9, could be this the problem?

Thanks in advance!

Is it possible to create a specific(general trigger) ?

hello everyone,
we have general reply for unknown trigger
ex :

+ *
- please, try with other words

but i'd like to question like this :

who is Einstein / what is an apple / how is the fire....

i'd like to create that :

+ who is *
- {@<star>}      # redirects to known trigger (in atomic.learn for example)

+ who *
- I don't know who it is. I can search on wiki if you want,

and same for what / how .... to create more realistic replies.

Tried ! and doesn't work

Please help

Error with array of words when using object macro

I get this error when using array like, [*] (get|show|fetch) keyword * with an object macro
Without the array it works correct, + [*] show note #

// trigger eg: show note 23
// get a note from its id
+ [*] (get|show|fetch) note #
    - note <star> is: <call>getNote <star></call>
[RS] Error executing Python object: 'NoneType' object is not subscriptable
Bot> note show is: [ERR: Error when executing Python object]

Also another issue is why does the Python version not have a rs.GetVariable("botmaster") ?
Like the Golang version. func (rs *RiveScript) GetVariable(name string) (string, error)

Reply method returns None

For the template

+ [*] [what] [is|are|were|was] [_] (latest|new|hot off the press) [news|info|information] [_] [please|thanks|thank you|thank you very much]
- latest

and the input message "what is new" the reply method returns a None.

Traceback:

File "basic_bot.py", line 42, in on_message
    reply = self.rs.reply(user, message)
  File "/Library/Python/2.7/site-packages/rivescript/rivescript.py", line 1786, in reply
    reply = self._getreply(user, msg, ignore_object_errors=errors_as_replies)
  File "/Library/Python/2.7/site-packages/rivescript/rivescript.py", line 2142, in _getreply
    reply = self._process_tags(user, msg, reply, stars, thatstars, step, ignore_object_errors)
  File "/Library/Python/2.7/site-packages/rivescript/rivescript.py", line 2391, in _process_tags
    reply = reply.replace('<star>', stars[1])
TypeError: coercing to Unicode: need string or buffer, NoneType found

Problems found in new sorting algorithm

In #67 the sorting algorithm was refactored and I found a rather visible breakage from it: in the example bot I wasn't able to match the hello triggers:

You> hello bot
Bot> Please go on.
You> hi
Bot> I'm not sure I understand you fully.
You> my name is noah
Bot> Noah, nice to meet you.
You> hello
Bot> Please go on.

In the previous state of the master branch (commit 405e391) it gives the expected result:

You> hello bot
Bot> Hi. What seems to be your problem?
You> hello
Bot> How do you do. Please state your problem.

I made this local change to my rivescript/interactive.py to print the sorted lists for both versions:

diff --git a/rivescript/interactive.py b/rivescript/interactive.py
index 3b67727..5cf9510 100644
--- a/rivescript/interactive.py
+++ b/rivescript/interactive.py
@@ -200,6 +200,12 @@ def interactive_mode():
     bot.load_directory(args.path)
     bot.sort_replies()
 
+    topics = sorted(bot._sorted['topics'].keys())
+    for topic in topics:
+        print("Topic:", topic)
+        for trigger in bot._sorted['topics'][topic]:
+            print("\t", trigger[0])
+
     # Interactive mode?
     if args.json:
         # Read from standard input.

I've attached the outputs of the above sort lists:
broken-sort.txt
good-sort.txt

Here is a snippet of the buggy version's output around the relevant trigger:

  	 i am *
  	 everyone *
- 	 *
  	 i am (sad|unhappy|mad|angry|pissed|depressed) [*]
  	 i am (happy|excited|glad) [*]
+ 	 (hello|hi|hey|howdy|hola|hai|yo) [*]
  	 (what|who|when|where|how) [*]
  	 my (girlfriend|boyfriend)* name is *

So it seems the bare wildcard * took a higher precedence over triggers that contained alternatives and optional *'s.

I also saw similar cases in the output of the triggers not being sorted the best: in the topics used for the RPG game demo, the _ * trigger was at the very bottom (below *) when they should've been in the opposite order (_ * > *).


I'm not planning a new official release too soon, so I'll leave PR #67 merged for now and hopefully these last couple bugs can be resolved. If I do need to make a new release before then I'll have to revert #67 and try again later.

Short Discussions don't work with JSON payloads

The error raises wether I communicate to the bot by invoking the interactive mode with the --json (or -j) flag or running flask app accessible via a JSON endpoint.


ERROR in app: Exception on /reply [POST]
Traceback (most recent call last):
  File "/home/botmaster/.virtualenvs/a004/local/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/botmaster/.virtualenvs/a004/local/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/botmaster/.virtualenvs/a004/local/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/botmaster/.virtualenvs/a004/local/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/botmaster/.virtualenvs/a004/local/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "server.py", line 54, in reply
    reply = bot.reply(username, message)
  File "../../rivescript/rivescript.py", line 999, in reply
    return self._brain.reply(user, msg, errors_as_replies)
  File "../../rivescript/brain.py", line 69, in reply
    reply = self._getreply(user, msg, ignore_object_errors=errors_as_replies)
  File "../../rivescript/brain.py", line 301, in _getreply
    self.master.set_uservar(user, "__lastmatch__", matchedTrigger)
  File "../../rivescript/rivescript.py", line 757, in set_uservar
    self._session.set(user, {name: value})
  File "/home/botmaster/bot/eg/json-server/redis_storage.py", line 38, in set
    self.c.set(self.key(username), json.dumps(data))
  File "/usr/lib/python2.7/json/__init__.py", line 244, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <_sre.SRE_Pattern object at 0xb6b1ee58> is not JSON serializable

Edit/fixed the post formatting. --Kirsle

UTF-8 accents on triggers

Hello,
in my 1.14 python version,
and with ai = RiveScript(utf8=True) on my python file,
I can't enter any accents "éèàç..." on question.

here is the error :

Traceback (most recent call last):
File "C:\Users\neo\Downloads\rivescript-python\RS_AI.py", line 17, in
reply = ai.reply("localuser", msg)
File "C:\Users\neo\Downloads\rivescript-python\rivescript\rivescript.py", line 999, in reply
return self._brain.reply(user, msg, errors_as_replies)
File "C:\Users\neo\Downloads\rivescript-python\rivescript\brain.py", line 46, in reply
self.say("Get reply to [" + user + "] " + msg)
File "C:\Users\neo\Downloads\rivescript-python\rivescript\brain.py", line 41, in say
self.master._say(_args, *_kwargs)
File "C:\Users\neo\Downloads\rivescript-python\rivescript\rivescript.py", line 149, in _say
self._log.write("[RS] " + message + "\n")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 25: ordinal not in range(128)

What did I miss ???

Thanks Kirsle
Vincent

Know which file contains the trigger

Hello,
I don't know if it's usefull to be included in the master branch, but I wonder if it's possible to know in which file is loaded a specific trigger.

Example : I split my project in plugins. Each plugin contains a a rivescript file containing triggers, call/answers.

I would like to know before calling the reply() (and retrieve the answer) which trigger will be ran and in which file. As it is loaded in memory and not know the source file, I don't know if it's possible.
My goal is to do a rule-engine which will be able to modify the message before sending it to reply() IF it match a specific plugin.

Thanks

can't use array and sub at same time !!

here is the problem :

// my bot is controlled with pocketsphinx, so never numeric numbers. Each value is alphabetic. So I need to automatic convert with sub

begin :

! array number = un deux trois

! sub   one     = 1
! sub           two     = 2

question :

+ I am (@number) years old  //really need array 
- <star> ? Good !

could i use multiple % in same sequence ?

ex :

--------------------------
+ i leave
- ok i change question
--------------------------
+ send question
- are you ok
- are you ready
--------------------------
+ yes
% are you ok
- `good`

+ yes
% are you ready
- good

+ no
% are you ok
- bad

+ no
% are you ready
- bad

+ *
% are you ok
% are you ready
- @i leave

Is there any possibility to use multiple % like in previous star trigger ?
Thanks all

how to get original text which contain special char

for example

+ what is *
- <star> is something.

user> what is domain\account
bot > domainaccount is something

expect reply: domain\account is something

or

+ what is *
- <formal> is something.

user> what is Cindy Wang (IS-TW)
bot >Cindy Wang (is-Tw) is something

expect reply: Cindy Wang IS-TW) is something

tks

Identical sequences of random tags all pick the same choice

If you have multiple {random}...{/random} sequences and they all look 100% identical (same words in the same order, etc.), then only one of them is actually processed (random choice chosen) and the random choice replaces all occurrences of the sequence.

Example:

- {random}red|blue|green|black|white|gray|pink{/random} {random}red|blue|green|black|white|gray|pink{/random} {random}red|blue|green|black|white|gray|pink{/random}

This might yield an answer of "green green green".

The problem is likely because: after the random choice is picked, it does a regexp find/replace on the full original text of the tag with the answer, but it probably does a global replace, also replacing all other matching tag sequences. If you alternate the words in each set the problem is resolved.

Redis session not compatible with Rivescript %(previous) command

It will result in a "TypeError: re.compile('^(.*?)$') is not JSON serializable" when you have % (previous) command triggered and using redis session manager at the same time. It works fine when RedisSessionStorage() is not in use.

File "/home/ubuntu/anaconda3/lib/python3.5/site-packages/rivescript/rivescript.py", line 999, in reply
    return self._brain.reply(user, msg, errors_as_replies)
File "/home/ubuntu/anaconda3/lib/python3.5/site-packages/rivescript/brain.py", line 69, in reply
    reply = self._getreply(user, msg, ignore_object_errors=errors_as_replies)
File "/home/ubuntu/anaconda3/lib/python3.5/site-packages/rivescript/brain.py", line 301, in _getreply
    self.master.set_uservar(user, "__lastmatch__", matchedTrigger)
File "/home/ubuntu/anaconda3/lib/python3.5/site-packages/rivescript/rivescript.py", line 757, in set_uservar
    self._session.set(user, {name: value})
File "/home/www/chatbot/redis_storage.py", line 39, in set
    self.c.set(self.key(username), json.dumps(data))
File "/home/ubuntu/anaconda3/lib/python3.5/json/__init__.py", line 230, in dumps
    return _default_encoder.encode(obj)
File "/home/ubuntu/anaconda3/lib/python3.5/json/encoder.py", line 198, in encode
    chunks = self.iterencode(o, _one_shot=True)
File "/home/ubuntu/anaconda3/lib/python3.5/json/encoder.py", line 256, in iterencode
    return _iterencode(o, 0)
File "/home/ubuntu/anaconda3/lib/python3.5/json/encoder.py", line 179, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: re.compile('^(.*?)$') is not JSON serializable

Edit by @kirsle: use fenced code blocks.

Auto user sesson expiry

Hi. Could you please add a session expiry method to the rivescript base session handler, aswell as a core method to set it via the bot object.
I tried expiring it from outside rivescript session, but that requires another Session instance.
Such a mehod will work great with Redis session. Tia

# rivescript.py

def expire_user(self, user, time):
    """Delete user session when time expires.
        eg. expire Jonny5's session in 10 minutes
        bot.expire_user("Jonny5", 600)
    """
    # set expiry
    self._session.expire(user, time)

Revisit regular expression substitutions for Python 3.6

Python 3.6 is creating a breaking change to the way re.sub() works, in that any unknown escape sequence in the repl parameter (a backslash followed by any ASCII letter) becomes a runtime exception.

This commit fixes the particular case that was causing the unit tests in Travis CI to fail under Python 3.6.0a2 (nightly build).

In normal (non-UTF8) operation of RiveScript it should be difficult to trigger a similar exception, but with UTF-8 mode enabled and specially crafted RiveScript source files it could become possible to crash the library.

Every instance of re.sub() should be visited to make sure that no escape sequence will ever appear as the repl parameter that will cause a runtime crash of the program. Even if the user disables strict mode.

See also: https://docs.python.org/3.6/library/re.html#re.sub

Changed in version 3.6: Unknown escapes consisting of '\' and an ASCII letter now are errors.

Python 3.6 is set for release on December 12, 2016 and RiveScript should be ready for it before then.

Problem with french language

Hello,

In the french language we use these letters :
àâäçèéêëîïôöùûü and as special character : ' @

' can be used in words like : "aujourd'hui" (means today in english)
@ can be used to give an email address to perform some custom action with.

Can you update the regexp to handle these utf8 characters please ?

Thanks a lot for your amazing work !!

Problems with optionals and array in triggers

Hello,
Here is the examples :

[*] (yes|No) [*]
% are you young
* <star>== yes => good
* <star>== No => bad

*
% are you young
- ok, i leave

If i reply "yes" or "yes i am" it replies ok i leave
It should say good !!

Any solution ?

Second problem :

! array nombre = un deux trois...
! sub un = 1
! sub deux = 2
.....

+ [*] # [*]
% how many arms do i have
* <star>==2=> good
- bad answer

+ *
% how many arms do i have
- ok i leave

I say : you have four arms my friend
It replies : ok i leave (should be : bad answer)

Sometimes it work, and sometimes no !!!

Is there any problem ?

Thanks Noah

rivescript-python cannot support other language like Chinese

There are lots of regex like match=re.match(r'[^a-z0-9....),so it cann't support for other language like chinese. I have to change it to "match=re.match(ur'[^a-z0-9\u4E00-\u9FA5....) " in lots of places. Now my question is:
How can I modify it more easy in order to support my language?

I have read some issues, so I have to give more infomation:
code init in example.py with: rs = RiveScript(utf8=True)
and then a trigger like this:

  • 你好 [*]
  • 很高兴认识你

my input is : 你好 帅哥

I cannot find this brach now :https://github.com/kirsle/rivescript-python/tree/unicode

Thank you!

UnicodeDecodeError

I god error when i input 'comment ça va'
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 8: ordinal not in range(128)

I can fix this issue when add a line on rivescript.py (line 1520)

def reply(self, user, msg, errors_as_replies=True):
    """Fetch a reply from the RiveScript brain."""
    msg = msg.decode('utf8')    #<<<<<<-----------  add this line
    self._say("Get reply to [" + user + "] " + msg)

Please check it.
Thanks

get raw message for wildcard logging

Is there a way to get the original user message so to use it in a logWildcard(user, msg) function ?
get_uservar(user, "history")["input][0] does not give the current user message while processing the trigger, only the previous one.
This is for logging various wildcards in various topics. So to improve trigger creation.

Consider using a different file extension

.rs is used by Rust, which is considerably more mainstream than this; it'd be convenient if the file extension for RiveScript were changed to something else. A quick search suggests that .rive is unused, it sounds to me a better (more discoverable) extension for RiveScript, too, though being four characters isn't quite so nice.

backup actual user vars to file (text file)

I'd like to save all vars in a textfile named with the actual user, and call it at startup, when user is named like the textfile.

tested save vars :

object savevars python
a = (args)
id= "".join(a)
ID= id.encode('utf8')
vars = rs.get_uservars()
vars = str(vars)
file = open("./eg/neo_brain/uservars/"+ID+".save", "w")
file.write(vars)
file.close()
< object // dic saved in textfile OK !

tested load vars :

object loadvars python
file = open("./eg/neo_brain/uservars/vincent.save", "r")
a = file.read()
a = unicode(a)
file.close()
rs.set_uservars(a)
< object

Doesn't work !!
set_uservars() may only be called with types (unicode, dict) or (dict<unicode, dict>) but you called it with types (<type 'unicode'>, <type 'NoneType'>)")
Any help ?
Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.