Skip to main content

Creating a simple chatbot, made easy

Project description

PyPI package Supported Python versions Test Coverage Status Documentation Status Pypi downloads Pypi downloads Pypi downloads

Djamago

djamago logo

Djamago

Have you ever used chatbot AI <https://pypi.org/project/chatbotAI/>_ It is a python module for creating chatting robots.

I used chatbotai since it was extremely difficult to use ai powerred modules like chatterbot <https://pypi.org/project/chatterbot/>_ which could not install on my pc, or trying to generate them myself using torch or tensorflow.

Djamago provides a simple, bulky but personalized approach to that by adding support for some parsing like tools.

Djamago deeply uses djamago <https://pypi.org/project/djamago>_ and so will you see in the examples

If you want to create a little chatbot, with simple and clear code... I will discourage you, It still appears that code with djamago is still somehow bulky or junk, but I'm working on that.

How works

flow.png

Setting up Expressions

During this steps, the several expressions and dataset to be used are loaded to djamago, happens such: Expression.register(name: str, list[tuple[score, regex]])

Expressions.py
# Extract from pango
from djamago import Expression


question = lambda re: (
    fr"(?:.*(?:please|question.?)? ?{re}\??)"
    fr"|(?:may )?i ask you {re}\??"
)  # Formulate the passed RegEx as a question

Expression.register("whois", [
    (100, r"(?:who is) (.*)"),
    (30, r"(?:do you know) (.*)"),
    # Score, regex
])
Expression.register("greetings", [
    (100, r"hello ?(.*)?"),
    (100, r"good (?:morning|evening|night|after-?noon) ?(.*)?"),
    (70, r"greetings ?(.*)?"),
    (20, r"good day ?(.*)?"),
])
Expression.register("name", [
    (70, r"((?:[\w_\-]+)+ ?)"),
])
Full code from djamago import Expression
    question = lambda re: (
        fr"(?:.*(?:please|question.?)? ?{re}\??)"
        fr"|(?:may )?i ask you {re}\??"
    )

    Expression.register("R", [
        (100, r"(.*)"),
    ])
    Expression.register("whois", [
        (100, r"(?:who is) (.*)"),
        (30, r"(?:do you know) (.*)"),
    ])
    Expression.register("whatis", [
        (100, r"(?:what is) (.*)"),
        (50, r"(?:tell me.? ?(?:djamago)? what is) (.*)"),
    ])
    Expression.register("greetings", [
        (100, r"hello"),
        (100, r"good (?:morning|evening|night|after-?noon)"),
        (70, r"greetings"),
        (20, r"good day"),
    ])
    Expression.register("callyou", [
        (100, question(r"how do you call yourself")),
        (100, fr"(?:tell me.? ?(?:djamago)? what is) (.*)"),
        (100, question(r"what is your name")),
        (100, question(r"how can I call you")),
    ])
    Expression.register("askingMyname", [
        (100, question(
            r"(?:how can (?:i|we) call you|what is your name|who are you|"
            r"how (?:do you|can you|are)? (?:call you|called))"
        )),
    ])
    Expression.register("username", [
        (100, question(r"(?:do you (?:know|remember))?(?: ?what is)? ?my name")),
    ])
    Expression.register("whoMadeMe", [
        (100, question(r"who (?:created|programmed|made|coded|trained) you")),
    ])
    Expression.register("name", [
        (100, r"[\w\d_\- \@]+"),
    ])

    Expression.register("aboutAUser", [
        (50,
            question(
                r"(?:do you know(?: about)?|who is|tell me about"
                r"|are you familiar with) ([\w\-_]+)"
            )
        )
    ])
</code>

[!WARNING] Expressions are registered globaly, so if you wan't to create an extension use prefixed names to prevent conflicts

Adding topics

topics.py

we create a topic simply by subclassing the topic class:

class Biology(djamago.Topic):
    pass

Adding callbacks

To add callbacks we simply define a method we will decorate with a djamago.Callback instance, it will automatically register the method

[!TIP] You could change the handler for a callback simply by calling it over an other method

The Callback receives as argument a list of djamago.Pattern instances.

example

class Biology(Topic):
    @Callback([
        (100, Expression("greetings(name)"))
    ])
    def greeted(node: Node):
        node.set_topics(("biology", "faq"))  # Set topics for the consecutive queries
        node.response = "Hello %s!" % node.vars.get("name", "You")

    @Callback([
        (0, RegEx(".*"))  # 0 not to override other answers
    ])
    def anything(node: Node):
        # not Setting topics will use parent topics
        node.response = random.choice([
            "Sorry, I did not understand",
            "Could you reformulate, please"
        ])

Adding Faqs

