From c5ef201755ad51c839ef199db54e07bdb7a35eb8 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Wed, 18 Oct 2023 16:22:24 -0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(store):=20add=20store=20servic?= =?UTF-8?q?e=20to=20integrate=20langflow=20with=20the=20store?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds the necessary files to implement the store service in langflow. The store service allows searching, getting, posting, and downloading components from the store. The store service is integrated with a Directus instance. The following files were added: - `src/backend/langflow/services/store/__init__.py`: Initializes the store service. - `src/backend/langflow/services/store/factory.py`: Implements the store service factory. - `src/backend/langflow/services/store/schema.py`: Defines the schema for the component response. - `src/backend/langflow/services/store/service.py`: Implements the store service, including methods for searching, listing components, downloading, and uploading components. The store service requires the `SettingsService` to be passed during initialization. The base URL and components URL are retrieved from the `MARKETPLACE_URL` setting. The store service provides the following methods: - `search`: Searches for components in the store based on various parameters. - `list_components`: Lists components from the store. - `download`: Downloads a specific component from the store. - `upload`: Uploads a new component to the store. The store service uses the `httpx` library to perform HTTP requests to the store API. The `_get` method is a utility method to perform GET requests with optional API key and parameters. The `ComponentResponse` schema defines the structure of the component response from the store. It includes various properties such as name, description, id, status, sort, user_created, date_created, user_updated, date_updated, is_component, likes, tags, data, and documentation. The `get_api_key` method is not implemented and will be completed in a future commit. --- .../{marketplace => store}/__init__.py | 0 .../{marketplace => store}/factory.py | 8 +++--- .../services/{marketplace => store}/schema.py | 0 .../{marketplace => store}/service.py | 27 ++++++++++++------- 4 files changed, 21 insertions(+), 14 deletions(-) rename src/backend/langflow/services/{marketplace => store}/__init__.py (100%) rename src/backend/langflow/services/{marketplace => store}/factory.py (54%) rename src/backend/langflow/services/{marketplace => store}/schema.py (100%) rename src/backend/langflow/services/{marketplace => store}/service.py (84%) diff --git a/src/backend/langflow/services/marketplace/__init__.py b/src/backend/langflow/services/store/__init__.py similarity index 100% rename from src/backend/langflow/services/marketplace/__init__.py rename to src/backend/langflow/services/store/__init__.py diff --git a/src/backend/langflow/services/marketplace/factory.py b/src/backend/langflow/services/store/factory.py similarity index 54% rename from src/backend/langflow/services/marketplace/factory.py rename to src/backend/langflow/services/store/factory.py index ae97943f8..a25ad78c7 100644 --- a/src/backend/langflow/services/marketplace/factory.py +++ b/src/backend/langflow/services/store/factory.py @@ -1,14 +1,14 @@ from typing import TYPE_CHECKING -from langflow.services.marketplace.service import MarketplaceService +from langflow.services.store.service import StoreService from langflow.services.factory import ServiceFactory if TYPE_CHECKING: from langflow.services.settings.service import SettingsService -class MarketplaceServiceFactory(ServiceFactory): +class StoreServiceFactory(ServiceFactory): def __init__(self): - super().__init__(MarketplaceService) + super().__init__(StoreService) def create(self, settings_service: "SettingsService"): - return MarketplaceService(settings_service) + return StoreService(settings_service) diff --git a/src/backend/langflow/services/marketplace/schema.py b/src/backend/langflow/services/store/schema.py similarity index 100% rename from src/backend/langflow/services/marketplace/schema.py rename to src/backend/langflow/services/store/schema.py diff --git a/src/backend/langflow/services/marketplace/service.py b/src/backend/langflow/services/store/service.py similarity index 84% rename from src/backend/langflow/services/marketplace/service.py rename to src/backend/langflow/services/store/service.py index 6a7bb1010..a6b4b8400 100644 --- a/src/backend/langflow/services/marketplace/service.py +++ b/src/backend/langflow/services/store/service.py @@ -3,18 +3,18 @@ from langflow.services.base import Service from typing import TYPE_CHECKING, List, Dict, Any, Optional import httpx from httpx import HTTPError -from langflow.services.marketplace.schema import ComponentResponse +from langflow.services.store.schema import ComponentResponse if TYPE_CHECKING: from langflow.services.settings.service import SettingsService -class MarketplaceService(Service): - """This is a service that integrates langflow with the marketplace which +class StoreService(Service): + """This is a service that integrates langflow with the store which is a Directus instance. It allows to search, get and post components to - the marketplace.""" + the store.""" - name = "marketplace_service" + name = "store_service" def __init__(self, settings_service: "SettingsService"): self.settings_service = settings_service @@ -25,7 +25,10 @@ class MarketplaceService(Service): self, url: str, api_key: str, params: Dict[str, Any] = None ) -> List[Dict[str, Any]]: """Utility method to perform GET requests.""" - headers = {"Authorization": f"Bearer {api_key}"} + if api_key: + headers = {"Authorization": f"Bearer {api_key}"} + else: + headers = {} try: response = httpx.get(url, headers=headers, params=params) response.raise_for_status() @@ -35,7 +38,7 @@ class MarketplaceService(Service): def search( self, - api_key: str, + api_key: Optional[str], query: str, page: int = 1, limit: int = 10, @@ -44,7 +47,8 @@ class MarketplaceService(Service): date_from: Optional[datetime] = None, date_to: Optional[datetime] = None, sort_by: Optional[str] = "likes", - sort_order: Optional[str] = "desc", # or "asc" + sort: Optional[List[str]] = None, + fields: Optional[List[str]] = None, ) -> List[ComponentResponse]: params = { "filter[name][_like]": query, @@ -65,8 +69,11 @@ class MarketplaceService(Service): if date_to: params["filter[date_updated][_lte]"] = date_to.isoformat() - if sort_order: - params["sort"] = f"{sort_order}_{sort_by}" + if sort: + params["sort"] = ",".join(sort) + + if fields: + params["fields"] = ",".join(fields) results = self._get(self.components_url, api_key, params) return [ComponentResponse(**component) for component in results]