From b51300987fc4a953f2b93bba4c93df3d1265521e Mon Sep 17 00:00:00 2001 From: rileyok-ons <205916635+rileyok-ons@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:17:09 +0000 Subject: [PATCH 1/6] chore: updated all servers docstrings for better summary --- src/classifai/servers/__init__.py | 1 + src/classifai/servers/main.py | 5 ++- src/classifai/servers/pydantic_models.py | 52 +++++++++++++++--------- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/classifai/servers/__init__.py b/src/classifai/servers/__init__.py index 2652182..31156e5 100644 --- a/src/classifai/servers/__init__.py +++ b/src/classifai/servers/__init__.py @@ -1,4 +1,5 @@ """This module provides functionality for creating or extending a REST-API service. + This allows a user to call the search methods of one or more `VectorStore` objects, from an API endpoint. diff --git a/src/classifai/servers/main.py b/src/classifai/servers/main.py index 14c5f19..882d98e 100644 --- a/src/classifai/servers/main.py +++ b/src/classifai/servers/main.py @@ -1,5 +1,6 @@ # pylint: disable=C0301 """This module provides functionality for creating a start a restAPI service. + This allows a user to call the search methods of different VectorStore objects, from an api-endpoint. @@ -135,6 +136,8 @@ def get_server(vector_stores: list[VectorStore], endpoint_names: list[str]) -> F class LogLevel(StrEnum): + """Importance levels of Logs.""" + DEBUG = "debug" INFO = "info" WARNING = "warning" @@ -157,7 +160,7 @@ def run_server( # noqa: PLR0913 endpoint_names (list[str]): A list of endpoint names corresponding to the `VectorStore`s to be exposed. port (int): [optional] The port on which the API server will run. Defaults to 8000. host_ip (str): [optional] The ip address that the api server runs on. Defaults to 127.0.0.1, note: default 127.0.0.1 exposes to connections from the same machine only, to expose for external connections use 0.0.0.0. - log_level ( str ): [optional] The level of logs for the uvicorn server, levels are ['critial', 'error', 'warning', 'log', 'debug']. + log_level (str): [optional] The level of logs for the uvicorn server, levels are ['critial', 'error', 'warning', 'log', 'debug']. demo_mode (bool): [optional] Flag to show demo server info (Updates the openapi docs to show info indicating server is an api demo). Raises: diff --git a/src/classifai/servers/pydantic_models.py b/src/classifai/servers/pydantic_models.py index 3d05d9e..e49b6bc 100644 --- a/src/classifai/servers/pydantic_models.py +++ b/src/classifai/servers/pydantic_models.py @@ -6,8 +6,9 @@ class SearchRequestEntry(BaseModel): - """Atomic model for a single row of `VectorStore` search method input data (i.e. a single query input) , includes `id` and - `query`. + """Atomic model for a single row of `VectorStore` search method input data (i.e. a single query input). + + Includes `id` and `query`. """ id: str = Field(examples=["1"]) @@ -18,8 +19,9 @@ class SearchRequestEntry(BaseModel): class SearchRequestSet(BaseModel): - """Model for a list of many `SearchRequestEntry` Pydantic models, i.e. several queries to be searched - in the `VectorStore`. + """Model for a list of many `SearchRequestEntry` Pydantic models. + + i.e. several queries to be searched in the `VectorStore`. """ entries: list[SearchRequestEntry] = Field(description="array of search queries to be searched in the VectorStore.") @@ -38,7 +40,10 @@ class Config: class SearchResponseSet(BaseModel): - """Model for a list of many `SearchResponseEntry` Pydantic models, representing a ranked list of `VectorStore` search results for a provided query.""" + """Model for a list of many `SearchResponseEntry` Pydantic models. + + Representing a ranked list of `VectorStore` search results for a provided query. + """ query_id: str = Field(description="The id of the query input for which these are the search results.") query_text: str = Field(description="The text of the query input for which these are the search results.") @@ -48,8 +53,9 @@ class SearchResponseSet(BaseModel): class SearchResponseBody(BaseModel): - """Model for the overall search response body, which includes a list of `SearchResponseSet` objects, - representing the search results for each input query. + """Model for the overall search response body, which includes a list of `SearchResponseSet` objects. + + Representing the search results for each input query. """ data: list[SearchResponseSet] @@ -66,16 +72,18 @@ class ReverseSearchRequestEntry(BaseModel): class ReverseSearchRequestSet(BaseModel): - """Model for a list of many `ReverseSearchRequestEntry` Pydantic models, i.e. several `VectorStore` row entry - labels to be looked up in the `VectorStore`. + """Model for a list of many `ReverseSearchRequestEntry` Pydantic models. + + i.e. several `VectorStore` row entry labels to be looked up in the `VectorStore`. """ entries: list[ReverseSearchRequestEntry] = Field(description="array of VectorStore row entry labels to look up.") class ReverseSearchResponseEntry(BaseModel): - """Atomic model for single reverse search result entry, includes retrieved `doc_label` and `doc_text` which - are expected as str types. + """Atomic model for single reverse search result entry. + + Includes retrieved `doc_label` and `doc_text` which are expected as str types. """ doc_label: str @@ -86,8 +94,9 @@ class Config: class ReverseSearchResponseSet(BaseModel): - """Model for a list of many `ReverseSearchResponseEntry` pydnatic models, representing a list of `VectorStore` - entries found (partially) matching an input 'searched_doc_label' and corresponding input `id`. + """Model for a list of many `ReverseSearchResponseEntry` pydnatic models. + + Representing a list of `VectorStore` entries found (partially) matching an input 'searched_doc_label' and corresponding input `id`. """ input_id: str = Field( @@ -102,8 +111,9 @@ class ReverseSearchResponseSet(BaseModel): class ReverseSearchResponseBody(BaseModel): - """Model for the overall reverse search response body, which includes a list of `ReverseSearchResponseSet` - objects, representing the reverse search results for each input `VectorStore` row entry `id`. + """Model for the overall reverse search response body, which includes a list of `ReverseSearchResponseSet` objects. + + Representing the reverse search results for each input `VectorStore` row entry `id`. """ data: list[ReverseSearchResponseSet] @@ -119,7 +129,10 @@ class EmbedRequestEntry(BaseModel): class EmbedRequestSet(BaseModel): - """Model for a list of many `EmbedRequestEntry` Pydantic models, representing several text strings to be embedded with the `VectorStore` embed method.""" + """Model for a list of many `EmbedRequestEntry` Pydantic models. + + Representing several text strings to be embedded with the `VectorStore` embed method. + """ entries: list[EmbedRequestEntry] = Field( description="array of text entries to be embedded, with their corresponding text and id" @@ -150,8 +163,7 @@ class EmbedResponseBody(BaseModel): def convert_reverse_search_dataframe_to_pydantic_response( df: pd.DataFrame, meta_data: dict, original_input: list[dict] ) -> ReverseSearchResponseBody: - """Convert a `VectorStoreReverseSearchOutput` DataFrame into a JSON object conforming to the `ReverseSearchResponseBody` Pydantic - model. + """Convert a `VectorStoreReverseSearchOutput` DataFrame into a JSON object conforming to the `ReverseSearchResponseBody` Pydantic model. Args: df (pd.DataFrame): Pandas DataFrame containing reverse search results. @@ -235,8 +247,7 @@ def convert_reverse_search_dataframe_to_pydantic_response( def convert_search_dataframe_to_pydantic_response(df: pd.DataFrame, meta_data: dict) -> SearchResponseBody: - """Convert a `VectorStoreSearchOutput` DataFrame into a JSON object conforming to the `SearchResponseBody` Pydantic - model. + """Convert a `VectorStoreSearchOutput` DataFrame into a JSON object conforming to the `SearchResponseBody` Pydantic model. Args: df (pd.DataFrame): Pandas DataFrame containing search results. @@ -307,6 +318,7 @@ def convert_search_dataframe_to_pydantic_response(df: pd.DataFrame, meta_data: d def convert_embedding_dataframe_to_pydantic_response(df: pd.DataFrame) -> EmbedResponseBody: """Convert a `VectorStoreEmbedOutput` DataFrame into a JSON object conforming to the `EmbedResponseBody` Pydantic model. + Unlike the conversion functions for search and reverse search, this function does not take in a `meta_data` dictionary as an argument, as meta data comes from the `VectorStore` which is not accessed during the embedding process, and thus there are no reserved meta data columns to check for. Instead, this function identifies any extra columns in the DataFrame that are not `id`, `text` or `embedding` as "hook" columns, From 6ba2b55f73c528e00e675fe5912f6da75b20c666 Mon Sep 17 00:00:00 2001 From: rileyok-ons <205916635+rileyok-ons@users.noreply.github.com> Date: Thu, 25 Jun 2026 13:02:52 +0000 Subject: [PATCH 2/6] chore: added docstrings for log level checks --- src/classifai/servers/main.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/classifai/servers/main.py b/src/classifai/servers/main.py index 9a9b51e..2ec36ad 100644 --- a/src/classifai/servers/main.py +++ b/src/classifai/servers/main.py @@ -146,7 +146,14 @@ class LogLevel(str, Enum): def is_valid_log_level(value: str) -> bool: - """Check if `str` is valid log level.""" + """Check if `str` is valid log level. + + Args: + value: (str): Input log level + + Returns: + (bool) + """ return value in {e.value for e in LogLevel} From 81a7651232a3bbf873a0c9f55a8c12a5cc73e32e Mon Sep 17 00:00:00 2001 From: rileyok-ons <205916635+rileyok-ons@users.noreply.github.com> Date: Fri, 26 Jun 2026 09:23:15 +0000 Subject: [PATCH 3/6] chore: removed D205 exception --- pyproject.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bd27785..2fef534 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,8 +87,6 @@ select = [ ] ignore = [ - # Conflicts with google docstring style - "D205", # Allow missing docstring, remove to enforce docstrings across the board "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", # Disable line length check as it is handled by black From 53b6210391fcf2d6e4b965dfc9ed482209c00d61 Mon Sep 17 00:00:00 2001 From: rileyok-ons <205916635+rileyok-ons@users.noreply.github.com> Date: Fri, 26 Jun 2026 09:33:16 +0000 Subject: [PATCH 4/6] fix: readded D205 ignore as affects other branches --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2fef534..b47f2bd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,8 +87,10 @@ select = [ ] ignore = [ + # Conflicts with google docstring style + "D205", # Allow missing docstring, remove to enforce docstrings across the board - "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", + # "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", # Disable line length check as it is handled by black # :TODO: Remove E501 when ruff supports all black rules "E501", From 013bb897d563969ff8e89914bc089b0c763cf0e7 Mon Sep 17 00:00:00 2001 From: rileyok-ons <205916635+rileyok-ons@users.noreply.github.com> Date: Fri, 26 Jun 2026 10:02:10 +0000 Subject: [PATCH 5/6] chore: fixed the Dx ignores --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b47f2bd..bd27785 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -90,7 +90,7 @@ ignore = [ # Conflicts with google docstring style "D205", # Allow missing docstring, remove to enforce docstrings across the board - # "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", + "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", # Disable line length check as it is handled by black # :TODO: Remove E501 when ruff supports all black rules "E501", From 0f29aa0907eb9a223fd785912855f173938db7c0 Mon Sep 17 00:00:00 2001 From: rileyok-ons <205916635+rileyok-ons@users.noreply.github.com> Date: Fri, 26 Jun 2026 12:17:43 +0000 Subject: [PATCH 6/6] chore: improved docs --- src/classifai/servers/__init__.py | 6 +-- src/classifai/servers/main.py | 47 ++++++++++-------------- src/classifai/servers/pydantic_models.py | 6 +-- 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/classifai/servers/__init__.py b/src/classifai/servers/__init__.py index 31156e5..2551d4d 100644 --- a/src/classifai/servers/__init__.py +++ b/src/classifai/servers/__init__.py @@ -1,11 +1,11 @@ -"""This module provides functionality for creating or extending a REST-API service. +"""This module provides functionality for building and running ClassifAI as a REST API service. This allows a user to call the search methods of one or more `VectorStore` objects, from an API endpoint. These functions interact with the ClassifAI Indexer module's `VectorStore` objects, -such that their `embed`, `search` and `reverse_search` methods are exposed on -REST-API endpoints, via a FastAPI app. +such that their `embed`, `search` and `reverse_search` methods are exposed as +REST API endpoints, as a FastAPI service started with these functions. Full API documentation for FastAPI endpoints and Pydantic Models can be found in autogenerated app Swagger docs at `/docs`. diff --git a/src/classifai/servers/main.py b/src/classifai/servers/main.py index 2ec36ad..57baa74 100644 --- a/src/classifai/servers/main.py +++ b/src/classifai/servers/main.py @@ -1,12 +1,12 @@ # pylint: disable=C0301 -"""This module provides functionality for creating a start a restAPI service. +"""This module provides functionality for building and running ClassifAI as a REST API service. -This allows a user to call the search methods of different VectorStore objects, from -an api-endpoint. +This allows a user to call the search methods of one or more `VectorStore` objects, +from an API endpoint. -These functions interact with the ClassifAI PackageIndexer modules -VectorStore objects, such that their embed and search methods are exposed on -restAPI endpoints, in a FastAPI restAPI service started with these functions. +These functions interact with the ClassifAI Package's Indexer modules +`VectorStore` objects, such that their embed and search methods are exposed on +REST API endpoints, as a FastAPI service started with these functions. """ from __future__ import annotations @@ -96,7 +96,7 @@ def get_router(vector_stores: list[VectorStore], endpoint_names: list[str]) -> A make_endpoints(router, vector_stores_dict) @router.get("/", description="UI accessibility", tags=["docs"]) - def docs(): + def docs() -> RedirectResponse: """Redirect users to the API documentation page. Returns: @@ -136,7 +136,7 @@ def get_server(vector_stores: list[VectorStore], endpoint_names: list[str]) -> F class LogLevel(str, Enum): - """Valid importance levels of logs.""" + """Valid levels of logs.""" DEBUG = "debug" INFO = "info" @@ -146,14 +146,7 @@ class LogLevel(str, Enum): def is_valid_log_level(value: str) -> bool: - """Check if `str` is valid log level. - - Args: - value: (str): Input log level - - Returns: - (bool) - """ + """Check if `str` is valid log level.""" return value in {e.value for e in LogLevel} @@ -164,7 +157,7 @@ def run_server( # noqa: PLR0913 host_ip: str = "127.0.0.1", log_level: str = "warning", demo_mode: bool = False, -): +) -> None: """Create and run a `FastAPI` server with search endpoints. Args: @@ -206,7 +199,7 @@ def _set_demo_defaults(app: FastAPI): app.description = "This is a demo of the ClassifAI server module" -def make_endpoints(main_router: APIRouter | FastAPI, vector_stores_dict: dict[str, VectorStore]): +def make_endpoints(main_router: APIRouter | FastAPI, vector_stores_dict: dict[str, VectorStore]) -> None: """Create and register the different endpoints to your app. Args: @@ -227,13 +220,13 @@ def make_endpoints(main_router: APIRouter | FastAPI, vector_stores_dict: dict[st main_router.include_router(sub_router) -def _create_embedding_endpoint(router: APIRouter | FastAPI, endpoint_name: str, vector_store: VectorStore): - """Create and register an embedding endpoint for a specific `VectorStore`. +def _create_embedding_endpoint(router: APIRouter | FastAPI, endpoint_name: str, vector_store: VectorStore) -> None: + """Create and register an `embed` endpoint for a specific `VectorStore`. Args: router (APIRouter | FastAPI): The `FastAPI` application instance. endpoint_name (str): The name of the endpoint to be created. - vector_store: The vector store object responsible for generating embeddings. + vector_store (VectorStore): The vector store object responsible for generating embeddings. The created endpoint accepts POST requests with input data, generates embeddings for the provided documents, and returns the results in a structured format. @@ -258,13 +251,13 @@ async def embedding_endpoint(data: EmbedRequestSet) -> EmbedResponseBody: return formatted_result -def _create_search_endpoint(router: APIRouter | FastAPI, endpoint_name: str, vector_store: VectorStore): - """Create and register a search endpoint for a specific `VectorStore`. +def _create_search_endpoint(router: APIRouter | FastAPI, endpoint_name: str, vector_store: VectorStore) -> None: + """Create and register a `search` endpoint for a specific `VectorStore`. Args: router (APIRouter | FastAPI): The `FastAPI` application instance. endpoint_name (str): The name of the endpoint to be created. - vector_store: The `VectorStore` object responsible for performing search operations. + vector_store (VectorStore): The `VectorStore` object responsible for performing search operations. The created endpoint accepts POST requests with input data and a query parameter specifying the number of results to return. It performs a search operation using @@ -303,13 +296,13 @@ async def search_endpoint( return formatted_result -def _create_reverse_search_endpoint(router: APIRouter | FastAPI, endpoint_name: str, vector_store: VectorStore): - """Create and register a reverse_search endpoint for a specific vector store. +def _create_reverse_search_endpoint(router: APIRouter | FastAPI, endpoint_name: str, vector_store: VectorStore) -> None: + """Create and register a `reverse_search` endpoint for a specific vector store. Args: router (APIRouter | FastAPI): The `FastAPI` application instance. endpoint_name (str): The name of the endpoint to be created. - vector_store: The `VectorStore` object responsible for performing search operations. + vector_store (VectorStore): The `VectorStore` object responsible for performing search operations. The created endpoint accepts POST requests with input data and a query parameter specifying the number of results to return. It performs a reverse search operation using diff --git a/src/classifai/servers/pydantic_models.py b/src/classifai/servers/pydantic_models.py index e49b6bc..f908843 100644 --- a/src/classifai/servers/pydantic_models.py +++ b/src/classifai/servers/pydantic_models.py @@ -1,5 +1,5 @@ # pylint: disable=C0301 -"""Pydantic Classes to model request and response data for ClassifAI FastAPI RESTful API.""" +"""Pydantic Classes to model request and response data for ClassifAI FastAPI REST API.""" import pandas as pd from pydantic import BaseModel, Extra, Field @@ -21,10 +21,10 @@ class SearchRequestEntry(BaseModel): class SearchRequestSet(BaseModel): """Model for a list of many `SearchRequestEntry` Pydantic models. - i.e. several queries to be searched in the `VectorStore`. + i.e. several search query `entries` to be searched in the `VectorStore`. """ - entries: list[SearchRequestEntry] = Field(description="array of search queries to be searched in the VectorStore.") + entries: list[SearchRequestEntry] = Field(description="Array of search queries to be searched in the VectorStore.") class SearchResponseEntry(BaseModel):