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

Failure to import langserve because fastapi is missing #212

Open
cbornet opened this issue Nov 11, 2023 · 9 comments
Open

Failure to import langserve because fastapi is missing #212

cbornet opened this issue Nov 11, 2023 · 9 comments
Labels
help wanted Extra attention is needed

Comments

@cbornet
Copy link

cbornet commented Nov 11, 2023

LangServe declares fastapi as optional dependency but fastapi seems required.
In a new virtual env:

pip install langserve

>>> import langserve
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/private/tmp/pythonProject/lib/python3.11/site-packages/langserve/__init__.py", line 9, in <module>
    from langserve.server import add_routes
  File "/private/tmp/pythonProject/lib/python3.11/site-packages/langserve/server.py", line 28, in <module>
    from fastapi import HTTPException, Request, Response
ModuleNotFoundError: No module named 'fastapi'

I can fix with a PR if needed.

@eyurtsev
Copy link
Collaborator

Hi @cbornet thanks for reporting! This behavior is intentional -- Langserve contains both server and client code, and the client code should be installable without fastapi as a requirement.

Use the 'all' extra to install both client and server dependencies.

@eyurtsev eyurtsev added the wontfix This will not be worked on label Nov 11, 2023
@cbornet
Copy link
Author

cbornet commented Nov 12, 2023

Currently fastapi is a dependency of both the server and the client:

 python -m venv /tmp/venv 
source /tmp/venv/bin/activate
pip install "langserve[client]"
python

>>> from langserve import RemoteRunnable
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/private/tmp/venv/lib/python3.11/site-packages/langserve/__init__.py", line 9, in <module>
    from langserve.server import add_routes
  File "/private/tmp/venv/lib/python3.11/site-packages/langserve/server.py", line 28, in <module>
    from fastapi import HTTPException, Request, Response
ModuleNotFoundError: No module named 'fastapi'

It is because both the server and client code are imported in the root __init__.py : https://github.com/langchain-ai/langserve/blob/main/langserve/__init__.py#L7-L9

@eyurtsev
Copy link
Collaborator

Yeah :(

It's a bug -- tests aren't set up to catch that yet, once the tests are set up should be much easier hopefully

@Vinno97
Copy link

Vinno97 commented Dec 5, 2023

Is there any work on this? This issue currently has a wontfix label, but the current code makes the optional client and server dependency groups required anyways.

Like @cbornet mentioned, both the client and the server are imported in the root __init__.py.

I believe this leaves three solutions:

  • The root __init__.py needs to not import the submodules (luckily LangServe's API version is not yet in stable 1.x.x)
  • The imports are wrapped in try-catch statements (would make server not importable when the server dependencies are not installed, but I guess that could be intended behaviour)
  • The imports in the client and server code should be wrapped in if-statements/try-catch statements, with added exceptions when their logic is called. (would not change the API, would be more trouble than it's worth in my opinion)

@thaysom22
Copy link

I came across this because I want to use RemoteRunnable to invoke a runnable exposed with langserve in another service.

When I try to import it, I get this error. I'd prefer not to install fastapi as a dependency in my calling service, just to essentially make a http request, but I like the wrapper. I'm leaning towards just using requests instead of RemoteRunnable. Any suggestions?

@Vinno97
Copy link

Vinno97 commented May 1, 2024

Honestely? Just patch it yourself, it doesn't seem like they're ever going to patch this dumb design flaw. If you have control over the installations, any of the three options could work. Otherwise, you could do some very dirty import patching like this:

import sys

class fakemodule(object):
    @classmethod
    def __getattribute__(cls, name: str):
        return cls

sys.modules["fastapi"] = fakemodule()
sys.modules["fastapi.encoders"] = fakemodule()
sys.modules["fastapi.exceptions"] = fakemodule()
sys.modules["starlette"] = fakemodule()
sys.modules["starlette.requests"] = fakemodule()
sys.modules["starlette.responses"] = fakemodule()
sys.modules["fastapi.responses"] = fakemodule()

from langserve import RemoteRunnable

eyurtsev added a commit that referenced this issue Jun 10, 2024
Just a quickfix for #212.

It would be better not to have to install fastapi only for using the
client, but in my opinion this is still better then getting errors when
importing the `RemoteRunnable` after a `pip install
"langserve[client]"`.

Otherwise at least the readme should be updated.

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
@Vinno97
Copy link

Vinno97 commented Jul 2, 2024

@eyurtsev any update on this?

@eyurtsev
Copy link
Collaborator

eyurtsev commented Jul 2, 2024

Hi @Vinno97, I won't get to this soon, but I'm happy to review any PRs that fix this issue and happy to provide guidance on how to implement it.

@eyurtsev eyurtsev added help wanted Extra attention is needed and removed wontfix This will not be worked on labels Jul 2, 2024
@Vinno97
Copy link

Vinno97 commented Jul 3, 2024

Sure, I wouldn't mind taking this up. However, my prefered solution (the first option from my previous message), would require an API-breaking change. Its effect would be fairly minimal as people would just need to change out their imports for more specific ones, though it's still breaking:

from langserve import RemoteRunnable -> from langserve.client import RemoteRunnable
from langserve import add_routes, APIHandler -> from langserve.server import add_routes, APIHandler

For reference, my previous suggestions:

I believe this leaves three solutions:

  • The root init.py needs to not import the submodules (luckily LangServe's API version is not yet in stable 1.x.x)
  • The imports are wrapped in try-catch statements (would make server not importable when the server dependencies are not installed, but I guess that could be intended behaviour)
  • The imports in the client and server code should be wrapped in if-statements/try-catch statements, with added exceptions when their logic is called. (would not change the API, would be more trouble than it's worth in my opinion)

I am not aware of any method to detect the importing of a specific method. If that would be possible, we could print a deprecation notice for a version or two when people still use the from langserve import ... path, possibly making a hybrid out of option 1 and 2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants