langroid 0.9.5__py3-none-any.whl → 0.10.0__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.
@@ -6,7 +6,7 @@ from .chat_document import (
6
6
  ChatDocument,
7
7
  )
8
8
  from .chat_agent import ChatAgentConfig, ChatAgent
9
- from .tool_message import ToolMessage
9
+ from .tool_message import ToolMessage, FinalResultTool
10
10
  from .task import Task
11
11
 
12
12
  from . import base
@@ -29,6 +29,7 @@ __all__ = [
29
29
  "ChatAgent",
30
30
  "ChatAgentConfig",
31
31
  "ToolMessage",
32
+ "FinalResultTool",
32
33
  "Task",
33
34
  "base",
34
35
  "chat_document",
langroid/agent/base.py CHANGED
@@ -1056,6 +1056,7 @@ class Agent(ABC):
1056
1056
  """
1057
1057
  try:
1058
1058
  tools = self.get_tool_messages(msg)
1059
+ tools = [t for t in tools if self._tool_recipient_match(t)]
1059
1060
  except ValidationError as ve:
1060
1061
  # correct tool name but bad fields
1061
1062
  return self.tool_validation_error(ve)
@@ -453,7 +453,7 @@ class ChatAgent(Agent):
453
453
  # remove leading and trailing newlines and other whitespace
454
454
  return LLMMessage(role=Role.SYSTEM, content=content.strip())
455
455
 
456
- def unhanded_tools(self) -> set[str]:
456
+ def unhandled_tools(self) -> set[str]:
457
457
  """The set of tools that are known but not handled.
458
458
  Useful in task flow: an agent can refuse to accept an incoming msg
459
459
  when it only has unhandled tools.
@@ -719,7 +719,7 @@ class ChatAgent(Agent):
719
719
  llm_msgs = ChatDocument.to_LLMMessage(message, self.oai_tool_calls)
720
720
  # LLM only responds to the content, so only those msgs with
721
721
  # non-empty content should be kept
722
- llm_msgs = [m for m in llm_msgs if m.content != ""]
722
+ llm_msgs = [m for m in llm_msgs if m.content.strip() != ""]
723
723
  if len(llm_msgs) == 0:
724
724
  return [], 0
725
725
  # process tools if any
@@ -119,7 +119,9 @@ class ChatDocument(Document):
119
119
  oai_tool_id2result: Optional[OrderedDict[str, str]] = None
120
120
  oai_tool_choice: ToolChoiceTypes | Dict[str, Dict[str, str] | str] = "auto"
121
121
  function_call: Optional[LLMFunctionCall] = None
122
- tool_messages: List[ToolMessage] = [] # only handle-able tools
122
+ # tools that are explicitly added by agent response/handler,
123
+ # or tools recognized in the ChatDocument as handle-able tools
124
+ tool_messages: List[ToolMessage] = []
123
125
  # all known tools in the msg that are in an agent's llm_tools_known list,
124
126
  # even if non-used/handled
125
127
  all_tool_messages: List[ToolMessage] = []
@@ -0,0 +1,9 @@
1
+ from langroid.agent.tool_message import ToolMessage
2
+
3
+
4
+ class StructuredMessage(ToolMessage):
5
+ request: str = ""
6
+ purpose: str = "Wrapper for a structured message"
7
+
8
+ # allow subclasses to inhert this "extras allowed" config
9
+ # model_config = ConfigDict(extra=Extra.allow)
langroid/agent/task.py CHANGED
@@ -33,7 +33,7 @@ from langroid.agent.chat_document import (
33
33
  ChatDocument,
34
34
  StatusCode,
35
35
  )
36
- from langroid.agent.tool_message import ToolMessage
36
+ from langroid.agent.tool_message import FinalResultTool, ToolMessage
37
37
  from langroid.agent.tools.orchestration import AgentDoneTool, DoneTool
38
38
  from langroid.cachedb.redis_cachedb import RedisCache, RedisCacheConfig
39
39
  from langroid.exceptions import InfiniteLoopException
@@ -1399,14 +1399,18 @@ class Task:
1399
1399
  # if there is an LLMDoneTool or AgentDoneTool among these,
1400
1400
  # we extract content and tools from here, and ignore all others
1401
1401
  for t in tool_messages:
1402
- if isinstance(t, (AgentDoneTool, DoneTool)):
1402
+ if isinstance(t, FinalResultTool):
1403
+ content = ""
1404
+ tool_messages = [t] # pass it on to parent so it also quits
1405
+ break
1406
+ elif isinstance(t, (AgentDoneTool, DoneTool)):
1403
1407
  # there shouldn't be multiple tools like this; just take the first
1404
1408
  content = t.content
1405
1409
  if isinstance(t, AgentDoneTool):
1406
1410
  tool_messages = t.tools
1407
1411
  break
1408
1412
  # drop the "Done" tools since they should not be part of the task result,
1409
- # or else they would cause the parent task to get done!
1413
+ # or else they would cause the parent task to get unintentionally done!
1410
1414
  tool_messages = [
1411
1415
  t for t in tool_messages if not isinstance(t, (DoneTool, AgentDoneTool))
1412
1416
  ]
@@ -1473,7 +1477,7 @@ class Task:
1473
1477
  and (
1474
1478
  DONE in result.content
1475
1479
  or any(
1476
- isinstance(t, (DoneTool, AgentDoneTool))
1480
+ isinstance(t, (DoneTool, AgentDoneTool, FinalResultTool))
1477
1481
  for t in result.tool_messages
1478
1482
  )
1479
1483
  )
@@ -1594,7 +1598,8 @@ class Task:
1594
1598
  done_result = result is not None and (
1595
1599
  DONE in (result.content if isinstance(result, str) else result.content)
1596
1600
  or any(
1597
- isinstance(t, (DoneTool, AgentDoneTool)) for t in result.tool_messages
1601
+ isinstance(t, (DoneTool, AgentDoneTool, FinalResultTool))
1602
+ for t in result.tool_messages
1598
1603
  )
1599
1604
  )
1600
1605
 
@@ -273,3 +273,29 @@ class ToolMessage(ABC, BaseModel):
273
273
  exclude=list(cls.Config.schema_extra["exclude"]),
274
274
  )
