Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add evaluate_mathematically #80

Closed
wants to merge 16 commits into from
Closed

Conversation

DarkmatterVale
Copy link
Collaborator

Here is my first attempt at adding a way to evaluate mathematical expressions. @gunthercox what do you think? What are your thoughts on improving implementation?

A couple of notes. This is not finished, but I am at a point where I need to get input on how to implement it into the program. It currently looks at every incoming question or statement and attempts to decide whether or not the point is to evaluate a mathematical expression. This sort of works, but you run into issues pretty easily once you start describing the quantity of an object. It might think you are trying to have a mathematical expression evaluated, and then it will give the incorrect answer.

Another thing to note is the way I structured the function. I decided to create a new kind of adapter because this is definitely not an io adapter, nor is it a storage adapter. You could argue it is a logic adapter, but it doesn't work independent of another logic adapter.

Also, the reason the build is failing is because the answer in Python 3.x comes out to 1.0 while in 2.7 it is 1.

Doesn’t actually do anything yet, but it works :)
The class can now evaluate basic expressions & successfully completes
tests
More dynamic input is allowed
Now, it can successfully take any size number that is represented in
word ( if they are in the table, which is the next thing to improve )
- Updated storage to be more dynamic
- Removed error causing print statement
- Finished tests
@gunthercox
Copy link
Owner

@DarkmatterVale This is awesome. I will go over this pull request and provide some thorough feedback as soon as possible.

So far I think I like the concept of the processor adapter. This might be a really good addition in the future for determining if logic adapters need to run in other multi-logic adapter scenarios.

@DarkmatterVale
Copy link
Collaborator Author

I had a similar thought process and agree that this could be very useful in the future. This will come especially in handy when you need a logic adapter in addition to a context adapter (or other kinds of adapters).

@DarkmatterVale
Copy link
Collaborator Author

I have renamed the addition so that evaluate_mathematically() is now a plugin. This is a much better name for the function's purpose.

Also, plugins should allow for "external" functionality to be implemented, while Logic adapters should act as the way the user interfaces with the chatbot. In the future, we can use the plugins directory to add new functions such as sending emails, reading twitter messages, etc.

- Updated implementation, making it more dynamic
- Expansion for future plugins is easy now
- Cleaned up evaluate_mathematically() tests
it returns False.
"""

if string.isdigit():
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this handle negative integers?

If not, it should be possible to detect them like this:

string.lstrip('-').isdigit()

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I have made sure that it will handle negative integers without any issues

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are lacking tests for negative numbers, which is why I'm also curious about how they are being handled.

isdigit will return False if there are any non-digits (including decimals and the negative sign) in the string.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added tests in my next commit. They were previously being treated as floats, which I have now changed by replacing the is_integer() code with:

try:
            return int( string )
except:
            return False

@@ -207,4 +224,3 @@ def test_database_is_not_updated_when_read_only(self):

self.assertFalse(exists_before)
self.assertFalse(exists_after)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why this is happening with the last line of a file...I will look at how to fix this with Atom within the next week and incorporate additional lines into a future commit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like Atom was removing the extra blank line at the end of the file.

There were two blank lines before, now there is only one.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes more sense than my theory :)

@DarkmatterVale
Copy link
Collaborator Author

@gunthercox and @kevin-brown Do you guys have any more questions? Do I need to give a more in-depth explanation for how the code works?

@gunthercox
Copy link
Owner

I'm checking this out locally using examples/terminal_example.py. It appears that when I enter a value that contains a mathematical expression, such as "What is 5 + 5?", no response is returned. This is strange since I can clearly see that tests are passing.

@DarkmatterVale
Copy link
Collaborator Author

I had the same problem. In fact, I am unable to see any changes I make to the code when I run the examples ( just in general ). The best way to test, which is the way I do it because of this issue, is to add a print statement right before the return statement. Then rerun the tests with --nocapture. The before and after code is below.

Before:

if not plugin_response is False:
     return plugin_response

After:

if not plugin_response is False:
     print plugin_response
     return plugin_response

The problem ( since I ran into the same issue on other projects ) is that the examples use the version of chatterbot currently installed on the computer, and not the local repository. Have you ever encountered the same situation?

@gunthercox
Copy link
Owner

In general, a good way to test out changes to python packages that are also imported in other local projects is just to install the package (with the changes you have made) locally.

This can be done using:

pip install . --upgrade

This should be run from within the same directory as setup.py.


Also, another item I noticed is that you will need to include the json data file you created in the installed package. This can be done by adding the following line to MANIFEST.in:

recursive-include chatterbot/adapters/* *.json

@DarkmatterVale
Copy link
Collaborator Author

Thank you for that information! I will not make these mistakes again; sorry for not doing things properly in the first place!

I was able to test ( correctly this time ) the adapter and I found the problem. I was not processing the response properly, leading it to not being displayed. This is fixed in the next commit along with the MANIFEST.in update. Please let me know if this fixes the problem on your machine!

@gunthercox
Copy link
Owner

No problem, this is all really good work and its cool to see it coming together. Also, that corrected the issue.

@DarkmatterVale
Copy link
Collaborator Author

Awesome, glad that fixed the issue! I will remember all of this next time I make changes so you guys don't have to spend hours reviewing code :D

How does it work? I know it doesn't work for all math expressions ( far from it ), but it is a start and a place to work from.

@gunthercox
Copy link
Owner

Code review is a part of programming. It's always possible to make a mistake, having a few more sets of eyes on it never hurts.

So far everything that I'm seeing here looks great. Performance-wise it works excellently. At the moment I believe there is only one more thing in the code that I believe could be improved, I'll leave a comment about it on the line.


string = ''

for chunk in input_text.split( ' ' ):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I use input_text.split() instead of input_text.split( ' ' )? That way I would be separating the words based on all whitespace characters not just spaces.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, input_text.split() is the way to go here 👍

@gunthercox
Copy link
Owner

@DarkmatterVale These changes look good to me. Did you have any more additions before I merge this?

@DarkmatterVale
Copy link
Collaborator Author

No I do not have any additional changes to make.

@gunthercox
Copy link
Owner

Alright, just did a manual merge with master because there was some conflicts that GitHub couldn't resolve automatically. Either way, this is an awesome addition and it will be available in the next release on pypi.

@gunthercox gunthercox closed this Dec 4, 2015
@gunthercox gunthercox deleted the evaluate_mathematically branch December 4, 2015 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants