diff --git a/langfuse/api/unstable/__init__.py b/langfuse/api/unstable/__init__.py index e5356c235..827a2ac6b 100644 --- a/langfuse/api/unstable/__init__.py +++ b/langfuse/api/unstable/__init__.py @@ -94,6 +94,7 @@ CreateEvaluatorRequest_Code, CreateEvaluatorRequest_LlmAsJudge, CreateLlmAsJudgeEvaluatorRequest, + DeleteEvaluatorResponse, Evaluator, EvaluatorBase, Evaluator_Code, @@ -121,6 +122,7 @@ "CreateLlmAsJudgeEvaluatorRequest": ".evaluators", "DateTimeEvaluationRuleFilter": ".commons", "DeleteEvaluationRuleResponse": ".evaluation_rules", + "DeleteEvaluatorResponse": ".evaluators", "EvaluationRule": ".evaluation_rules", "EvaluationRuleArrayOptionsFilterOperator": ".commons", "EvaluationRuleBooleanFilterOperator": ".commons", @@ -242,6 +244,7 @@ def __dir__(): "CreateLlmAsJudgeEvaluatorRequest", "DateTimeEvaluationRuleFilter", "DeleteEvaluationRuleResponse", + "DeleteEvaluatorResponse", "EvaluationRule", "EvaluationRuleArrayOptionsFilterOperator", "EvaluationRuleBooleanFilterOperator", diff --git a/langfuse/api/unstable/evaluators/__init__.py b/langfuse/api/unstable/evaluators/__init__.py index 20a72ef82..ec54f35c9 100644 --- a/langfuse/api/unstable/evaluators/__init__.py +++ b/langfuse/api/unstable/evaluators/__init__.py @@ -13,6 +13,7 @@ CreateEvaluatorRequest_Code, CreateEvaluatorRequest_LlmAsJudge, CreateLlmAsJudgeEvaluatorRequest, + DeleteEvaluatorResponse, Evaluator, EvaluatorBase, Evaluator_Code, @@ -27,6 +28,7 @@ "CreateEvaluatorRequest_Code": ".types", "CreateEvaluatorRequest_LlmAsJudge": ".types", "CreateLlmAsJudgeEvaluatorRequest": ".types", + "DeleteEvaluatorResponse": ".types", "Evaluator": ".types", "EvaluatorBase": ".types", "Evaluator_Code": ".types", @@ -70,6 +72,7 @@ def __dir__(): "CreateEvaluatorRequest_Code", "CreateEvaluatorRequest_LlmAsJudge", "CreateLlmAsJudgeEvaluatorRequest", + "DeleteEvaluatorResponse", "Evaluator", "EvaluatorBase", "Evaluator_Code", diff --git a/langfuse/api/unstable/evaluators/client.py b/langfuse/api/unstable/evaluators/client.py index ac63e2da9..5a5a03944 100644 --- a/langfuse/api/unstable/evaluators/client.py +++ b/langfuse/api/unstable/evaluators/client.py @@ -6,6 +6,7 @@ from ...core.request_options import RequestOptions from .raw_client import AsyncRawEvaluatorsClient, RawEvaluatorsClient from .types.create_evaluator_request import CreateEvaluatorRequest +from .types.delete_evaluator_response import DeleteEvaluatorResponse from .types.evaluator import Evaluator from .types.evaluators import Evaluators @@ -211,6 +212,54 @@ def get( _response = self._raw_client.get(evaluator_id, request_options=request_options) return _response.data + def delete( + self, + evaluator_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeleteEvaluatorResponse: + """ + Delete an evaluator. + + Important behavior: + - This deletes the evaluator including all of its stored versions; `evaluatorId` may reference any version. + - The API returns `409` while evaluation rules still reference the evaluator. Delete those evaluation rules first. + - Langfuse-managed evaluators (`scope=managed`) cannot be deleted; the API returns `403`. + - Scores already produced by the evaluator are not deleted. + + Parameters + ---------- + evaluator_id : str + Evaluator identifier returned by the evaluator endpoints. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeleteEvaluatorResponse + + Examples + -------- + from langfuse import LangfuseAPI + + client = LangfuseAPI( + x_langfuse_sdk_name="YOUR_X_LANGFUSE_SDK_NAME", + x_langfuse_sdk_version="YOUR_X_LANGFUSE_SDK_VERSION", + x_langfuse_public_key="YOUR_X_LANGFUSE_PUBLIC_KEY", + username="YOUR_USERNAME", + password="YOUR_PASSWORD", + base_url="https://yourhost.com/path/to/api", + ) + client.unstable.evaluators.delete( + evaluator_id="evaluatorId", + ) + """ + _response = self._raw_client.delete( + evaluator_id, request_options=request_options + ) + return _response.data + class AsyncEvaluatorsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): @@ -435,3 +484,59 @@ async def main() -> None: evaluator_id, request_options=request_options ) return _response.data + + async def delete( + self, + evaluator_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeleteEvaluatorResponse: + """ + Delete an evaluator. + + Important behavior: + - This deletes the evaluator including all of its stored versions; `evaluatorId` may reference any version. + - The API returns `409` while evaluation rules still reference the evaluator. Delete those evaluation rules first. + - Langfuse-managed evaluators (`scope=managed`) cannot be deleted; the API returns `403`. + - Scores already produced by the evaluator are not deleted. + + Parameters + ---------- + evaluator_id : str + Evaluator identifier returned by the evaluator endpoints. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeleteEvaluatorResponse + + Examples + -------- + import asyncio + + from langfuse import AsyncLangfuseAPI + + client = AsyncLangfuseAPI( + x_langfuse_sdk_name="YOUR_X_LANGFUSE_SDK_NAME", + x_langfuse_sdk_version="YOUR_X_LANGFUSE_SDK_VERSION", + x_langfuse_public_key="YOUR_X_LANGFUSE_PUBLIC_KEY", + username="YOUR_USERNAME", + password="YOUR_PASSWORD", + base_url="https://yourhost.com/path/to/api", + ) + + + async def main() -> None: + await client.unstable.evaluators.delete( + evaluator_id="evaluatorId", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.delete( + evaluator_id, request_options=request_options + ) + return _response.data diff --git a/langfuse/api/unstable/evaluators/raw_client.py b/langfuse/api/unstable/evaluators/raw_client.py index 30034d033..ab6f2fd10 100644 --- a/langfuse/api/unstable/evaluators/raw_client.py +++ b/langfuse/api/unstable/evaluators/raw_client.py @@ -42,6 +42,7 @@ from ..errors.errors.unprocessable_content_error import UnprocessableContentError from ..errors.types.public_api_error import PublicApiError from .types.create_evaluator_request import CreateEvaluatorRequest +from .types.delete_evaluator_response import DeleteEvaluatorResponse from .types.evaluator import Evaluator from .types.evaluators import Evaluators @@ -642,6 +643,204 @@ def get( body=_response_json, ) + def delete( + self, + evaluator_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[DeleteEvaluatorResponse]: + """ + Delete an evaluator. + + Important behavior: + - This deletes the evaluator including all of its stored versions; `evaluatorId` may reference any version. + - The API returns `409` while evaluation rules still reference the evaluator. Delete those evaluation rules first. + - Langfuse-managed evaluators (`scope=managed`) cannot be deleted; the API returns `403`. + - Scores already produced by the evaluator are not deleted. + + Parameters + ---------- + evaluator_id : str + Evaluator identifier returned by the evaluator endpoints. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[DeleteEvaluatorResponse] + """ + _response = self._client_wrapper.httpx_client.request( + f"api/public/unstable/evaluators/{jsonable_encoder(evaluator_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + DeleteEvaluatorResponse, + parse_obj_as( + type_=DeleteEvaluatorResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise unstable_errors_errors_unauthorized_error_UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise unstable_errors_errors_access_denied_error_AccessDeniedError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise unstable_errors_errors_not_found_error_NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 405: + raise unstable_errors_errors_method_not_allowed_error_MethodNotAllowedError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 400: + raise Error( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise commons_errors_unauthorized_error_UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise commons_errors_access_denied_error_AccessDeniedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 405: + raise commons_errors_method_not_allowed_error_MethodNotAllowedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise commons_errors_not_found_error_NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.text, + ) + raise ApiError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response_json, + ) + class AsyncRawEvaluatorsClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): @@ -1235,3 +1434,201 @@ async def get( headers=dict(_response.headers), body=_response_json, ) + + async def delete( + self, + evaluator_id: str, + *, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[DeleteEvaluatorResponse]: + """ + Delete an evaluator. + + Important behavior: + - This deletes the evaluator including all of its stored versions; `evaluatorId` may reference any version. + - The API returns `409` while evaluation rules still reference the evaluator. Delete those evaluation rules first. + - Langfuse-managed evaluators (`scope=managed`) cannot be deleted; the API returns `403`. + - Scores already produced by the evaluator are not deleted. + + Parameters + ---------- + evaluator_id : str + Evaluator identifier returned by the evaluator endpoints. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[DeleteEvaluatorResponse] + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/public/unstable/evaluators/{jsonable_encoder(evaluator_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + DeleteEvaluatorResponse, + parse_obj_as( + type_=DeleteEvaluatorResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise unstable_errors_errors_unauthorized_error_UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise unstable_errors_errors_access_denied_error_AccessDeniedError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise unstable_errors_errors_not_found_error_NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 405: + raise unstable_errors_errors_method_not_allowed_error_MethodNotAllowedError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 409: + raise ConflictError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 500: + raise InternalServerError( + headers=dict(_response.headers), + body=typing.cast( + PublicApiError, + parse_obj_as( + type_=PublicApiError, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 400: + raise Error( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 401: + raise commons_errors_unauthorized_error_UnauthorizedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 403: + raise commons_errors_access_denied_error_AccessDeniedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 405: + raise commons_errors_method_not_allowed_error_MethodNotAllowedError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + if _response.status_code == 404: + raise commons_errors_not_found_error_NotFoundError( + headers=dict(_response.headers), + body=typing.cast( + typing.Any, + parse_obj_as( + type_=typing.Any, # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.text, + ) + raise ApiError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response_json, + ) diff --git a/langfuse/api/unstable/evaluators/types/__init__.py b/langfuse/api/unstable/evaluators/types/__init__.py index 650598592..fd031d61d 100644 --- a/langfuse/api/unstable/evaluators/types/__init__.py +++ b/langfuse/api/unstable/evaluators/types/__init__.py @@ -14,6 +14,7 @@ CreateEvaluatorRequest_LlmAsJudge, ) from .create_llm_as_judge_evaluator_request import CreateLlmAsJudgeEvaluatorRequest + from .delete_evaluator_response import DeleteEvaluatorResponse from .evaluator import Evaluator, Evaluator_Code, Evaluator_LlmAsJudge from .evaluator_base import EvaluatorBase from .evaluators import Evaluators @@ -25,6 +26,7 @@ "CreateEvaluatorRequest_Code": ".create_evaluator_request", "CreateEvaluatorRequest_LlmAsJudge": ".create_evaluator_request", "CreateLlmAsJudgeEvaluatorRequest": ".create_llm_as_judge_evaluator_request", + "DeleteEvaluatorResponse": ".delete_evaluator_response", "Evaluator": ".evaluator", "EvaluatorBase": ".evaluator_base", "Evaluator_Code": ".evaluator", @@ -68,6 +70,7 @@ def __dir__(): "CreateEvaluatorRequest_Code", "CreateEvaluatorRequest_LlmAsJudge", "CreateLlmAsJudgeEvaluatorRequest", + "DeleteEvaluatorResponse", "Evaluator", "EvaluatorBase", "Evaluator_Code", diff --git a/langfuse/api/unstable/evaluators/types/delete_evaluator_response.py b/langfuse/api/unstable/evaluators/types/delete_evaluator_response.py new file mode 100644 index 000000000..1cbcc050f --- /dev/null +++ b/langfuse/api/unstable/evaluators/types/delete_evaluator_response.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ....core.pydantic_utilities import UniversalBaseModel + + +class DeleteEvaluatorResponse(UniversalBaseModel): + """ + Confirmation response returned after successful deletion. + """ + + message: str = pydantic.Field() + """ + Always `Evaluator successfully deleted`. + """ + + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( + extra="allow", frozen=True + )