langroid 0.2.2__py3-none-any.whl → 0.2.3__py3-none-any.whl

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.
langroid/agent/task.py CHANGED
@@ -184,8 +184,8 @@ class Task:
184
184
  Note: erasing can reduce prompt sizes, but results in repetitive
185
185
  sub-task delegation.
186
186
  allow_null_result (bool):
187
- If true, allow null (empty or NO_ANSWER) as the result of a step or
188
- overall task result.
187
+ If true, create dummy NO_ANSWER response when no valid response is found
188
+ in a step.
189
189
  Optional, default is False.
190
190
  *Note:* In non-interactive mode, when this is set to True,
191
191
  you can have a situation where an LLM generates (non-tool) text,
@@ -193,7 +193,9 @@ class Task:
193
193
  is inserted as a dummy response from the User entity, so the LLM
194
194
  will now respond to this Null result, and this will continue
195
195
  until the LLM emits a DONE signal (if instructed to do so),
196
- otherwise it can result in an infinite loop.
196
+ otherwise langroid detects a potential infinite loop after
197
+ a certain number of such steps (= `TaskConfig.inf_loop_wait_factor`)
198
+ and will raise an InfiniteLoopException.
197
199
  max_stalled_steps (int): task considered done after this many consecutive
198
200
  steps with no progress. Default is 3.
199
201
  done_if_no_response (List[Responder]): consider task done if NULL
@@ -1047,15 +1049,10 @@ class Task:
1047
1049
  self._show_pending_message_if_debug()
1048
1050
  return self.pending_message
1049
1051
 
1050
- def _process_valid_responder_result(
1051
- self,
1052
- r: Responder,
1053
- parent: ChatDocument | None,
1054
- result: ChatDocument,
1055
- ) -> None:
1056
- """Processes valid result from a responder, during a step"""
1052
+ def _update_no_answer_vars(self, result: ChatDocument) -> None:
1053
+ """Update variables related to NO_ANSWER responses, to aid
1054
+ in alternating NO_ANSWER infinite-loop detection."""
1057
1055
 
1058
- # in case the valid response was a NO_ANSWER,
1059
1056
  if NO_ANSWER in result.content:
1060
1057
  if self._no_answer_step == self._step_idx - 2:
1061
1058
  # N/A two steps ago
@@ -1067,6 +1064,16 @@ class Task:
1067
1064
  # record the last step where the best explicit response was N/A
1068
1065
  self._no_answer_step = self._step_idx
1069
1066
 
1067
+ def _process_valid_responder_result(
1068
+ self,
1069
+ r: Responder,
1070
+ parent: ChatDocument | None,
1071
+ result: ChatDocument,
1072
+ ) -> None:
1073
+ """Processes valid result from a responder, during a step"""
1074
+
1075
+ self._update_no_answer_vars(result)
1076
+
1070
1077
  # pending_sender is of type Responder,
1071
1078
  # i.e. it is either one of the agent's entities
1072
1079
  # OR a sub-task, that has produced a valid response.
@@ -1131,6 +1138,7 @@ class Task:
1131
1138
  metadata=ChatDocMetaData(sender=responder, parent_id=parent_id),
1132
1139
  )
1133
1140
  self.pending_sender = responder
1141
+ self._update_no_answer_vars(self.pending_message)
1134
1142
  self.log_message(self.pending_sender, self.pending_message, mark=True)
1135
1143
 
1136
1144
  def _show_pending_message_if_debug(self) -> None:
@@ -1346,13 +1354,20 @@ class Task:
1346
1354
  def _maybe_infinite_loop(self) -> bool:
1347
1355
  """
1348
1356
  Detect possible infinite loop based on message frequencies.
1349
- NOTE: This only (attempts to) detect "exact" loops, i.e. a cycle
1350
- of messages that repeats exactly, e.g.
1357
+ NOTE: This detects two types of loops:
1358
+ - Alternating NO_ANSWER loops, specifically of the form
1359
+ x1 NO_ANSWER x2 NO_ANSWER x3 NO_ANSWER...
1360
+ (e.g. an LLM repeatedly saying something different, and another responder
1361
+ or sub-task saying NO_ANSWER -- i.e. "DO-NOT-KNOW")
1362
+
1363
+ - "exact" loops, i.e. a cycle of messages that repeats exactly, e.g.
1351
1364
  a r b i t r a t e r a t e r a t e r a t e ...
1352
1365
 
1353
- [It does not detect "approximate" loops, where the LLM is generating a
1354
- sequence of messages that are similar, but not exactly the same.]
1366
+ [It does not detect more general "approximate" loops, where two entities are
1367
+ responding to each other potentially forever, with (slightly) different
1368
+ messages each time]
1355
1369
 
1370
+ Here is the logic for the exact-loop detection:
1356
1371
  Intuition: when you look at a sufficiently long sequence with an m-message
1357
1372
  loop, then the frequencies of these m messages will "dominate" those
1358
1373
  of all other messages.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langroid
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -32,7 +32,7 @@ langroid/agent/special/sql/utils/populate_metadata.py,sha256=1J22UsyEPKzwK0XlJZt
32
32
  langroid/agent/special/sql/utils/system_message.py,sha256=qKLHkvQWRQodTtPLPxr1GSLUYUFASZU8x-ybV67cB68,1885
33
33
  langroid/agent/special/sql/utils/tools.py,sha256=vFYysk6Vi7HJjII8B4RitA3pt_z3gkSglDNdhNVMiFc,1332
34
34
  langroid/agent/special/table_chat_agent.py,sha256=d9v2wsblaRx7oMnKhLV7uO_ujvk9gh59pSGvBXyeyNc,9659
35
- langroid/agent/task.py,sha256=2v2-LEUxwJo65bbcLLALKOnMGVC02IZyBuyukOvP5Nw,71431
35
+ langroid/agent/task.py,sha256=ALqGmqzqUNaZB3u8jReBcsC8rRti3WqsN82EMm4CFAo,72189
36
36
  langroid/agent/tool_message.py,sha256=wIyZnUcZpxkiRPvM9O3MO3b5BBAdLEEan9kqPbvtApc,9743
37
37
  langroid/agent/tools/__init__.py,sha256=e-63cfwQNk_ftRKQwgDAJQK16QLbRVWDBILeXIc7wLk,402
38
38
  langroid/agent/tools/duckduckgo_search_tool.py,sha256=NhsCaGZkdv28nja7yveAhSK_w6l_Ftym8agbrdzqgfo,1935
@@ -128,8 +128,8 @@ langroid/vector_store/meilisearch.py,sha256=6frB7GFWeWmeKzRfLZIvzRjllniZ1cYj3Hmh
128
128
  langroid/vector_store/momento.py,sha256=QaPzUnTwlswoawGB-paLtUPyLRvckFXLfLDfvbTzjNQ,10505
129
129
  langroid/vector_store/qdrant_cloud.py,sha256=3im4Mip0QXLkR6wiqVsjV1QvhSElfxdFSuDKddBDQ-4,188
130
130
  langroid/vector_store/qdrantdb.py,sha256=wYOuu5c2vIKn9ZgvTXcAiZXMpV8AOXEWFAzI8S8UP-0,16828
131
- pyproject.toml,sha256=dJzlQA4tW7aK-naR-m3P-BrNk0KOzQ8S2w8EtfYJx4s,6963
132
- langroid-0.2.2.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
133
- langroid-0.2.2.dist-info/METADATA,sha256=grLp3cBevoVDKZ1N2Hnj33aQHhvxLioyNx1NiE-Ukyo,53146
134
- langroid-0.2.2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
135
- langroid-0.2.2.dist-info/RECORD,,
131
+ pyproject.toml,sha256=MX6Rg0hLOiPlYpb9q4G0H0jLdqAjNWSI_tnKXB8mkuQ,6963
132
+ langroid-0.2.3.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
133
+ langroid-0.2.3.dist-info/METADATA,sha256=1GD93aMG3wEtL7pE3NBXM1gxjyjEO0Og5XdtNGb3UGA,53146
134
+ langroid-0.2.3.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
135
+ langroid-0.2.3.dist-info/RECORD,,
pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langroid"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "Harness LLMs with Multi-Agent Programming"
5
5
  authors = ["Prasad Chalasani <pchalasani@gmail.com>"]
6
6
  readme = "README.md"