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

Make login flow a tad nicer #48

Merged
merged 8 commits into from
Dec 20, 2024
Merged

Conversation

SamuelGabriel
Copy link
Collaborator

Change Description

I reworked a lot of our logic in the client to achieve the following:

  1. be able to log out

in our current client i still had the following:

In [1]: import tabpfn_client

In [2]: tabpfn_client.init()
  Welcome Back! Found existing access token, reusing it for authentication.

In [3]: tabpfn_client.reset()

In [4]: tabpfn_client.init()
  Welcome Back! Found existing access token, reusing it for authentication.
  1. easier to understand the state. the config is now very reduced and all 4 service classes are singletons

  2. the api for the tokens got simpler, see README.md

  3. 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.

Copy link
Collaborator

@noahho noahho left a 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?

@noahho
Copy link
Collaborator

noahho commented Nov 26, 2024

I just checked the OpenAI Api and they have client objects (not singletons)
image

Why did you introduce singletons here?

@SamuelGabriel
Copy link
Collaborator Author

SamuelGabriel commented Dec 16, 2024

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.

@LeoGrin
Copy link
Collaborator

LeoGrin commented Dec 16, 2024

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 deepcopy(ServiceClient) instead each time, which is a bit weird but should work? (I think the usage of ServiceClient in the GUI is not super natural anyway, because we want something stateless). Otherwise I don't have a strong opinion on whether we should be using singletons.

@@ -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"
Copy link
Collaborator

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

Copy link
Collaborator Author

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):
Copy link
Collaborator

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

Copy link
Collaborator Author

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

Copy link
Collaborator

@LeoGrin LeoGrin left a 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 :)

@SamuelGabriel SamuelGabriel force-pushed the make_login_flow_a_tad_nicer branch from 4fbc81c to 4855f08 Compare December 20, 2024 10:32
@SamuelGabriel SamuelGabriel merged commit 0899de6 into main Dec 20, 2024
2 checks passed
@SamuelGabriel SamuelGabriel deleted the make_login_flow_a_tad_nicer branch December 20, 2024 11:35
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.

3 participants