Skip to content

Commit ab78ce2

Browse files
author
Andrei Bratu
committed
simplify decorators
1 parent ce96aaf commit ab78ce2

File tree

14 files changed

+242
-1285
lines changed

14 files changed

+242
-1285
lines changed

src/humanloop/client.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
from contextlib import contextmanager
12
import os
23
import typing
3-
from typing import List, Optional, Sequence
4-
from typing_extensions import Unpack
4+
from typing import Any, List, Optional, Sequence
55

66
import httpx
77
from opentelemetry.sdk.resources import Resource
@@ -10,7 +10,6 @@
1010

1111
from humanloop.core.client_wrapper import SyncClientWrapper
1212
from humanloop.eval_utils.run import prompt_call_evaluation_aware
13-
from humanloop.utilities.types import DecoratorPromptKernelRequestParams
1413

1514
from humanloop.eval_utils import log_with_evaluation_context, run_eval
1615
from humanloop.eval_utils.types import Dataset, Evaluator, EvaluatorCheck, File
@@ -147,11 +146,11 @@ def __init__(
147146
else:
148147
self._opentelemetry_tracer = opentelemetry_tracer
149148

149+
@contextmanager
150150
def prompt(
151151
self,
152152
*,
153-
path: Optional[str] = None,
154-
**prompt_kernel: Unpack[DecoratorPromptKernelRequestParams], # type: ignore
153+
path: str,
155154
):
156155
"""Decorator for declaring a [Prompt](https://humanloop.com/docs/explanation/prompts) in code.
157156
@@ -226,17 +225,14 @@ def call_llm(messages):
226225
227226
:param prompt_kernel: Attributes that define the Prompt. See `class:DecoratorPromptKernelRequestParams`
228227
"""
229-
return prompt_decorator_factory(
230-
opentelemetry_tracer=self._opentelemetry_tracer,
231-
path=path,
232-
**prompt_kernel,
233-
)
228+
return prompt_decorator_factory(path=path)
234229

235230
def tool(
236231
self,
237232
*,
238-
path: Optional[str] = None,
239-
**tool_kernel: Unpack[ToolKernelRequestParams], # type: ignore
233+
path: str,
234+
attributes: dict[str, Any] | None = None,
235+
setup_values: dict[str, Any] | None = None,
240236
):
241237
"""Decorator for declaring a [Tool](https://humanloop.com/docs/explanation/tools) in code.
242238
@@ -309,14 +305,15 @@ def calculator(a: int, b: Optional[int]) -> int:
309305
return tool_decorator_factory(
310306
opentelemetry_tracer=self._opentelemetry_tracer,
311307
path=path,
312-
**tool_kernel,
308+
attributes=attributes,
309+
setup_values=setup_values,
313310
)
314311

315312
def flow(
316313
self,
317314
*,
318-
path: Optional[str] = None,
319-
**flow_kernel: Unpack[FlowKernelRequestParams], # type: ignore
315+
path: str = None,
316+
attributes: dict[str, Any] | None = None,
320317
):
321318
"""Decorator for declaring a [Flow](https://humanloop.com/docs/explanation/flows) in code.
322319
@@ -371,7 +368,7 @@ def entrypoint():
371368
return flow_decorator_factory(
372369
opentelemetry_tracer=self._opentelemetry_tracer,
373370
path=path,
374-
**flow_kernel,
371+
attributes=attributes,
375372
)
376373

377374

src/humanloop/context.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from dataclasses import dataclass
2+
import threading
3+
from typing import Callable, Optional
4+
from opentelemetry import context as context_api
5+
6+
from humanloop.otel.constants import (
7+
HUMANLOOP_CONTEXT_EVALUATION,
8+
HUMANLOOP_CONTEXT_PROMPT_PATH,
9+
HUMANLOOP_CONTEXT_TRACE_ID,
10+
)
11+
12+
13+
ResetToken = object
14+
15+
16+
def get_trace_id() -> Optional[str]:
17+
key = hash((HUMANLOOP_CONTEXT_TRACE_ID, threading.get_ident()))
18+
context_api.get_value()
19+
return context_api.get_value(key=key)
20+
21+
22+
def set_trace_id(flow_log_id: str) -> ResetToken:
23+
key = hash((HUMANLOOP_CONTEXT_TRACE_ID, threading.get_ident()))
24+
return context_api.attach(context_api.set_value(key=key, value=flow_log_id))
25+
26+
27+
def reset_trace_id_context(token: ResetToken):
28+
context_api.detach(token=token)
29+
30+
31+
def set_prompt_path(path: str) -> ResetToken:
32+
key = hash((HUMANLOOP_CONTEXT_PROMPT_PATH, threading.get_ident()))
33+
return context_api.set_value(key=key, value=path)
34+
35+
36+
def reset_prompt_path(token: ResetToken):
37+
context_api.detach(token=token)
38+
39+
40+
def get_prompt_path() -> Optional[str]:
41+
key = hash((HUMANLOOP_CONTEXT_PROMPT_PATH, threading.get_ident()))
42+
return context_api.get_value(key)
43+
44+
45+
@dataclass
46+
class EvaluationContext:
47+
source_datapoint_id: str
48+
run_id: str
49+
callback: Callable[[str], None]
50+
file_id: str
51+
path: str
52+
53+
54+
def set_evaluation_context(evaluation_context: EvaluationContext):
55+
key = hash((HUMANLOOP_CONTEXT_EVALUATION, threading.get_ident()))
56+
context_api.set_value(key, evaluation_context)
57+
58+
59+
def get_evaluation_context() -> Optional[EvaluationContext]:
60+
key = hash((HUMANLOOP_CONTEXT_EVALUATION, threading.get_ident()))
61+
return context_api.get_value(key)

src/humanloop/context_variables.py

Lines changed: 0 additions & 135 deletions
This file was deleted.

src/humanloop/eval_utils/run.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,16 @@
1616
import sys
1717
import threading
1818
import time
19-
import types
2019
import typing
2120
from concurrent.futures import ThreadPoolExecutor
2221
from datetime import datetime
2322
from functools import partial
2423
from logging import INFO
25-
from typing import Callable, Dict, List, Literal, Optional, Sequence, Tuple, TypeVar, Union
24+
from typing import Callable, Dict, List, Literal, Optional, Sequence, Tuple, Union
2625

2726
from humanloop import EvaluatorResponse, FlowResponse, PromptResponse, ToolResponse
27+
from humanloop.context import EvaluationContext, set_evaluation_context
2828
from humanloop.core.api_error import ApiError
29-
from humanloop.context_variables import EvaluationContext, set_evaluation_context
3029
from humanloop.eval_utils.types import Dataset, Evaluator, EvaluatorCheck, File
3130

3231
# We use TypedDicts for requests, which is consistent with the rest of the SDK

src/humanloop/otel/constants.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
HUMANLOOP_FILE_KEY = "humanloop.file"
33
# Attribute name prefix on Humanloop spans for log-related attributes
44
HUMANLOOP_LOG_KEY = "humanloop.log"
5+
HUMANLOOP_LOG_ID_KEY = "humanloop.log_id"
56
HUMANLOOP_FILE_TYPE_KEY = "humanloop.file.type"
67
HUMANLOOP_PATH_KEY = "humanloop.file.path"
78
# Required for the exporter to know when to mark the Flow Log as complete
89
HUMANLOOP_FLOW_PREREQUISITES_KEY = "humanloop.flow.prerequisites"
9-
HUMANLOOP_INTERCEPTED_HL_CALL_SPAN_NAME = "humanloop_intercepted_hl_call"
10-
HUMANLOOP_INTERCEPTED_HL_CALL_RESPONSE = "intercepted_call_response"
10+
HUMANLOOP_INTERCEPTED_PROMPT_CALL_SPAN_NAME = "humanloop_intercepted_hl_call"
11+
HUMANLOOP_INTERCEPTED_PROMPT_CALL_RESPONSE = "intercepted_call_response"
12+
HUMANLOOP_CONTEXT_PROMPT_PATH = "humanloop.context.prompt.path"
13+
HUMANLOOP_CONTEXT_TRACE_ID = "humanloop.context.flow.trace_id"
14+
HUMANLOOP_CONTEXT_EVALUATION = "humanloop.context.evaluation"

0 commit comments

Comments
 (0)