langroid 0.19.5__py3-none-any.whl → 0.20.1__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.
@@ -0,0 +1,120 @@
1
+ from langroid.agent.special.neo4j.tools import (
2
+ cypher_creation_tool_name,
3
+ cypher_retrieval_tool_name,
4
+ graph_schema_tool_name,
5
+ )
6
+ from langroid.agent.tools.orchestration import DoneTool
7
+
8
+ done_tool_name = DoneTool.default_value("request")
9
+
10
+ graph_schema_tool_description = f"""
11
+ `{graph_schema_tool_name}` tool/function-call to get all the node labels, relationship
12
+ types, and property keys available in your Neo4j database. You MUST use
13
+ this tool BEFORE attempting to use the `{cypher_retrieval_tool_name}` tool,
14
+ to ensure that you are using the correct node labels, relationship types, and
15
+ property keys in your `{cypher_retrieval_tool_name}` tool/function-call.
16
+ """
17
+
18
+ cypher_retrieval_tool_description = f"""
19
+ `{cypher_retrieval_tool_name}` tool/function-call to retrieve information from the
20
+ graph database to answer questions.
21
+ """
22
+
23
+ cypher_creation_tool_description = f"""
24
+ `{cypher_creation_tool_name}` tool/function-call to execute cypher query that creates
25
+ entities/relationships in the graph database.
26
+ """
27
+
28
+ cypher_query_instructions = """
29
+ You must be smart about using the right node labels, relationship types, and property
30
+ keys based on the english description. If you are thinking of using a node label,
31
+ relationship type, or property key that does not exist, you are probably on the wrong
32
+ track, so you should try your best to answer based on an existing table or column.
33
+ DO NOT assume any nodes or relationships other than those above.
34
+ """
35
+
36
+
37
+ # sys msg to use when schema already provided initially,
38
+ # so agent does not need to use schema tool, at least initially,
39
+ # but may do so later if the db evolves, or if needs to bring in the schema
40
+ # to more recent context.
41
+ SCHEMA_PROVIDED_SYS_MSG = f"""You are a data scientist and expert in Knowledge Graphs,
42
+ with expertise in answering questions by interacting with a Neo4j graph database.
43
+
44
+ The schema below describes the Neo4j database structure, node labels,
45
+ relationship types, and property keys available in your Neo4j database.
46
+
47
+ === SCHEMA ===
48
+ {{schema}}
49
+ === END SCHEMA ===
50
+
51
+ To help with the user's question or database update/creation request,
52
+ you have access to these tools:
53
+
54
+ - {cypher_retrieval_tool_description}
55
+
56
+ - {cypher_creation_tool_description}
57
+
58
+ Since the schema has been provided, you may not need to use the tool below,
59
+ but you may use it if you need to remind yourself about the schema:
60
+
61
+ - {graph_schema_tool_description}
62
+
63
+ """
64
+
65
+ # sys msg to use when schema is not initially provided,
66
+ # and we want agent to use schema tool to get schema
67
+ SCHEMA_TOOLS_SYS_MSG = f"""You are a data scientist and expert in Knowledge Graphs,
68
+ with expertise in answering questions by querying Neo4j database.
69
+ You have access to the following tools:
70
+
71
+ - {graph_schema_tool_description}
72
+
73
+ - {cypher_retrieval_tool_description}
74
+
75
+ - {cypher_creation_tool_description}
76
+
77
+ """
78
+
79
+ DEFAULT_NEO4J_CHAT_SYSTEM_MESSAGE = f"""
80
+ {{mode}}
81
+
82
+ You do not need to be able to answer a question with just one query.
83
+ You could make a sequence of Cypher queries to find the answer to the question.
84
+
85
+ {cypher_query_instructions}
86
+
87
+
88
+
89
+ RETRY-SUGGESTIONS:
90
+ If you receive a null or other unexpected result,
91
+ (a) make sure you use the available TOOLs correctly,
92
+ (b) USE `{graph_schema_tool_name}` tool/function-call to get all the node labels,
93
+ relationship types, and property keys available in your Neo4j database.
94
+ (c) LABELS are CASE-SENSITIVE -- make sure you adhere to the exact label name
95
+ you found in the schema.
96
+ (d) see if you have made an assumption in your Neo4j query, and try another way,
97
+ or use `{cypher_retrieval_tool_name}` to explore the database contents before
98
+ submitting your final query.
99
+ (e) USE `{cypher_creation_tool_name}` tool/function-call to execute cypher query that
100
+ creates entities/relationships in the graph database.
101
+ (f) Try APPROXIMATE or PARTIAL MATCHES to strings in the user's query,
102
+ e.g. user may ask about "Godfather" instead of "The Godfather",
103
+ or try using CASE-INSENSITIVE MATCHES.
104
+
105
+ Start by asking what the user needs help with.
106
+ """
107
+
108
+ ADDRESSING_INSTRUCTION = """
109
+ IMPORTANT - Whenever you are NOT writing a CYPHER query, make sure you address the
110
+ user using {prefix}User. You MUST use the EXACT syntax {prefix} !!!
111
+
112
+ In other words, you ALWAYS EITHER:
113
+ - write a CYPHER query using one of the tools,
114
+ - OR address the user using {prefix}User.
115
+ """
116
+
117
+ DONE_INSTRUCTION = f"""
118
+ When you finally have the answer to a user's query or request,
119
+ use the `{done_tool_name}` with `content` set to the answer or result.
120
+ """
@@ -0,0 +1,32 @@
1
+ from langroid.agent import ToolMessage
2
+
3
+
4
+ class CypherRetrievalTool(ToolMessage):
5
+ request: str = "cypher_retrieval_tool"
6
+ purpose: str = """To send the <cypher_query> to retrieve
7
+ data from the graph database based on provided text description and schema.
8
+ """
9
+ cypher_query: str
10
+
11
+
12
+ cypher_retrieval_tool_name = CypherRetrievalTool.default_value("request")
13
+
14
+
15
+ class CypherCreationTool(ToolMessage):
16
+ request: str = "cypher_creation_tool"
17
+ purpose: str = """
18
+ To send the <cypher_query> to create
19
+ entities/relationships in the graph database.
20
+ """
21
+ cypher_query: str
22
+
23
+
24
+ cypher_creation_tool_name = CypherCreationTool.default_value("request")
25
+
26
+
27
+ class GraphSchemaTool(ToolMessage):
28
+ request: str = "graph_schema_tool"
29
+ purpose: str = """To get the schema of the graph database."""
30
+
31
+
32
+ graph_schema_tool_name = GraphSchemaTool.default_value("request")
@@ -14,7 +14,7 @@ from rich import print
14
14
  from rich.console import Console