275
275
  return schema
276
+
277
+
278
+ class FinalResultTool(ToolMessage):
279
+ """Class to use as a wrapper for sending arbitrary results from an Agent's
280
+ agent_response or tool handlers, to:
281
+ (a) trigger completion of the current task as well as all parent tasks, and
282
+ (b) be returned as the final result of the root task, i.e. this tool would appear
283
+ in the final ChatDocument's `tool_messages` list.
284
+ See test_tool_handlers_and_results in test_tool_messages.py, and
285
+ examples/basic/tool-extract-short-example.py.
286
+
287
+ Note:
288
+ - when defining a tool handler or agent_response, you can directly return
289
+ FinalResultTool(field1 = val1, ...),
290
+ where the values can be aribitrary data structures, including nested
291
+ Pydantic objs, or you can define a subclass of FinalResultTool with the
292
+ fields you want to return.
293
+ - This is a special ToolMessage that is NOT meant to be used or handled
294
+ by an agent.
295
+ """
296
+
297
+ request: str = ""
298
+ purpose: str = "Ignored; Wrapper for a structured message"
299
+
300
+ class Config:
301
+ extra = Extra.allow
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langroid
3
- Version: 0.9.5
3
+ Version: 0.10.0
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -1,11 +1,11 @@
1
1
  langroid/__init__.py,sha256=z_fCOLQJPOw3LLRPBlFB5-2HyCjpPgQa4m4iY5Fvb8Y,1800
2
- langroid/agent/__init__.py,sha256=ll0Cubd2DZ-fsCMl7e10hf9ZjFGKzphfBco396IKITY,786
3
- langroid/agent/base.py,sha256=MYG3kBduJxgQsGUpcS97SE2clTq4VUnGm1Ky6tKJhnM,58995
2
+ langroid/agent/__init__.py,sha256=CFjjVvXVEV4ac0PdNPHVQHREV2HbbHCF6wj42v5MpJ4,826
3
+ langroid/agent/base.py,sha256=c5RYAKotgJH1vfqZvnMBt10RCino26jJv3thEMKYyy0,59067
4
4
  langroid/agent/batch.py,sha256=feRA_yRG768ElOQjrKEefcRv6Aefd_yY7qktuYUQDwc,10040
