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