Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix streaming endpoint failure handling #314

Merged
merged 11 commits into from Oct 11, 2023
Merged

Conversation

yunfeng-scale
Copy link
Collaborator

@yunfeng-scale yunfeng-scale commented Oct 10, 2023

  • Fix streaming endpoint failure handling

before the fix, getting error:

urllib3.exceptions.ProtocolError: ("Connection broken: InvalidChunkLength(got length b'', 0 bytes read)", InvalidChunkLength(got length b'', 0 bytes read))

after the fix, getting response:

b"data: {'error': {'status_code': 404, 'detail': 'Model endpoint a not found.'}}\r\n\r\n"

@@ -55,6 +55,7 @@ repos:
hooks:
- id: mypy
name: mypy-clients-python
files: clients/python/.*
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't be using clients/python mypy checking server files

model_endpoint_service=external_interfaces.model_endpoint_service,
llm_model_endpoint_service=external_interfaces.llm_model_endpoint_service,
)
response = use_case.execute(user=auth, model_endpoint_name=model_endpoint_name, request=request)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here use_case.execute doesn't actually execute until L237

@yunfeng-scale yunfeng-scale requested a review from a team October 10, 2023 04:26
)
assert response_1.status_code == 404


@pytest.mark.skip(reason="Need to figure out FastAPI test client asyncio funkiness")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we still want to skip this test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, unfortunately i still haven't figured out how to run two streaming tests in a row. there's something wrong about how test client uses event loop that i wasn't able to fix: more context in encode/starlette#1315

model-engine/tests/unit/api/test_llms.py Outdated Show resolved Hide resolved
except (ObjectNotFoundException, ObjectNotAuthorizedException) as exc:
yield {"data": {"error": {"status_code": 404, "detail": str(exc)}}}
except ObjectHasInvalidValueException as exc:
yield {"data": {"error": {"status_code": 400, "detail": str(exc)}}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have a helper function to generate these payloads?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this snippet is short enough so okay to not have a helper function

model-engine/model_engine_server/api/llms_v1.py Outdated Show resolved Hide resolved
Copy link
Member

@yixu34 yixu34 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also have @song-william take a look

model-engine/model_engine_server/api/llms_v1.py Outdated Show resolved Hide resolved
{
"request_id": str(request_id),
"error": {
"status_code": code,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is a bit pedantic (pydantic? lol), but since you ended up creating the DTOS anyway, wonder if it makes sense to instantiate the DTOs and convert them to JSON? That way you get the typing.

Alternatively, I think we want a unit test to enforce the API contract behind the error return type.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do. for test i added test_completion_stream_endpoint_not_found_returns_404 but unfortunately i still haven't figured out how to run it (it works individually)

async for message in response:
yield {"data": message.json()}
except (InvalidRequestException, ObjectHasInvalidValueException) as exc:
yield handle_streaming_exception(exc, 400, str(exc))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for my edification, was the primary fix for urllib3.exceptions.ProtocolError to push the exception handling inside the generator with yield?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exception in use_case.execute won't throw until async for message in response:, and since originally we don't capture exceptions other than InvalidRequestException, my understanding is 0 bytes would get returned and client side throws error about not able to decode

@yunfeng-scale yunfeng-scale merged commit 65afe0a into main Oct 11, 2023
5 checks passed
@yunfeng-scale yunfeng-scale deleted the yunfeng-streaming-error branch October 11, 2023 23:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants