Spaces:
Running
Running
import importlib | |
import inspect | |
from typing import TYPE_CHECKING, get_type_hints | |
from cachetools import LRUCache, cached | |
from loguru import logger | |
from langflow.services.schema import ServiceType | |
if TYPE_CHECKING: | |
from langflow.services.base import Service | |
class ServiceFactory: | |
def __init__( | |
self, | |
service_class, | |
) -> None: | |
self.service_class = service_class | |
self.dependencies = infer_service_types(self, import_all_services_into_a_dict()) | |
def create(self, *args, **kwargs) -> "Service": | |
raise self.service_class(*args, **kwargs) | |
def hash_factory(factory: ServiceFactory) -> str: | |
return factory.service_class.__name__ | |
def hash_dict(d: dict) -> str: | |
return str(d) | |
def hash_infer_service_types_args(factory: ServiceFactory, available_services=None) -> str: | |
factory_hash = hash_factory(factory) | |
services_hash = hash_dict(available_services) | |
return f"{factory_hash}_{services_hash}" | |
def infer_service_types(factory: ServiceFactory, available_services=None) -> list["ServiceType"]: | |
create_method = factory.create | |
type_hints = get_type_hints(create_method, globalns=available_services) | |
service_types = [] | |
for param_name, param_type in type_hints.items(): | |
# Skip the return type if it's included in type hints | |
if param_name == "return": | |
continue | |
# Convert the type to the expected enum format directly without appending "_SERVICE" | |
type_name = param_type.__name__.upper().replace("SERVICE", "_SERVICE") | |
try: | |
# Attempt to find a matching enum value | |
service_type = ServiceType[type_name] | |
service_types.append(service_type) | |
except KeyError as e: | |
msg = f"No matching ServiceType for parameter type: {param_type.__name__}" | |
raise ValueError(msg) from e | |
return service_types | |
def import_all_services_into_a_dict(): | |
# Services are all in langflow.services.{service_name}.service | |
# and are subclass of Service | |
# We want to import all of them and put them in a dict | |
# to use as globals | |
from langflow.services.base import Service | |
services = {} | |
for service_type in ServiceType: | |
try: | |
service_name = ServiceType(service_type).value.replace("_service", "") | |
module_name = f"langflow.services.{service_name}.service" | |
module = importlib.import_module(module_name) | |
services.update( | |
{ | |
name: obj | |
for name, obj in inspect.getmembers(module, inspect.isclass) | |
if issubclass(obj, Service) and obj is not Service | |
} | |
) | |
except Exception as exc: | |
logger.exception(exc) | |
msg = "Could not initialize services. Please check your settings." | |
raise RuntimeError(msg) from exc | |
return services | |