Skip to content

Commit 2f34092

Browse files
committed
todo clarifty case sensitivity
1 parent c1bd882 commit 2f34092

File tree

2 files changed

+71
-64
lines changed

2 files changed

+71
-64
lines changed

langfuse/_client/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ def start_as_current_span(
355355
level: Optional[SpanLevel] = None,
356356
status_message: Optional[str] = None,
357357
end_on_exit: Optional[bool] = None,
358-
as_type: Optional[Literal["generation", "span", "event", "agent", "tool", "chain", "retriever"]] = None,
358+
as_type: Optional[Literal["generation", "span", "GENERATION", "EVENT", "SPAN", "AGENT", "TOOL", "CHAIN", "RETRIEVER", "EMBEDDING"]],
359359
) -> _AgnosticContextManager[LangfuseSpan]:
360360
"""Create a new span and set it as the current span in a context manager.
361361

langfuse/_client/observe.py

Lines changed: 70 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@ def sub_process():
182182
- For async functions, the decorator returns an async function wrapper.
183183
- For sync functions, the decorator returns a synchronous wrapper.
184184
"""
185+
if as_type is not None and type is not None:
186+
raise ValueError(
187+
"Cannot specify both 'as_type' and 'type' parameters. Please use only one of them."
188+
)
185189
if type is not None and type not in VALID_OBSERVATION_TYPES:
186190
raise ValueError(
187191
f"Invalid observation type '{type}'. Valid types are: {', '.join(sorted(VALID_OBSERVATION_TYPES))}"
@@ -210,14 +214,14 @@ def sub_process():
210214
)
211215

212216
def decorator(func: F) -> F:
213-
# Merge as_type and type parameters - type takes precedence for graph observations
214-
final_as_type = type or as_type
217+
# TODO: merge smartly with manually set as_type
218+
consolidated_type = type or as_type
215219

216220
return (
217221
self._async_observe(
218222
func,
219223
name=name,
220-
as_type=final_as_type,
224+
as_type=consolidated_type,
221225
capture_input=should_capture_input,
222226
capture_output=should_capture_output,
223227
transform_to_string=transform_to_string,
@@ -226,7 +230,7 @@ def decorator(func: F) -> F:
226230
else self._sync_observe(
227231
func,
228232
name=name,
229-
as_type=final_as_type,
233+
as_type=consolidated_type,
230234
capture_input=should_capture_input,
231235
capture_output=should_capture_output,
232236
transform_to_string=transform_to_string,
@@ -253,7 +257,7 @@ def _async_observe(
253257
func: F,
254258
*,
255259
name: Optional[str],
256-
as_type: Optional[str],
260+
as_type: Optional[Literal["generation", "GENERATION", "EVENT", "SPAN", "AGENT", "TOOL", "CHAIN", "RETRIEVER", "EMBEDDING"]],
257261
capture_input: bool,
258262
capture_output: bool,
259263
transform_to_string: Optional[Callable[[Iterable], str]] = None,
@@ -283,77 +287,80 @@ async def async_wrapper(*args: Tuple[Any], **kwargs: Dict[str, Any]) -> Any:
283287
else None
284288
)
285289
public_key = cast(str, kwargs.pop("langfuse_public_key", None))
286-
langfuse_client = get_client(public_key=public_key)
287290

288-
# Use consolidated as_type parameter
289-
final_obs_type = as_type
290-
291-
context_manager: Optional[
292-
Union[
293-
_AgnosticContextManager[LangfuseGeneration],
294-
_AgnosticContextManager[LangfuseSpan],
295-
]
296-
] = (
297-
(
298-
langfuse_client.start_as_current_generation(
299-
name=final_name,
300-
trace_context=trace_context,
301-
input=input,
302-
end_on_exit=False, # when returning a generator, closing on exit would be to early
303-
)
304-
if final_obs_type in ("generation", "GENERATION")
305-
else langfuse_client.start_as_current_span(
306-
name=final_name,
307-
trace_context=trace_context,
308-
input=input,
309-
end_on_exit=False, # when returning a generator, closing on exit would be to early
310-
as_type=final_obs_type,
291+
# Set public key in execution context for nested decorated functions
292+
with _set_current_public_key(public_key):
293+
langfuse_client = get_client(public_key=public_key)
294+
295+
# Use consolidated as_type parameter
296+
final_obs_type = as_type
297+
298+
context_manager: Optional[
299+
Union[
300+
_AgnosticContextManager[LangfuseGeneration],
301+
_AgnosticContextManager[LangfuseSpan],
302+
]
303+
] = (
304+
(
305+
langfuse_client.start_as_current_generation(
306+
name=final_name,
307+
trace_context=trace_context,
308+
input=input,
309+
end_on_exit=False, # when returning a generator, closing on exit would be to early
310+
)
311+
if final_obs_type in ("generation", "GENERATION")
312+
else langfuse_client.start_as_current_span(
313+
name=final_name,
314+
trace_context=trace_context,
315+
input=input,
316+
end_on_exit=False, # when returning a generator, closing on exit would be to early
317+
as_type=final_obs_type,
318+
)
311319
)
320+
if langfuse_client
321+
else None
312322
)
313-
if langfuse_client
314-
else None
315-
)
316323

317-
if context_manager is None:
318-
return await func(*args, **kwargs)
324+
if context_manager is None:
325+
return await func(*args, **kwargs)
319326

320-
with context_manager as langfuse_span_or_generation:
321-
is_return_type_generator = False
327+
with context_manager as langfuse_span_or_generation:
328+
is_return_type_generator = False
322329

323-
try:
324-
result = await func(*args, **kwargs)
330+
try:
331+
result = await func(*args, **kwargs)
325332

326-
if capture_output is True:
327-
if inspect.isgenerator(result):
328-
is_return_type_generator = True
333+
if capture_output is True:
334+
if inspect.isgenerator(result):
335+
is_return_type_generator = True
329336

330-
return self._wrap_sync_generator_result(
331-
langfuse_span_or_generation,
332-
result,
333-
transform_to_string,
334-
)
337+
return self._wrap_sync_generator_result(
338+
langfuse_span_or_generation,
339+
result,
340+
transform_to_string,
341+
)
335342

336-
if inspect.isasyncgen(result):
337-
is_return_type_generator = True
343+
if inspect.isasyncgen(result):
344+
is_return_type_generator = True
338345

339-
return self._wrap_async_generator_result(
340-
langfuse_span_or_generation,
341-
result,
342-
transform_to_string,
343-
)
346+
return self._wrap_async_generator_result(
347+
langfuse_span_or_generation,
348+
result,
349+
transform_to_string,
350+
)
344351

345-
langfuse_span_or_generation.update(output=result)
352+
langfuse_span_or_generation.update(output=result)
346353

347-
return result
348-
except Exception as e:
349-
langfuse_span_or_generation.update(
350-
level="ERROR", status_message=str(e)
351-
)
354+
return result
355+
except Exception as e:
356+
langfuse_span_or_generation.update(
357+
level="ERROR", status_message=str(e)
358+
)
352359

353-
raise e
354-
finally:
355-
if not is_return_type_generator:
356-
langfuse_span_or_generation.end()
360+
raise e
361+
finally:
362+
if not is_return_type_generator:
363+
langfuse_span_or_generation.end()
357364

358365
return cast(F, async_wrapper)
359366

0 commit comments

Comments
 (0)