lucidicai 3.2.0__py3-none-any.whl → 3.3.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.
- lucidicai/__init__.py +1 -1
- lucidicai/api/resources/prompt.py +70 -14
- lucidicai/client.py +12 -1
- lucidicai/core/config.py +34 -7
- {lucidicai-3.2.0.dist-info → lucidicai-3.3.1.dist-info}/METADATA +1 -1
- {lucidicai-3.2.0.dist-info → lucidicai-3.3.1.dist-info}/RECORD +8 -8
- {lucidicai-3.2.0.dist-info → lucidicai-3.3.1.dist-info}/WHEEL +0 -0
- {lucidicai-3.2.0.dist-info → lucidicai-3.3.1.dist-info}/top_level.txt +0 -0
lucidicai/__init__.py
CHANGED
|
@@ -1,30 +1,57 @@
|
|
|
1
1
|
"""Prompt resource API operations."""
|
|
2
2
|
import logging
|
|
3
|
-
|
|
3
|
+
import time
|
|
4
|
+
from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING
|
|
4
5
|
|
|
5
6
|
from ..client import HttpClient
|
|
6
7
|
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from ...core.config import SDKConfig
|
|
10
|
+
|
|
7
11
|
logger = logging.getLogger("Lucidic")
|
|
8
12
|
|
|
9
13
|
|
|
10
14
|
class PromptResource:
|
|
11
15
|
"""Handle prompt-related API operations."""
|
|
12
16
|
|
|
13
|
-
def __init__(self, http: HttpClient, production: bool = False):
|
|
17
|
+
def __init__(self, http: HttpClient, config: "SDKConfig", production: bool = False):
|
|
14
18
|
"""Initialize prompt resource.
|
|
15
19
|
|
|
16
20
|
Args:
|
|
17
21
|
http: HTTP client instance
|
|
22
|
+
config: SDK configuration
|
|
18
23
|
production: Whether to suppress errors in production mode
|
|
19
24
|
"""
|
|
20
25
|
self.http = http
|
|
26
|
+
self._config = config
|
|
21
27
|
self._production = production
|
|
28
|
+
self._cache: Dict[Tuple[str, str], Dict[str, Any]] = {}
|
|
29
|
+
|
|
30
|
+
def _is_cache_valid(self, cache_key: Tuple[str, str], cache_ttl: int) -> bool:
|
|
31
|
+
"""Check if a cached prompt is still valid.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
cache_key: The (prompt_name, label) tuple
|
|
35
|
+
cache_ttl: Cache TTL in seconds (-1 = indefinite, 0 = no cache)
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
True if cache is valid, False otherwise
|
|
39
|
+
"""
|
|
40
|
+
if cache_ttl == 0:
|
|
41
|
+
return False
|
|
42
|
+
if cache_key not in self._cache:
|
|
43
|
+
return False
|
|
44
|
+
if cache_ttl == -1:
|
|
45
|
+
return True
|
|
46
|
+
cached = self._cache[cache_key]
|
|
47
|
+
return (time.time() - cached["timestamp"]) < cache_ttl
|
|
22
48
|
|
|
23
49
|
def get(
|
|
24
50
|
self,
|
|
25
51
|
prompt_name: str,
|
|
26
52
|
variables: Optional[Dict[str, Any]] = None,
|
|
27
53
|
label: str = "production",
|
|
54
|
+
cache_ttl: int = 0,
|
|
28
55
|
) -> str:
|
|
29
56
|
"""Get a prompt from the prompt database.
|
|
30
57
|
|
|
@@ -32,21 +59,36 @@ class PromptResource:
|
|
|
32
59
|
prompt_name: Name of the prompt.
|
|
33
60
|
variables: Variables to interpolate into the prompt.
|
|
34
61
|
label: Prompt version label (default: "production").
|
|
62
|
+
cache_ttl: Cache TTL in seconds. 0 = no cache, -1 = cache indefinitely,
|
|
63
|
+
positive value = seconds before refetching.
|
|
35
64
|
|
|
36
65
|
Returns:
|
|
37
66
|
The prompt content with variables interpolated.
|
|
38
67
|
"""
|
|
39
68
|
try:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
)
|
|
44
|
-
|
|
69
|
+
cache_key = (prompt_name, label)
|
|
70
|
+
|
|
71
|
+
# Check cache
|
|
72
|
+
if self._is_cache_valid(cache_key, cache_ttl):
|
|
73
|
+
prompt = self._cache[cache_key]["content"]
|
|
74
|
+
else:
|
|
75
|
+
response = self.http.get(
|
|
76
|
+
"getprompt",
|
|
77
|
+
{"prompt_name": prompt_name, "label": label, "agent_id": self._config.agent_id},
|
|
78
|
+
)
|
|
79
|
+
prompt = response.get("prompt_content", "")
|
|
80
|
+
|
|
81
|
+
# Store in cache if caching is enabled
|
|
82
|
+
if cache_ttl != 0:
|
|
83
|
+
self._cache[cache_key] = {
|
|
84
|
+
"content": prompt,
|
|
85
|
+
"timestamp": time.time(),
|
|
86
|
+
}
|
|
45
87
|
|
|
46
88
|
# Replace variables
|
|
47
89
|
if variables:
|
|
48
90
|
for key, value in variables.items():
|
|
49
|
-
prompt = prompt.replace(f"{{{key}}}", str(value))
|
|
91
|
+
prompt = prompt.replace(f"{{{{{key}}}}}", str(value))
|
|
50
92
|
|
|
51
93
|
return prompt
|
|
52
94
|
except Exception as e:
|
|
@@ -60,21 +102,35 @@ class PromptResource:
|
|
|
60
102
|
prompt_name: str,
|
|
61
103
|
variables: Optional[Dict[str, Any]] = None,
|
|
62
104
|
label: str = "production",
|
|
105
|
+
cache_ttl: int = 0,
|
|
63
106
|
) -> str:
|
|
64
107
|
"""Get a prompt from the prompt database (asynchronous).
|
|
65
108
|
|
|
66
109
|
See get() for full documentation.
|
|
67
110
|
"""
|
|
68
111
|
try:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
)
|
|
73
|
-
|
|
112
|
+
cache_key = (prompt_name, label)
|
|
113
|
+
|
|
114
|
+
# Check cache
|
|
115
|
+
if self._is_cache_valid(cache_key, cache_ttl):
|
|
116
|
+
prompt = self._cache[cache_key]["content"]
|
|
117
|
+
else:
|
|
118
|
+
response = await self.http.aget(
|
|
119
|
+
"getprompt",
|
|
120
|
+
{"prompt_name": prompt_name, "label": label, "agent_id": self._config.agent_id},
|
|
121
|
+
)
|
|
122
|
+
prompt = response.get("prompt_content", "")
|
|
123
|
+
|
|
124
|
+
# Store in cache if caching is enabled
|
|
125
|
+
if cache_ttl != 0:
|
|
126
|
+
self._cache[cache_key] = {
|
|
127
|
+
"content": prompt,
|
|
128
|
+
"timestamp": time.time(),
|
|
129
|
+
}
|
|
74
130
|
|
|
75
131
|
if variables:
|
|
76
132
|
for key, value in variables.items():
|
|
77
|
-
prompt = prompt.replace(f"{{{key}}}", str(value))
|
|
133
|
+
prompt = prompt.replace(f"{{{{{key}}}}}", str(value))
|
|
78
134
|
|
|
79
135
|
return prompt
|
|
80
136
|
except Exception as e:
|
lucidicai/client.py
CHANGED
|
@@ -64,6 +64,8 @@ class LucidicAI:
|
|
|
64
64
|
auto_end: Whether sessions auto-end on context exit or process shutdown.
|
|
65
65
|
production: If True, suppress SDK errors. If None, checks LUCIDIC_PRODUCTION env var.
|
|
66
66
|
region: Deployment region ("us", "india"). Falls back to LUCIDIC_REGION env var.
|
|
67
|
+
base_url: Custom base URL for API requests. Takes precedence over region.
|
|
68
|
+
Falls back to LUCIDIC_BASE_URL env var.
|
|
67
69
|
**kwargs: Additional configuration options passed to SDKConfig.
|
|
68
70
|
|
|
69
71
|
Raises:
|
|
@@ -93,6 +95,13 @@ class LucidicAI:
|
|
|
93
95
|
agent_id="...",
|
|
94
96
|
region="india"
|
|
95
97
|
)
|
|
98
|
+
|
|
99
|
+
# Custom base URL (e.g., self-hosted deployment)
|
|
100
|
+
client = LucidicAI(
|
|
101
|
+
api_key="...",
|
|
102
|
+
agent_id="...",
|
|
103
|
+
base_url="https://custom.example.com/api"
|
|
104
|
+
)
|
|
96
105
|
"""
|
|
97
106
|
|
|
98
107
|
def __init__(
|
|
@@ -103,6 +112,7 @@ class LucidicAI:
|
|
|
103
112
|
auto_end: bool = True,
|
|
104
113
|
production: Optional[bool] = None,
|
|
105
114
|
region: Optional[str] = None,
|
|
115
|
+
base_url: Optional[str] = None,
|
|
106
116
|
**kwargs,
|
|
107
117
|
):
|
|
108
118
|
# Generate unique client ID for telemetry routing
|
|
@@ -119,6 +129,7 @@ class LucidicAI:
|
|
|
119
129
|
agent_id=agent_id,
|
|
120
130
|
auto_end=auto_end,
|
|
121
131
|
region=region,
|
|
132
|
+
base_url=base_url,
|
|
122
133
|
**kwargs,
|
|
123
134
|
)
|
|
124
135
|
|
|
@@ -144,7 +155,7 @@ class LucidicAI:
|
|
|
144
155
|
"events": EventResource(self._http, self._production),
|
|
145
156
|
"datasets": DatasetResource(self._http, self._config.agent_id, self._production),
|
|
146
157
|
"experiments": ExperimentResource(self._http, self._config.agent_id, self._production),
|
|
147
|
-
"prompts": PromptResource(self._http, self._production),
|
|
158
|
+
"prompts": PromptResource(self._http, self._config, self._production),
|
|
148
159
|
"feature_flags": FeatureFlagResource(self._http, self._config.agent_id, self._production),
|
|
149
160
|
"evals": EvalsResource(self._http, self._production),
|
|
150
161
|
}
|
lucidicai/core/config.py
CHANGED
|
@@ -53,16 +53,20 @@ class NetworkConfig:
|
|
|
53
53
|
connection_pool_maxsize: int = 100
|
|
54
54
|
|
|
55
55
|
@classmethod
|
|
56
|
-
def from_env(cls, region: Optional[str] = None, debug: bool = False) -> 'NetworkConfig':
|
|
56
|
+
def from_env(cls, region: Optional[str] = None, base_url: Optional[str] = None, debug: bool = False) -> 'NetworkConfig':
|
|
57
57
|
"""Load network configuration from environment variables.
|
|
58
58
|
|
|
59
|
-
Priority: debug >
|
|
59
|
+
Priority: debug > base_url argument > LUCIDIC_BASE_URL > region argument > LUCIDIC_REGION > default
|
|
60
60
|
|
|
61
61
|
Args:
|
|
62
62
|
region: Region string override (e.g., "us", "india")
|
|
63
|
-
|
|
63
|
+
base_url: Custom base URL override (takes precedence over region)
|
|
64
|
+
debug: If True, use localhost URL regardless of other settings
|
|
64
65
|
"""
|
|
65
|
-
|
|
66
|
+
import logging
|
|
67
|
+
logger = logging.getLogger("Lucidic")
|
|
68
|
+
|
|
69
|
+
# If debug mode, use localhost (highest priority)
|
|
66
70
|
if debug:
|
|
67
71
|
return cls(
|
|
68
72
|
base_url=DEBUG_URL,
|
|
@@ -74,7 +78,28 @@ class NetworkConfig:
|
|
|
74
78
|
connection_pool_maxsize=int(os.getenv("LUCIDIC_CONNECTION_POOL_MAXSIZE", "100"))
|
|
75
79
|
)
|
|
76
80
|
|
|
77
|
-
# Resolve
|
|
81
|
+
# Resolve base_url: argument > env var
|
|
82
|
+
resolved_base_url = base_url or os.getenv("LUCIDIC_BASE_URL")
|
|
83
|
+
|
|
84
|
+
if resolved_base_url:
|
|
85
|
+
# base_url takes precedence over region
|
|
86
|
+
region_str = region or os.getenv("LUCIDIC_REGION")
|
|
87
|
+
if region_str:
|
|
88
|
+
logger.warning(
|
|
89
|
+
f"[LucidicAI] Both base_url and region specified. "
|
|
90
|
+
f"Using base_url '{resolved_base_url}', ignoring region '{region_str}'."
|
|
91
|
+
)
|
|
92
|
+
return cls(
|
|
93
|
+
base_url=resolved_base_url,
|
|
94
|
+
region=None, # Custom deployment, no region
|
|
95
|
+
timeout=int(os.getenv("LUCIDIC_TIMEOUT", "30")),
|
|
96
|
+
max_retries=int(os.getenv("LUCIDIC_MAX_RETRIES", "3")),
|
|
97
|
+
backoff_factor=float(os.getenv("LUCIDIC_BACKOFF_FACTOR", "0.5")),
|
|
98
|
+
connection_pool_size=int(os.getenv("LUCIDIC_CONNECTION_POOL_SIZE", "20")),
|
|
99
|
+
connection_pool_maxsize=int(os.getenv("LUCIDIC_CONNECTION_POOL_MAXSIZE", "100"))
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Fall back to region-based URL resolution
|
|
78
103
|
region_str = region or os.getenv("LUCIDIC_REGION")
|
|
79
104
|
resolved_region = Region.from_string(region_str) if region_str else DEFAULT_REGION
|
|
80
105
|
|
|
@@ -147,11 +172,13 @@ class SDKConfig:
|
|
|
147
172
|
debug: bool = False
|
|
148
173
|
|
|
149
174
|
@classmethod
|
|
150
|
-
def from_env(cls, region: Optional[str] = None, **overrides) -> 'SDKConfig':
|
|
175
|
+
def from_env(cls, region: Optional[str] = None, base_url: Optional[str] = None, **overrides) -> 'SDKConfig':
|
|
151
176
|
"""Create configuration from environment variables with optional overrides.
|
|
152
177
|
|
|
153
178
|
Args:
|
|
154
179
|
region: Region string (e.g., "us", "india"). Priority: arg > env var > default
|
|
180
|
+
base_url: Custom base URL override. Takes precedence over region.
|
|
181
|
+
Falls back to LUCIDIC_BASE_URL env var.
|
|
155
182
|
**overrides: Additional configuration overrides
|
|
156
183
|
"""
|
|
157
184
|
from dotenv import load_dotenv
|
|
@@ -165,7 +192,7 @@ class SDKConfig:
|
|
|
165
192
|
auto_end=os.getenv("LUCIDIC_AUTO_END", "true").lower() == "true",
|
|
166
193
|
production_monitoring=False,
|
|
167
194
|
blob_threshold=int(os.getenv("LUCIDIC_BLOB_THRESHOLD", "65536")),
|
|
168
|
-
network=NetworkConfig.from_env(region=region, debug=debug),
|
|
195
|
+
network=NetworkConfig.from_env(region=region, base_url=base_url, debug=debug),
|
|
169
196
|
error_handling=ErrorHandlingConfig.from_env(),
|
|
170
197
|
telemetry=TelemetryConfig.from_env(),
|
|
171
198
|
environment=Environment.DEBUG if debug else Environment.PRODUCTION,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
lucidicai/__init__.py,sha256=
|
|
1
|
+
lucidicai/__init__.py,sha256=Dur2YTPgHbjFM09QQ36SHOHE0B62uFb5dIUHKo4oy7g,1284
|
|
2
2
|
lucidicai/action.py,sha256=sPRd1hTIVXDqnvG9ZXWEipUFh0bsXcE0Fm7RVqmVccM,237
|
|
3
|
-
lucidicai/client.py,sha256=
|
|
3
|
+
lucidicai/client.py,sha256=BGKP91_Oj5kHQU0osYf1T_BWakL8KIhs0AgUc5X99sU,15104
|
|
4
4
|
lucidicai/constants.py,sha256=zN8O7TjoRHRlaGa9CZUWppS73rhzKGwaEkF9XMTV0Cg,1160
|
|
5
5
|
lucidicai/context.py,sha256=ruEXAndSv0gQ-YEXLlC4Fx6NNbaylfp_dZxbpwmLZSA,4622
|
|
6
6
|
lucidicai/dataset.py,sha256=wu25X02JyWkht_yQabgQpGZFfzbNTxG6tf5k9ol8Amo,4005
|
|
@@ -26,10 +26,10 @@ lucidicai/api/resources/evals.py,sha256=_3nLE6dMLht844mWw7kl_hctjv5JIuC6MP06YWUg
|
|
|
26
26
|
lucidicai/api/resources/event.py,sha256=GTIU5sIbLNTWAHk4rB120xWTRkhnraz9JNfamEygyNo,14267
|
|
27
27
|
lucidicai/api/resources/experiment.py,sha256=fOIKJ5d89bHJBVZ3wjbhY_6XF3kLHz9TE3BVPA5pNpA,3563
|
|
28
28
|
lucidicai/api/resources/feature_flag.py,sha256=ii412DIkZCEAhrXdGydcpQKveqGlFq4NlgdmWQnU83c,2259
|
|
29
|
-
lucidicai/api/resources/prompt.py,sha256=
|
|
29
|
+
lucidicai/api/resources/prompt.py,sha256=5pIV3vTfOQkovQpINohDVseY678E04CWz2E5V4NA-i8,4625
|
|
30
30
|
lucidicai/api/resources/session.py,sha256=jW_bftHdunhLHl_3-k0nqB5FrtLhlFeCF0tMFE82nNw,20761
|
|
31
31
|
lucidicai/core/__init__.py,sha256=b0YQkd8190Y_GgwUcmf0tOiSLARd7L4kq4jwfhhGAyI,39
|
|
32
|
-
lucidicai/core/config.py,sha256=
|
|
32
|
+
lucidicai/core/config.py,sha256=q4h-yR35Ay_3znL7vavri6ScfeM69RjHShNNzjoQthc,10194
|
|
33
33
|
lucidicai/core/errors.py,sha256=bYSRPqadXUCPadVLb-2fj63CB6jlAnfDeu2azHB2z8M,2137
|
|
34
34
|
lucidicai/core/types.py,sha256=KabcTBQe7SemigccKfJSDiJmjSJDJJvvtefSd8pfrJI,702
|
|
35
35
|
lucidicai/integrations/__init__.py,sha256=9eJxdcw9C_zLXLQGdKK-uwCYhjdnEelrXbYYNo48ewk,292
|
|
@@ -93,7 +93,7 @@ lucidicai/utils/images.py,sha256=z8mlIKgFfrIbuk-l4L2rB62uw_uPO79sHPXPY7eLu2A,128
|
|
|
93
93
|
lucidicai/utils/logger.py,sha256=R3B3gSee64F6UVHUrShihBq_O7W7bgfrBiVDXTO3Isg,4777
|
|
94
94
|
lucidicai/utils/queue.py,sha256=8DQwnGw7pINEJ0dNSkB0PhdPW-iBQQ-YZg23poe4umE,17323
|
|
95
95
|
lucidicai/utils/serialization.py,sha256=KdOREZd7XBxFBAZ86DePMfYPzSVyKr4RcgUa82aFxrs,820
|
|
96
|
-
lucidicai-3.
|
|
97
|
-
lucidicai-3.
|
|
98
|
-
lucidicai-3.
|
|
99
|
-
lucidicai-3.
|
|
96
|
+
lucidicai-3.3.1.dist-info/METADATA,sha256=-VsGzxsuN4ux1cLJN6jcbEO2cOv2G756BdsAWY8uiio,902
|
|
97
|
+
lucidicai-3.3.1.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
|
|
98
|
+
lucidicai-3.3.1.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
|
|
99
|
+
lucidicai-3.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|