15
15
 
16
16
  from langroid.exceptions import LangroidImportError
17
- from langroid.utils.constants import DONE
17
+ from langroid.utils.constants import DONE, SEND_TO
18
18
 
19
19
  try:
20
20
  from sqlalchemy import MetaData, Row, create_engine, inspect, text
@@ -96,7 +96,7 @@ class SQLChatAgentConfig(ChatAgentConfig):
96
96
  context_descriptions: Dict[str, Dict[str, Union[str, Dict[str, str]]]] = {}
97
97
  use_schema_tools: bool = False
98
98
  multi_schema: bool = False
99
- addressing_prefix: str = ""
99
+ addressing_prefix: str = SEND_TO
100
100
 
101
101
  """
102
102
  Optional, but strongly recommended, context descriptions for tables, columns,
@@ -257,6 +257,7 @@ class SQLChatAgent(ChatAgent):
257
257
  self, message: Optional[str | ChatDocument] = None
258
258
  ) -> Optional[ChatDocument]:
259
259
  self.llm_responded = True
260
+ self.used_run_query = False
260
261
  return super().llm_response(message)
261
262
 
262
263
  def user_response(
@@ -270,7 +271,11 @@ class SQLChatAgent(ChatAgent):
270
271
  def handle_message_fallback(
271
272
  self, msg: str | ChatDocument
272
273
  ) -> str | ChatDocument | None:
273
-
274
+ """
275
+ Handle the scenario where current msg is not a tool.
276
+ Special handling is only needed if the message was from the LLM
277
+ (as indicated by self.llm_responded).
278
+ """
274
279
  if not self.llm_responded:
275
280
  return None
276
281
  if self.used_run_query:
langroid/agent/task.py CHANGED
@@ -1226,7 +1226,6 @@ class Task:
1226
1226
  # reset stuck counter since we made progress
1227
1227
  self.n_stalled_steps = 0
1228
1228
 
1229
-
1230
1229
  if self.pending_message is not None:
1231
1230
  if (
1232
1231
  self._is_done_response(result, r)
@@ -1331,6 +1330,9 @@ class Task:
1331
1330
  max_cost=self.max_cost,
1332
1331
  max_tokens=self.max_tokens,
1333
1332
  )
1333
+ # update result.tool_messages if any
1334
+ if isinstance(result, ChatDocument):
1335
+ self.agent.get_tool_messages(result)
1334
1336
  if result is not None:
1335
1337
  content, id2result, oai_tool_id = self.agent.process_tool_results(
1336
1338
  result.content,
@@ -1359,6 +1361,9 @@ class Task:
1359
1361
  else:
1360
1362
  response_fn = self._entity_responder_map[cast(Entity, e)]
1361
1363
  result = response_fn(self.pending_message)
1364
+ # update result.tool_messages if any
1365
+ if isinstance(result, ChatDocument):
1366
+ self.agent.get_tool_messages(result)
1362
1367
 
1363
1368
  result_chat_doc = self.agent.to_ChatDocument(
1364
1369
  result,
@@ -1389,7 +1394,7 @@ class Task:
1389
1394
  # ignore all string-based signaling/routing
1390
1395
  return result
1391
1396
  # parse various routing/addressing strings in result
1392
- is_pass, recipient, content = parse_routing(
1397
+ is_pass, recipient, content = self._parse_routing(
1393
1398
  result,
1394
1399
  addressing_prefix=self.config.addressing_prefix,
1395
1400
  )
@@ -1522,7 +1527,7 @@ class Task:
1522
1527
  oai_tool_id2result = result_msg.oai_tool_id2result if result_msg else None
1523
1528
  fun_call = result_msg.function_call if result_msg else None
1524
1529
  tool_messages = result_msg.tool_messages if result_msg else []
1525
- # if there is an LLMDoneTool or AgentDoneTool among these,
1530
+ # if there is an DoneTool or AgentDoneTool among these,
1526
1531
  # we extract content and tools from here, and ignore all others
1527
1532
  for t in tool_messages:
1528
1533
  if isinstance(t, FinalResultTool):
@@ -1534,6 +1539,8 @@ class Task:
1534
1539
  # there shouldn't be multiple tools like this; just take the first
1535
1540
  content = to_string(t.content)
1536
1541
  content_any = t.content
1542
+ fun_call = None
1543
+ oai_tool_calls = None
1537
1544
  if isinstance(t, AgentDoneTool):
1538
1545
  # AgentDoneTool may have tools, unlike DoneTool
1539
1546
  tool_messages = t.tools
@@ -1906,6 +1913,7 @@ class Task:
1906
1913
  # user, then wait for user response
1907
1914
  self.pending_message is not None
1908
1915
  and self.pending_message.metadata.recipient == Entity.USER
1916
+ and not self.agent.has_tool_message_attempt(self.pending_message)
1909
1917
  )
1910
1918
 
1911
1919
  def _can_respond(self, e: Responder) -> bool:
@@ -1940,58 +1948,72 @@ class Task:
1940
1948
  """
