langroid 0.1.234__tar.gz → 0.1.235__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 (126) hide show
  1. {langroid-0.1.234 → langroid-0.1.235}/PKG-INFO +1 -1
  2. {langroid-0.1.234 → langroid-0.1.235}/langroid/__init__.py +2 -0
  3. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/batch.py +1 -0
  4. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/chat_document.py +19 -0
  5. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/table_chat_agent.py +0 -1
  6. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/task.py +95 -13
  7. {langroid-0.1.234 → langroid-0.1.235}/langroid/cachedb/redis_cachedb.py +1 -1
  8. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/constants.py +1 -1
  9. {langroid-0.1.234 → langroid-0.1.235}/pyproject.toml +1 -1
  10. {langroid-0.1.234 → langroid-0.1.235}/LICENSE +0 -0
  11. {langroid-0.1.234 → langroid-0.1.235}/README.md +0 -0
  12. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/__init__.py +0 -0
  13. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/base.py +0 -0
  14. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/callbacks/__init__.py +0 -0
  15. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/callbacks/chainlit.py +0 -0
  16. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/chat_agent.py +0 -0
  17. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/helpers.py +0 -0
  18. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/junk +0 -0
  19. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/openai_assistant.py +0 -0
  20. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/__init__.py +0 -0
  21. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/doc_chat_agent.py +0 -0
  22. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/lance_doc_chat_agent.py +0 -0
  23. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/lance_rag/__init__.py +0 -0
  24. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/lance_rag/critic_agent.py +0 -0
  25. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/lance_rag/lance_rag_task.py +0 -0
  26. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/lance_rag/query_planner_agent.py +0 -0
  27. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/lance_tools.py +0 -0
  28. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/neo4j/__init__.py +0 -0
  29. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/neo4j/csv_kg_chat.py +0 -0
  30. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/neo4j/neo4j_chat_agent.py +0 -0
  31. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/neo4j/utils/__init__.py +0 -0
  32. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/neo4j/utils/system_message.py +0 -0
  33. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/relevance_extractor_agent.py +0 -0
  34. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/retriever_agent.py +0 -0
  35. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/sql/__init__.py +0 -0
  36. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/sql/sql_chat_agent.py +0 -0
  37. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/sql/utils/__init__.py +0 -0
  38. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/sql/utils/description_extractors.py +0 -0
  39. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/sql/utils/populate_metadata.py +0 -0
  40. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/sql/utils/system_message.py +0 -0
  41. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/special/sql/utils/tools.py +0 -0
  42. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tool_message.py +0 -0
  43. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tools/__init__.py +0 -0
  44. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tools/duckduckgo_search_tool.py +0 -0
  45. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tools/extract_tool.py +0 -0
  46. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tools/generator_tool.py +0 -0
  47. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tools/google_search_tool.py +0 -0
  48. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tools/metaphor_search_tool.py +0 -0
  49. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tools/recipient_tool.py +0 -0
  50. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tools/run_python_code.py +0 -0
  51. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent/tools/segment_extract_tool.py +0 -0
  52. {langroid-0.1.234 → langroid-0.1.235}/langroid/agent_config.py +0 -0
  53. {langroid-0.1.234 → langroid-0.1.235}/langroid/cachedb/__init__.py +0 -0
  54. {langroid-0.1.234 → langroid-0.1.235}/langroid/cachedb/base.py +0 -0
  55. {langroid-0.1.234 → langroid-0.1.235}/langroid/cachedb/momento_cachedb.py +0 -0
  56. {langroid-0.1.234 → langroid-0.1.235}/langroid/embedding_models/__init__.py +0 -0
  57. {langroid-0.1.234 → langroid-0.1.235}/langroid/embedding_models/base.py +0 -0
  58. {langroid-0.1.234 → langroid-0.1.235}/langroid/embedding_models/clustering.py +0 -0
  59. {langroid-0.1.234 → langroid-0.1.235}/langroid/embedding_models/models.py +0 -0
  60. {langroid-0.1.234 → langroid-0.1.235}/langroid/embedding_models/protoc/embeddings.proto +0 -0
  61. {langroid-0.1.234 → langroid-0.1.235}/langroid/embedding_models/protoc/embeddings_pb2.py +0 -0
  62. {langroid-0.1.234 → langroid-0.1.235}/langroid/embedding_models/protoc/embeddings_pb2.pyi +0 -0
  63. {langroid-0.1.234 → langroid-0.1.235}/langroid/embedding_models/protoc/embeddings_pb2_grpc.py +0 -0
  64. {langroid-0.1.234 → langroid-0.1.235}/langroid/embedding_models/remote_embeds.py +0 -0
  65. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/__init__.py +0 -0
  66. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/azure_openai.py +0 -0
  67. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/base.py +0 -0
  68. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/config.py +0 -0
  69. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/openai_assistants.py +0 -0
  70. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/openai_gpt.py +0 -0
  71. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/prompt_formatter/__init__.py +0 -0
  72. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/prompt_formatter/base.py +0 -0
  73. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/prompt_formatter/hf_formatter.py +0 -0
  74. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/prompt_formatter/llama2_formatter.py +0 -0
  75. {langroid-0.1.234 → langroid-0.1.235}/langroid/language_models/utils.py +0 -0
  76. {langroid-0.1.234 → langroid-0.1.235}/langroid/mytypes.py +0 -0
  77. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/__init__.py +0 -0
  78. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/agent_chats.py +0 -0
  79. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/code-parsing.md +0 -0
  80. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/code_parser.py +0 -0
  81. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/config.py +0 -0
  82. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/document_parser.py +0 -0
  83. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/image_text.py +0 -0
  84. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/para_sentence_split.py +0 -0
  85. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/parse_json.py +0 -0
  86. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/parser.py +0 -0
  87. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/repo_loader.py +0 -0
  88. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/search.py +0 -0
  89. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/spider.py +0 -0
  90. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/table_loader.py +0 -0
  91. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/url_loader.py +0 -0
  92. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/url_loader_cookies.py +0 -0
  93. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/urls.py +0 -0
  94. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/utils.py +0 -0
  95. {langroid-0.1.234 → langroid-0.1.235}/langroid/parsing/web_search.py +0 -0
  96. {langroid-0.1.234 → langroid-0.1.235}/langroid/prompts/__init__.py +0 -0
  97. {langroid-0.1.234 → langroid-0.1.235}/langroid/prompts/chat-gpt4-system-prompt.md +0 -0
  98. {langroid-0.1.234 → langroid-0.1.235}/langroid/prompts/dialog.py +0 -0
  99. {langroid-0.1.234 → langroid-0.1.235}/langroid/prompts/prompts_config.py +0 -0
  100. {langroid-0.1.234 → langroid-0.1.235}/langroid/prompts/templates.py +0 -0
  101. {langroid-0.1.234 → langroid-0.1.235}/langroid/prompts/transforms.py +0 -0
  102. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/__init__.py +0 -0
  103. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/algorithms/__init__.py +0 -0
  104. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/algorithms/graph.py +0 -0
  105. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/configuration.py +0 -0
  106. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/docker.py +0 -0
  107. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/globals.py +0 -0
  108. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/llms/__init__.py +0 -0
  109. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/llms/strings.py +0 -0
  110. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/logging.py +0 -0
  111. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/output/__init__.py +0 -0
  112. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/output/printing.py +0 -0
  113. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/output/status.py +0 -0
  114. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/pandas_utils.py +0 -0
  115. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/pydantic_utils.py +0 -0
  116. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/system.py +0 -0
  117. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/web/__init__.py +0 -0
  118. {langroid-0.1.234 → langroid-0.1.235}/langroid/utils/web/login.py +0 -0
  119. {langroid-0.1.234 → langroid-0.1.235}/langroid/vector_store/__init__.py +0 -0
  120. {langroid-0.1.234 → langroid-0.1.235}/langroid/vector_store/base.py +0 -0
  121. {langroid-0.1.234 → langroid-0.1.235}/langroid/vector_store/chromadb.py +0 -0
  122. {langroid-0.1.234 → langroid-0.1.235}/langroid/vector_store/lancedb.py +0 -0
  123. {langroid-0.1.234 → langroid-0.1.235}/langroid/vector_store/meilisearch.py +0 -0
  124. {langroid-0.1.234 → langroid-0.1.235}/langroid/vector_store/momento.py +0 -0
  125. {langroid-0.1.234 → langroid-0.1.235}/langroid/vector_store/qdrant_cloud.py +0 -0
  126. {langroid-0.1.234 → langroid-0.1.235}/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.234
3
+ Version: 0.1.235
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -27,6 +27,7 @@ from .agent.batch import (
27
27
  )
28
28
 
29
29
  from .agent.chat_document import (
30
+ StatusCode,
30
31
  ChatDocument,
31
32
  ChatDocMetaData,
32
33
  )
@@ -77,6 +78,7 @@ __all__ = [
77
78
  "AgentConfig",
78
79
  "ChatAgent",
79
80
  "ChatAgentConfig",
81
+ "StatusCode",
80
82
  "ChatDocument",
81
83
  "ChatDocMetaData",
82
84
  "Task",
@@ -53,6 +53,7 @@ def run_batch_task_gen(
53
53
  message (Optional[str]): optionally overrides the console status messages
54
54
  handle_exceptions: bool: Whether to replace exceptions with outputs of None
55
55
  max_cost: float: maximum cost to run the task (default 0.0 for unlimited)
56
+ max_tokens: int: maximum token usage (in and out) (default 0 for unlimited)
56
57
 
57
58
 
58
59
  Returns:
@@ -1,4 +1,5 @@
1
1
  import json
2
+ from enum import Enum
2
3
  from typing import List, Optional, Union
3
4
 
4
5
  from pydantic import BaseModel, Extra
@@ -23,6 +24,23 @@ class ChatDocAttachment(BaseModel):
23
24
  extra = Extra.allow
24
25
 
25
26
 
27
+ class StatusCode(str, Enum):
28
+ """Codes meant to be returned by task.run(). Some are not used yet."""
29
+
30
+ OK = "OK"
31
+ ERROR = "ERROR"
32
+ DONE = "DONE"
33
+ STALLED = "STALLED"
34
+ INF_LOOP = "INF_LOOP"
35
+ KILL = "KILL"
36
+ MAX_TURNS = "MAX_TURNS"
37
+ MAX_COST = "MAX_COST"
38
+ MAX_TOKENS = "MAX_TOKENS"
39
+ TIMEOUT = "TIMEOUT"
40
+ NO_ANSWER = "NO_ANSWER"
41
+ USER_QUIT = "USER_QUIT"
42
+
43
+
26
44
  class ChatDocMetaData(DocMetaData):
27
45
  parent: Optional["ChatDocument"] = None
28
46
  sender: Entity
@@ -35,6 +53,7 @@ class ChatDocMetaData(DocMetaData):
35
53
  usage: Optional[LLMTokenUsage]
36
54
  cached: bool = False
37
55
  displayed: bool = False
56
+ status: Optional[StatusCode] = None
38
57
 
39
58
 
40
59
  class ChatDocLoggerFields(BaseModel):
@@ -203,7 +203,6 @@ class TableChatAgent(ChatAgent):
203
203
  # Temporarily redirect standard output to our string-based I/O stream
204
204
  sys.stdout = code_out
205
205
 
206
-
207
206
  # Evaluate the last line and get the result
208
207
  try:
209
208
  eval_result = pd.eval(exprn, local_dict=local_vars)
@@ -27,11 +27,20 @@ from langroid.agent.chat_document import (
27
27
  ChatDocLoggerFields,
28
28
  ChatDocMetaData,
29
29
  ChatDocument,
30
+ StatusCode,
30
31
  )
32
+ from langroid.cachedb.redis_cachedb import RedisCache, RedisCacheConfig
31
33
  from langroid.mytypes import Entity
32
34
  from langroid.parsing.parse_json import extract_top_level_json
33
35
  from langroid.utils.configuration import settings
34
- from langroid.utils.constants import DONE, NO_ANSWER, PASS, PASS_TO, SEND_TO, USER_QUIT
36
+ from langroid.utils.constants import (
37
+ DONE,
38
+ NO_ANSWER,
39
+ PASS,
40
+ PASS_TO,
41
+ SEND_TO,
42
+ USER_QUIT_STRINGS,
43
+ )
35
44
  from langroid.utils.logging import RichFileLogger, setup_file_logger
36
45
 
37
46
  logger = logging.getLogger(__name__)
@@ -73,6 +82,8 @@ class Task:
73
82
  the value of `result()`, which is the final result of the task.
74
83
  """
75
84
 
85
+ # class variable called `cache` that is a RedisCache object
86
+ cache: RedisCache = RedisCache(RedisCacheConfig(fake=False))
76
87
  def __init__(
77
88
  self,
78
89
  agent: Optional[Agent] = None,
@@ -141,7 +152,6 @@ class Task:
141
152
  """
142
153
  if agent is None:
143
154
  agent = ChatAgent()
144
-
145
155
  self.callbacks = SimpleNamespace(
146
156
  show_subtask_response=noop_fn,
147
157
  set_parent_agent=noop_fn,
@@ -172,6 +182,7 @@ class Task:
172
182
  agent.set_user_message(user_message)
173
183
  self.max_cost: float = 0
174
184
  self.max_tokens: int = 0
185
+ self.session_id: str = ""
175
186
  self.logger: None | RichFileLogger = None
176
187
  self.tsv_logger: None | logging.Logger = None
177
188
  self.color_log: bool = False if settings.notebook else True
@@ -285,6 +296,54 @@ class Task:
285
296
  def __str__(self) -> str:
286
297
  return f"{self.name}"
287
298
 
299
+ def _cache_session_store(self, key: str, value: str) -> None:
300
+ """
301
+ Cache a key-value pair for the current session.
302
+ E.g. key = "kill", value = "1"
303
+ """
304
+ try:
305
+ self.cache.store(f"{self.session_id}:{key}", value)
306
+ except Exception as e:
307
+ logging.error(f"Error in Task._cache_session_store: {e}")
308
+
309
+ def _cache_session_lookup(self, key: str) -> Dict[str, Any] | str | None:
310
+ """
311
+ Retrieve a value from the cache for the current session.
312
+ """
313
+ session_id_key = f"{self.session_id}:{key}"
314
+ try:
315
+ cached_val = self.cache.retrieve(session_id_key)
316
+ except Exception as e:
317
+ logging.error(f"Error in Task._cache_session_lookup: {e}")
318
+ return None
319
+ return cached_val
320
+
321
+ def _is_kill(self) -> bool:
322
+ """
323
+ Check if the current session is killed.
324
+ """
325
+ return self._cache_session_lookup("kill") == "1"
326
+
327
+ def _set_alive(self) -> None:
328
+ """
329
+ Initialize the kill status of the current session.
330
+ """
331
+ self._cache_session_store("kill", "0")
332
+
333
+ @classmethod
334
+ def kill_session(cls, session_id=""):
335
+ """
336
+ Kill the current session.
337
+ """
338
+ session_id_kill_key = f"{session_id}:kill"
339
+ cls.cache.store(session_id_kill_key, "1")
340
+
341
+ def kill(self) -> None:
342
+ """
343
+ Kill the task run associated with the current session.
344
+ """
345
+ self._cache_session_store("kill", "1")
346
+
288
347
  @property
289
348
  def _level(self) -> int:
290
349
  if self.caller is None:
@@ -378,6 +437,7 @@ class Task:
378
437
  caller: None | Task = None,
379
438
  max_cost: float = 0,
380
439
  max_tokens: int = 0,
440
+ session_id: str = "",
381
441
  ) -> Optional[ChatDocument]:
382
442
  """Synchronous version of `run_async()`.
383
443
  See `run_async()` for details."""
@@ -385,6 +445,9 @@ class Task:
385
445
  self.n_stalled_steps = 0
386
446
  self.max_cost = max_cost
387
447
  self.max_tokens = max_tokens
448
+ self.session_id = session_id
449
+ self._set_alive()
450
+
388
451
  assert (
389
452
  msg is None or isinstance(msg, str) or isinstance(msg, ChatDocument)
390
453
  ), f"msg arg in Task.run() must be None, str, or ChatDocument, not {type(msg)}"
@@ -406,15 +469,19 @@ class Task:
406
469
  i = 0
407
470
  while True:
408
471
  self.step()
409
- if self.done():
472
+ done, status = self.done()
473
+ if done:
410
474
  if self._level == 0 and not settings.quiet:
411
475
  print("[magenta]Bye, hope this was useful!")
412
476
  break
413
477
  i += 1
414
478
  if turns > 0 and i >= turns:
479
+ status = StatusCode.MAX_TURNS
415
480
  break
416
481
 
417
482
  final_result = self.result()
483
+ if final_result is not None:
484
+ final_result.metadata.status = status
418
485
  self._post_run_loop()
419
486
  return final_result
420
487
 
@@ -425,6 +492,7 @@ class Task:
425
492
  caller: None | Task = None,
426
493
  max_cost: float = 0,
427
494
  max_tokens: int = 0,
495
+ session_id: str = "",
428
496
  ) -> Optional[ChatDocument]:
429
497
  """
430
498
  Loop over `step()` until task is considered done or `turns` is reached.
@@ -443,6 +511,7 @@ class Task:
443
511
  caller (Task|None): the calling task, if any
444
512
  max_cost (float): max cost allowed for the task (default 0 -> no limit)
445
513
  max_tokens (int): max tokens allowed for the task (default 0 -> no limit)
514
+ session_id (str): session id for the task
446
515
 
447
516
  Returns:
448
517
  Optional[ChatDocument]: valid result of the task.
@@ -456,6 +525,9 @@ class Task:
456
525
  self.n_stalled_steps = 0
457
526
  self.max_cost = max_cost
458
527
  self.max_tokens = max_tokens
528
+ self.session_id = session_id
529
+ self._set_alive()
530
+
459
531
  if (
460
532
  isinstance(msg, ChatDocument)
461
533
  and msg.metadata.recipient != ""
@@ -473,15 +545,19 @@ class Task:
473
545
  i = 0
474
546
  while True:
475
547
  await self.step_async()
476
- if self.done():
548
+ done, status = self.done()
549
+ if done:
477
550
  if self._level == 0 and not settings.quiet:
478
551
  print("[magenta]Bye, hope this was useful!")
479
552
  break
480
553
  i += 1
481
554
  if turns > 0 and i >= turns:
555
+ status = StatusCode.MAX_TURNS
482
556
  break
483
557
 
484
558
  final_result = self.result()
559
+ if final_result is not None:
560
+ final_result.metadata.status = status
485
561
  self._post_run_loop()
486
562
  return final_result
487
563
 
@@ -942,6 +1018,7 @@ class Task:
942
1018
  recipient = result_msg.metadata.recipient if result_msg else None
943
1019
  responder = result_msg.metadata.parent_responder if result_msg else None
944
1020
  tool_ids = result_msg.metadata.tool_ids if result_msg else []
1021
+ status = result_msg.metadata.status if result_msg else None
945
1022
 
946
1023
  # regardless of which entity actually produced the result,
947
1024
  # when we return the result, we set entity to USER
@@ -954,6 +1031,7 @@ class Task:
954
1031
  source=Entity.USER,
955
1032
  sender=Entity.USER,
956
1033
  block=block,
1034
+ status=status,
957
1035
  parent_responder=responder,
958
1036
  sender_name=self.name,
959
1037
  recipient=recipient,
@@ -1036,7 +1114,7 @@ class Task:
1036
1114
 
1037
1115
  def done(
1038
1116
  self, result: ChatDocument | None = None, r: Responder | None = None
1039
- ) -> bool:
1117
+ ) -> Tuple[bool, StatusCode]:
1040
1118
  """
1041
1119
  Check if task is done. This is the default behavior.
1042
1120
  Derived classes can override this.
@@ -1046,26 +1124,29 @@ class Task:
1046
1124
  Not used here, but could be used by derived classes.
1047
1125
  Returns:
1048
1126
  bool: True if task is done, False otherwise
1127
+ StatusCode: status code indicating why task is done
1049
1128
  """
1129
+ if self._is_kill():
1130
+ return (True, StatusCode.KILL)
1050
1131
  result = result or self.pending_message
1051
1132
  user_quit = (
1052
1133
  result is not None
1053
- and result.content in USER_QUIT
1134
+ and result.content in USER_QUIT_STRINGS
1054
1135
  and result.metadata.sender == Entity.USER
1055
1136
  )
1056
1137
  if self._level == 0 and self.only_user_quits_root:
1057
1138
  # for top-level task, only user can quit out
1058
- return user_quit
1139
+ return (user_quit, StatusCode.USER_QUIT if user_quit else StatusCode.OK)
1059
1140
 
1060
1141
  if self.is_done:
1061
- return True
1142
+ return (True, StatusCode.DONE)
1062
1143
 
1063
1144
  if self.n_stalled_steps >= self.max_stalled_steps:
1064
1145
  # we are stuck, so bail to avoid infinite loop
1065
1146
  logger.warning(
1066
1147
  f"Task {self.name} stuck for {self.max_stalled_steps} steps; exiting."
1067
1148
  )
1068
- return True
1149
+ return (True, StatusCode.STALLED)
1069
1150
 
1070
1151
  if self.max_cost > 0 and self.agent.llm is not None:
1071
1152
  try:
@@ -1073,7 +1154,7 @@ class Task:
1073
1154
  logger.warning(
1074
1155
  f"Task {self.name} cost exceeded {self.max_cost}; exiting."
1075
1156
  )
1076
- return True
1157
+ return (True, StatusCode.MAX_COST)
1077
1158
  except Exception:
1078
1159
  pass
1079
1160
 
@@ -1083,10 +1164,10 @@ class Task:
1083
1164
  logger.warning(
1084
1165
  f"Task {self.name} uses > {self.max_tokens} tokens; exiting."
1085
1166
  )
1086
- return True
1167
+ return (True, StatusCode.MAX_TOKENS)
1087
1168
  except Exception:
1088
1169
  pass
1089
- return (
1170
+ final = (
1090
1171
  # no valid response from any entity/agent in current turn
1091
1172
  result is None
1092
1173
  # An entity decided task is done
@@ -1103,6 +1184,7 @@ class Task:
1103
1184
  # )
1104
1185
  or user_quit
1105
1186
  )
1187
+ return (final, StatusCode.OK)
1106
1188
 
1107
1189
  def valid(
1108
1190
  self,
@@ -1120,7 +1202,7 @@ class Task:
1120
1202
 
1121
1203
  # if task would be considered done given responder r's `result`,
1122
1204
  # then consider the result valid.
1123
- if result is not None and self.done(result, r):
1205
+ if result is not None and self.done(result, r)[0]:
1124
1206
  return True
1125
1207
  return (
1126
1208
  result is not None
@@ -109,7 +109,7 @@ class RedisCache(CacheDB):
109
109
  key (str): The key to retrieve the value for.
110
110
 
111
111
  Returns:
112
- dict: The value associated with the key.
112
+ dict|str|None: The value associated with the key.
113
113
  """
114
114
  with self.redis_client() as client: # type: ignore
115
115
  try:
@@ -13,7 +13,7 @@ class Colors(BaseModel):
13
13
  RESET: str = "\033[0m"
14
14
 
15
15
 
16
- USER_QUIT = ["q", "x", "quit", "exit", "bye"]
16
+ USER_QUIT_STRINGS = ["q", "x", "quit", "exit", "bye"]
17
17
  NO_ANSWER = "DO-NOT-KNOW"
18
18
  DONE = "DONE"
19
19
  PASS = "__PASS__"
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langroid"
3
- version = "0.1.234"
3
+ version = "0.1.235"
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