-
Notifications
You must be signed in to change notification settings - Fork 12
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
Make login flow a tad nicer #48
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very nice, simplifying code is always great!
I am however a bit unsure about the singleton. This changes the behavior a bit and breaks the user interface as it is now implemented. The user interface is connected to a server, that uses the tabpfn client to execute our models. Now this server must handle several concurrent sessions, which will be hard with the Singleton approach. @LeoGrin this would affect the interface?
I see how the changing interface annoys, but I think the interface for the login token got much nicer now, no? Before it was a bit hacky. It should not be very hard to adapt the client, is it? I think now is the time to make breaking api changes, later it will be harder. We did have singletons before already (through @common_utils.singleton), that was not newly introduced by me in this PR, I just implement them in a less hard to understand way and added them to more classes that are actually logically singletons. We want singletons as we never want to have multiple client objects at the same time, unlike openai, I guess. It should just make our life easier to be sure there are not two versions of an object, if we never want two version of that object. |
Using singletons for the ServiceClient and InferenceClient does break the user interface, which was creating a ServiceClient instance each time it needed it. But I think it's not too hard to fix by doing |
tabpfn_client/server_config.yaml
Outdated
@@ -5,8 +5,8 @@ | |||
|
|||
# production | |||
protocol: "https" | |||
host: "tabpfn-server-wjedmz7r5a-ez.a.run.app" | |||
# host: tabpfn-server-preprod-wjedmz7r5a-ez.a.run.app # preprod | |||
# host: "tabpfn-server-wjedmz7r5a-ez.a.run.app" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should still default to prod
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OMG thanks for spotting this, that was very bad
return ServiceClient.get_access_token() | ||
|
||
|
||
def set_access_token(access_token: str): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if I use set_access_token
with a wrong token, I get a very cryptic error:
RuntimeError: Fail to call upload_train_set with error: 500, reason: Internal Server Error and text: Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/jwt/api_jws.py", line 258, in _load
signing_input, crypto_segment = jwt.rsplit(b".", 1)
ValueError: not enough values to unpack (expected 2, got 1)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/errors.py", line 165, in __call__
await self.app(scope, receive, _send)
File "/usr/local/lib/python3.10/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 715, in __call__
await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 735, in app
await route.handle(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 288, in handle
await self.app(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 76, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
raise exc
File "/usr/local/lib/python3.10/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
await app(scope, receive, sender)
File "/usr/local/lib/python3.10/site-packages/starlette/routing.py", line 73, in app
response = await f(request)
File "/usr/local/lib/python3.10/site-packages/fastapi/routing.py", line 291, in app
solved_result = await solve_dependencies(
File "/usr/local/lib/python3.10/site-packages/fastapi/dependencies/utils.py", line 640, in solve_dependencies
solved = await run_in_threadpool(call, **solved_result.values)
File "/usr/local/lib/python3.10/site-packages/starlette/concurrency.py", line 39, in run_in_threadpool
return await anyio.to_thread.run_sync(func, *args)
File "/usr/local/lib/python3.10/site-packages/anyio/to_thread.py", line 56, in run_sync
return await get_async_backend().run_sync_in_worker_thread(
File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 2441, in run_sync_in_worker_thread
return await future
File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 943, in run
result = context.run(func, *args)
File "/code/tabpfn-server/app/dependencies.py", line 115, in get_current_user
status, user = user_auth.get_user_by_token(token)
File "/code/tabpfn-server/app/services/user_auth_service.py", line 265, in get_user_by_token
token_data = self._decode_token(token)
File "/code/tabpfn-server/app/services/user_auth_service.py", line 279, in _decode_token
return self._jwt_token_handler.decode_token(token)
File "/code/tabpfn-server/app/services/user_auth_service.py", line 58, in decode_token
return jwt.decode(token, self._JWT_SECRET, algorithms=self._JWT_ALGO)
File "/usr/local/lib/python3.10/site-packages/jwt/api_jwt.py", line 211, in decode
decoded = self.decode_complete(
File "/usr/local/lib/python3.10/site-packages/jwt/api_jwt.py", line 152, in decode_complete
decoded = api_jws.decode_complete(
File "/usr/local/lib/python3.10/site-packages/jwt/api_jws.py", line 199, in decode_complete
payload, signing_input, header, signature = self._load(jwt)
File "/usr/local/lib/python3.10/site-packages/jwt/api_jws.py", line 261, in _load
raise DecodeError("Not enough segments") from err
jwt.exceptions.DecodeError: Not enough segments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be fixed in a server-side pr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Just a few minor comments + need to be merged with main.
I agree the logic is now much nicer :)
Co-authored-by: LeoGrin <[email protected]>
Co-authored-by: LeoGrin <[email protected]>
Co-authored-by: LeoGrin <[email protected]>
4fbc81c
to
4855f08
Compare
Change Description
I reworked a lot of our logic in the client to achieve the following:
in our current client i still had the following:
easier to understand the state. the config is now very reduced and all 4 service classes are singletons
the api for the tokens got simpler, see README.md
i did some typing fixes
If you used new dependencies: Did you add them to
requirements.txt
?no
Who did you ping on Mattermost to review your PR? Please ping that person again whenever you are ready for another review.
@noahho @liam-sbhoo
Breaking changes
If you made any breaking changes, please update the version number.
Breaking changes are totally fine, we just need to make sure to keep the users informed and the server in sync.
Does this PR break the API? If so, what is the corresponding server commit?
No.
Does this PR break the user interface? If so, why?
Slightly, the part with setting the access tokens, which is very new, though.
Please do not mark comments/conversations as resolved unless you are the assigned reviewer. This helps maintain clarity during the review process.