langroid 0.1.260__tar.gz → 0.1.262__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.
Files changed (132) hide show
  1. {langroid-0.1.260 → langroid-0.1.262}/PKG-INFO +1 -1
  2. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/chat_document.py +0 -2
  3. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/task.py +33 -29
  4. {langroid-0.1.260 → langroid-0.1.262}/pyproject.toml +1 -1
  5. {langroid-0.1.260 → langroid-0.1.262}/LICENSE +0 -0
  6. {langroid-0.1.260 → langroid-0.1.262}/README.md +0 -0
  7. {langroid-0.1.260 → langroid-0.1.262}/langroid/__init__.py +0 -0
  8. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/__init__.py +0 -0
  9. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/base.py +0 -0
  10. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/batch.py +0 -0
  11. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/callbacks/__init__.py +0 -0
  12. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/callbacks/chainlit.py +0 -0
  13. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/chat_agent.py +0 -0
  14. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/helpers.py +0 -0
  15. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/junk +0 -0
  16. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/openai_assistant.py +0 -0
  17. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/__init__.py +0 -0
  18. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/doc_chat_agent.py +0 -0
  19. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/lance_doc_chat_agent.py +0 -0
  20. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/lance_rag/__init__.py +0 -0
  21. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/lance_rag/critic_agent.py +0 -0
  22. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/lance_rag/lance_rag_task.py +0 -0
  23. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/lance_rag/query_planner_agent.py +0 -0
  24. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/lance_tools.py +0 -0
  25. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/neo4j/__init__.py +0 -0
  26. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/neo4j/csv_kg_chat.py +0 -0
  27. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/neo4j/neo4j_chat_agent.py +0 -0
  28. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/neo4j/utils/__init__.py +0 -0
  29. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/neo4j/utils/system_message.py +0 -0
  30. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/relevance_extractor_agent.py +0 -0
  31. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/retriever_agent.py +0 -0
  32. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/sql/__init__.py +0 -0
  33. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/sql/sql_chat_agent.py +0 -0
  34. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/sql/utils/__init__.py +0 -0
  35. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/sql/utils/description_extractors.py +0 -0
  36. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/sql/utils/populate_metadata.py +0 -0
  37. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/sql/utils/system_message.py +0 -0
  38. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/sql/utils/tools.py +0 -0
  39. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/special/table_chat_agent.py +0 -0
  40. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tool_message.py +0 -0
  41. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/__init__.py +0 -0
  42. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/duckduckgo_search_tool.py +0 -0
  43. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/extract_tool.py +0 -0
  44. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/generator_tool.py +0 -0
  45. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/google_search_tool.py +0 -0
  46. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/metaphor_search_tool.py +0 -0
  47. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/recipient_tool.py +0 -0
  48. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/retrieval_tool.py +0 -0
  49. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/run_python_code.py +0 -0
  50. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent/tools/segment_extract_tool.py +0 -0
  51. {langroid-0.1.260 → langroid-0.1.262}/langroid/agent_config.py +0 -0
  52. {langroid-0.1.260 → langroid-0.1.262}/langroid/cachedb/__init__.py +0 -0
  53. {langroid-0.1.260 → langroid-0.1.262}/langroid/cachedb/base.py +0 -0
  54. {langroid-0.1.260 → langroid-0.1.262}/langroid/cachedb/momento_cachedb.py +0 -0
  55. {langroid-0.1.260 → langroid-0.1.262}/langroid/cachedb/redis_cachedb.py +0 -0
  56. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/__init__.py +0 -0
  57. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/base.py +0 -0
  58. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/clustering.py +0 -0
  59. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/models.py +0 -0
  60. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/protoc/__init__.py +0 -0
  61. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/protoc/embeddings.proto +0 -0
  62. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/protoc/embeddings_pb2.py +0 -0
  63. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/protoc/embeddings_pb2.pyi +0 -0
  64. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/protoc/embeddings_pb2_grpc.py +0 -0
  65. {langroid-0.1.260 → langroid-0.1.262}/langroid/embedding_models/remote_embeds.py +0 -0
  66. {langroid-0.1.260 → langroid-0.1.262}/langroid/exceptions.py +0 -0
  67. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/__init__.py +0 -0
  68. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/azure_openai.py +0 -0
  69. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/base.py +0 -0
  70. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/config.py +0 -0
  71. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/openai_assistants.py +0 -0
  72. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/openai_gpt.py +0 -0
  73. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/prompt_formatter/__init__.py +0 -0
  74. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/prompt_formatter/base.py +0 -0
  75. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/prompt_formatter/hf_formatter.py +0 -0
  76. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/prompt_formatter/llama2_formatter.py +0 -0
  77. {langroid-0.1.260 → langroid-0.1.262}/langroid/language_models/utils.py +0 -0
  78. {langroid-0.1.260 → langroid-0.1.262}/langroid/mytypes.py +0 -0
  79. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/__init__.py +0 -0
  80. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/agent_chats.py +0 -0
  81. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/code-parsing.md +0 -0
  82. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/code_parser.py +0 -0
  83. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/config.py +0 -0
  84. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/document_parser.py +0 -0
  85. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/image_text.py +0 -0
  86. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/para_sentence_split.py +0 -0
  87. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/parse_json.py +0 -0
  88. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/parser.py +0 -0
  89. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/parser.pyi +0 -0
  90. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/repo_loader.py +0 -0
  91. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/routing.py +0 -0
  92. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/search.py +0 -0
  93. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/spider.py +0 -0
  94. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/table_loader.py +0 -0
  95. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/url_loader.py +0 -0
  96. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/url_loader_cookies.py +0 -0
  97. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/urls.py +0 -0
  98. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/utils.py +0 -0
  99. {langroid-0.1.260 → langroid-0.1.262}/langroid/parsing/web_search.py +0 -0
  100. {langroid-0.1.260 → langroid-0.1.262}/langroid/prompts/__init__.py +0 -0
  101. {langroid-0.1.260 → langroid-0.1.262}/langroid/prompts/chat-gpt4-system-prompt.md +0 -0
  102. {langroid-0.1.260 → langroid-0.1.262}/langroid/prompts/dialog.py +0 -0
  103. {langroid-0.1.260 → langroid-0.1.262}/langroid/prompts/prompts_config.py +0 -0
  104. {langroid-0.1.260 → langroid-0.1.262}/langroid/prompts/templates.py +0 -0
  105. {langroid-0.1.260 → langroid-0.1.262}/langroid/prompts/transforms.py +0 -0
  106. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/__init__.py +0 -0
  107. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/algorithms/__init__.py +0 -0
  108. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/algorithms/graph.py +0 -0
  109. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/configuration.py +0 -0
  110. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/constants.py +0 -0
  111. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/docker.py +0 -0
  112. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/globals.py +0 -0
  113. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/llms/__init__.py +0 -0
  114. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/llms/strings.py +0 -0
  115. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/logging.py +0 -0
  116. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/output/__init__.py +0 -0
  117. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/output/citations.py +0 -0
  118. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/output/printing.py +0 -0
  119. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/output/status.py +0 -0
  120. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/pandas_utils.py +0 -0
  121. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/pydantic_utils.py +0 -0
  122. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/system.py +0 -0
  123. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/web/__init__.py +0 -0
  124. {langroid-0.1.260 → langroid-0.1.262}/langroid/utils/web/login.py +0 -0
  125. {langroid-0.1.260 → langroid-0.1.262}/langroid/vector_store/__init__.py +0 -0
  126. {langroid-0.1.260 → langroid-0.1.262}/langroid/vector_store/base.py +0 -0
  127. {langroid-0.1.260 → langroid-0.1.262}/langroid/vector_store/chromadb.py +0 -0
  128. {langroid-0.1.260 → langroid-0.1.262}/langroid/vector_store/lancedb.py +0 -0
  129. {langroid-0.1.260 → langroid-0.1.262}/langroid/vector_store/meilisearch.py +0 -0
  130. {langroid-0.1.260 → langroid-0.1.262}/langroid/vector_store/momento.py +0 -0
  131. {langroid-0.1.260 → langroid-0.1.262}/langroid/vector_store/qdrant_cloud.py +0 -0
  132. {langroid-0.1.260 → langroid-0.1.262}/langroid/vector_store/qdrantdb.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langroid
3
- Version: 0.1.260
3
+ Version: 0.1.262
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -45,8 +45,6 @@ class ChatDocMetaData(DocMetaData):
45
45
  parent: Optional["ChatDocument"] = None
46
46
  sender: Entity
47
47
  tool_ids: List[str] = [] # stack of tool_ids; used by OpenAIAssistant
48
- # when result returns to parent, pretend message is from this entity
49
- parent_responder: None | Entity = None
50
48
  block: None | Entity = None
51
49
  sender_name: str = ""
52
50
  recipient: str = ""
@@ -72,7 +72,7 @@ class TaskConfig(BaseModel):
72
72
 
73
73
  inf_loop_cycle_len: int = 10
74
74
  inf_loop_dominance_factor: float = 1.5
75
- inf_loop_wait_factor: float = 5.0
75
+ inf_loop_wait_factor: int = 5
76
76
 
77
77
 
78
78
  class Task:
@@ -190,7 +190,11 @@ class Task:
190
190
  # counts of distinct pending messages in history,
191
191
  # to help detect (exact) infinite loops
192
192
  self.message_counter: Counter[str] = Counter()
193
- self.history_count: Deque[int] = deque(maxlen=self.config.inf_loop_cycle_len)
193
+ self._init_message_counter()
194
+
195
+ self.history: Deque[str] = deque(
196
+ maxlen=self.config.inf_loop_cycle_len * self.config.inf_loop_wait_factor
197
+ )
194
198
  # copy the agent's config, so that we don't modify the original agent's config,
195
199
  # which may be shared by other agents.
196
200
  try:
@@ -334,6 +338,12 @@ class Task:
334
338
  def __str__(self) -> str:
335
339
  return f"{self.name}"
336
340
 
341
+ def _init_message_counter(self) -> None:
342
+ self.message_counter.clear()
343
+ # create a unique string that will not likely be in any message,
344
+ # so we always have a message with count=1
345
+ self.message_counter.update([hash("___NO_MESSAGE___")])
346
+
337
347
  def _cache_session_store(self, key: str, value: str) -> None:
338
348
  """
339
349
  Cache a key-value pair for the current session.
@@ -445,7 +455,7 @@ class Task:
445
455
  ),
446
456
  )
447
457
  else:
448
- self.pending_message = msg
458
+ self.pending_message = copy.deepcopy(msg)
449
459
  if self.pending_message is not None and self.caller is not None:
450
460
  # msg may have come from `caller`, so we pretend this is from
451
461
  # the CURRENT task's USER entity
@@ -485,8 +495,8 @@ class Task:
485
495
  self.max_tokens = max_tokens
486
496
  self.session_id = session_id
487
497
  self._set_alive()
488
- self.message_counter.clear()
489
- self.history_count.clear()
498
+ self._init_message_counter()
499
+ self.history.clear()
490
500
 
491
501
  assert (
492
502
  msg is None or isinstance(msg, str) or isinstance(msg, ChatDocument)
@@ -585,8 +595,8 @@ class Task:
585
595
  self.max_tokens = max_tokens
586
596
  self.session_id = session_id
587
597
  self._set_alive()
588
- self.message_counter.clear()
589
- self.history_count.clear()
598
+ self._init_message_counter()
599
+ self.history.clear()
590
600
 
591
601
  if (
592
602
  isinstance(msg, ChatDocument)
@@ -666,9 +676,7 @@ class Task:
666
676
  )
667
677
  # TODO decide on whether or not to print, based on is_async
668
678
  llm_model = (
669
- "no-LLM"
670
- if self.agent.config.llm is None
671
- else self.agent.config.llm.chat_model
679
+ "no-LLM" if self.agent.llm is None else self.agent.llm.config.chat_model
672
680
  )
673
681
  if not settings.quiet:
674
682
  print(
@@ -906,7 +914,7 @@ class Task:
906
914
  if self.pending_message is not None:
907
915
  hashed_msg = hash(str(self.pending_message))
908
916
  self.message_counter.update([hashed_msg])
909
- self.history_count.append(self.message_counter[hashed_msg])
917
+ self.history.append(hashed_msg)
910
918
 
911
919
  def _process_invalid_step_result(self, parent: ChatDocument | None) -> None:
912
920
  """
@@ -914,14 +922,10 @@ class Task:
914
922
  self.pending_message to a NO_ANSWER message from the opposite entity,
915
923
  or leave it as is.
916
924
  Args:
917
- parent (ChatDocument|None): parent message of the current message
925
+ parent (ChatDocument|None): parent message of the current message
918
926
  """
919
927
  self.n_stalled_steps += 1
920
- user_dummy_response = self.pending_sender != Entity.USER and self.interactive
921
- if (not self.is_pass_thru) and (
922
- not self.task_progress or self.allow_null_result or user_dummy_response
923
- ):
924
-
928
+ if (not self.task_progress or self.allow_null_result) and not self.is_pass_thru:
925
929
  # There has been no progress at all in this task, so we
926
930
  # update the pending_message to a dummy NO_ANSWER msg
927
931
  # from the entity 'opposite' to the current pending_sender,
@@ -1068,7 +1072,6 @@ class Task:
1068
1072
  tool_messages = result_msg.tool_messages if result_msg else []
1069
1073
  block = result_msg.metadata.block if result_msg else None
1070
1074
  recipient = result_msg.metadata.recipient if result_msg else None
1071
- responder = result_msg.metadata.parent_responder if result_msg else None
1072
1075
  tool_ids = result_msg.metadata.tool_ids if result_msg else []
1073
1076
  status = result_msg.metadata.status if result_msg else None
1074
1077
 
@@ -1084,7 +1087,6 @@ class Task:
1084
1087
  sender=Entity.USER,
1085
1088
  block=block,
1086
1089
  status=status,
1087
- parent_responder=responder,
1088
1090
  sender_name=self.name,
1089
1091
  recipient=recipient,
1090
1092
  tool_ids=tool_ids,
@@ -1154,9 +1156,9 @@ class Task:
1154
1156
  So if you plot these frequencies in decreasing order,
1155
1157
  you will see a big drop in the plot, from m to m+1.
1156
1158
  We call the freqs until m the "dominant" freqs.
1157
- 2. Say we found m such dominant frequencies.
1158
- If these are the same as the freqs of the last m messages,
1159
- then we are likely in a loop.
1159
+ 2. Say we found m such dominant messages
1160
+ If the set of last (W * m) messages are the same as the
1161
+ set of m dominant messages, then we are likely in a loop.
1160
1162
  """
1161
1163
  max_cycle_len = self.config.inf_loop_cycle_len
1162
1164
  if max_cycle_len <= 0:
@@ -1167,6 +1169,7 @@ class Task:
1167
1169
  # we haven't seen enough messages to detect a loop
1168
1170
  return False
1169
1171
 
1172
+ # recall there's always a dummy msg with freq = 1
1170
1173
  most_common_msg_counts: List[Tuple[str, int]] = (
1171
1174
  self.message_counter.most_common(max_cycle_len + 1)
1172
1175
  )
@@ -1179,7 +1182,7 @@ class Task:
1179
1182
  ratios = counts[:-1] / counts[1:]
1180
1183
  diffs = counts[:-1] - counts[1:]
1181
1184
  indices = np.where((ratios > F) & (diffs > wait_factor))[0]
1182
- m = indices[0] if indices.size > 0 else -1
1185
+ m = indices[-1] if indices.size > 0 else -1
1183
1186
  if m < 0:
1184
1187
  # no dominance found, but...
1185
1188
  if len(most_common_msg_counts) <= max_cycle_len:
@@ -1195,12 +1198,13 @@ class Task:
1195
1198
  return False
1196
1199
 
1197
1200
  dominant_msg_counts = most_common_msg_counts[: m + 1]
1198
- # if the dominant m message counts are the same as the
1199
- # counts of the last m messages, then we are likely in a loop
1200
- dominant_counts = sorted([c for _, c in dominant_msg_counts])
1201
- recent_counts = sorted(list(self.history_count)[-(m + 1) :])
1202
-
1203
- return dominant_counts == recent_counts
1201
+ # if the SET of dominant m messages is the same as the
1202
+ # the SET of last m*w messages, (where w = config.inf_loop_wait_factor),
1203
+ # then we are likely in a loop
1204
+ dominant_msgs = set([msg for msg, _ in dominant_msg_counts])
1205
+ lookback = wait_factor * (m + 1)
1206
+ recent_msgs = set(list(self.history)[-lookback:])
1207
+ return dominant_msgs == recent_msgs
1204
1208
 
1205
1209
  def done(
1206
1210
  self, result: ChatDocument | None = None, r: Responder | None = None
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langroid"
3
- version = "0.1.260"
3
+ version = "0.1.262"
4
4
  description = "Harness LLMs with Multi-Agent Programming"
5
5
  authors = ["Prasad Chalasani <pchalasani@gmail.com>"]
6
6
  readme = "README.md"
File without changes
File without changes