41
41
42
42
from typing_extensions import ParamSpec , TypeGuard , get_args , get_origin
43
43
44
+ import langsmith ._internal ._context as _context
44
45
from langsmith import client as ls_client
45
46
from langsmith import run_trees , schemas , utils
46
47
from langsmith ._internal import _aiter as aitertools
53
54
from langchain_core .runnables import Runnable
54
55
55
56
LOGGER = logging .getLogger (__name__ )
56
- _PARENT_RUN_TREE = contextvars .ContextVar [Optional [run_trees .RunTree ]](
57
- "_PARENT_RUN_TREE" , default = None
58
- )
59
- _PROJECT_NAME = contextvars .ContextVar [Optional [str ]]("_PROJECT_NAME" , default = None )
60
- _TAGS = contextvars .ContextVar [Optional [list [str ]]]("_TAGS" , default = None )
61
- _METADATA = contextvars .ContextVar [Optional [dict [str , Any ]]]("_METADATA" , default = None )
62
-
63
-
64
- _TRACING_ENABLED = contextvars .ContextVar [Optional [Union [bool , Literal ["local" ]]]](
65
- "_TRACING_ENABLED" , default = None
66
- )
67
- _CLIENT = contextvars .ContextVar [Optional [ls_client .Client ]]("_CLIENT" , default = None )
68
57
_CONTEXT_KEYS : dict [str , contextvars .ContextVar ] = {
69
- "parent" : _PARENT_RUN_TREE ,
70
- "project_name" : _PROJECT_NAME ,
71
- "tags" : _TAGS ,
72
- "metadata" : _METADATA ,
73
- "enabled" : _TRACING_ENABLED ,
74
- "client" : _CLIENT ,
58
+ "parent" : _context . _PARENT_RUN_TREE ,
59
+ "project_name" : _context . _PROJECT_NAME ,
60
+ "tags" : _context . _TAGS ,
61
+ "metadata" : _context . _METADATA ,
62
+ "enabled" : _context . _TRACING_ENABLED ,
63
+ "client" : _context . _CLIENT ,
75
64
"replicas" : run_trees ._REPLICAS ,
76
65
"distributed_parent_id" : run_trees ._DISTRIBUTED_PARENT_ID ,
77
66
}
83
72
84
73
def get_current_run_tree () -> Optional [run_trees .RunTree ]:
85
74
"""Get the current run tree."""
86
- return _PARENT_RUN_TREE .get ()
75
+ return _context . _PARENT_RUN_TREE .get ()
87
76
88
77
89
78
def get_tracing_context (
@@ -92,12 +81,12 @@ def get_tracing_context(
92
81
"""Get the current tracing context."""
93
82
if context is None :
94
83
return {
95
- "parent" : _PARENT_RUN_TREE .get (),
96
- "project_name" : _PROJECT_NAME .get (),
97
- "tags" : _TAGS .get (),
98
- "metadata" : _METADATA .get (),
99
- "enabled" : _TRACING_ENABLED .get (),
100
- "client" : _CLIENT .get (),
84
+ "parent" : _context . _PARENT_RUN_TREE .get (),
85
+ "project_name" : _context . _PROJECT_NAME .get (),
86
+ "tags" : _context . _TAGS .get (),
87
+ "metadata" : _context . _METADATA .get (),
88
+ "enabled" : _context . _TRACING_ENABLED .get (),
89
+ "client" : _context . _CLIENT .get (),
101
90
"replicas" : run_trees ._REPLICAS .get (),
102
91
"distributed_parent_id" : run_trees ._DISTRIBUTED_PARENT_ID .get (),
103
92
}
@@ -995,8 +984,8 @@ def _setup(self) -> run_trees.RunTree:
995
984
self .old_ctx = get_tracing_context ()
996
985
enabled = utils .tracing_is_enabled (self .old_ctx )
997
986
998
- outer_tags = _TAGS .get ()
999
- outer_metadata = _METADATA .get ()
987
+ outer_tags = _context . _TAGS .get () or _context . _GLOBAL_TAGS
988
+ outer_metadata = _context . _METADATA .get () or _context . _GLOBAL_METADATA
1000
989
client_ = self .client or self .old_ctx .get ("client" )
1001
990
parent_run_ = _get_parent_run (
1002
991
{
@@ -1049,11 +1038,11 @@ def _setup(self) -> run_trees.RunTree:
1049
1038
if enabled is True :
1050
1039
self .new_run .post ()
1051
1040
if enabled :
1052
- _TAGS .set (tags_ )
1053
- _METADATA .set (metadata )
1054
- _PARENT_RUN_TREE .set (self .new_run )
1055
- _PROJECT_NAME .set (project_name_ )
1056
- _CLIENT .set (client_ )
1041
+ _context . _TAGS .set (tags_ )
1042
+ _context . _METADATA .set (metadata )
1043
+ _context . _PARENT_RUN_TREE .set (self .new_run )
1044
+ _context . _PROJECT_NAME .set (project_name_ )
1045
+ _context . _CLIENT .set (client_ )
1057
1046
1058
1047
return self .new_run
1059
1048
@@ -1161,8 +1150,10 @@ def _get_project_name(project_name: Optional[str]) -> Optional[str]:
1161
1150
prt = _PARENT_RUN_TREE .get ()
1162
1151
return (
1163
1152
# Maintain tree consistency first
1164
- _PROJECT_NAME .get ()
1153
+ _context . _PROJECT_NAME .get ()
1165
1154
or (prt .session_name if prt else None )
1155
+ # Global fallback configured via ls.configure(...)
1156
+ or _context ._GLOBAL_PROJECT_NAME
1166
1157
# fallback to the default for the environment
1167
1158
or utils .get_tracer_project ()
1168
1159
)
@@ -1453,21 +1444,22 @@ def _setup_run(
1453
1444
dangerously_allow_filesystem = container_input .get (
1454
1445
"dangerously_allow_filesystem" , False
1455
1446
)
1456
- outer_project = _PROJECT_NAME .get ()
1447
+ outer_project = _context . _PROJECT_NAME .get ()
1457
1448
langsmith_extra = langsmith_extra or LangSmithExtra ()
1458
1449
name = langsmith_extra .get ("name" ) or container_input .get ("name" )
1459
- client_ = langsmith_extra .get ("client" , client ) or _CLIENT .get ()
1450
+ client_ = langsmith_extra .get ("client" , client ) or _context . _CLIENT .get ()
1460
1451
parent_run_ = _get_parent_run (
1461
1452
{** langsmith_extra , "client" : client_ }, kwargs .get ("config" )
1462
1453
)
1463
- project_cv = _PROJECT_NAME .get ()
1454
+ project_cv = _context . _PROJECT_NAME .get ()
1464
1455
selected_project = (
1465
1456
project_cv # From parent trace
1466
1457
or (
1467
1458
parent_run_ .session_name if parent_run_ else None
1468
1459
) # from parent run attempt 2 (not managed by traceable)
1469
1460
or langsmith_extra .get ("project_name" ) # at invocation time
1470
1461
or container_input ["project_name" ] # at decorator time
1462
+ or _context ._GLOBAL_PROJECT_NAME # global fallback from ls.configure
1471
1463
or utils .get_tracer_project () # default
1472
1464
)
1473
1465
reference_example_id = langsmith_extra .get ("reference_example_id" )
@@ -1492,14 +1484,14 @@ def _setup_run(
1492
1484
signature = inspect .signature (func )
1493
1485
name_ = name or utils ._get_function_name (func )
1494
1486
extra_inner = _collect_extra (extra_outer , langsmith_extra )
1495
- outer_metadata = _METADATA .get ()
1496
- outer_tags = _TAGS .get ()
1487
+ outer_metadata = _context . _METADATA .get () or _context . _GLOBAL_METADATA
1488
+ outer_tags = _context . _TAGS .get () or _context . _GLOBAL_TAGS
1497
1489
context = copy_context ()
1498
1490
metadata_ = {
1499
1491
** (langsmith_extra .get ("metadata" ) or {}),
1500
1492
** (outer_metadata or {}),
1501
1493
}
1502
- context .run (_METADATA .set , metadata_ )
1494
+ context .run (_context . _METADATA .set , metadata_ )
1503
1495
metadata_ .update (metadata or {})
1504
1496
metadata_ ["ls_method" ] = "traceable"
1505
1497
extra_inner ["metadata" ] = metadata_
@@ -1523,7 +1515,7 @@ def _setup_run(
1523
1515
except BaseException as e :
1524
1516
LOGGER .error (f"Failed to filter inputs for { name_ } : { e } " )
1525
1517
tags_ = (langsmith_extra .get ("tags" ) or []) + (outer_tags or [])
1526
- context .run (_TAGS .set , tags_ )
1518
+ context .run (_context . _TAGS .set , tags_ )
1527
1519
tags_ += tags or []
1528
1520
if parent_run_ is not None :
1529
1521
new_run = parent_run_ .create_child (
@@ -1568,7 +1560,7 @@ def _setup_run(
1568
1560
context = context ,
1569
1561
_token_event_logged = False ,
1570
1562
)
1571
- context .run (_PROJECT_NAME .set , response_container ["project_name" ])
1563
+ context .run (_context . _PROJECT_NAME .set , response_container ["project_name" ])
1572
1564
context .run (_PARENT_RUN_TREE .set , response_container ["new_run" ])
1573
1565
return response_container
1574
1566
@@ -2081,3 +2073,12 @@ def _maybe_create_otel_context(run_tree: Optional[run_trees.RunTree]):
2081
2073
2082
2074
non_recording_span = NonRecordingSpan (span_context )
2083
2075
return use_span (non_recording_span )
2076
+
2077
+
2078
+ # For backwards compatibility
2079
+ _PROJECT_NAME = _context ._PROJECT_NAME
2080
+ _TAGS = _context ._TAGS
2081
+ _METADATA = _context ._METADATA
2082
+ _TRACING_ENABLED = _context ._TRACING_ENABLED
2083
+ _CLIENT = _context ._CLIENT
2084
+ _PARENT_RUN_TREE = _context ._PARENT_RUN_TREE
0 commit comments