langroid 0.1.230__py3-none-any.whl → 0.1.233__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/batch.py CHANGED
@@ -31,6 +31,8 @@ def run_batch_task_gen(
31
31
  turns: int = -1,
32
32
  message: Optional[str] = None,
33
33
  handle_exceptions: bool = False,
34
+ max_cost: float = 0.0,
35
+ max_tokens: int = 0,
34
36
  ) -> list[U]:
35
37
  """
36
38
  Generate and run copies of a task async/concurrently one per item in `items` list.
@@ -50,6 +52,8 @@ def run_batch_task_gen(
50
52
  turns (int): number of turns to run, -1 for infinite
51
53
  message (Optional[str]): optionally overrides the console status messages
52
54
  handle_exceptions: bool: Whether to replace exceptions with outputs of None
55
+ max_cost: float: maximum cost to run the task (default 0.0 for unlimited)
56
+
53
57
 
54
58
  Returns:
55
59
  list[Any]: list of final results
@@ -62,7 +66,9 @@ def run_batch_task_gen(
62
66
  task_i.agent.llm.set_stream(False)
63
67
  task_i.agent.config.show_stats = False
64
68
 
65
- result = await task_i.run_async(input, turns=turns)
69
+ result = await task_i.run_async(
70
+ input, turns=turns, max_cost=max_cost, max_tokens=max_tokens
71
+ )
66
72
  return result
67
73
 
68
74
  async def _do_all(
@@ -120,6 +126,8 @@ def run_batch_tasks(
120
126
  sequential: bool = True,
121
127
  batch_size: Optional[int] = None,
122
128
  turns: int = -1,
129
+ max_cost: float = 0.0,
130
+ max_tokens: int = 0,
123
131
  ) -> List[U]:
124
132
  """
125
133
  Run copies of `task` async/concurrently one per item in `items` list.
@@ -137,6 +145,8 @@ def run_batch_tasks(
137
145
  batch_size (Optional[int]): The number of tasks to run at a time,
138
146
  if None, unbatched
139
147
  turns (int): number of turns to run, -1 for infinite
148
+ max_cost: float: maximum cost to run the task (default 0.0 for unlimited)
149
+ max_tokens: int: maximum token usage (in and out) (default 0 for unlimited)
140
150
 
141
151
  Returns:
142
152
  list[Any]: list of final results
@@ -151,6 +161,8 @@ def run_batch_tasks(
151
161
  batch_size,
152
162
  turns,
153
163
  message,
164
+ max_cost=max_cost,
165
+ max_tokens=max_tokens,
154
166
  )
155
167
 
156
168
 
@@ -117,6 +117,7 @@ class DocChatAgentConfig(ChatAgentConfig):
117
117
  )
118
118
  rerank_diversity: bool = True # rerank to maximize diversity?
119
119
  rerank_periphery: bool = True # rerank to avoid Lost In the Middle effect?
120
+ rerank_after_adding_context: bool = True # rerank after adding context window?
120
121
  embed_batch_size: int = 500 # get embedding of at most this many at a time
121
122
  cache: bool = True # cache results
122
123
  debug: bool = False
@@ -1110,9 +1111,10 @@ class DocChatAgent(ChatAgent):
1110
1111
  if len(passages) == 0:
1111
1112
  return []
1112
1113
 
1113
- passages_scores = [(p, 0.0) for p in passages]
1114
- passages_scores = self.add_context_window(passages_scores)
1115
- passages = [p for p, _ in passages_scores]
1114
+ if self.config.rerank_after_adding_context:
1115
+ passages_scores = [(p, 0.0) for p in passages]
1116
+ passages_scores = self.add_context_window(passages_scores)
1117
+ passages = [p for p, _ in passages_scores]
1116
1118
  # now passages can potentially have a lot of doc chunks,
1117
1119
  # so we re-rank them using a cross-encoder scoring model,
1118
1120
  # and pick top k where k = config.parsing.n_similar_docs
@@ -1129,6 +1131,11 @@ class DocChatAgent(ChatAgent):
1129
1131
  # (see Lost In the Middle issue).
1130
1132
  passages = self.rerank_to_periphery(passages)
1131
1133
 
1134
+ if not self.config.rerank_after_adding_context:
1135
+ passages_scores = [(p, 0.0) for p in passages]
1136
+ passages_scores = self.add_context_window(passages_scores)
1137
+ passages = [p for p, _ in passages_scores]
1138
+
1132
1139
  return passages
1133
1140
 
1134
1141
  @no_type_check
langroid/agent/task.py CHANGED
@@ -170,7 +170,8 @@ class Task:
170
170
  agent.set_system_message(system_message)
171
171
  if user_message:
172
172
  agent.set_user_message(user_message)
173
-
173
+ self.max_cost: float = 0
174
+ self.max_tokens: int = 0
174
175
  self.logger: None | RichFileLogger = None
175
176
  self.tsv_logger: None | logging.Logger = None
176
177
  self.color_log: bool = False if settings.notebook else True
@@ -375,11 +376,15 @@ class Task:
375
376
  msg: Optional[str | ChatDocument] = None,
376
377
  turns: int = -1,
377
378
  caller: None | Task = None,
379
+ max_cost: float = 0,
380
+ max_tokens: int = 0,
378
381
  ) -> Optional[ChatDocument]:
379
382
  """Synchronous version of `run_async()`.
380
383
  See `run_async()` for details."""
381
384
  self.task_progress = False
382
385
  self.n_stalled_steps = 0
386
+ self.max_cost = max_cost
387
+ self.max_tokens = max_tokens
383
388
  assert (
384
389
  msg is None or isinstance(msg, str) or isinstance(msg, ChatDocument)
385
390
  ), f"msg arg in Task.run() must be None, str, or ChatDocument, not {type(msg)}"
@@ -418,6 +423,8 @@ class Task:
418
423
  msg: Optional[str | ChatDocument] = None,
419
424
  turns: int = -1,
420
425
  caller: None | Task = None,
426
+ max_cost: float = 0,
427
+ max_tokens: int = 0,
421
428
  ) -> Optional[ChatDocument]:
422
429
  """
423
430
  Loop over `step()` until task is considered done or `turns` is reached.
@@ -434,6 +441,8 @@ class Task:
434
441
  turns (int): number of turns to run the task for;
435
442
  default is -1, which means run until task is done.
436
443
  caller (Task|None): the calling task, if any
444
+ max_cost (float): max cost allowed for the task (default 0 -> no limit)
445
+ max_tokens (int): max tokens allowed for the task (default 0 -> no limit)
437
446
 
438
447
  Returns:
439
448
  Optional[ChatDocument]: valid result of the task.
@@ -444,6 +453,9 @@ class Task:
444
453
  # message can be considered to be from the USER
445
454
  # (from the POV of this agent's LLM).
446
455
  self.task_progress = False
456
+ self.n_stalled_steps = 0
457
+ self.max_cost = max_cost
458
+ self.max_tokens = max_tokens
447
459
  if (
448
460
  isinstance(msg, ChatDocument)
449
461
  and msg.metadata.recipient != ""
@@ -819,6 +831,8 @@ class Task:
819
831
  self.pending_message,
820
832
  turns=actual_turns,
821
833
  caller=self,
834
+ max_cost=self.max_cost,
835
+ max_tokens=self.max_tokens,
822
836
  )
823
837
  result_str = str(ChatDocument.to_LLMMessage(result))
824
838
  maybe_tool = len(extract_top_level_json(result_str)) > 0
@@ -894,6 +908,8 @@ class Task:
894
908
  self.pending_message,
895
909
  turns=actual_turns,
896
910
  caller=self,
911
+ max_cost=self.max_cost,
912
+ max_tokens=self.max_tokens,
897
913
  )
898
914
  result_str = str(ChatDocument.to_LLMMessage(result))
899
915
  maybe_tool = len(extract_top_level_json(result_str)) > 0
@@ -1051,6 +1067,25 @@ class Task:
1051
1067
  )
1052
1068
  return True
1053
1069
 
1070
+ if self.max_cost > 0 and self.agent.llm is not None:
1071
+ try:
1072
+ if self.agent.llm.tot_tokens_cost()[1] > self.max_cost:
1073
+ logger.warning(
1074
+ f"Task {self.name} cost exceeded {self.max_cost}; exiting."
1075
+ )
1076
+ return True
1077
+ except Exception:
1078
+ pass
1079
+
1080
+ if self.max_tokens > 0 and self.agent.llm is not None:
1081
+ try:
1082
+ if self.agent.llm.tot_tokens_cost()[0] > self.max_tokens:
1083
+ logger.warning(
1084
+ f"Task {self.name} uses > {self.max_tokens} tokens; exiting."
1085
+ )
1086
+ return True
1087
+ except Exception:
1088
+ pass
1054
1089
  return (
1055
1090
  # no valid response from any entity/agent in current turn
1056
1091
  result is None
@@ -449,6 +449,18 @@ class LanguageModel(ABC):
449
449
  s += f"{model}: {counter}\n"
450
450
  return s
451
451
 
452
+ @classmethod
453
+ def tot_tokens_cost(cls) -> Tuple[int, float]:
454
+ """
455
+ Return total tokens used and total cost across all models.
456
+ """
457
+ total_tokens = 0
458
+ total_cost = 0.0
459
+ for counter in cls.usage_cost_dict.values():
460
+ total_tokens += counter.total_tokens
461
+ total_cost += counter.cost
462
+ return total_tokens, total_cost
463
+
452
464
  def followup_to_standalone(
453
465
  self, chat_history: List[Tuple[str, str]], question: str
454
466
  ) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langroid
3
- Version: 0.1.230
3
+ Version: 0.1.233
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -1,7 +1,7 @@
1
1
  langroid/__init__.py,sha256=qgY-OqzYSWOc6EytQJN9sH2PwDp1UIzP9lXhrYH6aLU,1645
2
2
  langroid/agent/__init__.py,sha256=_D8dxnfdr92ch1CIrUkKjrB5HVvsQdn62b1Fb2kBxV8,785
3
3
  langroid/agent/base.py,sha256=jyGFmojrFuOy81lUkNsJlR6mLIOY6kOD20P9dhEcEuw,35059
4
- langroid/agent/batch.py,sha256=T9dgSPThrmIWxQxqDlGwhHa7yw3XIKE_U30bLMRDpNQ,9481
4
+ langroid/agent/batch.py,sha256=SyvUwKetPH_4JKgTnV0bgXS7eD_qfFl9cq06lnill4o,9956
5
5
  langroid/agent/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  langroid/agent/callbacks/chainlit.py,sha256=aYuJ8M4VDHr5oymoXL2bpThM7p6P9L45fgJf3MLdkWo,20997
7
7
  langroid/agent/chat_agent.py,sha256=X5uVMm9qdw3j-FRf4hbN8k8ByaSdtQCTuU8olKE0sbs,38750
@@ -10,7 +10,7 @@ langroid/agent/helpers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  langroid/agent/junk,sha256=LxfuuW7Cijsg0szAzT81OjWWv1PMNI-6w_-DspVIO2s,339
11
11
  langroid/agent/openai_assistant.py,sha256=xWSDR4SyMcZhCUkgaM4-mu77rbEDF_xpt7N8m8CkiA4,32962
12
12
  langroid/agent/special/__init__.py,sha256=XPE076zD-roskxNBn-A1hnh4AHoMiQN9gk1UDjPaBaU,1201
13
- langroid/agent/special/doc_chat_agent.py,sha256=Ur57J3xolTaoTgzr2DfP8TY7BViIMNFGNEmmRfHbkL4,53373
13
+ langroid/agent/special/doc_chat_agent.py,sha256=LwWNb_1s5n9rOk9OpOFPuuY1VnVX5DjzQmPwBanKRrM,53763
14
14
  langroid/agent/special/lance_doc_chat_agent.py,sha256=USp0U3eTaJzwF_3bdqE7CedSLbaqAi2tm-VzygcyLaA,10175
15
15
  langroid/agent/special/lance_rag/__init__.py,sha256=QTbs0IVE2ZgDg8JJy1zN97rUUg4uEPH7SLGctFNumk4,174
16
16
  langroid/agent/special/lance_rag/critic_agent.py,sha256=pi_9eMBxEycbWTddtq_yz-mOb2V4SgGm3zfsOH1HU-Q,5775
@@ -32,7 +32,7 @@ langroid/agent/special/sql/utils/populate_metadata.py,sha256=x2OMKfmIBnJESBG3qKt
32
32
  langroid/agent/special/sql/utils/system_message.py,sha256=qKLHkvQWRQodTtPLPxr1GSLUYUFASZU8x-ybV67cB68,1885
33
33
  langroid/agent/special/sql/utils/tools.py,sha256=6uB2424SLtmapui9ggcEr0ZTiB6_dL1-JRGgN8RK9Js,1332
34
34
  langroid/agent/special/table_chat_agent.py,sha256=-Qtqr2FP8VcyYcA-Pzqa9ucSl1-nXudbNsv_qakSSco,9041
35
- langroid/agent/task.py,sha256=sFncTES0L_O2IpbnHRrNzad0HhtsbHoQ7j3Cjc9eTt0,49711
35
+ langroid/agent/task.py,sha256=jUeKRreYvs_6OlOqVxqfYWQHtvDZViUDtx5wl_b9cyY,51160
36
36
  langroid/agent/tool_message.py,sha256=2kPsQUwi3ZzINTUNj10huKnZLjLp5SXmefacTHx8QDc,8304
37
37
  langroid/agent/tools/__init__.py,sha256=q-maq3k2BXhPAU99G0H6-j_ozoRvx15I1RFpPVicQIU,304
38
38
  langroid/agent/tools/duckduckgo_search_tool.py,sha256=mLGhlgs6pwbYZIwrOs9shfh1dMBVT4DtkR29pYL3cCQ,1900
@@ -59,7 +59,7 @@ langroid/embedding_models/protoc/embeddings_pb2_grpc.py,sha256=9dYQqkW3JPyBpSEje
59
59
  langroid/embedding_models/remote_embeds.py,sha256=6_kjXByVbqhY9cGwl9R83ZcYC2km-nGieNNAo1McHaY,5151
60
60
  langroid/language_models/__init__.py,sha256=5L9ndEEC8iLJHjDJmYFTnv6-2-3xsxWUMHcugR8IeDs,821
61
61
  langroid/language_models/azure_openai.py,sha256=ncRCbKooqLVOY-PWQUIo9C3yTuKEFbAwyngXT_M4P7k,5989
62
- langroid/language_models/base.py,sha256=Yy_6TP9Qj5CmNtDVQfbcyfytCsvGyow0e1OeqhWGY0A,20638
62
+ langroid/language_models/base.py,sha256=B6dX43ZR65mIvjD95W4RcfpT-WpmiuEcstR3eMrr56Y,21029
63
63
  langroid/language_models/config.py,sha256=5UF3DzO1a-Dfsc3vghE0XGq7g9t_xDsRCsuRiU4dgBg,366
64
64
  langroid/language_models/openai_assistants.py,sha256=9K-DEAL2aSWHeXj2hwCo2RAlK9_1oCPtqX2u1wISCj8,36
65
65
  langroid/language_models/openai_gpt.py,sha256=hR0ibmumIq1TnOGdb80SW0EN6YZn6DZazd5waFHKqGk,49357
@@ -120,7 +120,7 @@ langroid/vector_store/meilisearch.py,sha256=d2huA9P-NoYRuAQ9ZeXJmMKr7ry8u90RUSR2
120
120
  langroid/vector_store/momento.py,sha256=9cui31TTrILid2KIzUpBkN2Ey3g_CZWOQVdaFsA4Ors,10045
121
121
  langroid/vector_store/qdrant_cloud.py,sha256=3im4Mip0QXLkR6wiqVsjV1QvhSElfxdFSuDKddBDQ-4,188
122
122
  langroid/vector_store/qdrantdb.py,sha256=foKRxRv0BBony6S4Vt0Vav9Rn9HMxZvcIh1cE7nosFE,13524
123
- langroid-0.1.230.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
124
- langroid-0.1.230.dist-info/METADATA,sha256=SfBCAgSG2P-_1R2NxEFQWLFTAVzdNOGXRhR79EpYkeE,47863
125
- langroid-0.1.230.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
126
- langroid-0.1.230.dist-info/RECORD,,
123
+ langroid-0.1.233.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
124
+ langroid-0.1.233.dist-info/METADATA,sha256=vxJscoG8qWCn8tfLfCDhVHiomACst_EJcldbP3PNw_M,47863
125
+ langroid-0.1.233.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
126
+ langroid-0.1.233.dist-info/RECORD,,