1941
1949
  self.color_log = enable
1942
1950
 
1951
+ def _parse_routing(
1952
+ self,
1953
+ msg: ChatDocument | str,
1954
+ addressing_prefix: str = "",
1955
+ ) -> Tuple[bool | None, str | None, str | None]:
1956
+ """
1957
+ Parse routing instruction if any, of the form:
1958
+ PASS:<recipient> (pass current pending msg to recipient)
1959
+ SEND:<recipient> <content> (send content to recipient)
1960
+ @<recipient> <content> (send content to recipient)
1961
+ Args:
1962
+ msg (ChatDocument|str|None): message to parse
1963
+ addressing_prefix (str): prefix to address other agents or entities,
1964
+ (e.g. "@". See documentation of `TaskConfig` for details).
1965
+ Returns:
1966
+ Tuple[bool|None, str|None, str|None]:
1967
+ bool: true=PASS, false=SEND, or None if neither
1968
+ str: recipient, or None
1969
+ str: content to send, or None
1970
+ """
1971
+ # handle routing instruction-strings in result if any,
1972
+ # such as PASS, PASS_TO, or SEND
1943
1973
 
1944
- def parse_routing(
1945
- msg: ChatDocument | str,
1946
- addressing_prefix: str = "",
1947
- ) -> Tuple[bool | None, str | None, str | None]:
1948
- """
1949
- Parse routing instruction if any, of the form:
1950
- PASS:<recipient> (pass current pending msg to recipient)
1951
- SEND:<recipient> <content> (send content to recipient)
1952
- @<recipient> <content> (send content to recipient)
1953
- Args:
1954
- msg (ChatDocument|str|None): message to parse
1955
- addressing_prefix (str): prefix to address other agents or entities,
1956
- (e.g. "@". See documentation of `TaskConfig` for details).
1957
- Returns:
1958
- Tuple[bool|None, str|None, str|None]:
1959
- bool: true=PASS, false=SEND, or None if neither
1960
- str: recipient, or None
1961
- str: content to send, or None
1962
- """
1963
- # handle routing instruction in result if any,
1964
- # of the form PASS=<recipient>
1965
- content = msg.content if isinstance(msg, ChatDocument) else msg
1966
- content = content.strip()
1967
- if PASS in content and PASS_TO not in content:
1968
- return True, None, None
1969
- if PASS_TO in content and content.split(":")[1] != "":
1970
- return True, content.split(":")[1], None
1971
- if (
1972
- SEND_TO in content
1973
- and (addressee_content := parse_addressed_message(content, SEND_TO))[0]
1974
- is not None
1975
- ):
1976
- (addressee, content_to_send) = addressee_content
1977
- # if no content then treat same as PASS_TO
1978
- if content_to_send == "":
1979
- return True, addressee, None
1980
- else:
1981
- return False, addressee, content_to_send
1982
- if (
1983
- addressing_prefix != ""
1984
- and addressing_prefix in content
1985
- and (addressee_content := parse_addressed_message(content, addressing_prefix))[
1986
- 0
1987
- ]
1988
- is not None
1989
- ):
1990
- (addressee, content_to_send) = addressee_content
1991
- # if no content then treat same as PASS_TO
1992
- if content_to_send == "":
1993
- return True, addressee, None
1994
- else:
1995
- return False, addressee, content_to_send
1974
+ msg_str = msg.content if isinstance(msg, ChatDocument) else msg
1975
+ if (
1976
+ self.agent.has_tool_message_attempt(msg)
1977
+ and not msg_str.startswith(PASS)
1978
+ and not msg_str.startswith(PASS_TO)
1979
+ and not msg_str.startswith(SEND_TO)
1980
+ ):
1981
+ # if there's an attempted tool-call, we ignore any routing strings,
1982
+ # unless they are at the start of the msg
1983
+ return None, None, None
1984
+
1985
+ content = msg.content if isinstance(msg, ChatDocument) else msg
1986
+ content = content.strip()
1987
+ if PASS in content and PASS_TO not in content:
1988
+ return True, None, None
1989
+ if PASS_TO in content and content.split(":")[1] != "":
1990
+ return True, content.split(":")[1], None
1991
+ if (
1992
+ SEND_TO in content
1993
+ and (addressee_content := parse_addressed_message(content, SEND_TO))[0]
1994
+ is not None
1995
+ ):
1996
+ # Note this will discard any portion of content BEFORE SEND_TO.
1997
+ # TODO maybe make this configurable.
1998
+ (addressee, content_to_send) = addressee_content
1999
+ # if no content then treat same as PASS_TO
2000
+ if content_to_send == "":
2001
+ return True, addressee, None
2002
+ else:
2003
+ return False, addressee, content_to_send
2004
+ if (
2005
+ addressing_prefix != ""
2006
+ and addressing_prefix in content
2007
+ and (
2008
+ addressee_content := parse_addressed_message(content, addressing_prefix)
2009
+ )[0]
2010
+ is not None
2011
+ ):
2012
+ (addressee, content_to_send) = addressee_content
2013
+ # if no content then treat same as PASS_TO
2014
+ if content_to_send == "":
2015
+ return True, addressee, None
2016
+ else:
2017
+ return False, addressee, content_to_send
1996
2018
 
