langwatch 0.9.0__py3-none-any.whl → 0.10.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.
@@ -8,6 +8,7 @@ or when API is unavailable.
8
8
 
9
9
  Follows the facade pattern to coordinate between LocalPromptLoader and PromptApiService.
10
10
  """
11
+ from pathlib import Path
11
12
  from typing import Any, Dict, List, Literal, Optional
12
13
  import time
13
14
  from langwatch.generated.langwatch_rest_api_client.client import (
@@ -35,10 +36,16 @@ class PromptsFacade:
35
36
  work even when offline or when API is unavailable.
36
37
  """
37
38
 
38
- def __init__(self, rest_api_client: LangWatchRestApiClient):
39
+ def __init__(
40
+ self,
41
+ rest_api_client: LangWatchRestApiClient,
42
+ prompts_path: Optional[str] = None,
43
+ ):
39
44
  """Initialize the prompt service facade with dependencies."""
40
45
  self._api_service = PromptApiService(rest_api_client)
41
- self._local_loader = LocalPromptLoader()
46
+ self._local_loader = LocalPromptLoader(
47
+ base_path=Path(prompts_path) if prompts_path else None
48
+ )
42
49
  self._cache: Dict[str, Dict[str, Any]] = {}
43
50
 
44
51
  @classmethod
@@ -50,7 +57,7 @@ class PromptsFacade:
50
57
  raise RuntimeError(
51
58
  "LangWatch client has not been initialized. Call setup() first."
52
59
  )
53
- return cls(instance.rest_api_client)
60
+ return cls(instance.rest_api_client, prompts_path=instance.prompts_path)
54
61
 
