dynamic-learning-model 2.1.5__tar.gz → 3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dynamic_learning_model-2.1.5/dynamic_learning_model.egg-info → dynamic_learning_model-3.1}/PKG-INFO +9 -12
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/README.md +6 -11
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/dlm/DLM.py +114 -93
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1/dynamic_learning_model.egg-info}/PKG-INFO +9 -12
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/dynamic_learning_model.egg-info/requires.txt +2 -0
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/setup.py +4 -2
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/LICENSE +0 -0
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/dlm/__init__.py +0 -0
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/dynamic_learning_model.egg-info/SOURCES.txt +0 -0
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/dynamic_learning_model.egg-info/dependency_links.txt +0 -0
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/dynamic_learning_model.egg-info/top_level.txt +0 -0
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/pyproject.toml +0 -0
- {dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1}/setup.cfg +0 -0
{dynamic_learning_model-2.1.5/dynamic_learning_model.egg-info → dynamic_learning_model-3.1}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dynamic-learning-model
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.1
|
|
4
4
|
Summary: A Dynamic Learning Model for processing NLP queries using hybrid AI and reasoning.
|
|
5
5
|
Home-page: https://github.com/VigneshT24/Dynamic_Learning_Model
|
|
6
6
|
Author: Vignesh Thondikulam
|
|
@@ -16,6 +16,8 @@ Requires-Dist: nltk
|
|
|
16
16
|
Requires-Dist: spacy
|
|
17
17
|
Requires-Dist: better_profanity
|
|
18
18
|
Requires-Dist: word2number
|
|
19
|
+
Requires-Dist: transformers
|
|
20
|
+
Requires-Dist: hf_xet
|
|
19
21
|
Dynamic: author
|
|
20
22
|
Dynamic: author-email
|
|
21
23
|
Dynamic: classifier
|
|
@@ -30,6 +32,7 @@ Dynamic: summary
|
|
|
30
32
|
|
|
31
33
|

|
|
32
34
|

|
|
35
|
+