1997
- return None, None, None
2019
+ return None, None, None
@@ -41,11 +41,11 @@ class DoneTool(ToolMessage):
41
41
  """Tool for Agent Entity (i.e. agent_response) or LLM entity (i.e. llm_response) to
42
42
  signal the current task is done, with some content as the result."""
43
43
 
44
- purpose = """
44
+ purpose: str = """
45
45
  To signal the current task is done, along with an optional message <content>
46
46
  of arbitrary type (default None).
47
47
  """
48
- request = "done_tool"
48
+ request: str = "done_tool"
49
49
  content: str = ""
50
50
 
51
51
  def response(self, agent: ChatAgent) -> ChatDocument:
@@ -77,7 +77,7 @@ class ResultTool(ToolMessage):
77
77
  Note:
78
78
  - when defining a tool handler or agent_response, you can directly return
79
79
  ResultTool(field1 = val1, ...),
80
- where the values can be aribitrary data structures, including nested
80
+ where the values can be arbitrary data structures, including nested
81
81
  Pydantic objs, or you can define a subclass of ResultTool with the
82
82
  fields you want to return.
83
83
  - This is a special ToolMessage that is NOT meant to be used or handled
@@ -143,10 +143,10 @@ class PassTool(ToolMessage):
143
143
  Similar to ForwardTool, but without specifying the recipient agent.
144
144
  """
