Skip to content

Commit f538cc7

Browse files
author
Andrei Bratu
committed
QA pass
1 parent 914091b commit f538cc7

File tree

9 files changed

+45
-36
lines changed

9 files changed

+45
-36
lines changed

src/humanloop/evals/run.py

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595

9696
EvaluatorDict = Union[CodeEvaluatorDict, LLMEvaluatorDict, HumanEvaluatorDict, ExternalEvaluator]
9797
Version = Union[FlowDict, PromptDict, ToolDict, EvaluatorDict]
98-
FileType = Literal["flow", "prompt", "tool", "evaluator"]
98+
FileType = Literal["flow", "prompt", "agent"]
9999

100100

101101
# ANSI escape codes for logging colors
@@ -153,7 +153,8 @@ def run_eval(
153153
evaluators_worker_pool = ThreadPoolExecutor(max_workers=workers)
154154

155155
hl_file, function_ = _get_hl_file(client=client, file_config=file)
156-
type_ = hl_file.type
156+
# cast is safe, we can only fetch Files allowed by FileType
157+
type_ = typing.cast(FileType, hl_file.type)
157158
try:
158159
hl_dataset = _upsert_dataset(dataset=dataset, client=client)
159160
except Exception as e:
@@ -211,11 +212,11 @@ def handle_exit_signal(signum, frame):
211212
# Generate locally if a file `callable` is provided
212213
if function_ is None:
213214
# TODO: trigger run when updated API is available
214-
print_info(f"\nRunning '{hl_file.name}' {hl_file.type.capitalize()} over the Dataset '{hl_dataset.name}'")
215+
print_info(f"\nRunning '{hl_file.name}' {type_.capitalize()} over the '{hl_dataset.name}' Dataset")
215216
else:
216217
# Running the evaluation locally
217218
print_info(
218-
f"\nRunning '{hl_file.name}' {hl_file.type.capitalize()} over the Dataset '{hl_dataset.name}' using {workers} workers...\n"
219+
f"\nRunning '{hl_file.name}' {type_.capitalize()} over the '{hl_dataset.name}' Dataset using {workers} workers...\n"
219220
)
220221

221222
_PROGRESS_BAR = _SimpleProgressBar(len(hl_dataset.datapoints))
@@ -420,58 +421,71 @@ def _safe_get_default_file_version(client: "BaseHumanloop", file_config: FileEva
420421
raise HumanloopRuntimeError(
421422
f"File in Humanloop workspace at {path} is not of type {type}, but {hl_file.type}."
422423
)
423-
return hl_file
424-
else:
424+
# cast is safe, we can only fetch Files allowed by FileType
425+
return typing.cast(EvaluatedFile, hl_file)
426+
elif file_id is not None:
425427
subclient = _get_subclient(client=client, file_config=file_config)
426428
return subclient.get(id=file_id)
429+
else:
430+
raise HumanloopRuntimeError("You must provide a path or id in your `file` config.")
427431

428432

429433
def _resolve_file(client: "BaseHumanloop", file_config: FileEvalConfig) -> tuple[EvaluatedFile, Optional[Callable]]:
430434
"""Resolve the File to be evaluated. Will return a FileResponse and an optional callable.
431435
432436
If the callable is null, the File will be evaluated on Humanloop. Otherwise, the File will be evaluated locally.
433437
"""
434-
hl_file = _safe_get_default_file_version(client=client, file_config=file_config)
435438
file_id = file_config.get("id")
436439
path = file_config.get("path")
437440
version_id = file_config.get("version_id")
438441
environment = file_config.get("environment")
439442
callable = _get_file_callable(file_config=file_config)
440443
version = file_config.get("version")
441444

442-
if version is not None and path is None and file_id:
445+
if callable and path is None and file_id is None:
446+
raise HumanloopRuntimeError(
447+
"You are trying to create a new version of the File by passing the `version` argument. "
448+
"You must pass either the `file.path` or `file.id` argument and provider proper `file.version` for upserting the File."
449+
)
450+
hl_file = _safe_get_default_file_version(client=client, file_config=file_config)
451+
452+
if (version_id or environment) and (callable or version):
443453
raise HumanloopRuntimeError(
444-
"You are trying to create a new version of the File by passing the `version` argument. You must pass either the `file.path` or `file.id` argument."
454+
"You are trying to create a local Evaluation while requesting a specific File version by version ID or environment."
445455
)
446456

447-
if version:
448-
# User wants to upsert a version
449-
return (_upsert_file(file_config=file_config, client=client), callable)
457+
if callable:
458+
# User responsibility to provide adequate file.version for upserting the file
459+
print_info(
460+
"Upserting a new File version based on `file.version`. Will use provided callable for generating Logs."
461+
)
462+
try:
463+
return (_upsert_file(file_config=file_config, client=client), callable)
464+
except Exception as e:
465+
raise HumanloopRuntimeError(f"Error upserting the File. Please ensure `file.version` is valid: {e}") from e
450466

451467
if version_id is None and environment is None:
452468
# Return default version of the File
453469
return hl_file, callable
454470

455-
if callable:
456-
raise HumanloopRuntimeError(
457-
"You cannot request local evaluation while requesting a specific File version by version ID or environment"
458-
)
459-
460471
if file_id is None and (version_id or environment):
461472
raise HumanloopRuntimeError(
462473
"You must provide the `file.id` when addressing a file by version ID or environment"
463474
)
475+
464476
# Use version_id or environment to retrieve specific version of the File
465477
subclient = _get_subclient(client=client, file_config=file_config)
466478
# Let backend handle case where both or none of version_id and environment are provided
467479
return subclient.get(
468-
version_id=file_config.get("version_id"),
469-
environment=file_config.get("environment"),
480+
# Earlier if checked that file_id is not None
481+
id=file_id, # type: ignore [arg-type]
482+
version_id=version_id,
483+
environment=environment,
470484
), None
471485

472486

473487
def _get_hl_file(client: "BaseHumanloop", file_config: FileEvalConfig) -> tuple[EvaluatedFile, Optional[Callable]]:
474-
"""Check if the config object is valid, and resolve the File to be evaluated
488+
"""Check if the config object is valid, and resolve the File to be evaluated.
475489
476490
The callable will be null if the evaluation will happen on Humanloop runtime.
477491
Otherwise, the evaluation will happen locally.
@@ -617,20 +631,19 @@ def _file_or_file_inside_hl_decorator(file_config: FileEvalConfig) -> FileEvalCo
617631
return file_
618632

619633

620-
def _check_file_type(file: FileEvalConfig) -> FileEvalConfig:
634+
def _check_file_type(file_config: FileEvalConfig) -> FileEvalConfig:
621635
"""Check that the file type is provided, or set it to `flow` if not provided."""
622636
try:
623-
type_ = typing.cast(FileType, file.pop("type")) # type: ignore [arg-type, misc]
637+
type_ = typing.cast(FileType, file_config.pop("type")) # type: ignore [arg-type, misc]
624638
print_info(
625-
f"Evaluating your {type_} function corresponding to `{file.get('path') or file.get('id')}` on Humanloop\n\n"
639+
f"Evaluating your {type_} function corresponding to `{file_config.get('path') or file_config.get('id')}` on Humanloop\n\n"
626640
)
627-
if type_ is None:
628-
file["type"] = "flow"
641+
file_config["type"] = type_ or "flow"
629642
except KeyError as _:
630643
type_ = "flow"
631644
print_warning("No `file` type specified, defaulting to flow.")
632-
file["type"] = type_
633-
return file
645+
file_config["type"] = type_
646+
return file_config
634647

635648

636649
def _get_file_callable(file_config: FileEvalConfig) -> Optional[Callable]:
@@ -653,6 +666,7 @@ def _upsert_file(client: "BaseHumanloop", file_config: FileEvalConfig) -> Evalua
653666
# Get or create the file on Humanloop
654667
version = file_config.pop("version", {})
655668
file_dict = {**file_config, **version}
669+
del file_dict["type"]
656670
type_ = file_config.get("type")
657671
subclient = _get_subclient(client=client, file_config=file_config)
658672

@@ -672,7 +686,8 @@ def _upsert_file(client: "BaseHumanloop", file_config: FileEvalConfig) -> Evalua
672686
else:
673687
raise NotImplementedError(f"Unsupported File type: {type_}")
674688

675-
return subclient.upsert(**file_dict)
689+
# mypy complains about the polymorphic subclient
690+
return subclient.upsert(**file_dict) # type: ignore [arg-type]
676691

677692

678693
def _upsert_dataset(dataset: DatasetEvalConfig, client: "BaseHumanloop"):

src/humanloop/types/version_id_response_version.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from __future__ import annotations
44
import typing
55
from .dataset_response import DatasetResponse
6-
import typing
76

87
if typing.TYPE_CHECKING:
98
from .prompt_response import PromptResponse

src/humanloop/types/version_reference_response.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from __future__ import annotations
44
import typing
5-
import typing
65

76
if typing.TYPE_CHECKING:
87
from .version_deployment_response import VersionDeploymentResponse

tests/custom/test_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
# Get started with writing tests with pytest at https://docs.pytest.org
55
@pytest.mark.skip(reason="Unimplemented")
66
def test_client() -> None:
7-
assert True == True
7+
assert True is True

tests/utils/assets/models/circle.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
# This file was auto-generated by Fern from our API Definition.
44

5-
import typing_extensions
65
import typing_extensions
76
from humanloop.core.serialization import FieldMetadata
87

tests/utils/assets/models/object_with_optional_field.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import typing_extensions
66
import typing
7-
import typing_extensions
87
from humanloop.core.serialization import FieldMetadata
98
import datetime as dt
109
import uuid

tests/utils/assets/models/shape.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from __future__ import annotations
66
import typing_extensions
7-
import typing_extensions
87
import typing
98
from humanloop.core.serialization import FieldMetadata
109

tests/utils/assets/models/square.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
# This file was auto-generated by Fern from our API Definition.
44

5-
import typing_extensions
65
import typing_extensions
76
from humanloop.core.serialization import FieldMetadata
87

tests/utils/test_query_encoding.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ def test_query_encoding_deep_object_arrays() -> None:
3434

3535
def test_encode_query_with_none() -> None:
3636
encoded = encode_query(None)
37-
assert encoded == None
37+
assert encoded is None

0 commit comments

Comments
 (0)