|
|
33
36
|
|
|
34
37
|
# Dynamic Learning Model
|
|
35
38
|
**ABOUT**:
|
|
@@ -50,8 +53,7 @@ Whether you're building a student support bot, a domain-specific assistant, or a
|
|
|
50
53
|
* The constructor requires passing in two parameters:
|
|
51
54
|
- Bot Mode:
|
|
52
55
|
- 'learn' = Enables training using the memory model. The bot can be updated with new information,
|
|
53
|
-
- '
|
|
54
|
-
- 'compute' = Activates the computation model for processing and solving queries algorithmically (no training)
|
|
56
|
+
- 'apply' = The bot automatically switches between its "compute" and "memory" model depending on the query asked
|
|
55
57
|
- Empty SQL Database for training the bot with queries and for the memory model
|
|
56
58
|
* The ask() method also requires passing in two parameters:
|
|
57
59
|
- Query: "What is the definition of FAFSA" (as an example)
|
|
@@ -74,22 +76,17 @@ training_bot = DLM("learn", "college_knowledge.db")
|
|
|
74
76
|
training_bot.ask("What is FAFSA in college?", True)
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
('
|
|
79
|
+
('apply' mode [deployment/production use after training])
|
|
78
80
|
```python
|
|
79
81
|
from dlm import DLM
|
|
80
82
|
|
|
81
|
-
commercial_bot = DLM("
|
|
83
|
+
commercial_bot = DLM("apply", "college_knowledge.db")
|
|
82
84
|
|
|
83
85
|
commercial_bot.ask("What is the difference between FAFSA and CADAA in California?", False)
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
('compute' mode [computation queries])
|
|
87
|
-
```python
|
|
88
|
-
from dlm import DLM
|
|
89
86
|
|
|
90
|
-
|
|
87
|
+
# or
|
|
91
88
|
|
|
92
|
-
|
|
89
|
+
commercial_bot.ask("Tell me the result for the following: 5 * 5 * 5 + 5 / 5", True)
|
|
93
90
|
```
|
|
94
91
|
|
|
95
92
|
**HIGH-LEVEL PIPELINE VISUAL**:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|

|
|
2
2
|

|
|
3
|
+

|
|
3
4
|
|
|
4
5
|
# Dynamic Learning Model
|
|
5
6
|
**ABOUT**:
|
|
@@ -20,8 +21,7 @@ Whether you're building a student support bot, a domain-specific assistant, or a
|
|
|
20
21
|
* The constructor requires passing in two parameters:
|
|
21
22
|
- Bot Mode:
|
|
22
23
|
- 'learn' = Enables training using the memory model. The bot can be updated with new information,
|
|
23
|
-
- '
|
|
24
|
-
- 'compute' = Activates the computation model for processing and solving queries algorithmically (no training)
|
|
24
|
+
- 'apply' = The bot automatically switches between its "compute" and "memory" model depending on the query asked
|
|
25
25
|
- Empty SQL Database for training the bot with queries and for the memory model
|
|
26
26
|
* The ask() method also requires passing in two parameters:
|
|
27
27
|
- Query: "What is the definition of FAFSA" (as an example)
|
|
@@ -44,22 +44,17 @@ training_bot = DLM("learn", "college_knowledge.db")
|
|
|
44
44
|
training_bot.ask("What is FAFSA in college?", True)
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
('
|
|
47
|
+
('apply' mode [deployment/production use after training])
|
|
48
48
|
```python
|
|
49
49
|
from dlm import DLM
|
|
50
50
|
|
|
51
|
-
commercial_bot = DLM("
|
|
51
|
+
commercial_bot = DLM("apply", "college_knowledge.db")
|
|
52
52
|
|
|
53
53
|
commercial_bot.ask("What is the difference between FAFSA and CADAA in California?", False)
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
('compute' mode [computation queries])
|
|
57
|
-
```python
|
|
58
|
-
from dlm import DLM
|
|
59
54
|
|
|
60
|
-
|
|
55
|
+
# or
|
|
61
56
|
|
|
62
|
-
|
|
57
|
+
commercial_bot.ask("Tell me the result for the following: 5 * 5 * 5 + 5 / 5", True)
|
|
63
58
|
```
|
|
64
59
|
|
|
65
60
|
**HIGH-LEVEL PIPELINE VISUAL**:
|
|
@@ -7,6 +7,7 @@ import sqlite3
|
|
|
7
7
|
import re
|
|
8
8
|
import nltk
|
|
9
9
|
import math
|
|
10
|
+
from transformers import pipeline
|
|
10
11
|
from better_profanity import profanity
|
|
11
12
|
from nltk.corpus import names
|
|
12
13
|
from word2number import w2n
|
|
@@ -19,12 +20,16 @@ class DLM:
|
|
|
19
20
|
__nlp = None # Spacy NLP analysis
|
|
20
21
|
__tone = None # sentimental tone of user query
|
|
21
22
|
__trainingPwd = "371507" # password to enter training mode
|
|
22
|
-
__mode = None # either "learn"
|
|
23
|
+
__mode = None # either "learn" or "apply"
|
|
23
24
|
__unsure_while_thinking = False # if uncertain while thinking, then it will let the user know that
|
|
24
25
|
__nlp_similarity_value = None # saves the similarity value by doing SpaCy calculation (for debugging)
|
|
25
26
|
__special_stripped_query = None # saves query without any special words for reduced interference while vector calculating
|
|
26
27
|
__nltk_names = set(name.lower() for name in names.words()) # list of name corpus to be identified in complex word problems
|
|
27
28
|
__refuse_to_respond = False # if profanity or all caps-lock frustration is detected, refuse to respond and suggest user to try again (bot respect)
|
|
29
|
+
__model = None # BETA: bot automatically chooses between "compute" or "memory" model based on query type
|
|
30
|
+
__hf_classifier = None # loading huggingface model to determine the query type for auto_mode
|
|
31
|
+
__successfully_computed = False # for when computation model was able to give an answer to a mathematical problem
|
|
32
|
+
__second_run = False # if the bot tried "memory" model first then decided to try "compute" model
|
|
28
33
|
|
|
29
34
|
# personalized responses to let the user know that the bot doesn't know the answer
|
|
30
35
|
__fallback_responses = [
|
|
@@ -177,7 +182,7 @@ class DLM:
|
|
|
177
182
|
"divide", "divided by", "split", "shared equally",
|
|
178
183
|
"per", "share", "shared", "equal parts", "equal groups",
|
|
179
184
|
"ratio", "quotient", "for each", "out of",
|
|
180
|
-
"for every", "into", "
|
|
185
|
+
"for every", "into", "/", "÷"
|
|
181
186
|
],
|
|
182
187
|
# convert
|
|
183
188
|
"=": [
|
|
@@ -356,21 +361,22 @@ class DLM:
|
|
|
356
361
|
|
|
357
362
|
Parameters:
|
|
358
363
|
mode (str): The access mode. Options:
|
|
359
|
-
'learn' for training mode (to train the bot with queries)
|
|
360
|
-
'
|
|
361
|
-
'compute' for mathematical queries (for arithmetic, conversion, or geometric queries).
|
|
364
|
+
'learn' for training mode (to train the bot with queries).
|
|
365
|
+
'apply' for a trained model to choose between compute and memory mode.
|
|
362
366
|
db_filename (str): The SQLite database file used to train and retrieve
|
|
363
367
|
question-answer-category triples.
|
|
364
368
|
|
|
365
369
|
Behavior:
|
|
366
370
|
- Loads the SpaCy NLP model ('en_core_web_lg').
|
|
371
|
+
- Loads the HuggingFace model for auto-model detection.
|
|
367
372
|
- Loads Better-Profanity for profane phrase sensing.
|
|
368
373
|
- Connects to the specified SQLite database file.
|
|
369
|
-
- Set appropriate mode value
|
|
370
|
-
- Verify login information based on mode
|
|
374
|
+
- Set appropriate mode value.
|
|
375
|
+
- Verify login information based on mode.
|
|
371
376
|
- Ensures the required table structure exists (creates if missing).
|
|
372
377
|
"""
|
|
373
378
|
self.__nlp = spacy.load("en_core_web_lg")
|
|
379
|
+
self.__hf_classifier = pipeline("zero-shot-classification", model="facebook/bart-large-mnli")
|
|
374
380
|
profanity.load_censor_words()
|
|
375
381
|
self.__filename = db_filename
|
|
376
382
|
self.__mode = mode
|
|
@@ -379,25 +385,22 @@ class DLM:
|
|
|
379
385
|
|
|
380
386
|
def __login_verification(self, mode): # no return, void
|
|
381
387
|
"""
|
|
382
|
-
Verify and initialize the selected access mode (Learn
|
|
388
|
+
Verify and initialize the selected access mode (Learn or Apply).
|
|
383
389
|
|
|
384
390
|
Parameters:
|
|
385
391
|
mode (str): The access mode. Options:
|
|
386
|
-
'learn' for training mode (to train the bot with queries)
|
|
387
|
-
'
|
|
388
|
-
'compute' for mathematical queries (for arithmetic or conversion queries).
|
|
392
|
+
'learn' for training mode (to train the bot with queries).
|
|
393
|
+
'apply' for trained model to choose "compute" or "memory" mode.
|
|
389
394
|
Behavior:
|
|
390
395
|
- If mode is 'learn', prompts for a password and displays mandatory training instructions.
|
|
391
|
-
- If mode is '
|
|
392
|
-
- If mode is 'compute', proceeds with computation model with reasoning capabilities.
|
|
396
|
+
- If mode is 'apply', enters without prompting password and allows model to answer queries.
|
|
393
397
|
"""
|
|
394
398
|
if mode.lower() == "learn":
|
|
395
399
|
password = input("Enter the password to enter Learn Mode: ")
|
|
396
400
|
while password != self.__trainingPwd:
|
|
397
|
-
password = input(
|
|
398
|
-
"Password is incorrect, try again or type 'stop' to enter in recall mode instead: ")
|
|
401
|
+
password = input("Password is incorrect, try again or type 'stop' to enter in apply mode instead: ")
|
|
399
402
|
if password.lower() == "stop":
|
|
400
|
-
self.__mode = "
|
|
403
|
+
self.__mode = "apply"
|
|
401
404
|
print("\n")
|
|
402
405
|
break
|
|
403
406
|
if password == self.__trainingPwd:
|
|
@@ -418,16 +421,13 @@ class DLM:
|
|
|
418
421
|
confirmation = input(
|
|
419
422
|
"Make sure to understand and note these instructions somewhere as the generated responses would get corrupt otherwise.\nType 'Y' if you understood: ")
|
|
420
423
|
while confirmation.lower() != "y": # trainers must understand the instructions above
|
|
421
|
-
confirmation = input(
|
|
422
|
-
"You cannot proceed to train without understanding the instructions aforementioned. Type 'Y' to continue: ")
|
|
424
|
+
confirmation = input("You cannot proceed to train without understanding the instructions aforementioned. Type 'Y' to continue: ")
|
|
423
425
|
self.__mode = "learn"
|
|
424
426
|
print("\n")
|
|
425
|
-
self.
|
|
427
|
+
self.__loading_animation("Logging in as Trainer", 0.6)
|
|
426
428
|
print("\n")
|
|
427
|
-
elif mode.lower() == "recall":
|
|
428
|
-
self.__mode = "recall"
|
|
429
429
|
else:
|
|
430
|
-
self.__mode = "
|
|
430
|
+
self.__mode = "apply"
|
|
431
431
|
|
|
432
432
|
def __create_table_if_missing(self): # no return, void
|
|
433
433
|
"""
|
|
@@ -436,10 +436,10 @@ class DLM:
|
|
|
436
436
|
Behavior:
|
|
437
437
|
- Establishes a connection to the SQLite database specified by self.__filename.
|
|
438
438
|
- Creates the 'knowledge_base' table if it does not exist, with the following columns:
|
|
439
|
-
- id (INTEGER, PRIMARY KEY, AUTOINCREMENT)
|
|
440
|
-
- question (TEXT, NOT NULL, UNIQUE)
|
|
441
|
-
- answer (TEXT, NOT NULL)
|
|
442
|
-
- category (TEXT, NOT NULL)
|
|
439
|
+
- id (INTEGER, PRIMARY KEY, AUTOINCREMENT).
|
|
440
|
+
- question (TEXT, NOT NULL, UNIQUE).
|
|
441
|
+
- answer (TEXT, NOT NULL).
|
|
442
|
+
- category (TEXT, NOT NULL).
|
|
443
443
|
- If the table already exists but is missing the 'category' column, the method adds it with a default empty string.
|
|
444
444
|
- Used exclusively within the class constructor to ensure the database schema is properly initialized.
|
|
445
445
|
"""
|
|
@@ -528,7 +528,7 @@ class DLM:
|
|
|
528
528
|
|
|
529
529
|
@staticmethod
|
|
530
530
|
# loading animation for bot thought process
|
|
531
|
-
def
|
|
531
|
+
def __loading_animation(user_input, duration): # no return, void
|
|
532
532
|
for seconds in range(0, 3):
|
|
533
533
|
print(f"{'\033[33m'}\r{user_input}{'.' * (seconds + 1)} {'\033[0m'}", end="", flush=True)
|
|
534
534
|
time.sleep(duration)
|
|
@@ -548,7 +548,7 @@ class DLM:
|
|
|
548
548
|
- Tokenizes the input into words.
|
|
549
549
|
- Removes filler words unless:
|
|
550
550
|
- It's the first word and part of the exception list.
|
|
551
|
-
- The current
|
|
551
|
+
- The current model is 'compute' and the word is a computation keyword.
|
|
552
552
|
- Preserves word order while removing duplicates.
|
|
553
553
|
- Joins the remaining words back into a single filtered string.
|
|
554
554
|
"""
|
|
@@ -571,7 +571,7 @@ class DLM:
|
|
|
571
571
|
for kws in self.__computation_identifiers.values()
|
|
572
572
|
for kw in kws)
|
|
573
573
|
|
|
574
|
-
if word_lowered not in self.__filler_words or (self.
|
|
574
|
+
if word_lowered not in self.__filler_words or (self.__model == "compute" and is_computation_kw):
|
|
575
575
|
filtered_words.append(word)
|
|
576
576
|
|
|
577
577
|
# remove duplicates while preserving order (numbers excluded)
|
|
@@ -601,12 +601,12 @@ class DLM:
|
|
|
601
601
|
Behavior:
|
|
602
602
|
- Detects aggressive language using profanity filtering.
|
|
603
603
|
- Analyzes punctuation and casing to infer emotional tone such as:
|
|
604
|
-
- 'angry aggressive' for profane content - refuse to respond
|
|
605
|
-
- 'angry frustrated' for all-uppercase text - refuse to respond
|
|
606
|
-
- 'angry confused' for combined "?" and "!"
|
|
607
|
-
- 'angry excited' for "!" only
|
|
608
|
-
- 'confused unclear' for "?" only
|
|
609
|
-
- 'doubtful uncertain' for ellipses ("..." or "..")
|
|
604
|
+
- 'angry aggressive' for profane content - refuse to respond.
|
|
605
|
+
- 'angry frustrated' for all-uppercase text - refuse to respond.
|
|
606
|
+
- 'angry confused' for combined "?" and "!".
|
|
607
|
+
- 'angry excited' for "!" only.
|
|
608
|
+
- 'confused unclear' for "?" only.
|
|
609
|
+
- 'doubtful uncertain' for ellipses ("..." or "..").
|
|
610
610
|
- Stores the result in self.__tone as a string label.
|
|
611
611
|
"""
|
|
612
612
|
is_profane = profanity.contains_profanity(orig_input)
|
|
@@ -631,20 +631,20 @@ class DLM:
|
|
|
631
631
|
|
|
632
632
|
def __geometric_calculation(self, filtered_query, display_thought): # returns float result or None
|
|
633
633
|
"""
|
|
634
|
-
Perform geometric problems that will be called inside perform_advanced_CoT
|
|
634
|
+
Perform geometric problems that will be called inside perform_advanced_CoT.
|
|
635
635
|
|
|
636
636
|
Parameters:
|
|
637
|
-
filtered_query (str): user query that has been filtered to have mostly computational details
|
|
638
|
-
display_thought (bool): Indicates whether the user wants to have the bot display its thought process or just give the answer
|
|
637
|
+
filtered_query (str): user query that has been filtered to have mostly computational details.
|
|
638
|
+
display_thought (bool): Indicates whether the user wants to have the bot display its thought process or just give the answer.
|
|
639
639
|
|
|
640
640
|
Returns:
|
|
641
|
-
float: The result after computing the geometric calculation
|
|
641
|
+
float: The result after computing the geometric calculation.
|
|
642
642
|
|
|
643
643
|
Behavior:
|
|
644
|
-
- Search through query to find specific keywords like 'area' or 'volume'
|
|
645
|
-
- Then, search to find shape or object to perform math on like 'triangle' or 'square'
|
|
646
|
-
- Find numbers associated with object details and store in appropriate list
|
|
647
|
-
- Finally, find appropriate formula with identifiers and plug in and return answer
|
|
644
|
+
- Search through query to find specific keywords like 'area' or 'volume'.
|
|
645
|
+
- Then, search to find shape or object to perform math on like 'triangle' or 'square'.
|
|
646
|
+
- Find numbers associated with object details and store in appropriate list.
|
|
647
|
+
- Finally, find appropriate formula with identifiers and plug in and return answer.
|
|
648
648
|
|
|
649
649
|
"""
|
|
650
650
|
height_value = None
|
|
@@ -739,19 +739,19 @@ class DLM:
|
|
|
739
739
|
# if allowed, display the inner thought process
|
|
740
740
|
obj_name = object_intel[1]
|
|
741
741
|
if display_thought:
|
|
742
|
-
self.
|
|
742
|
+
self.__loading_animation(f"It seems that the user wants to compute the {' of a '.join(object_intel)}", 0.5)
|
|
743
743
|
if height_value is not None:
|
|
744
|
-
self.
|
|
744
|
+
self.__loading_animation(
|
|
745
745
|
f"* The user has mentioned that the height of the {obj_name} object is {height_value}", 0.4)
|
|
746
746
|
else:
|
|
747
|
-
self.
|
|
747
|
+
self.__loading_animation(
|
|
748
748
|
f"* The {object_intel[1]} object has no height associated with it, so moving on", 0.4)
|
|
749
749
|
if len(other_values) > 0:
|
|
750
|
-
self.
|
|
750
|
+
self.__loading_animation(
|
|
751
751
|
f"* Additional numerical values associated with the dimensions of the {obj_name} object is {' and '.join(str(v) for v in other_values)}",
|
|
752
752
|
0.4)
|
|
753
753
|
else:
|
|
754
|
-
self.
|
|
754
|
+
self.__loading_animation(
|
|
755
755
|
f"* No additional numerical values associated with the dimensions of the {obj_name} were given",
|
|
756
756
|
0.4)
|
|
757
757
|
|
|
@@ -782,6 +782,11 @@ class DLM:
|
|
|
782
782
|
value_idx += 1
|
|
783
783
|
if len(other_values) <= 1:
|
|
784
784
|
break
|
|
785
|
+
|
|
786
|
+
if formula_inputs["height"] is None and len(other_values) > 1:
|
|
787
|
+
formula_inputs["height"] = other_values[len(other_values) - 1]
|
|
788
|
+
other_values.pop(len(other_values) - 1)
|
|
789
|
+
|
|
785
790
|
# Try calculating the result and return
|
|
786
791
|
result = round(formula(formula_inputs), 4)
|
|
787
792
|
return result
|
|
@@ -800,8 +805,8 @@ class DLM:
|
|
|
800
805
|
Perform advanced Chain-of-Thought (CoT) reasoning to solve arithmetic or unit conversion problems.
|
|
801
806
|
|
|
802
807
|
Parameters:
|
|
803
|
-
filtered_query (str): The cleaned user input, expected to be a math
|
|
804
|
-
display_thought (bool): Indicates whether the user wants to have the bot display its thought process or just give the answer
|
|
808
|
+
filtered_query (str): The cleaned user input, expected to be a math or logic-based question.
|
|
809
|
+
display_thought (bool): Indicates whether the user wants to have the bot display its thought process or just give the answer.
|
|
805
810
|
|
|
806
811
|
Behavior:
|
|
807
812
|
- Simulates step-by-step reasoning to solve arithmetic word problems without relying on memorized answers.
|
|
@@ -822,7 +827,7 @@ class DLM:
|
|
|
822
827
|
"sum", "combined", "add up", "accumulate", "bring to", "rise by", "grow by", "earned", "in all", "in total",
|
|
823
828
|
"difference", "deduct", "decrease by", "fell by", "drop by", "ate",
|
|
824
829
|
"multiply", "times", "product", "received", "pick", "paid", "gave", "pay",
|
|
825
|
-
"split", "shared equally", "equal parts", "equal groups", "ratio", "quotient", "
|
|
830
|
+
"split", "shared equally", "equal parts", "equal groups", "ratio", "quotient", "out of", "into"
|
|
826
831
|
]
|
|
827
832
|
filtered_query = filtered_query.title()
|
|
828
833
|
doc = self.__nlp(filtered_query)
|
|
@@ -830,8 +835,8 @@ class DLM:
|
|
|
830
835
|
if display_thought:
|
|
831
836
|
print(
|
|
832
837
|
f"{'\033[33m'}I am presented with a more involved query asking me to do some form of computation{'\033[0m'}")
|
|
833
|
-
self.
|
|
834
|
-
self.
|
|
838
|
+
self.__loading_animation("Let me think about this carefully and break it down so that I can solve it", 0.8)
|
|
839
|
+
self.__loading_animation(f"I’ve trimmed away any extra words so I’m focusing on \"{filtered_query}\" now",
|
|
835
840
|
0.8)
|
|
836
841
|
|
|
837
842
|
# Have the bot pick out names mentioned (in order) using SpaCy and NLTK (for maximum coverage)
|
|
@@ -898,9 +903,7 @@ class DLM:
|
|
|
898
903
|
# Direct match or lemma match
|
|
899
904
|
if (kw.lower() == fq.lower()) or p1[0].lemma_ == p2[0].lemma_:
|
|
900
905
|
keywords_mentioned.append(kw.title())
|
|
901
|
-
if kw.lower() == "
|
|
902
|
-
operands_mentioned.append("+")
|
|
903
|
-
elif kw.lower() == "out of":
|
|
906
|
+
if kw.lower() == "out of":
|
|
904
907
|
if word_num_surrounded:
|
|
905
908
|
operands_mentioned.append(operand)
|
|
906
909
|
found_operand = True
|
|
@@ -915,9 +918,7 @@ class DLM:
|
|
|
915
918
|
if p1.vector_norm != 0 and p2.vector_norm != 0 and (
|
|
916
919
|
p1.similarity(p2) > 0.80 and difflib.SequenceMatcher(None, kw, fq_l).ratio() > 0.40):
|
|
917
920
|
keywords_mentioned.append(kw.title())
|
|
918
|
-
if kw.lower() == "
|
|
919
|
-
operands_mentioned.append("+")
|
|
920
|
-
elif kw.lower() == "out of":
|
|
921
|
+
if kw.lower() == "out of":
|
|
921
922
|
if word_num_surrounded:
|
|
922
923
|
operands_mentioned.append(operand)
|
|
923
924
|
found_operand = True
|
|
@@ -931,9 +932,7 @@ class DLM:
|
|
|
931
932
|
# Fallback: high string similarity
|
|
932
933
|
elif difflib.SequenceMatcher(None, kw, fq_l).ratio() > 0.80:
|
|
933
934
|
keywords_mentioned.append(kw.title())
|
|
934
|
-
if kw.lower() == "
|
|
935
|
-
operands_mentioned.append("+")
|
|
936
|
-
elif kw.lower() == "out of":
|
|
935
|
+
if kw.lower() == "out of":
|
|
937
936
|
if word_num_surrounded:
|
|
938
937
|
operands_mentioned.append(operand)
|
|
939
938
|
found_operand = True
|
|
@@ -1028,34 +1027,36 @@ class DLM:
|
|
|
1028
1027
|
operands_mentioned = [op for op in operands_mentioned if op != '=']
|
|
1029
1028
|
|
|
1030
1029
|
# verify and possibly print thoughts
|
|
1031
|
-
if (not is_geometric_query) and (any(not lst for lst in (num_mentioned, operands_mentioned)) or (
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1030
|
+
if (not is_geometric_query) and (any(not lst for lst in (num_mentioned, operands_mentioned)) or ('=' not in operands_mentioned and num_mentioned.__len__() < 2)): # don't compute if parts are missing
|
|
1031
|
+
if (not self.__second_run):
|
|
1032
|
+
print(
|
|
1033
|
+
f"{self.__loading_animation('Hmm', 0.8) or '' if display_thought else ''}{'\033[34m'}It looks like some essential details are missing, so I can’t complete this calculation right now.{'\033[0m'}")
|
|
1034
|
+
print(
|
|
1035
|
+
f"\033[34mIf you are asking a geometric query, try including geometric identifiers like \"{'\", \"'.join(geo_types)}\" in your query.\033[0m")
|
|
1036
|
+
print(
|
|
1037
|
+
f"\033[34mCurrently, I can only compute those identifiers aforementioned, but more geometric features are coming soon!\033[0m")
|
|
1038
|
+
else:
|
|
1039
|
+
self.__loading_animation('Hmm', 0.8)
|
|
1039
1040
|
else: # else, the bot needs to explain what it has tokenized
|
|
1040
1041
|
if display_thought:
|
|
1041
|
-
self.
|
|
1042
|
+
self.__loading_animation(
|
|
1042
1043
|
f"1.) I see {', '.join(persons_mentioned) if persons_mentioned.__len__() >= 1 else 'no one'} mentioned as a person name; "
|
|
1043
1044
|
f"{'they’re likely key to this problem' if persons_mentioned.__len__() >= 1 else 'moving on'}", 0.2)
|
|
1044
|
-
self.
|
|
1045
|
+
self.__loading_animation(
|
|
1045
1046
|
f"2.) Moreover, I see {', '.join(items_mentioned) if items_mentioned.__len__() >= 1 else 'no items'} mentioned as proper nouns; "
|
|
1046
1047
|
f"{'this might be a key thing to this problem' if items_mentioned.__len__() >= 1 else 'moving on'}",
|
|
1047
1048
|
0.2)
|
|
1048
1049
|
if is_geometric_query:
|
|
1049
|
-
self.
|
|
1050
|
+
self.__loading_animation(f"3.) This is a geometric problem and I have already computed the answer",
|
|
1050
1051
|
0.2)
|
|
1051
1052
|
else:
|
|
1052
|
-
self.
|
|
1053
|
+
self.__loading_animation(
|
|
1053
1054
|
f"3.) I’ve also identified the numbers {' and '.join(num_mentioned)} that I need to compute with",
|
|
1054
1055
|
0.2)
|
|
1055
|
-
self.
|
|
1056
|
+
self.__loading_animation(
|
|
1056
1057
|
f"4.) I see the keywords \"{'\" and \"'.join(keywords_mentioned)}\", meaning I need to perform a \"{'\" and \"'.join(operands_mentioned)}\" operation for this query; I’ll use that to guide my calculation",
|
|
1057
1058
|
0.2)
|
|
1058
|
-
self.
|
|
1059
|
+
self.__loading_animation("Now I have the parts, so let me put it all together and solve", 0.3)
|
|
1059
1060
|
|
|
1060
1061
|
# Finally compute it and then give the response (if there is any)
|
|
1061
1062
|
# move "originally" numbers to the front
|
|
@@ -1091,6 +1092,7 @@ class DLM:
|
|
|
1091
1092
|
# geometric problem
|
|
1092
1093
|
if is_geometric_query:
|
|
1093
1094
|
print(f"{'\033[34m'}Geometric Answer: {geometric_ans}{'\033[0m'}")
|
|
1095
|
+
self.__successfully_computed = True
|
|
1094
1096
|
# conversion problem
|
|
1095
1097
|
elif len(num_mentioned) == 1 and len(operands_mentioned) == 1:
|
|
1096
1098
|
try:
|
|
@@ -1165,11 +1167,12 @@ class DLM:
|
|
|
1165
1167
|
if source_key and target_key:
|
|
1166
1168
|
result = (num0 * self.__units[source_key]) / self.__units[target_key]
|
|
1167
1169
|
if display_thought:
|
|
1168
|
-
self.
|
|
1170
|
+
self.__loading_animation(
|
|
1169
1171
|
f"I need to take {num0} and multiply it by {self.__units[source_key]}. Finally, I divide by {self.__units[target_key]} and I got my answer",
|
|
1170
1172
|
0.2)
|
|
1171
1173
|
expr = f"{num_mentioned[0]} {source_key}(s) ==> {round(result, 2)} {target_key}(s)"
|
|
1172
1174
|
print(f"{'\033[34m'}Conversion Answer: {expr} {'\033[0m'}")
|
|
1175
|
+
self.__successfully_computed = True
|
|
1173
1176
|
else:
|
|
1174
1177
|
print(f"{'\033[33m'}Could not identify both source and target units.{'\033[0m'}")
|
|
1175
1178
|
except SyntaxError:
|
|
@@ -1195,10 +1198,12 @@ class DLM:
|
|
|
1195
1198
|
expr = "(" + expr + ") / " + str(len(num_mentioned))
|
|
1196
1199
|
result /= len(num_mentioned)
|
|
1197
1200
|
print(f"{'\033[34m'}Arithmetic Answer: {expr} = {result}{'\033[0m'}")
|
|
1201
|
+
self.__successfully_computed = True
|
|
1198
1202
|
except SyntaxError:
|
|
1199
1203
|
print(
|
|
1200
1204
|
f"{'\033[34mAh'}, something about that stumped me. I’ll need to learn more to handle it properly.{'\033[0m'}")
|
|
1201
1205
|
else:
|
|
1206
|
+
self.__successfully_computed = False
|
|
1202
1207
|
print(f"{'\033[34m'}{random.choice(self.__fallback_responses)}{'\033[0m'}")
|
|
1203
1208
|
print(
|
|
1204
1209
|
f"{'\033[34m'}However, while I was trying to understand the math, I ran into \"{'" and "'.join(keywords_mentioned)}\", which I use to connect keywords to math operations.{'\033[0m'}")
|
|
@@ -1214,7 +1219,7 @@ class DLM:
|
|
|
1214
1219
|
best_match_question (str): The closest matching question found in the knowledge base.
|
|
1215
1220
|
best_match_answer (str): The corresponding answer to the matched question.
|
|
1216
1221
|
highest_similarity (float): The calculated string similarity score (0 to 1) for the match.
|
|
1217
|
-
display_thought (bool): "True" if the bot is allowed to print its thought or else "False"
|
|
1222
|
+
display_thought (bool): "True" if the bot is allowed to print its thought or else "False".
|
|
1218
1223
|
|
|
1219
1224
|
Behavior:
|
|
1220
1225
|
- Outputs step-by-step reasoning in a conversational format (e.g., interpreting the question's structure and tone).
|
|
@@ -1234,7 +1239,7 @@ class DLM:
|
|
|
1234
1239
|
if self.__tone != "":
|
|
1235
1240
|
print(
|
|
1236
1241
|
f"{'\033[33m'}Right off the bat, the user seems quite {sentiment_tone[0]} or {sentiment_tone[1]} by their query tone. Hopefully I won't disappoint!{'\033[0m'}")
|
|
1237
|
-
if self.
|
|
1242
|
+
if self.__model == "compute":
|
|
1238
1243
|
self.__perform_advanced_CoT(filtered_query, display_thought)
|
|
1239
1244
|
else:
|
|
1240
1245
|
interrogative_start = filtered_query.split()[0]
|
|
@@ -1254,7 +1259,7 @@ class DLM:
|
|
|
1254
1259
|
else:
|
|
1255
1260
|
print(
|
|
1256
1261
|
f"{'\033[33m'}The user starts their query with \"{interrogative_start.title()}\" and they are asking about \"{" ".join(identifier).title()}\".{'\033[0m'}")
|
|
1257
|
-
self.
|
|
1262
|
+
self.__loading_animation("Let me think about this carefully", 0.8)
|
|
1258
1263
|
|
|
1259
1264
|
for s in special_start:
|
|
1260
1265
|
for u in filtered_query.split():
|
|
@@ -1275,7 +1280,7 @@ class DLM:
|
|
|
1275
1280
|
print(
|
|
1276
1281
|
f"{'\033[33m'}Furthermore, an in-depth vector analysis revealed a similarity percentage of {int(self.__nlp_similarity_value * 100)}%.{'\033[0m'}")
|
|
1277
1282
|
print(
|
|
1278
|
-
f"{self.
|
|
1283
|
+
f"{self.__loading_animation("Hmm", 0.8) or ''}{'\033[33m'}I don't think I know the answer.{'\033[0m'}")
|
|
1279
1284
|
self.__unsure_while_thinking = True
|
|
1280
1285
|
else:
|
|
1281
1286
|
self.__unsure_while_thinking = False
|
|
@@ -1287,9 +1292,9 @@ class DLM:
|
|
|
1287
1292
|
if spacy_proceed:
|
|
1288
1293
|
print(
|
|
1289
1294
|
f"Additionally, doing a more in-depth vector NLP analysis resulted in {int(self.__nlp_similarity_value * 100)}% similarity. Although there are room for error, we will see.{'\033[0m'}")
|
|
1290
|
-
self.
|
|
1295
|
+
self.__loading_animation("Let me recall that answer", 0.8)
|
|
1291
1296
|
print("\n")
|
|
1292
|
-
elif self.
|
|
1297
|
+
elif self.__model == "compute":
|
|
1293
1298
|
self.__perform_advanced_CoT(filtered_query, display_thought)
|
|
1294
1299
|
|
|
1295
1300
|
def __generate_response(self, best_match_answer, best_match_question): # no return, void
|
|
@@ -1564,16 +1569,17 @@ class DLM:
|
|
|
1564
1569
|
NOTICE: To make the bot run continuously, implement a loop in your program.
|
|
1565
1570
|
|
|
1566
1571
|
Parameters:
|
|
1567
|
-
query (str): Question the bot would
|
|
1568
|
-
display_thought (bool): "True" for allowing bot to print its thought and CoT or "False"
|
|
1572
|
+
query (str): Question the bot would learn or respond to.
|
|
1573
|
+
display_thought (bool): "True" for allowing bot to print its thought and CoT or "False".
|
|
1569
1574
|
|
|
1570
1575
|
Behavior:
|
|
1571
1576
|
- Prompts the user for input.
|
|
1577
|
+
- Determines whether to choose "compute" or "memory" model to respond.
|
|
1572
1578
|
- Detects tone, filters input, searches knowledge base.
|
|
1573
1579
|
- Performs Chain-of-Thought (CoT) while recalling learnt answer.
|
|
1574
1580
|
- If match is found, generates a response.
|
|
1575
1581
|
- If in learning mode and answer is incorrect or not found, prompts user to teach the bot.
|
|
1576
|
-
- In
|
|
1582
|
+
- In apply mode, automatically chooses between its compute and memory model to answer the query.
|
|
1577
1583
|
"""
|
|
1578
1584
|
self.__query = query
|
|
1579
1585
|
while self.__query is None or self.__query == "":
|
|
@@ -1587,9 +1593,18 @@ class DLM:
|
|
|
1587
1593
|
self.__query = input("Empty input is unacceptable. Please enter something: ")
|
|
1588
1594
|
self.__set_sentiment_tone(self.__query)
|
|
1589
1595
|
|
|
1596
|
+
# auto model choose using HuggingFace
|
|
1597
|
+
if self.__mode != "learn":
|
|
1598
|
+
auto_model_choice = self.__hf_classifier(self.__query, ["mathematical", "not mathematical"])["labels"][0]
|
|
1599
|
+
if auto_model_choice == "mathematical":
|
|
1600
|
+
self.__model = "compute"
|
|
1601
|
+
else:
|
|
1602
|
+
self.__model = "memory"
|
|
1603
|
+
else:
|
|
1604
|
+
self.__model = "memory"
|
|
1590
1605
|
|
|
1591
1606
|
# storing the user-query (filtered, lower-case, no punctuation)
|
|
1592
|
-
if self.
|
|
1607
|
+
if self.__model == "compute":
|
|
1593
1608
|
# We want to keep the following
|
|
1594
1609
|
keep = {".", "+", "-", "*", "/", "="}
|
|
1595
1610
|
to_remove = "".join(ch for ch in string.punctuation if ch not in keep)
|
|
@@ -1597,9 +1612,7 @@ class DLM:
|
|
|
1597
1612
|
to_remove = string.punctuation
|
|
1598
1613
|
|
|
1599
1614
|
translation_table = str.maketrans("", "", to_remove)
|
|
1600
|
-
filtered_query = self.__filtered_input(
|
|
1601
|
-
self.__query.lower().translate(translation_table)
|
|
1602
|
-
)
|
|
1615
|
+
filtered_query = self.__filtered_input(self.__query.lower().translate(translation_table))
|
|
1603
1616
|
|
|
1604
1617
|
# match_query is the query without special words to prevent interference with SpaCy similarity
|
|
1605
1618
|
self.__special_stripped_query = filtered_query
|
|
@@ -1637,7 +1650,7 @@ class DLM:
|
|
|
1637
1650
|
display_thought)
|
|
1638
1651
|
|
|
1639
1652
|
# accept a match if highest_similarity is 65% or more, or if semantic similarity is recognized
|
|
1640
|
-
if self.
|
|
1653
|
+
if self.__model == "memory":
|
|
1641
1654
|
if (not self.__unsure_while_thinking) and ((highest_similarity >= 0.65) or (
|
|
1642
1655
|
best_match_answer and self.__semantic_similarity(self.__special_stripped_query,
|
|
1643
1656
|
best_match_question))):
|
|
@@ -1674,5 +1687,13 @@ class DLM:
|
|
|
1674
1687
|
self.__learn(self.__expectation,
|
|
1675
1688
|
self.__category) # learn this new question and answer pair and add to knowledgebase
|
|
1676
1689
|
print("I learned something new!") # confirmation that it went through the whole process
|
|
1677
|
-
else: # only executes when in
|
|
1678
|
-
|
|
1690
|
+
else: # only executes when in apply mode and bot cannot find the answer
|
|
1691
|
+
self.__loading_animation(f"Let me put this into my computation model, maybe it was a mathematical query", 0.5)
|
|
1692
|
+
self.__model = "compute"
|
|
1693
|
+
self.__second_run = True
|
|
1694
|
+
self.__generate_thought(filtered_query, best_match_question, best_match_answer, highest_similarity,
|
|
1695
|
+
display_thought)
|
|
1696
|
+
if not self.__successfully_computed:
|
|
1697
|
+
print(f"{'\033[34m'}{random.choice(self.__fallback_responses)}{'\033[0m'}")
|
|
1698
|
+
self.__second_run = False
|
|
1699
|
+
self.__successfully_computed = False
|
{dynamic_learning_model-2.1.5 → dynamic_learning_model-3.1/dynamic_learning_model.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dynamic-learning-model
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.1
|
|
4
4
|
Summary: A Dynamic Learning Model for processing NLP queries using hybrid AI and reasoning.
|
|
5
5
|
Home-page: https://github.com/VigneshT24/Dynamic_Learning_Model
|
|
6
6
|
Author: Vignesh Thondikulam
|
|
@@ -16,6 +16,8 @@ Requires-Dist: nltk
|
|
|
16
16
|
Requires-Dist: spacy
|
|
17
17
|
Requires-Dist: better_profanity
|
|
18
18
|
Requires-Dist: word2number
|
|
19
|
+
Requires-Dist: transformers
|
|
20
|
+
Requires-Dist: hf_xet
|
|
19
21
|
Dynamic: author
|
|
20
22
|
Dynamic: author-email
|
|
21
23
|
Dynamic: classifier
|
|
@@ -30,6 +32,7 @@ Dynamic: summary
|
|
|
30
32
|
|
|
31
33
|

|
|
32
34
|

|
|
35
|
+

|
|
33
36
|
|
|
34
37
|
# Dynamic Learning Model
|
|
35
38
|
**ABOUT**:
|
|
@@ -50,8 +53,7 @@ Whether you're building a student support bot, a domain-specific assistant, or a
|
|
|
50
53
|
* The constructor requires passing in two parameters:
|
|
51
54
|
- Bot Mode:
|
|
52
55
|
- 'learn' = Enables training using the memory model. The bot can be updated with new information,
|
|
53
|
-
- '
|
|
54
|
-
- 'compute' = Activates the computation model for processing and solving queries algorithmically (no training)
|
|
56
|
+
- 'apply' = The bot automatically switches between its "compute" and "memory" model depending on the query asked
|
|
55
57
|
- Empty SQL Database for training the bot with queries and for the memory model
|
|
56
58
|
* The ask() method also requires passing in two parameters:
|
|
57
59
|
- Query: "What is the definition of FAFSA" (as an example)
|
|
@@ -74,22 +76,17 @@ training_bot = DLM("learn", "college_knowledge.db")
|
|
|
74
76
|
training_bot.ask("What is FAFSA in college?", True)
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
('
|
|
79
|
+
('apply' mode [deployment/production use after training])
|
|
78
80
|
```python
|
|
79
81
|
from dlm import DLM
|
|
80
82
|
|
|
81
|
-
commercial_bot = DLM("
|
|
83
|
+
commercial_bot = DLM("apply", "college_knowledge.db")
|
|
82
84
|
|
|
83
85
|
commercial_bot.ask("What is the difference between FAFSA and CADAA in California?", False)
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
('compute' mode [computation queries])
|
|
87
|
-
```python
|
|
88
|
-
from dlm import DLM
|
|
89
86
|
|
|
90
|
-
|
|
87
|
+
# or
|
|
91
88
|
|
|
92
|
-
|
|
89
|
+
commercial_bot.ask("Tell me the result for the following: 5 * 5 * 5 + 5 / 5", True)
|
|
93
90
|
```
|
|
94
91
|
|
|
95
92
|
**HIGH-LEVEL PIPELINE VISUAL**:
|
|
@@ -5,7 +5,7 @@ with open('README.md', 'r', encoding='utf-8') as f:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name='dynamic-learning-model',
|
|
8
|
-
version='
|
|
8
|
+
version='3.1',
|
|
9
9
|
author='Vignesh Thondikulam',
|
|
10
10
|
author_email='vignesh.tho2006@gmail.com',
|
|
11
11
|
description='A Dynamic Learning Model for processing NLP queries using hybrid AI and reasoning.',
|
|
@@ -18,7 +18,9 @@ setup(
|
|
|
18
18
|
'nltk',
|
|
19
19
|
'spacy',
|
|
20
20
|
'better_profanity',
|
|
21
|
-
'word2number'
|
|
21
|
+
'word2number',
|
|
22
|
+
'transformers',
|
|
23
|
+
'hf_xet'
|
|
22
24
|
],
|
|
23
25
|
classifiers=[
|
|
24
26
|
'Programming Language :: Python :: 3',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|