langroid 0.2.6__py3-none-any.whl → 0.2.9__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/openai_assistant.py +17 -4
- langroid/agent/task.py +6 -2
- langroid/language_models/__init__.py +2 -0
- langroid/language_models/base.py +2 -1
- langroid/language_models/openai_gpt.py +27 -5
- langroid/utils/configuration.py +1 -1
- {langroid-0.2.6.dist-info → langroid-0.2.9.dist-info}/METADATA +1 -1
- {langroid-0.2.6.dist-info → langroid-0.2.9.dist-info}/RECORD +11 -11
- pyproject.toml +1 -1
- {langroid-0.2.6.dist-info → langroid-0.2.9.dist-info}/LICENSE +0 -0
- {langroid-0.2.6.dist-info → langroid-0.2.9.dist-info}/WHEEL +0 -0
@@ -100,6 +100,10 @@ class OpenAIAssistant(ChatAgent):
|
|
100
100
|
super().__init__(config)
|
101
101
|
self.config: OpenAIAssistantConfig = config
|
102
102
|
self.llm: OpenAIGPT = OpenAIGPT(self.config.llm)
|
103
|
+
assert (
|
104
|
+
self.llm.cache is not None
|
105
|
+
), "OpenAIAssistant requires a cache to store Assistant and Thread ids"
|
106
|
+
|
103
107
|
if not isinstance(self.llm.client, openai.OpenAI):
|
104
108
|
raise ValueError("Client must be OpenAI")
|
105
109
|
# handles for various entities and methods
|
@@ -235,19 +239,23 @@ class OpenAIAssistant(ChatAgent):
|
|
235
239
|
"""Try to retrieve cached thread_id associated with
|
236
240
|
this user + machine + organization"""
|
237
241
|
key = self._cache_thread_key()
|
242
|
+
if self.llm.cache is None:
|
243
|
+
return None
|
238
244
|
return self.llm.cache.retrieve(key)
|
239
245
|
|
240
246
|
@no_type_check
|
241
247
|
def _cache_assistant_lookup(self) -> str | None:
|
242
248
|
"""Try to retrieve cached assistant_id associated with
|
243
249
|
this user + machine + organization"""
|
250
|
+
if self.llm.cache is None:
|
251
|
+
return None
|
244
252
|
key = self._cache_assistant_key()
|
245
253
|
return self.llm.cache.retrieve(key)
|
246
254
|
|
247
255
|
@no_type_check
|
248
256
|
def _cache_messages_lookup(self) -> LLMResponse | None:
|
249
257
|
"""Try to retrieve cached response for the message-list-hash"""
|
250
|
-
if not settings.cache:
|
258
|
+
if not settings.cache or self.llm.cache is None:
|
251
259
|
return None
|
252
260
|
key = self._cache_messages_key()
|
253
261
|
cached_dict = self.llm.cache.retrieve(key)
|
@@ -260,6 +268,8 @@ class OpenAIAssistant(ChatAgent):
|
|
260
268
|
Cache the assistant_id, thread_id associated with
|
261
269
|
this user + machine + organization
|
262
270
|
"""
|
271
|
+
if self.llm.cache is None:
|
272
|
+
return
|
263
273
|
if self.thread is None or self.assistant is None:
|
264
274
|
raise ValueError("Thread or Assistant is None")
|
265
275
|
thread_key = self._cache_thread_key()
|
@@ -336,7 +346,8 @@ class OpenAIAssistant(ChatAgent):
|
|
336
346
|
Could not delete thread with id {cached}, ignoring.
|
337
347
|
"""
|
338
348
|
)
|
339
|
-
self.llm.cache
|
349
|
+
if self.llm.cache is not None:
|
350
|
+
self.llm.cache.delete_keys([self._cache_thread_key()])
|
340
351
|
if self.thread is None:
|
341
352
|
if self.assistant is None:
|
342
353
|
raise ValueError("Assistant is None")
|
@@ -392,7 +403,8 @@ class OpenAIAssistant(ChatAgent):
|
|
392
403
|
Could not delete assistant with id {cached}, ignoring.
|
393
404
|
"""
|
394
405
|
)
|
395
|
-
self.llm.cache
|
406
|
+
if self.llm.cache is not None:
|
407
|
+
self.llm.cache.delete_keys([self._cache_assistant_key()])
|
396
408
|
if self.assistant is None:
|
397
409
|
self.assistant = self.client.beta.assistants.create(
|
398
410
|
name=self.config.name,
|
@@ -614,7 +626,8 @@ class OpenAIAssistant(ChatAgent):
|
|
614
626
|
usage=None, # TODO
|
615
627
|
cached=False, # TODO - revisit when able to insert Assistant responses
|
616
628
|
)
|
617
|
-
self.llm.cache
|
629
|
+
if self.llm.cache is not None:
|
630
|
+
self.llm.cache.store(key, result.dict())
|
618
631
|
return result
|
619
632
|
|
620
633
|
def _parse_run_required_action(self) -> List[AssistantToolCall]:
|
langroid/agent/task.py
CHANGED
@@ -73,7 +73,7 @@ class TaskConfig(BaseModel):
|
|
73
73
|
inf_loop_wait_factor (int): wait this * cycle_len msgs before loop-check
|
74
74
|
restart_subtask_run (bool): whether to restart *every* run of this task
|
75
75
|
when run as a subtask.
|
76
|
-
addressing_prefix (str): prefix an agent can use to address other
|
76
|
+
addressing_prefix (str): "@"-like prefix an agent can use to address other
|
77
77
|
agents, or entities of the agent. E.g., if this is "@", the addressing
|
78
78
|
string would be "@Alice", or "@user", "@llm", "@agent", etc.
|
79
79
|
If this is an empty string, then addressing is disabled.
|
@@ -85,6 +85,10 @@ class TaskConfig(BaseModel):
|
|
85
85
|
Instead, use the `RecipientTool` to have agents address other agents or
|
86
86
|
entities. If you do choose to use `addressing_prefix`, the recommended
|
87
87
|
setting is to use `langroid.utils.constants.AT`, which currently is "|@|".
|
88
|
+
Note that this setting does NOT affect the use of `constants.SEND_TO` --
|
89
|
+
this is always enabled since this is a critical way for responders to
|
90
|
+
indicate that the message should be sent to a specific entity/agent.
|
91
|
+
(Search for "SEND_TO" in the examples/ dir to see how this is used.)
|
88
92
|
"""
|
89
93
|
|
90
94
|
inf_loop_cycle_len: int = 10
|
@@ -223,7 +227,7 @@ class Task:
|
|
223
227
|
set_parent_agent=noop_fn,
|
224
228
|
)
|
225
229
|
self.config = config
|
226
|
-
# how to behave as a sub-task; can be
|
230
|
+
# how to behave as a sub-task; can be overridden by `add_sub_task()`
|
227
231
|
self.config_sub_task = copy.deepcopy(config)
|
228
232
|
# counts of distinct pending messages in history,
|
229
233
|
# to help detect (exact) infinite loops
|
@@ -16,6 +16,7 @@ from .base import (
|
|
16
16
|
)
|
17
17
|
from .openai_gpt import (
|
18
18
|
OpenAIChatModel,
|
19
|
+
AnthropicModel,
|
19
20
|
OpenAICompletionModel,
|
20
21
|
OpenAIGPTConfig,
|
21
22
|
OpenAIGPT,
|
@@ -39,6 +40,7 @@ __all__ = [
|
|
39
40
|
"LLMTokenUsage",
|
40
41
|
"LLMResponse",
|
41
42
|
"OpenAIChatModel",
|
43
|
+
"AnthropicModel",
|
42
44
|
"OpenAICompletionModel",
|
43
45
|
"OpenAIGPTConfig",
|
44
46
|
"OpenAIGPT",
|
langroid/language_models/base.py
CHANGED
@@ -17,6 +17,7 @@ from typing import (
|
|
17
17
|
)
|
18
18
|
|
19
19
|
from langroid.cachedb.base import CacheDBConfig
|
20
|
+
from langroid.cachedb.redis_cachedb import RedisCacheConfig
|
20
21
|
from langroid.parsing.agent_chats import parse_message
|
21
22
|
from langroid.parsing.parse_json import top_level_json_field
|
22
23
|
from langroid.prompts.dialog import collate_chat_history
|
@@ -50,7 +51,7 @@ class LLMConfig(BaseSettings):
|
|
50
51
|
# use chat model for completion? For OpenAI models, this MUST be set to True!
|
51
52
|
use_chat_for_completion: bool = True
|
52
53
|
stream: bool = True # stream output from API?
|
53
|
-
cache_config: None | CacheDBConfig =
|
54
|
+
cache_config: None | CacheDBConfig = RedisCacheConfig()
|
54
55
|
|
55
56
|
# Dict of model -> (input/prompt cost, output/completion cost)
|
56
57
|
chat_cost_per_1k_tokens: Tuple[float, float] = (0.0, 0.0)
|
@@ -65,6 +65,15 @@ OLLAMA_API_KEY = "ollama"
|
|
65
65
|
DUMMY_API_KEY = "xxx"
|
66
66
|
|
67
67
|
|
68
|
+
class AnthropicModel(str, Enum):
|
69
|
+
"""Enum for Anthropic models"""
|
70
|
+
|
71
|
+
CLAUDE_3_5_SONNET = "claude-3-5-sonnet-20240620"
|
72
|
+
CLAUDE_3_OPUS = "claude-3-opus-20240229"
|
73
|
+
CLAUDE_3_SONNET = "claude-3-sonnet-20240229"
|
74
|
+
CLAUDE_3_HAIKU = "claude-3-turbo-20240307"
|
75
|
+
|
76
|
+
|
68
77
|
class OpenAIChatModel(str, Enum):
|
69
78
|
"""Enum for OpenAI Chat models"""
|
70
79
|
|
@@ -90,6 +99,10 @@ _context_length: Dict[str, int] = {
|
|
90
99
|
OpenAIChatModel.GPT4_TURBO: 128_000,
|
91
100
|
OpenAIChatModel.GPT4o: 128_000,
|
92
101
|
OpenAICompletionModel.TEXT_DA_VINCI_003: 4096,
|
102
|
+
AnthropicModel.CLAUDE_3_5_SONNET: 200_000,
|
103
|
+
AnthropicModel.CLAUDE_3_OPUS: 200_000,
|
104
|
+
AnthropicModel.CLAUDE_3_SONNET: 200_000,
|
105
|
+
AnthropicModel.CLAUDE_3_HAIKU: 200_000,
|
93
106
|
}
|
94
107
|
|
95
108
|
_cost_per_1k_tokens: Dict[str, Tuple[float, float]] = {
|
@@ -99,6 +112,10 @@ _cost_per_1k_tokens: Dict[str, Tuple[float, float]] = {
|
|
99
112
|
OpenAIChatModel.GPT4: (0.03, 0.06), # 8K context
|
100
113
|
OpenAIChatModel.GPT4_TURBO: (0.01, 0.03), # 128K context
|
101
114
|
OpenAIChatModel.GPT4o: (0.005, 0.015), # 128K context
|
115
|
+
AnthropicModel.CLAUDE_3_5_SONNET: (0.003, 0.015),
|
116
|
+
AnthropicModel.CLAUDE_3_OPUS: (0.015, 0.075),
|
117
|
+
AnthropicModel.CLAUDE_3_SONNET: (0.003, 0.015),
|
118
|
+
AnthropicModel.CLAUDE_3_HAIKU: (0.00025, 0.00125),
|
102
119
|
}
|
103
120
|
|
104
121
|
|
@@ -478,8 +495,9 @@ class OpenAIGPT(LanguageModel):
|
|
478
495
|
timeout=Timeout(self.config.timeout),
|
479
496
|
)
|
480
497
|
|
481
|
-
self.cache: CacheDB
|
482
|
-
|
498
|
+
self.cache: CacheDB | None = None
|
499
|
+
use_cache = self.config.cache_config is not None
|
500
|
+
if settings.cache_type == "momento" and use_cache:
|
483
501
|
from langroid.cachedb.momento_cachedb import (
|
484
502
|
MomentoCache,
|
485
503
|
MomentoCacheConfig,
|
@@ -492,7 +510,7 @@ class OpenAIGPT(LanguageModel):
|
|
492
510
|
# switch to fresh momento config if needed
|
493
511
|
config.cache_config = MomentoCacheConfig()
|
494
512
|
self.cache = MomentoCache(config.cache_config)
|
495
|
-
elif "redis" in settings.cache_type:
|
513
|
+
elif "redis" in settings.cache_type and use_cache:
|
496
514
|
if config.cache_config is None or not isinstance(
|
497
515
|
config.cache_config,
|
498
516
|
RedisCacheConfig,
|
@@ -505,10 +523,10 @@ class OpenAIGPT(LanguageModel):
|
|
505
523
|
# force use of fake redis if global cache_type is "fakeredis"
|
506
524
|
config.cache_config.fake = True
|
507
525
|
self.cache = RedisCache(config.cache_config)
|
508
|
-
|
526
|
+
elif settings.cache_type != "none" and use_cache:
|
509
527
|
raise ValueError(
|
510
528
|
f"Invalid cache type {settings.cache_type}. "
|
511
|
-
"Valid types are momento, redis, fakeredis"
|
529
|
+
"Valid types are momento, redis, fakeredis, none"
|
512
530
|
)
|
513
531
|
|
514
532
|
self.config._validate_litellm()
|
@@ -818,6 +836,8 @@ class OpenAIGPT(LanguageModel):
|
|
818
836
|
)
|
819
837
|
|
820
838
|
def _cache_store(self, k: str, v: Any) -> None:
|
839
|
+
if self.cache is None:
|
840
|
+
return
|
821
841
|
try:
|
822
842
|
self.cache.store(k, v)
|
823
843
|
except Exception as e:
|
@@ -825,6 +845,8 @@ class OpenAIGPT(LanguageModel):
|
|
825
845
|
pass
|
826
846
|
|
827
847
|
def _cache_lookup(self, fn_name: str, **kwargs: Dict[str, Any]) -> Tuple[str, Any]:
|
848
|
+
if self.cache is None:
|
849
|
+
return "", None # no cache, return empty key and None result
|
828
850
|
# Use the kwargs as the cache key
|
829
851
|
sorted_kwargs_str = str(sorted(kwargs.items()))
|
830
852
|
raw_key = f"{fn_name}:{sorted_kwargs_str}"
|
langroid/utils/configuration.py
CHANGED
@@ -16,7 +16,7 @@ class Settings(BaseSettings):
|
|
16
16
|
progress: bool = False # show progress spinners/bars?
|
17
17
|
stream: bool = True # stream output?
|
18
18
|
cache: bool = True # use cache?
|
19
|
-
cache_type: Literal["redis", "fakeredis", "momento"] = "redis" # cache type
|
19
|
+
cache_type: Literal["redis", "fakeredis", "momento", "none"] = "redis" # cache type
|
20
20
|
interactive: bool = True # interactive mode?
|
21
21
|
gpt3_5: bool = True # use GPT-3.5?
|
22
22
|
chat_model: str = "" # language model name, e.g. litellm/ollama/llama2
|
@@ -8,7 +8,7 @@ langroid/agent/chat_agent.py,sha256=nO6Yx5WvFsul5RmTP-HCdzeQPhccmzU_mDcPNdkzQ-s,
|
|
8
8
|
langroid/agent/chat_document.py,sha256=MwtNABK28tfSzqCeQlxoauT8uPn8oldU7dlnrX8aQ10,11232
|
9
9
|
langroid/agent/helpers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
10
|
langroid/agent/junk,sha256=LxfuuW7Cijsg0szAzT81OjWWv1PMNI-6w_-DspVIO2s,339
|
11
|
-
langroid/agent/openai_assistant.py,sha256=
|
11
|
+
langroid/agent/openai_assistant.py,sha256=3saI9PwF8IZNJcjqyUy-rj73TInAzdlk14LiOvT_Dkc,33548
|
12
12
|
langroid/agent/special/__init__.py,sha256=gik_Xtm_zV7U9s30Mn8UX3Gyuy4jTjQe9zjiE3HWmEo,1273
|
13
13
|
langroid/agent/special/doc_chat_agent.py,sha256=CXFLfDMEabaBZwZwFgNOaG3E3S86xcBM4txrsMD_70I,54014
|
14
14
|
langroid/agent/special/lance_doc_chat_agent.py,sha256=USp0U3eTaJzwF_3bdqE7CedSLbaqAi2tm-VzygcyLaA,10175
|
@@ -32,7 +32,7 @@ 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=
|
35
|
+
langroid/agent/task.py,sha256=vKM2dmRYSH4i_VA0lf2axUtZcTGU44rVHz6EyxI4kG0,73990
|
36
36
|
langroid/agent/tool_message.py,sha256=wIyZnUcZpxkiRPvM9O3MO3b5BBAdLEEan9kqPbvtApc,9743
|
37
37
|
langroid/agent/tools/__init__.py,sha256=e-63cfwQNk_ftRKQwgDAJQK16QLbRVWDBILeXIc7wLk,402
|
38
38
|
langroid/agent/tools/duckduckgo_search_tool.py,sha256=NhsCaGZkdv28nja7yveAhSK_w6l_Ftym8agbrdzqgfo,1935
|
@@ -62,12 +62,12 @@ langroid/embedding_models/protoc/embeddings_pb2.pyi,sha256=UkNy7BrNsmQm0vLb3NtGX
|
|
62
62
|
langroid/embedding_models/protoc/embeddings_pb2_grpc.py,sha256=9dYQqkW3JPyBpSEjeGXTNpSqAkC-6FPtBHyteVob2Y8,2452
|
63
63
|
langroid/embedding_models/remote_embeds.py,sha256=6_kjXByVbqhY9cGwl9R83ZcYC2km-nGieNNAo1McHaY,5151
|
64
64
|
langroid/exceptions.py,sha256=w_Cr41nPAmsa6gW5nNFaO9yDcBCWdQqRspL1jYvZf5w,2209
|
65
|
-
langroid/language_models/__init__.py,sha256=
|
65
|
+
langroid/language_models/__init__.py,sha256=1sUGobooTqq77XC7LxKsvME0RgSd5GGmeyrPo9SMh4U,940
|
66
66
|
langroid/language_models/azure_openai.py,sha256=ncRCbKooqLVOY-PWQUIo9C3yTuKEFbAwyngXT_M4P7k,5989
|
67
|
-
langroid/language_models/base.py,sha256=
|
67
|
+
langroid/language_models/base.py,sha256=oAK2lXBqksMglqWqE2CjC03X3qPFXWgtjFWpH9hJ3C8,17500
|
68
68
|
langroid/language_models/config.py,sha256=9Q8wk5a7RQr8LGMT_0WkpjY8S4ywK06SalVRjXlfCiI,378
|
69
69
|
langroid/language_models/mock_lm.py,sha256=qdgj-wtbQBXlibo_0rIRfCt0hGTPRoxy1C4VjN6quI4,2707
|
70
|
-
langroid/language_models/openai_gpt.py,sha256=
|
70
|
+
langroid/language_models/openai_gpt.py,sha256=sALSYei56U57x8ugMayGIR6MtR9b9QsJ0MYhdt3_aMA,51674
|
71
71
|
langroid/language_models/prompt_formatter/__init__.py,sha256=2-5cdE24XoFDhifOLl8yiscohil1ogbP1ECkYdBlBsk,372
|
72
72
|
langroid/language_models/prompt_formatter/base.py,sha256=eDS1sgRNZVnoajwV_ZIha6cba5Dt8xjgzdRbPITwx3Q,1221
|
73
73
|
langroid/language_models/prompt_formatter/hf_formatter.py,sha256=TFL6ppmeQWnzr6CKQzRZFYY810zE1mr8DZnhw6i85ok,5217
|
@@ -104,7 +104,7 @@ langroid/pydantic_v1/main.py,sha256=p_k7kDY9eDrsA5dxNNqXusKLgx7mS_icGnS7fu4goqY,
|
|
104
104
|
langroid/utils/__init__.py,sha256=Sruos2tB4G7Tn0vlblvYlX9PEGR0plI2uE0PJ4d_EC4,353
|
105
105
|
langroid/utils/algorithms/__init__.py,sha256=WylYoZymA0fnzpB4vrsH_0n7WsoLhmuZq8qxsOCjUpM,41
|
106
106
|
langroid/utils/algorithms/graph.py,sha256=JbdpPnUOhw4-D6O7ou101JLA3xPCD0Lr3qaPoFCaRfo,2866
|
107
|
-
langroid/utils/configuration.py,sha256=
|
107
|
+
langroid/utils/configuration.py,sha256=LgjHGB0qgKKTwBaVt84APiqvJbz6pLwylUvHWYmzyP0,3303
|
108
108
|
langroid/utils/constants.py,sha256=w3eBQ5Q2HjxMBN_y1UarK0keREqCwXSxQXizMafsG-M,911
|
109
109
|
langroid/utils/docker.py,sha256=kJQOLTgM0x9j9pgIIqp0dZNZCTvoUDhp6i8tYBq1Jr0,1105
|
110
110
|
langroid/utils/globals.py,sha256=Az9dOFqR6n9CoTYSqa2kLikQWS0oCQ9DFQIQAnG-2q8,1355
|
@@ -129,8 +129,8 @@ langroid/vector_store/meilisearch.py,sha256=6frB7GFWeWmeKzRfLZIvzRjllniZ1cYj3Hmh
|
|
129
129
|
langroid/vector_store/momento.py,sha256=QaPzUnTwlswoawGB-paLtUPyLRvckFXLfLDfvbTzjNQ,10505
|
130
130
|
langroid/vector_store/qdrant_cloud.py,sha256=3im4Mip0QXLkR6wiqVsjV1QvhSElfxdFSuDKddBDQ-4,188
|
131
131
|
langroid/vector_store/qdrantdb.py,sha256=wYOuu5c2vIKn9ZgvTXcAiZXMpV8AOXEWFAzI8S8UP-0,16828
|
132
|
-
pyproject.toml,sha256=
|
133
|
-
langroid-0.2.
|
134
|
-
langroid-0.2.
|
135
|
-
langroid-0.2.
|
136
|
-
langroid-0.2.
|
132
|
+
pyproject.toml,sha256=vsVtb6-2IMl64e-3J3mqLEdL-hGAIw2X3gBjNk_HILs,6957
|
133
|
+
langroid-0.2.9.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
|
134
|
+
langroid-0.2.9.dist-info/METADATA,sha256=yColHB7bdfQ1nlYGucfcfH14xywCqm2IAjd8kPs3GhI,53950
|
135
|
+
langroid-0.2.9.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
136
|
+
langroid-0.2.9.dist-info/RECORD,,
|
pyproject.toml
CHANGED
File without changes
|
File without changes
|