5
5
  langroid/agent/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  langroid/agent/callbacks/chainlit.py,sha256=Qedk1-CBCgo9PdaIa7AboLBFCTgAMg9q5nGmoqpZ378,22050
7
- langroid/agent/chat_agent.py,sha256=VUuYweOLuH4lokvZLY74WXIG4AlxRU4L907ox_hoRA4,48107
8
- langroid/agent/chat_document.py,sha256=Cq-TbPefpxbx2QzGl-CUpIrCcEC34GHDGH6Fd0w7aYs,16693
7
+ langroid/agent/chat_agent.py,sha256=q39Taek6yhinGWDYP7Uze6p8jP5v5nvn-Y1k-yJB8TQ,48116
8
+ langroid/agent/chat_document.py,sha256=DnmRLma0zud0XsN_wm-F0fnQv3fjQghv3t8Ahudq238,16799
9
9
  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=2rjCZw45ysNBEGNzQM4uf0bTC4KkatGYAWcVcW4xcek,34337
@@ -32,8 +32,9 @@ 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=taSP80E_pcqa6OEGi9weOQXx7It8SZvgosfuVv4DQcw,80300
36
- langroid/agent/tool_message.py,sha256=pArap87HNODwBVH2Dyu4Oi_OOhK0NH65pDUOHvIKV0E,10101
35
+ langroid/agent/structured_message.py,sha256=y7pud1EgRNeTFZlJmBkLmwME3yQJ_IYik-Xds9kdZbY,282
36
+ langroid/agent/task.py,sha256=y4FXXLSJv_8LIox4-E48MG_VQl1558WCLR9w35-KBJ4,80560
37
+ langroid/agent/tool_message.py,sha256=EcWsi3LS7SGENO1V8DpM8UFdc5pwlcqelt1UL6KgLwA,11195
37
38
  langroid/agent/tools/__init__.py,sha256=lgWAWsPgMx-NdDPVX6tXO_U0cIQX7dwzhUC0G4IfUgk,726
38
39
  langroid/agent/tools/duckduckgo_search_tool.py,sha256=NhsCaGZkdv28nja7yveAhSK_w6l_Ftym8agbrdzqgfo,1935
39
40
  langroid/agent/tools/extract_tool.py,sha256=u5lL9rKBzaLBOrRyLnTAZ97pQ1uxyLP39XsWMnpaZpw,3789
@@ -133,8 +134,8 @@ langroid/vector_store/meilisearch.py,sha256=6frB7GFWeWmeKzRfLZIvzRjllniZ1cYj3Hmh
133
134
  langroid/vector_store/momento.py,sha256=qR-zBF1RKVHQZPZQYW_7g-XpTwr46p8HJuYPCkfJbM4,10534
134
135
  langroid/vector_store/qdrant_cloud.py,sha256=3im4Mip0QXLkR6wiqVsjV1QvhSElfxdFSuDKddBDQ-4,188
135
136
  langroid/vector_store/qdrantdb.py,sha256=v88lqFkepADvlN6lByUj9I4NEKa9X9lWH16uTPPbYrE,17457
136
- pyproject.toml,sha256=STQ2CYykc2Cf2J4p_RgIb0nXTw8esZs7k2gqurI6HSY,7087
137
- langroid-0.9.5.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
138
- langroid-0.9.5.dist-info/METADATA,sha256=OoluP4y6n-wu3Jsx2p9Ah5SRyhMTKQOA3_R5CyNvA7g,54751
139
- langroid-0.9.5.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
140
- langroid-0.9.5.dist-info/RECORD,,
137
+ pyproject.toml,sha256=WE_GhHAyFWSrzXRv6PO2Fz7Vz-JGL_Md8QPI5bKqYrw,7088
138
+ langroid-0.10.0.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
139
+ langroid-0.10.0.dist-info/METADATA,sha256=PDxK3LArvELAz8HNVfwwLK2o9Uk5kGKJfpwcd-ev9uY,54752
140
+ langroid-0.10.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
141
+ langroid-0.10.0.dist-info/RECORD,,
pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langroid"
3
- version = "0.9.5"
3
+ version = "0.10.0"
4
4
  description = "Harness LLMs with Multi-Agent Programming"
5
5
  authors = ["Prasad Chalasani <pchalasani@gmail.com>"]
6
6
  readme = "README.md"