6767from humanloop .types .datapoint_response import DatapointResponse
6868from humanloop .types .dataset_response import DatasetResponse
6969from humanloop .types .evaluation_run_response import EvaluationRunResponse
70+ from humanloop .types .evaluator_log_response import EvaluatorLogResponse
71+ from humanloop .types .flow_log_response import FlowLogResponse
72+ from humanloop .types .log_response import LogResponse
73+ from humanloop .types .prompt_log_response import PromptLogResponse
7074from humanloop .types .run_stats_response import RunStatsResponse
7175from pydantic import ValidationError
7276
77+ from humanloop .types .tool_log_response import ToolLogResponse
78+
7379if typing .TYPE_CHECKING :
7480 from humanloop .client import BaseHumanloop
7581
99105CLIENT_TYPE = TypeVar ("CLIENT_TYPE" , PromptsClient , ToolsClient , FlowsClient , EvaluatorsClient )
100106
101107
102- class HumanloopUtilityError (Exception ):
103- def __init__ (self , message ):
108+ class HumanloopDecoratorError (Exception ):
109+ def __init__ (self , message : Optional [ str ] = None ):
104110 self .message = message
105111
106112 def __str__ (self ):
113+ if self .message is None :
114+ return super ().__str__ ()
107115 return self .message
108116
109117
@@ -202,7 +210,7 @@ def upload_callback(log_id: str):
202210 with set_evaluation_context (
203211 EvaluationContext (
204212 source_datapoint_id = dp .id ,
205- callback = upload_callback ,
213+ logging_callback = upload_callback ,
206214 file_id = hl_file .id ,
207215 run_id = run .id ,
208216 path = hl_file .path ,
@@ -219,17 +227,25 @@ def upload_callback(log_id: str):
219227 try :
220228 output = _call_function (function_ , hl_file .type , dp )
221229 evaluation_context = get_evaluation_context ()
222- if not evaluation_context .logging_counter == 0 :
230+ if evaluation_context is None :
231+ raise HumanloopDecoratorError (
232+ "Internal error: evaluation context is not set while processing a datapoint."
233+ )
234+ if evaluation_context .logging_counter == 0 :
223235 # function_ did not Log against the source_datapoint_id/ run_id pair
224236 # so we need to create a Log
225- log_func (
237+ log = log_func (
226238 inputs = dp .inputs ,
227239 output = output ,
228240 start_time = start_time ,
229241 end_time = datetime .now (),
230242 source_datapoint_id = dp .id ,
231243 run_id = run .id ,
232244 )
245+ evaluation_context .logging_counter += 1
246+ evaluation_context .logging_callback (log .id )
247+ except HumanloopDecoratorError as e :
248+ raise e
233249 except Exception as e :
234250 log_func (
235251 inputs = dp .inputs ,
@@ -648,13 +664,49 @@ def _call_function(
648664 return output
649665
650666
667+ def _get_log_func (
668+ client : "BaseHumanloop" ,
669+ file_type : Literal ["flow" ],
670+ file_id : str ,
671+ version_id : str ,
672+ run_id : str ,
673+ ) -> Callable [..., FlowLogResponse ]: ...
674+
675+
676+ def _get_log_func (
677+ client : "BaseHumanloop" ,
678+ file_type : Literal ["prompt" ],
679+ file_id : str ,
680+ version_id : str ,
681+ run_id : str ,
682+ ) -> Callable [..., PromptLogResponse ]: ...
683+
684+
685+ def _get_log_func (
686+ client : "BaseHumanloop" ,
687+ file_type : Literal ["tool" ],
688+ file_id : str ,
689+ version_id : str ,
690+ run_id : str ,
691+ ) -> Callable [..., ToolLogResponse ]: ...
692+
693+
694+ def _get_log_func (
695+ client : "BaseHumanloop" ,
696+ file_type : Literal ["evaluator" ],
697+ file_id : str ,
698+ version_id : str ,
699+ run_id : str ,
700+ ) -> Callable [..., EvaluatorLogResponse ]: ...
701+
702+
651703def _get_log_func (
652704 client : "BaseHumanloop" ,
653705 file_type : FileType ,
654706 file_id : str ,
655707 version_id : str ,
656708 run_id : str ,
657- ) -> Callable :
709+ ) -> Callable [..., LogResponse ] :
658710 """Returns the appropriate log function pre-filled with common parameters."""
659711 log_request = {
660712 # TODO: why does the Log `id` field refer to the file ID in the API?
0 commit comments