dynamic-learning-model 1.1.1__tar.gz → 1.2.5__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-1.1.1/dynamic_learning_model.egg-info → dynamic_learning_model-1.2.5}/PKG-INFO +1 -1
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/dlm/DLM.py +109 -83
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5/dynamic_learning_model.egg-info}/PKG-INFO +1 -1
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/setup.py +1 -1
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/LICENSE +0 -0
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/README.md +0 -0
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/dlm/__init__.py +0 -0
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/dynamic_learning_model.egg-info/SOURCES.txt +0 -0
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/dynamic_learning_model.egg-info/dependency_links.txt +0 -0
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/dynamic_learning_model.egg-info/requires.txt +0 -0
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/dynamic_learning_model.egg-info/top_level.txt +0 -0
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/pyproject.toml +0 -0
- {dynamic_learning_model-1.1.1 → dynamic_learning_model-1.2.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dynamic-learning-model
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.5
|
|
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
|
|
@@ -491,7 +491,9 @@ class DLM:
|
|
|
491
491
|
float(word) # Try to treat as number
|
|
492
492
|
unique_words.append(word) # Keep numeric strings (duplicates allowed)
|
|
493
493
|
except ValueError:
|
|
494
|
-
if word
|
|
494
|
+
if any(word in keywords for keywords in self.__computation_identifiers.values()):
|
|
495
|
+
unique_words.append(word) # Keep identifier words (duplicates allowed)
|
|
496
|
+
elif word not in seen:
|
|
495
497
|
seen.add(word)
|
|
496
498
|
unique_words.append(word)
|
|
497
499
|
|
|
@@ -532,12 +534,13 @@ class DLM:
|
|
|
532
534
|
else:
|
|
533
535
|
self.__tone = ""
|
|
534
536
|
|
|
535
|
-
def __perform_advanced_CoT(self, filtered_query): # no return, void
|
|
537
|
+
def __perform_advanced_CoT(self, filtered_query, display_thought): # no return, void
|
|
536
538
|
"""
|
|
537
539
|
Perform advanced Chain-of-Thought (CoT) reasoning to solve arithmetic or unit conversion problems.
|
|
538
540
|
|
|
539
541
|
Parameters:
|
|
540
542
|
filtered_query (str): The cleaned user input, expected to be a math- or logic-based question.
|
|
543
|
+
display_thought (bool): Indicates whether the user wants to have the bot display its thought process or just give the answer
|
|
541
544
|
|
|
542
545
|
Behavior:
|
|
543
546
|
- Simulates step-by-step reasoning to solve arithmetic word problems without relying on memorized answers.
|
|
@@ -545,14 +548,9 @@ class DLM:
|
|
|
545
548
|
- Detects arithmetic operations via lexical and semantic matching with predefined keyword sets.
|
|
546
549
|
- Handles both numeric digits and text-based numbers (e.g., "three", "double").
|
|
547
550
|
- Supports simple arithmetic expressions and unit conversions (e.g., inches to cm).
|
|
548
|
-
- Prints the interpreted steps, logical inferences, and the final computed result with contextual explanations.
|
|
551
|
+
- Prints the interpreted steps, logical inferences (if display_thought is True), and the final computed result with contextual explanations.
|
|
549
552
|
- Displays fallback messages if the query is incomplete or too ambiguous to solve.
|
|
550
553
|
"""
|
|
551
|
-
print(
|
|
552
|
-
f"{'\033[33m'}I am presented with a more involved query asking me to do some form of computation{'\033[0m'}")
|
|
553
|
-
self.__loadingAnimation("Let me think about this carefully and break it down so that I can solve it", 0.8)
|
|
554
|
-
self.__loadingAnimation(
|
|
555
|
-
f"I’ve trimmed away any extra words so I’m focusing on \"{filtered_query.title()}\" now", 0.8)
|
|
556
554
|
persons_mentioned = []
|
|
557
555
|
items_mentioned = []
|
|
558
556
|
keywords_mentioned = []
|
|
@@ -568,6 +566,13 @@ class DLM:
|
|
|
568
566
|
filtered_query = filtered_query.title()
|
|
569
567
|
doc = self.__nlp(filtered_query)
|
|
570
568
|
|
|
569
|
+
if display_thought:
|
|
570
|
+
print(
|
|
571
|
+
f"{'\033[33m'}I am presented with a more involved query asking me to do some form of computation{'\033[0m'}")
|
|
572
|
+
self.__loadingAnimation("Let me think about this carefully and break it down so that I can solve it", 0.8)
|
|
573
|
+
self.__loadingAnimation(f"I’ve trimmed away any extra words so I’m focusing on \"{filtered_query}\" now",
|
|
574
|
+
0.8)
|
|
575
|
+
|
|
571
576
|
# Have the bot pick out names mentioned (in order) using SpaCy and NLTK (for maximum coverage)
|
|
572
577
|
for ent in doc.ents:
|
|
573
578
|
if ent.label_ == "PERSON":
|
|
@@ -603,6 +608,7 @@ class DLM:
|
|
|
603
608
|
continue
|
|
604
609
|
if fq_l in {"+", "-", "*", "/"}:
|
|
605
610
|
operands_mentioned.append(fq_l)
|
|
611
|
+
keywords_mentioned.append(fq_l)
|
|
606
612
|
continue # move on to the next token
|
|
607
613
|
for operand, keywords in self.__computation_identifiers.items():
|
|
608
614
|
for kw in keywords:
|
|
@@ -741,7 +747,6 @@ class DLM:
|
|
|
741
747
|
else:
|
|
742
748
|
if '=' in operands_mentioned:
|
|
743
749
|
operands_mentioned = [op for op in operands_mentioned if op != '=']
|
|
744
|
-
operands_mentioned = list(dict.fromkeys(operands_mentioned))
|
|
745
750
|
|
|
746
751
|
print("\n")
|
|
747
752
|
if any(not lst for lst in (num_mentioned, operands_mentioned)) or (
|
|
@@ -749,21 +754,23 @@ class DLM:
|
|
|
749
754
|
print(
|
|
750
755
|
f"{self.__loadingAnimation('Hmm', 0.8) or ''}{'\033[34m'}It looks like some essential details are missing, so I can’t complete this calculation right now.{'\033[0m'}")
|
|
751
756
|
else: # else, the bot needs to explain what it has tokenized
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
757
|
+
if display_thought:
|
|
758
|
+
self.__loadingAnimation(
|
|
759
|
+
f"1.) I see {', '.join(persons_mentioned) if persons_mentioned.__len__() >= 1 else 'no one'} mentioned as a person name; "
|
|
760
|
+
f"{'they’re likely key to this problem' if persons_mentioned.__len__() >= 1 else 'moving on'}", 0.2)
|
|
761
|
+
self.__loadingAnimation(
|
|
762
|
+
f"2.) Moreover, I see {', '.join(items_mentioned) if items_mentioned.__len__() >= 1 else 'no items'} mentioned as proper nouns; "
|
|
763
|
+
f"{'this might be a key thing to this problem' if items_mentioned.__len__() >= 1 else 'moving on'}",
|
|
764
|
+
0.2)
|
|
765
|
+
self.__loadingAnimation(
|
|
766
|
+
f"3.) I’ve also identified the numbers {' and '.join(num_mentioned)} that I need to compute with",
|
|
767
|
+
0.2)
|
|
768
|
+
self.__loadingAnimation(
|
|
769
|
+
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",
|
|
770
|
+
0.2)
|
|
771
|
+
self.__loadingAnimation("Now I have the parts, so let me put it all together and solve", 0.3)
|
|
766
772
|
|
|
773
|
+
# Finally compute it and then give the response (if there is any)
|
|
767
774
|
# move "originally" numbers to the front
|
|
768
775
|
indicators = {"original", "originally", "initial", "initially", "at first", "to begin with", "had",
|
|
769
776
|
"savings", "saving", "of"}
|
|
@@ -867,9 +874,10 @@ class DLM:
|
|
|
867
874
|
# 4) Compute only if we have both source_key and target_key
|
|
868
875
|
if source_key and target_key:
|
|
869
876
|
result = (num0 * self.__units[source_key]) / self.__units[target_key]
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
877
|
+
if display_thought:
|
|
878
|
+
self.__loadingAnimation(
|
|
879
|
+
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",
|
|
880
|
+
0.2)
|
|
873
881
|
expr = f"{num_mentioned[0]} {source_key}(s) ==> {round(result, 2)} {target_key}(s)"
|
|
874
882
|
print(f"{'\033[34m'}Conversion Answer: {expr} {'\033[0m'}")
|
|
875
883
|
else:
|
|
@@ -907,8 +915,8 @@ class DLM:
|
|
|
907
915
|
print(
|
|
908
916
|
f"{'\033[34m'}That might've confused me a bit, maybe try leaving one of those out or rephrase it to make it clearer?{'\033[0m'}")
|
|
909
917
|
|
|
910
|
-
def __generate_thought(self, filtered_query, best_match_question, best_match_answer,
|
|
911
|
-
|
|
918
|
+
def __generate_thought(self, filtered_query, best_match_question, best_match_answer, highest_similarity,
|
|
919
|
+
display_thought): # no return, void
|
|
912
920
|
"""
|
|
913
921
|
Simulate a Chain-of-Thought (CoT) reasoning process by printing the bot's internal analysis.
|
|
914
922
|
|
|
@@ -917,6 +925,7 @@ class DLM:
|
|
|
917
925
|
best_match_question (str): The closest matching question found in the knowledge base.
|
|
918
926
|
best_match_answer (str): The corresponding answer to the matched question.
|
|
919
927
|
highest_similarity (float): The calculated string similarity score (0 to 1) for the match.
|
|
928
|
+
display_thought (bool): "True" if the bot is allowed to print its thought or else "False"
|
|
920
929
|
|
|
921
930
|
Behavior:
|
|
922
931
|
- Outputs step-by-step reasoning in a conversational format (e.g., interpreting the question's structure and tone).
|
|
@@ -925,63 +934,74 @@ class DLM:
|
|
|
925
934
|
- Displays confidence based on similarity metrics and sets flags for uncertain answers.
|
|
926
935
|
- Uses colorized terminal output and a loading animation to simulate reflective thought.
|
|
927
936
|
"""
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
f"{'\033[33m'}I couldn't pick out any context or clear topic. If I see a match in my database I will respond with that, or else I have no clue!{'\033[0m'}")
|
|
932
|
-
else:
|
|
933
|
-
sentiment_tone = self.__tone.split()
|
|
934
|
-
|
|
935
|
-
if self.__tone != "":
|
|
937
|
+
if display_thought:
|
|
938
|
+
print("\nThought Process (Yellow):")
|
|
939
|
+
if filtered_query is None or filtered_query == "":
|
|
936
940
|
print(
|
|
937
|
-
f"{'\033[33m'}
|
|
938
|
-
if self.__mode == "experimental":
|
|
939
|
-
self.__perform_advanced_CoT(filtered_query)
|
|
941
|
+
f"{'\033[33m'}I couldn't pick out any context or clear topic. If I see a match in my database I will respond with that, or else I have no clue!{'\033[0m'}")
|
|
940
942
|
else:
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
"meaning"] # special word in different form
|
|
945
|
-
for word in special_start:
|
|
946
|
-
identifier = identifier.replace(word, "")
|
|
947
|
-
# collapse any extra spaces
|
|
948
|
-
identifier = " ".join(identifier.split())
|
|
949
|
-
identifier = identifier.split()
|
|
950
|
-
|
|
951
|
-
if " ".join(identifier) == "":
|
|
943
|
+
sentiment_tone = self.__tone.split()
|
|
944
|
+
|
|
945
|
+
if self.__tone != "":
|
|
952
946
|
print(
|
|
953
|
-
f"{'\033[33m'}
|
|
947
|
+
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'}")
|
|
948
|
+
if self.__mode == "experimental":
|
|
949
|
+
self.__perform_advanced_CoT(filtered_query, display_thought)
|
|
954
950
|
else:
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
for
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
951
|
+
interrogative_start = filtered_query.split()[0]
|
|
952
|
+
identifier = filtered_query
|
|
953
|
+
special_start = ["definition", "explanation", "description", "comparison", "calculation",
|
|
954
|
+
"translation",
|
|
955
|
+
"meaning"] # special word in different form
|
|
956
|
+
for word in special_start:
|
|
957
|
+
identifier = identifier.replace(word, "")
|
|
958
|
+
# collapse any extra spaces
|
|
959
|
+
identifier = " ".join(identifier.split())
|
|
960
|
+
identifier = identifier.split()
|
|
961
|
+
|
|
962
|
+
if " ".join(identifier) == "":
|
|
963
|
+
print(
|
|
964
|
+
f"{'\033[33m'}The user starts their query with \"{interrogative_start.title()}\", but I couldn't pick out a clear topic or context.{'\033[0m'}")
|
|
965
|
+
else:
|
|
966
|
+
print(
|
|
967
|
+
f"{'\033[33m'}The user starts their query with \"{interrogative_start.title()}\" and they are asking about \"{" ".join(identifier).title()}\".{'\033[0m'}")
|
|
968
|
+
self.__loadingAnimation("Let me think about this carefully", 0.8)
|
|
969
|
+
|
|
970
|
+
for s in special_start:
|
|
971
|
+
for u in filtered_query.split():
|
|
972
|
+
s_input = self.__nlp(s)
|
|
973
|
+
u_input = self.__nlp(u)
|
|
974
|
+
if (s_input.vector_norm != 0 and u_input.vector_norm != 0) and (
|
|
975
|
+
s_input.similarity(u_input) > 0.60):
|
|
976
|
+
print(
|
|
977
|
+
f"{'\033[33m'}It seems like they want a {s} of \"{" ".join(identifier).title()}\".{'\033[0m'}")
|
|
978
|
+
|
|
979
|
+
self.__semantic_similarity(self.__special_stripped_query, best_match_question)
|
|
980
|
+
spacy_proceed = self.__nlp_similarity_value is not None
|
|
981
|
+
if (best_match_answer is None) or (
|
|
982
|
+
highest_similarity < 0.65 and (spacy_proceed and self.__nlp_similarity_value < 0.85)):
|
|
983
|
+
print(
|
|
984
|
+
f"{'\033[33m'}The closest match is only {int(highest_similarity * 100)}% similar when I used sequence matching.{'\033[0m'}")
|
|
985
|
+
if spacy_proceed:
|
|
965
986
|
print(
|
|
966
|
-
f"{'\033[33m'}
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
print(
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
print("\n")
|
|
987
|
+
f"{'\033[33m'}Furthermore, an in-depth vector analysis revealed a similarity percentage of {int(self.__nlp_similarity_value * 100)}%.{'\033[0m'}")
|
|
988
|
+
print(
|
|
989
|
+
f"{self.__loadingAnimation("Hmm", 0.8) or ''}{'\033[33m'}I don't think I know the answer, so I am going to let the user know that.{'\033[0m'}")
|
|
990
|
+
self.__unsure_while_thinking = True
|
|
991
|
+
else:
|
|
992
|
+
self.__unsure_while_thinking = False
|
|
993
|
+
DB_identifier = self.__get_specific_question(best_match_answer)
|
|
994
|
+
print(
|
|
995
|
+
f"{'\033[33m'}Yes! I do remember learning about \"{DB_identifier}\" and I might have the right answer!")
|
|
996
|
+
print(
|
|
997
|
+
f"This is because when I did a sequence similarity calculation to one of the closest match in my database, I found it to be {int(highest_similarity * 100)}% similar.")
|
|
998
|
+
if spacy_proceed:
|
|
999
|
+
print(
|
|
1000
|
+
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'}")
|
|
1001
|
+
self.__loadingAnimation("Let me recall that answer", 0.8)
|
|
1002
|
+
print("\n")
|
|
1003
|
+
elif self.__mode == "experimental":
|
|
1004
|
+
self.__perform_advanced_CoT(filtered_query, display_thought)
|
|
985
1005
|
|
|
986
1006
|
def __generate_response(self, best_match_answer, best_match_question): # no return, void
|
|
987
1007
|
"""
|
|
@@ -1248,10 +1268,15 @@ class DLM:
|
|
|
1248
1268
|
conn.commit()
|
|
1249
1269
|
conn.close()
|
|
1250
1270
|
|
|
1251
|
-
def ask(self, query): # no return, void
|
|
1271
|
+
def ask(self, query, display_thought): # no return, void
|
|
1252
1272
|
"""
|
|
1253
1273
|
Handle a full user interaction loop with the DLM bot.
|
|
1254
|
-
|
|
1274
|
+
|
|
1275
|
+
NOTICE: To make the bot run continuously, implement a loop in your program.
|
|
1276
|
+
|
|
1277
|
+
Parameters:
|
|
1278
|
+
query (str): Question the bot would answer, compute, or learn
|
|
1279
|
+
display_thought (bool): "True" for allowing bot to print its thought and CoT or "False"
|
|
1255
1280
|
|
|
1256
1281
|
Behavior:
|
|
1257
1282
|
- Prompts the user for input.
|
|
@@ -1312,7 +1337,8 @@ class DLM:
|
|
|
1312
1337
|
best_match_answer = stored_answer
|
|
1313
1338
|
|
|
1314
1339
|
# "Chain of Thought" (CoT) Feature
|
|
1315
|
-
self.__generate_thought(filtered_query, best_match_question, best_match_answer, highest_similarity
|
|
1340
|
+
self.__generate_thought(filtered_query, best_match_question, best_match_answer, highest_similarity,
|
|
1341
|
+
display_thought)
|
|
1316
1342
|
|
|
1317
1343
|
# accept a match if highest_similarity is 65% or more, or if semantic similarity is recognized
|
|
1318
1344
|
if self.__mode != "experimental":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dynamic-learning-model
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.5
|
|
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
|
|
@@ -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='1.
|
|
8
|
+
version='1.2.5',
|
|
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.',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|