langroid 0.50.11__py3-none-any.whl → 0.50.12__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.
@@ -759,11 +759,7 @@ class OpenAIGPT(LanguageModel):
759
759
 
760
760
  def get_stream(self) -> bool:
761
761
  """Get streaming status."""
762
- return (
763
- self.config.stream
764
- and settings.stream
765
- and self.info().allows_streaming
766
- )
762
+ return self.config.stream and settings.stream and self.info().allows_streaming
767
763
 
768
764
  @no_type_check
769
765
  def _process_stream_event(
@@ -812,7 +808,7 @@ class OpenAIGPT(LanguageModel):
812
808
  event_args = ""
813
809
  event_fn_name = ""
814
810
  event_tool_deltas: Optional[List[Dict[str, Any]]] = None
815
- silent = self.config.async_stream_quiet or settings.quiet
811
+ silent = settings.quiet
816
812
  # The first two events in the stream of Azure OpenAI is useless.
817
813
  # In the 1st: choices list is empty, in the 2nd: the dict delta has null content
818
814
  if chat:
@@ -999,9 +995,7 @@ class OpenAIGPT(LanguageModel):
999
995
  if not silent:
1000
996
  sys.stdout.write(Colors().GREEN + "FUNC: " + event_fn_name + ": ")
1001
997
  sys.stdout.flush()
1002
- await self.config.streamer_async(
1003
- event_fn_name, StreamEventType.FUNC_NAME
1004
- )
998
+ await self.config.streamer_async(event_fn_name, StreamEventType.FUNC_NAME)
1005
999
 
1006
1000
  if event_args:
1007
1001
  function_args += event_args
@@ -1,16 +1,17 @@
1
- import copy
2
1
  import os
2
+ import threading
3
3
  from contextlib import contextmanager
4
- from typing import Iterator, List, Literal
4
+ from typing import Any, Dict, Iterator, List, Literal, cast
5
5
 
6
6
  from dotenv import find_dotenv, load_dotenv
7
7
 
8
8
  from langroid.pydantic_v1 import BaseSettings
9
9
 
10
+ # Global reentrant lock to serialize any modifications to the global settings.
11
+ _global_lock = threading.RLock()
12
+
10
13
 
11
14
  class Settings(BaseSettings):
12
- # NOTE all of these can be overridden in your .env file with upper-case names,
13
- # for example CACHE_TYPE=momento
14
15
  debug: bool = False # show debug messages?
15
16
  max_turns: int = -1 # maximum number of turns in a task (to avoid inf loop)
16
17
  progress: bool = False # show progress spinners/bars?
@@ -25,74 +26,112 @@ class Settings(BaseSettings):
25
26
  extra = "forbid"
26
27
 
27
28
 
28
- load_dotenv(find_dotenv(usecwd=True)) # get settings from .env file
29
- settings = Settings()
29
+ # Load environment variables from .env file.
30
+ load_dotenv(find_dotenv(usecwd=True))
31
+
32
+ # The global (default) settings instance.
33
+ # This is updated by update_global_settings() and set_global().
34
+ _global_settings = Settings()
35
+
36
+ # Thread-local storage for temporary (per-thread) settings overrides.
37
+ _thread_local = threading.local()
38
+
39
+
40
+ class SettingsProxy:
41
+ """
42
+ A proxy for the settings that returns a thread‐local override if set,
43
+ or else falls back to the global settings.
44
+ """
45
+
46
+ def __getattr__(self, name: str) -> Any:
47
+ # If the calling thread has set an override, use that.
48
+ if hasattr(_thread_local, "override"):
49
+ return getattr(_thread_local.override, name)
50
+ return getattr(_global_settings, name)
51
+
52
+ def __setattr__(self, name: str, value: Any) -> None:
53
+ # All writes go to the global settings.
54
+ setattr(_global_settings, name, value)
55
+
56
+ def update(self, new_settings: Settings) -> None:
57
+ _global_settings.__dict__.update(new_settings.__dict__)
58
+
59
+ def dict(self) -> Dict[str, Any]:
60
+ # Return a dict view of the settings as seen by the caller.
61
+ # Note that temporary overrides are not “merged” with global settings.
62
+ if hasattr(_thread_local, "override"):
63
+ return cast(Dict[str, Any], cast(Settings, _thread_local.override.dict()))
64
+ return _global_settings.dict()
65
+
66
+
67
+ settings = SettingsProxy()
30
68
 
31
69
 
32
70
  def update_global_settings(cfg: BaseSettings, keys: List[str]) -> None:
33
71
  """
34
- Update global settings so modules can access them via (as an example):
35
- ```
36
- from langroid.utils.configuration import settings
37
- if settings.debug...
38
- ```
39
- Caution we do not want to have too many such global settings!
40
- Args:
41
- cfg: pydantic config, typically from a main script
42
- keys: which keys from cfg to use, to update the global settings object
72
+ Update global settings so that modules can later access them via, e.g.,
73
+
74
+ from langroid.utils.configuration import settings
75
+ if settings.debug: ...
76
+
77
+ This updates the global default.
43
78
  """
44
79
  config_dict = cfg.dict()
45
-
46
- # Filter the config_dict based on the keys
47
80
  filtered_config = {key: config_dict[key] for key in keys if key in config_dict}
48
-
49
- # create a new Settings() object to let pydantic validate it
50
81
  new_settings = Settings(**filtered_config)
51
-
52
- # Update the unique global settings object
53
- settings.__dict__.update(new_settings.__dict__)
82
+ _global_settings.__dict__.update(new_settings.__dict__)
54
83
 
55
84
 
56
85
  def set_global(key_vals: Settings) -> None:
57
- """Update the unique global settings object"""
58
- settings.__dict__.update(key_vals.__dict__)
86
+ """
87
+ Update the global settings object.
88
+ """
89
+ _global_settings.__dict__.update(key_vals.__dict__)
59
90
 
60
91
 
61
92
  @contextmanager
62
93
  def temporary_settings(temp_settings: Settings) -> Iterator[None]:
63
- """Temporarily update the global settings and restore them afterward."""
64
- original_settings = copy.deepcopy(settings)
65
-
66
- set_global(temp_settings)
94
+ """
95
+ Temporarily override the settings for the calling thread.
67
96
 
97
+ Within the context, any access to "settings" will use the provided temporary
98
+ settings. Once the context is exited, the thread reverts to the global settings.
99
+ """
100
+ saved = getattr(_thread_local, "override", None)
101
+ _thread_local.override = temp_settings
68
102
  try:
69
103
  yield
70
104
  finally:
71
- settings.__dict__.update(original_settings.__dict__)
105
+ if saved is not None:
106
+ _thread_local.override = saved
107
+ else:
108
+ del _thread_local.override
72
109
 
73
110
 
74
111
  @contextmanager
75
112
  def quiet_mode(quiet: bool = True) -> Iterator[None]:
76
- """Temporarily set quiet=True in global settings and restore afterward."""
77
- original_settings = copy.deepcopy(settings)
78
- if quiet:
79
- temp_settings = original_settings.copy(update={"quiet": True})
80
- set_global(temp_settings)
81
-
82
- try:
113
+ """
114
+ Temporarily override settings.quiet for the current thread.
115
+ This implementation builds on the thread‑local temporary_settings context manager.
116
+ The effective quiet mode is merged:
117
+ if quiet is already True (from an outer context),
118
+ then it remains True even if a nested context passes quiet=False.
119
+ """
120
+ current_effective = settings.dict() # get the current thread's effective settings
121
+ # Create a new settings instance from the current effective state.
122
+ temp = Settings(**current_effective)
123
+ # Merge the new flag: once quiet is enabled, it stays enabled.
124
+ temp.quiet = settings.quiet or quiet
125
+ with temporary_settings(temp):
83
126
  yield
84
- finally:
85
- if quiet:
86
- settings.__dict__.update(original_settings.__dict__)
87
127
 
88
128
 
89
- def set_env(settings: BaseSettings) -> None:
129
+ def set_env(settings_instance: BaseSettings) -> None:
90
130
  """
91
- Set environment variables from a BaseSettings instance
92
- Args:
93
- settings (BaseSettings): desired settings
94
- Returns:
131
+ Set environment variables from a BaseSettings instance.
132
+
133
+ Each field in the settings is written to os.environ.
95
134
  """
96
- for field_name, field in settings.__class__.__fields__.items():
135
+ for field_name, field in settings_instance.__class__.__fields__.items():
97
136
  env_var_name = field.field_info.extra.get("env", field_name).upper()
98
- os.environ[env_var_name] = str(settings.dict()[field_name])
137
+ os.environ[env_var_name] = str(settings_instance.dict()[field_name])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langroid
3
- Version: 0.50.11
3
+ Version: 0.50.12
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  Author-email: Prasad Chalasani <pchalasani@gmail.com>
6
6
  License: MIT
@@ -73,7 +73,7 @@ langroid/language_models/base.py,sha256=sCDC02hqIgjY73KnCvc-YGxZJm_LAs4Z1VVQpIFW
73
73
  langroid/language_models/config.py,sha256=9Q8wk5a7RQr8LGMT_0WkpjY8S4ywK06SalVRjXlfCiI,378
74
74
  langroid/language_models/mock_lm.py,sha256=5BgHKDVRWFbUwDT_PFgTZXz9-k8wJSA2e3PZmyDgQ1k,4022
75
75
  langroid/language_models/model_info.py,sha256=tfBBxL0iUf2mVN6CjcvqflzFUVg2oZqOJZexZ8jHTYA,12216
76
- langroid/language_models/openai_gpt.py,sha256=o-iOvdpSnkXtvrJyhlItJwYIcZoF8vz3blUBjzOcGS0,84843
76
+ langroid/language_models/openai_gpt.py,sha256=FG3eMWedko0kN-n-SkSbwnrm5hSxoW2wmJSBAvOAOYU,84731
77
77
  langroid/language_models/utils.py,sha256=hC5p61P_Qlrowkm5wMap1A1b5ZUCwK_XhPIzAQk1T1s,5483
78
78
  langroid/language_models/prompt_formatter/__init__.py,sha256=2-5cdE24XoFDhifOLl8yiscohil1ogbP1ECkYdBlBsk,372
79
79
  langroid/language_models/prompt_formatter/base.py,sha256=eDS1sgRNZVnoajwV_ZIha6cba5Dt8xjgzdRbPITwx3Q,1221
@@ -104,7 +104,7 @@ langroid/prompts/templates.py,sha256=VV84HVf_amOx6xdWQyIsN9i5dNfrbl8rsfFp6hyfOss
104
104
  langroid/pydantic_v1/__init__.py,sha256=HxPGVERapVueRUORgSpj2JX_vTZxVlVbWvhpQlpjygE,283
105
105
  langroid/pydantic_v1/main.py,sha256=p_k7kDY9eDrsA5dxNNqXusKLgx7mS_icGnS7fu4goqY,147
106
106
  langroid/utils/__init__.py,sha256=Sruos2tB4G7Tn0vlblvYlX9PEGR0plI2uE0PJ4d_EC4,353
107
- langroid/utils/configuration.py,sha256=V3RS8OP7AC0_bDKczxfortD0F5H3cnsZL0ulKBxuoHU,3213
107
+ langroid/utils/configuration.py,sha256=FJVoseN3mkqx5vzpmtkzCLuQEYlWZEK_11YJ-Ge-L5o,4812
108
108
  langroid/utils/constants.py,sha256=CK09kda9bNDEhnwClq7ZTWZOh38guJlfcZ5hKUS1Ijo,1075
109
109
  langroid/utils/git_utils.py,sha256=WnflJ3R3owhlD0LNdSJakcKhExcEehE1UW5jYVQl8JY,7955
110
110
  langroid/utils/globals.py,sha256=Az9dOFqR6n9CoTYSqa2kLikQWS0oCQ9DFQIQAnG-2q8,1355
@@ -129,7 +129,7 @@ langroid/vector_store/pineconedb.py,sha256=otxXZNaBKb9f_H75HTaU3lMHiaR2NUp5MqwLZ
129
129
  langroid/vector_store/postgres.py,sha256=wHPtIi2qM4fhO4pMQr95pz1ZCe7dTb2hxl4VYspGZoA,16104
130
130
  langroid/vector_store/qdrantdb.py,sha256=O6dSBoDZ0jzfeVBd7LLvsXu083xs2fxXtPa9gGX3JX4,18443
131
131
  langroid/vector_store/weaviatedb.py,sha256=Yn8pg139gOy3zkaPfoTbMXEEBCiLiYa1MU5d_3UA1K4,11847
132
- langroid-0.50.11.dist-info/METADATA,sha256=oAh04rgGQXXGEe7tu3yAX7t1787xRBG85NqEh996F_0,63642
133
- langroid-0.50.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
134
- langroid-0.50.11.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
135
- langroid-0.50.11.dist-info/RECORD,,
132
+ langroid-0.50.12.dist-info/METADATA,sha256=b1vQBIkydfimg9r80ud7w07d7540XJAdhpegeqAPPTw,63642
133
+ langroid-0.50.12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
134
+ langroid-0.50.12.dist-info/licenses/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
135
+ langroid-0.50.12.dist-info/RECORD,,