From 2f47c529d39a616710656eafdb63e5b5b9701b8d Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 31 Oct 2023 11:45:06 +0000 Subject: [PATCH 1/3] Fix crash when mounting same chain twice in same app The crash was due to Config.configurable pydantic base model not being renamed, fixed by recursively renaming field annotations which are themselves base models --- langserve/server.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/langserve/server.py b/langserve/server.py index 563fceb4..8f2f0d2f 100644 --- a/langserve/server.py +++ b/langserve/server.py @@ -110,14 +110,16 @@ def _unpack_input(validated_model: BaseModel) -> Any: return model -def _rename_pydantic_model(model: Type[BaseModel], name: str) -> Type[BaseModel]: +def _rename_pydantic_model(model: Type[BaseModel], prefix: str) -> Type[BaseModel]: """Rename the given pydantic model to the given name.""" return create_model( - name, + prefix + model.__name__, __config__=model.__config__, **{ fieldname: ( - field.annotation, + _rename_pydantic_model(field.annotation, prefix) + if issubclass(field.annotation, BaseModel) + else field.annotation, Field( field.default, title=fieldname, @@ -155,7 +157,7 @@ def _resolve_model( if model.__name__ in _SEEN_NAMES and hash_ not in _MODEL_REGISTRY: # If the model name has been seen before, but the model itself is different # generate a new name for the model. - model_to_use = _rename_pydantic_model(model, f"{namespace}{model.__name__}") + model_to_use = _rename_pydantic_model(model, namespace) hash_ = model_to_use.schema_json() else: model_to_use = model @@ -180,10 +182,7 @@ def _add_namespace_to_model(namespace: str, model: Type[BaseModel]) -> Type[Base Returns: A new model with name prepended with the given namespace. """ - model_with_unique_name = _rename_pydantic_model( - model, - f"{namespace}{model.__name__}", - ) + model_with_unique_name = _rename_pydantic_model(model, namespace) model_with_unique_name.update_forward_refs() return model_with_unique_name From 19360c6b62188900f95ee4c256ddc8c8342fcc31 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 31 Oct 2023 11:47:54 +0000 Subject: [PATCH 2/3] Lint --- langserve/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langserve/server.py b/langserve/server.py index 8f2f0d2f..28332137 100644 --- a/langserve/server.py +++ b/langserve/server.py @@ -118,7 +118,7 @@ def _rename_pydantic_model(model: Type[BaseModel], prefix: str) -> Type[BaseMode **{ fieldname: ( _rename_pydantic_model(field.annotation, prefix) - if issubclass(field.annotation, BaseModel) + if isclass(field.annotation) and issubclass(field.annotation, BaseModel) else field.annotation, Field( field.default, From 555494bfd73ae6935a1f408caf2571449485f4e2 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Tue, 31 Oct 2023 11:49:23 +0000 Subject: [PATCH 3/3] Update test --- tests/unit_tests/test_server_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_server_client.py b/tests/unit_tests/test_server_client.py index 8767c3e4..39401144 100644 --- a/tests/unit_tests/test_server_client.py +++ b/tests/unit_tests/test_server_client.py @@ -920,7 +920,7 @@ class Foo(BaseModel): Model = _rename_pydantic_model(Foo, "Bar") assert isinstance(Model, type) - assert Model.__name__ == "Bar" + assert Model.__name__ == "BarFoo" @pytest.mark.asyncio