langroid 0.1.231__tar.gz → 0.1.234__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.231 → langroid-0.1.234}/PKG-INFO +1 -1
  2. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/batch.py +8 -1
  3. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/__init__.py +2 -2
  4. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/doc_chat_agent.py +10 -3
  5. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/table_chat_agent.py +39 -49
  6. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/task.py +20 -2
  7. {langroid-0.1.231 → langroid-0.1.234}/pyproject.toml +1 -1
  8. {langroid-0.1.231 → langroid-0.1.234}/LICENSE +0 -0
  9. {langroid-0.1.231 → langroid-0.1.234}/README.md +0 -0
  10. {langroid-0.1.231 → langroid-0.1.234}/langroid/__init__.py +0 -0
  11. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/__init__.py +0 -0
  12. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/base.py +0 -0
  13. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/callbacks/__init__.py +0 -0
  14. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/callbacks/chainlit.py +0 -0
  15. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/chat_agent.py +0 -0
  16. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/chat_document.py +0 -0
  17. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/helpers.py +0 -0
  18. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/junk +0 -0
  19. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/openai_assistant.py +0 -0
  20. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/lance_doc_chat_agent.py +0 -0
  21. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/lance_rag/__init__.py +0 -0
  22. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/lance_rag/critic_agent.py +0 -0
  23. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/lance_rag/lance_rag_task.py +0 -0
  24. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/lance_rag/query_planner_agent.py +0 -0
  25. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/lance_tools.py +0 -0
  26. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/neo4j/__init__.py +0 -0
  27. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/neo4j/csv_kg_chat.py +0 -0
  28. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/neo4j/neo4j_chat_agent.py +0 -0
  29. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/neo4j/utils/__init__.py +0 -0
  30. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/neo4j/utils/system_message.py +0 -0
  31. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/relevance_extractor_agent.py +0 -0
  32. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/retriever_agent.py +0 -0
  33. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/sql/__init__.py +0 -0
  34. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/sql/sql_chat_agent.py +0 -0
  35. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/sql/utils/__init__.py +0 -0
  36. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/sql/utils/description_extractors.py +0 -0
  37. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/sql/utils/populate_metadata.py +0 -0
  38. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/sql/utils/system_message.py +0 -0
  39. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/special/sql/utils/tools.py +0 -0
  40. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tool_message.py +0 -0
  41. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tools/__init__.py +0 -0
  42. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tools/duckduckgo_search_tool.py +0 -0
  43. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tools/extract_tool.py +0 -0
  44. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tools/generator_tool.py +0 -0
  45. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tools/google_search_tool.py +0 -0
  46. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tools/metaphor_search_tool.py +0 -0
  47. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tools/recipient_tool.py +0 -0
  48. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tools/run_python_code.py +0 -0
  49. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent/tools/segment_extract_tool.py +0 -0
  50. {langroid-0.1.231 → langroid-0.1.234}/langroid/agent_config.py +0 -0
  51. {langroid-0.1.231 → langroid-0.1.234}/langroid/cachedb/__init__.py +0 -0
  52. {langroid-0.1.231 → langroid-0.1.234}/langroid/cachedb/base.py +0 -0
  53. {langroid-0.1.231 → langroid-0.1.234}/langroid/cachedb/momento_cachedb.py +0 -0
  54. {langroid-0.1.231 → langroid-0.1.234}/langroid/cachedb/redis_cachedb.py +0 -0
  55. {langroid-0.1.231 → langroid-0.1.234}/langroid/embedding_models/__init__.py +0 -0
  56. {langroid-0.1.231 → langroid-0.1.234}/langroid/embedding_models/base.py +0 -0
  57. {langroid-0.1.231 → langroid-0.1.234}/langroid/embedding_models/clustering.py +0 -0
  58. {langroid-0.1.231 → langroid-0.1.234}/langroid/embedding_models/models.py +0 -0
  59. {langroid-0.1.231 → langroid-0.1.234}/langroid/embedding_models/protoc/embeddings.proto +0 -0
  60. {langroid-0.1.231 → langroid-0.1.234}/langroid/embedding_models/protoc/embeddings_pb2.py +0 -0
  61. {langroid-0.1.231 → langroid-0.1.234}/langroid/embedding_models/protoc/embeddings_pb2.pyi +0 -0
  62. {langroid-0.1.231 → langroid-0.1.234}/langroid/embedding_models/protoc/embeddings_pb2_grpc.py +0 -0
  63. {langroid-0.1.231 → langroid-0.1.234}/langroid/embedding_models/remote_embeds.py +0 -0
  64. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/__init__.py +0 -0
  65. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/azure_openai.py +0 -0
  66. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/base.py +0 -0
  67. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/config.py +0 -0
  68. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/openai_assistants.py +0 -0
  69. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/openai_gpt.py +0 -0
  70. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/prompt_formatter/__init__.py +0 -0
  71. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/prompt_formatter/base.py +0 -0
  72. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/prompt_formatter/hf_formatter.py +0 -0
  73. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/prompt_formatter/llama2_formatter.py +0 -0
  74. {langroid-0.1.231 → langroid-0.1.234}/langroid/language_models/utils.py +0 -0
  75. {langroid-0.1.231 → langroid-0.1.234}/langroid/mytypes.py +0 -0
  76. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/__init__.py +0 -0
  77. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/agent_chats.py +0 -0
  78. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/code-parsing.md +0 -0
  79. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/code_parser.py +0 -0
  80. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/config.py +0 -0
  81. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/document_parser.py +0 -0
  82. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/image_text.py +0 -0
  83. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/para_sentence_split.py +0 -0
  84. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/parse_json.py +0 -0
  85. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/parser.py +0 -0
  86. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/repo_loader.py +0 -0
  87. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/search.py +0 -0
  88. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/spider.py +0 -0
  89. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/table_loader.py +0 -0
  90. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/url_loader.py +0 -0
  91. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/url_loader_cookies.py +0 -0
  92. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/urls.py +0 -0
  93. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/utils.py +0 -0
  94. {langroid-0.1.231 → langroid-0.1.234}/langroid/parsing/web_search.py +0 -0
  95. {langroid-0.1.231 → langroid-0.1.234}/langroid/prompts/__init__.py +0 -0
  96. {langroid-0.1.231 → langroid-0.1.234}/langroid/prompts/chat-gpt4-system-prompt.md +0 -0
  97. {langroid-0.1.231 → langroid-0.1.234}/langroid/prompts/dialog.py +0 -0
  98. {langroid-0.1.231 → langroid-0.1.234}/langroid/prompts/prompts_config.py +0 -0
  99. {langroid-0.1.231 → langroid-0.1.234}/langroid/prompts/templates.py +0 -0
  100. {langroid-0.1.231 → langroid-0.1.234}/langroid/prompts/transforms.py +0 -0
  101. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/__init__.py +0 -0
  102. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/algorithms/__init__.py +0 -0
  103. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/algorithms/graph.py +0 -0
  104. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/configuration.py +0 -0
  105. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/constants.py +0 -0
  106. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/docker.py +0 -0
  107. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/globals.py +0 -0
  108. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/llms/__init__.py +0 -0
  109. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/llms/strings.py +0 -0
  110. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/logging.py +0 -0
  111. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/output/__init__.py +0 -0
  112. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/output/printing.py +0 -0
  113. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/output/status.py +0 -0
  114. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/pandas_utils.py +0 -0
  115. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/pydantic_utils.py +0 -0
  116. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/system.py +0 -0
  117. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/web/__init__.py +0 -0
  118. {langroid-0.1.231 → langroid-0.1.234}/langroid/utils/web/login.py +0 -0
  119. {langroid-0.1.231 → langroid-0.1.234}/langroid/vector_store/__init__.py +0 -0
  120. {langroid-0.1.231 → langroid-0.1.234}/langroid/vector_store/base.py +0 -0
  121. {langroid-0.1.231 → langroid-0.1.234}/langroid/vector_store/chromadb.py +0 -0
  122. {langroid-0.1.231 → langroid-0.1.234}/langroid/vector_store/lancedb.py +0 -0
  123. {langroid-0.1.231 → langroid-0.1.234}/langroid/vector_store/meilisearch.py +0 -0
  124. {langroid-0.1.231 → langroid-0.1.234}/langroid/vector_store/momento.py +0 -0
  125. {langroid-0.1.231 → langroid-0.1.234}/langroid/vector_store/qdrant_cloud.py +0 -0
  126. {langroid-0.1.231 → langroid-0.1.234}/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.231
3
+ Version: 0.1.234
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -32,6 +32,7 @@ def run_batch_task_gen(
32
32
  message: Optional[str] = None,
33
33
  handle_exceptions: bool = False,
34
34
  max_cost: float = 0.0,
35
+ max_tokens: int = 0,
35
36
  ) -> list[U]:
36
37
  """
37
38
  Generate and run copies of a task async/concurrently one per item in `items` list.
@@ -53,6 +54,7 @@ def run_batch_task_gen(
53
54
  handle_exceptions: bool: Whether to replace exceptions with outputs of None
54
55
  max_cost: float: maximum cost to run the task (default 0.0 for unlimited)
55
56
 
57
+
56
58
  Returns:
57
59
  list[Any]: list of final results
58
60
  """
@@ -64,7 +66,9 @@ def run_batch_task_gen(
64
66
  task_i.agent.llm.set_stream(False)
65
67
  task_i.agent.config.show_stats = False
66
68
 
67
- result = await task_i.run_async(input, turns=turns, max_cost=max_cost)
69
+ result = await task_i.run_async(
70
+ input, turns=turns, max_cost=max_cost, max_tokens=max_tokens
71
+ )
68
72
  return result
69
73
 
70
74
  async def _do_all(
@@ -123,6 +127,7 @@ def run_batch_tasks(
123
127
  batch_size: Optional[int] = None,
124
128
  turns: int = -1,
125
129
  max_cost: float = 0.0,
130
+ max_tokens: int = 0,
126
131
  ) -> List[U]:
127
132
  """
128
133
  Run copies of `task` async/concurrently one per item in `items` list.
@@ -141,6 +146,7 @@ def run_batch_tasks(
141
146
  if None, unbatched
142
147
  turns (int): number of turns to run, -1 for infinite
143
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)
144
150
 
145
151
  Returns:
146
152
  list[Any]: list of final results
@@ -156,6 +162,7 @@ def run_batch_tasks(
156
162
  turns,
157
163
  message,
158
164
  max_cost=max_cost,
165
+ max_tokens=max_tokens,
159
166
  )
160
167
 
161
168
 
@@ -14,7 +14,7 @@ from .table_chat_agent import (
14
14
  dataframe_summary,
15
15
  TableChatAgent,
16
16
  TableChatAgentConfig,
17
- RunCodeTool,
17
+ PandasEvalTool,
18
18
  )
19
19
  from . import sql
20
20
  from . import relevance_extractor_agent
@@ -38,7 +38,7 @@ __all__ = [
38
38
  "dataframe_summary",
39
39
  "TableChatAgent",
40
40
  "TableChatAgentConfig",
41
- "RunCodeTool",
41
+ "PandasEvalTool",
42
42
  "sql",
43
43
  "relevance_extractor_agent",
44
44
  "doc_chat_agent",
@@ -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
@@ -2,10 +2,11 @@
2
2
  Agent that supports asking queries about a tabular dataset, internally
3
3
  represented as a Pandas dataframe. The `TableChatAgent` is configured with a
4
4
  dataset, which can be a Pandas df, file or URL. The delimiter/separator
5
- is auto-detected. In response to a user query, the Agent's LLM generates Pandas
6
- code to answer the query. The code is passed via the `run_code` tool/function-call,
7
- which is handled by the Agent's `run_code` method. This method executes/evaluates
8
- the code and returns the result as a string.
5
+ is auto-detected. In response to a user query, the Agent's LLM generates a Pandas
6
+ expression (involving a dataframe `df`) to answer the query.
7
+ The expression is passed via the `pandas_eval` tool/function-call,
8
+ which is handled by the Agent's `pandas_eval` method. This method evaluates
9
+ the expression and returns the result as a string.
9
10
  """
10
11
 
11
12
  import io
@@ -35,25 +36,26 @@ DEFAULT_TABLE_CHAT_SYSTEM_MESSAGE = f"""
35
36
  You are a savvy data scientist, with expertise in analyzing tabular datasets,
36
37
  using Python and the Pandas library for dataframe manipulation.
37
38
  Since you do not have access to the dataframe 'df', you
38
- will need to use the `run_code` tool/function-call to answer my questions.
39
+ will need to use the `pandas_eval` tool/function-call to answer my questions.
39
40
  Here is a summary of the dataframe:
40
41
  {{summary}}
41
42
  Do not assume any columns other than those shown.
42
- In the code you submit to the `run_code` tool/function,
43
- do not forget to include any necessary imports, such as `import pandas as pd`.
44
- Sometimes you may not be able to answer the question in a single call to `run_code`,
45
- so you can use a series of calls to `run_code` to build up the answer.
43
+ In the expression you submit to the `pandas_eval` tool/function,
44
+ you are allowed to use the variable 'df' to refer to the dataframe.
45
+
46
+ Sometimes you may not be able to answer the question in a single call to `pandas_eval`,
47
+ so you can use a series of calls to `pandas_eval` to build up the answer.
46
48
  For example you may first want to know something about the possible values in a column.
47
49
 
48
50
  If you receive a null or other unexpected result, see if you have made an assumption
49
- in your code, and try another way, or use `run_code` to explore the dataframe
51
+ in your code, and try another way, or use `pandas_eval` to explore the dataframe
50
52
  before submitting your final code.
51
53
 
52
54
  Once you have the answer to the question, possibly after a few steps,
53
55
  say {DONE} and show me the answer. If you receive an error message,
54
- try using the `run_code` tool/function again with the corrected code.
56
+ try using the `pandas_eval` tool/function again with the corrected code.
55
57
 
56
- VERY IMPORTANT: When using the `run_code` tool/function, DO NOT EXPLAIN ANYTHING,
58
+ VERY IMPORTANT: When using the `pandas_eval` tool/function, DO NOT EXPLAIN ANYTHING,
57
59
  SIMPLY USE THE TOOL, with the CODE.
58
60
  Start by asking me what I want to know about the data.
59
61
  """
@@ -123,22 +125,22 @@ class TableChatAgentConfig(ChatAgentConfig):
123
125
  )
124
126
 
125
127
 
126
- class RunCodeTool(ToolMessage):
127
- """Tool/function to run code on a dataframe named `df`"""
128
+ class PandasEvalTool(ToolMessage):
129
+ """Tool/function to evaluate a pandas expression involving a dataframe `df`"""
128
130
 
129
- request: str = "run_code"
131
+ request: str = "pandas_eval"
130
132
  purpose: str = """
131
- To run <code> on the dataframe 'df' and
133
+ To eval a pandas <expression> on the dataframe 'df' and
132
134
  return the results to answer a question.
133
- IMPORTANT: ALL the code should be in the <code> field.
135
+ IMPORTANT: the <expression> field should be a valid pandas expression.
134
136
  """
135
- code: str
137
+ expression: str
136
138
 
137
139
  @classmethod
138
140
  def examples(cls) -> List["ToolMessage"]:
139
141
  return [
140
- cls(code="df.head()"),
141
- cls(code="df[(df['gender'] == 'Male')]['income'].mean()"),
142
+ cls(expression="df.head()"),
143
+ cls(expression="df[(df['gender'] == 'Male')]['income'].mean()"),
142
144
  ]
143
145
 
144
146
 
@@ -147,7 +149,7 @@ class TableChatAgent(ChatAgent):
147
149
  Agent for chatting with a collection of documents.
148
150
  """
149
151
 
150
- sent_code: bool = False
152
+ sent_expression: bool = False
151
153
 
152
154
  def __init__(self, config: TableChatAgentConfig):
153
155
  if isinstance(config.data, pd.DataFrame):
@@ -170,8 +172,8 @@ class TableChatAgent(ChatAgent):
170
172
  {self.df.columns}
171
173
  """
172
174
  )