145
145
 
146
- purpose = """
146
+ purpose: str = """
147
147
  To pass the current message so that other agents can handle it.
148
148
  """
149
- request = "pass_tool"
149
+ request: str = "pass_tool"
150
150
 
151
151
  def response(self, agent: ChatAgent, chat_doc: ChatDocument) -> ChatDocument:
152
152
  """When this tool is enabled for an Agent, this will result in a method
@@ -178,10 +178,10 @@ class DonePassTool(PassTool):
178
178
  Similar to PassTool, except we append a DoneTool to the result tool_messages.
179
179
  """
180
180
 
181
- purpose = """
181
+ purpose: str = """
182
182
  To signal the current task is done, with results set to the current/incoming msg.
183
183
  """
184
- request = "done_pass_tool"
184
+ request: str = "done_pass_tool"
185
185
 
186
186
  def response(self, agent: ChatAgent, chat_doc: ChatDocument) -> ChatDocument:
187
187
  # use PassTool to get the right ChatDocument to pass...
@@ -66,6 +66,12 @@ class Parser:
66
66
  tokens = self.tokenizer.encode(text)
67
67
  return len(tokens)
68
68
 
69
+ def truncate_tokens(self, text: str, max_tokens: int) -> str:
70
+ tokens = self.tokenizer.encode(text)
71
+ if len(tokens) <= max_tokens:
72
+ return text
73
+ return self.tokenizer.decode(tokens[:max_tokens])
74
+
69
75
  def add_window_ids(self, chunks: List[Document]) -> None:
