langroid 0.53.2__py3-none-any.whl → 0.53.4__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/base.py +9 -12
- langroid/agent/chat_agent.py +32 -22
- langroid/agent/special/table_chat_agent.py +4 -2
- langroid/agent/xml_tool_message.py +11 -1
- {langroid-0.53.2.dist-info → langroid-0.53.4.dist-info}/METADATA +4 -2
- {langroid-0.53.2.dist-info → langroid-0.53.4.dist-info}/RECORD +8 -8
- {langroid-0.53.2.dist-info → langroid-0.53.4.dist-info}/WHEEL +0 -0
- {langroid-0.53.2.dist-info → langroid-0.53.4.dist-info}/licenses/LICENSE +0 -0
langroid/agent/base.py
CHANGED
@@ -124,13 +124,8 @@ async def async_lambda_noop_fn() -> Callable[..., Coroutine[Any, Any, None]]:
|
|
124
124
|
|
125
125
|
class Agent(ABC):
|
126
126
|
"""
|
127
|
-
An Agent is an abstraction that
|
128
|
-
|
129
|
-
- a language model (LLM)
|
130
|
-
- a vector store (vecdb)
|
131
|
-
|
132
|
-
plus associated components such as a parser, and variables that hold
|
133
|
-
information about any tool/function-calling messages that have been defined.
|
127
|
+
An Agent is an abstraction that typically (but not necessarily)
|
128
|
+
encapsulates an LLM.
|
134
129
|
"""
|
135
130
|
|
136
131
|
id: str = Field(default_factory=lambda: ObjectRegistry.new_id())
|
@@ -1087,8 +1082,9 @@ class Agent(ABC):
|
|
1087
1082
|
return False
|
1088
1083
|
|
1089
1084
|
def _tool_recipient_match(self, tool: ToolMessage) -> bool:
|
1090
|
-
"""Is tool
|
1091
|
-
|
1085
|
+
"""Is tool enabled for handling by this agent and intended for this
|
1086
|
+
agent to handle (i.e. if there's any explicit `recipient` field exists in
|
1087
|
+
tool, then it matches this agent's name)?
|
1092
1088
|
"""
|
1093
1089
|
if tool.default_value("request") not in self.llm_tools_handled:
|
1094
1090
|
return False
|
@@ -1098,8 +1094,8 @@ class Agent(ABC):
|
|
1098
1094
|
|
1099
1095
|
def has_only_unhandled_tools(self, msg: str | ChatDocument) -> bool:
|
1100
1096
|
"""
|
1101
|
-
Does the msg have at least one tool, and
|
1102
|
-
|
1097
|
+
Does the msg have at least one tool, and none of the tools in the msg are
|
1098
|
+
handleable by this agent?
|
1103
1099
|
"""
|
1104
1100
|
if msg is None:
|
1105
1101
|
return False
|
@@ -1535,7 +1531,8 @@ class Agent(ABC):
|
|
1535
1531
|
|
1536
1532
|
def handle_message_fallback(self, msg: str | ChatDocument) -> Any:
|
1537
1533
|
"""
|
1538
|
-
Fallback method for the
|
1534
|
+
Fallback method for the case where the msg has no tools that
|
1535
|
+
can be handled by this agent.
|
1539
1536
|
This method can be overridden by subclasses, e.g.,
|
1540
1537
|
to create a "reminder" message when a tool is expected but the LLM "forgot"
|
1541
1538
|
to generate one.
|
langroid/agent/chat_agent.py
CHANGED
@@ -574,8 +574,14 @@ class ChatAgent(Agent):
|
|
574
574
|
|
575
575
|
def handle_message_fallback(self, msg: str | ChatDocument) -> Any:
|
576
576
|
"""
|
577
|
-
Fallback method for the "no-tools" scenario.
|
578
|
-
|
577
|
+
Fallback method for the "no-tools" scenario, i.e., the current `msg`
|
578
|
+
(presumably emitted by the LLM) does not have any tool that the agent
|
579
|
+
can handle.
|
580
|
+
NOTE: The `msg` may contain tools but either (a) the agent is not
|
581
|
+
enabled to handle them, or (b) there's an explicit `recipient` field
|
582
|
+
in the tool that doesn't match the agent's name.
|
583
|
+
|
584
|
+
Uses the self.config.non_tool_routing to determine the action to take.
|
579
585
|
|
580
586
|
This method can be overridden by subclasses, e.g.,
|
581
587
|
to create a "reminder" message when a tool is expected but the LLM "forgot"
|
@@ -586,27 +592,31 @@ class ChatAgent(Agent):
|
|
586
592
|
Returns:
|
587
593
|
Any: The result of the handler method
|
588
594
|
"""
|
589
|
-
if
|
595
|
+
if (
|
596
|
+
isinstance(msg, str)
|
597
|
+
or msg.metadata.sender != Entity.LLM
|
598
|
+
or self.config.handle_llm_no_tool is None
|
599
|
+
or self.has_only_unhandled_tools(msg)
|
600
|
+
):
|
590
601
|
return None
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
return no_tool_option
|
602
|
+
# we ONLY use the `handle_llm_no_tool` config option when
|
603
|
+
# the msg is from LLM and does not contain ANY tools at all.
|
604
|
+
from langroid.agent.tools.orchestration import AgentDoneTool, ForwardTool
|
605
|
+
|
606
|
+
no_tool_option = self.config.handle_llm_no_tool
|
607
|
+
if no_tool_option in list(NonToolAction):
|
608
|
+
# in case the `no_tool_option` is one of the special NonToolAction vals
|
609
|
+
match self.config.handle_llm_no_tool:
|
610
|
+
case NonToolAction.FORWARD_USER:
|
611
|
+
return ForwardTool(agent="User")
|
612
|
+
case NonToolAction.DONE:
|
613
|
+
return AgentDoneTool(content=msg.content, tools=msg.tool_messages)
|
614
|
+
elif is_callable(no_tool_option):
|
615
|
+
return no_tool_option(msg)
|
616
|
+
# Otherwise just return `no_tool_option` as is:
|
617
|
+
# This can be any string, such as a specific nudge/reminder to the LLM,
|
618
|
+
# or even something like ResultTool etc.
|
619
|
+
return no_tool_option
|
610
620
|
|
611
621
|
def unhandled_tools(self) -> set[str]:
|
612
622
|
"""The set of tools that are known but not handled.
|
@@ -211,9 +211,11 @@ class TableChatAgent(ChatAgent):
|
|
211
211
|
# Temporarily redirect standard output to our string-based I/O stream
|
212
212
|
sys.stdout = code_out
|
213
213
|
|
214
|
-
# Evaluate the last line and get the result
|
214
|
+
# Evaluate the last line and get the result;
|
215
|
+
# SECURITY: eval only with empty globals and {"df": df} in locals to
|
216
|
+
# prevent arbitrary Python code execution.
|
215
217
|
try:
|
216
|
-
eval_result =
|
218
|
+
eval_result = eval(exprn, {}, local_vars)
|
217
219
|
except Exception as e:
|
218
220
|
eval_result = f"ERROR: {type(e)}: {e}"
|
219
221
|
|
@@ -49,7 +49,17 @@ class XMLToolMessage(ToolMessage):
|
|
49
49
|
Raises:
|
50
50
|
etree.XMLSyntaxError: If the input string is not valid XML.
|
51
51
|
"""
|
52
|
-
|
52
|
+
# SECURITY: Initialize XMLParser with flags to prevent
|
53
|
+
# XML External Entity (XXE), billion laughs, and external DTD attacks by
|
54
|
+
# disabling entity resolution, DTD loading, and network access;
|
55
|
+
# `strip_cdata=False` is needed to preserve
|
56
|
+
# content within CDATA sections (e.g., for code).
|
57
|
+
parser = etree.XMLParser(
|
58
|
+
strip_cdata=False,
|
59
|
+
resolve_entities=False,
|
60
|
+
load_dtd=False,
|
61
|
+
no_network=True,
|
62
|
+
)
|
53
63
|
root = etree.fromstring(formatted_string.encode("utf-8"), parser=parser)
|
54
64
|
|
55
65
|
def parse_element(element: etree._Element) -> Any:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: langroid
|
3
|
-
Version: 0.53.
|
3
|
+
Version: 0.53.4
|
4
4
|
Summary: Harness LLMs with Multi-Agent Programming
|
5
5
|
Author-email: Prasad Chalasani <pchalasani@gmail.com>
|
6
6
|
License: MIT
|
@@ -27,7 +27,7 @@ Requires-Dist: grpcio<2.0.0,>=1.62.1
|
|
27
27
|
Requires-Dist: halo<1.0.0,>=0.0.31
|
28
28
|
Requires-Dist: jinja2<4.0.0,>=3.1.2
|
29
29
|
Requires-Dist: json-repair<1.0.0,>=0.29.9
|
30
|
-
Requires-Dist: lxml<
|
30
|
+
Requires-Dist: lxml<6.0.0,>=5.4.0
|
31
31
|
Requires-Dist: markdownify>=0.13.1
|
32
32
|
Requires-Dist: nest-asyncio<2.0.0,>=1.6.0
|
33
33
|
Requires-Dist: nltk<4.0.0,>=3.8.2
|
@@ -216,6 +216,8 @@ Description-Content-Type: text/markdown
|
|
216
216
|
[](https://colab.research.google.com/github/langroid/langroid/blob/main/examples/Langroid_quick_start.ipynb)
|
217
217
|
[](https://discord.gg/ZU36McDgDs)
|
218
218
|
[](https://langroid.substack.com/p/langroid-harness-llms-with-multi-agent-programming)
|
219
|
+
|
220
|
+
[](https://gitmcp.io/langroid/langroid)
|
219
221
|
</div>
|
220
222
|
|
221
223
|
<h3 align="center">
|
@@ -3,14 +3,14 @@ langroid/exceptions.py,sha256=OPjece_8cwg94DLPcOGA1ddzy5bGh65pxzcHMnssTz8,2995
|
|
3
3
|
langroid/mytypes.py,sha256=HIcYAqGeA9OK0Hlscym2FI5Oax9QFljDZoVgRlomhRk,4014
|
4
4
|
langroid/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
langroid/agent/__init__.py,sha256=ll0Cubd2DZ-fsCMl7e10hf9ZjFGKzphfBco396IKITY,786
|
6
|
-
langroid/agent/base.py,sha256=
|
6
|
+
langroid/agent/base.py,sha256=zHwhNU403H-ZvogH4QhKTzaZn5_jt0ZdPHzSEmycDoc,80035
|
7
7
|
langroid/agent/batch.py,sha256=vi1r5i1-vN80WfqHDSwjEym_KfGsqPGUtwktmiK1nuk,20635
|
8
|
-
langroid/agent/chat_agent.py,sha256=
|
8
|
+
langroid/agent/chat_agent.py,sha256=igo7wl3tOig7yae8NokEEqXS5AYuAeWJGq1YZhpzOho,85739
|
9
9
|
langroid/agent/chat_document.py,sha256=6O20Fp4QrquykaF2jFtwNHkvcoDte1LLwVZNk9mVH9c,18057
|
10
10
|
langroid/agent/openai_assistant.py,sha256=JkAcs02bIrgPNVvUWVR06VCthc5-ulla2QMBzux_q6o,34340
|
11
11
|
langroid/agent/task.py,sha256=HB6N-Jn80HFqCf0ZYOC1v3Bn3oO7NLjShHQJJFwW0q4,90557
|
12
12
|
langroid/agent/tool_message.py,sha256=BhjP-_TfQ2tgxuY4Yo_JHLOwwt0mJ4BwjPnREvEY4vk,14744
|
13
|
-
langroid/agent/xml_tool_message.py,sha256=
|
13
|
+
langroid/agent/xml_tool_message.py,sha256=Yf-OsqO6z17qgQbfcTX4dxmPMtwYZVfgcWjcWI8nJzE,15506
|
14
14
|
langroid/agent/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
15
|
langroid/agent/callbacks/chainlit.py,sha256=UHB6P_J40vsVnssosqkpkOVWRf9NK4TOY0_G2g_Arsg,20900
|
16
16
|
langroid/agent/special/__init__.py,sha256=gik_Xtm_zV7U9s30Mn8UX3Gyuy4jTjQe9zjiE3HWmEo,1273
|
@@ -20,7 +20,7 @@ langroid/agent/special/lance_doc_chat_agent.py,sha256=s8xoRs0gGaFtDYFUSIRchsgDVb
|
|
20
20
|
langroid/agent/special/lance_tools.py,sha256=qS8x4wi8mrqfbYV2ztFzrcxyhHQ0ZWOc-zkYiH7awj0,2105
|
21
21
|
langroid/agent/special/relevance_extractor_agent.py,sha256=zIx8GUdVo1aGW6ASla0NPQjYYIpmriK_TYMijqAx3F8,4796
|
22
22
|
langroid/agent/special/retriever_agent.py,sha256=o2UfqiCGME0t85SZ6qjK041_WZYqXSuV1SeH_3KtVuc,1931
|
23
|
-
langroid/agent/special/table_chat_agent.py,sha256=
|
23
|
+
langroid/agent/special/table_chat_agent.py,sha256=wC4DWRVMAGfVY33JqP8cNR4kO0dqD8ryjWzAkMFT5j0,9780
|
24
24
|
langroid/agent/special/arangodb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
25
|
langroid/agent/special/arangodb/arangodb_agent.py,sha256=12Y54c84c9qXV-YXRBcI5HaqyiY75JR4TmqlURYKJAM,25851
|
26
26
|
langroid/agent/special/arangodb/system_messages.py,sha256=udwfLleTdyz_DuxHuoiv2wHEZoAPBPbwdF_ivjIfP5c,6867
|
@@ -132,7 +132,7 @@ langroid/vector_store/pineconedb.py,sha256=otxXZNaBKb9f_H75HTaU3lMHiaR2NUp5MqwLZ
|
|
132
132
|
langroid/vector_store/postgres.py,sha256=wHPtIi2qM4fhO4pMQr95pz1ZCe7dTb2hxl4VYspGZoA,16104
|
133
133
|
langroid/vector_store/qdrantdb.py,sha256=O6dSBoDZ0jzfeVBd7LLvsXu083xs2fxXtPa9gGX3JX4,18443
|
134
134
|
langroid/vector_store/weaviatedb.py,sha256=Yn8pg139gOy3zkaPfoTbMXEEBCiLiYa1MU5d_3UA1K4,11847
|
135
|
-
langroid-0.53.
|
136
|
-
langroid-0.53.
|
137
|
-
langroid-0.53.
|
138
|
-
langroid-0.53.
|
135
|
+
langroid-0.53.4.dist-info/METADATA,sha256=mJijMq7-4U64bl-XA2rQiGdgW6A3TxdMMx60sa-E1Fc,64945
|
136
|
+
langroid-0.53.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
137
|
+
langroid-0.53.4.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
|
138
|
+
langroid-0.53.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|