173
- # enable the agent to use and handle the RunCodeTool
174
- self.enable_message(RunCodeTool)
175
+ # enable the agent to use and handle the PandasEvalTool
176
+ self.enable_message(PandasEvalTool)
175
177
 
176
178
  def user_response(
177
179
  self,
@@ -179,44 +181,32 @@ class TableChatAgent(ChatAgent):
179
181
  ) -> Optional[ChatDocument]:
180
182
  response = super().user_response(msg)
181
183
  if response is not None and response.content != "":
182
- self.sent_code = False
184
+ self.sent_expression = False
183
185
  return response
184
186
 
185
- def run_code(self, msg: RunCodeTool) -> str:
187
+ def pandas_eval(self, msg: PandasEvalTool) -> str:
186
188
  """
187
- Handle a RunCodeTool message by running the code and returning the result.
189
+ Handle a PandasEvalTool message by evaluating the `expression` field
190
+ and returning the result.
188
191
  Args:
189
- msg (RunCodeTool): The tool-message to handle.
192
+ msg (PandasEvalTool): The tool-message to handle.
190
193
 
191
194
  Returns:
192
195
  str: The result of running the code along with any print output.
193
196
  """
194
- self.sent_code = True
195
- code = msg.code
196
- # Create a dictionary that maps 'df' to the actual DataFrame
197
+ self.sent_expression = True
198
+ exprn = msg.expression
197
199
  local_vars = {"df": self.df}
198
-
199
200
  # Create a string-based I/O stream
200
201
  code_out = io.StringIO()
201
202
 
202
203
  # Temporarily redirect standard output to our string-based I/O stream
203
204
  sys.stdout = code_out
204
205
 
205
- # Split the code into lines
206
- lines = code.strip().split("\n")
207
-
208
- lines = [
209
- "import pandas as pd",
210
- "import numpy as np",
211
- ] + lines
212
-
213
- # Run all lines as statements except for the last one
214
- for line in lines[:-1]:
215
- exec(line, {}, local_vars)
216
206
 
217
207
  # Evaluate the last line and get the result
218
208
  try:
219
- eval_result = pd.eval(lines[-1], local_dict=local_vars)
209
+ eval_result = pd.eval(exprn, local_dict=local_vars)
220
210
  except Exception as e:
221
211
  eval_result = f"ERROR: {type(e)}: {e}"
222
212
 
@@ -242,15 +232,15 @@ class TableChatAgent(ChatAgent):
242
232
  def handle_message_fallback(
243
233
  self, msg: str | ChatDocument
244
234
  ) -> str | ChatDocument | None:
245
- """Handle scenario where LLM forgets to say DONE or forgets to use run_code"""
235
+ """Handle scenario where LLM forgets to say DONE or
236
+ forgets to use pandas_eval"""
246
237
  if isinstance(msg, ChatDocument) and msg.metadata.sender == lr.Entity.LLM:
247
- if self.sent_code:
238
+ if self.sent_expression:
248
239
  return DONE
249
240
  else:
250
241
  return """
251
- You forgot to use the `run_code` tool/function to find the answer.
252
- Try again using the `run_code` tool/function.
253
- Remember that ALL your code, including imports,
254
- should be in the `code` field.
242
+ You forgot to use the `pandas_eval` tool/function
243
+ to find the answer.
244
+ Try again using the `pandas_eval` tool/function.
255
245
  """
256
246
  return None
@@ -171,6 +171,7 @@ class Task:
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
@@ -376,12 +377,14 @@ class Task:
376
377
  turns: int = -1,
377
378
  caller: None | Task = None,
378
379
  max_cost: float = 0,
380
+ max_tokens: int = 0,
379
381
  ) -> Optional[ChatDocument]:
380
382
  """Synchronous version of `run_async()`.
381
383
  See `run_async()` for details."""
382
384
  self.task_progress = False
383
385
  self.n_stalled_steps = 0
384
386
  self.max_cost = max_cost
387
+ self.max_tokens = max_tokens
385
388
  assert (
386
389
  msg is None or isinstance(msg, str) or isinstance(msg, ChatDocument)
387
390
  ), f"msg arg in Task.run() must be None, str, or ChatDocument, not {type(msg)}"
@@ -421,6 +424,7 @@ class Task:
421
424
  turns: int = -1,
422
425
  caller: None | Task = None,
423
426
  max_cost: float = 0,
427
+ max_tokens: int = 0,
424
428
  ) -> Optional[ChatDocument]:
425
429
  """
426
430
  Loop over `step()` until task is considered done or `turns` is reached.
@@ -437,7 +441,8 @@ class Task:
437
441
  turns (int): number of turns to run the task for;
438
442
  default is -1, which means run until task is done.
439
443
  caller (Task|None): the calling task, if any
440
- max_cost (float): maximum cost allowed for the task (default 0 -> no limit)
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)
441
446
 
442
447
  Returns:
443
448
  Optional[ChatDocument]: valid result of the task.
@@ -450,6 +455,7 @@ class Task:
450
455
  self.task_progress = False
451
456
  self.n_stalled_steps = 0
452
457
  self.max_cost = max_cost
458
+ self.max_tokens = max_tokens
453
459
  if (
454
460
  isinstance(msg, ChatDocument)
455
461
  and msg.metadata.recipient != ""
@@ -826,6 +832,7 @@ class Task:
826
832
  turns=actual_turns,
827
833
  caller=self,
828
834
  max_cost=self.max_cost,
835
+ max_tokens=self.max_tokens,
829
836
  )
830
837
  result_str = str(ChatDocument.to_LLMMessage(result))
831
838
  maybe_tool = len(extract_top_level_json(result_str)) > 0
@@ -901,6 +908,8 @@ class Task:
901
908
  self.pending_message,
902
909
  turns=actual_turns,
903
910
  caller=self,
911
+ max_cost=self.max_cost,
912
+ max_tokens=self.max_tokens,
904
913
  )
905
914
  result_str = str(ChatDocument.to_LLMMessage(result))
906
915
  maybe_tool = len(extract_top_level_json(result_str)) > 0
@@ -1062,12 +1071,21 @@ class Task:
1062
1071
  try:
1063
1072
  if self.agent.llm.tot_tokens_cost()[1] > self.max_cost:
1064
1073
  logger.warning(
1065
- f"Task {self.name} exceeded max cost {self.max_cost}; exiting."
1074
+ f"Task {self.name} cost exceeded {self.max_cost}; exiting."
1066
1075
  )
1067
1076
  return True
1068
1077
  except Exception:
1069
1078
  pass
1070
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
1071
1089
  return (
1072
1090
  # no valid response from any entity/agent in current turn
1073
1091
  result is None
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langroid"
3
- version = "0.1.231"
3
+ version = "0.1.234"
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