70
76
  """Chunks may belong to multiple docs, but for each doc,
71
77
  they appear consecutively. Add window_ids in metadata"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langroid
3
- Version: 0.19.5
3
+ Version: 0.20.1
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Provides-Extra: all
15
+ Provides-Extra: arango
15
16
  Provides-Extra: chainlit
16
17
  Provides-Extra: chromadb
17
18
  Provides-Extra: db
@@ -35,7 +36,9 @@ Provides-Extra: sql
35
36
  Provides-Extra: transformers
36
37
  Provides-Extra: unstructured
37
38
  Provides-Extra: vecdbs
39
+ Requires-Dist: adb-cloud-connector (>=1.0.2,<2.0.0)
38
40
  Requires-Dist: aiohttp (>=3.9.1,<4.0.0)
41
+ Requires-Dist: arango-datasets (>=1.2.2,<2.0.0) ; extra == "all" or extra == "arango"
39
42
  Requires-Dist: async-generator (>=1.10,<2.0)
40
43
  Requires-Dist: bs4 (>=0.0.1,<0.0.2)
41
44
  Requires-Dist: cerebras-cloud-sdk (>=1.1.0,<2.0.0)
@@ -82,6 +85,7 @@ Requires-Dist: pymysql (>=1.1.0,<2.0.0) ; extra == "db" or extra == "all" or ext
82
85
  Requires-Dist: pyparsing (>=3.0.9,<4.0.0)
83
86
  Requires-Dist: pypdf (>=3.12.2,<4.0.0) ; extra == "doc-chat" or extra == "all" or extra == "pdf-parsers"
84
87
  Requires-Dist: pytesseract (>=0.3.10,<0.4.0) ; extra == "doc-chat" or extra == "all" or extra == "pdf-parsers"
88
+ Requires-Dist: python-arango (>=8.1.2,<9.0.0) ; extra == "all" or extra == "arango"
85
89
  Requires-Dist: python-docx (>=1.1.0,<2.0.0) ; extra == "doc-chat" or extra == "all" or extra == "docx"
86
90
  Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
87
91
  Requires-Dist: python-magic (>=0.4.27,<0.5.0)
@@ -1,6 +1,6 @@
1
1
  langroid/__init__.py,sha256=z_fCOLQJPOw3LLRPBlFB5-2HyCjpPgQa4m4iY5Fvb8Y,1800
2
2
  langroid/agent/__init__.py,sha256=ll0Cubd2DZ-fsCMl7e10hf9ZjFGKzphfBco396IKITY,786
3
- langroid/agent/base.py,sha256=swttuRRJKdDt-GUFsBNKHn1MQRj29b2f2U7Tuw5V5pk,64793
3
+ langroid/agent/base.py,sha256=sOZapdzHaB4kbCLu8vI_zZx78jIhv9fmWn0EWV4yTAE,65371
4
4
  langroid/agent/batch.py,sha256=QZdlt1563hx4l3AXrCaGovE-PNG93M3DsvQAbDzdiS8,13705
5
5
  langroid/agent/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  langroid/agent/callbacks/chainlit.py,sha256=JJXI3UGTyTDg2FFath4rqY1GyUo_0pbVBt8CZpvdtn4,23289
@@ -10,6 +10,11 @@ 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
12
12
  langroid/agent/special/__init__.py,sha256=gik_Xtm_zV7U9s30Mn8UX3Gyuy4jTjQe9zjiE3HWmEo,1273
13
+ langroid/agent/special/arangodb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ langroid/agent/special/arangodb/arangodb_agent.py,sha256=y9zp2ZQcKkNsUegvDZryn79exth3T-hsmkR-z4gSU-w,25522
15
+ langroid/agent/special/arangodb/system_messages.py,sha256=Uni6uDOSZpD9miCNzx7CEQjnyxDF8Egbe-hFvkraSt4,6739
16
+ langroid/agent/special/arangodb/tools.py,sha256=WasFERC1cToLOWi1cWqUs-TujU0A68gZWbhbP128obo,3499
17
+ langroid/agent/special/arangodb/utils.py,sha256=LIevtkayIdVVXyj3jlbKH2WgdZTtH5-JLgbXOHC7uxs,1420
13
18
  langroid/agent/special/doc_chat_agent.py,sha256=xIqBOyLax_jMU0UevxqXf_aQUrRkW6MQUKpKnKvaqkQ,59281
14
19
  langroid/agent/special/lance_doc_chat_agent.py,sha256=s8xoRs0gGaFtDYFUSIRchsgDVbS5Q3C2b2mr3V1Fd-Q,10419
15
20
  langroid/agent/special/lance_rag/__init__.py,sha256=QTbs0IVE2ZgDg8JJy1zN97rUUg4uEPH7SLGctFNumk4,174
@@ -19,13 +24,13 @@ langroid/agent/special/lance_rag/query_planner_agent.py,sha256=5YPeliCjlRk1LEDe5
19
24
  langroid/agent/special/lance_tools.py,sha256=qS8x4wi8mrqfbYV2ztFzrcxyhHQ0ZWOc-zkYiH7awj0,2105
20
25
  langroid/agent/special/neo4j/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
26
  langroid/agent/special/neo4j/csv_kg_chat.py,sha256=dRsAgMBa1H_EMI2YYgJR2Xyv1D7e4o3G9M64mTewq_c,6409
22
- langroid/agent/special/neo4j/neo4j_chat_agent.py,sha256=2r9kZ1AH3AxvJ6BZn0BZLhz-Bw8b7xUBlRv86gSEE8s,13542
23
- langroid/agent/special/neo4j/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- langroid/agent/special/neo4j/utils/system_message.py,sha256=_2NKX2Sx_7nLGNk_0rUyDkgTHZJuKm_DgtG7M_BFPkY,2920
27
+ langroid/agent/special/neo4j/neo4j_chat_agent.py,sha256=1RMKupJra0KZ-hA7AiiR662STJyYDZi8ZnAnnXF8oCA,16726
28
+ langroid/agent/special/neo4j/system_messages.py,sha256=m2jsVayey6E_88F5B_gW2WbWKBJvIeDUoVCRBbNs97o,4522
29
+ langroid/agent/special/neo4j/tools.py,sha256=Vw3HvtDfG2c4_bUHgt4_ZbJq48lpIQstbjjwhh1BjrQ,905
25
30
  langroid/agent/special/relevance_extractor_agent.py,sha256=zIx8GUdVo1aGW6ASla0NPQjYYIpmriK_TYMijqAx3F8,4796
26
31
  langroid/agent/special/retriever_agent.py,sha256=lvMvf-u9rSosg4YASuFdUbGLgkzLPknXAbJZfZ1LZCc,1868
27
32
  langroid/agent/special/sql/__init__.py,sha256=mWfmm1QpXCezpFOS2eI57M0L_Ok3q5_ukG8tXBnBrEA,319
28
- langroid/agent/special/sql/sql_chat_agent.py,sha256=PArNz9up0atw0cJet1LOfWlpW6xgofVBDR7Z3xvpzHk,16592
33
+ langroid/agent/special/sql/sql_chat_agent.py,sha256=LVTuOlaY6m5DpsMFLFv00eOz04y6vKeO4mfGLIUp6AY,16844
29
34
  langroid/agent/special/sql/utils/__init__.py,sha256=JFif6CRTrN-bc91uuAI4K9fe2ndIWSNMVxJ0WA68--M,446
30
35
  langroid/agent/special/sql/utils/description_extractors.py,sha256=cX8TIpmTPXZXQTMpIi3OUFwFsPywxFFdurpx717Kq0I,6529
31
36
  langroid/agent/special/sql/utils/populate_metadata.py,sha256=1J22UsyEPKzwK0XlJZtYn9r6kYc0FXIr8-lZrndYlhc,3131
@@ -33,14 +38,14 @@ langroid/agent/special/sql/utils/system_message.py,sha256=qKLHkvQWRQodTtPLPxr1GS
33
38
  langroid/agent/special/sql/utils/tools.py,sha256=vFYysk6Vi7HJjII8B4RitA3pt_z3gkSglDNdhNVMiFc,1332
34
39
  langroid/agent/special/table_chat_agent.py,sha256=d9v2wsblaRx7oMnKhLV7uO_ujvk9gh59pSGvBXyeyNc,9659
35
40
  langroid/agent/structured_message.py,sha256=y7pud1EgRNeTFZlJmBkLmwME3yQJ_IYik-Xds9kdZbY,282
36
- langroid/agent/task.py,sha256=DUitErf1VIhaPNirP3fdOYU2MZEGjO1FPfEniIzFoks,85356
41
+ langroid/agent/task.py,sha256=f7clh6p6Md0G4YGHqbFeeT88U4XoP0i3eatekV21hHE,86643
37
42
  langroid/agent/tool_message.py,sha256=jkN7uq7YwUC_wBcSCNUYjrB_His2YCfQay_lqIa4Tww,10498
38
43
  langroid/agent/tools/__init__.py,sha256=IMgCte-_ZIvCkozGQmvMqxIw7_nKLKzD78ccJL1bnQU,804
39
44
  langroid/agent/tools/duckduckgo_search_tool.py,sha256=NhsCaGZkdv28nja7yveAhSK_w6l_Ftym8agbrdzqgfo,1935
40
45
  langroid/agent/tools/file_tools.py,sha256=GjPB5YDILucYapElnvvoYpGJuZQ25ecLs2REv7edPEo,7292
41
46
  langroid/agent/tools/google_search_tool.py,sha256=y7b-3FtgXf0lfF4AYxrZ3K5pH2dhidvibUOAGBE--WI,1456
42
47
  langroid/agent/tools/metaphor_search_tool.py,sha256=qj4gt453cLEX3EGW7nVzVu6X7LCdrwjSlcNY0qJW104,2489
43
- langroid/agent/tools/orchestration.py,sha256=vp2Qx-DYPtDnACosxKqwHGy6DeD1QnEllWz0Ht81Cyc,10880
48
+ langroid/agent/tools/orchestration.py,sha256=EDv1EMVGYqX82x3bCRbTn9gFNs66oosiUM8WTSZkUJg,10909
44
49
  langroid/agent/tools/recipient_tool.py,sha256=dr0yTxgNEIoxUYxH6TtaExC4G_8WdJ0xGohIa4dFLhY,9808
45
50
  langroid/agent/tools/retrieval_tool.py,sha256=2q2pfoYbZNfbWQ0McxrtmfF0ekGglIgRl-6uF26pa-E,871
46
51
  langroid/agent/tools/rewind_tool.py,sha256=XAXL3BpNhCmBGYq_qi_sZfHJuIw7NY2jp4wnojJ7WRs,5606
@@ -86,7 +91,7 @@ langroid/parsing/document_parser.py,sha256=ZGxgG4ytnCIah4HWk3ZrK3EGAMXDjAzI9KaPE
86
91
  langroid/parsing/image_text.py,sha256=sbLIQ5nHe2UnYUksBaQsmZGaX-X0qgEpPd7CEzi_z5M,910
87
92
  langroid/parsing/para_sentence_split.py,sha256=AJBzZojP3zpB-_IMiiHismhqcvkrVBQ3ZINoQyx_bE4,2000
88
93
  langroid/parsing/parse_json.py,sha256=aADo38bAHQhC8on4aWZZzVzSDy-dK35vRLZsFI2ewh8,4756
89
- langroid/parsing/parser.py,sha256=AgtmlVUvrkSG1l7-YZPX8rlldgXjh_HqXAMqpXkBxUo,11746
94
+ langroid/parsing/parser.py,sha256=bTG5TO2CEwGdLf9979j9_dFntKX5FloGF8vhts6ObU0,11978
90
95
  langroid/parsing/repo_loader.py,sha256=3GjvPJS6Vf5L6gV2zOU8s-Tf1oq_fZm-IB_RL_7CTsY,29373
91
96
  langroid/parsing/routing.py,sha256=-FcnlqldzL4ZoxuDwXjQPNHgBe9F9-F4R6q7b_z9CvI,1232
92
97
  langroid/parsing/search.py,sha256=0i_r0ESb5HEQfagA2g7_uMQyxYPADWVbdcN9ixZhS4E,8992
@@ -137,8 +142,8 @@ langroid/vector_store/meilisearch.py,sha256=6frB7GFWeWmeKzRfLZIvzRjllniZ1cYj3Hmh
137
142
  langroid/vector_store/momento.py,sha256=qR-zBF1RKVHQZPZQYW_7g-XpTwr46p8HJuYPCkfJbM4,10534
138
143
  langroid/vector_store/qdrant_cloud.py,sha256=3im4Mip0QXLkR6wiqVsjV1QvhSElfxdFSuDKddBDQ-4,188
139
144
  langroid/vector_store/qdrantdb.py,sha256=v88lqFkepADvlN6lByUj9I4NEKa9X9lWH16uTPPbYrE,17457
140
- pyproject.toml,sha256=tKD9OebCwUNxXivb-EoM3ZvOjGBmFx4m-Bl9bztRkyg,7251
141
- langroid-0.19.5.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
142
- langroid-0.19.5.dist-info/METADATA,sha256=jStMm7ROZxiIDxUHVKXHhc7UNXJ6LkK5QRpr7pTiUAU,56513
143
- langroid-0.19.5.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
144
- langroid-0.19.5.dist-info/RECORD,,
145
+ pyproject.toml,sha256=m6gT-kRBlRmBQ50VGLcLDXOmo3MmaYPAHxbySfpGd1E,7488
146
+ langroid-0.20.1.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
147
+ langroid-0.20.1.dist-info/METADATA,sha256=8qg7AF3qK12XRvtEqpR2P8eyidON7E4womWSiY3QW_E,56758
148
+ langroid-0.20.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
149
+ langroid-0.20.1.dist-info/RECORD,,
pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langroid"
3
- version = "0.19.5"
3
+ version = "0.20.1"
4
4
  description = "Harness LLMs with Multi-Agent Programming"
5
5
  authors = ["Prasad Chalasani <pchalasani@gmail.com>"]
6
6
  readme = "README.md"
@@ -90,6 +90,9 @@ python-magic = "^0.4.27"
90
90
  json-repair = "^0.29.9"
91
91
  cerebras-cloud-sdk = "^1.1.0"
92
92
  gitpython = "^3.1.43"
93
+ python-arango = {version="^8.1.2", optional=true}
94
+ arango-datasets = {version="^1.2.2", optional=true}
95
+ adb-cloud-connector = "^1.0.2"
93
96
 
94
97
 
95
98
  [tool.poetry.extras]
@@ -113,6 +116,7 @@ all = [
113
116
  # "lancedb", "tantivy", "pyarrow",
114
117
  "chromadb",
115
118
  "metaphor-python", "neo4j",
119
+ "python-arango", "arango-datasets",
116
120
  "litellm",
117
121
  "chainlit", "python-socketio",
118
122
  "fastembed"
@@ -130,6 +134,7 @@ mysql = ["pymysql"]
130
134
  sql = ["sqlalchemy", "pymysql", "psycopg2"]
131
135
  litellm = ["litellm"]
132
136
  neo4j = ["neo4j"]
137
+ arango = ["python-arango", "arango-datasets"]
133
138
  metaphor = ["metaphor-python"]
134
139
  chainlit = ["chainlit", "python-socketio"]
135
140
  chromadb = ["chromadb"]
@@ -166,6 +171,7 @@ coverage = "^7.2.5"
166
171
  pytest-xdist = "^3.6.1"
167
172
  pytest-timeout = "^2.3.1"
168
173
  pytest-cov = "^5.0.0"
174
+ docker = "^7.1.0"
169
175
 
170
176
  [tool.poetry.group.docs]
171
177
  optional = true