You have a good database of questions and answers?, here how to add it.

djamago.QA is a djamago.Topic subclass which permit adding QAs of FAQs into the djamago bot. The QA should be a list containing tuple of questions, or question scores (tuple[str] | tuple[tuple[float, str]]) and a list of answers djamago will choose randomly. you may define a format_response, which will process the node before it is returned.

There are few ways to create a QA:

Using data attribute

Here the list of QAs are already parsed and stored as a list:

class Faq(QA):
    data = [
        (
            ("what is biology",),
            ("The study of live things",),
        ),
        (
            (
                (70, "what is chemistry"),
            ),
            ("The study of chemical things",),
        ),
    ]

    def format_response(node):
        node.response = f"score: {node.score:5.2f}%\n" + node.response

Using json file:

class Faq(djamago.QA):
    source_json = "faqs.json"

    def format_response(node):
        ...

[!TIP] To use nltk python features, call pyoload.use_nltk(True), it will make sure the required tools are installed before modifying the setting globally

Using yaml file, (easier to read)

If you want an easy to read markup you will edit yourself, this the way forward

Make sure you have yaml installed(pip install PyYAML), then create a yaml file:

%YAML 1.2
---
- - - what is biology
    - what is the intent of biology
  - |
    Biology is the study of living things
  - |
    I do not know...
- - - why sbook
    - why creating sbook
    - what is the need of sbook
    - who needs sbook
    - why do we need sbook
  - |
    It have been noticed by [UNESCO](https://unesco.org) that a high number
    of children could not have acces to quality education, due to factors
    like:

    - Instability, political or location
    - Risks or Security due to threats as Thieves, or bullies.
    - Lack of infrastructure for building schools
    - Defficient curricula leading to incomplete learning.

    Reason why we @Antimony; crated Sbook, A web platform
- - - Who created Sbook
  - |
    Sbook web platform and mobile app were two created by @Antimony;

Then, you are all set!!, let's join all of that into a Djamgo instance

Running the app

Subclassing Djamago

We will simply sublass djamago

class MyChatbot(Djamago):
    def __init__(self):
        super().__init__("Jane Doe")

Adding the topics

MyChatbot.topic(Biology)
MyChatbot.topic(Faq)

Running it...

chatbot = MyChatbot()

while True:
    query = input("> ")
    node = chatbot.respond(query)
    print(node.response)
> Good morning ken-morel
Hello ken-morel!
> good after-noon ama
Hello ama!
> what is biology?
72.85533905932736
score: 72.86%
The study of live things
> what is bio
Sorry, I did not understand
> what is chemistry
Could you reformulate, please
>
Full source from djamago import *
use_nltk()


question = lambda re: (
    fr"(?:.*(?:please|question.?)? ?{re}\??)"
    fr"|(?:may )?i ask you {re}\??"
)  # Formulate the passed RegEx as a question

Expression.register("whois", [
    (100, r"(?:who is) (.*)"),
    (30, r"(?:do you know) (.*)"),
    # Score, regex
])
Expression.register("greetings", [
    (100, r"hello ?(.*)?"),
    (100, r"good (?:morning|evening|night|after-?noon) ?(.*)?"),
    (70, r"greetings ?(.*)?"),
    (20, r"good day ?(.*)?"),
])
Expression.register("name", [
    (70, r"((?:[\w_\-]+)+ ?)"),
])


class Biology(Topic):
    @Callback([
        (100, Expression("greetings(name)"))
    ])
    def greeted(node: Node):
        node.set_topics(("biology", "faq"))  # Set topics for the consecutive queries
        node.response = "Hello %s!" % node.vars.get("name", "You")

    @Callback([
        (0, RegEx(".*"))  # 0 not to override other answers
    ])
    def anything(node: Node):
        node.set_topics(("biology", "faq"))  # Set topics for the consecutive queries
        node.response = random.choice([
            "Sorry, I did not understand",
            "Could you reformulate, please"
        ])


class Faq(QA):
    data = [
        (
            ("what is biology",),
            ("The study of live things",),
        ),
        (
            (
                (70, "what is chemistry"),
            ),
            ("The study of chemical things",),
        ),
    ]

    def format_response(node):
        node.response = f"score: {node.score:5.2f}%\n" + node.response


class MyChatbot(Djamago):
    def __init__(self):
        super().__init__("Jane Doe")


MyChatbot.topic(Biology)
MyChatbot.topic(Faq)

chatbot = MyChatbot()
while True:
    query = input("> ")
    node = chatbot.respond(query)
    print(node.response)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

djamago-0.0.1.tar.gz (18.0 kB view hashes)

Uploaded Source

Built Distribution

djamago-0.0.1-py3-none-any.whl (14.3 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page