diff --git a/litellm/proxy/fine_tuning_endpoints/endpoints.py b/litellm/proxy/fine_tuning_endpoints/endpoints.py index c560e7b53..2f6ad20cf 100644 --- a/litellm/proxy/fine_tuning_endpoints/endpoints.py +++ b/litellm/proxy/fine_tuning_endpoints/endpoints.py @@ -138,7 +138,6 @@ async def create_fine_tuning_job( # add llm_provider_config to data data.update(llm_provider_config) - # For now, use custom_llm_provider=="openai" -> this will change as LiteLLM adds more providers for fine-tuning response = await litellm.acreate_fine_tuning_job(**data) ### ALERTING ### @@ -191,3 +190,105 @@ async def create_fine_tuning_job( param=getattr(e, "param", "None"), code=getattr(e, "status_code", 500), ) + + +@router.get( + "/v1/fine_tuning/jobs", + dependencies=[Depends(user_api_key_auth)], + tags=["fine-tuning"], +) +async def list_fine_tuning_jobs( + request: Request, + fastapi_response: Response, + custom_llm_provider: Literal["openai", "azure"], + after: Optional[str] = None, + limit: Optional[int] = None, + user_api_key_dict: dict = Depends(user_api_key_auth), +): + """ + Lists fine-tuning jobs for the organization. + This is the equivalent of GET https://api.openai.com/v1/fine_tuning/jobs + + Supported Query Params: + - `custom_llm_provider`: Name of the LiteLLM provider + - `after`: Identifier for the last job from the previous pagination request. + - `limit`: Number of fine-tuning jobs to retrieve (default is 20). + """ + from litellm.proxy.proxy_server import ( + add_litellm_data_to_request, + general_settings, + get_custom_headers, + proxy_config, + proxy_logging_obj, + version, + ) + + data: dict = {} + try: + # Include original request and headers in the data + data = await add_litellm_data_to_request( + data=data, + request=request, + general_settings=general_settings, + user_api_key_dict=user_api_key_dict, + version=version, + proxy_config=proxy_config, + ) + + # get configs for custom_llm_provider + llm_provider_config = get_fine_tuning_provider_config( + custom_llm_provider=custom_llm_provider + ) + + data.update(llm_provider_config) + + response = await litellm.alist_fine_tuning_jobs( + **data, + after=after, + limit=limit, + ) + + ### RESPONSE HEADERS ### + hidden_params = getattr(response, "_hidden_params", {}) or {} + model_id = hidden_params.get("model_id", None) or "" + cache_key = hidden_params.get("cache_key", None) or "" + api_base = hidden_params.get("api_base", None) or "" + + fastapi_response.headers.update( + get_custom_headers( + user_api_key_dict=user_api_key_dict, + model_id=model_id, + cache_key=cache_key, + api_base=api_base, + version=version, + model_region=getattr(user_api_key_dict, "allowed_model_region", ""), + ) + ) + + return response + + except Exception as e: + await proxy_logging_obj.post_call_failure_hook( + user_api_key_dict=user_api_key_dict, original_exception=e, request_data=data + ) + verbose_proxy_logger.error( + "litellm.proxy.proxy_server.list_fine_tuning_jobs(): Exception occurred - {}".format( + str(e) + ) + ) + verbose_proxy_logger.debug(traceback.format_exc()) + if isinstance(e, HTTPException): + raise ProxyException( + message=getattr(e, "message", str(e.detail)), + type=getattr(e, "type", "None"), + param=getattr(e, "param", "None"), + code=getattr(e, "status_code", status.HTTP_400_BAD_REQUEST), + ) + else: + error_msg = f"{str(e)}" + raise ProxyException( + message=getattr(e, "message", error_msg), + type=getattr(e, "type", "None"), + param=getattr(e, "param", "None"), + code=getattr(e, "status_code", 500), + ) diff --git a/litellm/proxy/proxy_config.yaml b/litellm/proxy/proxy_config.yaml index 20c08fe63..b78832a10 100644 --- a/litellm/proxy/proxy_config.yaml +++ b/litellm/proxy/proxy_config.yaml @@ -38,7 +38,7 @@ finetune_settings: # for /files endpoints files_settings: - custom_llm_provider: azure - api_base: http://0.0.0.0:8090 + api_base: https://exampleopenaiendpoint-production.up.railway.app api_key: fake-key api_version: "2023-03-15-preview" - custom_llm_provider: openai diff --git a/tests/test_openai_fine_tuning.py b/tests/test_openai_fine_tuning.py index 94ef156b2..096aabea4 100644 --- a/tests/test_openai_fine_tuning.py +++ b/tests/test_openai_fine_tuning.py @@ -10,14 +10,44 @@ async def test_openai_fine_tuning(): """ client = AsyncOpenAI(api_key="sk-1234", base_url="http://0.0.0.0:4000") - file_name = "openai_batch_completions.jsonl" - _current_dir = os.path.dirname(os.path.abspath(__file__)) - file_path = os.path.join(_current_dir, file_name) + # file_name = "openai_batch_completions.jsonl" + # _current_dir = os.path.dirname(os.path.abspath(__file__)) + # file_path = os.path.join(_current_dir, file_name) - response = await client.files.create( - extra_body={"custom_llm_provider": "azure"}, - file=open(file_path, "rb"), - purpose="fine-tune", + # response = await client.files.create( + # extra_body={"custom_llm_provider": "azure"}, + # file=open(file_path, "rb"), + # purpose="fine-tune", + # ) + + # print("response from files.create: {}".format(response)) + + # # create fine tuning job + + # ft_job = await client.fine_tuning.jobs.create( + # model="gpt-35-turbo-1106", + # training_file=response.id, + # extra_body={"custom_llm_provider": "azure"}, + # ) + + # print("response from ft job={}".format(ft_job)) + + # # response from example endpoint + # assert ft_job.id == "file-abc123" + + # get fine tuning job + # specific_ft_job = await client.fine_tuning.jobs.retrieve( + # fine_tuning_job_id="123", + # extra_body={"custom_llm_provider": "azure"}, + # ) + + # list all fine tuning jobs + list_ft_jobs = await client.fine_tuning.jobs.list( + extra_query={"custom_llm_provider": "azure"} ) - print("response from files.create: {}".format(response)) + # cancel specific fine tuning job + cancel_ft_job = await client.fine_tuning.jobs.cancel( + fine_tuning_job_id="123", + extra_body={"custom_llm_provider": "azure"}, + )