langroid 0.21.0__py3-none-any.whl → 0.22.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.
- langroid/agent/base.py +37 -1
- langroid/agent/chat_agent.py +31 -0
- langroid/agent/special/arangodb/arangodb_agent.py +1 -26
- langroid/agent/special/arangodb/tools.py +5 -0
- langroid/agent/tool_message.py +13 -1
- {langroid-0.21.0.dist-info → langroid-0.22.0.dist-info}/METADATA +7 -4
- {langroid-0.21.0.dist-info → langroid-0.22.0.dist-info}/RECORD +10 -10
- pyproject.toml +1 -1
- {langroid-0.21.0.dist-info → langroid-0.22.0.dist-info}/LICENSE +0 -0
- {langroid-0.21.0.dist-info → langroid-0.22.0.dist-info}/WHEEL +0 -0
langroid/agent/base.py
CHANGED
@@ -1450,6 +1450,40 @@ class Agent(ABC):
|
|
1450
1450
|
|
1451
1451
|
return None
|
1452
1452
|
|
1453
|
+
def _maybe_truncate_result(
|
1454
|
+
self, result: str | ChatDocument | None, max_tokens: int | None
|
1455
|
+
) -> str | ChatDocument | None:
|
1456
|
+
"""
|
1457
|
+
Truncate the result string to `max_tokens` tokens.
|
1458
|
+
"""
|
1459
|
+
if result is None or max_tokens is None:
|
1460
|
+
return result
|
1461
|
+
result_str = result.content if isinstance(result, ChatDocument) else result
|
1462
|
+
num_tokens = (
|
1463
|
+
self.parser.num_tokens(result_str)
|
1464
|
+
if self.parser is not None
|
1465
|
+
else len(result_str) / 4.0
|
1466
|
+
)
|
1467
|
+
if num_tokens <= max_tokens:
|
1468
|
+
return result
|
1469
|
+
truncate_warning = f"""
|
1470
|
+
The TOOL result was large, so it was truncated to {max_tokens} tokens.
|
1471
|
+
To get the full result, the TOOL must be called again.
|
1472
|
+
"""
|
1473
|
+
if isinstance(result, str):
|
1474
|
+
return (
|
1475
|
+
self.parser.truncate_tokens(result, max_tokens)
|
1476
|
+
if self.parser is not None
|
1477
|
+
else result[: max_tokens * 4] # approx truncate
|
1478
|
+
) + truncate_warning
|
1479
|
+
elif isinstance(result, ChatDocument):
|
1480
|
+
result.content = (
|
1481
|
+
self.parser.truncate_tokens(result.content, max_tokens)
|
1482
|
+
if self.parser is not None
|
1483
|
+
else result.content[: max_tokens * 4] # approx truncate
|
1484
|
+
) + truncate_warning
|
1485
|
+
return result
|
1486
|
+
|
1453
1487
|
def handle_tool_message(
|
1454
1488
|
self,
|
1455
1489
|
tool: ToolMessage,
|
@@ -1485,7 +1519,9 @@ class Agent(ABC):
|
|
1485
1519
|
# not a pydantic validation error,
|
1486
1520
|
# which we check in `handle_message`
|
1487
1521
|
raise e
|
1488
|
-
return
|
1522
|
+
return self._maybe_truncate_result(
|
1523
|
+
result, tool._max_result_tokens
|
1524
|
+
) # type: ignore
|
1489
1525
|
|
1490
1526
|
def num_tokens(self, prompt: str | List[LLMMessage]) -> int:
|
1491
1527
|
if self.parser is None:
|
langroid/agent/chat_agent.py
CHANGED
@@ -623,6 +623,33 @@ class ChatAgent(Agent):
|
|
623
623
|
self.llm_tools_usable.discard(r)
|
624
624
|
self.llm_functions_usable.discard(r)
|
625
625
|
|
626
|
+
def _reduce_raw_tool_results(self, message: ChatDocument) -> None:
|
627
|
+
"""
|
628
|
+
If message is the result of a ToolMessage that had the
|
629
|
+
flag `_retain_raw_results = False`, then we replace contents
|
630
|
+
with a placeholder message.
|
631
|
+
"""
|
632
|
+
parent_message: ChatDocument | None = message.parent
|
633
|
+
tools = [] if parent_message is None else parent_message.tool_messages
|
634
|
+
truncate_tools = [t for t in tools if t._max_retained_tokens is not None]
|
635
|
+
limiting_tool = truncate_tools[0] if len(truncate_tools) > 0 else None
|
636
|
+
if limiting_tool is not None and limiting_tool._max_retained_tokens is not None:
|
637
|
+
tool_name = limiting_tool.default_value("request")
|
638
|
+
max_tokens: int = limiting_tool._max_retained_tokens
|
639
|
+
truncation_warning = f"""
|
640
|
+
The result of the {tool_name} tool were too large,
|
641
|
+
and has been truncated to {max_tokens} tokens.
|
642
|
+
To obtain the full result, the tool needs to be re-used.
|
643
|
+
"""
|
644
|
+
llm_msg = self.message_history[message.metadata.msg_idx]
|
645
|
+
orig_content = llm_msg.content
|
646
|
+
new_content = (
|
647
|
+
self.parser.truncate_tokens(orig_content, max_tokens)
|
648
|
+
if self.parser is not None
|
649
|
+
else orig_content[: max_tokens * 4] # approx truncation
|
650
|
+
)
|
651
|
+
llm_msg.content = new_content + "\n\n" + truncation_warning
|
652
|
+
|
626
653
|
def llm_response(
|
627
654
|
self, message: Optional[str | ChatDocument] = None
|
628
655
|
) -> Optional[ChatDocument]:
|
@@ -650,6 +677,8 @@ class ChatAgent(Agent):
|
|
650
677
|
self.message_history.extend(ChatDocument.to_LLMMessage(response))
|
651
678
|
response.metadata.msg_idx = len(self.message_history) - 1
|
652
679
|
response.metadata.agent_id = self.id
|
680
|
+
if isinstance(message, ChatDocument):
|
681
|
+
self._reduce_raw_tool_results(message)
|
653
682
|
# Preserve trail of tool_ids for OpenAI Assistant fn-calls
|
654
683
|
response.metadata.tool_ids = (
|
655
684
|
[]
|
@@ -681,6 +710,8 @@ class ChatAgent(Agent):
|
|
681
710
|
self.message_history.extend(ChatDocument.to_LLMMessage(response))
|
682
711
|
response.metadata.msg_idx = len(self.message_history) - 1
|
683
712
|
response.metadata.agent_id = self.id
|
713
|
+
if isinstance(message, ChatDocument):
|
714
|
+
self._reduce_raw_tool_results(message)
|
684
715
|
# Preserve trail of tool_ids for OpenAI Assistant fn-calls
|
685
716
|
response.metadata.tool_ids = (
|
686
717
|
[]
|
@@ -94,7 +94,6 @@ class ArangoChatAgentConfig(ChatAgentConfig):
|
|
94
94
|
prepopulate_schema: bool = True
|
95
95
|
use_functions_api: bool = True
|
96
96
|
max_num_results: int = 10 # how many results to return from AQL query
|
97
|
-
max_result_tokens: int = 1000 # truncate long results to this many tokens
|
98
97
|
max_schema_fields: int = 500 # max fields to show in schema
|
99
98
|
max_tries: int = 10 # how many attempts to answer user question
|
100
99
|
use_tools: bool = False
|
@@ -343,28 +342,6 @@ class ArangoChatAgent(ChatAgent):
|
|
343
342
|
success=False, data=f"Failed after max retries: {str(e)}"
|
344
343
|
)
|
345
344
|
|
346
|
-
def _limit_tokens(self, text: str) -> str:
|
347
|
-
result = text
|
348
|
-
n_toks = self.num_tokens(result)
|
349
|
-
if n_toks > self.config.max_result_tokens:
|
350
|
-
logger.warning(
|
351
|
-
f"""
|
352
|
-
Your query resulted in a large result of
|
353
|
-
{n_toks} tokens,
|
354
|
-
which will be truncated to {self.config.max_result_tokens} tokens.
|
355
|
-
If this does not give satisfactory results,
|
356
|
-
please retry with a more focused query.
|
357
|
-
"""
|
358
|
-
)
|
359
|
-
if self.parser is not None:
|
360
|
-
result = self.parser.truncate_tokens(
|
361
|
-
result,
|
362
|
-
self.config.max_result_tokens,
|
363
|
-
)
|
364
|
-
else:
|
365
|
-
result = result[: self.config.max_result_tokens * 4] # truncate roughly
|
366
|
-
return result
|
367
|
-
|
368
345
|
def aql_retrieval_tool(self, msg: AQLRetrievalTool) -> str:
|
369
346
|
"""Handle AQL query for data retrieval"""
|
370
347
|
if not self.tried_schema:
|
@@ -395,9 +372,7 @@ class ArangoChatAgent(ChatAgent):
|
|
395
372
|
Try modifying your query based on the RETRY-SUGGESTIONS
|
396
373
|
in your instructions.
|
397
374
|
"""
|
398
|
-
|
399
|
-
result = str(response.data)
|
400
|
-
return self._limit_tokens(result)
|
375
|
+
return str(response.data)
|
401
376
|
|
402
377
|
def aql_creation_tool(self, msg: AQLCreationTool) -> str:
|
403
378
|
"""Handle AQL query for creating data"""
|
@@ -13,6 +13,9 @@ class AQLRetrievalTool(ToolMessage):
|
|
13
13
|
"""
|
14
14
|
aql_query: str
|
15
15
|
|
16
|
+
_max_result_tokens = 500
|
17
|
+
_max_retained_tokens = 200
|
18
|
+
|
16
19
|
@classmethod
|
17
20
|
def examples(cls) -> List[ToolMessage | Tuple[str, ToolMessage]]:
|
18
21
|
"""Few-shot examples to include in tool instructions."""
|
@@ -98,5 +101,7 @@ class ArangoSchemaTool(ToolMessage):
|
|
98
101
|
properties: bool = True
|
99
102
|
collections: List[str] | None = None
|
100
103
|
|
104
|
+
_max_result_tokens = 500
|
105
|
+
|
101
106
|
|
102
107
|
arango_schema_tool_name = ArangoSchemaTool.default_value("request")
|
langroid/agent/tool_message.py
CHANGED
@@ -44,7 +44,19 @@ class ToolMessage(ABC, BaseModel):
|
|
44
44
|
|
45
45
|
_allow_llm_use: bool = True # allow an LLM to use (i.e. generate) this tool?
|
46
46
|
|
47
|
-
#
|
47
|
+
# Optional param to limit number of result tokens to retain in msg history.
|
48
|
+
# Some tools can have large results that we may not want to fully retain,
|
49
|
+
# e.g. result of a db query, which the LLM later reduces to a summary, so
|
50
|
+
# in subsequent dialog we may only want to retain the summary,
|
51
|
+
# and replace this raw result truncated to _max_result_tokens.
|
52
|
+
# Important to note: unlike _max_result_tokens, this param is used
|
53
|
+
# NOT used to immediately truncate the result;
|
54
|
+
# it is only used to truncate what is retained in msg history AFTER the
|
55
|
+
# response to this result.
|
56
|
+
_max_retained_tokens: int | None = None
|
57
|
+
|
58
|
+
# Optional param to limit number of tokens in the result of the tool.
|
59
|
+
_max_result_tokens: int | None = None
|
48
60
|
|
49
61
|
class Config:
|
50
62
|
extra = Extra.allow
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: langroid
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.22.0
|
4
4
|
Summary: Harness LLMs with Multi-Agent Programming
|
5
5
|
License: MIT
|
6
6
|
Author: Prasad Chalasani
|
@@ -207,7 +207,7 @@ import langroid.language_models as lm
|
|
207
207
|
# set up LLM
|
208
208
|
llm_cfg = lm.OpenAIGPTConfig( # or OpenAIAssistant to use Assistant API
|
209
209
|
# any model served via an OpenAI-compatible API
|
210
|
-
chat_model=lm.OpenAIChatModel.
|
210
|
+
chat_model=lm.OpenAIChatModel.GPT4o, # or, e.g., "ollama/mistral"
|
211
211
|
)
|
212
212
|
# use LLM directly
|
213
213
|
mdl = lm.OpenAIGPT(llm_cfg)
|
@@ -249,6 +249,9 @@ teacher_task.run()
|
|
249
249
|
<summary> <b>Click to expand</b></summary>
|
250
250
|
|
251
251
|
- **Nov 2024:**
|
252
|
+
- **[0.22.0](https://langroid.github.io/langroid/notes/large-tool-results/)**:
|
253
|
+
Optional parameters to truncate large tool results.
|
254
|
+
- **[0.21.0](https://langroid.github.io/langroid/notes/gemini/)** Direct support for Gemini models via OpenAI client instead of using LiteLLM.
|
252
255
|
- **[0.20.0](https://github.com/langroid/langroid/releases/tag/0.20.0)** Support for
|
253
256
|
ArangoDB Knowledge Graphs.
|
254
257
|
- **Oct 2024:**
|
@@ -364,7 +367,7 @@ teacher_task.run()
|
|
364
367
|
decides a filter and rephrase query to send to a RAG agent.
|
365
368
|
- **[0.1.141](https://github.com/langroid/langroid/releases/tag/0.1.141):**
|
366
369
|
API Simplifications to reduce boilerplate:
|
367
|
-
auto-select an available OpenAI model (preferring gpt-
|
370
|
+
auto-select an available OpenAI model (preferring gpt-4o), simplifies defaults.
|
368
371
|
Simpler `Task` initialization with default `ChatAgent`.
|
369
372
|
- **Nov 2023:**
|
370
373
|
- **[0.1.126](https://github.com/langroid/langroid/releases/tag/0.1.126):**
|
@@ -648,7 +651,7 @@ provides more information, and you can set each environment variable as follows:
|
|
648
651
|
- `AZURE_OPENAI_API_BASE` from the value of `ENDPOINT`, typically looks like `https://your.domain.azure.com`.
|
649
652
|
- For `AZURE_OPENAI_API_VERSION`, you can use the default value in `.env-template`, and latest version can be found [here](https://learn.microsoft.com/en-us/azure/ai-services/openai/whats-new#azure-openai-chat-completion-general-availability-ga)
|
650
653
|
- `AZURE_OPENAI_DEPLOYMENT_NAME` is the name of the deployed model, which is defined by the user during the model setup
|
651
|
-
- `AZURE_OPENAI_MODEL_NAME` Azure OpenAI allows specific model names when you select the model for your deployment. You need to put precisly the exact model name that was selected. For example, GPT-
|
654
|
+
- `AZURE_OPENAI_MODEL_NAME` Azure OpenAI allows specific model names when you select the model for your deployment. You need to put precisly the exact model name that was selected. For example, GPT-4 (should be `gpt-4-32k` or `gpt-4`).
|
652
655
|
- `AZURE_OPENAI_MODEL_VERSION` is required if `AZURE_OPENAI_MODEL_NAME = gpt=4`, which will assist Langroid to determine the cost of the model
|
653
656
|
</details>
|
654
657
|
|
@@ -1,19 +1,19 @@
|
|
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=
|
3
|
+
langroid/agent/base.py,sha256=FEAIVwFKlmkOSV3RfRR0-v5UofJBfsBUUSsSEE2ioUI,66824
|
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
|
7
|
-
langroid/agent/chat_agent.py,sha256=
|
7
|
+
langroid/agent/chat_agent.py,sha256=2aUDqM6jsdeU8xt-P86JU2TuZhTpPkUVx9mkXFMy8Rs,51646
|
8
8
|
langroid/agent/chat_document.py,sha256=FZ_PkeKU5OVp1IUlMvspfqxIXzlyd7J_F32DSYrxQ7E,17651
|
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
|
12
12
|
langroid/agent/special/__init__.py,sha256=gik_Xtm_zV7U9s30Mn8UX3Gyuy4jTjQe9zjiE3HWmEo,1273
|
13
13
|
langroid/agent/special/arangodb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
-
langroid/agent/special/arangodb/arangodb_agent.py,sha256=
|
14
|
+
langroid/agent/special/arangodb/arangodb_agent.py,sha256=12Y54c84c9qXV-YXRBcI5HaqyiY75JR4TmqlURYKJAM,25851
|
15
15
|
langroid/agent/special/arangodb/system_messages.py,sha256=udwfLleTdyz_DuxHuoiv2wHEZoAPBPbwdF_ivjIfP5c,6867
|
16
|
-
langroid/agent/special/arangodb/tools.py,sha256=
|
16
|
+
langroid/agent/special/arangodb/tools.py,sha256=Mixl9WS0r0Crd4nrw2YAB0eY33fTsKISul1053eyeio,3590
|
17
17
|
langroid/agent/special/arangodb/utils.py,sha256=LIevtkayIdVVXyj3jlbKH2WgdZTtH5-JLgbXOHC7uxs,1420
|
18
18
|
langroid/agent/special/doc_chat_agent.py,sha256=xIqBOyLax_jMU0UevxqXf_aQUrRkW6MQUKpKnKvaqkQ,59281
|
19
19
|
langroid/agent/special/lance_doc_chat_agent.py,sha256=s8xoRs0gGaFtDYFUSIRchsgDVbS5Q3C2b2mr3V1Fd-Q,10419
|
@@ -39,7 +39,7 @@ langroid/agent/special/sql/utils/tools.py,sha256=vFYysk6Vi7HJjII8B4RitA3pt_z3gkS
|
|
39
39
|
langroid/agent/special/table_chat_agent.py,sha256=d9v2wsblaRx7oMnKhLV7uO_ujvk9gh59pSGvBXyeyNc,9659
|
40
40
|
langroid/agent/structured_message.py,sha256=y7pud1EgRNeTFZlJmBkLmwME3yQJ_IYik-Xds9kdZbY,282
|
41
41
|
langroid/agent/task.py,sha256=f7clh6p6Md0G4YGHqbFeeT88U4XoP0i3eatekV21hHE,86643
|
42
|
-
langroid/agent/tool_message.py,sha256=
|
42
|
+
langroid/agent/tool_message.py,sha256=qQebCWogYTtptznIF1mLERwspWjmVxDWFJeERBO-YsI,11207
|
43
43
|
langroid/agent/tools/__init__.py,sha256=IMgCte-_ZIvCkozGQmvMqxIw7_nKLKzD78ccJL1bnQU,804
|
44
44
|
langroid/agent/tools/duckduckgo_search_tool.py,sha256=NhsCaGZkdv28nja7yveAhSK_w6l_Ftym8agbrdzqgfo,1935
|
45
45
|
langroid/agent/tools/file_tools.py,sha256=GjPB5YDILucYapElnvvoYpGJuZQ25ecLs2REv7edPEo,7292
|
@@ -142,8 +142,8 @@ langroid/vector_store/meilisearch.py,sha256=6frB7GFWeWmeKzRfLZIvzRjllniZ1cYj3Hmh
|
|
142
142
|
langroid/vector_store/momento.py,sha256=qR-zBF1RKVHQZPZQYW_7g-XpTwr46p8HJuYPCkfJbM4,10534
|
143
143
|
langroid/vector_store/qdrant_cloud.py,sha256=3im4Mip0QXLkR6wiqVsjV1QvhSElfxdFSuDKddBDQ-4,188
|
144
144
|
langroid/vector_store/qdrantdb.py,sha256=v88lqFkepADvlN6lByUj9I4NEKa9X9lWH16uTPPbYrE,17457
|
145
|
-
pyproject.toml,sha256=
|
146
|
-
langroid-0.
|
147
|
-
langroid-0.
|
148
|
-
langroid-0.
|
149
|
-
langroid-0.
|
145
|
+
pyproject.toml,sha256=uLe37eP_bS9-a9g2l1uNFzDJgpCRqJvbmmwmLQlD3AA,7488
|
146
|
+
langroid-0.22.0.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
|
147
|
+
langroid-0.22.0.dist-info/METADATA,sha256=M15Qy48jMSppZvJRZLNNVLMZpQR9gNoDeFjoLBCKr6M,57107
|
148
|
+
langroid-0.22.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
149
|
+
langroid-0.22.0.dist-info/RECORD,,
|
pyproject.toml
CHANGED
File without changes
|
File without changes
|