55
62
  def get(
56
63
  self,
langwatch/types.py CHANGED
@@ -89,6 +89,11 @@ class LangWatchClientProtocol(Protocol):
89
89
  """Get whether OpenTelemetry setup is skipped."""
90
90
  ...
91
91
 
92
+ @property
93
+ def prompts_path(self) -> Optional[str]:
94
+ """Get the base path for local prompt files."""
95
+ ...
96
+
92
97
  # Regular attributes (not properties)
93
98
  base_attributes: BaseAttributes
94
99
  tracer_provider: Optional[TracerProvider]
@@ -3,14 +3,16 @@
3
3
  import logging
4
4
  import os
5
5
  import sys
6
+ from pathlib import Path
6
7
  from typing import List, Optional, Sequence
7
- from opentelemetry.sdk.trace import TracerProvider
8
+
8
9
  from opentelemetry import trace
9
10
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
11
+ from opentelemetry.sdk.trace import TracerProvider
10
12
 
11
- from langwatch.state import get_instance, set_instance
12
13
  from langwatch.client import Client
13
14
  from langwatch.domain import BaseAttributes, SpanProcessingExcludeRule
15
+ from langwatch.state import get_instance, set_instance
14
16
 
15
17
  logger: logging.Logger = logging.getLogger(__name__)
16
18
 
@@ -41,6 +43,7 @@ def setup(
41
43
  span_exclude_rules: Optional[List[SpanProcessingExcludeRule]] = None,
42
44
  debug: Optional[bool] = None,
43
45
  skip_open_telemetry_setup: Optional[bool] = None,
46
+ prompts_path: Optional[str] = None,
44
47
  ) -> Client:
45
48
  """
46
49
  Initialize the LangWatch client.
@@ -54,6 +57,7 @@ def setup(
54
57
  span_exclude_rules: Optional. A list of rules that will be applied to spans processed by the exporter.
55
58
  debug: Whether to enable debug logging for the LangWatch client.
56
59
  skip_open_telemetry_setup: Whether to skip setting up the OpenTelemetry tracer provider. If this is skipped, instrumentors will be added to the global tracer provider.
60
+ prompts_path: The base path for local prompt files. If not set, defaults to the current working directory.
57
61
  Returns:
58
62
  The LangWatch client.
59
63
  """
@@ -62,6 +66,11 @@ def setup(
62
66
  if debug:
63
67
  logger.info("Setting up LangWatch client...")
64
68
 
69
+ if prompts_path is not None:
70
+ prompts_path = str(
71
+ Path(prompts_path).resolve()
72
+ ) # Convert to absolute path asap
73
+
65
74
  # Get existing client to check if we're changing the API key
66
75
  existing_client = get_instance()
67
76
  changed_api_key = False
@@ -87,6 +96,7 @@ def setup(
87
96
  span_exclude_rules=span_exclude_rules,
88
97
  ignore_global_tracer_provider_override_warning=changed_api_key,
89
98
  skip_open_telemetry_setup=skip_open_telemetry_setup,
99
+ prompts_path=prompts_path,
90
100
  )
91
101
 
92
102
  if debug:
langwatch/utils/utils.py CHANGED
@@ -5,9 +5,11 @@ from pydantic import BaseModel
5
5
 
6
6
  def safe_get(d: Union[Dict[str, Any], BaseModel], *keys: str) -> Optional[Any]:
7
7
  for key in keys:
8
+ if d is None:
9
+ return None
8
10
  if isinstance(d, dict):
9
11
  d = d.get(key, None)
10
- if hasattr(d, key):
12
+ elif hasattr(d, key):
11
13
  d = getattr(d, key)
12
14
  else:
13
15
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langwatch
3
- Version: 0.9.0
3
+ Version: 0.10.1
4
4
  Summary: LangWatch Python SDK, for monitoring your LLMs
5
5
  Author-email: Langwatch Engineers <engineering@langwatch.ai>
6
6
  License: MIT
@@ -1,24 +1,25 @@
1
- langwatch/__init__.py,sha256=GMq4SV2Tz2i0JD05shqnw2lBW5cgMx4Zzo141hp106k,4266
2
- langwatch/__version__.py,sha256=sympc_lD0EH1ffjgsP80P8i4Sqm2XBcIgblEeQTq6bs,91
1
+ langwatch/__init__.py,sha256=VGkLDw3h8hOtzyaTMObWupGTQosn4E17Dk5zcfDmy7g,4462
2
+ langwatch/__version__.py,sha256=96vdgjIvZZ7XbIP2U10ynaU8nnbGmXfLBXugfC_8r3Q,92
3
3
  langwatch/attributes.py,sha256=nXdI_G85wQQCAdAcwjCiLYdEYj3wATmfgCmhlf6dVIk,3910
4
4
  langwatch/batch_evaluation.py,sha256=Y_S3teXpHV07U-vvJYyV1PB6d0CgyFM_rTzPp6GnEBo,16165
5
- langwatch/client.py,sha256=WTNcYSik7kZ2kH-qGDnhbMTosc8e_Xhab_lZlfh5TC8,25559
6
- langwatch/evaluations.py,sha256=W-nxhcbQ4Niyx949LjHjTehw74pj31dUVs5rjkQUBLo,16951
5
+ langwatch/client.py,sha256=xwqvTnbAZ-Qr8OnI8-D8cV3J7YPsJ6l0trHbd2PSi6Q,26148
6
+ langwatch/evaluations.py,sha256=-rvlpw8J3-0lMn9tdnte1Z3qHpuE60DGB3gmI8VMexQ,8983
7
7
  langwatch/guardrails.py,sha256=4d320HyklXPUVszF34aWsDKGzuvPggcDM_f45_eJTnc,1352
8
8
  langwatch/langchain.py,sha256=HjbBBIDwwt688g0W4K0EsZGuGBbo1Mv5LQ-7Mkn56iQ,18726
9
- langwatch/litellm.py,sha256=mPcw5cLykt0SQf9bTNSoT7elMx4gj-wZ_K2PC14Bw50,11998
9
+ langwatch/litellm.py,sha256=v2fXvsdvqRdSLVwTKNBbiJJy9YJvV9M9OSnugIMvNtg,12328
10
10
  langwatch/login.py,sha256=o0DxYVMhMCRHeopyF0qlj_U4o6yD1rL8QjfKvKnHv0s,965
11
- langwatch/openai.py,sha256=h_NCIwJ0qs57PS-R7gQZsnf2_EBAahlYQMuqS9-Cj3Q,25139
11
+ langwatch/openai.py,sha256=UnfZtskUSvpnZUA-2CHpP3iRjrG3DmDQ1Xftuos6JMk,25724
12
12
  langwatch/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  langwatch/state.py,sha256=qXvPAjO90jdokCU6tPSwjHIac4QU_5N0pSd9dfmc9kY,1204
14
14
  langwatch/tracer.py,sha256=t5FOdP1es9H_pPGqGUBLXCyEln0tTi4m4M9b6WxCrPU,975
15
- langwatch/types.py,sha256=h6r3tNTzWqENx-9j_JPmOMZfFoKq9SNpEtxpAACk2G0,3114
15
+ langwatch/types.py,sha256=HtnfmGc3p6k7rLitnJsf3MOXZfvjyZ8soB74kPyoCGY,3242
16
16
  langwatch/dataset/__init__.py,sha256=hZBcbjXuBO2qE5osJtd9wIE9f45F6-jpNTrne5nk4eE,2606
17
- langwatch/domain/__init__.py,sha256=gSCOV3WkRhp_--9D1vxw7BYpnMRbpGh-2NbsXd4KZC0,6074
18
- langwatch/dspy/__init__.py,sha256=wp8AmobV8XGVWOI8MQFmXPHu-8Wq3wvjB6YiHQm9Fdg,33007
19
- langwatch/evaluation/__init__.py,sha256=dctG-Ec0N_Or2Ta0XW6liYtdpMZN3ZtRXqUoeG5ksnk,870
20
- langwatch/evaluation/evaluation.py,sha256=MqMiGlsPIS5zqN1wKfhEs6mIGLRwB452iqDTSQFbtYo,31735
21
- langwatch/evaluation/platform_run.py,sha256=cwuRNtG99nhvqGL-YoOwdvEH3x-hDaVUzl7Vx9orjPo,14546
17
+ langwatch/domain/__init__.py,sha256=BVpWugFqiohIA2MiTZy3x1BQCbIgN3okIXzmT6BHUkQ,6183
18
+ langwatch/dspy/__init__.py,sha256=ahOMnNefVD9xsf7Z0P6iE0SbKylANixrNZkbKoK2FTs,35208
19
+ langwatch/evaluation/__init__.py,sha256=8SOSZZbSzXa1jL-9Zlyt0f9u5sOA_TrO1J61ueASBLI,16980
20
+ langwatch/experiment/__init__.py,sha256=nv2OfoNMMZwUA9KfozW2ZNaR1-J1LCmU4NykjGfe9is,3001
21
+ langwatch/experiment/experiment.py,sha256=5xj58FKVC0y_LxgfwjJZP9lDp7tZ9FUUbERBtui_nC8,33026
22
+ langwatch/experiment/platform_run.py,sha256=qiy_bwp786TbkH4HIlZVlJPmCtQlStAq9vUdG4-3VdU,13850
22
23
  langwatch/exporters/filterable_batch_span_exporter.py,sha256=MlhZjui56XD6p2sa8kEGyr-Hb3wqudknngmemnB4Twg,2142
23
24
  langwatch/generated/langwatch_rest_api_client/__init__.py,sha256=8r-9pAj7fK7vnVX3mT0y_zS4B9ZRqD6RZiBo5fPra60,156
24
25
  langwatch/generated/langwatch_rest_api_client/client.py,sha256=o_mdLqyBCQstu5tS1WZFwqIEbGwkvWQ7eQjuCJw_5VY,12419
@@ -393,10 +394,10 @@ langwatch/generated/langwatch_rest_api_client/models/timestamps.py,sha256=-nRKUP
393
394
  langwatch/generated/langwatch_rest_api_client/models/trace.py,sha256=K9Lc_EQOrJ2dqMXx9EpiUXReT1_uYF7WRfYyhlfbi3I,7537
394
395
  langwatch/prompts/__init__.py,sha256=OGf3BrzVsTZnSPYSqSqe_eWmGIBRiOUlovOduYzKCx4,1259
395
396
  langwatch/prompts/errors.py,sha256=kmaGeA1QPot9Ii5lgooxmAFlvUPOGjAnzzPBuw4h6Bw,5124
396
- langwatch/prompts/local_loader.py,sha256=luvk39Kc4S-x4lBSms-AoWqg0Im_Uu-Lcpt3cRJFmdY,6774
397
+ langwatch/prompts/local_loader.py,sha256=DifYVaAIdEdsApChPIEx0zsYinNixJoPgi8s0zy1MNY,7490
397
398
  langwatch/prompts/prompt.py,sha256=SgLDo9hO-CuRE-AZ8zx9v7-KqjiabiW8GzD9jdx1IoA,6914
398
399
  langwatch/prompts/prompt_api_service.py,sha256=tHhwIRjUBSM43_jwDAoGCHJjvvqVeSCrUPwcwMvUHho,9823
399
- langwatch/prompts/prompt_facade.py,sha256=fc16TB4ZBhKpwXVx9SNTJxLvQVms4eu4w0ZOH4Kk55w,8950
400
+ langwatch/prompts/prompt_facade.py,sha256=yUq9-5JHcHrgiz9EgijzNXp_KkK6ZUouoGtEtF4_xdE,9154
400
401
  langwatch/prompts/decorators/prompt_service_tracing.py,sha256=uSYw0vExo7AuxbcCRnxbYl6UOfOQSC0IsisSqYy153Y,2395
401
402
  langwatch/prompts/decorators/prompt_tracing.py,sha256=x_PQvJlGbGF1h2HtGNiqaZ8K1qNd1jRf5pTOBTQx-7M,3963
402
403
  langwatch/prompts/types/__init__.py,sha256=jwaFV4VJHrOE6dm6yyLtWk6_7dqZpR5uZjN1cswtga4,579
@@ -412,10 +413,10 @@ langwatch/telemetry/__tests__/test_tracing.py,sha256=Px2vcpbRWBgwwaXzw3MgRfkcL-I
412
413
  langwatch/utils/__init__.py,sha256=3rqQTgzEtmICJW_KSPuLa5q8p5udxt5SRi28Z2vZB10,138
413
414
  langwatch/utils/capture.py,sha256=uVKPqHCm-o8CpabsUfhqbNFr5sgUHzcKnBadvL2oIwI,1172
414
415
  langwatch/utils/exceptions.py,sha256=b-dorrnQ9XBJcijLLNJP9LRQzdOZGEiyQ3f8GcA1kgk,1046
415
- langwatch/utils/initialization.py,sha256=1KoZmkHOvGEVF0j-4t4xRQdA_2C_SPiF7qFXqEG4Nkw,4553
416
+ langwatch/utils/initialization.py,sha256=2egw2aXGYdbgLsyOfkQ3Oz0JFbfnQnpiFg_Q-gcoEgo,4915
416
417
  langwatch/utils/module.py,sha256=KLBNOK3mA9gCSifCcQX_lOtU48BJQDWvFKtF6NMvwVA,688
417
418
  langwatch/utils/transformation.py,sha256=76MGXyrYTxM0Yri36NJqLK-XxL4BBYdmKWAXXlw3D4Q,7690
418
- langwatch/utils/utils.py,sha256=ZCOSie4o9LdJ7odshNfCNjmgwgQ27ojc5ENqt1rXuSs,596
419
- langwatch-0.9.0.dist-info/METADATA,sha256=JtLLtVbyy0iau3ySelLpMO4RpjrQAEyhd72J9NkxHl8,13192
420
- langwatch-0.9.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
421
- langwatch-0.9.0.dist-info/RECORD,,
419
+ langwatch/utils/utils.py,sha256=RW01NPA_cpWsTlUvLd0FGuoVECtMVO9Bj4gdIVx8fUg,644
420
+ langwatch-0.10.1.dist-info/METADATA,sha256=KjaQMj1Rk2spt7K6_UFEb2BNY6KraJVzvcCX7Qvwqfw,13193
421
+ langwatch-0.10.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
422
+ langwatch-0.10.1.dist-info/RECORD,,