From 28e8379c4669fb901cdf76c0d34d6a75752db275 Mon Sep 17 00:00:00 2001 From: jphillips Date: Tue, 18 Mar 2025 11:55:57 -0500 Subject: [PATCH 01/24] Add perspective tags, modules, and local loading. Signed-off-by: jphillips --- .cursor/rules/task.mdc | 171 +++++++++- pyproject.toml | 4 +- .../graphcap/perspectives/__init__.py | 214 +++++++++++-- .../graphcap/perspectives/loaders/__init__.py | 20 ++ .../perspectives/loaders/directory.py | 28 ++ .../perspectives/loaders/json_file.py | 46 +++ .../graphcap/perspectives/loaders/modules.py | 303 ++++++++++++++++++ .../graphcap/perspectives/loaders/settings.py | 43 +++ .../graphcap/perspectives/models.py | 56 ++++ .../graphcap/perspectives/module.py | 38 +++ .../perspectives/perspective_loader.py | 288 +++-------------- .../graphcap/perspectives/processor.py | 198 ++++++++++++ .../graphcap/providers/clients/__init__.py | 3 +- .../graphcap/providers/clients/base_client.py | 4 +- .../providers/clients/gemini_client.py | 1 - .../providers/clients/ollama_client.py | 6 +- .../graphcap/providers/factory.py | 26 +- .../graphcap/providers/provider_manager.py | 8 +- servers/inference_server/pyproject.toml | 3 +- .../inference_server/server/server/config.py | 2 +- .../server/features/perspectives/__init__.py | 2 +- .../server/features/perspectives/models.py | 29 +- .../server/features/perspectives/router.py | 33 +- .../server/features/perspectives/service.py | 99 +++--- .../server/features/providers/__init__.py | 2 +- .../server/features/providers/models.py | 6 +- .../server/features/providers/router.py | 22 +- .../server/features/providers/service.py | 14 +- .../server/features/repositories/types.py | 2 +- .../server/server/pipelines/dagster_client.py | 1 + .../server/server/utils/resizing.py | 88 ++--- .../tests/test_perspective_modules.py | 187 +++++++++++ servers/inference_server/uv.lock | 115 +++++++ workspace/config/perspective_settings.json | 37 +++ .../art_critic.json | 7 +- .../custom_caption.json | 7 +- .../emotional_sentiment.json | 7 +- .../graph_caption.json | 7 +- .../locality_graph.json | 7 +- .../out_of_frame.json | 7 +- .../poetic_metaphor.json | 7 +- .../simple_temporarium.json | 7 +- .../storytelling.json | 7 +- .../synthesized_caption.json | 7 +- .../temporarium.json | 7 +- .../time_tags.json | 7 +- 46 files changed, 1718 insertions(+), 465 deletions(-) create mode 100644 servers/inference_server/graphcap/perspectives/loaders/__init__.py create mode 100644 servers/inference_server/graphcap/perspectives/loaders/directory.py create mode 100644 servers/inference_server/graphcap/perspectives/loaders/json_file.py create mode 100644 servers/inference_server/graphcap/perspectives/loaders/modules.py create mode 100644 servers/inference_server/graphcap/perspectives/loaders/settings.py create mode 100644 servers/inference_server/graphcap/perspectives/models.py create mode 100644 servers/inference_server/graphcap/perspectives/module.py create mode 100644 servers/inference_server/graphcap/perspectives/processor.py create mode 100644 servers/inference_server/tests/test_perspective_modules.py create mode 100644 workspace/config/perspective_settings.json rename workspace/{config/perspectives => perspective_library}/art_critic.json (86%) rename workspace/{config/perspectives => perspective_library}/custom_caption.json (74%) rename workspace/{config/perspectives => perspective_library}/emotional_sentiment.json (77%) rename workspace/{config/perspectives => perspective_library}/graph_caption.json (92%) rename workspace/{config/perspectives => perspective_library}/locality_graph.json (92%) rename workspace/{config/perspectives => perspective_library}/out_of_frame.json (90%) rename workspace/{config/perspectives => perspective_library}/poetic_metaphor.json (91%) rename workspace/{config/perspectives => perspective_library}/simple_temporarium.json (86%) rename workspace/{config/perspectives => perspective_library}/storytelling.json (86%) rename workspace/{config/perspectives => perspective_library}/synthesized_caption.json (90%) rename workspace/{config/perspectives => perspective_library}/temporarium.json (89%) rename workspace/{config/perspectives => perspective_library}/time_tags.json (85%) diff --git a/.cursor/rules/task.mdc b/.cursor/rules/task.mdc index f0517dcc..c1689c67 100644 --- a/.cursor/rules/task.mdc +++ b/.cursor/rules/task.mdc @@ -3,5 +3,172 @@ description: Current Task for the Agent globs: alwaysApply: true --- -# Feature Request: -We are reworking and cleaning up our ui architecture. Please utilize our best practices and style guidelines. \ No newline at end of file +### Is your feature request related to a problem? +Currently perspectives are loaded from a flat directory from files with minimal metadata. We should add support for perspective directories to be able to toggle on and off different modules. We should also allow support for loading and writing to perspectives in a certain instance to allow for prototyping without comitting new code. + +### Describe the solution you'd like +- Add directory loading of perspectives +- Add support for a local perspective directory +- Add additional metadata tags to perspective schema +- Add ability to add and edit perspectives to help with iteration +- Add route to ui for viewing, testing, and authoring new perspectives +- Add basic versioning ui +- Add graceful handling of deprecated / removed perspectives + +## Current State Analysis + +1. The `load_all_perspectives` function in `perspective_loader.py` already recursively searches for JSON files using `config_dir.rglob("*.json")`. +2. While it finds files in subdirectories, it doesn't appear to organize them in a hierarchical structure. +3. The loader attempts to load each JSON file as a perspective but doesn't handle modules or grouping. +4. The current implementation uses a flat dictionary to store perspectives by name. + +## Issues to Address + +1. The current code doesn't have a concept of perspective modules/groups. +2. There's no mechanism to toggle modules on/off. +3. No support for local perspective directory for prototyping. +4. Missing metadata for categorization and organization. +5. No versioning or handling of deprecated perspectives. + +## Implementation Plan + +### 1. Enhanced Perspective Metadata Structure + +We need to extend the `PerspectiveConfig` model to include: + +```python +class PerspectiveConfig(BaseModel): + """Configuration for a perspective loaded from JSON.""" + # Existing fields + name: str + display_name: str + version: str + prompt: str + schema_fields: List[SchemaField] + table_columns: List[Dict[str, str]] + context_template: str + + # New fields + module: str = Field(default="default", description="Module this perspective belongs to") + tags: List[str] = Field(default_factory=list, description="Tags for categorizing perspectives") + description: str = Field(default="", description="Detailed description of the perspective") + deprecated: bool = Field(default=False, description="Whether this perspective is deprecated") + replacement: Optional[str] = Field(default=None, description="Name of perspective that replaces this one") + priority: int = Field(default=100, description="Priority for sorting (lower is higher priority)") +``` + +### 2. Hierarchical Perspective Loading + +Create a new data structure to represent module-based perspectives: + +```python +class PerspectiveModule: + """Represents a module of related perspectives.""" + name: str + display_name: str + enabled: bool + perspectives: Dict[str, JsonPerspectiveProcessor] + + def toggle(self, enabled: bool) -> None: + """Toggle this module on or off.""" + self.enabled = enabled +``` + +Modify the perspective loader to organize perspectives by module: + +```python +def load_all_perspectives(config_dir: Union[str, Path]) -> Dict[str, PerspectiveModule]: + """Load perspectives organized by module.""" + # Implementation details +``` + +### 3. Local Perspective Directory Support + +Create a mechanism to support local perspectives alongside the main ones: + +```python +def get_perspective_directories() -> List[Path]: + """Get all directories where perspectives can be found.""" + dirs = [WORKSPACE_PERSPECTIVES_DIR] + + # Check for local perspective directory + local_dir = Path.home() / ".graphcap" / "perspectives" + if local_dir.exists(): + dirs.append(local_dir) + + return dirs +``` + +### 4. Configuration Update for Module Control + +Create a configuration file to control module enablement: + +```json +{ + "modules": { + "core": {"enabled": true}, + "experimental": {"enabled": false}, + "deprecated": {"enabled": false} + }, + "local_override": true +} +``` + +### 5. Testing Plan + +#### Unit Tests + +1. **Schema Loading Test**: Verify that perspectives with the new metadata fields load correctly. +2. **Module Structure Test**: Ensure perspectives are properly organized into modules. +3. **Directory Structure Test**: Test that the loader correctly handles nested directory structures. +4. **Local Override Test**: Verify that local perspectives can override workspace perspectives. +5. **Toggling Test**: Ensure that modules can be toggled on and off. + +#### Integration Tests + +1. **API Integration Test**: Test that the API correctly returns perspectives based on module enablement. +2. **UI Integration Test**: Test that the UI correctly displays perspectives organized by module. +3. **Versioning Test**: Test that versioning information is correctly displayed and used. + +#### Test Data Structure + +Create a test directory structure: +``` +test_perspectives/ +├── core/ +│ ├── base_caption.json +│ └── custom_caption.json +├── experimental/ +│ ├── new_technique.json +│ └── beta_feature.json +└── local/ + └── prototype_caption.json +``` + +## UI Component for Perspective Management + +Develop a React component for managing perspectives: +- Allow viewing all perspectives organized by module +- Enable toggling modules on/off +- Provide UI for testing perspectives +- Include version management interface +- Display deprecation warnings for deprecated perspectives + +## Implementation Steps + +1. Update the `PerspectiveConfig` model with new metadata fields +2. Implement the hierarchical perspective loading structure +3. Add local perspective directory support +4. Create configuration mechanism for module control +5. Implement tests for all new functionality +6. Develop UI components for perspective management +7. Add APIs for perspective CRUD operations + +## Potential Challenges + +1. **Backward Compatibility**: Ensure old perspectives still work with the new system +2. **Performance**: Loading many perspectives from nested directories might impact startup time +3. **Conflict Resolution**: Handle conflicts between workspace and local perspectives +4. **Schema Evolution**: Support for evolving perspective schemas across versions + +This plan addresses all the requirements in the task while maintaining compatibility with the existing codebase. The approach enhances the perspective loader to support modular organization, local development, versioning, and deprecation handling. diff --git a/pyproject.toml b/pyproject.toml index f029d36c..99491de5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ exclude = [ ] # Source directories -src = ["./src"] +src = ["./servers/inference_server"] # Same as Black line-length = 120 @@ -61,7 +61,7 @@ target-version = "py311" [tool.ruff.lint] # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default select = ["E", "F", "W", "I001"] -ignore = [] +ignore = ["W293"] # Allow fix for all enabled rules (when `--fix`) is provided fixable = ["ALL"] diff --git a/servers/inference_server/graphcap/perspectives/__init__.py b/servers/inference_server/graphcap/perspectives/__init__.py index 189aba86..fffa256b 100644 --- a/servers/inference_server/graphcap/perspectives/__init__.py +++ b/servers/inference_server/graphcap/perspectives/__init__.py @@ -1,36 +1,58 @@ """ # SPDX-License-Identifier: Apache-2.0 -Caption Perspectives Module +Perspectives Package -Collection of different perspectives for analyzing and captioning images. -Each perspective provides a unique way of understanding and describing visual content. - -Perspectives are defined in JSON configuration files in workspace/config/perspectives directory. -Each perspective configuration specifies its analysis approach and prompting strategy. -Perspectives can be organized in subdirectories for better organization. +Provides utilities for working with different perspectives/views of data. """ from pathlib import Path -from typing import Dict, List +from typing import Any, Dict, List, Optional from loguru import logger from .constants import WORKSPACE_PERSPECTIVES_DIR -from .perspective_loader import JsonPerspectiveProcessor, load_all_perspectives +from .perspective_loader import ( + # Classes + JsonPerspectiveProcessor, + ModuleConfig, + PerspectiveConfig, + PerspectiveModule, + PerspectiveSettings, + # Models + SchemaField, + get_all_modules, + # Functions + get_perspective_directories, + load_all_perspectives, + load_module_settings, + load_perspective_config, + load_perspective_from_json, +) # Load JSON-based perspectives from workspace config _json_perspectives: Dict[str, JsonPerspectiveProcessor] = {} +_modules: Dict[str, PerspectiveModule] = {} + +# Get all perspective directories +perspective_dirs = get_perspective_directories() +logger.info(f"Looking for perspectives in: {perspective_dirs}") + +# Load module settings +settings = load_module_settings() + +# Load perspectives organized by modules +try: + _modules = get_all_modules(perspective_dirs, settings) + _json_perspectives = load_all_perspectives(perspective_dirs, settings) -logger.info(f"Looking for perspectives in: {WORKSPACE_PERSPECTIVES_DIR}") -logger.info(f"Directory exists: {WORKSPACE_PERSPECTIVES_DIR.exists()}") -if WORKSPACE_PERSPECTIVES_DIR.exists(): - logger.info(f"Directory contents: {list(WORKSPACE_PERSPECTIVES_DIR.glob('*.json'))}") - _json_perspectives = load_all_perspectives(WORKSPACE_PERSPECTIVES_DIR) - logger.info( - f"Loaded {len(_json_perspectives)} perspectives from workspace configurations: {list(_json_perspectives.keys())}" - ) -else: - logger.warning(f"No perspective configurations found at {WORKSPACE_PERSPECTIVES_DIR}") + # Log loaded modules and perspectives + enabled_modules = [name for name, module in _modules.items() if module.enabled] + logger.info(f"Loaded {len(_modules)} modules: {list(_modules.keys())}") + logger.info(f"Enabled modules: {enabled_modules}") + logger.info(f"Loaded {len(_json_perspectives)} perspectives: {list(_json_perspectives.keys())}") +except Exception as e: + logger.error(f"Error loading perspectives: {str(e)}") + logger.exception(e) def get_perspective(perspective_name: str, **kwargs): @@ -52,7 +74,7 @@ def get_perspective(perspective_name: str, **kwargs): available = list(_json_perspectives.keys()) logger.error(f"Perspective {perspective_name} not found. Available: {available}") - logger.error(f"Perspectives directory contents: {list(WORKSPACE_PERSPECTIVES_DIR.glob('*.json'))}") + logger.error(f"Perspectives directories: {perspective_dirs}") raise ValueError(f"Unknown perspective: {perspective_name}. Available perspectives: {available}") @@ -66,6 +88,103 @@ def get_perspective_list() -> List[str]: return list(_json_perspectives.keys()) +def get_perspective_modules() -> Dict[str, PerspectiveModule]: + """ + Get all perspective modules. + + Returns: + Dictionary mapping module names to module objects + """ + return _modules + + +def get_module_perspectives(module_name: str) -> Dict[str, JsonPerspectiveProcessor]: + """ + Get all perspectives in a specific module. + + Args: + module_name: The name of the module + + Returns: + Dictionary mapping perspective names to processors + + Raises: + ValueError: If the module name is unknown + """ + if module_name in _modules: + return _modules[module_name].get_perspectives() + + available = list(_modules.keys()) + raise ValueError(f"Unknown module: {module_name}. Available modules: {available}") + + +def get_perspectives_by_tag(tag: str) -> Dict[str, JsonPerspectiveProcessor]: + """ + Get all perspectives with a specific tag. + + Args: + tag: The tag to filter by + + Returns: + Dictionary mapping perspective names to processors + """ + result = {} + for name, perspective in _json_perspectives.items(): + if tag in perspective.tags: + result[name] = perspective + return result + + +def get_perspectives_by_tags(tags: List[str], match_all: bool = False) -> Dict[str, JsonPerspectiveProcessor]: + """ + Get all perspectives matching the specified tags. + + Args: + tags: List of tags to filter by + match_all: If True, perspective must have all tags; if False, any matching tag is sufficient + + Returns: + Dictionary mapping perspective names to processors + """ + result = {} + for name, perspective in _json_perspectives.items(): + if match_all: + # All tags must match + if all(tag in perspective.tags for tag in tags): + result[name] = perspective + else: + # Any tag match is sufficient + if any(tag in perspective.tags for tag in tags): + result[name] = perspective + return result + + +def toggle_module(module_name: str, enabled: bool) -> None: + """ + Toggle a module on or off. + + Args: + module_name: The name of the module to toggle + enabled: Whether to enable or disable the module + + Raises: + ValueError: If the module name is unknown + """ + if module_name not in _modules: + available = list(_modules.keys()) + raise ValueError(f"Unknown module: {module_name}. Available modules: {available}") + + _modules[module_name].toggle(enabled) + + # Reload perspectives to reflect changes + global _json_perspectives + _json_perspectives = {} + for name, module in _modules.items(): + if module.enabled: + for perspective_name, perspective in module.perspectives.items(): + _json_perspectives[perspective_name] = perspective + + def get_synthesizer() -> JsonPerspectiveProcessor: """ Get the synthesized caption processor. @@ -82,9 +201,58 @@ def get_synthesizer() -> JsonPerspectiveProcessor: raise ValueError("Synthesized caption perspective not found in JSON configurations") +def get_non_deprecated_perspectives() -> Dict[str, JsonPerspectiveProcessor]: + """ + Get all non-deprecated perspectives. + + Returns: + Dictionary mapping perspective names to processors + """ + return {name: p for name, p in _json_perspectives.items() if not p.is_deprecated} + + +def get_perspective_metadata() -> List[Dict[str, Any]]: + """ + Get metadata for all perspectives. + + Returns: + List of dictionaries with perspective metadata + """ + result = [] + for name, perspective in _json_perspectives.items(): + result.append( + { + "name": name, + "display_name": perspective.display_name, + "version": perspective.version, + "module": perspective.module_name, + "tags": perspective.tags, + "description": perspective.description, + "deprecated": perspective.is_deprecated, + "replacement": perspective.replacement, + "priority": perspective.priority, + } + ) + + # Sort by priority (lowest first) + result.sort(key=lambda x: x["priority"]) + return result + + __all__ = [ + # Models + "SchemaField", + "PerspectiveConfig", + "ModuleConfig", + "PerspectiveSettings", + # Classes "JsonPerspectiveProcessor", - "get_perspective", - "get_perspective_list", - "get_synthesizer", + "PerspectiveModule", + # Functions + "get_perspective_directories", + "load_perspective_config", + "load_perspective_from_json", + "get_all_modules", + "load_all_perspectives", + "load_module_settings", ] diff --git a/servers/inference_server/graphcap/perspectives/loaders/__init__.py b/servers/inference_server/graphcap/perspectives/loaders/__init__.py new file mode 100644 index 00000000..779e0628 --- /dev/null +++ b/servers/inference_server/graphcap/perspectives/loaders/__init__.py @@ -0,0 +1,20 @@ +""" +# SPDX-License-Identifier: Apache-2.0 +Perspective Loaders Package + +Contains utilities for loading perspectives from various sources. +""" + +from .directory import get_perspective_directories +from .json_file import load_perspective_config, load_perspective_from_json +from .modules import get_all_modules, load_all_perspectives +from .settings import load_module_settings + +__all__ = [ + "get_perspective_directories", + "load_perspective_config", + "load_perspective_from_json", + "get_all_modules", + "load_all_perspectives", + "load_module_settings", +] diff --git a/servers/inference_server/graphcap/perspectives/loaders/directory.py b/servers/inference_server/graphcap/perspectives/loaders/directory.py new file mode 100644 index 00000000..76d9d583 --- /dev/null +++ b/servers/inference_server/graphcap/perspectives/loaders/directory.py @@ -0,0 +1,28 @@ +""" +# SPDX-License-Identifier: Apache-2.0 +Directory Loader Module + +Provides functions for finding directories that contain perspective files. +""" + +from pathlib import Path +from typing import List + + +def get_perspective_directories() -> List[Path]: + """Get all directories where perspectives can be found.""" + from ..constants import WORKSPACE_PERSPECTIVES_DIR + + dirs = [WORKSPACE_PERSPECTIVES_DIR] + + # Check for local perspective directory in user's home + local_dir = Path.home() / ".graphcap" / "perspectives" + if local_dir.exists(): + dirs.append(local_dir) + + # Also check for "perspective_library" directory that seems to be used + perspective_library = Path("/workspace") / "perspective_library" + if perspective_library.exists(): + dirs.append(perspective_library) + + return dirs diff --git a/servers/inference_server/graphcap/perspectives/loaders/json_file.py b/servers/inference_server/graphcap/perspectives/loaders/json_file.py new file mode 100644 index 00000000..316c2ebd --- /dev/null +++ b/servers/inference_server/graphcap/perspectives/loaders/json_file.py @@ -0,0 +1,46 @@ +""" +# SPDX-License-Identifier: Apache-2.0 +JSON File Loader + +Provides utilities for loading perspective configurations from JSON files. +""" + +import json +from pathlib import Path +from typing import Union + +from ..models import PerspectiveConfig +from ..processor import JsonPerspectiveProcessor + + +def load_perspective_config(config_path: Union[str, Path]) -> PerspectiveConfig: + """Load a perspective configuration from a JSON file.""" + with open(config_path, "r") as f: + config_data = json.load(f) + + return PerspectiveConfig(**config_data) + + +def load_perspective_from_json(config_path: Union[str, Path]) -> JsonPerspectiveProcessor: + """Load and instantiate a perspective from a JSON configuration file.""" + config = load_perspective_config(config_path) + return JsonPerspectiveProcessor(config) + + +def prepare_module_from_file_path(config_data: dict, json_path: Path, config_dir: Path) -> None: + """ + Prepare module information from file path if not specified in config. + + Args: + config_data: The perspective configuration data + json_path: Path to the JSON file + config_dir: Base directory for perspectives + """ + # If module is not specified in the file, use directory name as module + if "module" not in config_data: + # Use parent directory name as module, or "default" if at root + rel_path = json_path.relative_to(config_dir) + if len(rel_path.parts) > 1: + config_data["module"] = rel_path.parts[0] + else: + config_data["module"] = "default" diff --git a/servers/inference_server/graphcap/perspectives/loaders/modules.py b/servers/inference_server/graphcap/perspectives/loaders/modules.py new file mode 100644 index 00000000..52e8c727 --- /dev/null +++ b/servers/inference_server/graphcap/perspectives/loaders/modules.py @@ -0,0 +1,303 @@ +""" +# SPDX-License-Identifier: Apache-2.0 +Module Loader + +Provides utilities for loading perspective modules and organizing +perspectives by module. +""" + +import json +from pathlib import Path +from typing import Dict, List, Optional, Set, Tuple + +from loguru import logger + +from ..models import PerspectiveConfig, PerspectiveSettings +from ..module import PerspectiveModule +from ..processor import JsonPerspectiveProcessor +from .directory import get_perspective_directories +from .json_file import prepare_module_from_file_path +from .settings import load_module_settings + + +def find_json_files(config_dir: Path) -> List[Path]: + """ + Find all JSON files in a directory recursively. + + Args: + config_dir: Directory to search + + Returns: + List of paths to JSON files + """ + if not config_dir.exists(): + logger.warning(f"Perspective directory does not exist: {config_dir}") + return [] + + logger.info(f"Scanning for JSON files in: {config_dir}") + json_files = list(config_dir.rglob("*.json")) + logger.info(f"Found {len(json_files)} JSON files in {config_dir}") + return json_files + + +def load_json_file(json_path: Path) -> Optional[dict]: + """ + Load a JSON file safely. + + Args: + json_path: Path to the JSON file + + Returns: + Loaded JSON data as a dictionary, or None if loading failed + """ + logger.info(f"Attempting to load perspective from: {json_path}") + try: + with open(json_path, "r", encoding="utf-8") as f: + config_data = json.load(f) + logger.info(f"Successfully read JSON from: {json_path}") + return config_data + except Exception as e: + logger.error(f"Failed to load perspective from {json_path}: {str(e)}") + logger.exception(e) # This will log the full stack trace + return None + + +def validate_perspective_name(config_data: dict, json_path: Path, processed_names: Set[str]) -> Optional[str]: + """ + Validate the perspective name and check for duplicates. + + Args: + config_data: The perspective configuration data + json_path: Path to the JSON file + processed_names: Set of already processed perspective names + + Returns: + The perspective name if valid, None otherwise + """ + name = config_data.get("name") + if not name: + logger.warning(f"Skipping {json_path}: Missing 'name' field") + return None + + # Check for duplicates - later files override earlier ones + if name in processed_names: + logger.info(f"Duplicate perspective name '{name}' found in {json_path}, overriding previous definition") + + return name + + +def create_perspective_processor( + config_data: dict, json_path: Path, config_dir: Path +) -> Optional[JsonPerspectiveProcessor]: + """ + Create a perspective processor from config data. + + Args: + config_data: The perspective configuration data + json_path: Path to the JSON file + config_dir: Base directory for perspectives + + Returns: + JsonPerspectiveProcessor instance, or None if creation failed + """ + try: + # Prepare module information from file path if not specified + prepare_module_from_file_path(config_data, json_path, config_dir) + + # Create perspective config and processor + config = PerspectiveConfig(**config_data) + perspective = JsonPerspectiveProcessor(config) + + return perspective + except Exception as e: + logger.error(f"Failed to create PerspectiveConfig from {json_path}: {str(e)}") + return None + + +def prepare_module(module_name: str, settings: PerspectiveSettings) -> PerspectiveModule: + """ + Prepare a module with appropriate settings. + + Args: + module_name: The name of the module + settings: Perspective settings + + Returns: + New PerspectiveModule instance + """ + # Create module with default settings or from config + display_name = module_name.replace("_", " ").title() + if module_name in settings.modules and settings.modules[module_name].display_name: + module_display_name = settings.modules[module_name].display_name + # Ensure display_name is not None + if module_display_name is not None: + display_name = module_display_name + + enabled = True + if module_name in settings.modules: + enabled = settings.modules[module_name].enabled + + return PerspectiveModule( + name=module_name, + display_name=display_name, + enabled=enabled, + ) + + +def process_json_file( + json_path: Path, + config_dir: Path, + modules: Dict[str, PerspectiveModule], + processed_names: Set[str], + settings: PerspectiveSettings, +) -> Tuple[Optional[str], Optional[JsonPerspectiveProcessor]]: + """ + Process a single JSON file and create perspective processor. + + Args: + json_path: Path to the JSON file + config_dir: Base directory for perspectives + modules: Dictionary of existing modules + processed_names: Set of already processed perspective names + settings: Perspective settings + + Returns: + Tuple of (perspective_name, perspective_processor) or (None, None) if processing failed + """ + # Load the JSON file + config_data = load_json_file(json_path) + if not config_data: + return None, None + + # Validate the perspective name + name = validate_perspective_name(config_data, json_path, processed_names) + if not name: + return None, None + + # Create the perspective processor + perspective = create_perspective_processor(config_data, json_path, config_dir) + if not perspective: + return None, None + + # Get or create the module + module_name = perspective.module_name + if module_name not in modules: + modules[module_name] = prepare_module(module_name, settings) + + # Add perspective to module + modules[module_name].add_perspective(perspective) + + logger.info(f"Successfully loaded perspective '{name}' from {json_path} in module '{module_name}'") + return name, perspective + + +def process_config_directory( + config_dir: Path, + modules: Dict[str, PerspectiveModule], + processed_names: Set[str], + perspectives_by_name: Dict[str, JsonPerspectiveProcessor], + settings: PerspectiveSettings, +) -> None: + """ + Process all JSON files in a config directory. + + Args: + config_dir: Directory to search for JSON files + modules: Dictionary of modules to update + processed_names: Set of processed perspective names + perspectives_by_name: Dictionary of perspectives by name + settings: Perspective settings + """ + # Find all JSON files + json_files = find_json_files(config_dir) + + # Process each JSON file + for json_path in json_files: + name, perspective = process_json_file(json_path, config_dir, modules, processed_names, settings) + + if name and perspective: + processed_names.add(name) + perspectives_by_name[name] = perspective + + +def get_all_modules( + config_dirs: Optional[List[Path]] = None, + settings: Optional[PerspectiveSettings] = None, +) -> Dict[str, PerspectiveModule]: + """ + Load all perspective configurations and return organized by modules. + + Args: + config_dirs: List of directories to search for perspective JSON files + settings: Optional settings controlling which modules are enabled + + Returns: + Dictionary mapping module names to module objects + """ + if config_dirs is None: + config_dirs = get_perspective_directories() + + if settings is None: + settings = load_module_settings() + + # Track loaded modules and processed perspective names + modules: Dict[str, PerspectiveModule] = {} + processed_names: Set[str] = set() + + # Process each config directory + for config_dir in config_dirs: + process_config_directory( + config_dir, + modules, + processed_names, + {}, # Dummy perspectives_by_name - not used by get_all_modules + settings, + ) + + logger.info(f"Total modules loaded: {len(modules)}") + logger.info(f"Module names: {list(modules.keys())}") + + return modules + + +def load_all_perspectives( + config_dirs: Optional[List[Path]] = None, + settings: Optional[PerspectiveSettings] = None, +) -> Dict[str, JsonPerspectiveProcessor]: + """ + Load all perspective configurations from directories and organize them by modules. + + Args: + config_dirs: List of directories to search for perspective JSON files + settings: Optional settings controlling which modules are enabled + + Returns: + Dictionary mapping perspective names to their processors + """ + if config_dirs is None: + config_dirs = get_perspective_directories() + + if settings is None: + settings = load_module_settings() + + # Track loaded modules and perspectives + modules: Dict[str, PerspectiveModule] = {} + perspectives_by_name: Dict[str, JsonPerspectiveProcessor] = {} + processed_names: Set[str] = set() + + # Process each config directory + for config_dir in config_dirs: + process_config_directory(config_dir, modules, processed_names, perspectives_by_name, settings) + + # Return flat dictionary for backward compatibility + result = {} + for module_name, module in modules.items(): + if module.enabled: + for name, perspective in module.perspectives.items(): + result[name] = perspective + + logger.info(f"Total perspectives loaded: {len(result)}") + logger.info(f"Loaded perspective names: {list(result.keys())}") + logger.info(f"Modules: {list(modules.keys())}") + + return result diff --git a/servers/inference_server/graphcap/perspectives/loaders/settings.py b/servers/inference_server/graphcap/perspectives/loaders/settings.py new file mode 100644 index 00000000..06d7ec37 --- /dev/null +++ b/servers/inference_server/graphcap/perspectives/loaders/settings.py @@ -0,0 +1,43 @@ +""" +# SPDX-License-Identifier: Apache-2.0 +Perspective Settings Loader + +Provides utilities for loading perspective module settings from configuration files. +""" + +import json +from pathlib import Path +from typing import Union + +from loguru import logger + +from ..models import PerspectiveSettings + + +def load_module_settings(settings_path: Union[str, Path, None] = None) -> PerspectiveSettings: + """ + Load module settings from a JSON file. + + Args: + settings_path: Path to the settings file, or None to use the default + + Returns: + PerspectiveSettings model with loaded settings or defaults + """ + default_settings = PerspectiveSettings() + + if settings_path is None: + # Default settings path + settings_path = Path("/workspace") / "config" / "perspective_settings.json" + + if not Path(settings_path).exists(): + logger.info(f"No module settings found at {settings_path}, using defaults") + return default_settings + + try: + with open(settings_path, "r") as f: + settings_data = json.load(f) + return PerspectiveSettings(**settings_data) + except Exception as e: + logger.error(f"Failed to load module settings from {settings_path}: {str(e)}") + return default_settings diff --git a/servers/inference_server/graphcap/perspectives/models.py b/servers/inference_server/graphcap/perspectives/models.py new file mode 100644 index 00000000..882afdeb --- /dev/null +++ b/servers/inference_server/graphcap/perspectives/models.py @@ -0,0 +1,56 @@ +""" +# SPDX-License-Identifier: Apache-2.0 +Perspective Models Module + +Contains the data models used for perspective configuration and management. +""" + +from typing import Any, Dict, List, Optional + +from pydantic import BaseModel, Field +from typing_extensions import override + +from .base import PerspectiveData + + +class SchemaField(BaseModel): + """Definition of a field in a perspective schema.""" + + name: str + type: str + description: str + is_list: bool = False + + +class PerspectiveConfig(BaseModel): + """Configuration for a perspective loaded from JSON.""" + + name: str + display_name: str + version: str + prompt: str + schema_fields: List[SchemaField] + table_columns: List[Dict[str, str]] + context_template: str + + # Metadata fields + module: str = Field(default="default", description="Module this perspective belongs to") + tags: List[str] = Field(default_factory=list, description="Tags for categorizing perspectives") + description: str = Field(default="", description="Detailed description of the perspective") + deprecated: bool = Field(default=False, description="Whether this perspective is deprecated") + replacement: Optional[str] = Field(default=None, description="Name of perspective that replaces this one") + priority: int = Field(default=100, description="Priority for sorting (lower is higher priority)") + + +class ModuleConfig(BaseModel): + """Configuration for module settings.""" + + enabled: bool = True + display_name: Optional[str] = None + + +class PerspectiveSettings(BaseModel): + """Settings for perspectives configuration.""" + + modules: Dict[str, ModuleConfig] = {} + local_override: bool = True diff --git a/servers/inference_server/graphcap/perspectives/module.py b/servers/inference_server/graphcap/perspectives/module.py new file mode 100644 index 00000000..755d3774 --- /dev/null +++ b/servers/inference_server/graphcap/perspectives/module.py @@ -0,0 +1,38 @@ +""" +# SPDX-License-Identifier: Apache-2.0 +Perspective Module + +Provides module functionality for organizing perspectives into groups +that can be enabled or disabled. +""" + +from typing import Dict + +from pydantic import BaseModel + +from .processor import JsonPerspectiveProcessor + + +class PerspectiveModule(BaseModel): + """Represents a module of related perspectives.""" + + name: str + display_name: str + enabled: bool = True + perspectives: Dict[str, JsonPerspectiveProcessor] = {} + + model_config = {"arbitrary_types_allowed": True} + + def toggle(self, enabled: bool) -> None: + """Toggle this module on or off.""" + self.enabled = enabled + + def get_perspectives(self) -> Dict[str, JsonPerspectiveProcessor]: + """Get all perspectives in this module if enabled.""" + if not self.enabled: + return {} + return self.perspectives + + def add_perspective(self, perspective: JsonPerspectiveProcessor) -> None: + """Add a perspective to this module.""" + self.perspectives[perspective.config.name] = perspective diff --git a/servers/inference_server/graphcap/perspectives/perspective_loader.py b/servers/inference_server/graphcap/perspectives/perspective_loader.py index 1ef870d1..c44a5e23 100644 --- a/servers/inference_server/graphcap/perspectives/perspective_loader.py +++ b/servers/inference_server/graphcap/perspectives/perspective_loader.py @@ -6,251 +6,43 @@ This module reduces code duplication by allowing perspectives to be defined declaratively. """ -import json -from pathlib import Path -from typing import Any, Dict, List, Union - -from loguru import logger -from pydantic import BaseModel, Field, create_model -from rich.table import Table -from typing_extensions import override - -from .base import BasePerspective, PerspectiveData - - -class SchemaField(BaseModel): - """Definition of a field in a perspective schema.""" - - name: str - type: str - description: str - is_list: bool = False - - -class PerspectiveConfig(BaseModel): - """Configuration for a perspective loaded from JSON.""" - - name: str - display_name: str - version: str - prompt: str - schema_fields: List[SchemaField] - table_columns: List[Dict[str, str]] - context_template: str - - -class JsonPerspectiveProcessor(BasePerspective): - """ - Processor for perspectives defined in JSON configuration files. - - This class dynamically creates schema models and implements methods - based on the configuration provided in the JSON file. - """ - - def __init__(self, config: PerspectiveConfig): - """Initialize the processor with a JSON configuration.""" - self.config = config - self.display_name = config.display_name - - # Dynamically create schema model from JSON definition - schema_fields = {} - for field in config.schema_fields: - field_type = self._get_field_type(field.type, field.is_list) - schema_fields[field.name] = (field_type, Field(description=field.description)) - - # Create the schema model dynamically - schema_class = create_model(f"{config.name.capitalize()}Schema", __base__=PerspectiveData, **schema_fields) - - super().__init__( - config_name=config.name, - version=config.version, - prompt=config.prompt, - schema=schema_class, - ) - - def _get_field_type(self, type_name: str, is_list: bool) -> Any: - """Convert string type name to actual Python type.""" - type_map = { - "str": str, - "int": int, - "float": float, - "bool": bool, - } - - base_type = type_map.get(type_name, str) - if is_list: - return List[base_type] - return base_type - - @override - def create_rich_table(self, caption_data: Dict[str, Any]) -> Table: - """Create Rich table for displaying caption data based on JSON config.""" - result = caption_data["parsed"] - - table = Table(show_header=True, header_style="bold magenta", expand=True) - - # Add columns based on configuration - for column in self.config.table_columns: - table.add_column(column["name"], style=column.get("style", "default")) - - # Add rows based on schema fields - rows = [] - for field in self.config.schema_fields: - field_name = field.name - field_value = result.get(field_name, "") - - # Format list values if needed - if field.is_list and isinstance(field_value, list): - field_value = "\n".join(f"• {item}" for item in field_value) - - rows.append(field_value) - - table.add_row(*rows) - logger.info(f"Generated {self.display_name} for {caption_data['filename']}") - return table - - @override - def write_outputs(self, job_dir: Path, caption_data: Dict[str, Any]) -> None: - """Write perspective outputs to the job directory.""" - result = caption_data["parsed"] - - # Create output dictionary - output = {"filename": caption_data["filename"], "analysis": {}} - - # Add each field from the parsed result - for field in self.config.schema_fields: - field_name = field.name - output["analysis"][field_name] = result.get(field_name, "") - - # Write to JSON file - response_file = job_dir / f"{self.config.name}_response.json" - with response_file.open("a") as f: - json.dump(output, f, indent=2) - f.write("\n") # Separate entries by newline - - @override - def to_table(self, caption_data: Dict[str, Any]) -> Dict[str, Any]: - """Convert perspective data to a flat dictionary.""" - result = caption_data.get("parsed", {}) - - # Check for error - if "error" in result: - return { - "filename": caption_data.get("filename", "unknown"), - "error": result["error"], - } - - # Create output dictionary with filename - output = {"filename": caption_data.get("filename", "unknown")} - - # Add each field from the parsed result - for field in self.config.schema_fields: - field_name = field.name - field_value = result.get(field_name, "") - - # Format list values if needed - if field.is_list and isinstance(field_value, list): - field_value = ", ".join(field_value) - - output[field_name] = field_value - - return output - - @override - def to_context(self, caption_data: Dict[str, Any]) -> str: - """Convert perspective data to a context string using the template.""" - result = caption_data.get("parsed", {}) - - # Replace placeholders in the template with actual values - context = self.config.context_template - for field in self.config.schema_fields: - field_name = field.name - field_value = result.get(field_name, "") - - # Format list values if needed - if field.is_list and isinstance(field_value, list): - field_value = ", ".join(field_value) - - # Replace placeholder with value - placeholder = f"{{{field_name}}}" - context = context.replace(placeholder, str(field_value)) - - return context - - @property - def config_name(self) -> str: - """Get the configuration name.""" - return self.config.name - - @property - def version(self) -> str: - """Get the perspective version.""" - return self.config.version - - -def load_perspective_config(config_path: Union[str, Path]) -> PerspectiveConfig: - """Load a perspective configuration from a JSON file.""" - with open(config_path, "r") as f: - config_data = json.load(f) - - return PerspectiveConfig(**config_data) - - -def load_perspective_from_json(config_path: Union[str, Path]) -> JsonPerspectiveProcessor: - """Load and instantiate a perspective from a JSON configuration file.""" - config = load_perspective_config(config_path) - return JsonPerspectiveProcessor(config) - - -def load_all_perspectives(config_dir: Union[str, Path]) -> Dict[str, JsonPerspectiveProcessor]: - """ - Load all perspective configurations from a directory and its subdirectories. - - Args: - config_dir: Path to the directory containing perspective JSON configurations - - Returns: - Dictionary mapping perspective names to their processors - """ - config_dir = Path(config_dir) - perspectives: Dict[str, JsonPerspectiveProcessor] = {} - - logger.info(f"Scanning for JSON files in: {config_dir}") - # Recursively find all JSON files - json_files = list(config_dir.rglob("*.json")) - logger.info(f"Found JSON files: {json_files}") - - for json_path in json_files: - logger.info(f"Attempting to load perspective from: {json_path}") - try: - with open(json_path, "r", encoding="utf-8") as f: - config_data = json.load(f) - logger.info(f"Successfully read JSON from: {json_path}") - - # Each perspective must have a unique name - name = config_data.get("name") - if not name: - logger.warning(f"Skipping {json_path}: Missing 'name' field") - continue - - if name in perspectives: - logger.warning(f"Duplicate perspective name '{name}' found in {json_path}, skipping") - continue - - # Convert the dictionary to a PerspectiveConfig model - try: - config = PerspectiveConfig(**config_data) - perspectives[name] = JsonPerspectiveProcessor(config) - logger.info(f"Successfully loaded perspective '{name}' from {json_path}") - except Exception as e: - logger.error(f"Failed to create PerspectiveConfig from {json_path}: {str(e)}") - continue - - except Exception as e: - logger.error(f"Failed to load perspective from {json_path}: {str(e)}") - logger.exception(e) # This will log the full stack trace - continue - - logger.info(f"Total perspectives loaded: {len(perspectives)}") - logger.info(f"Loaded perspective names: {list(perspectives.keys())}") - return perspectives +# Re-export models for backward compatibility +# Re-export loader functions +from .loaders import ( + get_all_modules, + get_perspective_directories, + load_all_perspectives, + load_module_settings, + load_perspective_config, + load_perspective_from_json, +) +from .models import ( + ModuleConfig, + PerspectiveConfig, + PerspectiveSettings, + SchemaField, +) + +# Re-export module +from .module import PerspectiveModule + +# Re-export processor +from .processor import JsonPerspectiveProcessor + +__all__ = [ + # Models + "SchemaField", + "PerspectiveConfig", + "ModuleConfig", + "PerspectiveSettings", + # Classes + "JsonPerspectiveProcessor", + "PerspectiveModule", + # Functions + "get_perspective_directories", + "load_perspective_config", + "load_perspective_from_json", + "get_all_modules", + "load_all_perspectives", + "load_module_settings", +] diff --git a/servers/inference_server/graphcap/perspectives/processor.py b/servers/inference_server/graphcap/perspectives/processor.py new file mode 100644 index 00000000..482c4d9c --- /dev/null +++ b/servers/inference_server/graphcap/perspectives/processor.py @@ -0,0 +1,198 @@ +""" +# SPDX-License-Identifier: Apache-2.0 +Perspective Processor Module + +Provides implementation of the perspective processor class that handles +dynamically created schema models and implements conversion methods. +""" + +import json +from pathlib import Path +from typing import Any, Dict, List, Optional + +from loguru import logger +from pydantic import Field, create_model +from rich.table import Table +from typing_extensions import override + +from .base import BasePerspective, PerspectiveData +from .models import PerspectiveConfig + + +class JsonPerspectiveProcessor(BasePerspective): + """ + Processor for perspectives defined in JSON configuration files. + + This class dynamically creates schema models and implements methods + based on the configuration provided in the JSON file. + """ + + def __init__(self, config: PerspectiveConfig): + """Initialize the processor with a JSON configuration.""" + self.config = config + self.display_name = config.display_name + + # Dynamically create schema model from JSON definition + schema_fields = {} + for field in config.schema_fields: + field_type = self._get_field_type(field.type, field.is_list) + schema_fields[field.name] = (field_type, Field(description=field.description)) + + # Create the schema model dynamically + schema_class = create_model(f"{config.name.capitalize()}Schema", __base__=PerspectiveData, **schema_fields) + + super().__init__( + config_name=config.name, + version=config.version, + prompt=config.prompt, + schema=schema_class, + ) + + def _get_field_type(self, type_name: str, is_list: bool) -> Any: + """Convert string type name to actual Python type.""" + type_map = { + "str": str, + "int": int, + "float": float, + "bool": bool, + } + + base_type = type_map.get(type_name, str) + if is_list: + return List[base_type] + return base_type + + @override + def create_rich_table(self, caption_data: Dict[str, Any]) -> Table: + """Create Rich table for displaying caption data based on JSON config.""" + result = caption_data["parsed"] + + table = Table(show_header=True, header_style="bold magenta", expand=True) + + # Add columns based on configuration + for column in self.config.table_columns: + table.add_column(column["name"], style=column.get("style", "default")) + + # Add rows based on schema fields + rows = [] + for field in self.config.schema_fields: + field_name = field.name + field_value = result.get(field_name, "") + + # Format list values if needed + if field.is_list and isinstance(field_value, list): + field_value = "\n".join(f"• {item}" for item in field_value) + + rows.append(field_value) + + table.add_row(*rows) + logger.info(f"Generated {self.display_name} for {caption_data['filename']}") + return table + + @override + def write_outputs(self, job_dir: Path, caption_data: Dict[str, Any]) -> None: + """Write perspective outputs to the job directory.""" + result = caption_data["parsed"] + + # Create output dictionary + output = {"filename": caption_data["filename"], "analysis": {}} + + # Add each field from the parsed result + for field in self.config.schema_fields: + field_name = field.name + output["analysis"][field_name] = result.get(field_name, "") + + # Write to JSON file + response_file = job_dir / f"{self.config.name}_response.json" + with response_file.open("a") as f: + json.dump(output, f, indent=2) + f.write("\n") # Separate entries by newline + + @override + def to_table(self, caption_data: Dict[str, Any]) -> Dict[str, Any]: + """Convert perspective data to a flat dictionary.""" + result = caption_data.get("parsed", {}) + + # Check for error + if "error" in result: + return { + "filename": caption_data.get("filename", "unknown"), + "error": result["error"], + } + + # Create output dictionary with filename + output = {"filename": caption_data.get("filename", "unknown")} + + # Add each field from the parsed result + for field in self.config.schema_fields: + field_name = field.name + field_value = result.get(field_name, "") + + # Format list values if needed + if field.is_list and isinstance(field_value, list): + field_value = ", ".join(field_value) + + output[field_name] = field_value + + return output + + @override + def to_context(self, caption_data: Dict[str, Any]) -> str: + """Convert perspective data to a context string using the template.""" + result = caption_data.get("parsed", {}) + + # Replace placeholders in the template with actual values + context = self.config.context_template + for field in self.config.schema_fields: + field_name = field.name + field_value = result.get(field_name, "") + + # Format list values if needed + if field.is_list and isinstance(field_value, list): + field_value = ", ".join(field_value) + + # Replace placeholder with value + placeholder = f"{{{field_name}}}" + context = context.replace(placeholder, str(field_value)) + + return context + + @property + def config_name(self) -> str: + """Get the configuration name.""" + return self.config.name + + @property + def version(self) -> str: + """Get the perspective version.""" + return self.config.version + + @property + def module_name(self) -> str: + """Get the module name.""" + return self.config.module + + @property + def tags(self) -> List[str]: + """Get the perspective tags.""" + return self.config.tags + + @property + def description(self) -> str: + """Get the perspective description.""" + return self.config.description + + @property + def is_deprecated(self) -> bool: + """Check if the perspective is deprecated.""" + return self.config.deprecated + + @property + def replacement(self) -> Optional[str]: + """Get the replacement perspective name if deprecated.""" + return self.config.replacement + + @property + def priority(self) -> int: + """Get the perspective priority.""" + return self.config.priority diff --git a/servers/inference_server/graphcap/providers/clients/__init__.py b/servers/inference_server/graphcap/providers/clients/__init__.py index 96b1a13b..6666d098 100644 --- a/servers/inference_server/graphcap/providers/clients/__init__.py +++ b/servers/inference_server/graphcap/providers/clients/__init__.py @@ -29,7 +29,7 @@ from .vllm_client import VLLMClient -def get_client(kind: str, **kwargs) -> BaseClient: +def get_client(kind: str, **kwargs) -> BaseClient: client: BaseClient logger.info(f"Creating client for {kind} with args: {kwargs}") if kind == "openai": @@ -46,6 +46,7 @@ def get_client(kind: str, **kwargs) -> BaseClient: raise ValueError(f"Unknown provider kind: {kind}") return client + __all__ = [ "BaseClient", "GeminiClient", diff --git a/servers/inference_server/graphcap/providers/clients/base_client.py b/servers/inference_server/graphcap/providers/clients/base_client.py index 01d804e1..f2401492 100644 --- a/servers/inference_server/graphcap/providers/clients/base_client.py +++ b/servers/inference_server/graphcap/providers/clients/base_client.py @@ -133,13 +133,13 @@ async def vision( """Create a vision completion with rate limiting""" logger.info(f"Starting vision request for model: {model}") logger.debug(f"Vision parameters - max_tokens: {max_tokens}, temperature: {temperature}, top_p: {top_p}") - + # Estimate token count - this is approximate estimated_tokens = len(prompt.split()) + 1000 # Base tokens + image tokens logger.debug(f"Estimated token count: {estimated_tokens}") await self._enforce_rate_limits(estimated_tokens) - + # Handle image input if isinstance(image, (str, Path)) and not str(image).startswith("data:"): logger.debug(f"Loading image from path: {image}") diff --git a/servers/inference_server/graphcap/providers/clients/gemini_client.py b/servers/inference_server/graphcap/providers/clients/gemini_client.py index 18b5ebda..4e232c56 100644 --- a/servers/inference_server/graphcap/providers/clients/gemini_client.py +++ b/servers/inference_server/graphcap/providers/clients/gemini_client.py @@ -54,7 +54,6 @@ def create_structured_completion( json_schema = self._get_schema_from_input(schema) try: - completion = self.chat.completions.create( model=model, messages=messages, response_format={"type": "json_schema", "schema": json_schema}, **kwargs ) diff --git a/servers/inference_server/graphcap/providers/clients/ollama_client.py b/servers/inference_server/graphcap/providers/clients/ollama_client.py index aea52294..fe42c180 100644 --- a/servers/inference_server/graphcap/providers/clients/ollama_client.py +++ b/servers/inference_server/graphcap/providers/clients/ollama_client.py @@ -33,10 +33,10 @@ def __init__(self, name: str, kind: str, environment: str, env_var: str, base_ur logger.info(f" - environment: {environment}") logger.info(f" - base_url: {base_url}") logger.info(f" - default_model: {default_model}") - + # Store the raw base URL for Ollama-specific endpoints base_url = base_url.rstrip("/") - + # For OpenAI compatibility, we need /v1 in the URL # But we need to handle cases where it's already there if "/v1" in base_url: @@ -50,7 +50,7 @@ def __init__(self, name: str, kind: str, environment: str, env_var: str, base_ur self._raw_base_url = base_url openai_base_url = f"{base_url}/v1" logger.debug("Adding /v1 to base URL for OpenAI compatibility") - + # Initialize with OpenAI-compatible base URL super().__init__( name=name, diff --git a/servers/inference_server/graphcap/providers/factory.py b/servers/inference_server/graphcap/providers/factory.py index 90a806f7..efbac5ab 100644 --- a/servers/inference_server/graphcap/providers/factory.py +++ b/servers/inference_server/graphcap/providers/factory.py @@ -22,15 +22,15 @@ def initialize_provider_manager(config_path: Optional[str | Path] = None) -> ProviderManager: """Initialize the global provider manager with the given config path. - + Args: config_path: Path to the provider configuration file. If None, uses default locations. - + Returns: ProviderManager: The initialized provider manager """ global _provider_manager - + if config_path is None: # Try to find config in standard locations possible_paths = [ @@ -40,19 +40,19 @@ def initialize_provider_manager(config_path: Optional[str | Path] = None) -> Pro "/app/provider.config.toml", "/app/config/provider.config.toml", ] - + for path in possible_paths: if path and Path(path).exists(): config_path = path break - + if not config_path or not Path(str(config_path)).exists(): logger.warning(f"No provider config found at {config_path}. Using empty configuration.") # Create a temporary empty config file with tempfile.NamedTemporaryFile(delete=False, suffix=".toml") as temp: temp.write(b"# Empty provider config\n") config_path = temp.name - + # At this point, config_path should not be None _provider_manager = ProviderManager(str(config_path)) return _provider_manager @@ -60,26 +60,26 @@ def initialize_provider_manager(config_path: Optional[str | Path] = None) -> Pro def get_provider_client(provider_name: str = "default") -> BaseClient: """Get a provider client by name. - + Args: provider_name: Name of the provider to get. Defaults to "default". - + Returns: BaseClient: The provider client - + Raises: ValueError: If the provider is not found """ global _provider_manager - + if _provider_manager is None: initialize_provider_manager() - + if _provider_manager is None: raise ValueError("Failed to initialize provider manager") - + try: return _provider_manager.get_client(provider_name) except ValueError as e: logger.error(f"Failed to get provider client: {e}") - raise \ No newline at end of file + raise diff --git a/servers/inference_server/graphcap/providers/provider_manager.py b/servers/inference_server/graphcap/providers/provider_manager.py index 405cada6..8db97294 100644 --- a/servers/inference_server/graphcap/providers/provider_manager.py +++ b/servers/inference_server/graphcap/providers/provider_manager.py @@ -62,7 +62,7 @@ def get_client(self, provider_name: str) -> BaseClient: logger.info(f" - environment: {config.environment}") logger.info(f" - base_url: {config.base_url}") logger.info(f" - default_model: {config.default_model}") - + try: client = get_client( name=provider_name, @@ -75,7 +75,9 @@ def get_client(self, provider_name: str) -> BaseClient: # Set rate limits if configured if config.rate_limits: - logger.debug(f"Setting rate limits for {provider_name} - requests: {config.rate_limits.requests_per_minute}/min, tokens: {config.rate_limits.tokens_per_minute}/min") + logger.debug( + f"Setting rate limits for {provider_name} - requests: {config.rate_limits.requests_per_minute}/min, tokens: {config.rate_limits.tokens_per_minute}/min" + ) client.requests_per_minute = config.rate_limits.requests_per_minute client.tokens_per_minute = config.rate_limits.tokens_per_minute @@ -109,4 +111,4 @@ def get_provider_config(self, provider_name: str) -> ProviderConfig: logger.error(f"Requested config for unknown provider: {provider_name}") raise ValueError(f"Unknown provider: {provider_name}") logger.debug(f"Returning config for provider: {provider_name}") - return self.providers[provider_name] \ No newline at end of file + return self.providers[provider_name] diff --git a/servers/inference_server/pyproject.toml b/servers/inference_server/pyproject.toml index b68d20dd..af588a00 100644 --- a/servers/inference_server/pyproject.toml +++ b/servers/inference_server/pyproject.toml @@ -10,6 +10,7 @@ dependencies = [ "openai>=1.63.2", "pydantic>=2.10.6", "rich>=13.9.4", + "tenacity>=9.0.0", ] [dependency-groups] @@ -71,7 +72,7 @@ target-version = "py311" [tool.ruff.lint] # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default select = ["E", "F", "W", "I001"] -ignore = [] +ignore = ["W293"] # Allow fix for all enabled rules (when `--fix`) is provided fixable = ["ALL"] diff --git a/servers/inference_server/server/server/config.py b/servers/inference_server/server/server/config.py index ad83fbe1..024ac23d 100644 --- a/servers/inference_server/server/server/config.py +++ b/servers/inference_server/server/server/config.py @@ -42,7 +42,7 @@ def __init__(self, **kwargs): # If provider config not set, default to config directory if not self.PROVIDER_CONFIG_PATH: self.PROVIDER_CONFIG_PATH = self.CONFIG_PATH / "provider.config.toml" - + # Construct DATABASE_URL if not provided if not self.DATABASE_URL: self.DATABASE_URL = f"postgresql+asyncpg://{self.POSTGRES_USER}:{self.POSTGRES_PASSWORD}@{self.POSTGRES_HOST}:{self.POSTGRES_PORT}/{self.POSTGRES_DB}" diff --git a/servers/inference_server/server/server/features/perspectives/__init__.py b/servers/inference_server/server/server/features/perspectives/__init__.py index 78528bb7..c2fa4fea 100644 --- a/servers/inference_server/server/server/features/perspectives/__init__.py +++ b/servers/inference_server/server/server/features/perspectives/__init__.py @@ -3,4 +3,4 @@ Perspectives Feature Module Provides API endpoints for accessing and using perspective captions. -""" \ No newline at end of file +""" diff --git a/servers/inference_server/server/server/features/perspectives/models.py b/servers/inference_server/server/server/features/perspectives/models.py index 37bdf0de..a5d043cd 100644 --- a/servers/inference_server/server/server/features/perspectives/models.py +++ b/servers/inference_server/server/server/features/perspectives/models.py @@ -19,8 +19,7 @@ DESC_GLOBAL_CONTEXT = "Global context for the caption" DESC_ADDITIONAL_CONTEXT = "Additional context for the caption" DESC_RESIZE_RESOLUTION = ( - "Resolution to resize to (None to disable, or SD_VGA, HD_720P, " - "FHD_1080P, QHD_1440P, UHD_4K, UHD_8K)" + "Resolution to resize to (None to disable, or SD_VGA, HD_720P, FHD_1080P, QHD_1440P, UHD_4K, UHD_8K)" ) @@ -32,7 +31,7 @@ class SchemaField(BaseModel): description: str = Field(..., description="Description of the field") is_list: bool = Field(False, description="Whether the field is a list") is_complex: bool = Field(False, description="Whether the field is a complex type") - fields: Optional[List['SchemaField']] = Field(None, description="Fields for complex types") + fields: Optional[List["SchemaField"]] = Field(None, description="Fields for complex types") class TableColumn(BaseModel): @@ -62,6 +61,13 @@ class PerspectiveInfo(BaseModel): version: str = Field(..., description="Version of the perspective") description: str = Field("", description="Description of what the perspective analyzes") schema: Optional[PerspectiveSchema] = Field(None, description="Schema information for the perspective") + + # New metadata fields + module: str = Field("default", description="Module this perspective belongs to") + tags: List[str] = Field(default_factory=list, description="Tags for categorizing perspectives") + deprecated: bool = Field(False, description="Whether this perspective is deprecated") + replacement: Optional[str] = Field(None, description="Name of perspective that replaces this one") + priority: int = Field(100, description="Priority for sorting (lower is higher priority)") class PerspectiveListResponse(BaseModel): @@ -77,11 +83,7 @@ class ImageSource(BaseModel): base64: Optional[str] = Field(None, description="Base64-encoded image data") class Config: - schema_extra = { - "example": { - "url": "https://example.com/image.jpg" - } - } + schema_extra = {"example": {"url": "https://example.com/image.jpg"}} class CaptionRequest(BaseModel): @@ -101,12 +103,10 @@ class Config: schema_extra = { "example": { "perspective": "custom_caption", - "image": { - "url": "https://example.com/image.jpg" - }, + "image": {"url": "https://example.com/image.jpg"}, "max_tokens": 4096, "temperature": 0.8, - "resize_resolution": "HD_720P" + "resize_resolution": "HD_720P", } } @@ -136,7 +136,7 @@ def __init__( repetition_penalty: Optional[float] = Form(1.15, description=DESC_REPETITION_PENALTY), global_context: Optional[str] = Form(None, description=DESC_GLOBAL_CONTEXT), context: Optional[str] = Form(None, description="Additional context for the caption (JSON array string)"), - resize_resolution: Optional[str] = Form(None, description=DESC_RESIZE_RESOLUTION) + resize_resolution: Optional[str] = Form(None, description=DESC_RESIZE_RESOLUTION), ): self.perspective = perspective self.file = file @@ -153,6 +153,7 @@ def __init__( self.context = None if context: import json + try: self.context = json.loads(context) except json.JSONDecodeError: @@ -182,6 +183,6 @@ class Config: "provider": "gemini", "max_tokens": 4096, "temperature": 0.8, - "resize_resolution": "HD_720P" + "resize_resolution": "HD_720P", } } diff --git a/servers/inference_server/server/server/features/perspectives/router.py b/servers/inference_server/server/server/features/perspectives/router.py index 39cf94b7..8fc5d853 100644 --- a/servers/inference_server/server/server/features/perspectives/router.py +++ b/servers/inference_server/server/server/features/perspectives/router.py @@ -55,6 +55,7 @@ async def debug_perspective(perspective_name: str) -> dict: HTTPException: If the perspective is not found """ from graphcap.perspectives import get_perspective + try: perspective = get_perspective(perspective_name) # Get perspective attributes @@ -68,9 +69,11 @@ async def debug_perspective(perspective_name: str) -> dict: # Get method signatures if available if attributes["has_process_single"]: import inspect + attributes["process_single_signature"] = str(inspect.signature(perspective.process_single)) if attributes["has_process_batch"]: import inspect + attributes["process_batch_signature"] = str(inspect.signature(perspective.process_batch)) return { "perspective": perspective_name, @@ -94,7 +97,7 @@ async def create_caption( repetition_penalty: Optional[float] = Form(1.15, description="Repetition penalty"), global_context: Optional[str] = Form(None, description="Global context for the caption"), context: Optional[str] = Form(None, description="Additional context for the caption as JSON array string"), - resize_resolution: Optional[str] = Form(None, description="Resolution to resize to (None to disable resizing)") + resize_resolution: Optional[str] = Form(None, description="Resolution to resize to (None to disable resizing)"), ) -> CaptionResponse: """ Generate a caption for an image using a perspective. @@ -128,9 +131,7 @@ async def create_caption( image_path = await save_uploaded_file(file) # Log resize options - options = { - 'resize_resolution': resize_resolution - } + options = {"resize_resolution": resize_resolution} log_resize_options(options) # Resize the image if resize_resolution is provided @@ -230,10 +231,7 @@ async def create_caption_from_path( temp_path = None # Handle image resizing if requested - image_path, temp_path = await _resize_image_if_needed( - image_path, - request.resize_resolution - ) + image_path, temp_path = await _resize_image_if_needed(image_path, request.resize_resolution) # Process context context = _process_context(request.context) @@ -255,11 +253,7 @@ async def create_caption_from_path( _cleanup_temp_file(temp_path) # Prepare the response - return _prepare_caption_response( - caption_data, - request.perspective, - request.provider - ) + return _prepare_caption_response(caption_data, request.perspective, request.provider) except Exception as e: logger.error(f"Error creating caption from path: {str(e)}") if isinstance(e, HTTPException): @@ -275,15 +269,12 @@ def _validate_image_path(image_path_str: str) -> Path: return image_path -async def _resize_image_if_needed( - image_path: Path, - resize_resolution: Optional[str] -) -> tuple[Path, Optional[Path]]: +async def _resize_image_if_needed(image_path: Path, resize_resolution: Optional[str]) -> tuple[Path, Optional[Path]]: """Resize the image if a resize resolution is provided.""" temp_path = None # Log resize options - options = {'resize_resolution': resize_resolution} + options = {"resize_resolution": resize_resolution} log_resize_options(options) if not resize_resolution: @@ -348,11 +339,7 @@ def _cleanup_temp_file(temp_path: Optional[Path]) -> None: logger.error(f"Error removing temporary file: {str(e)}") -def _prepare_caption_response( - caption_data: dict, - perspective: str, - provider: str -) -> CaptionResponse: +def _prepare_caption_response(caption_data: dict, perspective: str, provider: str) -> CaptionResponse: """Prepare the caption response from the caption data.""" # Log the caption data for debugging logger.debug(f"Caption data: {caption_data}") diff --git a/servers/inference_server/server/server/features/perspectives/service.py b/servers/inference_server/server/server/features/perspectives/service.py index 8a94fb01..474a9071 100644 --- a/servers/inference_server/server/server/features/perspectives/service.py +++ b/servers/inference_server/server/server/features/perspectives/service.py @@ -29,13 +29,10 @@ async def download_image(url: str) -> Path: """ Download an image from a URL to a temporary file. - Args: url: URL of the image to download - Returns: Path to the downloaded image - Raises: HTTPException: If the image cannot be downloaded """ @@ -49,10 +46,7 @@ async def download_image(url: str) -> Path: async with aiohttp.ClientSession() as session: async with session.get(url) as response: if response.status != 200: - raise HTTPException( - status_code=400, - detail=f"Failed to download image from URL: {response.status}" - ) + raise HTTPException(status_code=400, detail=f"Failed to download image from URL: {response.status}") content = await response.read() with open(temp_file, "wb") as f: @@ -67,13 +61,13 @@ async def download_image(url: str) -> Path: async def save_base64_image(base64_data: str) -> Path: """ Save a base64-encoded image to a temporary file. - + Args: base64_data: Base64-encoded image data - + Returns: Path to the saved image - + Raises: HTTPException: If the image cannot be saved """ @@ -104,26 +98,26 @@ async def save_base64_image(base64_data: str) -> Path: def load_perspective_schema(perspective_name: str) -> Optional[PerspectiveSchema]: """ Load the schema for a perspective from its configuration file. - + Args: perspective_name: Name of the perspective - + Returns: Schema information for the perspective, or None if not found """ try: # Construct the path to the schema file - schema_path = Path("/workspace/config/perspectives") / f"{perspective_name}.json" - + schema_path = Path("/workspace/perspective_library") / f"{perspective_name}.json" + # Check if the schema file exists if not schema_path.exists(): logger.warning(f"Schema file not found for perspective {perspective_name}") return None - + # Load and parse the schema file with open(schema_path, "r") as f: schema_data = json.load(f) - + # Convert the schema data to our models schema_fields = [] for field_data in schema_data.get("schema_fields", []): @@ -136,11 +130,11 @@ def load_perspective_schema(perspective_name: str) -> Optional[PerspectiveSchema type=f["type"], description=f["description"], is_list=f.get("is_list", False), - is_complex=f.get("is_complex", False) + is_complex=f.get("is_complex", False), ) for f in field_data["fields"] ] - + schema_fields.append( SchemaField( name=field_data["name"], @@ -148,15 +142,14 @@ def load_perspective_schema(perspective_name: str) -> Optional[PerspectiveSchema description=field_data["description"], is_list=field_data.get("is_list", False), is_complex=field_data.get("is_complex", False), - fields=nested_fields + fields=nested_fields, ) ) - + table_columns = [ - TableColumn(name=col["name"], style=col["style"]) - for col in schema_data.get("table_columns", []) + TableColumn(name=col["name"], style=col["style"]) for col in schema_data.get("table_columns", []) ] - + return PerspectiveSchema( name=schema_data["name"], display_name=schema_data["display_name"], @@ -164,7 +157,7 @@ def load_perspective_schema(perspective_name: str) -> Optional[PerspectiveSchema prompt=schema_data["prompt"], schema_fields=schema_fields, table_columns=table_columns, - context_template=schema_data["context_template"] + context_template=schema_data["context_template"], ) except Exception as e: logger.error(f"Error loading schema for perspective {perspective_name}: {str(e)}") @@ -174,7 +167,7 @@ def load_perspective_schema(perspective_name: str) -> Optional[PerspectiveSchema def get_available_perspectives() -> List[PerspectiveInfo]: """ Get a list of available perspectives with their schemas. - + Returns: List of perspective information including schemas """ @@ -185,14 +178,19 @@ def get_available_perspectives() -> List[PerspectiveInfo]: try: perspective = get_perspective(name) schema = load_perspective_schema(perspective.config_name) - + perspectives.append( PerspectiveInfo( name=perspective.config_name, display_name=perspective.display_name, version=perspective.version, - description="", # Could be added to the perspective config in the future - schema=schema + description=perspective.description, + schema=schema, + module=perspective.module_name, + tags=perspective.tags, + deprecated=perspective.is_deprecated, + replacement=perspective.replacement, + priority=perspective.priority, ) ) except Exception as e: @@ -214,7 +212,7 @@ async def generate_caption( ) -> Dict: """ Generate a caption for an image using a perspective. - + Args: perspective_name: Name of the perspective to use image_path: Path to the image file @@ -225,10 +223,10 @@ async def generate_caption( context: Additional context for the caption global_context: Global context for the caption provider_name: Name of the provider to use (default: "gemini") - + Returns: Caption data - + Raises: HTTPException: If the caption cannot be generated """ @@ -238,22 +236,22 @@ async def generate_caption( # Get the provider client from the provider manager provider_manager = get_provider_manager() - + # Debug: Log available providers available_providers = provider_manager.available_providers() logger.debug(f"Available providers: {available_providers}") - + # Debug: Try to resolve host.docker.internal try: - host_ip = socket.gethostbyname('host.docker.internal') + host_ip = socket.gethostbyname("host.docker.internal") logger.debug(f"host.docker.internal resolves to: {host_ip}") except socket.gaierror as e: logger.warning(f"Could not resolve host.docker.internal: {e}") - + try: provider: BaseClient = provider_manager.get_client(provider_name) # Debug: Log provider details - logger.debug(f"Provider details:") + logger.debug("Provider details:") logger.debug(f" - Name: {provider_name}") logger.debug(f" - Kind: {provider.kind}") logger.debug(f" - Environment: {provider.environment}") @@ -263,16 +261,19 @@ async def generate_caption( logger.error(f"Provider '{provider_name}' not found: {str(e)}") raise HTTPException( status_code=404, - detail=f"Provider '{provider_name}' not found. Available providers: {', '.join(provider_manager.available_providers())}" + detail=f"""Provider '{provider_name}' not found. + Available providers: {', '.join(provider_manager.available_providers())}""", ) - + # Create a temporary output directory with tempfile.TemporaryDirectory() as temp_dir: output_dir = Path(temp_dir) - + # Generate the caption - logger.info(f"Generating caption for {image_path} using {perspective_name} perspective and {provider_name} provider") - + logger.info( + f"Generating caption for {image_path} using {perspective_name} perspective and {provider_name} provider" + ) + # Check if the perspective has process_batch method if hasattr(perspective, "process_batch"): logger.info(f"Using process_batch method for {perspective_name}") @@ -286,14 +287,14 @@ async def generate_caption( top_p=top_p, repetition_penalty=repetition_penalty, global_context=global_context, - name=perspective_name + name=perspective_name, ) - + # Get the first (and only) result if not caption_data_list or len(caption_data_list) == 0: logger.error(f"No caption data returned for {image_path}") raise HTTPException(status_code=500, detail="No caption data returned") - + caption_data = caption_data_list[0] else: # Fallback to process_single if process_batch is not available @@ -308,10 +309,10 @@ async def generate_caption( context=context, global_context=global_context, ) - + # Log the result logger.info(f"Caption generated successfully: {caption_data.keys() if caption_data else 'None'}") - + return caption_data except ValueError as e: logger.error(f"Error getting perspective: {str(e)}") @@ -324,13 +325,13 @@ async def generate_caption( async def save_uploaded_file(file: UploadFile) -> Path: """ Save an uploaded file to a temporary location. - + Args: file: Uploaded file object - + Returns: Path to the saved file - + Raises: HTTPException: If the file cannot be saved """ diff --git a/servers/inference_server/server/server/features/providers/__init__.py b/servers/inference_server/server/server/features/providers/__init__.py index 2999ceaa..ac7be2ec 100644 --- a/servers/inference_server/server/server/features/providers/__init__.py +++ b/servers/inference_server/server/server/features/providers/__init__.py @@ -7,4 +7,4 @@ from .router import router -__all__ = ["router"] \ No newline at end of file +__all__ = ["router"] diff --git a/servers/inference_server/server/server/features/providers/models.py b/servers/inference_server/server/server/features/providers/models.py index 75b0ec84..506f7298 100644 --- a/servers/inference_server/server/server/features/providers/models.py +++ b/servers/inference_server/server/server/features/providers/models.py @@ -26,7 +26,7 @@ class ProviderListResponse(BaseModel): class ModelInfo(BaseModel): """Information about a model.""" - + id: str = Field(..., description="Unique identifier for the model") name: str = Field(..., description="Display name of the model") is_default: bool = Field(False, description="Whether this is the default model for the provider") @@ -34,6 +34,6 @@ class ModelInfo(BaseModel): class ProviderModelsResponse(BaseModel): """Response model for listing available models for a provider.""" - + provider: str = Field(..., description="Name of the provider") - models: List[ModelInfo] = Field(..., description="List of available models") \ No newline at end of file + models: List[ModelInfo] = Field(..., description="List of available models") diff --git a/servers/inference_server/server/server/features/providers/router.py b/servers/inference_server/server/server/features/providers/router.py index 663641cd..4e71725a 100644 --- a/servers/inference_server/server/server/features/providers/router.py +++ b/servers/inference_server/server/server/features/providers/router.py @@ -34,28 +34,28 @@ async def list_providers() -> ProviderListResponse: async def check_provider(provider_name: str) -> dict: """ Check if a specific provider is available. - + Args: provider_name: Name of the provider to check - + Returns: Status of the provider - + Raises: HTTPException: If the provider is not found """ provider_manager = get_provider_manager() available_providers = provider_manager.available_providers() - + if provider_name not in available_providers: raise HTTPException( status_code=404, - detail=f"Provider '{provider_name}' not found. Available providers: {', '.join(available_providers)}" + detail=f"Provider '{provider_name}' not found. Available providers: {', '.join(available_providers)}", ) - + # Get the provider config provider_config = provider_manager.get_provider_config(provider_name) - + return { "status": "available", "provider": provider_name, @@ -69,13 +69,13 @@ async def check_provider(provider_name: str) -> dict: async def list_provider_models(provider_name: str) -> ProviderModelsResponse: """ List available models for a specific provider. - + Args: provider_name: Name of the provider to get models for - + Returns: List of available models for the provider - + Raises: HTTPException: If the provider is not found """ @@ -85,4 +85,4 @@ async def list_provider_models(provider_name: str) -> ProviderModelsResponse: except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) except Exception as e: - raise HTTPException(status_code=500, detail=f"Error getting models: {str(e)}") \ No newline at end of file + raise HTTPException(status_code=500, detail=f"Error getting models: {str(e)}") diff --git a/servers/inference_server/server/server/features/providers/service.py b/servers/inference_server/server/server/features/providers/service.py index 84f053c2..c4186d7a 100644 --- a/servers/inference_server/server/server/features/providers/service.py +++ b/servers/inference_server/server/server/features/providers/service.py @@ -93,11 +93,8 @@ def get_available_providers() -> List[ProviderInfo]: def _create_model_info(model_id: str, default_model: str) -> ModelInfo: """Create a ModelInfo instance with the given ID and default model.""" - return ModelInfo( - id=model_id, - name=model_id, - is_default=(model_id == default_model) - ) + return ModelInfo(id=model_id, name=model_id, is_default=(model_id == default_model)) + def _extract_model_id(model: Any) -> str: """Extract model ID from a model object.""" @@ -105,6 +102,7 @@ def _extract_model_id(model: Any) -> str: return model.id return model.name if hasattr(model, "name") else str(model) + async def _fetch_models_from_available_models(client: Any, default_model: str) -> List[ModelInfo]: """Fetch models using get_available_models method.""" models = [] @@ -117,6 +115,7 @@ async def _fetch_models_from_available_models(client: Any, default_model: str) - return models + async def _fetch_models_from_get_models(client: Any, default_model: str) -> List[ModelInfo]: """Fetch models using get_models method.""" models = [] @@ -129,10 +128,12 @@ async def _fetch_models_from_get_models(client: Any, default_model: str) -> List return models + def _get_configured_models(config: Any) -> List[ModelInfo]: """Get models from configuration.""" return [_create_model_info(model_id, config.default_model) for model_id in config.models] + async def _fetch_provider_models(client: Any, provider_name: str, config: Any) -> List[ModelInfo]: """Attempt to fetch models from the provider.""" models = [] @@ -152,10 +153,11 @@ async def _fetch_provider_models(client: Any, provider_name: str, config: Any) - return models + async def get_provider_models(provider_name: str) -> List[ModelInfo]: """ Get a list of available models for a specific provider. - + Args: provider_name: Name of the provider to get models for Returns: diff --git a/servers/inference_server/server/server/features/repositories/types.py b/servers/inference_server/server/server/features/repositories/types.py index 05bb458c..d781488b 100644 --- a/servers/inference_server/server/server/features/repositories/types.py +++ b/servers/inference_server/server/server/features/repositories/types.py @@ -1,8 +1,8 @@ from pydantic import BaseModel + class RepositoryParams(BaseModel): repo_location_name: str = "pipelines.definitions" repo_name: str = "__repository__" dagster_host: str = "graphcap_pipelines" # Docker service name for Dagster dagster_port: int = 32300 - \ No newline at end of file diff --git a/servers/inference_server/server/server/pipelines/dagster_client.py b/servers/inference_server/server/server/pipelines/dagster_client.py index 214282b0..da421159 100644 --- a/servers/inference_server/server/server/pipelines/dagster_client.py +++ b/servers/inference_server/server/server/pipelines/dagster_client.py @@ -6,6 +6,7 @@ params = RepositoryParams() + class DagsterClientWrapper: def __init__(self, params: RepositoryParams = RepositoryParams()): """ diff --git a/servers/inference_server/server/server/utils/resizing.py b/servers/inference_server/server/server/utils/resizing.py index ef786ee9..16378432 100644 --- a/servers/inference_server/server/server/utils/resizing.py +++ b/servers/inference_server/server/server/utils/resizing.py @@ -2,7 +2,7 @@ """ Image Resizing Utilities -This module provides utility functions for resizing images to standard display +This module provides utility functions for resizing images to standard display and video resolutions while maintaining aspect ratio. """ @@ -13,6 +13,7 @@ try: from PIL import Image, ImageFile + ImageFile.LOAD_TRUNCATED_IMAGES = True except ImportError: raise ImportError("This module requires Pillow. Install it with 'pip install Pillow'.") @@ -21,12 +22,12 @@ def log_resize_options(options: Dict[str, Any]) -> None: """ Log the resize options to help with debugging. - + Args: options: The options dictionary containing resize settings """ - resize_resolution = options.get('resize_resolution') - + resize_resolution = options.get("resize_resolution") + if resize_resolution: logger.info(f"Image resizing is ENABLED with resolution: {resize_resolution}") else: @@ -35,13 +36,13 @@ def log_resize_options(options: Dict[str, Any]) -> None: class ResolutionPreset(Enum): """Standard display and video resolution presets.""" - - SD_VGA = (640, 480) # Standard Definition VGA - HD_720P = (1280, 720) # High Definition 720p - FHD_1080P = (1920, 1080) # Full High Definition 1080p - QHD_1440P = (2560, 1440) # Quad HD 1440p - UHD_4K = (3840, 2160) # Ultra HD 4K - UHD_8K = (7680, 4320) # 8K UHD + + SD_VGA = (640, 480) # Standard Definition VGA + HD_720P = (1280, 720) # High Definition 720p + FHD_1080P = (1920, 1080) # Full High Definition 1080p + QHD_1440P = (2560, 1440) # Quad HD 1440p + UHD_4K = (3840, 2160) # Ultra HD 4K + UHD_8K = (7680, 4320) # 8K UHD def resize_image( @@ -49,21 +50,21 @@ def resize_image( resolution: Union[ResolutionPreset, Tuple[int, int]], maintain_aspect_ratio: bool = True, upscale: bool = False, - output_format: Optional[str] = None + output_format: Optional[str] = None, ) -> Image.Image: """ Resize an image to a target resolution while maintaining aspect ratio. - + Args: image: Path to the image file or PIL Image object resolution: Target resolution as ResolutionPreset enum or (width, height) tuple maintain_aspect_ratio: If True, preserve aspect ratio; if False, force to exact dimensions upscale: If True, allow upscaling of images smaller than target resolution output_format: Output format (e.g., 'JPEG', 'PNG'). If None, uses input format. - + Returns: Resized PIL Image object - + Raises: ValueError: If the image path is invalid or resolution is not recognized IOError: If there's an error opening or processing the image @@ -87,19 +88,23 @@ def resize_image( # Get original dimensions orig_width, orig_height = img.size - - logger.info(f"Resizing image: original dimensions {orig_width}x{orig_height}, target {target_width}x{target_height}") - + + logger.info( + f"Resizing image: original dimensions {orig_width}x{orig_height}, target {target_width}x{target_height}" + ) + # Skip resizing if the image is already smaller than target and upscale is False if not upscale and orig_width <= target_width and orig_height <= target_height: - logger.info(f"Skipping resize: image {orig_width}x{orig_height} already smaller than target {target_width}x{target_height}") + logger.info( + f"Skipping resize: image {orig_width}x{orig_height} already smaller than target {target_width}x{target_height}" + ) return img - + if maintain_aspect_ratio: # Calculate aspect ratios target_ratio = target_width / target_height image_ratio = orig_width / orig_height - + if image_ratio > target_ratio: # Image is wider than target: fit to width new_width = target_width @@ -111,27 +116,25 @@ def resize_image( else: # Force to exact dimensions without maintaining aspect ratio new_width, new_height = target_width, target_height - + # Perform the resize operation resized_img = img.resize((new_width, new_height), Image.LANCZOS) logger.info(f"Image resized: original {orig_width}x{orig_height} → final {new_width}x{new_height}") - + return resized_img def resize_to_fit_max_dimension( - image: Union[str, Path, Image.Image], - max_dimension: int, - upscale: bool = False + image: Union[str, Path, Image.Image], max_dimension: int, upscale: bool = False ) -> Image.Image: """ Resize an image so its largest dimension does not exceed max_dimension. - + Args: image: Path to the image file or PIL Image object max_dimension: Maximum size for the largest dimension upscale: If True, allow upscaling of images smaller than target size - + Returns: Resized PIL Image object """ @@ -140,17 +143,17 @@ def resize_to_fit_max_dimension( img = Image.open(str(image)) else: img = image - + # Get original dimensions width, height = img.size - + logger.info(f"Resizing to max dimension: original dimensions {width}x{height}, max dimension {max_dimension}") - + # Skip if no resizing needed if not upscale and max(width, height) <= max_dimension: logger.info(f"Skipping resize: largest dimension {max(width, height)} already smaller than max {max_dimension}") return img - + # Calculate new dimensions if width >= height: new_width = max_dimension @@ -158,11 +161,11 @@ def resize_to_fit_max_dimension( else: new_height = max_dimension new_width = int(width * (max_dimension / height)) - + # Perform the resize resized_img = img.resize((new_width, new_height), Image.LANCZOS) logger.info(f"Image resized: original {width}x{height} → final {new_width}x{new_height}") - + return resized_img @@ -171,11 +174,11 @@ def save_with_quality( output_path: Union[str, Path], format: Optional[str] = None, quality: int = 90, - optimize: bool = True + optimize: bool = True, ) -> None: """ Save an image with specified quality settings. - + Args: image: PIL Image object to save output_path: Path where the image should be saved @@ -183,13 +186,10 @@ def save_with_quality( quality: Quality setting (0-100, higher is better quality) optimize: Whether to optimize the image """ - save_params = { - 'quality': quality, - 'optimize': optimize - } - + save_params = {"quality": quality, "optimize": optimize} + # Remove quality parameter for formats that don't support it - if format and format.upper() in ('PNG', 'GIF'): - del save_params['quality'] - + if format and format.upper() in ("PNG", "GIF"): + del save_params["quality"] + image.save(str(output_path), format=format, **save_params) diff --git a/servers/inference_server/tests/test_perspective_modules.py b/servers/inference_server/tests/test_perspective_modules.py new file mode 100644 index 00000000..44e479f8 --- /dev/null +++ b/servers/inference_server/tests/test_perspective_modules.py @@ -0,0 +1,187 @@ +""" +# SPDX-License-Identifier: Apache-2.0 +Tests for perspective module loading functionality. +""" + +import json +import tempfile +from pathlib import Path + +import pytest +from graphcap.perspectives.perspective_loader import ( + ModuleConfig, + PerspectiveSettings, + get_all_modules, + load_all_perspectives, +) + + +@pytest.fixture +def temp_perspective_dir(): + """Create a temporary directory for test perspectives.""" + with tempfile.TemporaryDirectory() as temp_dir: + # Create module directories + core_dir = Path(temp_dir) / "core" + core_dir.mkdir() + + experimental_dir = Path(temp_dir) / "experimental" + experimental_dir.mkdir() + + # Create a few test perspectives + core_perspective = { + "name": "test_core", + "display_name": "Test Core", + "version": "1", + "prompt": "Test prompt", + "schema_fields": [{"name": "caption", "type": "str", "description": "A test caption", "is_list": False}], + "table_columns": [{"name": "Caption", "style": "green"}], + "context_template": "\n{caption}\n\n", + "module": "core", + "tags": ["test", "core"], + "description": "A test perspective", + "deprecated": False, + "priority": 10, + } + + with open(core_dir / "test_core.json", "w") as f: + json.dump(core_perspective, f, indent=2) + + # Create a perspective without explicit module (should use directory name) + auto_module_perspective = { + "name": "test_experimental", + "display_name": "Test Experimental", + "version": "0.1", + "prompt": "Test experimental prompt", + "schema_fields": [{"name": "caption", "type": "str", "description": "A test caption", "is_list": False}], + "table_columns": [{"name": "Caption", "style": "yellow"}], + "context_template": "\n{caption}\n\n", + "tags": ["test", "experimental"], + "description": "An experimental test perspective", + "deprecated": False, + "priority": 20, + } + + with open(experimental_dir / "test_experimental.json", "w") as f: + json.dump(auto_module_perspective, f, indent=2) + + # Also add a perspective in the root directory + root_perspective = { + "name": "test_root", + "display_name": "Test Root", + "version": "1", + "prompt": "Test root prompt", + "schema_fields": [{"name": "caption", "type": "str", "description": "A test caption", "is_list": False}], + "table_columns": [{"name": "Caption", "style": "blue"}], + "context_template": "\n{caption}\n\n", + "module": "default", + "tags": ["test", "default"], + "description": "A default module test perspective", + "deprecated": False, + "priority": 30, + } + + with open(Path(temp_dir) / "test_root.json", "w") as f: + json.dump(root_perspective, f, indent=2) + + yield temp_dir + + +@pytest.fixture +def settings(): + """Create test settings.""" + return PerspectiveSettings( + modules={ + "core": ModuleConfig(enabled=True, display_name="Core Test"), + "experimental": ModuleConfig(enabled=False, display_name="Experimental Test"), + "default": ModuleConfig(enabled=True, display_name="Default Test"), + }, + local_override=True, + ) + + +def test_load_perspectives_from_modules(temp_perspective_dir, settings): + """Test loading perspectives from module directories.""" + # Test loading with all modules + all_modules = get_all_modules([Path(temp_perspective_dir)], settings) + + # Check that we have the expected modules + assert set(all_modules.keys()) == {"core", "experimental", "default"} + + # Check module display names from settings + assert all_modules["core"].display_name == "Core Test" + assert all_modules["experimental"].display_name == "Experimental Test" + assert all_modules["default"].display_name == "Default Test" + + # Check module enabled status + assert all_modules["core"].enabled is True + assert all_modules["experimental"].enabled is False + assert all_modules["default"].enabled is True + + # Check that each module has the correct perspectives + assert "test_core" in all_modules["core"].perspectives + assert "test_experimental" in all_modules["experimental"].perspectives + assert "test_root" in all_modules["default"].perspectives + + # Test loading perspectives respecting module enabled status + perspectives = load_all_perspectives([Path(temp_perspective_dir)], settings) + + # Experimental module is disabled, so its perspective shouldn't be included + assert "test_core" in perspectives + assert "test_experimental" not in perspectives + assert "test_root" in perspectives + + +def test_perspective_module_toggle(temp_perspective_dir, settings): + """Test toggling modules on and off.""" + all_modules = get_all_modules([Path(temp_perspective_dir)], settings) + + # Initially, experimental is disabled + assert all_modules["experimental"].enabled is False + + # Toggle experimental on + all_modules["experimental"].toggle(True) + assert all_modules["experimental"].enabled is True + + # Create a new settings object with experimental enabled + updated_settings = PerspectiveSettings( + modules={ + "core": ModuleConfig(enabled=True, display_name="Core Test"), + "experimental": ModuleConfig(enabled=True, display_name="Experimental Test"), + "default": ModuleConfig(enabled=True, display_name="Default Test"), + }, + local_override=True, + ) + + # Now load perspectives again, should include experimental + perspectives = load_all_perspectives([Path(temp_perspective_dir)], updated_settings) + + assert "test_experimental" in perspectives + + +def test_auto_module_detection(temp_perspective_dir): + """Test that perspectives without explicit module are assigned based on directory.""" + # Load without providing settings + all_modules = get_all_modules([Path(temp_perspective_dir)]) + + # The experimental perspective should be in the experimental module + assert "test_experimental" in all_modules["experimental"].perspectives + + # The perspective itself should have the right module + assert all_modules["experimental"].perspectives["test_experimental"].module_name == "experimental" + + +def test_perspective_metadata(temp_perspective_dir, settings): + """Test that perspective metadata is correctly accessible.""" + perspectives = load_all_perspectives([Path(temp_perspective_dir)], settings) + + # Check that core perspective has the right metadata + assert perspectives["test_core"].module_name == "core" + assert perspectives["test_core"].tags == ["test", "core"] + assert perspectives["test_core"].description == "A test perspective" + assert perspectives["test_core"].is_deprecated is False + assert perspectives["test_core"].priority == 10 + + # Check root perspective + assert perspectives["test_root"].module_name == "default" + assert "default" in perspectives["test_root"].tags + assert perspectives["test_root"].priority == 30 diff --git a/servers/inference_server/uv.lock b/servers/inference_server/uv.lock index 9a23d2b1..6636e2a5 100644 --- a/servers/inference_server/uv.lock +++ b/servers/inference_server/uv.lock @@ -24,6 +24,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/46/eb/e7f063ad1fec6b3178a3cd82d1a3c4de82cccf283fc42746168188e1cdd5/anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a", size = 96041 }, ] +[[package]] +name = "build" +version = "1.2.2.post1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "os_name == 'nt'" }, + { name = "packaging" }, + { name = "pyproject-hooks" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/46/aeab111f8e06793e4f0e421fcad593d547fb8313b50990f31681ee2fb1ad/build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7", size = 46701 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/c2/80633736cd183ee4a62107413def345f7e6e3c01563dbca1417363cf957e/build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5", size = 22950 }, +] + [[package]] name = "certifi" version = "2025.1.31" @@ -61,6 +75,14 @@ dependencies = [ { name = "openai" }, { name = "pydantic" }, { name = "rich" }, + { name = "tenacity" }, +] + +[package.dev-dependencies] +dev = [ + { name = "build" }, + { name = "pytest" }, + { name = "ruff" }, ] [package.metadata] @@ -70,6 +92,14 @@ requires-dist = [ { name = "openai", specifier = ">=1.63.2" }, { name = "pydantic", specifier = ">=2.10.6" }, { name = "rich", specifier = ">=13.9.4" }, + { name = "tenacity", specifier = ">=9.0.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "build", specifier = ">=1.2.2.post1" }, + { name = "pytest", specifier = ">=8.3.4" }, + { name = "ruff", specifier = ">=0.9.6" }, ] [[package]] @@ -118,6 +148,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] +[[package]] +name = "iniconfig" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, +] + [[package]] name = "jiter" version = "0.8.2" @@ -218,6 +257,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/15/64/db3462b358072387b8e93e6e6a38d3c741a17b4a84171ef01d6c85c63f25/openai-1.63.2-py3-none-any.whl", hash = "sha256:1f38b27b5a40814c2b7d8759ec78110df58c4a614c25f182809ca52b080ff4d4", size = 472282 }, ] +[[package]] +name = "packaging" +version = "24.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, +] + [[package]] name = "pydantic" version = "2.10.6" @@ -294,6 +351,30 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, ] +[[package]] +name = "pyproject-hooks" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216 }, +] + +[[package]] +name = "pytest" +version = "8.3.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 }, +] + [[package]] name = "rich" version = "13.9.4" @@ -307,6 +388,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, ] +[[package]] +name = "ruff" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/77/2b/7ca27e854d92df5e681e6527dc0f9254c9dc06c8408317893cf96c851cdd/ruff-0.11.0.tar.gz", hash = "sha256:e55c620690a4a7ee6f1cccb256ec2157dc597d109400ae75bbf944fc9d6462e2", size = 3799407 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/40/3d0340a9e5edc77d37852c0cd98c5985a5a8081fc3befaeb2ae90aaafd2b/ruff-0.11.0-py3-none-linux_armv6l.whl", hash = "sha256:dc67e32bc3b29557513eb7eeabb23efdb25753684b913bebb8a0c62495095acb", size = 10098158 }, + { url = "https://files.pythonhosted.org/packages/ec/a9/d8f5abb3b87b973b007649ac7bf63665a05b2ae2b2af39217b09f52abbbf/ruff-0.11.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:38c23fd9bdec4eb437b4c1e3595905a0a8edfccd63a790f818b28c78fe345639", size = 10879071 }, + { url = "https://files.pythonhosted.org/packages/ab/62/aaa198614c6211677913ec480415c5e6509586d7b796356cec73a2f8a3e6/ruff-0.11.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7c8661b0be91a38bd56db593e9331beaf9064a79028adee2d5f392674bbc5e88", size = 10247944 }, + { url = "https://files.pythonhosted.org/packages/9f/52/59e0a9f2cf1ce5e6cbe336b6dd0144725c8ea3b97cac60688f4e7880bf13/ruff-0.11.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6c0e8d3d2db7e9f6efd884f44b8dc542d5b6b590fc4bb334fdbc624d93a29a2", size = 10421725 }, + { url = "https://files.pythonhosted.org/packages/a6/c3/dcd71acc6dff72ce66d13f4be5bca1dbed4db678dff2f0f6f307b04e5c02/ruff-0.11.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c3156d3f4b42e57247275a0a7e15a851c165a4fc89c5e8fa30ea6da4f7407b8", size = 9954435 }, + { url = "https://files.pythonhosted.org/packages/a6/9a/342d336c7c52dbd136dee97d4c7797e66c3f92df804f8f3b30da59b92e9c/ruff-0.11.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:490b1e147c1260545f6d041c4092483e3f6d8eba81dc2875eaebcf9140b53905", size = 11492664 }, + { url = "https://files.pythonhosted.org/packages/84/35/6e7defd2d7ca95cc385ac1bd9f7f2e4a61b9cc35d60a263aebc8e590c462/ruff-0.11.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1bc09a7419e09662983b1312f6fa5dab829d6ab5d11f18c3760be7ca521c9329", size = 12207856 }, + { url = "https://files.pythonhosted.org/packages/22/78/da669c8731bacf40001c880ada6d31bcfb81f89cc996230c3b80d319993e/ruff-0.11.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcfa478daf61ac8002214eb2ca5f3e9365048506a9d52b11bea3ecea822bb844", size = 11645156 }, + { url = "https://files.pythonhosted.org/packages/ee/47/e27d17d83530a208f4a9ab2e94f758574a04c51e492aa58f91a3ed7cbbcb/ruff-0.11.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6fbb2aed66fe742a6a3a0075ed467a459b7cedc5ae01008340075909d819df1e", size = 13884167 }, + { url = "https://files.pythonhosted.org/packages/9f/5e/42ffbb0a5d4b07bbc642b7d58357b4e19a0f4774275ca6ca7d1f7b5452cd/ruff-0.11.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92c0c1ff014351c0b0cdfdb1e35fa83b780f1e065667167bb9502d47ca41e6db", size = 11348311 }, + { url = "https://files.pythonhosted.org/packages/c8/51/dc3ce0c5ce1a586727a3444a32f98b83ba99599bb1ebca29d9302886e87f/ruff-0.11.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e4fd5ff5de5f83e0458a138e8a869c7c5e907541aec32b707f57cf9a5e124445", size = 10305039 }, + { url = "https://files.pythonhosted.org/packages/60/e0/475f0c2f26280f46f2d6d1df1ba96b3399e0234cf368cc4c88e6ad10dcd9/ruff-0.11.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:96bc89a5c5fd21a04939773f9e0e276308be0935de06845110f43fd5c2e4ead7", size = 9937939 }, + { url = "https://files.pythonhosted.org/packages/e2/d3/3e61b7fd3e9cdd1e5b8c7ac188bec12975c824e51c5cd3d64caf81b0331e/ruff-0.11.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a9352b9d767889ec5df1483f94870564e8102d4d7e99da52ebf564b882cdc2c7", size = 10923259 }, + { url = "https://files.pythonhosted.org/packages/30/32/cd74149ebb40b62ddd14bd2d1842149aeb7f74191fb0f49bd45c76909ff2/ruff-0.11.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:049a191969a10897fe052ef9cc7491b3ef6de79acd7790af7d7897b7a9bfbcb6", size = 11406212 }, + { url = "https://files.pythonhosted.org/packages/00/ef/033022a6b104be32e899b00de704d7c6d1723a54d4c9e09d147368f14b62/ruff-0.11.0-py3-none-win32.whl", hash = "sha256:3191e9116b6b5bbe187447656f0c8526f0d36b6fd89ad78ccaad6bdc2fad7df2", size = 10310905 }, + { url = "https://files.pythonhosted.org/packages/ed/8a/163f2e78c37757d035bd56cd60c8d96312904ca4a6deeab8442d7b3cbf89/ruff-0.11.0-py3-none-win_amd64.whl", hash = "sha256:c58bfa00e740ca0a6c43d41fb004cd22d165302f360aaa56f7126d544db31a21", size = 11411730 }, + { url = "https://files.pythonhosted.org/packages/4e/f7/096f6efabe69b49d7ca61052fc70289c05d8d35735c137ef5ba5ef423662/ruff-0.11.0-py3-none-win_arm64.whl", hash = "sha256:868364fc23f5aa122b00c6f794211e85f7e78f5dffdf7c590ab90b8c4e69b657", size = 10538956 }, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -316,6 +422,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, ] +[[package]] +name = "tenacity" +version = "9.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/94/91fccdb4b8110642462e653d5dcb27e7b674742ad68efd146367da7bdb10/tenacity-9.0.0.tar.gz", hash = "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b", size = 47421 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/cb/b86984bed139586d01532a587464b5805f12e397594f19f931c4c2fbfa61/tenacity-9.0.0-py3-none-any.whl", hash = "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539", size = 28169 }, +] + [[package]] name = "tqdm" version = "4.67.1" diff --git a/workspace/config/perspective_settings.json b/workspace/config/perspective_settings.json new file mode 100644 index 00000000..942df60a --- /dev/null +++ b/workspace/config/perspective_settings.json @@ -0,0 +1,37 @@ +{ + "modules": { + "core": { + "enabled": true, + "display_name": "Core Perspectives" + }, + "narrative": { + "enabled": true, + "display_name": "Narrative Perspectives" + }, + "emotional": { + "enabled": true, + "display_name": "Emotional Perspectives" + }, + "art": { + "enabled": true, + "display_name": "Art Analysis" + }, + "temporal": { + "enabled": true, + "display_name": "Temporal Analysis" + }, + "speculative": { + "enabled": true, + "display_name": "Speculative Perspectives" + }, + "experimental": { + "enabled": false, + "display_name": "Experimental Perspectives" + }, + "deprecated": { + "enabled": false, + "display_name": "Deprecated Perspectives" + } + }, + "local_override": true +} \ No newline at end of file diff --git a/workspace/config/perspectives/art_critic.json b/workspace/perspective_library/art_critic.json similarity index 86% rename from workspace/config/perspectives/art_critic.json rename to workspace/perspective_library/art_critic.json index 2c484050..29e96f24 100644 --- a/workspace/config/perspectives/art_critic.json +++ b/workspace/perspective_library/art_critic.json @@ -45,5 +45,10 @@ "style": "green" } ], - "context_template": "\n{formal_analysis}\n\n" + "context_template": "\n{formal_analysis}\n\n", + "module": "art", + "tags": ["art", "formal-analysis", "visual-elements", "objective"], + "description": "An art critic perspective that focuses on formal analysis principles, providing objective observations of visual elements, technical aspects, and stylistic choices without subjective interpretation.", + "deprecated": false, + "priority": 30 } \ No newline at end of file diff --git a/workspace/config/perspectives/custom_caption.json b/workspace/perspective_library/custom_caption.json similarity index 74% rename from workspace/config/perspectives/custom_caption.json rename to workspace/perspective_library/custom_caption.json index 14eeaf89..6c05c970 100644 --- a/workspace/config/perspectives/custom_caption.json +++ b/workspace/perspective_library/custom_caption.json @@ -27,5 +27,10 @@ "style": "green" } ], - "context_template": "\n{caption}\n\n" + "context_template": "\n{caption}\n\n", + "module": "core", + "tags": ["customizable", "general-purpose", "flexible"], + "description": "A customizable perspective that allows users to provide their own instructions for image analysis, supporting versatile use cases and custom analysis approaches.", + "deprecated": false, + "priority": 10 } \ No newline at end of file diff --git a/workspace/config/perspectives/emotional_sentiment.json b/workspace/perspective_library/emotional_sentiment.json similarity index 77% rename from workspace/config/perspectives/emotional_sentiment.json rename to workspace/perspective_library/emotional_sentiment.json index bdaea7ed..3a64dd84 100644 --- a/workspace/config/perspectives/emotional_sentiment.json +++ b/workspace/perspective_library/emotional_sentiment.json @@ -27,5 +27,10 @@ "style": "green" } ], - "context_template": "\n{sentiment_caption}\n\n" + "context_template": "\n{sentiment_caption}\n\n", + "module": "emotional", + "tags": ["emotion", "sentiment", "mood", "affective"], + "description": "A perspective focused on analyzing the emotional tone conveyed by an image, providing insights into mood and sentiment through descriptive language.", + "deprecated": false, + "priority": 25 } \ No newline at end of file diff --git a/workspace/config/perspectives/graph_caption.json b/workspace/perspective_library/graph_caption.json similarity index 92% rename from workspace/config/perspectives/graph_caption.json rename to workspace/perspective_library/graph_caption.json index d728a71b..8577f134 100644 --- a/workspace/config/perspectives/graph_caption.json +++ b/workspace/perspective_library/graph_caption.json @@ -57,5 +57,10 @@ "style": "green" } ], - "context_template": "\n{short_caption}\n\nTags: {tags_list}\n\n" + "context_template": "\n{short_caption}\n\nTags: {tags_list}\n\n", + "module": "graph", + "tags": ["graph", "caption", "analysis"], + "description": "Graph caption analysis", + "deprecated": false, + "priority": 50 } \ No newline at end of file diff --git a/workspace/config/perspectives/locality_graph.json b/workspace/perspective_library/locality_graph.json similarity index 92% rename from workspace/config/perspectives/locality_graph.json rename to workspace/perspective_library/locality_graph.json index 1341d06a..e3b02613 100644 --- a/workspace/config/perspectives/locality_graph.json +++ b/workspace/perspective_library/locality_graph.json @@ -62,5 +62,10 @@ "style": "green" } ], - "context_template": "\n{composition_summary}\nNodes: {nodes}\nEdges: {edges}\n" + "context_template": "\n{composition_summary}\nNodes: {nodes}\nEdges: {edges}\n", + "module": "graph", + "tags": ["graph", "locality", "analysis"], + "description": "Graph locality analysis", + "deprecated": false, + "priority": 50 } diff --git a/workspace/config/perspectives/out_of_frame.json b/workspace/perspective_library/out_of_frame.json similarity index 90% rename from workspace/config/perspectives/out_of_frame.json rename to workspace/perspective_library/out_of_frame.json index 5e3b8af2..72225fc8 100644 --- a/workspace/config/perspectives/out_of_frame.json +++ b/workspace/perspective_library/out_of_frame.json @@ -45,5 +45,10 @@ "style": "green" } ], - "context_template": "\n{narrative_possibilities}\n\n" + "context_template": "\n{narrative_possibilities}\n\n", + "module": "speculative", + "tags": ["speculative", "imagination", "beyond-frame"], + "description": "Speculative interpretation of what might exist beyond the boundaries of the image", + "deprecated": false, + "priority": 50 } \ No newline at end of file diff --git a/workspace/config/perspectives/poetic_metaphor.json b/workspace/perspective_library/poetic_metaphor.json similarity index 91% rename from workspace/config/perspectives/poetic_metaphor.json rename to workspace/perspective_library/poetic_metaphor.json index 57c4cae6..d2143ea5 100644 --- a/workspace/config/perspectives/poetic_metaphor.json +++ b/workspace/perspective_library/poetic_metaphor.json @@ -45,5 +45,10 @@ "style": "green" } ], - "context_template": "\n{poetic_description}\n\n" + "context_template": "\n{poetic_description}\n\n", + "module": "artististic", + "tags": ["poetic", "metaphor", "imagery", "figurative"], + "description": "Poetic metaphor analysis", + "deprecated": false, + "priority": 50 } \ No newline at end of file diff --git a/workspace/config/perspectives/simple_temporarium.json b/workspace/perspective_library/simple_temporarium.json similarity index 86% rename from workspace/config/perspectives/simple_temporarium.json rename to workspace/perspective_library/simple_temporarium.json index 2748c045..6cd1ce82 100644 --- a/workspace/config/perspectives/simple_temporarium.json +++ b/workspace/perspective_library/simple_temporarium.json @@ -51,5 +51,10 @@ "style": "green" } ], - "context_template": "\n{simple_caption}\n" + "context_template": "\n{temporal_caption}\n\n", + "module": "speculative", + "tags": ["time", "historical", "simplified", "era", "indicators"], + "description": "A simplified version of the Temporarium perspective that focuses on basic temporal analysis with less complexity and reasoning steps.", + "deprecated": false, + "priority": 45 } \ No newline at end of file diff --git a/workspace/config/perspectives/storytelling.json b/workspace/perspective_library/storytelling.json similarity index 86% rename from workspace/config/perspectives/storytelling.json rename to workspace/perspective_library/storytelling.json index 00d41ea9..83fe9ca5 100644 --- a/workspace/config/perspectives/storytelling.json +++ b/workspace/perspective_library/storytelling.json @@ -45,5 +45,10 @@ "style": "green" } ], - "context_template": "\n{plot_elements}\n\n" + "context_template": "\n{plot_elements}\n\n", + "module": "narrative", + "tags": ["storytelling", "narrative", "creative", "plot", "characters"], + "description": "A narrative-focused perspective that constructs a cohesive story from visual elements, including scene setting, character development, plot, and thematic analysis.", + "deprecated": false, + "priority": 20 } \ No newline at end of file diff --git a/workspace/config/perspectives/synthesized_caption.json b/workspace/perspective_library/synthesized_caption.json similarity index 90% rename from workspace/config/perspectives/synthesized_caption.json rename to workspace/perspective_library/synthesized_caption.json index 2d3073af..d3ff7cbd 100644 --- a/workspace/config/perspectives/synthesized_caption.json +++ b/workspace/perspective_library/synthesized_caption.json @@ -51,5 +51,10 @@ {"name": "Component", "style": "cyan"}, {"name": "Content", "style": "green"} ], - "context_template": "\n{short_caption}\n\nTags: {synthesis_tags}\n\n" + "context_template": "\n{short_caption}\n\nTags: {synthesis_tags}\n\n", + "module": "core", + "tags": ["synthesis", "integration", "comprehensive", "multi-perspective"], + "description": "A meta-perspective that integrates insights from multiple other perspectives to create a comprehensive, cohesive analysis with multiple levels of detail and explicit reasoning.", + "deprecated": false, + "priority": 5 } diff --git a/workspace/config/perspectives/temporarium.json b/workspace/perspective_library/temporarium.json similarity index 89% rename from workspace/config/perspectives/temporarium.json rename to workspace/perspective_library/temporarium.json index 6fc08c19..031e0c7c 100644 --- a/workspace/config/perspectives/temporarium.json +++ b/workspace/perspective_library/temporarium.json @@ -75,5 +75,10 @@ "style": "green" } ], - "context_template": "\n{detailed_caption}\n\n" + "context_template": "\n{detailed_caption}\n\n", + "module": "speculative", + "tags": ["time", "historical", "futuristic", "epoch", "continuity", "speculative"], + "description": "A perspective focused on temporal analysis, examining historical or futuristic elements, epoch context, historical continuity, and temporal speculation with chain-of-thought reasoning.", + "deprecated": false, + "priority": 40 } \ No newline at end of file diff --git a/workspace/config/perspectives/time_tags.json b/workspace/perspective_library/time_tags.json similarity index 85% rename from workspace/config/perspectives/time_tags.json rename to workspace/perspective_library/time_tags.json index af55b3f7..d0d4f985 100644 --- a/workspace/config/perspectives/time_tags.json +++ b/workspace/perspective_library/time_tags.json @@ -57,5 +57,10 @@ } ], - "context_template": "\nWhy Important:\n{why_important}\n\nTags:\n{time_tags}\n\n" + "context_template": "\nPeriod: {time_period_tags}\nCategory: {temporal_category}\nQualities: {time_quality_tags}\n\n", + "module": "temporal", + "tags": ["time", "tagging", "classification", "historical", "periods"], + "description": "A tagging-focused perspective that categorizes images based on time periods, temporal indicators, and time-related qualities for easier image classification.", + "deprecated": false, + "priority": 50 } \ No newline at end of file From f8479a4d8189f06b261447cc4a7d5c23bcea29f4 Mon Sep 17 00:00:00 2001 From: jphillips Date: Tue, 18 Mar 2025 11:56:16 -0500 Subject: [PATCH 02/24] Ruff autoformat Signed-off-by: jphillips --- .../pipelines/pipelines/common/constants.py | 2 +- .../pipelines/pipelines/common/resources.py | 1 + .../pipelines/pipelines/definitions.py | 1 + .../pipelines/io/image/load_images.py | 31 ++++++------- .../pipelines/perspectives/assets.py | 43 ++++++++++--------- .../pipelines/perspectives/jobs/__init__.py | 1 - .../jobs/basic_perspective_pipeline.py | 2 +- .../pipelines/perspectives/jobs/config.py | 10 ++--- .../pipelines/pipelines/providers/util.py | 1 + servers/inference_server/scripts/__init__.py | 2 +- servers/inference_server/scripts/__main__.py | 2 +- servers/inference_server/scripts/setup.py | 19 ++++---- test/inference_tests/constants.py | 4 -- test/inference_tests/ollama_client_test.py | 26 +++++------ test/inference_tests/ollama_graphcap_REST.py | 2 +- .../inference_tests/ollama_structured_test.py | 7 ++- test/inference_tests/rest_api_test.py | 21 +++++---- .../provider_tests/test_provider_config.py | 1 - .../provider_tests/test_providers.py | 3 +- 19 files changed, 90 insertions(+), 89 deletions(-) diff --git a/servers/inference_server/pipelines/pipelines/common/constants.py b/servers/inference_server/pipelines/pipelines/common/constants.py index 0baad527..dff54528 100644 --- a/servers/inference_server/pipelines/pipelines/common/constants.py +++ b/servers/inference_server/pipelines/pipelines/common/constants.py @@ -8,4 +8,4 @@ # Workspace configuration WORKSPACE_ROOT = Path("/workspace") WORKSPACE_CONFIG_DIR = WORKSPACE_ROOT / "config" -WORKSPACE_PERSPECTIVES_DIR = WORKSPACE_CONFIG_DIR / "perspectives" \ No newline at end of file +WORKSPACE_PERSPECTIVES_DIR = WORKSPACE_CONFIG_DIR / "perspectives" diff --git a/servers/inference_server/pipelines/pipelines/common/resources.py b/servers/inference_server/pipelines/pipelines/common/resources.py index 4b2b6b92..ab0003b7 100644 --- a/servers/inference_server/pipelines/pipelines/common/resources.py +++ b/servers/inference_server/pipelines/pipelines/common/resources.py @@ -28,6 +28,7 @@ class ProviderConfigFile(dg.ConfigurableResource): provider_config: str = "/workspace/config/provider.config.toml" default_provider: str = "gemini" + class PerspectiveConfig(dg.ConfigurableResource): """Configuration for perspective operations.""" diff --git a/servers/inference_server/pipelines/pipelines/definitions.py b/servers/inference_server/pipelines/pipelines/definitions.py index a99d9449..c2b86142 100644 --- a/servers/inference_server/pipelines/pipelines/definitions.py +++ b/servers/inference_server/pipelines/pipelines/definitions.py @@ -14,6 +14,7 @@ from .huggingface import huggingface_client from .huggingface.types import HfUploadManifestConfig from .perspectives.jobs import PerspectivePipelineRunConfig + # Import jobs from .jobs import JOBS diff --git a/servers/inference_server/pipelines/pipelines/io/image/load_images.py b/servers/inference_server/pipelines/pipelines/io/image/load_images.py index 8c662a19..b66dd3f8 100644 --- a/servers/inference_server/pipelines/pipelines/io/image/load_images.py +++ b/servers/inference_server/pipelines/pipelines/io/image/load_images.py @@ -141,14 +141,9 @@ def image_dataset_config(context: dg.AssetExecutionContext, config: DatasetIOCon return config -@asset( - group_name="image_load", - compute_kind="python", - deps=["perspective_pipeline_run_config"] -) +@asset(group_name="image_load", compute_kind="python", deps=["perspective_pipeline_run_config"]) def perspective_image_list( - context: dg.AssetExecutionContext, - perspective_pipeline_run_config: PerspectivePipelineConfig + context: dg.AssetExecutionContext, perspective_pipeline_run_config: PerspectivePipelineConfig ) -> list[str]: """ Load raw images from directory using the perspective pipeline configuration. @@ -160,7 +155,7 @@ def perspective_image_list( list[str]: A list of image paths. """ io_config = perspective_pipeline_run_config.io - + context.log.info(f"Loading image list for dataset {io_config.dataset_name}") image_files = get_image_list( @@ -170,14 +165,16 @@ def perspective_image_list( sampling_strategy=SamplingStrategy(io_config.sampling_strategy), num_samples=io_config.num_samples, ) - + copied_image_files: list[str] = copy_images(context, image_files, io_config.output_dir) - - context.add_output_metadata({ - "dataset_name": io_config.dataset_name, - "input_dir": io_config.input_dir, - "output_dir": io_config.output_dir, - "num_images": len(copied_image_files) - }) - + + context.add_output_metadata( + { + "dataset_name": io_config.dataset_name, + "input_dir": io_config.input_dir, + "output_dir": io_config.output_dir, + "num_images": len(copied_image_files), + } + ) + return copied_image_files diff --git a/servers/inference_server/pipelines/pipelines/perspectives/assets.py b/servers/inference_server/pipelines/pipelines/perspectives/assets.py index f08dc4c4..ef1f4a2e 100644 --- a/servers/inference_server/pipelines/pipelines/perspectives/assets.py +++ b/servers/inference_server/pipelines/pipelines/perspectives/assets.py @@ -34,10 +34,7 @@ async def perspective_caption( perspective_config = perspective_pipeline_run_config.perspective # Get enabled perspectives - enabled_perspectives = [ - name for name, enabled in perspective_config.enabled_perspectives.items() - if enabled - ] + enabled_perspectives = [name for name, enabled in perspective_config.enabled_perspectives.items() if enabled] context.log.info(f"Processing enabled perspectives: {enabled_perspectives}") # Instantiate the client @@ -51,9 +48,11 @@ async def perspective_caption( # Process images in batch image_paths = [Path(image) for image in perspective_image_list] caption_data_list = await processor.process_batch( - client, image_paths, output_dir=Path(io_config.run_dir), + client, + image_paths, + output_dir=Path(io_config.run_dir), global_context=perspective_config.global_context, - name=perspective + name=perspective, ) # Aggregate results @@ -81,6 +80,7 @@ async def perspective_caption( context.add_output_metadata(metadata) return all_results + @dg.asset( group_name="perspectives", compute_kind="python", @@ -92,7 +92,7 @@ def caption_contexts( perspective_pipeline_run_config: PerspectivePipelineConfig, ) -> Dict[str, List[str]]: """Extracts contexts from the perspective caption data and adds to a dictionary of path:List[str]. - if the path exists, the context is appended to the list.""" + if the path exists, the context is appended to the list.""" contexts = {} for item in perspective_caption: context.log.info(f"Processing {item['image_filename']} ({item['perspective']})") @@ -106,6 +106,7 @@ def caption_contexts( context.log.info(contexts) return contexts + @dg.asset( group_name="perspectives", compute_kind="python", @@ -125,26 +126,28 @@ async def synthesizer_caption( client = get_provider(provider_config.provider_config_file, provider_config.default) synthesizer = get_synthesizer() - image_dir = Path(io_config.output_dir)/"images" + image_dir = Path(io_config.output_dir) / "images" paths = [image_dir / path for path in caption_contexts.keys()] - results = await synthesizer.process_batch(client, paths, - output_dir=Path(io_config.run_dir), - contexts=caption_contexts, - name="synthesized_caption") + results = await synthesizer.process_batch( + client, paths, output_dir=Path(io_config.run_dir), contexts=caption_contexts, name="synthesized_caption" + ) # Format the results to match the perspective_caption output formatted_results = [] for path, caption_data in zip(paths, results): image_filename = path.name - formatted_results.append({ - "perspective": "synthesized_caption", - "image_filename": image_filename, - "caption_data": caption_data, - "context": synthesizer.to_context(caption_data), - }) + formatted_results.append( + { + "perspective": "synthesized_caption", + "image_filename": image_filename, + "caption_data": caption_data, + "context": synthesizer.to_context(caption_data), + } + ) context.log.info(f"Synthesizer caption results: {formatted_results}") return formatted_results + @dg.asset( group_name="perspectives", compute_kind="python", @@ -164,8 +167,7 @@ def caption_output_files( run_dir.mkdir(parents=True, exist_ok=True) # Get enabled perspectives enabled_perspectives = [ - name for name, enabled in perspective_pipeline_run_config.perspective.enabled_perspectives.items() - if enabled + name for name, enabled in perspective_pipeline_run_config.perspective.enabled_perspectives.items() if enabled ] timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") # Prepare data for DataFrame @@ -232,4 +234,3 @@ def caption_output_files( "parquet_output_path": str(parquet_path), } ) - diff --git a/servers/inference_server/pipelines/pipelines/perspectives/jobs/__init__.py b/servers/inference_server/pipelines/pipelines/perspectives/jobs/__init__.py index 1059be32..e5c5ab3a 100644 --- a/servers/inference_server/pipelines/pipelines/perspectives/jobs/__init__.py +++ b/servers/inference_server/pipelines/pipelines/perspectives/jobs/__init__.py @@ -30,4 +30,3 @@ "perspective_pipeline_run_config", "basic_perspective_pipeline", ] - diff --git a/servers/inference_server/pipelines/pipelines/perspectives/jobs/basic_perspective_pipeline.py b/servers/inference_server/pipelines/pipelines/perspectives/jobs/basic_perspective_pipeline.py index a2809c35..dc45af08 100644 --- a/servers/inference_server/pipelines/pipelines/perspectives/jobs/basic_perspective_pipeline.py +++ b/servers/inference_server/pipelines/pipelines/perspectives/jobs/basic_perspective_pipeline.py @@ -15,5 +15,5 @@ "synthesizer_caption", "caption_output_files", ], - description="Basic perspective pipeline, graphcap's \"hello world\" example", + description='Basic perspective pipeline, graphcap\'s "hello world" example', ) diff --git a/servers/inference_server/pipelines/pipelines/perspectives/jobs/config.py b/servers/inference_server/pipelines/pipelines/perspectives/jobs/config.py index 666221a6..ddf01c8f 100644 --- a/servers/inference_server/pipelines/pipelines/perspectives/jobs/config.py +++ b/servers/inference_server/pipelines/pipelines/perspectives/jobs/config.py @@ -48,6 +48,7 @@ class PerspectiveConfig: global_context: str enabled_perspectives: Dict[str, bool] = Field(default_factory=dict) + class PerspectivePipelineConfig(BaseModel): """Configuration for pipeline runs loaded from TOML file.""" @@ -75,7 +76,7 @@ def load_dataset(self, context: dg.AssetExecutionContext) -> PerspectivePipeline # Create perspective config with enabled perspectives perspective = PerspectiveConfig( global_context=config["perspective"]["global_context"], - enabled_perspectives=config["perspective"]["enabled"] + enabled_perspectives=config["perspective"]["enabled"], ) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") run_dir = config["io"]["output_dir"] + "/" + timestamp @@ -106,12 +107,7 @@ def load_dataset(self, context: dg.AssetExecutionContext) -> PerspectivePipeline ) # Return the complete config object - return PerspectivePipelineConfig( - perspective=perspective, - io=io, - provider=provider, - filesystem=filesystem - ) + return PerspectivePipelineConfig(perspective=perspective, io=io, provider=provider, filesystem=filesystem) @dg.asset diff --git a/servers/inference_server/pipelines/pipelines/providers/util.py b/servers/inference_server/pipelines/pipelines/providers/util.py index f1a3a4b7..5f058ba2 100644 --- a/servers/inference_server/pipelines/pipelines/providers/util.py +++ b/servers/inference_server/pipelines/pipelines/providers/util.py @@ -2,6 +2,7 @@ from graphcap.providers.clients import get_client from ..perspectives.jobs.config import PerspectivePipelineConfig + def get_provider(config_path: str, default_provider: str): """Instantiates the client based on the provider configuration. diff --git a/servers/inference_server/scripts/__init__.py b/servers/inference_server/scripts/__init__.py index 7c922a24..d642b489 100644 --- a/servers/inference_server/scripts/__init__.py +++ b/servers/inference_server/scripts/__init__.py @@ -13,4 +13,4 @@ from .config_writer import write_toml_config from .setup import cli -__all__ = ['write_toml_config', 'cli'] +__all__ = ["write_toml_config", "cli"] diff --git a/servers/inference_server/scripts/__main__.py b/servers/inference_server/scripts/__main__.py index fe9d2b28..100824ca 100644 --- a/servers/inference_server/scripts/__main__.py +++ b/servers/inference_server/scripts/__main__.py @@ -1,4 +1,4 @@ from .setup import cli if __name__ == "__main__": - cli() \ No newline at end of file + cli() diff --git a/servers/inference_server/scripts/setup.py b/servers/inference_server/scripts/setup.py index 605953d1..451bcef8 100644 --- a/servers/inference_server/scripts/setup.py +++ b/servers/inference_server/scripts/setup.py @@ -106,14 +106,12 @@ def check_existing_files() -> tuple[bool, bool]: if os.path.exists(dotenv_path): overwrite_env = Confirm.ask( - "[bold blue].env file already exists. Do you want to overwrite it?[/]", - default=False + "[bold blue].env file already exists. Do you want to overwrite it?[/]", default=False ) if os.path.exists(provider_config_path): overwrite_config = Confirm.ask( - "[bold blue]provider.config.toml file already exists. Do you want to overwrite it?[/]", - default=False + "[bold blue]provider.config.toml file already exists. Do you want to overwrite it?[/]", default=False ) return overwrite_env, overwrite_config @@ -130,6 +128,7 @@ def get_provider_selections() -> tuple[bool, bool, bool, bool, bool]: return enable_hugging_face, enable_openai, enable_google, enable_vllm, enable_ollama + def get_postgres_selections() -> tuple[str, str, str]: """Collect user selections for what values to use for Postgres variables.""" console.print("\n[bold]Set the following values for the Postgres installation:[/]") @@ -139,7 +138,10 @@ def get_postgres_selections() -> tuple[str, str, str]: return postgres_user_value, postgres_password_value, postgres_database_value -def collect_env_variables(providers: tuple[bool, bool, bool, bool, bool], postgres: tuple[str, str, str]) -> Mapping[str, str | None]: + +def collect_env_variables( + providers: tuple[bool, bool, bool, bool, bool], postgres: tuple[str, str, str] +) -> Mapping[str, str | None]: """Collect environment variables based on enabled providers.""" enable_hugging_face, enable_openai, enable_google, enable_vllm, enable_ollama = providers postgres_user_value, postgres_password_value, postgres_database_value = postgres @@ -162,8 +164,7 @@ def collect_env_variables(providers: tuple[bool, bool, bool, bool, bool], postgr if enable_vllm and not env_vars["VLLM_BASE_URL"]: cprint("VLLM_BASE_URL not set.", "yellow") env_vars["VLLM_BASE_URL"] = Prompt.ask( - "[bold blue]Please enter the vLLM base URL[/]", - default="http://localhost:12434" + "[bold blue]Please enter the vLLM base URL[/]", default="http://localhost:12434" ) os.environ["VLLM_BASE_URL"] = env_vars["VLLM_BASE_URL"] @@ -205,7 +206,7 @@ def cli(): # Get provider selections provider_selections = get_provider_selections() - + # Get postgres selections postgres_selections = get_postgres_selections() @@ -225,9 +226,11 @@ def cli(): console.print("[bold green]Provider configuration has been saved to workspace/config/provider.config.toml![/]") console.print("[bold magenta]Graphcap instance is ready to be launched![/]") + def main(): """Entry point for the script""" cli() + if __name__ == "__main__": main() diff --git a/test/inference_tests/constants.py b/test/inference_tests/constants.py index 62e27c49..7c7afc73 100644 --- a/test/inference_tests/constants.py +++ b/test/inference_tests/constants.py @@ -19,7 +19,3 @@ class StructuredCaption(BaseModel): scratchpad: str caption: str - - - - diff --git a/test/inference_tests/ollama_client_test.py b/test/inference_tests/ollama_client_test.py index c86bd475..2662876e 100644 --- a/test/inference_tests/ollama_client_test.py +++ b/test/inference_tests/ollama_client_test.py @@ -23,40 +23,40 @@ async def test_structured_vision(): """Test structured vision capabilities with Ollama client.""" # Set up provider configuration config_path = os.environ.get("PROVIDER_CONFIG_PATH", PROVIDER_CONFIG_PATH) - + # Create a minimal provider config if it doesn't exist if not Path(config_path).exists(): logger.warning(f"Provider config not found at {config_path}, creating minimal config") os.makedirs(os.path.dirname(config_path), exist_ok=True) with open(config_path, "w") as f: f.write(EXAMPLE_CONFIG) - + # Initialize provider manager provider_manager = initialize_provider_manager(config_path) - + # Get the Ollama client try: client = get_provider_client("ollama") logger.info(f"Successfully initialized Ollama client with model: {client.default_model}") - + # Debug the base URL logger.info(f"Client base URL: {client.base_url}") except Exception as e: logger.error(f"Failed to initialize Ollama client: {e}") return - + # Define the image path image_path = IMAGE_PATH if not Path(image_path).exists(): logger.error(f"Test image not found at {image_path}") return - + # Define the prompt prompt = ( "Analyze the provided image and generate a structured caption. " "Include a brief scratchpad of your thought process and a final concise caption." ) - + try: # Call the vision method with structured output completion = await client.vision( @@ -64,14 +64,14 @@ async def test_structured_vision(): image=image_path, model=client.default_model, schema=StructuredCaption, - temperature=.7, + temperature=0.7, ) - + # Process the response - if hasattr(completion, 'choices') and hasattr(completion.choices[0].message, 'parsed'): + if hasattr(completion, "choices") and hasattr(completion.choices[0].message, "parsed"): # Access the parsed response parsed_response = completion.choices[0].message.parsed - + # Display as formatted JSON logger.info("Structured Caption (JSON):") formatted_json = json.dumps(parsed_response.model_dump(), indent=2) @@ -79,11 +79,11 @@ async def test_structured_vision(): else: logger.error("Unexpected response format") print("Raw response:", completion) - + except Exception as e: logger.error(f"Error during structured vision test: {e}") if __name__ == "__main__": # Run the async test - asyncio.run(test_structured_vision()) \ No newline at end of file + asyncio.run(test_structured_vision()) diff --git a/test/inference_tests/ollama_graphcap_REST.py b/test/inference_tests/ollama_graphcap_REST.py index 076d0fe7..5937f9cb 100644 --- a/test/inference_tests/ollama_graphcap_REST.py +++ b/test/inference_tests/ollama_graphcap_REST.py @@ -16,4 +16,4 @@ ], "global_context": "You are a structured captioning model." }' -""" \ No newline at end of file +""" diff --git a/test/inference_tests/ollama_structured_test.py b/test/inference_tests/ollama_structured_test.py index d058934b..bbbfed3a 100644 --- a/test/inference_tests/ollama_structured_test.py +++ b/test/inference_tests/ollama_structured_test.py @@ -4,14 +4,17 @@ import openai from pydantic import BaseModel from constants import PROVIDER_CONFIG_PATH, EXAMPLE_CONFIG, StructuredCaption, IMAGE_PATH, OLLAMA_DEFAULT_MODEL + # Initialize the client using the OpenAI compatibility layer. client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama") + # Define the StructuredCaption schema. class StructuredCaption(BaseModel): scratchpad: str caption: str + # Define the prompt for generating a structured caption. prompt = ( "Analyze the provided image and generate a structured caption. " @@ -33,7 +36,7 @@ class StructuredCaption(BaseModel): "content": [ {"type": "text", "text": prompt}, {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64_image}"}}, - ] + ], } ], response_format=StructuredCaption, @@ -50,4 +53,4 @@ class StructuredCaption(BaseModel): except openai.LengthFinishReasonError as e: print(f"Too many tokens: {e}") except Exception as e: - print(f"Error during API call: {e}") \ No newline at end of file + print(f"Error during API call: {e}") diff --git a/test/inference_tests/rest_api_test.py b/test/inference_tests/rest_api_test.py index cc6604ed..4b7a710f 100644 --- a/test/inference_tests/rest_api_test.py +++ b/test/inference_tests/rest_api_test.py @@ -21,7 +21,7 @@ logger.add( sys.stderr, level="DEBUG", - format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} - {message}" + format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} - {message}", ) # Constants @@ -34,8 +34,10 @@ logger.debug(f"Using Ollama host: {OLLAMA_HOST}") logger.debug(f"Full Ollama URL: {OLLAMA_BASE_URL}") + class CaptionRequest(BaseModel): """Request model for caption generation.""" + perspective: str image_path: str provider: str @@ -46,11 +48,14 @@ class CaptionRequest(BaseModel): context: Optional[List[str]] = ["string"] global_context: str = "You are a structured captioning model." + class StructuredCaption(BaseModel): """Response model for structured caption.""" + scratchpad: str caption: str + async def check_ollama_health(): """Check if Ollama is running and healthy.""" try: @@ -80,13 +85,14 @@ async def check_ollama_health(): logger.debug(f"Exception details: {e.__cause__ if hasattr(e, '__cause__') else 'No cause info'}") return False + async def test_caption_generation(provider: str): """Test the caption generation REST API endpoint. - + Args: provider: The provider to use for caption generation (e.g., 'ollama' or 'gemini') """ - logger.info(f"\n{'='*50}\nTesting with {provider.upper()} provider\n{'='*50}") + logger.info(f"\n{'=' * 50}\nTesting with {provider.upper()} provider\n{'=' * 50}") # For Ollama provider, check health first if provider == "ollama": @@ -107,7 +113,7 @@ async def test_caption_generation(provider: str): top_p=0.9, repetition_penalty=1.15, context=["string"], - global_context="You are a structured captioning model." + global_context="You are a structured captioning model.", ) endpoint = f"{API_BASE_URL}/perspectives/caption-from-path" @@ -122,10 +128,7 @@ async def test_caption_generation(provider: str): response = await client.post( endpoint, json=request.model_dump(), - headers={ - "accept": "application/json", - "Content-Type": "application/json" - } + headers={"accept": "application/json", "Content-Type": "application/json"}, ) # Log response details @@ -165,6 +168,7 @@ async def test_caption_generation(provider: str): logger.debug(f"Exception details: {e.__cause__ if hasattr(e, '__cause__') else 'No cause info'}") raise + async def run_tests(): """Run tests with different providers.""" logger.debug("Starting test run") @@ -179,6 +183,7 @@ async def run_tests(): logger.debug("Test run completed") + if __name__ == "__main__": # Run all tests logger.debug("Initializing test script") diff --git a/test/library_tests/provider_tests/test_provider_config.py b/test/library_tests/provider_tests/test_provider_config.py index f144c3de..97a20106 100644 --- a/test/library_tests/provider_tests/test_provider_config.py +++ b/test/library_tests/provider_tests/test_provider_config.py @@ -13,7 +13,6 @@ None (contains test functions only) """ - import pytest from graphcap.providers.provider_config import _load_provider_config, get_providers_config, validate_config diff --git a/test/library_tests/provider_tests/test_providers.py b/test/library_tests/provider_tests/test_providers.py index 25b9d539..7eb57045 100644 --- a/test/library_tests/provider_tests/test_providers.py +++ b/test/library_tests/provider_tests/test_providers.py @@ -48,6 +48,7 @@ class StructuredVisionConfig: prompt: str schema: BaseModel + class TestStructuredOutput(BaseModel): is_cat: bool caption: str @@ -155,7 +156,6 @@ async def test_gemini_structured_vision(self, test_logger, provider_manager, pro await run_structured_vision(client, test_logger, image_path) - @pytest.mark.integration @pytest.mark.vllm class TestVLLMProvider: @@ -227,7 +227,6 @@ async def test_vllm_structured_vision(self, test_logger, provider_manager, provi await run_structured_vision(client, test_logger, image_path) - @pytest.mark.asyncio @pytest.mark.integration @pytest.mark.provider From dbcdf35b411d7188f3e0f407e94df18d9d20bae5 Mon Sep 17 00:00:00 2001 From: jphillips Date: Tue, 18 Mar 2025 14:11:27 -0500 Subject: [PATCH 03/24] Add perspective route scaffolding, return perspective metadate from REST api Signed-off-by: jphillips --- .../src/app/layout/RootLeftActionPanel.tsx | 8 ++ .../icons/PerspectiveLayersIcon.tsx | 34 +++++++ .../src/components/icons/index.tsx | 3 + .../PerspectiveActions/PerspectivesFooter.tsx | 2 +- .../components/PerspectiveManagementPanel.tsx | 88 +++++++++++++++++++ .../features/perspectives/components/index.ts | 1 + .../context/PerspectivesDataContext.tsx | 6 +- .../src/features/perspectives/hooks/index.ts | 1 + .../hooks/usePerspectiveModules.ts | 31 +++++++ .../src/features/perspectives/index.ts | 3 + .../src/features/perspectives/types/index.ts | 3 +- .../types/perspectiveModuleTypes.ts | 72 +++++++++++++++ .../src/routes/perspectives/index.tsx | 14 +++ .../perspectives/module/$moduleName.tsx | 16 ++++ .../perspective/$perspectiveName.tsx | 20 +++++ 15 files changed, 297 insertions(+), 5 deletions(-) create mode 100644 graphcap_studio/src/components/icons/PerspectiveLayersIcon.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx create mode 100644 graphcap_studio/src/features/perspectives/hooks/usePerspectiveModules.ts create mode 100644 graphcap_studio/src/features/perspectives/types/perspectiveModuleTypes.ts create mode 100644 graphcap_studio/src/routes/perspectives/index.tsx create mode 100644 graphcap_studio/src/routes/perspectives/module/$moduleName.tsx create mode 100644 graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx diff --git a/graphcap_studio/src/app/layout/RootLeftActionPanel.tsx b/graphcap_studio/src/app/layout/RootLeftActionPanel.tsx index 9e163080..d9628ee5 100644 --- a/graphcap_studio/src/app/layout/RootLeftActionPanel.tsx +++ b/graphcap_studio/src/app/layout/RootLeftActionPanel.tsx @@ -9,6 +9,7 @@ import { DatasetIcon, FilterIcon, FlagIcon, + PerspectiveLayersIcon, ProviderIcon, SettingsIcon, } from "@/components/icons"; @@ -17,6 +18,7 @@ import { FeatureFlagsPanel } from "@/features/app-settings/feature-flags"; import { DatasetPanel } from "@/features/datasets"; import { ProvidersPanel } from "@/features/inference/providers"; import { PerspectiveFilterPanel } from "@/features/perspectives/components/PerspectiveFilterPanel"; +import { PerspectiveManagementPanel } from "@/features/perspectives/components/PerspectiveManagementPanel"; import { ActionPanel } from "./ActionPanel"; /** @@ -53,6 +55,12 @@ export function RootLeftActionPanel() { icon: , content: , }, + { + id: "perspective-management", + title: "Perspective Management", + icon: , + content: , + }, { id: "settings", title: "Settings", diff --git a/graphcap_studio/src/components/icons/PerspectiveLayersIcon.tsx b/graphcap_studio/src/components/icons/PerspectiveLayersIcon.tsx new file mode 100644 index 00000000..ff401984 --- /dev/null +++ b/graphcap_studio/src/components/icons/PerspectiveLayersIcon.tsx @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: Apache-2.0 + +/** + * PerspectiveLayersIcon component + * + * An icon representing perspectives with eye and layers + */ +interface IconProps { + className?: string; +} + +export function PerspectiveLayersIcon({ className = "" }: Readonly) { + return ( + + + + + + + + + + + ); +} diff --git a/graphcap_studio/src/components/icons/index.tsx b/graphcap_studio/src/components/icons/index.tsx index e2081567..c1a9b8c6 100644 --- a/graphcap_studio/src/components/icons/index.tsx +++ b/graphcap_studio/src/components/icons/index.tsx @@ -172,3 +172,6 @@ export function DatasetIcon({ className = "" }: Readonly) { ); } + +// Export for PerspectiveLayersIcon +export { PerspectiveLayersIcon } from "./PerspectiveLayersIcon"; diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveActions/PerspectivesFooter.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveActions/PerspectivesFooter.tsx index 8a36b6dd..8435416d 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveActions/PerspectivesFooter.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveActions/PerspectivesFooter.tsx @@ -16,7 +16,7 @@ import { usePerspectiveUI, usePerspectivesData, } from "@/features/perspectives/context"; -import { CaptionOptions } from "@/features/perspectives/types"; +import type { CaptionOptions } from "@/features/perspectives/types"; import { Box, Button, diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx new file mode 100644 index 00000000..0e8b0209 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: Apache-2.0 +/** + * Perspective Management Panel + * + * This component displays a panel for managing perspectives and modules + */ + +import { LoadingSpinner } from "@/components/ui/status/LoadingSpinner"; +import { Link } from "@tanstack/react-router"; +import { usePerspectiveModules } from "../hooks"; + +/** + * Panel component for perspective management + */ +export function PerspectiveManagementPanel() { + // Use the perspective modules hook to get real data + const { modules, isLoading, error } = usePerspectiveModules(); + + // Handle loading state + if (isLoading) { + return ( +
+ +

Loading perspectives...

+
+ ); + } + + // Handle error state + if (error) { + return ( +
+

Error loading perspectives:

+

{error.message}

+
+ ); + } + + return ( +
+
+

Perspective Management

+ + {modules.length === 0 ? ( +

No perspectives found.

+ ) : ( +
+ {modules.map((module) => ( +
+ + {module.name} + + +
    + {module.perspectives.map((perspective) => { + // Extract perspective ID from the full name + const perspectiveId = perspective.name.includes("/") + ? perspective.name.split("/").pop() + : perspective.name; + + return ( +
  • + + {perspective.display_name} + +
  • + ); + })} +
+
+ ))} +
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/index.ts b/graphcap_studio/src/features/perspectives/components/index.ts index b5b311e3..d2ae8495 100644 --- a/graphcap_studio/src/features/perspectives/components/index.ts +++ b/graphcap_studio/src/features/perspectives/components/index.ts @@ -13,3 +13,4 @@ export { PerspectiveHeader } from "./PerspectiveNavigation/PerspectiveHeader"; export { PerspectivesPager } from "./PerspectiveNavigation/PerspectivesPager"; export { MetadataDisplay } from "./PerspectiveCard/MetadataDisplay"; export * from "./PerspectiveActions"; +export * from "./PerspectiveManagementPanel"; diff --git a/graphcap_studio/src/features/perspectives/context/PerspectivesDataContext.tsx b/graphcap_studio/src/features/perspectives/context/PerspectivesDataContext.tsx index d51287c4..505f9327 100644 --- a/graphcap_studio/src/features/perspectives/context/PerspectivesDataContext.tsx +++ b/graphcap_studio/src/features/perspectives/context/PerspectivesDataContext.tsx @@ -11,11 +11,11 @@ import { useServerConnectionsContext } from "@/context"; import { SERVER_IDS } from "@/features/server-connections/constants"; -import { Image } from "@/services/images"; +import type { Image } from "@/services/images"; import React, { createContext, useContext, - ReactNode, + type ReactNode, useState, useCallback, useEffect, @@ -24,7 +24,7 @@ import React, { import { useProviders } from "../../inference/services/providers"; import { useGeneratePerspectiveCaption } from "../hooks/useGeneratePerspectiveCaption"; import { usePerspectives } from "../hooks/usePerspectives"; -import { +import type { CaptionOptions, Perspective, PerspectiveData, diff --git a/graphcap_studio/src/features/perspectives/hooks/index.ts b/graphcap_studio/src/features/perspectives/hooks/index.ts index 3f4c234e..f84eae00 100644 --- a/graphcap_studio/src/features/perspectives/hooks/index.ts +++ b/graphcap_studio/src/features/perspectives/hooks/index.ts @@ -12,6 +12,7 @@ export { usePerspectiveUI } from "./usePerspectiveUI"; export { usePerspectives } from "./usePerspectives"; export { useGeneratePerspectiveCaption } from "./useGeneratePerspectiveCaption"; export { useImagePerspectives } from "./useImagePerspectives"; +export { usePerspectiveModules } from "./usePerspectiveModules"; // Utilities export * from "./utils"; diff --git a/graphcap_studio/src/features/perspectives/hooks/usePerspectiveModules.ts b/graphcap_studio/src/features/perspectives/hooks/usePerspectiveModules.ts new file mode 100644 index 00000000..857c2a1c --- /dev/null +++ b/graphcap_studio/src/features/perspectives/hooks/usePerspectiveModules.ts @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: Apache-2.0 +/** + * usePerspectiveModules Hook + * + * This hook fetches available perspectives and groups them by module. + */ + +import { useMemo } from "react"; +import { PerspectiveModule, groupPerspectivesByModule } from "../types"; +import { usePerspectives } from "./usePerspectives"; + +/** + * Hook to fetch perspectives and organize them into modules + */ +export function usePerspectiveModules() { + // Fetch perspectives using the existing hook + const perspectivesQuery = usePerspectives(); + + // Group perspectives by module + const modules = useMemo(() => { + if (perspectivesQuery.data) { + return groupPerspectivesByModule(perspectivesQuery.data); + } + return []; + }, [perspectivesQuery.data]); + + return { + ...perspectivesQuery, + modules, + }; +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/index.ts b/graphcap_studio/src/features/perspectives/index.ts index 29204acd..a198b9b3 100644 --- a/graphcap_studio/src/features/perspectives/index.ts +++ b/graphcap_studio/src/features/perspectives/index.ts @@ -22,3 +22,6 @@ export * from "./types"; // Export hooks export * from "./hooks"; + +// Export components +export * from "./components"; diff --git a/graphcap_studio/src/features/perspectives/types/index.ts b/graphcap_studio/src/features/perspectives/types/index.ts index 83395f28..6b6024f2 100644 --- a/graphcap_studio/src/features/perspectives/types/index.ts +++ b/graphcap_studio/src/features/perspectives/types/index.ts @@ -3,7 +3,8 @@ * Perspectives Types * * This module exports all types used by the perspectives feature. - * All type definitions are consolidated in the perspectivesTypes.ts file. + * Type definitions are consolidated in their respective files. */ export * from "./perspectivesTypes"; +export * from "./perspectiveModuleTypes"; diff --git a/graphcap_studio/src/features/perspectives/types/perspectiveModuleTypes.ts b/graphcap_studio/src/features/perspectives/types/perspectiveModuleTypes.ts new file mode 100644 index 00000000..4e15c32a --- /dev/null +++ b/graphcap_studio/src/features/perspectives/types/perspectiveModuleTypes.ts @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +/** + * Perspective Module Types + * + * This module defines types related to perspective modules and management. + */ + +import type { Perspective } from "./perspectivesTypes"; + +/** + * Represents a module containing multiple perspectives + */ +export interface PerspectiveModule { + id: string; + name: string; + enabled: boolean; + perspectives: Perspective[]; +} + +/** + * Represents a list of perspective modules + */ +export interface PerspectiveModuleList { + modules: PerspectiveModule[]; +} + +/** + * Groups perspectives by module + * @param perspectives Array of all perspectives + * @returns Map of modules with their perspectives + */ +export function groupPerspectivesByModule( + perspectives: Perspective[], +): PerspectiveModule[] { + // Initialize with default modules + const moduleMap = new Map(); + + // Add core module as default + moduleMap.set("core", { + id: "core", + name: "Core", + enabled: true, + perspectives: [], + }); + + // Group perspectives by module + perspectives.forEach((perspective) => { + // Extract module from perspective name or use "core" as default + // The module can be detected by checking for "/" in the perspective name + const moduleId = perspective.name.includes("/") + ? perspective.name.split("/")[0] + : "core"; + + const moduleName = moduleId.charAt(0).toUpperCase() + moduleId.slice(1); + + // Create module if it doesn't exist + if (!moduleMap.has(moduleId)) { + moduleMap.set(moduleId, { + id: moduleId, + name: moduleName, + enabled: true, + perspectives: [], + }); + } + + // Add perspective to module + moduleMap.get(moduleId)?.perspectives.push(perspective); + }); + + // Convert map to array + return Array.from(moduleMap.values()); +} diff --git a/graphcap_studio/src/routes/perspectives/index.tsx b/graphcap_studio/src/routes/perspectives/index.tsx new file mode 100644 index 00000000..07c1feb8 --- /dev/null +++ b/graphcap_studio/src/routes/perspectives/index.tsx @@ -0,0 +1,14 @@ +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/perspectives/")({ + component: PerspectivesPage, +}); + +function PerspectivesPage() { + return ( +
+

Perspectives Management

+

Select a module and perspective from the sidebar to manage perspectives.

+
+ ); +} \ No newline at end of file diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx new file mode 100644 index 00000000..043f39d5 --- /dev/null +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx @@ -0,0 +1,16 @@ +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/perspectives/module/$moduleName")({ + component: ModulePage, +}); + +function ModulePage() { + const { moduleName } = Route.useParams(); + + return ( +
+

Module: {moduleName}

+

Select a perspective from this module in the sidebar.

+
+ ); +} \ No newline at end of file diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx new file mode 100644 index 00000000..651766bf --- /dev/null +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx @@ -0,0 +1,20 @@ +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/perspectives/module/$moduleName/perspective/$perspectiveName")({ + component: PerspectiveDetailPage, +}); + +function PerspectiveDetailPage() { + const { moduleName, perspectiveName } = Route.useParams(); + + return ( +
+

Perspective: {perspectiveName}

+

Module: {moduleName}

+
+

Perspective Details

+

This is where the perspective management UI will be implemented.

+
+
+ ); +} \ No newline at end of file From 386447d3a8213cbde01cffc239626664f0178c09 Mon Sep 17 00:00:00 2001 From: jphillips Date: Tue, 18 Mar 2025 14:38:10 -0500 Subject: [PATCH 04/24] Load local perspectives schemas Signed-off-by: jphillips --- .../src/components/icons/index.tsx | 6 +- .../server/features/perspectives/router.py | 56 ++++++++++- .../server/features/perspectives/service.py | 93 +++++++++---------- 3 files changed, 101 insertions(+), 54 deletions(-) diff --git a/graphcap_studio/src/components/icons/index.tsx b/graphcap_studio/src/components/icons/index.tsx index c1a9b8c6..35354bb1 100644 --- a/graphcap_studio/src/components/icons/index.tsx +++ b/graphcap_studio/src/components/icons/index.tsx @@ -22,8 +22,8 @@ export function FlagIcon({ className = "" }: Readonly) { width="20" height="20" > - - + + ); } @@ -45,7 +45,7 @@ export function FilterIcon({ className = "" }: Readonly) { width="20" height="20" > - + ); } diff --git a/servers/inference_server/server/server/features/perspectives/router.py b/servers/inference_server/server/server/features/perspectives/router.py index 8fc5d853..2b59c356 100644 --- a/servers/inference_server/server/server/features/perspectives/router.py +++ b/servers/inference_server/server/server/features/perspectives/router.py @@ -15,7 +15,7 @@ import os import tempfile from pathlib import Path -from typing import List, Optional +from typing import Any, Dict, List, Optional from fastapi import APIRouter, BackgroundTasks, File, Form, HTTPException, UploadFile, status from loguru import logger @@ -374,3 +374,57 @@ def _parse_context(context_str) -> Optional[List[str]]: return [context_str] except json.JSONDecodeError: return [context_str] + + +@router.get("/debug", response_model=Dict[str, Any], tags=["perspectives"]) +async def debug_perspectives() -> Dict[str, Any]: + """ + Get debug information about perspectives and their configurations. + This is intended for troubleshooting issues with perspective schemas. + """ + + from graphcap.perspectives import get_perspective, get_perspective_directories, get_perspective_list + + debug_info = { + "perspective_dirs": [str(p) for p in get_perspective_directories()], + "perspective_count": 0, + "available_files": [], + "perspectives": {} + } + + # List all JSON files in perspective directories + for directory in get_perspective_directories(): + if directory.exists(): + json_files = list(directory.glob("*.json")) + debug_info["available_files"].extend([str(f) for f in json_files]) + + # Get info about registered perspectives + perspective_names = get_perspective_list() + debug_info["perspective_count"] = len(perspective_names) + + # Get detailed info about each perspective + for name in perspective_names: + try: + perspective = get_perspective(name) + # Get attributes from the perspective object + attrs = {} + for attr in ["config_name", "display_name", "version", "description", "module_name"]: + if hasattr(perspective, attr): + attrs[attr] = getattr(perspective, attr) + + debug_info["perspectives"][name] = { + "attributes": attrs, + "schema_found": False + } + + # Check if we can load the schema + from ..perspectives.service import load_perspective_schema + schema = load_perspective_schema(name) + if schema: + debug_info["perspectives"][name]["schema_found"] = True + except Exception as e: + debug_info["perspectives"][name] = { + "error": str(e) + } + + return debug_info diff --git a/servers/inference_server/server/server/features/perspectives/service.py b/servers/inference_server/server/server/features/perspectives/service.py index 474a9071..6be906a7 100644 --- a/servers/inference_server/server/server/features/perspectives/service.py +++ b/servers/inference_server/server/server/features/perspectives/service.py @@ -6,7 +6,6 @@ """ import base64 -import json import os import socket import tempfile @@ -106,59 +105,53 @@ def load_perspective_schema(perspective_name: str) -> Optional[PerspectiveSchema Schema information for the perspective, or None if not found """ try: - # Construct the path to the schema file - schema_path = Path("/workspace/perspective_library") / f"{perspective_name}.json" - - # Check if the schema file exists - if not schema_path.exists(): - logger.warning(f"Schema file not found for perspective {perspective_name}") - return None - - # Load and parse the schema file - with open(schema_path, "r") as f: - schema_data = json.load(f) - - # Convert the schema data to our models - schema_fields = [] - for field_data in schema_data.get("schema_fields", []): - # Convert nested fields for complex types - nested_fields = None - if field_data.get("fields"): - nested_fields = [ + # Import perspective function + from graphcap.perspectives import get_perspective + + # Get the perspective processor + perspective = get_perspective(perspective_name) + if perspective and hasattr(perspective, 'config'): + # Extract config directly from the processor + config = perspective.config + + # Create schema fields + schema_fields = [] + for field in config.schema_fields: + schema_fields.append( SchemaField( - name=f["name"], - type=f["type"], - description=f["description"], - is_list=f.get("is_list", False), - is_complex=f.get("is_complex", False), + name=field.name, + type=field.type, + description=field.description, + is_list=getattr(field, "is_list", False), + is_complex=getattr(field, "is_complex", False), + fields=None ) - for f in field_data["fields"] - ] - - schema_fields.append( - SchemaField( - name=field_data["name"], - type=field_data["type"], - description=field_data["description"], - is_list=field_data.get("is_list", False), - is_complex=field_data.get("is_complex", False), - fields=nested_fields, ) - ) - table_columns = [ - TableColumn(name=col["name"], style=col["style"]) for col in schema_data.get("table_columns", []) - ] - - return PerspectiveSchema( - name=schema_data["name"], - display_name=schema_data["display_name"], - version=schema_data["version"], - prompt=schema_data["prompt"], - schema_fields=schema_fields, - table_columns=table_columns, - context_template=schema_data["context_template"], - ) + # Create table columns + table_columns = [ + TableColumn(name=col["name"], style=col["style"]) + for col in config.table_columns + ] + + # Create the schema + schema = PerspectiveSchema( + name=config.name, + display_name=config.display_name, + version=config.version, + prompt=config.prompt, + schema_fields=schema_fields, + table_columns=table_columns, + context_template=config.context_template + ) + + logger.info(f"Successfully loaded schema for perspective '{perspective_name}'") + return schema + + logger.warning(f"""Could not load schema for perspective '{perspective_name}': + Perspective not found or does not have config attribute""") + return None + except Exception as e: logger.error(f"Error loading schema for perspective {perspective_name}: {str(e)}") return None From 027d1f11fc6593e346f0b04dc95af83c49f4b1ba Mon Sep 17 00:00:00 2001 From: jphillips Date: Tue, 18 Mar 2025 15:48:45 -0500 Subject: [PATCH 05/24] Consolidate perspective management & filter panel Signed-off-by: jphillips --- .../src/app/layout/RootLeftActionPanel.tsx | 7 - .../icons/PerspectiveLayersIcon.tsx | 1 + .../src/components/icons/index.tsx | 28 +- .../components/PerspectiveFilterPanel.tsx | 8 +- .../components/PerspectiveManagementPanel.tsx | 130 +++++---- graphcap_studio/src/routeTree.gen.ts | 276 ++++++++++++------ 6 files changed, 297 insertions(+), 153 deletions(-) diff --git a/graphcap_studio/src/app/layout/RootLeftActionPanel.tsx b/graphcap_studio/src/app/layout/RootLeftActionPanel.tsx index d9628ee5..54e5ad96 100644 --- a/graphcap_studio/src/app/layout/RootLeftActionPanel.tsx +++ b/graphcap_studio/src/app/layout/RootLeftActionPanel.tsx @@ -17,7 +17,6 @@ import { SettingsPanel } from "@/features/app-settings"; import { FeatureFlagsPanel } from "@/features/app-settings/feature-flags"; import { DatasetPanel } from "@/features/datasets"; import { ProvidersPanel } from "@/features/inference/providers"; -import { PerspectiveFilterPanel } from "@/features/perspectives/components/PerspectiveFilterPanel"; import { PerspectiveManagementPanel } from "@/features/perspectives/components/PerspectiveManagementPanel"; import { ActionPanel } from "./ActionPanel"; @@ -49,12 +48,6 @@ export function RootLeftActionPanel() { icon: , content: , }, - { - id: "perspectives", - title: "Perspectives", - icon: , - content: , - }, { id: "perspective-management", title: "Perspective Management", diff --git a/graphcap_studio/src/components/icons/PerspectiveLayersIcon.tsx b/graphcap_studio/src/components/icons/PerspectiveLayersIcon.tsx index ff401984..11557f0f 100644 --- a/graphcap_studio/src/components/icons/PerspectiveLayersIcon.tsx +++ b/graphcap_studio/src/components/icons/PerspectiveLayersIcon.tsx @@ -21,6 +21,7 @@ export function PerspectiveLayersIcon({ className = "" }: Readonly) { strokeLinejoin="round" className={className} > + Perspectives diff --git a/graphcap_studio/src/components/icons/index.tsx b/graphcap_studio/src/components/icons/index.tsx index 35354bb1..9a37668f 100644 --- a/graphcap_studio/src/components/icons/index.tsx +++ b/graphcap_studio/src/components/icons/index.tsx @@ -21,7 +21,9 @@ export function FlagIcon({ className = "" }: Readonly) { className={className} width="20" height="20" + aria-labelledby="flagIconTitle" > + Flag @@ -44,7 +46,9 @@ export function FilterIcon({ className = "" }: Readonly) { className={className} width="20" height="20" + aria-labelledby="filterIconTitle" > + Filter ); @@ -66,11 +70,13 @@ export function ServerIcon({ className = "" }: Readonly) { className={className} width="20" height="20" + aria-labelledby="serverIconTitle" > - - - - + Server + + + + ); } @@ -91,8 +97,10 @@ export function FolderIcon({ className = "" }: Readonly) { className={className} width="20" height="20" + aria-labelledby="folderIconTitle" > - + Folder + ); } @@ -113,9 +121,11 @@ export function SettingsIcon({ className = "" }: Readonly) { className={className} width="20" height="20" + aria-labelledby="settingsIconTitle" > - - + Settings + + ); } @@ -136,7 +146,9 @@ export function ProviderIcon({ className = "" }: Readonly) { className={className} width="20" height="20" + aria-labelledby="providerIconTitle" > + Provider @@ -163,7 +175,9 @@ export function DatasetIcon({ className = "" }: Readonly) { className={className} width="20" height="20" + aria-labelledby="datasetIconTitle" > + Dataset diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx index 5f902e98..1277abe8 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx @@ -88,9 +88,11 @@ export function PerspectiveFilterPanel() { size="xs" variant="outline" colorScheme="blue" - onClick={() => - perspectives.forEach((p) => togglePerspectiveVisibility(p.name)) - } + onClick={() => { + for (const p of perspectives) { + togglePerspectiveVisibility(p.name); + } + }} > Toggle All diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx index 0e8b0209..0eddbda3 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx @@ -6,8 +6,11 @@ */ import { LoadingSpinner } from "@/components/ui/status/LoadingSpinner"; +import { Box } from "@chakra-ui/react"; +import { Tabs } from "@chakra-ui/react"; import { Link } from "@tanstack/react-router"; import { usePerspectiveModules } from "../hooks"; +import { PerspectiveFilterPanel } from "./PerspectiveFilterPanel"; /** * Panel component for perspective management @@ -19,70 +22,91 @@ export function PerspectiveManagementPanel() { // Handle loading state if (isLoading) { return ( -
+ -

Loading perspectives...

-
+ Loading perspectives... + ); } // Handle error state if (error) { return ( -
-

Error loading perspectives:

-

{error.message}

-
+ + Error loading perspectives: + {error.message} + ); } return ( -
-
-

Perspective Management

- - {modules.length === 0 ? ( -

No perspectives found.

- ) : ( -
- {modules.map((module) => ( -
- - {module.name} - - -
    - {module.perspectives.map((perspective) => { - // Extract perspective ID from the full name - const perspectiveId = perspective.name.includes("/") - ? perspective.name.split("/").pop() - : perspective.name; + + + + Modules + Visibility + + + + + + + Perspective Modules + + {modules.length === 0 ? ( + No perspectives found. + ) : ( + + {modules.map((module) => ( + + + {module.name} + - return ( -
  • - - {perspective.display_name} - -
  • - ); - })} -
-
- ))} -
- )} -
-
+ + {module.perspectives.map((perspective) => { + // Extract perspective ID from the full name + const perspectiveId = perspective.name.includes("/") + ? perspective.name.split("/").pop() || perspective.name + : perspective.name; + + return ( + + + {perspective.display_name} + + + ); + })} + + + ))} + + )} + + + + + + + + + ); } \ No newline at end of file diff --git a/graphcap_studio/src/routeTree.gen.ts b/graphcap_studio/src/routeTree.gen.ts index 48fd82b8..fc2a3bcf 100644 --- a/graphcap_studio/src/routeTree.gen.ts +++ b/graphcap_studio/src/routeTree.gen.ts @@ -10,123 +10,218 @@ // Import Routes -import { Route as rootRoute } from "./routes/__root"; -import { Route as AboutImport } from "./routes/about"; -import { Route as GalleryDatasetIdImport } from "./routes/gallery/$datasetId"; -import { Route as GalleryIndexImport } from "./routes/gallery/index"; -import { Route as IndexImport } from "./routes/index"; +import { Route as rootRoute } from './routes/__root' +import { Route as AboutImport } from './routes/about' +import { Route as IndexImport } from './routes/index' +import { Route as PerspectivesIndexImport } from './routes/perspectives/index' +import { Route as GalleryIndexImport } from './routes/gallery/index' +import { Route as GalleryDatasetIdImport } from './routes/gallery/$datasetId' +import { Route as PerspectivesModuleModuleNameImport } from './routes/perspectives/module/$moduleName' +import { Route as PerspectivesModuleModuleNamePerspectivePerspectiveNameImport } from './routes/perspectives/module/$moduleName/perspective/$perspectiveName' // Create/Update Routes const AboutRoute = AboutImport.update({ - id: "/about", - path: "/about", - getParentRoute: () => rootRoute, -} as any); + id: '/about', + path: '/about', + getParentRoute: () => rootRoute, +} as any) const IndexRoute = IndexImport.update({ - id: "/", - path: "/", - getParentRoute: () => rootRoute, -} as any); + id: '/', + path: '/', + getParentRoute: () => rootRoute, +} as any) + +const PerspectivesIndexRoute = PerspectivesIndexImport.update({ + id: '/perspectives/', + path: '/perspectives/', + getParentRoute: () => rootRoute, +} as any) const GalleryIndexRoute = GalleryIndexImport.update({ - id: "/gallery/", - path: "/gallery/", - getParentRoute: () => rootRoute, -} as any); + id: '/gallery/', + path: '/gallery/', + getParentRoute: () => rootRoute, +} as any) const GalleryDatasetIdRoute = GalleryDatasetIdImport.update({ - id: "/gallery/$datasetId", - path: "/gallery/$datasetId", - getParentRoute: () => rootRoute, -} as any); + id: '/gallery/$datasetId', + path: '/gallery/$datasetId', + getParentRoute: () => rootRoute, +} as any) + +const PerspectivesModuleModuleNameRoute = + PerspectivesModuleModuleNameImport.update({ + id: '/perspectives/module/$moduleName', + path: '/perspectives/module/$moduleName', + getParentRoute: () => rootRoute, + } as any) + +const PerspectivesModuleModuleNamePerspectivePerspectiveNameRoute = + PerspectivesModuleModuleNamePerspectivePerspectiveNameImport.update({ + id: '/perspective/$perspectiveName', + path: '/perspective/$perspectiveName', + getParentRoute: () => PerspectivesModuleModuleNameRoute, + } as any) // Populate the FileRoutesByPath interface -declare module "@tanstack/react-router" { - interface FileRoutesByPath { - "/": { - id: "/"; - path: "/"; - fullPath: "/"; - preLoaderRoute: typeof IndexImport; - parentRoute: typeof rootRoute; - }; - "/about": { - id: "/about"; - path: "/about"; - fullPath: "/about"; - preLoaderRoute: typeof AboutImport; - parentRoute: typeof rootRoute; - }; - "/gallery/$datasetId": { - id: "/gallery/$datasetId"; - path: "/gallery/$datasetId"; - fullPath: "/gallery/$datasetId"; - preLoaderRoute: typeof GalleryDatasetIdImport; - parentRoute: typeof rootRoute; - }; - "/gallery/": { - id: "/gallery/"; - path: "/gallery"; - fullPath: "/gallery"; - preLoaderRoute: typeof GalleryIndexImport; - parentRoute: typeof rootRoute; - }; - } +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexImport + parentRoute: typeof rootRoute + } + '/about': { + id: '/about' + path: '/about' + fullPath: '/about' + preLoaderRoute: typeof AboutImport + parentRoute: typeof rootRoute + } + '/gallery/$datasetId': { + id: '/gallery/$datasetId' + path: '/gallery/$datasetId' + fullPath: '/gallery/$datasetId' + preLoaderRoute: typeof GalleryDatasetIdImport + parentRoute: typeof rootRoute + } + '/gallery/': { + id: '/gallery/' + path: '/gallery' + fullPath: '/gallery' + preLoaderRoute: typeof GalleryIndexImport + parentRoute: typeof rootRoute + } + '/perspectives/': { + id: '/perspectives/' + path: '/perspectives' + fullPath: '/perspectives' + preLoaderRoute: typeof PerspectivesIndexImport + parentRoute: typeof rootRoute + } + '/perspectives/module/$moduleName': { + id: '/perspectives/module/$moduleName' + path: '/perspectives/module/$moduleName' + fullPath: '/perspectives/module/$moduleName' + preLoaderRoute: typeof PerspectivesModuleModuleNameImport + parentRoute: typeof rootRoute + } + '/perspectives/module/$moduleName/perspective/$perspectiveName': { + id: '/perspectives/module/$moduleName/perspective/$perspectiveName' + path: '/perspective/$perspectiveName' + fullPath: '/perspectives/module/$moduleName/perspective/$perspectiveName' + preLoaderRoute: typeof PerspectivesModuleModuleNamePerspectivePerspectiveNameImport + parentRoute: typeof PerspectivesModuleModuleNameImport + } + } } // Create and export the route tree +interface PerspectivesModuleModuleNameRouteChildren { + PerspectivesModuleModuleNamePerspectivePerspectiveNameRoute: typeof PerspectivesModuleModuleNamePerspectivePerspectiveNameRoute +} + +const PerspectivesModuleModuleNameRouteChildren: PerspectivesModuleModuleNameRouteChildren = + { + PerspectivesModuleModuleNamePerspectivePerspectiveNameRoute: + PerspectivesModuleModuleNamePerspectivePerspectiveNameRoute, + } + +const PerspectivesModuleModuleNameRouteWithChildren = + PerspectivesModuleModuleNameRoute._addFileChildren( + PerspectivesModuleModuleNameRouteChildren, + ) + export interface FileRoutesByFullPath { - "/": typeof IndexRoute; - "/about": typeof AboutRoute; - "/gallery/$datasetId": typeof GalleryDatasetIdRoute; - "/gallery": typeof GalleryIndexRoute; + '/': typeof IndexRoute + '/about': typeof AboutRoute + '/gallery/$datasetId': typeof GalleryDatasetIdRoute + '/gallery': typeof GalleryIndexRoute + '/perspectives': typeof PerspectivesIndexRoute + '/perspectives/module/$moduleName': typeof PerspectivesModuleModuleNameRouteWithChildren + '/perspectives/module/$moduleName/perspective/$perspectiveName': typeof PerspectivesModuleModuleNamePerspectivePerspectiveNameRoute } export interface FileRoutesByTo { - "/": typeof IndexRoute; - "/about": typeof AboutRoute; - "/gallery/$datasetId": typeof GalleryDatasetIdRoute; - "/gallery": typeof GalleryIndexRoute; + '/': typeof IndexRoute + '/about': typeof AboutRoute + '/gallery/$datasetId': typeof GalleryDatasetIdRoute + '/gallery': typeof GalleryIndexRoute + '/perspectives': typeof PerspectivesIndexRoute + '/perspectives/module/$moduleName': typeof PerspectivesModuleModuleNameRouteWithChildren + '/perspectives/module/$moduleName/perspective/$perspectiveName': typeof PerspectivesModuleModuleNamePerspectivePerspectiveNameRoute } export interface FileRoutesById { - __root__: typeof rootRoute; - "/": typeof IndexRoute; - "/about": typeof AboutRoute; - "/gallery/$datasetId": typeof GalleryDatasetIdRoute; - "/gallery/": typeof GalleryIndexRoute; + __root__: typeof rootRoute + '/': typeof IndexRoute + '/about': typeof AboutRoute + '/gallery/$datasetId': typeof GalleryDatasetIdRoute + '/gallery/': typeof GalleryIndexRoute + '/perspectives/': typeof PerspectivesIndexRoute + '/perspectives/module/$moduleName': typeof PerspectivesModuleModuleNameRouteWithChildren + '/perspectives/module/$moduleName/perspective/$perspectiveName': typeof PerspectivesModuleModuleNamePerspectivePerspectiveNameRoute } export interface FileRouteTypes { - fileRoutesByFullPath: FileRoutesByFullPath; - fullPaths: "/" | "/about" | "/gallery/$datasetId" | "/gallery"; - fileRoutesByTo: FileRoutesByTo; - to: "/" | "/about" | "/gallery/$datasetId" | "/gallery"; - id: "__root__" | "/" | "/about" | "/gallery/$datasetId" | "/gallery/"; - fileRoutesById: FileRoutesById; + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: + | '/' + | '/about' + | '/gallery/$datasetId' + | '/gallery' + | '/perspectives' + | '/perspectives/module/$moduleName' + | '/perspectives/module/$moduleName/perspective/$perspectiveName' + fileRoutesByTo: FileRoutesByTo + to: + | '/' + | '/about' + | '/gallery/$datasetId' + | '/gallery' + | '/perspectives' + | '/perspectives/module/$moduleName' + | '/perspectives/module/$moduleName/perspective/$perspectiveName' + id: + | '__root__' + | '/' + | '/about' + | '/gallery/$datasetId' + | '/gallery/' + | '/perspectives/' + | '/perspectives/module/$moduleName' + | '/perspectives/module/$moduleName/perspective/$perspectiveName' + fileRoutesById: FileRoutesById } export interface RootRouteChildren { - IndexRoute: typeof IndexRoute; - AboutRoute: typeof AboutRoute; - GalleryDatasetIdRoute: typeof GalleryDatasetIdRoute; - GalleryIndexRoute: typeof GalleryIndexRoute; + IndexRoute: typeof IndexRoute + AboutRoute: typeof AboutRoute + GalleryDatasetIdRoute: typeof GalleryDatasetIdRoute + GalleryIndexRoute: typeof GalleryIndexRoute + PerspectivesIndexRoute: typeof PerspectivesIndexRoute + PerspectivesModuleModuleNameRoute: typeof PerspectivesModuleModuleNameRouteWithChildren } const rootRouteChildren: RootRouteChildren = { - IndexRoute: IndexRoute, - AboutRoute: AboutRoute, - GalleryDatasetIdRoute: GalleryDatasetIdRoute, - GalleryIndexRoute: GalleryIndexRoute, -}; + IndexRoute: IndexRoute, + AboutRoute: AboutRoute, + GalleryDatasetIdRoute: GalleryDatasetIdRoute, + GalleryIndexRoute: GalleryIndexRoute, + PerspectivesIndexRoute: PerspectivesIndexRoute, + PerspectivesModuleModuleNameRoute: + PerspectivesModuleModuleNameRouteWithChildren, +} export const routeTree = rootRoute - ._addFileChildren(rootRouteChildren) - ._addFileTypes(); + ._addFileChildren(rootRouteChildren) + ._addFileTypes() /* ROUTE_MANIFEST_START { @@ -137,7 +232,9 @@ export const routeTree = rootRoute "/", "/about", "/gallery/$datasetId", - "/gallery/" + "/gallery/", + "/perspectives/", + "/perspectives/module/$moduleName" ] }, "/": { @@ -151,6 +248,19 @@ export const routeTree = rootRoute }, "/gallery/": { "filePath": "gallery/index.tsx" + }, + "/perspectives/": { + "filePath": "perspectives/index.tsx" + }, + "/perspectives/module/$moduleName": { + "filePath": "perspectives/module/$moduleName.tsx", + "children": [ + "/perspectives/module/$moduleName/perspective/$perspectiveName" + ] + }, + "/perspectives/module/$moduleName/perspective/$perspectiveName": { + "filePath": "perspectives/module/$moduleName/perspective/$perspectiveName.tsx", + "parent": "/perspectives/module/$moduleName" } } } From ec0c2a6f15705b2faae8fe5e9de9f2689d3e67d4 Mon Sep 17 00:00:00 2001 From: jphillips Date: Tue, 18 Mar 2025 17:12:42 -0500 Subject: [PATCH 06/24] Implement perspective module subroute Signed-off-by: jphillips --- .../PerspectiveModules/ErrorDisplay.tsx | 23 ++ .../PerspectiveModules/LoadingDisplay.tsx | 21 ++ .../PerspectiveModules/ModuleInfo.tsx | 43 +++ .../PerspectiveModules/ModuleList.tsx | 70 +++++ .../PerspectiveModules/NotFound.tsx | 54 ++++ .../PerspectiveModules/PerspectiveDetail.tsx | 277 ++++++++++++++++++ .../components/PerspectiveModules/index.ts | 6 + .../src/routes/perspectives/index.tsx | 119 +++++++- .../perspectives/module/$moduleName.tsx | 75 ++++- .../perspective/$perspectiveName.tsx | 56 +++- 10 files changed, 716 insertions(+), 28 deletions(-) create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveModules/ErrorDisplay.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveModules/LoadingDisplay.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleInfo.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveModules/NotFound.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveModules/PerspectiveDetail.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveModules/index.ts diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ErrorDisplay.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ErrorDisplay.tsx new file mode 100644 index 00000000..6345fffe --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ErrorDisplay.tsx @@ -0,0 +1,23 @@ +import { + Box, + Heading, + Text, +} from "@chakra-ui/react"; + +interface ErrorDisplayProps { + message: string; +} + +/** + * ErrorDisplay component displays an error message + */ +export function ErrorDisplay({ message }: ErrorDisplayProps) { + return ( + + + Error + {message} + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/LoadingDisplay.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/LoadingDisplay.tsx new file mode 100644 index 00000000..b31a60c9 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/LoadingDisplay.tsx @@ -0,0 +1,21 @@ +import { + Box, + Spinner, + Text, +} from "@chakra-ui/react"; + +interface LoadingDisplayProps { + message?: string; +} + +/** + * LoadingDisplay component shows a loading spinner with an optional message + */ +export function LoadingDisplay({ message = "Loading..." }: LoadingDisplayProps) { + return ( + + + {message} + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleInfo.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleInfo.tsx new file mode 100644 index 00000000..3a7db304 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleInfo.tsx @@ -0,0 +1,43 @@ +import { useColorModeValue } from "@/components/ui/theme/color-mode"; +import type { PerspectiveModule } from "@/features/perspectives/types"; +import { + Badge, + Box, + Flex, + Heading, + Text, +} from "@chakra-ui/react"; + +interface ModuleInfoProps { + module: PerspectiveModule; +} + +/** + * ModuleInfo component displays information about a perspective module + */ +export function ModuleInfo({ module }: ModuleInfoProps) { + const borderColor = useColorModeValue("gray.200", "gray.700"); + + return ( + <> + + {module.name} + + {module.enabled ? "Enabled" : "Disabled"} + + + + + + + + Module Information + + + This module contains {module.perspectives.length}{" "} + perspectives. + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx new file mode 100644 index 00000000..a2e024c8 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx @@ -0,0 +1,70 @@ +import type { Perspective, PerspectiveModule } from "@/features/perspectives/types"; +import { + Badge, + Box, + Button, + Flex, + Heading, + Stack, + Text, + VStack, +} from "@chakra-ui/react"; +import { Link } from "@tanstack/react-router"; + +interface ModuleListProps { + module: PerspectiveModule; +} + +/** + * ModuleList component displays a list of perspectives from a specific module + */ +export function ModuleList({ module }: ModuleListProps) { + if (module.perspectives.length === 0) { + return No perspectives found in this module.; + } + + return ( + + {module.perspectives.map((perspective: Perspective) => ( + + + + {perspective.display_name || perspective.name} + + {perspective.version} + + + {perspective.schema?.prompt?.substring(0, 60) || "No prompt available"}... + + {perspective.name && ( + + + + )} + + ))} + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/NotFound.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/NotFound.tsx new file mode 100644 index 00000000..1d94b7b5 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/NotFound.tsx @@ -0,0 +1,54 @@ +import { + Box, + Button, + Heading, + Text, +} from "@chakra-ui/react"; +import { Link } from "@tanstack/react-router"; + +interface NotFoundProps { + type: "module" | "perspective"; + name: string; + moduleName?: string; +} + +/** + * NotFound component displays a message when a module or perspective is not found + */ +export function NotFound({ type, name, moduleName }: NotFoundProps) { + const getMessage = () => { + if (type === "module") { + return `The module "${name}" could not be found.`; + } + return `Perspective "${name}" not found in module "${moduleName}".`; + }; + + const getBackLink = () => { + if (type === "module") { + return { to: "/perspectives", params: {} }; + } + return { + to: "/perspectives/module/$moduleName", + params: { moduleName: moduleName || "" } + }; + }; + + return ( + + + Not Found + {getMessage()} + + + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/PerspectiveDetail.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/PerspectiveDetail.tsx new file mode 100644 index 00000000..cf430a9b --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/PerspectiveDetail.tsx @@ -0,0 +1,277 @@ +import { useColorModeValue } from "@/components/ui/theme/color-mode"; +import type { Perspective } from "@/features/perspectives/types"; +import { + Badge, + Box, + Button, + Code, + Flex, + Heading, + Stack, + Tabs, + Text, +} from "@chakra-ui/react"; +import { Link } from "@tanstack/react-router"; + +interface PerspectiveDetailProps { + perspective: Perspective; + moduleName: string; +} + +/** + * PerspectiveDetail component displays detailed information about a perspective + */ +export function PerspectiveDetail({ + perspective, + moduleName, +}: PerspectiveDetailProps) { + // Color mode values + const borderColor = useColorModeValue("gray.200", "gray.700"); + const tableHeaderBg = useColorModeValue("gray.50", "gray.700"); + const tableBorderColor = useColorModeValue("gray.200", "gray.600"); + + return ( + + {/* Header */} + + + + + {perspective.display_name || perspective.name} + + {perspective.version} + + Module: {moduleName} + + + + + + + + + {/* Description */} + + + Description + + {perspective.description || "No description available."} + + + {/* Tabs for different sections */} + + + Schema + Fields + Prompt + Management + + + + + + {perspective.schema ? ( + + + Schema Information + + + + Name: + {perspective.schema.name} + + + Version: + {perspective.schema.version} + + + + Context Template: + + {perspective.schema.context_template || "None"} + + + + + ) : ( + No schema information available for this perspective. + )} + + + + {perspective.schema?.schema_fields && + perspective.schema.schema_fields.length > 0 ? ( + + + + + + Name + + + Type + + + Description + + + List + + + Complex + + + + + {perspective.schema.schema_fields.map((field) => ( + + + {field.name} + + + {field.type} + + + {field.description} + + + {field.is_list ? "Yes" : "No"} + + + {field.is_complex ? "Yes" : "No"} + + + ))} + + + + ) : ( + No fields defined for this perspective. + )} + + + + + + Prompt Template + + + + {perspective.schema?.prompt ?? + "No prompt template available."} + + + + + + + + + Perspective Management + + + This section will allow you to edit and manage the perspective. + + + + + {perspective.schema?.table_columns && + perspective.schema.table_columns.length > 0 && ( + + + Table Columns + + + + + + Name + + + Style + + + Description + + + + + {perspective.schema.table_columns.map((column) => ( + + + {column.name} + + + {column.style} + + + {column.description || "-"} + + + ))} + + + + )} + + + + Metadata + + + {perspective.version && ( + Version: {perspective.version} + )} + + + + + + + + + + ); +} diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/index.ts b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/index.ts new file mode 100644 index 00000000..d3f7530f --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/index.ts @@ -0,0 +1,6 @@ +export { ModuleList } from './ModuleList'; +export { ModuleInfo } from './ModuleInfo'; +export { NotFound } from './NotFound'; +export { ErrorDisplay } from './ErrorDisplay'; +export { LoadingDisplay } from './LoadingDisplay'; +export { PerspectiveDetail } from './PerspectiveDetail'; diff --git a/graphcap_studio/src/routes/perspectives/index.tsx b/graphcap_studio/src/routes/perspectives/index.tsx index 07c1feb8..6b39f973 100644 --- a/graphcap_studio/src/routes/perspectives/index.tsx +++ b/graphcap_studio/src/routes/perspectives/index.tsx @@ -1,14 +1,115 @@ -import { createFileRoute } from "@tanstack/react-router"; +import { + SelectContent, + SelectItem, + SelectRoot, + SelectTrigger, + SelectValueText, +} from "@/components/ui/select"; +import { usePerspectiveModules } from "@/features/perspectives/hooks"; +import { Box, Flex, Heading, Spinner, Text } from "@chakra-ui/react"; +import { + type SelectValueChangeDetails, + createListCollection, +} from "@chakra-ui/react"; +import { Link, createFileRoute, useNavigate } from "@tanstack/react-router"; export const Route = createFileRoute("/perspectives/")({ - component: PerspectivesPage, + component: PerspectivesPage, }); +// Define the module item interface +interface ModuleItem { + label: string; + value: string; +} + function PerspectivesPage() { - return ( -
-

Perspectives Management

-

Select a module and perspective from the sidebar to manage perspectives.

-
- ); -} \ No newline at end of file + const { modules, isLoading, error } = usePerspectiveModules(); + const navigate = useNavigate(); + + // Create items collection for the select + const moduleItems: ModuleItem[] = + modules?.map((module) => ({ + label: `${module.name} (${module.perspectives.length} perspectives)`, + value: module.id, + })) || []; + + const collection = createListCollection({ + items: moduleItems, + }); + + // Handle module selection + const handleModuleChange = ( + details: SelectValueChangeDetails, + ) => { + if (details.value.length > 0) { + navigate({ + to: "/perspectives/module/$moduleName", + params: { moduleName: details.value[0] }, + }); + } + }; + + if (isLoading) { + return ( + + + Loading perspective modules... + + ); + } + + if (error) { + return ( + + + Error + {error.message} + + + ); + } + + return ( + + + Perspectives Management + + + + + + + Select a Module + + + Choose a module to browse its perspectives or manage configurations. + + + + + + + + + {moduleItems.map((item) => ( + + {item.label} + + ))} + + + + + + Total modules: {modules?.length || 0} + + + + ); +} diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx index 043f39d5..e3e3723f 100644 --- a/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx @@ -1,16 +1,69 @@ -import { createFileRoute } from "@tanstack/react-router"; +import { ErrorDisplay, LoadingDisplay, ModuleInfo, ModuleList, NotFound } from "@/features/perspectives/components/PerspectiveModules"; +import { usePerspectiveModules } from "@/features/perspectives/hooks"; +import type { PerspectiveModule } from "@/features/perspectives/types"; +import { + Box, + Flex, + Heading, +} from "@chakra-ui/react"; +import { Outlet, createFileRoute } from "@tanstack/react-router"; +import { useEffect, useState } from "react"; export const Route = createFileRoute("/perspectives/module/$moduleName")({ - component: ModulePage, + component: ModulePage, }); function ModulePage() { - const { moduleName } = Route.useParams(); - - return ( -
-

Module: {moduleName}

-

Select a perspective from this module in the sidebar.

-
- ); -} \ No newline at end of file + const { moduleName } = Route.useParams(); + const { modules, isLoading, error } = usePerspectiveModules(); + const [selectedModule, setSelectedModule] = + useState(null); + + // Find the selected module when data is loaded + useEffect(() => { + if (modules && modules.length > 0) { + const module = modules.find((m) => m.id === moduleName); + setSelectedModule(module || null); + } + }, [modules, moduleName]); + + // Handle loading state + if (isLoading) { + return ; + } + + // Handle error state + if (error) { + return ; + } + + // Handle case when module is not found + if (!selectedModule) { + return ; + } + + return ( + + {/* Module information at the top */} + + + + + {/* Main content area with list and outlet */} + + {/* Left sidebar with perspectives list (20% width) */} + + + Perspectives + + + + + {/* Right content area with outlet (80% width) */} + + + + + + ); +} diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx index 651766bf..02382499 100644 --- a/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx @@ -1,4 +1,11 @@ +import { useColorModeValue } from "@/components/ui/theme/color-mode"; +import { ErrorDisplay, LoadingDisplay, NotFound, PerspectiveDetail } from "@/features/perspectives/components/PerspectiveModules"; +import { usePerspectives } from "@/features/perspectives/hooks"; +import { + Box, +} from "@chakra-ui/react"; import { createFileRoute } from "@tanstack/react-router"; +import { useMemo } from "react"; export const Route = createFileRoute("/perspectives/module/$moduleName/perspective/$perspectiveName")({ component: PerspectiveDetailPage, @@ -6,15 +13,48 @@ export const Route = createFileRoute("/perspectives/module/$moduleName/perspecti function PerspectiveDetailPage() { const { moduleName, perspectiveName } = Route.useParams(); + const { data: perspectives, isLoading, error } = usePerspectives(); + // Color mode values + const bgColor = useColorModeValue("white", "gray.800"); + + // Find the specific perspective + const perspective = useMemo(() => { + if (!perspectives) return null; + + // First try direct match + let foundPerspective = perspectives.find(p => p.name === perspectiveName); + + // If not found, try to match with module prefix + if (!foundPerspective) { + const fullName = `${moduleName}/${perspectiveName}`; + foundPerspective = perspectives.find(p => p.name === fullName); + } + + return foundPerspective; + }, [perspectives, perspectiveName, moduleName]); + + // Handle loading state + if (isLoading) { + return ; + } + + // Handle error state + if (error) { + return ; + } + + // Handle case when perspective is not found + if (!perspective) { + return ; + } + return ( -
-

Perspective: {perspectiveName}

-

Module: {moduleName}

-
-

Perspective Details

-

This is where the perspective management UI will be implemented.

-
-
+ + + ); } \ No newline at end of file From 78f7f18cbd4a1b3501a6f549e27f9e7340508500 Mon Sep 17 00:00:00 2001 From: jphillips Date: Tue, 18 Mar 2025 22:49:21 +0000 Subject: [PATCH 07/24] Add perspective module endpoint Signed-off-by: jphillips --- .../server/features/perspectives/models.py | 23 +++ .../server/features/perspectives/router.py | 150 +++++++----------- .../server/features/perspectives/service.py | 70 +++++++- 3 files changed, 151 insertions(+), 92 deletions(-) diff --git a/servers/inference_server/server/server/features/perspectives/models.py b/servers/inference_server/server/server/features/perspectives/models.py index a5d043cd..54a6bfcf 100644 --- a/servers/inference_server/server/server/features/perspectives/models.py +++ b/servers/inference_server/server/server/features/perspectives/models.py @@ -76,6 +76,29 @@ class PerspectiveListResponse(BaseModel): perspectives: List[PerspectiveInfo] = Field(..., description="List of available perspectives") +class ModuleInfo(BaseModel): + """Information about a perspective module.""" + + name: str = Field(..., description="Unique identifier for the module") + display_name: str = Field(..., description="Human-readable name for the module") + description: str = Field("", description="Description of the module") + enabled: bool = Field(True, description="Whether the module is enabled") + perspective_count: int = Field(0, description="Number of perspectives in this module") + + +class ModuleListResponse(BaseModel): + """Response model for listing available modules.""" + + modules: List[ModuleInfo] = Field(..., description="List of available modules") + + +class ModulePerspectivesResponse(BaseModel): + """Response model for perspectives in a module.""" + + module: ModuleInfo = Field(..., description="Information about the module") + perspectives: List[PerspectiveInfo] = Field(..., description="List of perspectives in the module") + + class ImageSource(BaseModel): """Source of an image for captioning.""" diff --git a/servers/inference_server/server/server/features/perspectives/router.py b/servers/inference_server/server/server/features/perspectives/router.py index 2b59c356..3671273e 100644 --- a/servers/inference_server/server/server/features/perspectives/router.py +++ b/servers/inference_server/server/server/features/perspectives/router.py @@ -9,22 +9,32 @@ - POST /perspectives/caption - Generate a caption for an image using file upload - GET /perspectives/debug/{perspective_name} - Get debug information about a perspective - POST /perspectives/caption-from-path - Generate a caption for an image using a file path +- GET /perspectives/modules - List all available perspective modules +- GET /perspectives/modules/{module_name} - Get perspectives for a specific module """ import json import os import tempfile from pathlib import Path -from typing import Any, Dict, List, Optional +from typing import List, Optional from fastapi import APIRouter, BackgroundTasks, File, Form, HTTPException, UploadFile, status from loguru import logger from ...utils.resizing import ResolutionPreset, log_resize_options, resize_image -from .models import CaptionPathRequest, CaptionResponse, PerspectiveListResponse +from .models import ( + CaptionPathRequest, + CaptionResponse, + ModuleListResponse, + ModulePerspectivesResponse, + PerspectiveListResponse, +) from .service import ( generate_caption, + get_available_modules, get_available_perspectives, + get_perspectives_by_module, save_uploaded_file, ) @@ -43,48 +53,6 @@ async def list_perspectives() -> PerspectiveListResponse: return PerspectiveListResponse(perspectives=perspectives) -@router.get("/debug/{perspective_name}") -async def debug_perspective(perspective_name: str) -> dict: - """ - Get debug information about a perspective. - Args: - perspective_name: Name of the perspective to debug - Returns: - Debug information about the perspective - Raises: - HTTPException: If the perspective is not found - """ - from graphcap.perspectives import get_perspective - - try: - perspective = get_perspective(perspective_name) - # Get perspective attributes - attributes = { - "config_name": perspective.config_name, - "display_name": perspective.display_name, - "version": perspective.version, - "has_process_single": hasattr(perspective, "process_single"), - "has_process_batch": hasattr(perspective, "process_batch"), - } - # Get method signatures if available - if attributes["has_process_single"]: - import inspect - - attributes["process_single_signature"] = str(inspect.signature(perspective.process_single)) - if attributes["has_process_batch"]: - import inspect - - attributes["process_batch_signature"] = str(inspect.signature(perspective.process_batch)) - return { - "perspective": perspective_name, - "attributes": attributes, - "type": str(type(perspective)), - } - except Exception as e: - logger.error(f"Error getting perspective debug info: {str(e)}") - raise HTTPException(status_code=404, detail=f"Error getting perspective debug info: {str(e)}") - - @router.post("/caption", response_model=CaptionResponse, status_code=status.HTTP_200_OK) async def create_caption( background_tasks: BackgroundTasks, @@ -376,55 +344,55 @@ def _parse_context(context_str) -> Optional[List[str]]: return [context_str] -@router.get("/debug", response_model=Dict[str, Any], tags=["perspectives"]) -async def debug_perspectives() -> Dict[str, Any]: + + +@router.get("/modules", response_model=ModuleListResponse) +async def list_modules() -> ModuleListResponse: """ - Get debug information about perspectives and their configurations. - This is intended for troubleshooting issues with perspective schemas. + List all available perspective modules. + + Returns: + List of available modules with metadata """ + modules = get_available_modules() + return ModuleListResponse(modules=modules) - from graphcap.perspectives import get_perspective, get_perspective_directories, get_perspective_list - debug_info = { - "perspective_dirs": [str(p) for p in get_perspective_directories()], - "perspective_count": 0, - "available_files": [], - "perspectives": {} - } - - # List all JSON files in perspective directories - for directory in get_perspective_directories(): - if directory.exists(): - json_files = list(directory.glob("*.json")) - debug_info["available_files"].extend([str(f) for f in json_files]) - - # Get info about registered perspectives - perspective_names = get_perspective_list() - debug_info["perspective_count"] = len(perspective_names) - - # Get detailed info about each perspective - for name in perspective_names: - try: - perspective = get_perspective(name) - # Get attributes from the perspective object - attrs = {} - for attr in ["config_name", "display_name", "version", "description", "module_name"]: - if hasattr(perspective, attr): - attrs[attr] = getattr(perspective, attr) - - debug_info["perspectives"][name] = { - "attributes": attrs, - "schema_found": False - } - - # Check if we can load the schema - from ..perspectives.service import load_perspective_schema - schema = load_perspective_schema(name) - if schema: - debug_info["perspectives"][name]["schema_found"] = True - except Exception as e: - debug_info["perspectives"][name] = { - "error": str(e) - } +@router.get("/modules/{module_name}", response_model=ModulePerspectivesResponse) +async def get_module_perspectives(module_name: str) -> ModulePerspectivesResponse: + """ + Get all perspectives that belong to a specific module. + + Args: + module_name: Name of the module to get perspectives for + + Returns: + Module information and list of perspectives in the module - return debug_info + Raises: + HTTPException: If the module is not found + """ + try: + # Get perspectives for the module + perspectives = get_perspectives_by_module(module_name) + + # Get module info + modules = get_available_modules() + module = next((m for m in modules if m.name == module_name), None) + + if not module: + raise HTTPException(status_code=404, detail=f"Module '{module_name}' not found") + + return ModulePerspectivesResponse( + module=module, + perspectives=perspectives + ) + except HTTPException: + # Re-raise HTTP exceptions + raise + except Exception as e: + logger.error(f"Error getting perspectives for module '{module_name}': {str(e)}") + raise HTTPException( + status_code=500, + detail=f"Error getting perspectives for module '{module_name}': {str(e)}" + ) diff --git a/servers/inference_server/server/server/features/perspectives/service.py b/servers/inference_server/server/server/features/perspectives/service.py index 6be906a7..d52d969b 100644 --- a/servers/inference_server/server/server/features/perspectives/service.py +++ b/servers/inference_server/server/server/features/perspectives/service.py @@ -11,6 +11,7 @@ import tempfile from pathlib import Path from typing import Dict, List, Optional +from collections import defaultdict import aiohttp from fastapi import HTTPException, UploadFile @@ -22,7 +23,7 @@ from loguru import logger from ..providers.service import get_provider_manager -from .models import PerspectiveInfo, PerspectiveSchema, SchemaField, TableColumn +from .models import ModuleInfo, PerspectiveInfo, PerspectiveSchema, SchemaField, TableColumn async def download_image(url: str) -> Path: @@ -192,6 +193,73 @@ def get_available_perspectives() -> List[PerspectiveInfo]: return perspectives +def get_available_modules() -> List[ModuleInfo]: + """ + Get a list of available modules and their metadata. + + Returns: + List of module information + """ + perspectives = get_available_perspectives() + + # Group perspectives by module + module_map = defaultdict(list) + for perspective in perspectives: + module_map[perspective.module].append(perspective) + + # Create module info objects + modules = [] + for module_name, module_perspectives in module_map.items(): + # Try to find a display name, falling back to the module name + display_name = module_name.replace("_", " ").title() + + modules.append( + ModuleInfo( + name=module_name, + display_name=display_name, + description=f"Contains {len(module_perspectives)} perspectives", + enabled=True, # Default to enabled + perspective_count=len(module_perspectives) + ) + ) + + # Sort modules by name + modules.sort(key=lambda m: m.name) + + return modules + + +def get_perspectives_by_module(module_name: str) -> List[PerspectiveInfo]: + """ + Get a list of perspectives that belong to a specific module. + + Args: + module_name: Name of the module to filter by + + Returns: + List of perspective information in the specified module + + Raises: + HTTPException: If the module is not found + """ + perspectives = get_available_perspectives() + + # Filter perspectives by module name + module_perspectives = [p for p in perspectives if p.module == module_name] + + # If no perspectives were found for this module, the module might not exist + if not module_perspectives: + # Check if the module exists + all_modules = get_available_modules() + if not any(m.name == module_name for m in all_modules): + raise HTTPException(status_code=404, detail=f"Module '{module_name}' not found") + + # Sort perspectives by priority, then name + module_perspectives.sort(key=lambda p: (p.priority, p.name)) + + return module_perspectives + + async def generate_caption( perspective_name: str, image_path: Path, From 424a90bfd06bc78f3f4e7cf81e286c3502db65cf Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 00:11:13 +0000 Subject: [PATCH 08/24] Update client to use module api Signed-off-by: jphillips --- .../components/PerspectiveManagementPanel.tsx | 14 +- .../PerspectiveModules/ModuleInfo.tsx | 7 +- .../PerspectiveModules/ModuleList.tsx | 2 +- .../features/perspectives/constants/index.ts | 7 + .../src/features/perspectives/hooks/index.ts | 6 +- .../hooks/useModulePerspectives.ts | 129 ++++++++++++++++ .../features/perspectives/hooks/useModules.ts | 122 +++++++++++++++ .../hooks/usePerspectiveModules.ts | 117 +++++++++++++-- .../src/features/perspectives/services/api.ts | 141 +++++++++++++++++- .../perspectives/services/constants.ts | 29 ++++ .../features/perspectives/services/utils.ts | 63 ++++++-- .../types/perspectiveModuleTypes.ts | 93 ++++++------ .../perspectives/types/perspectivesTypes.ts | 4 +- .../perspectives/module/$moduleName.tsx | 65 +++++++- .../perspective/$perspectiveName.tsx | 29 +++- 15 files changed, 723 insertions(+), 105 deletions(-) create mode 100644 graphcap_studio/src/features/perspectives/hooks/useModulePerspectives.ts create mode 100644 graphcap_studio/src/features/perspectives/hooks/useModules.ts diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx index 0eddbda3..b12b9c1f 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx @@ -17,7 +17,7 @@ import { PerspectiveFilterPanel } from "./PerspectiveFilterPanel"; */ export function PerspectiveManagementPanel() { // Use the perspective modules hook to get real data - const { modules, isLoading, error } = usePerspectiveModules(); + const { modules, isLoading, error, hasModules } = usePerspectiveModules(); // Handle loading state if (isLoading) { @@ -58,22 +58,22 @@ export function PerspectiveManagementPanel() { Perspective Modules - {modules.length === 0 ? ( + {!hasModules ? ( No perspectives found. ) : ( {modules.map((module) => ( - + - {module.name} + {module.display_name} - {module.perspectives.map((perspective) => { + {module.perspectives && module.perspectives.map((perspective) => { // Extract perspective ID from the full name const perspectiveId = perspective.name.includes("/") ? perspective.name.split("/").pop() || perspective.name @@ -84,7 +84,7 @@ export function PerspectiveManagementPanel() { - {module.name} + {module.display_name} {module.enabled ? "Enabled" : "Disabled"} @@ -37,6 +37,11 @@ export function ModuleInfo({ module }: ModuleInfoProps) { This module contains {module.perspectives.length}{" "} perspectives. + {module.description && ( + + {module.description} + + )} ); diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx index a2e024c8..35270b3a 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx @@ -47,7 +47,7 @@ export function ModuleList({ module }: ModuleListProps) { + ["perspectives", "modules", moduleName] as const, caption: (imagePath: string, perspective: string) => [ ...perspectivesQueryKeys.perspectives, @@ -55,11 +58,15 @@ export const API_ENDPOINTS = { VIEW_IMAGE: "/images/view", REST_LIST_PERSPECTIVES: "/perspectives/list", REST_GENERATE_CAPTION: "/perspectives/caption-from-path", + // Module API endpoints + LIST_MODULES: "/perspectives/modules", + MODULE_PERSPECTIVES: "/perspectives/modules/{module_name}", }; // Cache stale times (in milliseconds) export const CACHE_TIMES = { PERSPECTIVES_STALE_TIME: 1000 * 60 * 5, // 5 minutes + MODULES_STALE_TIME: 1000 * 60 * 5, // 5 minutes }; // Default values diff --git a/graphcap_studio/src/features/perspectives/hooks/index.ts b/graphcap_studio/src/features/perspectives/hooks/index.ts index f84eae00..fc230ddf 100644 --- a/graphcap_studio/src/features/perspectives/hooks/index.ts +++ b/graphcap_studio/src/features/perspectives/hooks/index.ts @@ -2,7 +2,7 @@ /** * Perspectives Hooks * - * This module exports hooks for the perspectives components. + * This module exports all hooks used by the perspectives feature. */ // UI Hooks @@ -10,9 +10,11 @@ export { usePerspectiveUI } from "./usePerspectiveUI"; // API Hooks export { usePerspectives } from "./usePerspectives"; +export { usePerspectiveModules } from "./usePerspectiveModules"; export { useGeneratePerspectiveCaption } from "./useGeneratePerspectiveCaption"; export { useImagePerspectives } from "./useImagePerspectives"; -export { usePerspectiveModules } from "./usePerspectiveModules"; +export { useModules } from "./useModules"; +export { useModulePerspectives } from "./useModulePerspectives"; // Utilities export * from "./utils"; diff --git a/graphcap_studio/src/features/perspectives/hooks/useModulePerspectives.ts b/graphcap_studio/src/features/perspectives/hooks/useModulePerspectives.ts new file mode 100644 index 00000000..39da062b --- /dev/null +++ b/graphcap_studio/src/features/perspectives/hooks/useModulePerspectives.ts @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: Apache-2.0 +/** + * useModulePerspectives Hook + * + * This hook fetches perspectives for a specific module from the server. + */ + +import { useServerConnectionsContext } from "@/context"; +import { SERVER_IDS } from "@/features/server-connections/constants"; +import { ServerConnection } from "@/features/server-connections/types"; +import { useQuery } from "@tanstack/react-query"; +import { useEffect } from "react"; +import { + API_ENDPOINTS, + CACHE_TIMES, + perspectivesQueryKeys, +} from "../services/constants"; +import { getGraphCapServerUrl, handleApiError } from "../services/utils"; +import { ModulePerspectivesResponse, Perspective } from "../types"; +import { PerspectiveError } from "./usePerspectives"; + +/** + * Hook to fetch perspectives for a specific module from the server + * + * @param moduleName - Name of the module to fetch perspectives for + * @returns A query result with the module and its perspectives + */ +export function useModulePerspectives(moduleName: string) { + const { connections } = useServerConnectionsContext(); + const graphcapServerConnection = connections.find( + (conn: ServerConnection) => conn.id === SERVER_IDS.GRAPHCAP_SERVER, + ); + const isConnected = graphcapServerConnection?.status === "connected"; + + const query = useQuery<{ module: ModulePerspectivesResponse['module'], perspectives: Perspective[] }, Error>({ + queryKey: perspectivesQueryKeys.modulePerspectives(moduleName), + queryFn: async () => { + try { + // Handle case when server connection is not established + if (!isConnected) { + console.warn("Server connection not established"); + throw new PerspectiveError("Server connection not established", { + code: "SERVER_CONNECTION_ERROR", + context: { connections }, + }); + } + + const baseUrl = getGraphCapServerUrl(connections); + if (!baseUrl) { + console.warn("No GraphCap server URL available"); + throw new PerspectiveError("No GraphCap server URL available", { + code: "MISSING_SERVER_URL", + context: { connections }, + }); + } + + const endpoint = API_ENDPOINTS.MODULE_PERSPECTIVES.replace( + "{module_name}", + moduleName + ); + const url = `${baseUrl}${endpoint}`; + + console.debug(`Fetching perspectives for module '${moduleName}' from server: ${url}`); + + const response = await fetch(url); + + if (!response.ok) { + return handleApiError(response, `Failed to fetch perspectives for module '${moduleName}'`); + } + + const data = (await response.json()) as ModulePerspectivesResponse; + + console.debug( + `Successfully fetched ${data.perspectives.length} perspectives for module '${moduleName}'`, + ); + + return { + module: data.module, + perspectives: data.perspectives + }; + } catch (error) { + // Improve error handling - log the error and rethrow + console.error(`Error fetching perspectives for module '${moduleName}':`, error); + + // If it's already a PerspectiveError, just rethrow it + if (error instanceof PerspectiveError) { + throw error; + } + + // Otherwise, wrap it in a PerspectiveError + throw new PerspectiveError( + error instanceof Error + ? error.message + : `Unknown error fetching perspectives for module '${moduleName}'`, + { + code: "MODULE_PERSPECTIVES_FETCH_ERROR", + context: { error, moduleName }, + }, + ); + } + }, + // Only enable the query when the server is connected and a module name is provided + enabled: isConnected && !!moduleName, + staleTime: CACHE_TIMES.PERSPECTIVES, + retry: (failureCount, error) => { + // Don't retry for connection errors or missing URLs + if (error instanceof PerspectiveError) { + if ( + ["SERVER_CONNECTION_ERROR", "MISSING_SERVER_URL"].includes(error.code) + ) { + return false; + } + } + + // Retry other errors up to 3 times + return failureCount < 3; + }, + retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 30000), + }); + + // Watch for changes in connection status and refetch when connected + useEffect(() => { + if (isConnected && query.isError && moduleName) { + query.refetch(); + } + }, [isConnected, moduleName, query]); + + return query; +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/hooks/useModules.ts b/graphcap_studio/src/features/perspectives/hooks/useModules.ts new file mode 100644 index 00000000..ae29755f --- /dev/null +++ b/graphcap_studio/src/features/perspectives/hooks/useModules.ts @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: Apache-2.0 +/** + * useModules Hook + * + * This hook fetches available perspective modules from the server. + */ + +import { useServerConnectionsContext } from "@/context"; +import { SERVER_IDS } from "@/features/server-connections/constants"; +import { ServerConnection } from "@/features/server-connections/types"; +import { useQuery } from "@tanstack/react-query"; +import { useEffect } from "react"; +import { + API_ENDPOINTS, + CACHE_TIMES, + perspectivesQueryKeys, +} from "../services/constants"; +import { getGraphCapServerUrl, handleApiError } from "../services/utils"; +import { ModuleInfo, ModuleListResponse } from "../types"; +import { PerspectiveError } from "./usePerspectives"; + +/** + * Hook to fetch available perspective modules from the server + * + * @returns A query result with modules data + */ +export function useModules() { + const { connections } = useServerConnectionsContext(); + const graphcapServerConnection = connections.find( + (conn: ServerConnection) => conn.id === SERVER_IDS.GRAPHCAP_SERVER, + ); + const isConnected = graphcapServerConnection?.status === "connected"; + + const query = useQuery({ + queryKey: perspectivesQueryKeys.modules, + queryFn: async () => { + try { + // Handle case when server connection is not established + if (!isConnected) { + console.warn("Server connection not established"); + throw new PerspectiveError("Server connection not established", { + code: "SERVER_CONNECTION_ERROR", + context: { connections }, + }); + } + + const baseUrl = getGraphCapServerUrl(connections); + if (!baseUrl) { + console.warn("No GraphCap server URL available"); + throw new PerspectiveError("No GraphCap server URL available", { + code: "MISSING_SERVER_URL", + context: { connections }, + }); + } + + const endpoint = API_ENDPOINTS.LIST_MODULES; + const url = `${baseUrl}${endpoint}`; + + console.debug(`Fetching modules from server: ${url}`); + + const response = await fetch(url); + + if (!response.ok) { + return handleApiError(response, "Failed to fetch modules"); + } + + const data = (await response.json()) as ModuleListResponse; + + console.debug( + `Successfully fetched ${data.modules.length} modules`, + ); + + return data.modules; + } catch (error) { + // Improve error handling - log the error and rethrow + console.error("Error fetching modules:", error); + + // If it's already a PerspectiveError, just rethrow it + if (error instanceof PerspectiveError) { + throw error; + } + + // Otherwise, wrap it in a PerspectiveError + throw new PerspectiveError( + error instanceof Error + ? error.message + : "Unknown error fetching modules", + { + code: "MODULE_FETCH_ERROR", + context: { error }, + }, + ); + } + }, + // Only enable the query when the server is connected + enabled: isConnected, + staleTime: CACHE_TIMES.MODULES, + retry: (failureCount, error) => { + // Don't retry for connection errors or missing URLs + if (error instanceof PerspectiveError) { + if ( + ["SERVER_CONNECTION_ERROR", "MISSING_SERVER_URL"].includes(error.code) + ) { + return false; + } + } + + // Retry other errors up to 3 times + return failureCount < 3; + }, + retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 30000), + }); + + // Watch for changes in connection status and refetch when connected + useEffect(() => { + if (isConnected && query.isError) { + query.refetch(); + } + }, [isConnected, query]); + + return query; +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/hooks/usePerspectiveModules.ts b/graphcap_studio/src/features/perspectives/hooks/usePerspectiveModules.ts index 857c2a1c..2af8ac76 100644 --- a/graphcap_studio/src/features/perspectives/hooks/usePerspectiveModules.ts +++ b/graphcap_studio/src/features/perspectives/hooks/usePerspectiveModules.ts @@ -2,30 +2,115 @@ /** * usePerspectiveModules Hook * - * This hook fetches available perspectives and groups them by module. + * This hook fetches available perspective modules and their perspectives from the server. */ -import { useMemo } from "react"; -import { PerspectiveModule, groupPerspectivesByModule } from "../types"; -import { usePerspectives } from "./usePerspectives"; +import { useQuery } from "@tanstack/react-query"; +import { useServerConnectionsContext } from "@/context"; +import { SERVER_IDS } from "@/features/server-connections/constants"; +import { perspectivesQueryKeys } from "../services/constants"; +import { PerspectiveModule } from "../types"; +import { useModules } from "./useModules"; /** - * Hook to fetch perspectives and organize them into modules + * Hook to fetch modules and their perspectives + * + * This hook now uses the dedicated module API endpoints instead of + * client-side grouping of perspectives. + * + * @returns Query result with a list of modules and their perspectives */ export function usePerspectiveModules() { - // Fetch perspectives using the existing hook - const perspectivesQuery = usePerspectives(); + const { connections } = useServerConnectionsContext(); + const graphcapServerConnection = connections.find( + (conn) => conn.id === SERVER_IDS.GRAPHCAP_SERVER + ); + const isConnected = graphcapServerConnection?.status === "connected"; - // Group perspectives by module - const modules = useMemo(() => { - if (perspectivesQuery.data) { - return groupPerspectivesByModule(perspectivesQuery.data); - } - return []; - }, [perspectivesQuery.data]); + // First, fetch all available modules + const modulesQuery = useModules(); + + // Then fetch all module details in a single query + const modulesWithPerspectivesQuery = useQuery({ + // Use a different query key to avoid conflicts with useModules + queryKey: [...perspectivesQueryKeys.modules, 'with-perspectives'], + queryFn: async () => { + // If we don't have modules data yet, return empty array + if (!modulesQuery.data || modulesQuery.data.length === 0) { + return []; + } + + try { + // We need to fetch perspectives for each module + const modulePromises = modulesQuery.data.map(async (moduleInfo) => { + // Import the API here to avoid circular dependencies + const { perspectivesApi } = await import("../services/api"); + + try { + // Fetch perspectives for this module + const moduleData = await perspectivesApi.getModulePerspectives(moduleInfo.name); + + // Convert to our internal PerspectiveModule format + return { + name: moduleData.module.name, + display_name: moduleData.module.display_name, + description: moduleData.module.description, + enabled: moduleData.module.enabled, + perspectives: moduleData.perspectives + }; + } catch (error) { + console.error(`Error fetching perspectives for module ${moduleInfo.name}:`, error); + // Return a module with empty perspectives array on error + return { + name: moduleInfo.name, + display_name: moduleInfo.display_name, + description: moduleInfo.description || "", + enabled: moduleInfo.enabled, + perspectives: [] + }; + } + }); + + // Wait for all module promises to resolve + const modules = await Promise.all(modulePromises); + return modules; + } catch (error) { + console.error("Error fetching module perspectives:", error); + + // Return basic module data without perspectives instead of throwing + if (modulesQuery.data) { + return modulesQuery.data.map((moduleInfo) => ({ + name: moduleInfo.name, + display_name: moduleInfo.display_name, + description: moduleInfo.description || "", + enabled: moduleInfo.enabled, + perspectives: [] + })); + } + + throw error; + } + }, + // Only run this query when we have modules data and we're connected + enabled: isConnected && !modulesQuery.isLoading && !!modulesQuery.data, + // Use the previous data as placeholder while fetching new data + placeholderData: (prev) => prev || [] + }); + + // Always return a valid array of modules, even during loading + const modules = modulesWithPerspectivesQuery.data || []; return { - ...perspectivesQuery, - modules, + isLoading: modulesQuery.isLoading || modulesWithPerspectivesQuery.isLoading, + isError: modulesQuery.isError || modulesWithPerspectivesQuery.isError, + error: modulesQuery.error || modulesWithPerspectivesQuery.error, + data: modules, + modules: modules, + // Add a hasModules flag to easily check if we have modules + hasModules: modules.length > 0, + refetch: () => { + modulesQuery.refetch(); + modulesWithPerspectivesQuery.refetch(); + } }; } \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/services/api.ts b/graphcap_studio/src/features/perspectives/services/api.ts index cdd51088..d01671ad 100644 --- a/graphcap_studio/src/features/perspectives/services/api.ts +++ b/graphcap_studio/src/features/perspectives/services/api.ts @@ -11,10 +11,33 @@ import { CaptionRequestSchema, CaptionResponse, CaptionResponseSchema, + ModuleListResponse, + ModuleListResponseSchema, + ModulePerspectivesResponse, + ModulePerspectivesResponseSchema, Perspective, PerspectiveListResponseSchema, } from "../types"; -import { ensureWorkspacePath, handleApiError } from "./utils"; +import { ensureWorkspacePath, getGraphCapServerUrl, handleApiError } from "./utils"; + +/** + * Get server connections from local storage + */ +const getConnections = () => { + // Get the current connections from local storage + const connectionsStr = localStorage.getItem("graphcap-server-connections"); + let connections = []; + + if (connectionsStr) { + try { + connections = JSON.parse(connectionsStr); + } catch (e) { + console.warn("Could not parse server connections from localStorage"); + } + } + + return connections; +}; /** * Service for interacting with the perspectives API @@ -30,7 +53,16 @@ export const perspectivesApi = { */ async listPerspectives(): Promise { try { - const response = await fetch(API_ENDPOINTS.REST_LIST_PERSPECTIVES); + // Get the base URL using the utility function + const connections = getConnections(); + const baseUrl = getGraphCapServerUrl(connections); + + // Create the full URL by combining base URL and endpoint path + const url = `${baseUrl}${API_ENDPOINTS.LIST_PERSPECTIVES}`; + + console.debug(`Fetching perspectives from: ${url}`); + + const response = await fetch(url); if (!response.ok) { await handleApiError(response, "Failed to fetch perspectives"); @@ -42,7 +74,100 @@ export const perspectivesApi = { return validatedData.perspectives; } catch (error) { console.error("Error in perspectivesApi.listPerspectives:", error); - return []; + throw error; + } + }, + + /** + * Get a list of available perspective modules + * + * @returns Promise with the list of modules + */ + async listModules(): Promise { + try { + // Get the base URL using the utility function + const connections = getConnections(); + const baseUrl = getGraphCapServerUrl(connections); + + // Create the full URL by combining base URL and endpoint path + const url = `${baseUrl}${API_ENDPOINTS.LIST_MODULES}`; + + console.debug(`Fetching modules from: ${url}`); + + const response = await fetch(url); + + if (!response.ok) { + await handleApiError(response, "Failed to fetch perspective modules"); + } + + const data = await response.json(); + // Validate the response with Zod + const validatedData = ModuleListResponseSchema.parse(data); + return validatedData; + } catch (error) { + console.error("Error in perspectivesApi.listModules:", error); + throw error; + } + }, + + /** + * Get all perspectives for a specific module + * + * @param moduleName - Name of the module to get perspectives for + * @returns Promise with the module and its perspectives + */ + async getModulePerspectives(moduleName: string): Promise { + try { + // Get the base URL using the utility function + const connections = getConnections(); + const baseUrl = getGraphCapServerUrl(connections); + + // Create the endpoint path + const endpointPath = API_ENDPOINTS.MODULE_PERSPECTIVES.replace( + "{module_name}", + encodeURIComponent(moduleName) + ); + + // Create the full URL by combining base URL and endpoint path + const url = `${baseUrl}${endpointPath}`; + + console.debug(`Fetching perspectives for module '${moduleName}' from: ${url}`); + + const response = await fetch(url); + + if (!response.ok) { + // Check if we got HTML instead of JSON + const contentType = response.headers.get("content-type"); + if (contentType && contentType.includes("text/html")) { + throw new Error(`Received HTML response instead of JSON. Status: ${response.status}. This typically indicates a routing issue or server error.`); + } + + await handleApiError(response, `Failed to fetch perspectives for module '${moduleName}'`); + } + + // Check content type before parsing + const contentType = response.headers.get("content-type"); + if (!contentType || !contentType.includes("application/json")) { + console.error(`Unexpected content type: ${contentType}`); + throw new Error(`Expected JSON response but got ${contentType || "unknown content type"}`); + } + + const data = await response.json(); + + // Validate the response with Zod + try { + const validatedData = ModulePerspectivesResponseSchema.parse(data); + return validatedData; + } catch (validationError: unknown) { + console.error("Response validation error:", validationError); + const errorMessage = validationError instanceof Error + ? validationError.message + : "Unknown validation error"; + throw new Error(`Invalid response format: ${errorMessage}`); + } + } catch (error) { + console.error(`Error in perspectivesApi.getModulePerspectives(${moduleName}):`, error); + throw error; } }, @@ -56,10 +181,15 @@ export const perspectivesApi = { requestParams: CaptionRequest, ): Promise { try { + // Get the base URL using the utility function + const connections = getConnections(); + const baseUrl = getGraphCapServerUrl(connections); + // Ensure the image path has the correct workspace prefix const normalizedImagePath = ensureWorkspacePath(requestParams.image_path); console.log("Generating caption for image path:", normalizedImagePath); console.log("Request params:", requestParams); + // Create the request body and validate with Zod const request: CaptionRequest = { ...requestParams, @@ -68,9 +198,12 @@ export const perspectivesApi = { // Validate the request with Zod const validatedRequest = CaptionRequestSchema.parse(request); + + // Create the full URL by combining base URL and endpoint path + const url = `${baseUrl}${API_ENDPOINTS.REST_GENERATE_CAPTION}`; // Make the API request - const response = await fetch(API_ENDPOINTS.REST_GENERATE_CAPTION, { + const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", diff --git a/graphcap_studio/src/features/perspectives/services/constants.ts b/graphcap_studio/src/features/perspectives/services/constants.ts index a66261bf..ff1a850a 100644 --- a/graphcap_studio/src/features/perspectives/services/constants.ts +++ b/graphcap_studio/src/features/perspectives/services/constants.ts @@ -18,6 +18,17 @@ export const API_ENDPOINTS = { * Endpoint to generate a caption for an image using a perspective */ REST_GENERATE_CAPTION: "/perspectives/caption-from-path", + + /** + * Endpoint to list all available perspective modules + */ + LIST_MODULES: "/perspectives/modules", + + /** + * Endpoint to get perspectives for a specific module + * Note: This is a template that needs to be interpolated with the module name + */ + MODULE_PERSPECTIVES: "/perspectives/modules/{module_name}", }; /** @@ -28,6 +39,11 @@ export const CACHE_TIMES = { * Stale time for perspectives data (5 minutes) */ PERSPECTIVES: 5 * 60 * 1000, // 5 minutes + + /** + * Stale time for modules data (5 minutes) + */ + MODULES: 5 * 60 * 1000, // 5 minutes }; /** @@ -54,6 +70,19 @@ export const perspectivesQueryKeys = { */ perspectives: ["perspectives"], + /** + * Query key for fetching all modules + */ + modules: ["perspectives", "modules"], + + /** + * Query key for fetching perspectives in a specific module + * + * @param moduleName - Name of the module + * @returns Query key array + */ + modulePerspectives: (moduleName: string) => ["perspectives", "modules", moduleName], + /** * Query key for fetching a caption for an image using a perspective * diff --git a/graphcap_studio/src/features/perspectives/services/utils.ts b/graphcap_studio/src/features/perspectives/services/utils.ts index 9a08f2ea..46884f4d 100644 --- a/graphcap_studio/src/features/perspectives/services/utils.ts +++ b/graphcap_studio/src/features/perspectives/services/utils.ts @@ -17,11 +17,16 @@ export function getGraphCapServerUrl(connections: ServerConnection[]): string { (conn) => conn.id === SERVER_IDS.GRAPHCAP_SERVER, ); - return ( - graphcapServerConnection?.url ?? - import.meta.env.VITE_GRAPHCAP_SERVER_URL ?? - DEFAULTS.SERVER_URL - ); + // Get URL from connection, environment variable, or default + const serverUrl = graphcapServerConnection?.url || + import.meta.env.VITE_GRAPHCAP_SERVER_URL || + import.meta.env.VITE_API_URL || + DEFAULTS.SERVER_URL; + + // Log the server URL being used for debugging + console.debug(`Using GraphCap server URL: ${serverUrl}`); + + return serverUrl; } /** @@ -60,11 +65,14 @@ export async function handleApiError( defaultMessage: string, ): Promise { let errorMessage = `${defaultMessage}: ${response.status}`; + let errorDetails = null; try { - const contentType = response.headers.get("content-type"); + const contentType = response.headers.get("content-type") || ""; - if (contentType && contentType.includes("application/json")) { + // Handle different content types appropriately + if (contentType.includes("application/json")) { + // JSON response - parse and extract error details const errorData = await response.json(); // FastAPI error format @@ -79,24 +87,53 @@ export async function handleApiError( } else { errorMessage = JSON.stringify(errorData.detail); } + errorDetails = errorData; } else if (errorData.message) { errorMessage = errorData.message; + errorDetails = errorData; } else { errorMessage = JSON.stringify(errorData); + errorDetails = errorData; } + } else if (contentType.includes("text/html")) { + // HTML response - likely a server error page or redirect + const textError = await response.text(); + // Extract just a small portion to avoid huge error messages + const excerpt = textError.substring(0, 200) + (textError.length > 200 ? "..." : ""); + errorMessage = `${defaultMessage}: Received HTML response (Status: ${response.status})`; + errorDetails = { htmlExcerpt: excerpt }; + console.warn("Received HTML response instead of expected JSON:", excerpt); } else { - // Try to get text response + // Other content type - try to get text const textError = await response.text(); if (textError) { - errorMessage = textError; + errorMessage = textError.substring(0, 500); // Limit size + errorDetails = { text: textError }; } } } catch (e) { - // If we can't parse the error as JSON, use the status text + // If we can't parse the error, use the status text console.error("Error parsing API error response", e); - errorMessage = `${defaultMessage}: ${response.statusText}`; + errorMessage = `${defaultMessage}: ${response.statusText} (Status: ${response.status})`; + errorDetails = { parseError: e instanceof Error ? e.message : "Unknown error" }; } - console.error(`API Error: ${errorMessage}`); - throw new Error(errorMessage); + // Create a more informative error + console.error(`API Error: ${errorMessage}`, { + status: response.status, + url: response.url, + details: errorDetails + }); + + // Create an error with additional properties + const error = new Error(errorMessage) as Error & { + status?: number; + details?: any; + url?: string; + }; + error.status = response.status; + error.details = errorDetails; + error.url = response.url; + + throw error; } diff --git a/graphcap_studio/src/features/perspectives/types/perspectiveModuleTypes.ts b/graphcap_studio/src/features/perspectives/types/perspectiveModuleTypes.ts index 4e15c32a..3084b7ab 100644 --- a/graphcap_studio/src/features/perspectives/types/perspectiveModuleTypes.ts +++ b/graphcap_studio/src/features/perspectives/types/perspectiveModuleTypes.ts @@ -5,14 +5,58 @@ * This module defines types related to perspective modules and management. */ +import { z } from "zod"; +import { PerspectiveSchema } from "./perspectivesTypes"; import type { Perspective } from "./perspectivesTypes"; +/** + * Schema for module information + */ +export const ModuleInfoSchema = z.object({ + name: z.string(), + display_name: z.string(), + description: z.string(), + enabled: z.boolean(), + perspective_count: z.number() +}); + +/** + * Schema for module list response + */ +export const ModuleListResponseSchema = z.object({ + modules: z.array(ModuleInfoSchema) +}); + +/** + * Schema for module perspectives response + */ +export const ModulePerspectivesResponseSchema = z.object({ + module: ModuleInfoSchema, + perspectives: z.array(PerspectiveSchema) +}); + +/** + * Type representing module information + */ +export type ModuleInfo = z.infer; + +/** + * Type representing a module list response + */ +export type ModuleListResponse = z.infer; + +/** + * Type representing a module perspectives response + */ +export type ModulePerspectivesResponse = z.infer; + /** * Represents a module containing multiple perspectives */ export interface PerspectiveModule { - id: string; name: string; + display_name: string; + description: string; enabled: boolean; perspectives: Perspective[]; } @@ -23,50 +67,3 @@ export interface PerspectiveModule { export interface PerspectiveModuleList { modules: PerspectiveModule[]; } - -/** - * Groups perspectives by module - * @param perspectives Array of all perspectives - * @returns Map of modules with their perspectives - */ -export function groupPerspectivesByModule( - perspectives: Perspective[], -): PerspectiveModule[] { - // Initialize with default modules - const moduleMap = new Map(); - - // Add core module as default - moduleMap.set("core", { - id: "core", - name: "Core", - enabled: true, - perspectives: [], - }); - - // Group perspectives by module - perspectives.forEach((perspective) => { - // Extract module from perspective name or use "core" as default - // The module can be detected by checking for "/" in the perspective name - const moduleId = perspective.name.includes("/") - ? perspective.name.split("/")[0] - : "core"; - - const moduleName = moduleId.charAt(0).toUpperCase() + moduleId.slice(1); - - // Create module if it doesn't exist - if (!moduleMap.has(moduleId)) { - moduleMap.set(moduleId, { - id: moduleId, - name: moduleName, - enabled: true, - perspectives: [], - }); - } - - // Add perspective to module - moduleMap.get(moduleId)?.perspectives.push(perspective); - }); - - // Convert map to array - return Array.from(moduleMap.values()); -} diff --git a/graphcap_studio/src/features/perspectives/types/perspectivesTypes.ts b/graphcap_studio/src/features/perspectives/types/perspectivesTypes.ts index 622745f5..397bd09d 100644 --- a/graphcap_studio/src/features/perspectives/types/perspectivesTypes.ts +++ b/graphcap_studio/src/features/perspectives/types/perspectivesTypes.ts @@ -30,14 +30,14 @@ export const SchemaFieldSchema: z.ZodType<{ description: string; is_list?: boolean; is_complex?: boolean; - }>; + }> | null; }> = z.object({ name: z.string(), type: z.enum(["str", "float"]), description: z.string(), is_list: z.boolean().optional(), is_complex: z.boolean().optional(), - fields: z.array(z.lazy(() => SchemaFieldSchema)).optional(), + fields: z.nullable(z.array(z.lazy(() => SchemaFieldSchema))).optional(), }); /** diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx index e3e3723f..0a4606e8 100644 --- a/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx @@ -3,6 +3,7 @@ import { usePerspectiveModules } from "@/features/perspectives/hooks"; import type { PerspectiveModule } from "@/features/perspectives/types"; import { Box, + Button, Flex, Heading, } from "@chakra-ui/react"; @@ -15,15 +16,27 @@ export const Route = createFileRoute("/perspectives/module/$moduleName")({ function ModulePage() { const { moduleName } = Route.useParams(); - const { modules, isLoading, error } = usePerspectiveModules(); + const { modules, isLoading, error, refetch } = usePerspectiveModules(); const [selectedModule, setSelectedModule] = useState(null); + const [errorDetails, setErrorDetails] = useState(null); // Find the selected module when data is loaded useEffect(() => { if (modules && modules.length > 0) { - const module = modules.find((m) => m.id === moduleName); + const module = modules.find((m) => m.name === moduleName); setSelectedModule(module || null); + + // If module exists but has no perspectives, check if it might be an API error + if (module && module.perspectives.length === 0) { + // Look for HTML response errors in the console logs + console.debug(`Module ${moduleName} has 0 perspectives. This might indicate an API error.`); + setErrorDetails( + "No perspectives found for this module. This could be due to a server configuration issue." + ); + } else { + setErrorDetails(null); + } } }, [modules, moduleName]); @@ -34,7 +47,29 @@ function ModulePage() { // Handle error state if (error) { - return ; + return ( + + + Error Loading Module + + {error.message} + + + ); } // Handle case when module is not found @@ -47,6 +82,30 @@ function ModulePage() { {/* Module information at the top */} + + {/* Show warning if we have a module with no perspectives */} + {errorDetails && ( + + {errorDetails} + + + )} {/* Main content area with list and outlet */} diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx index 02382499..6a87fdcb 100644 --- a/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx @@ -1,6 +1,6 @@ import { useColorModeValue } from "@/components/ui/theme/color-mode"; import { ErrorDisplay, LoadingDisplay, NotFound, PerspectiveDetail } from "@/features/perspectives/components/PerspectiveModules"; -import { usePerspectives } from "@/features/perspectives/hooks"; +import { useModulePerspectives } from "@/features/perspectives/hooks"; import { Box, } from "@chakra-ui/react"; @@ -13,30 +13,38 @@ export const Route = createFileRoute("/perspectives/module/$moduleName/perspecti function PerspectiveDetailPage() { const { moduleName, perspectiveName } = Route.useParams(); - const { data: perspectives, isLoading, error } = usePerspectives(); + const { data, isLoading, error } = useModulePerspectives(moduleName); // Color mode values const bgColor = useColorModeValue("white", "gray.800"); // Find the specific perspective const perspective = useMemo(() => { - if (!perspectives) return null; + if (!data || !data.perspectives) return null; - // First try direct match - let foundPerspective = perspectives.find(p => p.name === perspectiveName); + // First try direct match on the perspective name + let foundPerspective = data.perspectives.find(p => p.name === perspectiveName); // If not found, try to match with module prefix if (!foundPerspective) { const fullName = `${moduleName}/${perspectiveName}`; - foundPerspective = perspectives.find(p => p.name === fullName); + foundPerspective = data.perspectives.find(p => p.name === fullName); + } + + // Also try matching just the last part of the name (for module-prefixed perspectives) + if (!foundPerspective) { + foundPerspective = data.perspectives.find(p => { + const parts = p.name.split('/'); + return parts[parts.length - 1] === perspectiveName; + }); } return foundPerspective; - }, [perspectives, perspectiveName, moduleName]); + }, [data, perspectiveName, moduleName]); // Handle loading state if (isLoading) { - return ; + return ; } // Handle error state @@ -44,6 +52,11 @@ function PerspectiveDetailPage() { return ; } + // Handle case when module data is missing + if (!data) { + return ; + } + // Handle case when perspective is not found if (!perspective) { return ; From 5918b2365a6f099547044cbb364efde2909ee8c3 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 02:06:15 +0000 Subject: [PATCH 09/24] Perspective Module UI checkpoint Signed-off-by: jphillips --- .../components/PerspectiveFilterPanel.tsx | 2 +- .../src/features/perspectives/services/api.ts | 15 +- .../perspectives/types/perspectivesTypes.ts | 15 +- .../perspectives/module/$moduleName.tsx | 186 ++++++++++++++---- .../graphcap/perspectives/models.py | 6 +- .../server/features/perspectives/models.py | 4 +- .../perspective_library/poetic_metaphor.json | 2 +- workspace/perspective_library/time_tags.json | 2 +- 8 files changed, 174 insertions(+), 58 deletions(-) diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx index 1277abe8..e83b6be8 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx @@ -51,7 +51,7 @@ export function PerspectiveFilterPanel() { - + {perspectives.map((perspective) => ( | null; }> = z.object({ name: z.string(), - type: z.enum(["str", "float"]), + type: z.union([z.string(), z.object({}).passthrough()]), // Accept string or object description: z.string(), is_list: z.boolean().optional(), is_complex: z.boolean().optional(), diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx index 0a4606e8..4bb66b93 100644 --- a/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx @@ -6,20 +6,92 @@ import { Button, Flex, Heading, + Text, + Code, } from "@chakra-ui/react"; -import { Outlet, createFileRoute } from "@tanstack/react-router"; -import { useEffect, useState } from "react"; +import { SelectContent, SelectItem, SelectRoot, SelectTrigger, SelectValueText } from "@/components/ui/select"; +import { createListCollection } from "@chakra-ui/react"; +import { Outlet, createFileRoute, useNavigate, useMatches } from "@tanstack/react-router"; +import { useEffect, useState, useMemo } from "react"; export const Route = createFileRoute("/perspectives/module/$moduleName")({ component: ModulePage, }); +/** + * Component to display detailed schema validation errors + */ +function SchemaValidationError({ error }: { error: Error }) { + // Check if the error contains validation information + const isSchemaError = error.message.includes("Invalid enum value") || + error.message.includes("schema_fields") || + error.message.includes("Expected 'str' | 'float'"); + + return ( + + + Schema Validation Error + + + {isSchemaError ? ( + <> + + There was an error loading perspectives due to schema validation issues with complex fields. + The system is expecting only simple field types ('str' or 'float') but found complex nested objects. + + Possible Solutions: + + Update the server to support complex field structures (recommended) + Simplify perspective schemas to avoid nested fields + + Technical Details: + + {error.message} + + + ) : ( + {error.message} + )} + + + ); +} + function ModulePage() { const { moduleName } = Route.useParams(); const { modules, isLoading, error, refetch } = usePerspectiveModules(); const [selectedModule, setSelectedModule] = useState(null); const [errorDetails, setErrorDetails] = useState(null); + const navigate = useNavigate(); + const matches = useMatches(); + + // Check if we're currently at the module root (no perspective selected) + const isModuleRoot = useMemo(() => { + return matches.some(match => + match.routeId === '/perspectives/module/$moduleName' && + match.pathname === `/perspectives/module/${moduleName}` + ); + }, [matches, moduleName]); + + // Create collection for the select component + const modulesCollection = useMemo(() => { + if (!modules) return createListCollection({ items: [] }); + + return createListCollection({ + items: modules.map(module => ({ + label: module.display_name || module.name, + value: module.name, + module: module, + })), + }); + }, [modules]); // Find the selected module when data is loaded useEffect(() => { @@ -36,9 +108,30 @@ function ModulePage() { ); } else { setErrorDetails(null); + + // If we're at the module root and the module has perspectives, + // automatically navigate to the first perspective + if (isModuleRoot && module && module.perspectives.length > 0) { + const firstPerspective = module.perspectives[0]; + navigate({ + to: "/perspectives/module/$moduleName/perspective/$perspectiveName", + params: { + moduleName: moduleName, + perspectiveName: firstPerspective.name + } + }); + } } } - }, [modules, moduleName]); + }, [modules, moduleName, navigate, isModuleRoot]); + + // Handle module change + const handleModuleChange = (details: any) => { + const newModuleName = details.value[0]; + if (newModuleName && newModuleName !== moduleName) { + navigate({ to: "/perspectives/module/$moduleName", params: { moduleName: newModuleName } }); + } + }; // Handle loading state if (isLoading) { @@ -48,26 +141,17 @@ function ModulePage() { // Handle error state if (error) { return ( - - - Error Loading Module - - {error.message} - + + + + + ); } @@ -78,9 +162,31 @@ function ModulePage() { } return ( - - {/* Module information at the top */} - + + {/* Left sidebar with module info and perspectives list (20% width) */} + + {/* Module selector */} + + + + + + + {modulesCollection.items.map((item) => ( + + {item.label} + + ))} + + + + + {/* Module information */} {/* Show warning if we have a module with no perspectives */} @@ -95,8 +201,9 @@ function ModulePage() { color="yellow.900" display="flex" alignItems="center" + flexDirection="column" > - {errorDetails} + {errorDetails} + + + + + {/* Description Panel */} + + + Description + + + {perspective.description || "No description available for this perspective."} + + + + {/* Tabs for different sections */} + + + + Schema + Fields + Prompt + Management + + + + + + {perspective.schema ? ( + + + Schema Information + + + + Name: + {perspective.schema.name} + + + Version: + {perspective.schema.version} + + + + Context Template: + + {perspective.schema.context_template || "None"} + + + + + ) : ( + No schema information available for this perspective. + )} + + + + {perspective.schema?.schema_fields && + perspective.schema.schema_fields.length > 0 ? ( + + + Field Definitions + + + + + + + Name + + + Type + + + Description + + + List + + + Complex + + + + + {perspective.schema.schema_fields.map((field) => ( + + + {field.name} + + + {getFieldTypeDisplay(field.type)} + + + {field.description} + + + {field.is_list ? "Yes" : "No"} + + + {field.is_complex ? "Yes" : "No"} + + + ))} + + + + + ) : ( + No fields defined for this perspective. + )} + + + + + + Prompt Template + + + + {getPromptContent()} + + + + + + + + + Perspective Management + + + This section allows you to edit and manage the perspective configuration. + + + + + {perspective.schema?.table_columns && + perspective.schema.table_columns.length > 0 && ( + + + Table Columns + + + + + + Name + + + Style + + + Description + + + + + {perspective.schema.table_columns.map((column) => ( + + + {column.name} + + + {column.style} + + + {column.description || "-"} + + + ))} + + + + )} + + + + Actions + + + + + + + + + + + + + + + ); +} diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/index.ts b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/index.ts new file mode 100644 index 00000000..a6698c0f --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/index.ts @@ -0,0 +1 @@ +export { PerspectiveEditor } from './PerspectiveEditor'; \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveFilterPanel.tsx similarity index 97% rename from graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx rename to graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveFilterPanel.tsx index e83b6be8..177d6f2c 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveFilterPanel.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveFilterPanel.tsx @@ -16,7 +16,7 @@ import { VStack, } from "@chakra-ui/react"; import { useMemo } from "react"; -import { usePerspectivesData } from "../context/PerspectivesDataContext"; +import { usePerspectivesData } from "../../context/PerspectivesDataContext"; /** * Component for filtering which perspectives are visible in the UI diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx similarity index 98% rename from graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx rename to graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx index b12b9c1f..30306670 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagementPanel.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx @@ -9,7 +9,7 @@ import { LoadingSpinner } from "@/components/ui/status/LoadingSpinner"; import { Box } from "@chakra-ui/react"; import { Tabs } from "@chakra-ui/react"; import { Link } from "@tanstack/react-router"; -import { usePerspectiveModules } from "../hooks"; +import { usePerspectiveModules } from "../../hooks"; import { PerspectiveFilterPanel } from "./PerspectiveFilterPanel"; /** diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleInfo.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModules/ModuleInfo.tsx similarity index 100% rename from graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleInfo.tsx rename to graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModules/ModuleInfo.tsx diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModules/ModuleList.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModules/ModuleList.tsx new file mode 100644 index 00000000..4246b609 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModules/ModuleList.tsx @@ -0,0 +1,80 @@ +import type { Perspective, PerspectiveModule } from "@/features/perspectives/types"; +import { + Badge, + Box, + Flex, + Heading, + Text, + VStack, +} from "@chakra-ui/react"; +import { Link } from "@tanstack/react-router"; + +interface ModuleListProps { + readonly module: PerspectiveModule; +} + +/** + * ModuleList component displays a list of perspectives from a specific module + */ +export function ModuleList({ module }: ModuleListProps) { + if (module.perspectives.length === 0) { + return No perspectives found in this module.; + } + + return ( + + {module.perspectives.map((perspective: Perspective) => ( + + + + + {perspective.display_name || perspective.name} + + + {perspective.version} + + + + {perspective.description?.substring(0, 60) ?? "No description available"}... + + + + ))} + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModules/index.ts b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModules/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/SchemaValidationError.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/SchemaValidationError.tsx new file mode 100644 index 00000000..41e7123f --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/SchemaValidationError.tsx @@ -0,0 +1,56 @@ +import { + Box, + Code, + Flex, + Heading, + Text +} from "@chakra-ui/react"; + +interface SchemaValidationErrorProps { + error: Error; +} + +/** + * Component to display detailed schema validation errors + */ +export function SchemaValidationError({ error }: SchemaValidationErrorProps) { + // Check if the error contains validation information + const isSchemaError = error.message.includes("Invalid enum value") || + error.message.includes("schema_fields") || + error.message.includes("Expected 'str' | 'float'"); + + return ( + + + Schema Validation Error + + + {isSchemaError ? ( + <> + + There was an error loading perspectives due to schema validation issues with complex fields. + The system is expecting only simple field types ('str' or 'float') but found complex nested objects. + + Possible Solutions: + + Update the server to support complex field structures (recommended) + Simplify perspective schemas to avoid nested fields + + Technical Details: + + {error.message} + + + ) : ( + {error.message} + )} + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/index.ts b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/index.ts new file mode 100644 index 00000000..0bbe6f9d --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/index.ts @@ -0,0 +1,7 @@ +export { ModuleList } from './PerspectiveModules/ModuleList'; +export { ModuleInfo } from './PerspectiveModules/ModuleInfo'; +export { NotFound } from './NotFound'; +export { ErrorDisplay } from './ErrorDisplay'; +export { LoadingDisplay } from './LoadingDisplay'; +export { PerspectiveEditor } from './PerspectiveEditor/PerspectiveEditor'; +export { SchemaValidationError } from './SchemaValidationError'; diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx deleted file mode 100644 index a0bb8f7d..00000000 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/ModuleList.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import type { Perspective, PerspectiveModule } from "@/features/perspectives/types"; -import { - Badge, - Box, - Button, - Flex, - Heading, - Stack, - Text, - VStack, -} from "@chakra-ui/react"; -import { Link } from "@tanstack/react-router"; - -interface ModuleListProps { - readonly module: PerspectiveModule; -} - -/** - * ModuleList component displays a list of perspectives from a specific module - */ -export function ModuleList({ module }: ModuleListProps) { - if (module.perspectives.length === 0) { - return No perspectives found in this module.; - } - - return ( - - {module.perspectives.map((perspective: Perspective) => ( - - - - {perspective.display_name || perspective.name} - - {perspective.version} - - - {perspective.schema?.prompt?.substring(0, 60) ?? "No prompt available"}... - - {perspective.name && ( - - - - )} - - ))} - - ); -} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/PerspectiveDetail.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/PerspectiveDetail.tsx deleted file mode 100644 index cf430a9b..00000000 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/PerspectiveDetail.tsx +++ /dev/null @@ -1,277 +0,0 @@ -import { useColorModeValue } from "@/components/ui/theme/color-mode"; -import type { Perspective } from "@/features/perspectives/types"; -import { - Badge, - Box, - Button, - Code, - Flex, - Heading, - Stack, - Tabs, - Text, -} from "@chakra-ui/react"; -import { Link } from "@tanstack/react-router"; - -interface PerspectiveDetailProps { - perspective: Perspective; - moduleName: string; -} - -/** - * PerspectiveDetail component displays detailed information about a perspective - */ -export function PerspectiveDetail({ - perspective, - moduleName, -}: PerspectiveDetailProps) { - // Color mode values - const borderColor = useColorModeValue("gray.200", "gray.700"); - const tableHeaderBg = useColorModeValue("gray.50", "gray.700"); - const tableBorderColor = useColorModeValue("gray.200", "gray.600"); - - return ( - - {/* Header */} - - - - - {perspective.display_name || perspective.name} - - {perspective.version} - - Module: {moduleName} - - - - - - - - - {/* Description */} - - - Description - - {perspective.description || "No description available."} - - - {/* Tabs for different sections */} - - - Schema - Fields - Prompt - Management - - - - - - {perspective.schema ? ( - - - Schema Information - - - - Name: - {perspective.schema.name} - - - Version: - {perspective.schema.version} - - - - Context Template: - - {perspective.schema.context_template || "None"} - - - - - ) : ( - No schema information available for this perspective. - )} - - - - {perspective.schema?.schema_fields && - perspective.schema.schema_fields.length > 0 ? ( - - - - - - Name - - - Type - - - Description - - - List - - - Complex - - - - - {perspective.schema.schema_fields.map((field) => ( - - - {field.name} - - - {field.type} - - - {field.description} - - - {field.is_list ? "Yes" : "No"} - - - {field.is_complex ? "Yes" : "No"} - - - ))} - - - - ) : ( - No fields defined for this perspective. - )} - - - - - - Prompt Template - - - - {perspective.schema?.prompt ?? - "No prompt template available."} - - - - - - - - - Perspective Management - - - This section will allow you to edit and manage the perspective. - - - - - {perspective.schema?.table_columns && - perspective.schema.table_columns.length > 0 && ( - - - Table Columns - - - - - - Name - - - Style - - - Description - - - - - {perspective.schema.table_columns.map((column) => ( - - - {column.name} - - - {column.style} - - - {column.description || "-"} - - - ))} - - - - )} - - - - Metadata - - - {perspective.version && ( - Version: {perspective.version} - )} - - - - - - - - - - ); -} diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/index.ts b/graphcap_studio/src/features/perspectives/components/PerspectiveModules/index.ts deleted file mode 100644 index d3f7530f..00000000 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveModules/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { ModuleList } from './ModuleList'; -export { ModuleInfo } from './ModuleInfo'; -export { NotFound } from './NotFound'; -export { ErrorDisplay } from './ErrorDisplay'; -export { LoadingDisplay } from './LoadingDisplay'; -export { PerspectiveDetail } from './PerspectiveDetail'; diff --git a/graphcap_studio/src/features/perspectives/components/index.ts b/graphcap_studio/src/features/perspectives/components/index.ts index d2ae8495..07d89562 100644 --- a/graphcap_studio/src/features/perspectives/components/index.ts +++ b/graphcap_studio/src/features/perspectives/components/index.ts @@ -5,12 +5,12 @@ * This module exports all component files from the perspectives feature. */ -export * from "./EmptyPerspectives"; +export * from "./PerspectiveCaption/EmptyPerspectives"; export * from "./PerspectivesErrorState"; -export * from "./PerspectiveFilterPanel"; -export * from "./ErrorMessage"; -export { PerspectiveHeader } from "./PerspectiveNavigation/PerspectiveHeader"; -export { PerspectivesPager } from "./PerspectiveNavigation/PerspectivesPager"; -export { MetadataDisplay } from "./PerspectiveCard/MetadataDisplay"; -export * from "./PerspectiveActions"; -export * from "./PerspectiveManagementPanel"; +export * from "./PerspectiveManagement/PerspectiveFilterPanel"; +export * from "./PerspectiveCaption/ErrorMessage"; +export { PerspectiveHeader } from "./PerspectiveCaption/PerspectiveNavigation/PerspectiveHeader"; +export { PerspectivesPager } from "./PerspectiveCaption/PerspectiveNavigation/PerspectivesPager"; +export { MetadataDisplay } from "./PerspectiveCaption/PerspectiveCard/MetadataDisplay"; +export * from "./PerspectiveCaption/PerspectiveActions"; +export * from "./PerspectiveManagement/PerspectiveManagementPanel"; diff --git a/graphcap_studio/src/pages/perspectives/index.ts b/graphcap_studio/src/pages/perspectives/index.ts new file mode 100644 index 00000000..6592fc74 --- /dev/null +++ b/graphcap_studio/src/pages/perspectives/index.ts @@ -0,0 +1,2 @@ +export { ModulePage } from './module/ModulePage'; +export { PerspectiveDetailPage } from './module/PerspectiveDetailPage'; \ No newline at end of file diff --git a/graphcap_studio/src/pages/perspectives/module/ModulePage.tsx b/graphcap_studio/src/pages/perspectives/module/ModulePage.tsx new file mode 100644 index 00000000..043eff8a --- /dev/null +++ b/graphcap_studio/src/pages/perspectives/module/ModulePage.tsx @@ -0,0 +1,228 @@ +import { SelectContent, SelectItem, SelectRoot, SelectTrigger, SelectValueText } from "@/components/ui/select"; +import { LoadingDisplay, ModuleInfo, ModuleList, NotFound, SchemaValidationError } from "@/features/perspectives/components/PerspectiveManagement"; +import { usePerspectiveModules } from "@/features/perspectives/hooks"; +import type { PerspectiveModule } from "@/features/perspectives/types"; +import { + Badge, + Box, + Button, + Flex, + Heading, + Text, + createListCollection +} from "@chakra-ui/react"; +import { Outlet, useMatches, useNavigate } from "@tanstack/react-router"; +import { useEffect, useMemo, useState } from "react"; + +interface ModulePageProps { + readonly moduleName: string; +} + +/** + * Page component that displays a module and its perspectives + */ +export function ModulePage({ moduleName }: ModulePageProps) { + const perspectiveModules = usePerspectiveModules(); + const { modules, isLoading, error, refetch, getModule } = perspectiveModules; + const [selectedModule, setSelectedModule] = + useState(null); + const [errorDetails, setErrorDetails] = useState(null); + const navigate = useNavigate(); + const matches = useMatches(); + + // Check if we're currently at the module root (no perspective selected) + const isModuleRoot = useMemo(() => { + return matches.some(match => + match.routeId === '/perspectives/module/$moduleName' && + match.pathname === `/perspectives/module/${moduleName}` + ); + }, [matches, moduleName]); + + // Create collection for the select component + const modulesCollection = useMemo(() => { + if (!modules) return createListCollection({ items: [] }); + + return createListCollection({ + items: modules.map(module => ({ + label: module.display_name || module.name, + value: module.name, + module: module, + })), + }); + }, [modules]); + + // Find the selected module when data is loaded + useEffect(() => { + if (modules && modules.length > 0) { + // Use getModule to find the module directly + const module = getModule(moduleName); + setSelectedModule(module || null); + + // If module exists but has no perspectives, check if it might be an API error + if (module && module.perspectives.length === 0) { + // Look for HTML response errors in the console logs + console.debug(`Module ${moduleName} has 0 perspectives. This might indicate an API error.`); + setErrorDetails( + "No perspectives found for this module. This could be due to a server configuration issue." + ); + } else { + setErrorDetails(null); + + // If we're at the module root and the module has perspectives, + // automatically navigate to the first perspective + if (isModuleRoot && module && module.perspectives.length > 0) { + const firstPerspective = module.perspectives[0]; + navigate({ + to: "/perspectives/module/$moduleName/perspective/$perspectiveName", + params: { + moduleName: moduleName, + perspectiveName: firstPerspective.name + } + }); + } + } + } + }, [modules, moduleName, navigate, isModuleRoot, getModule]); + + // Handle module change + const handleModuleChange = (details: { value: string[] }) => { + const newModuleName = details.value[0]; + if (newModuleName && newModuleName !== moduleName) { + navigate({ to: "/perspectives/module/$moduleName", params: { moduleName: newModuleName } }); + } + }; + + // Handle loading state + if (isLoading) { + return ; + } + + // Handle error state + if (error) { + return ( + + + + + + + ); + } + + // Handle case when module is not found + if (!selectedModule) { + return ; + } + + return ( + + {/* Left sidebar with module info and perspectives list */} + + {/* Module selector */} + + + + + + + {modulesCollection.items.map((item) => ( + + {item.label} + + ))} + + + + + {/* Module header section */} + + + {selectedModule.display_name || selectedModule.name} + + Enabled + + + Module: {selectedModule.name} + + + {/* Module information */} + + + Module Information + + + This module contains {selectedModule.perspectives.length} {selectedModule.perspectives.length === 1 ? 'perspective' : 'perspectives'}. + + + Contains {selectedModule.perspectives.length} {selectedModule.perspectives.length === 1 ? 'perspective' : 'perspectives'} + + + + {/* Show warning if we have a module with no perspectives */} + {errorDetails && ( + + {errorDetails} + + + )} + + {/* Perspectives list */} + + + + Perspectives + + + + + + + + {/* Right content area with outlet */} + + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/pages/perspectives/module/PerspectiveDetailPage.tsx b/graphcap_studio/src/pages/perspectives/module/PerspectiveDetailPage.tsx new file mode 100644 index 00000000..9223cc33 --- /dev/null +++ b/graphcap_studio/src/pages/perspectives/module/PerspectiveDetailPage.tsx @@ -0,0 +1,73 @@ +import { ErrorDisplay, LoadingDisplay, NotFound, PerspectiveDetail } from "@/features/perspectives/components/PerspectiveManagement"; +import { usePerspectiveModules } from "@/features/perspectives/hooks"; +import { Box } from "@chakra-ui/react"; +import { useMemo } from "react"; + +interface PerspectiveDetailPageProps { + readonly moduleName: string; + readonly perspectiveName: string; +} + +/** + * Page component that displays the details of a specific perspective + */ +export function PerspectiveDetailPage({ + moduleName, + perspectiveName +}: PerspectiveDetailPageProps) { + const { getModulePerspectives } = usePerspectiveModules(); + const { module, perspectives, isLoading, error } = getModulePerspectives(moduleName); + + // Find the specific perspective + const perspective = useMemo(() => { + if (!perspectives || perspectives.length === 0) return null; + + // First try direct match on the perspective name + let foundPerspective = perspectives.find(p => p.name === perspectiveName); + + // If not found, try to match with module prefix + if (!foundPerspective) { + const fullName = `${moduleName}/${perspectiveName}`; + foundPerspective = perspectives.find(p => p.name === fullName); + } + + // Also try matching just the last part of the name (for module-prefixed perspectives) + if (!foundPerspective) { + foundPerspective = perspectives.find(p => { + const parts = p.name.split('/'); + return parts[parts.length - 1] === perspectiveName; + }); + } + + return foundPerspective; + }, [perspectives, perspectiveName, moduleName]); + + // Handle loading state + if (isLoading) { + return ; + } + + // Handle error state + if (error) { + return ; + } + + // Handle case when module data is missing + if (!module) { + return ; + } + + // Handle case when perspective is not found + if (!perspective) { + return ; + } + + return ( + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/pages/perspectives/module/index.ts b/graphcap_studio/src/pages/perspectives/module/index.ts new file mode 100644 index 00000000..34c371de --- /dev/null +++ b/graphcap_studio/src/pages/perspectives/module/index.ts @@ -0,0 +1,2 @@ +export { ModulePage } from './ModulePage'; +export { PerspectiveDetailPage } from './PerspectiveDetailPage'; \ No newline at end of file diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx index 95134d56..bd0eb4d8 100644 --- a/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName.tsx @@ -1,232 +1,11 @@ -import { SelectContent, SelectItem, SelectRoot, SelectTrigger, SelectValueText } from "@/components/ui/select"; -import { LoadingDisplay, ModuleInfo, ModuleList, NotFound } from "@/features/perspectives/components/PerspectiveModules"; -import { usePerspectiveModules } from "@/features/perspectives/hooks"; -import type { PerspectiveModule } from "@/features/perspectives/types"; -import { - Box, - Button, - Code, - Flex, - Heading, - Text, - createListCollection -} from "@chakra-ui/react"; -import { Outlet, createFileRoute, useMatches, useNavigate } from "@tanstack/react-router"; -import { useEffect, useMemo, useState } from "react"; +import { ModulePage } from "@/pages/perspectives"; +import { createFileRoute } from "@tanstack/react-router"; export const Route = createFileRoute("/perspectives/module/$moduleName")({ - component: ModulePage, + component: ModulePageWrapper, }); -/** - * Component to display detailed schema validation errors - */ -function SchemaValidationError({ error }: { error: Error }) { - // Check if the error contains validation information - const isSchemaError = error.message.includes("Invalid enum value") || - error.message.includes("schema_fields") || - error.message.includes("Expected 'str' | 'float'"); - - return ( - - - Schema Validation Error - - - {isSchemaError ? ( - <> - - There was an error loading perspectives due to schema validation issues with complex fields. - The system is expecting only simple field types ('str' or 'float') but found complex nested objects. - - Possible Solutions: - - Update the server to support complex field structures (recommended) - Simplify perspective schemas to avoid nested fields - - Technical Details: - - {error.message} - - - ) : ( - {error.message} - )} - - - ); -} - -function ModulePage() { +function ModulePageWrapper() { const { moduleName } = Route.useParams(); - const perspectiveModules = usePerspectiveModules(); - const { modules, isLoading, error, refetch, getModule } = perspectiveModules; - const [selectedModule, setSelectedModule] = - useState(null); - const [errorDetails, setErrorDetails] = useState(null); - const navigate = useNavigate(); - const matches = useMatches(); - - // Check if we're currently at the module root (no perspective selected) - const isModuleRoot = useMemo(() => { - return matches.some(match => - match.routeId === '/perspectives/module/$moduleName' && - match.pathname === `/perspectives/module/${moduleName}` - ); - }, [matches, moduleName]); - - // Create collection for the select component - const modulesCollection = useMemo(() => { - if (!modules) return createListCollection({ items: [] }); - - return createListCollection({ - items: modules.map(module => ({ - label: module.display_name || module.name, - value: module.name, - module: module, - })), - }); - }, [modules]); - - // Find the selected module when data is loaded - useEffect(() => { - if (modules && modules.length > 0) { - // Use getModule to find the module directly - const module = getModule(moduleName); - setSelectedModule(module || null); - - // If module exists but has no perspectives, check if it might be an API error - if (module && module.perspectives.length === 0) { - // Look for HTML response errors in the console logs - console.debug(`Module ${moduleName} has 0 perspectives. This might indicate an API error.`); - setErrorDetails( - "No perspectives found for this module. This could be due to a server configuration issue." - ); - } else { - setErrorDetails(null); - - // If we're at the module root and the module has perspectives, - // automatically navigate to the first perspective - if (isModuleRoot && module && module.perspectives.length > 0) { - const firstPerspective = module.perspectives[0]; - navigate({ - to: "/perspectives/module/$moduleName/perspective/$perspectiveName", - params: { - moduleName: moduleName, - perspectiveName: firstPerspective.name - } - }); - } - } - } - }, [modules, moduleName, navigate, isModuleRoot, getModule]); - - // Handle module change - const handleModuleChange = (details: { value: string[] }) => { - const newModuleName = details.value[0]; - if (newModuleName && newModuleName !== moduleName) { - navigate({ to: "/perspectives/module/$moduleName", params: { moduleName: newModuleName } }); - } - }; - - // Handle loading state - if (isLoading) { - return ; - } - - // Handle error state - if (error) { - return ( - - - - - - - ); - } - - // Handle case when module is not found - if (!selectedModule) { - return ; - } - - return ( - - {/* Left sidebar with module info and perspectives list (20% width) */} - - {/* Module selector */} - - - - - - - {modulesCollection.items.map((item) => ( - - {item.label} - - ))} - - - - - {/* Module information */} - - - {/* Show warning if we have a module with no perspectives */} - {errorDetails && ( - - {errorDetails} - - - )} - - {/* Perspectives list */} - - Perspectives - - - - - {/* Right content area with outlet (80% width) */} - - - - - ); + return ; } diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx index 63c421f4..37381411 100644 --- a/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx @@ -1,70 +1,11 @@ -import { ErrorDisplay, LoadingDisplay, NotFound, PerspectiveDetail } from "@/features/perspectives/components/PerspectiveModules"; -import { usePerspectiveModules } from "@/features/perspectives/hooks"; -import { - Box, -} from "@chakra-ui/react"; +import { PerspectiveDetailPage } from "@/pages/perspectives"; import { createFileRoute } from "@tanstack/react-router"; -import { useMemo } from "react"; export const Route = createFileRoute("/perspectives/module/$moduleName/perspective/$perspectiveName")({ - component: PerspectiveDetailPage, + component: PerspectiveDetailPageWrapper, }); -function PerspectiveDetailPage() { +function PerspectiveDetailPageWrapper() { const { moduleName, perspectiveName } = Route.useParams(); - const { getModulePerspectives } = usePerspectiveModules(); - const { module, perspectives, isLoading, error } = getModulePerspectives(moduleName); - - // Find the specific perspective - const perspective = useMemo(() => { - if (!perspectives || perspectives.length === 0) return null; - - // First try direct match on the perspective name - let foundPerspective = perspectives.find(p => p.name === perspectiveName); - - // If not found, try to match with module prefix - if (!foundPerspective) { - const fullName = `${moduleName}/${perspectiveName}`; - foundPerspective = perspectives.find(p => p.name === fullName); - } - - // Also try matching just the last part of the name (for module-prefixed perspectives) - if (!foundPerspective) { - foundPerspective = perspectives.find(p => { - const parts = p.name.split('/'); - return parts[parts.length - 1] === perspectiveName; - }); - } - - return foundPerspective; - }, [perspectives, perspectiveName, moduleName]); - - // Handle loading state - if (isLoading) { - return ; - } - - // Handle error state - if (error) { - return ; - } - - // Handle case when module data is missing - if (!module) { - return ; - } - - // Handle case when perspective is not found - if (!perspective) { - return ; - } - - return ( - - - - ); + return ; } \ No newline at end of file From 3879b8675f4d9144a23aa28ff04766bcd0d6ccd8 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 04:57:51 -0500 Subject: [PATCH 14/24] Rename PerspectiveDetail to PerspectiveEditor Signed-off-by: jphillips --- .../PerspectiveManagement/PerspectiveManagementPanel.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx index 30306670..f32497f1 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx @@ -6,8 +6,7 @@ */ import { LoadingSpinner } from "@/components/ui/status/LoadingSpinner"; -import { Box } from "@chakra-ui/react"; -import { Tabs } from "@chakra-ui/react"; +import { Box, Tabs } from "@chakra-ui/react"; import { Link } from "@tanstack/react-router"; import { usePerspectiveModules } from "../../hooks"; import { PerspectiveFilterPanel } from "./PerspectiveFilterPanel"; @@ -73,10 +72,10 @@ export function PerspectiveManagementPanel() { - {module.perspectives && module.perspectives.map((perspective) => { + {module.perspectives?.map((perspective) => { // Extract perspective ID from the full name const perspectiveId = perspective.name.includes("/") - ? perspective.name.split("/").pop() || perspective.name + ? perspective.name.split("/").pop() ?? perspective.name : perspective.name; return ( From 11dd625c571d9b4ef4084b14781eaad374efffc0 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 04:58:06 -0500 Subject: [PATCH 15/24] Renamed PerspectiveDetail to PerspectiveEditor Signed-off-by: jphillips --- .../PerspectiveEditor/PerspectiveEditor.tsx | 8 ++-- .../hooks/useModulePerspectives.ts | 38 +++++++++++++++++++ .../src/pages/perspectives/index.ts | 2 +- .../pages/perspectives/module/ModulePage.tsx | 2 +- ...tailPage.tsx => PerspectiveEditorPage.tsx} | 10 ++--- .../src/pages/perspectives/module/index.ts | 2 +- .../perspective/$perspectiveName.tsx | 8 ++-- 7 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 graphcap_studio/src/features/perspectives/hooks/useModulePerspectives.ts rename graphcap_studio/src/pages/perspectives/module/{PerspectiveDetailPage.tsx => PerspectiveEditorPage.tsx} (88%) diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/PerspectiveEditor.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/PerspectiveEditor.tsx index fc033311..ca15ab30 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/PerspectiveEditor.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/PerspectiveEditor.tsx @@ -7,17 +7,15 @@ import { Code, Flex, Heading, - Icon, Stack, Tabs, Text, } from "@chakra-ui/react"; import { Link } from "@tanstack/react-router"; -import { ReactNode } from "react"; interface PerspectiveEditorProps { - perspective: Perspective; - moduleName: string; + readonly perspective: Perspective; + readonly moduleName: string; } /** @@ -297,7 +295,7 @@ export function PerspectiveEditor({ {column.style} - {column.description || "-"} + {column.description ?? "-"} ))} diff --git a/graphcap_studio/src/features/perspectives/hooks/useModulePerspectives.ts b/graphcap_studio/src/features/perspectives/hooks/useModulePerspectives.ts new file mode 100644 index 00000000..89b03138 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/hooks/useModulePerspectives.ts @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 +/** + * useModulePerspectives Hook (Compatibility Wrapper) + * + * This hook is kept for backward compatibility. It now uses the enhanced + * usePerspectiveModules hook internally. + * + * @deprecated Use usePerspectiveModules().getModulePerspectives() instead. + */ + +import { useMemo } from "react"; +import { usePerspectiveModules } from "./usePerspectiveModules"; + +/** + * Hook to fetch perspectives for a specific module from the server (compatibility wrapper) + * + * @param moduleName - Name of the module to fetch perspectives for + * @returns A query result with the module and its perspectives + */ +export function useModulePerspectives(moduleName: string) { + // Use the enhanced hooks to get the module data + const { getModulePerspectives } = usePerspectiveModules(); + const moduleData = getModulePerspectives(moduleName); + + // Map to the expected return shape for backward compatibility + return useMemo(() => { + return { + data: moduleData.module ? { + module: moduleData.module, + perspectives: moduleData.perspectives + } : undefined, + isLoading: moduleData.isLoading, + isError: moduleData.isError, + error: moduleData.error, + refetch: moduleData.refetch + }; + }, [moduleData]); +} \ No newline at end of file diff --git a/graphcap_studio/src/pages/perspectives/index.ts b/graphcap_studio/src/pages/perspectives/index.ts index 6592fc74..b01092f0 100644 --- a/graphcap_studio/src/pages/perspectives/index.ts +++ b/graphcap_studio/src/pages/perspectives/index.ts @@ -1,2 +1,2 @@ export { ModulePage } from './module/ModulePage'; -export { PerspectiveDetailPage } from './module/PerspectiveDetailPage'; \ No newline at end of file +export { PerspectiveEditorPage } from './module/PerspectiveEditorPage'; \ No newline at end of file diff --git a/graphcap_studio/src/pages/perspectives/module/ModulePage.tsx b/graphcap_studio/src/pages/perspectives/module/ModulePage.tsx index 043eff8a..2e03f0e8 100644 --- a/graphcap_studio/src/pages/perspectives/module/ModulePage.tsx +++ b/graphcap_studio/src/pages/perspectives/module/ModulePage.tsx @@ -1,5 +1,5 @@ import { SelectContent, SelectItem, SelectRoot, SelectTrigger, SelectValueText } from "@/components/ui/select"; -import { LoadingDisplay, ModuleInfo, ModuleList, NotFound, SchemaValidationError } from "@/features/perspectives/components/PerspectiveManagement"; +import { LoadingDisplay, ModuleList, NotFound, SchemaValidationError } from "@/features/perspectives/components/PerspectiveManagement"; import { usePerspectiveModules } from "@/features/perspectives/hooks"; import type { PerspectiveModule } from "@/features/perspectives/types"; import { diff --git a/graphcap_studio/src/pages/perspectives/module/PerspectiveDetailPage.tsx b/graphcap_studio/src/pages/perspectives/module/PerspectiveEditorPage.tsx similarity index 88% rename from graphcap_studio/src/pages/perspectives/module/PerspectiveDetailPage.tsx rename to graphcap_studio/src/pages/perspectives/module/PerspectiveEditorPage.tsx index 9223cc33..7a7287e1 100644 --- a/graphcap_studio/src/pages/perspectives/module/PerspectiveDetailPage.tsx +++ b/graphcap_studio/src/pages/perspectives/module/PerspectiveEditorPage.tsx @@ -1,9 +1,9 @@ -import { ErrorDisplay, LoadingDisplay, NotFound, PerspectiveDetail } from "@/features/perspectives/components/PerspectiveManagement"; +import { ErrorDisplay, LoadingDisplay, NotFound, PerspectiveEditor } from "@/features/perspectives/components/PerspectiveManagement"; import { usePerspectiveModules } from "@/features/perspectives/hooks"; import { Box } from "@chakra-ui/react"; import { useMemo } from "react"; -interface PerspectiveDetailPageProps { +interface PerspectiveEditorPageProps { readonly moduleName: string; readonly perspectiveName: string; } @@ -11,10 +11,10 @@ interface PerspectiveDetailPageProps { /** * Page component that displays the details of a specific perspective */ -export function PerspectiveDetailPage({ +export function PerspectiveEditorPage({ moduleName, perspectiveName -}: PerspectiveDetailPageProps) { +}: PerspectiveEditorPageProps) { const { getModulePerspectives } = usePerspectiveModules(); const { module, perspectives, isLoading, error } = getModulePerspectives(moduleName); @@ -64,7 +64,7 @@ export function PerspectiveDetailPage({ return ( - diff --git a/graphcap_studio/src/pages/perspectives/module/index.ts b/graphcap_studio/src/pages/perspectives/module/index.ts index 34c371de..1a007be2 100644 --- a/graphcap_studio/src/pages/perspectives/module/index.ts +++ b/graphcap_studio/src/pages/perspectives/module/index.ts @@ -1,2 +1,2 @@ export { ModulePage } from './ModulePage'; -export { PerspectiveDetailPage } from './PerspectiveDetailPage'; \ No newline at end of file +export { PerspectiveEditorPage } from './PerspectiveEditorPage'; \ No newline at end of file diff --git a/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx index 37381411..4deee943 100644 --- a/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx +++ b/graphcap_studio/src/routes/perspectives/module/$moduleName/perspective/$perspectiveName.tsx @@ -1,11 +1,11 @@ -import { PerspectiveDetailPage } from "@/pages/perspectives"; +import { PerspectiveEditorPage } from "@/pages/perspectives"; import { createFileRoute } from "@tanstack/react-router"; export const Route = createFileRoute("/perspectives/module/$moduleName/perspective/$perspectiveName")({ - component: PerspectiveDetailPageWrapper, + component: PerspectiveEditorPageWrapper, }); -function PerspectiveDetailPageWrapper() { +function PerspectiveEditorPageWrapper() { const { moduleName, perspectiveName } = Route.useParams(); - return ; + return ; } \ No newline at end of file From 44a32df7b81007fbc9f50b4dfbdb964189ffdbf2 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 05:17:59 -0500 Subject: [PATCH 16/24] Decompose Perspective Editor components Signed-off-by: jphillips --- .../PerspectiveEditor/PerspectiveEditor.tsx | 311 ++---------------- .../components/FieldsTab.tsx | 71 ++++ .../components/ManagementTab.tsx | 49 +++ .../components/PerspectiveDescription.tsx | 27 ++ .../components/PerspectiveHeader.tsx | 62 ++++ .../components/PromptTab.tsx | 36 ++ .../components/SchemaInfoTab.tsx | 46 +++ .../components/TableColumns.tsx | 58 ++++ .../PerspectiveEditor/components/index.ts | 6 + .../context/PerspectiveEditorContext.tsx | 152 +++++++++ .../PerspectiveEditor/index.ts | 3 +- 11 files changed, 542 insertions(+), 279 deletions(-) create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/FieldsTab.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/ManagementTab.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PerspectiveDescription.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PerspectiveHeader.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PromptTab.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/SchemaInfoTab.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/TableColumns.tsx create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/index.ts create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/context/PerspectiveEditorContext.tsx diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/PerspectiveEditor.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/PerspectiveEditor.tsx index ca15ab30..3b69805d 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/PerspectiveEditor.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/PerspectiveEditor.tsx @@ -1,21 +1,18 @@ -import { useColorModeValue } from "@/components/ui/theme/color-mode"; import type { Perspective } from "@/features/perspectives/types"; -import { - Badge, - Box, - Button, - Code, - Flex, - Heading, - Stack, - Tabs, - Text, -} from "@chakra-ui/react"; -import { Link } from "@tanstack/react-router"; +import { Box, Tabs } from "@chakra-ui/react"; +import { + FieldsTab, + ManagementTab, + PerspectiveHeader, + PromptTab, + SchemaInfoTab +} from "./components"; +import { PerspectiveEditorProvider, usePerspectiveEditor } from "./context/PerspectiveEditorContext"; interface PerspectiveEditorProps { readonly perspective: Perspective; readonly moduleName: string; + readonly perspectiveList?: Perspective[]; } /** @@ -24,89 +21,38 @@ interface PerspectiveEditorProps { export function PerspectiveEditor({ perspective, moduleName, + perspectiveList = [], }: PerspectiveEditorProps) { - // Color mode values - const borderColor = useColorModeValue("gray.200", "gray.700"); - const bgColor = useColorModeValue("white", "gray.800"); - const headerBgColor = useColorModeValue("gray.50", "gray.900"); - const descriptionBgColor = useColorModeValue("blue.50", "gray.700"); - const tableHeaderBg = useColorModeValue("gray.50", "gray.700"); - const tableBorderColor = useColorModeValue("gray.200", "gray.600"); - - // Format the prompt content to ensure it's a string - const getPromptContent = (): string => { - const prompt = perspective.schema?.prompt; - if (prompt === undefined || prompt === null) { - return "No prompt template available."; - } - - return typeof prompt === 'string' - ? prompt - : JSON.stringify(prompt, null, 2); - }; + return ( + + + + ); +} - // Format field type to ensure it's displayed as a string - const getFieldTypeDisplay = (type: string | object): string => { - if (typeof type === 'string') { - return type; - } - return JSON.stringify(type); - }; +/** + * PerspectiveEditorContent renders the editor UI using the context + */ +function PerspectiveEditorContent() { + const { colors } = usePerspectiveEditor(); return ( - {/* Header */} - - - - - - {perspective.display_name || perspective.name} - - {perspective.version} - - Module: {moduleName} - - - - - - - - {/* Description Panel */} - - - Description - - - {perspective.description || "No description available for this perspective."} - - + {/* Tabs for different sections */} - + Schema Fields Prompt @@ -116,210 +62,19 @@ export function PerspectiveEditor({ - {perspective.schema ? ( - - - Schema Information - - - - Name: - {perspective.schema.name} - - - Version: - {perspective.schema.version} - - - - Context Template: - - {perspective.schema.context_template || "None"} - - - - - ) : ( - No schema information available for this perspective. - )} + - {perspective.schema?.schema_fields && - perspective.schema.schema_fields.length > 0 ? ( - - - Field Definitions - - - - - - - Name - - - Type - - - Description - - - List - - - Complex - - - - - {perspective.schema.schema_fields.map((field) => ( - - - {field.name} - - - {getFieldTypeDisplay(field.type)} - - - {field.description} - - - {field.is_list ? "Yes" : "No"} - - - {field.is_complex ? "Yes" : "No"} - - - ))} - - - - - ) : ( - No fields defined for this perspective. - )} + - - - Prompt Template - - - - {getPromptContent()} - - - + - - - Perspective Management - - - This section allows you to edit and manage the perspective configuration. - - - - - {perspective.schema?.table_columns && - perspective.schema.table_columns.length > 0 && ( - - - Table Columns - - - - - - Name - - - Style - - - Description - - - - - {perspective.schema.table_columns.map((column) => ( - - - {column.name} - - - {column.style} - - - {column.description ?? "-"} - - - ))} - - - - )} - - - - Actions - - - - - - - - - + diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/FieldsTab.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/FieldsTab.tsx new file mode 100644 index 00000000..90a50272 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/FieldsTab.tsx @@ -0,0 +1,71 @@ +import { Box, Heading, Text } from "@chakra-ui/react"; +import { usePerspectiveEditor } from "../context/PerspectiveEditorContext"; + +/** + * FieldsTab displays the field definitions for a perspective schema + */ +export function FieldsTab() { + const { perspective, colors, getFieldTypeDisplay } = usePerspectiveEditor(); + + if (!perspective.schema?.schema_fields || perspective.schema.schema_fields.length === 0) { + return No fields defined for this perspective.; + } + + return ( + + + Field Definitions + + + + + + + Name + + + Type + + + Description + + + List + + + Complex + + + + + {perspective.schema.schema_fields.map((field) => ( + + + {field.name} + + + {getFieldTypeDisplay(field.type)} + + + {field.description} + + + {field.is_list ? "Yes" : "No"} + + + {field.is_complex ? "Yes" : "No"} + + + ))} + + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/ManagementTab.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/ManagementTab.tsx new file mode 100644 index 00000000..f47167d3 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/ManagementTab.tsx @@ -0,0 +1,49 @@ +import { Box, Button, Flex, Heading, Stack, Text } from "@chakra-ui/react"; +import { usePerspectiveEditor } from "../context/PerspectiveEditorContext"; +import { TableColumns } from "./TableColumns"; + +/** + * ManagementTab displays the perspective management options + */ +export function ManagementTab() { + const { perspective, colors } = usePerspectiveEditor(); + + return ( + + + Perspective Management + + + This section allows you to edit and manage the perspective configuration. + + + + + {perspective.schema?.table_columns && perspective.schema.table_columns.length > 0 && ( + + )} + + + + Actions + + + + + + + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PerspectiveDescription.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PerspectiveDescription.tsx new file mode 100644 index 00000000..3641d2c8 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PerspectiveDescription.tsx @@ -0,0 +1,27 @@ +import { Box, Heading, Text } from "@chakra-ui/react"; +import { usePerspectiveEditor } from "../context/PerspectiveEditorContext"; + +/** + * PerspectiveDescription displays the description of the perspective + */ +export function PerspectiveDescription() { + const { perspective, colors } = usePerspectiveEditor(); + + return ( + + + Description + + + {perspective.description || "No description available for this perspective."} + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PerspectiveHeader.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PerspectiveHeader.tsx new file mode 100644 index 00000000..c38b994b --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PerspectiveHeader.tsx @@ -0,0 +1,62 @@ +import { Badge, Box, Button, Flex, HStack, Heading, Text } from "@chakra-ui/react"; +import { Link } from "@tanstack/react-router"; +import { LuChevronLeft, LuChevronRight } from "react-icons/lu"; +import { usePerspectiveEditor } from "../context/PerspectiveEditorContext"; + +/** + * PerspectiveHeader displays the perspective title, version, description, and navigation + */ +export function PerspectiveHeader() { + const { perspective, moduleName, colors, onNavigateNext, onNavigatePrevious, hasPrevious, hasNext } = usePerspectiveEditor(); + + return ( + + + + + + {perspective.display_name || perspective.name} + + | Version : {perspective.version} | Module : {moduleName} + + + {perspective.description || "No description available for this perspective."} + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PromptTab.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PromptTab.tsx new file mode 100644 index 00000000..d24b1bee --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/PromptTab.tsx @@ -0,0 +1,36 @@ +import { Box, Code, Heading } from "@chakra-ui/react"; +import { usePerspectiveEditor } from "../context/PerspectiveEditorContext"; + +/** + * PromptTab displays the prompt template for the perspective + */ +export function PromptTab() { + const { colors, getPromptContent } = usePerspectiveEditor(); + + return ( + + + Prompt Template + + + + {getPromptContent()} + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/SchemaInfoTab.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/SchemaInfoTab.tsx new file mode 100644 index 00000000..b11c1269 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/SchemaInfoTab.tsx @@ -0,0 +1,46 @@ +import { Box, Code, Heading, Stack, Text } from "@chakra-ui/react"; +import { usePerspectiveEditor } from "../context/PerspectiveEditorContext"; + +/** + * SchemaInfoTab displays the basic schema information for a perspective + */ +export function SchemaInfoTab() { + const { perspective, colors } = usePerspectiveEditor(); + + if (!perspective.schema) { + return No schema information available for this perspective.; + } + + return ( + + + Schema Information + + + + Name: + {perspective.schema.name} + + + Version: + {perspective.schema.version} + + + + Context Template: + + {perspective.schema.context_template || "None"} + + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/TableColumns.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/TableColumns.tsx new file mode 100644 index 00000000..478066e3 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/TableColumns.tsx @@ -0,0 +1,58 @@ +import type { TableColumn } from "@/features/perspectives/types"; +import { Box, Text } from "@chakra-ui/react"; +import { usePerspectiveEditor } from "../context/PerspectiveEditorContext"; + +interface TableColumnsProps { + readonly tableColumns: TableColumn[]; +} + +/** + * TableColumns displays a table of column definitions + */ +export function TableColumns({ tableColumns }: TableColumnsProps) { + const { colors } = usePerspectiveEditor(); + + return ( + + + Table Columns + + + + + + Name + + + Style + + + Description + + + + + {tableColumns.map((column) => ( + + + {column.name} + + + {column.style} + + + {column.description ?? "-"} + + + ))} + + + + ); +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/index.ts b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/index.ts new file mode 100644 index 00000000..dc6a7551 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/components/index.ts @@ -0,0 +1,6 @@ +export * from "./PerspectiveHeader"; +export * from "./SchemaInfoTab"; +export * from "./FieldsTab"; +export * from "./PromptTab"; +export * from "./ManagementTab"; +export * from "./TableColumns"; \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/context/PerspectiveEditorContext.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/context/PerspectiveEditorContext.tsx new file mode 100644 index 00000000..c0bd9872 --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/context/PerspectiveEditorContext.tsx @@ -0,0 +1,152 @@ +import { useColorModeValue } from "@/components/ui/theme/color-mode"; +import type { Perspective } from "@/features/perspectives/types"; +import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react"; + +interface PerspectiveEditorContextType { + // Data + perspective: Perspective; + moduleName: string; + + // Navigation + onNavigateNext: () => void; + onNavigatePrevious: () => void; + hasPrevious: boolean; + hasNext: boolean; + + // Utility functions + getPromptContent: () => string; + getFieldTypeDisplay: (type: string | object) => string; + + // Theme values + colors: { + borderColor: string; + bgColor: string; + headerBgColor: string; + descriptionBgColor: string; + tableHeaderBg: string; + tableBorderColor: string; + }; +} + +const PerspectiveEditorContext = createContext(undefined); + +interface PerspectiveEditorProviderProps { + children: React.ReactNode; + perspective: Perspective; + moduleName: string; + perspectiveList?: Perspective[]; +} + +export function PerspectiveEditorProvider({ + children, + perspective, + moduleName, + perspectiveList = [], +}: PerspectiveEditorProviderProps) { + // State for current perspective + const [currentPerspective, setCurrentPerspective] = useState(perspective); + + // Update current perspective when prop changes + useEffect(() => { + setCurrentPerspective(perspective); + }, [perspective]); + + // Navigation logic + const currentIndex = useMemo(() => { + return perspectiveList.findIndex(p => p.name === currentPerspective.name); + }, [perspectiveList, currentPerspective.name]); + + const hasPrevious = currentIndex > 0; + const hasNext = currentIndex >= 0 && currentIndex < perspectiveList.length - 1; + + const onNavigatePrevious = useCallback(() => { + if (hasPrevious) { + setCurrentPerspective(perspectiveList[currentIndex - 1]); + } + }, [hasPrevious, perspectiveList, currentIndex]); + + const onNavigateNext = useCallback(() => { + if (hasNext) { + setCurrentPerspective(perspectiveList[currentIndex + 1]); + } + }, [hasNext, perspectiveList, currentIndex]); + + // Color mode values + const borderColor = useColorModeValue("gray.200", "gray.700"); + const bgColor = useColorModeValue("white", "gray.800"); + const headerBgColor = useColorModeValue("gray.50", "gray.900"); + const descriptionBgColor = useColorModeValue("blue.50", "gray.700"); + const tableHeaderBg = useColorModeValue("gray.50", "gray.700"); + const tableBorderColor = useColorModeValue("gray.200", "gray.600"); + + const colors = useMemo(() => ({ + borderColor, + bgColor, + headerBgColor, + descriptionBgColor, + tableHeaderBg, + tableBorderColor + }), [borderColor, bgColor, headerBgColor, descriptionBgColor, tableHeaderBg, tableBorderColor]); + + // Format the prompt content to ensure it's a string + const getPromptContent = useMemo(() => { + return (): string => { + const prompt = currentPerspective.schema?.prompt; + if (prompt === undefined || prompt === null) { + return "No prompt template available."; + } + + return typeof prompt === 'string' + ? prompt + : JSON.stringify(prompt, null, 2); + }; + }, [currentPerspective.schema?.prompt]); + + // Format field type to ensure it's displayed as a string + const getFieldTypeDisplay = useMemo(() => { + return (type: string | object): string => { + if (typeof type === 'string') { + return type; + } + return JSON.stringify(type); + }; + }, []); + + const value = useMemo(() => ({ + perspective: currentPerspective, + moduleName, + onNavigateNext, + onNavigatePrevious, + hasPrevious, + hasNext, + getPromptContent, + getFieldTypeDisplay, + colors + }), [ + currentPerspective, + moduleName, + onNavigateNext, + onNavigatePrevious, + hasPrevious, + hasNext, + getPromptContent, + getFieldTypeDisplay, + colors + ]); + + return ( + + {children} + + ); +} + +export function usePerspectiveEditor() { + const context = useContext(PerspectiveEditorContext); + + if (context === undefined) { + throw new Error("usePerspectiveEditor must be used within a PerspectiveEditorProvider"); + } + + return context; +} \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/index.ts b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/index.ts index a6698c0f..0fb3dd3e 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/index.ts +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveEditor/index.ts @@ -1 +1,2 @@ -export { PerspectiveEditor } from './PerspectiveEditor'; \ No newline at end of file +export * from "./PerspectiveEditor"; +export * from "./context/PerspectiveEditorContext"; \ No newline at end of file From 2ce3053d9ce94b79db9b3a78db992424ac77c5b5 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 05:31:42 -0500 Subject: [PATCH 17/24] Alpha testing doc update Signed-off-by: jphillips --- doc/alpha/alpha.md | 1 + doc/concepts/perspectives.rst | 287 +++++++++++++--------------------- doc/index.rst | 31 ++++ 3 files changed, 145 insertions(+), 174 deletions(-) create mode 100644 doc/alpha/alpha.md diff --git a/doc/alpha/alpha.md b/doc/alpha/alpha.md new file mode 100644 index 00000000..d89727ff --- /dev/null +++ b/doc/alpha/alpha.md @@ -0,0 +1 @@ +Stub entry for alpha testing. \ No newline at end of file diff --git a/doc/concepts/perspectives.rst b/doc/concepts/perspectives.rst index 6d7c5dc7..07ada047 100644 --- a/doc/concepts/perspectives.rst +++ b/doc/concepts/perspectives.rst @@ -12,20 +12,45 @@ At its core, a perspective is about asking specific questions about an image. Fo - What objects and relationships can we see? (Graph Caption) - How does the composition work? (Art Critic) - What feelings does it evoke? (Emotional Sentiment) -- What story does it tell? (Temporarium) +- What story does it tell? (Storytelling) +- What poetic metaphors might arise? (Poetic Metaphor) +- How does this image relate to time? (Temporarium) Each perspective has its own: -- Focus (what it looks for) -- Language (how it describes things) -- Structure (how it organizes information) -- Balance between describing what's visible and what it means + +- **Focus**: what it looks for in the image +- **Language**: how it describes what it sees +- **Structure**: how it organizes information +- **Balance**: between describing what's visible and interpreting meaning +- **Module**: which family of perspectives it belongs to +- **Tags**: categories that help organize and find perspectives + +The Perspective Ecosystem +======================== + +Perspectives in GraphCap are organized into modules that group related perspectives together. This organization makes it easier to: + +- Find perspectives relevant to your interests +- Enable or disable entire families of perspectives +- Understand relationships between similar perspectives + +Examples of modules include: + +- **Core**: Essential perspectives like Graph Caption and Custom Caption +- **Artistic**: Art Critic, Poetic Metaphor, and other artistic interpretations +- **Narrative**: Storytelling and related perspectives +- **Technical**: Specialized analytical perspectives +- **Synthesizer**: Perspectives that combine multiple captions into a focused output. Built-in Perspectives =================== +GraphCap comes with a diverse set of built-in perspectives, each designed for specific use cases: + Graph Caption ------------ -The "just the facts" perspective. It looks at what's actually in the image: +The "just the facts" perspective that captures objective elements: + - Objects and their relationships - Clear, verifiable descriptions - Confidence scores for each observation @@ -36,7 +61,8 @@ Example output: Art Critic --------- -The formal analysis perspective. It examines: +The formal analysis perspective for visual arts: + - Composition and framing - Color relationships - Technical execution @@ -47,7 +73,8 @@ Example output: Emotional Sentiment ----------------- -The feeling-focused perspective. It considers: +The feeling-focused perspective: + - Mood and atmosphere - Emotional impact - Human elements @@ -56,16 +83,40 @@ The feeling-focused perspective. It considers: Example output: "A serene moment capturing the quiet joy of a peaceful afternoon" -Temporarium ----------- -A temporal contextperspective. It explores: -- Historical or cultural context -- Potential narratives -- Broader implications -- Time-based elements -Example output: -"A snapshot of urban life in transition, where modern architecture meets historical preservation" +Working with Perspectives +======================= + +Discovering and Selecting +------------------------ +GraphCap offers an intuitive way to browse and select perspectives: + +- Browse by module to find related perspectives +- Filter by tags to find perspectives for specific needs +- Search by name or description +- View detailed descriptions to understand what each perspective offers + +Combining Perspectives +-------------------- +Perspectives work best when they complement each other. You might use: + +- Graph Caption + Art Critic for detailed artwork analysis +- Emotional Sentiment + Temporarium for storytelling +- Multiple perspectives for training data generation + +Local Development and Customization +================================= + +GraphCap allows you to create and test new perspectives locally before sharing them more broadly: + +Perspective Workspace +------------------- +Your perspective library can include both: + +- Standard perspectives from the GraphCap library +- Local perspectives you're developing or customizing + +This separation lets you experiment with new ideas while keeping the main system stable. Creating Your Own Perspective =========================== @@ -73,160 +124,38 @@ Creating Your Own Perspective Before You Start -------------- Ask yourself: + - What unique angle are you trying to capture? - Who will use this perspective and why? - How literal vs. interpretative should it be? - What kind of output will be most useful? +- Which module does it belong to? +- What tags would help users find it? -How to create a perspective +How to Create a Perspective -------------------------- -Define a config file for the perspective. Following these examples: - - - .. code-block:: json - { - "name": "graph_caption", - "display_name": "Graph Caption", - "version": "1", - "prompt": "Analyze this image and provide a structured analysis with the following components:\n\n1. Tags: Generate a list of categorized tags with confidence scores for key elements in the image. Each tag should include the tag name, category, and a confidence score between 0 and 1.\n\n2. Short Caption: Create a concise single-sentence caption (max 100 characters) that summarizes the main content of the image.\n\n3. Verification: Provide a brief verification of the tag accuracy and visual grounding, noting any potential issues or uncertainties.\n\n4. Dense Caption: Create a detailed narrative description that incorporates the tagged elements and provides a comprehensive understanding of the image content.\n\nYour analysis should be objective, detailed, and based solely on what is visible in the image.", - "schema_fields": [ - { - "name": "tags_list", - "type": "str", - "description": "List of categorized tags with confidence scores", - "is_list": true, - "is_complex": true, - "fields": [ - { - "name": "tag", - "type": "str", - "description": "Description of the tagged element" - }, - { - "name": "category", - "type": "str", - "description": "Category the tag belongs to" - }, - { - "name": "confidence", - "type": "float", - "description": "Confidence score between 0 and 1" - } - ] - }, - { - "name": "short_caption", - "type": "str", - "description": "Concise single sentence caption (max 100 chars)", - "is_list": false - }, - { - "name": "verification", - "type": "str", - "description": "Verification of tag accuracy and visual grounding", - "is_list": false - }, - { - "name": "dense_caption", - "type": "str", - "description": "Detailed narrative description incorporating tagged elements", - "is_list": false - } - ], - "table_columns": [ - { - "name": "Category", - "style": "cyan" - }, - { - "name": "Content", - "style": "green" - } - ], - "context_template": "\n{short_caption}\n\nTags: {tags_list}\n\n" - } - - .. code-block:: json - { - "name": "temporarium", - "display_name": "Temporarium", - "version": "1", - "prompt": "You are a temporal analysis agent. Analyze this image with a focus on time-related aspects and temporal dimensions. Your response should include a chain-of-thought reasoning process with the following components:\n\n1. Visual Analysis: Provide observations based solely on visible image details.\n\n2. Epoch Reasoning: Present logical reasoning about the implied historical or futuristic epoch.\n\n3. Epoch Context: Provide a concise summary of the inferred epoch context.\n\n4. Narrative Reasoning: Explain how key elements fit within the epoch context.\n\n5. Narrative Elements: Provide a factual description of key visible subjects or objects, linked to the epoch.\n\n6. Continuity Reasoning: Reason on how the scene connects to known historical trends or plausible futures.\n\n7. Continuity Elements: Provide a brief summary of historical or futuristic continuity.\n\n8. Speculative Reasoning: Present step-by-step reasoning behind any imaginative extrapolation.\n\n9. Temporal Speculation: Provide imaginative yet plausible speculative details derived from reasoning.\n\n10. Detailed Caption: Create a final cohesive caption integrating all chain-of-thought steps.\n\nYour analysis should be thoughtful and consider both explicit and implicit temporal elements in the image.", - "schema_fields": [ - { - "name": "visual_analysis", - "type": "str", - "description": "Observations based solely on visible image details.", - "is_list": false - }, - { - "name": "epoch_reasoning", - "type": "str", - "description": "Logical reasoning about the implied historical or futuristic epoch.", - "is_list": false - }, - { - "name": "epoch_context", - "type": "str", - "description": "Concise summary of the inferred epoch context.", - "is_list": false - }, - { - "name": "narrative_reasoning", - "type": "str", - "description": "Explanation of how key elements fit within the epoch context.", - "is_list": false - }, - { - "name": "narrative_elements", - "type": "str", - "description": "Factual description of key visible subjects or objects, linked to the epoch.", - "is_list": false - }, - { - "name": "continuity_reasoning", - "type": "str", - "description": "Reasoning on how the scene connects to known historical trends or plausible futures.", - "is_list": false - }, - { - "name": "continuity_elements", - "type": "str", - "description": "Brief summary of historical or futuristic continuity.", - "is_list": false - }, - { - "name": "speculative_reasoning", - "type": "str", - "description": "Step-by-step reasoning behind any imaginative extrapolation.", - "is_list": false - }, - { - "name": "temporal_speculation", - "type": "str", - "description": "Imaginative yet plausible speculative details derived from reasoning.", - "is_list": false - }, - { - "name": "detailed_caption", - "type": "str", - "description": "Final cohesive caption integrating all chain-of-thought steps.", - "is_list": false - } - ], - "table_columns": [ - { - "name": "Component", - "style": "cyan" - }, - { - "name": "Content", - "style": "green" - } - ], - "context_template": "\n{detailed_caption}\n\n" - } +Every perspective is defined by: + +1. **Basic Information**: + - Name and display name + - Version + - Description + - Module assignment + - Tags for categorization + - Priority level + +2. **Prompt**: + Clear instructions for how to analyze the image + +3. **Schema**: + The structured fields that will contain the analysis + +4. **Presentation**: + How the results will be displayed + +5. **Context Template**: + How the perspective's output can be used in broader contexts Tips for Good Perspectives ======================== @@ -246,20 +175,30 @@ Quality Matters - Get feedback from potential users - Have clear ways to measure success -Make It Useful ------------- -- Write clear documentation -- Include examples -- Make it easy to understand when to use this perspective -- Consider how it fits with other perspectives +Make It Discoverable +------------------ +- Place it in the appropriate module +- Use descriptive tags +- Write a clear, concise description +- Consider including example outputs in the description + +Evolution and Deprecation +----------------------- +As your needs evolve, perspectives can too: + +- Update existing perspectives with new versions +- Mark outdated perspectives as deprecated +- Suggest replacement perspectives when deprecating old ones Real-World Usage ============== -Perspectives work best when they complement each other. You might use: +GraphCap perspectives are designed to be useful in real-world applications: -- Graph Caption + Art Critic for detailed artwork analysis -- Emotional Sentiment + Temporarium for storytelling -- Multiple perspectives for training data generation +- **Content Creation**: Generate rich, varied descriptions for creative projects +- **Accessibility**: Provide detailed image descriptions for visually impaired users +- **Data Analysis**: Extract structured information from visual content +- **Education**: Teach different ways of seeing and analyzing visual material +- **Creative Inspiration**: Generate diverse interpretations to spark new ideas Remember: The goal isn't to replace human understanding, but to provide useful, structured ways of describing and analyzing images for different purposes. diff --git a/doc/index.rst b/doc/index.rst index 0926794c..59852360 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -4,6 +4,37 @@ GraphCap Welcome to GraphCap's documentation! +Alpha Testing +============ + +## GraphCap Project Overview for Alpha Testing + +**What is GraphCap?** + +GraphCap is an open-source, distributed captioning application designed under the Open Model Initiative. Its primary purpose is to generate detailed, insightful captions and analyses of images by leveraging multiple analytical perspectives. +The application utilizes directed acyclic graph structures to capture complex relationships within images, facilitating diverse, context-rich interpretations. + +### Core Features +- **Multi-Perspective Captioning:** GraphCap applies specialized analytical perspectives—such as formal artistic critique, emotional sentiment, storytelling, and temporal analysis—to generate comprehensive captions. +- **Distributed Processing:** Designed to operate efficiently in distributed environments, allowing for scalable, community-based computational resources. +- **Model Flexibility:** Supports integration with multiple Vision-Language Models (VLMs), enabling comparative analysis and ensuring adaptability across varied captioning tasks. +- **OMI-Compatible:** GraphCap is designed to be compatible with the Open Model Initiative data repository, allowing for easy integration with our open source image dataset. + +### Alpha Testing Goals +- Evaluate system stability and performance across diverse hardware and software environments. +- Collect feedback on caption accuracy, perspective usefulness, and overall usability. +- Identify critical bugs and areas for improvement in functionality and user experience. + +### Participating in Alpha Testing +Participants in the alpha test will: +- Test the application in their local or preferred computing environment. +- Provide structured feedback via surveys and discussions. +- Engage collaboratively in community discussions to shape future GraphCap development. + +Your insights and experiences during this alpha phase will directly contribute to refining GraphCap's capabilities and guiding its future development within the Open Model Initiative community. + + + Getting Started ============== From 247fc86dec9666bee03719ebb7893b315e6dbe1e Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 06:44:23 -0500 Subject: [PATCH 18/24] Add perspective types, rerack module groups Signed-off-by: jphillips --- workspace/perspective_library/art_critic.json | 3 ++- workspace/perspective_library/custom_caption.json | 1 + workspace/perspective_library/emotional_sentiment.json | 3 ++- workspace/perspective_library/graph_caption.json | 3 ++- workspace/perspective_library/locality_graph.json | 3 ++- workspace/perspective_library/out_of_frame.json | 3 ++- workspace/perspective_library/poetic_metaphor.json | 3 ++- workspace/perspective_library/simple_temporarium.json | 3 ++- workspace/perspective_library/storytelling.json | 3 ++- workspace/perspective_library/synthesized_caption.json | 1 + workspace/perspective_library/temporarium.json | 3 ++- workspace/perspective_library/time_tags.json | 3 ++- 12 files changed, 22 insertions(+), 10 deletions(-) diff --git a/workspace/perspective_library/art_critic.json b/workspace/perspective_library/art_critic.json index 29e96f24..2c08612c 100644 --- a/workspace/perspective_library/art_critic.json +++ b/workspace/perspective_library/art_critic.json @@ -46,7 +46,8 @@ } ], "context_template": "\n{formal_analysis}\n\n", - "module": "art", + "module": "core", + "type": "perspective", "tags": ["art", "formal-analysis", "visual-elements", "objective"], "description": "An art critic perspective that focuses on formal analysis principles, providing objective observations of visual elements, technical aspects, and stylistic choices without subjective interpretation.", "deprecated": false, diff --git a/workspace/perspective_library/custom_caption.json b/workspace/perspective_library/custom_caption.json index 6c05c970..46623e68 100644 --- a/workspace/perspective_library/custom_caption.json +++ b/workspace/perspective_library/custom_caption.json @@ -29,6 +29,7 @@ ], "context_template": "\n{caption}\n\n", "module": "core", + "type": "custom", "tags": ["customizable", "general-purpose", "flexible"], "description": "A customizable perspective that allows users to provide their own instructions for image analysis, supporting versatile use cases and custom analysis approaches.", "deprecated": false, diff --git a/workspace/perspective_library/emotional_sentiment.json b/workspace/perspective_library/emotional_sentiment.json index 3a64dd84..516fb30e 100644 --- a/workspace/perspective_library/emotional_sentiment.json +++ b/workspace/perspective_library/emotional_sentiment.json @@ -28,7 +28,8 @@ } ], "context_template": "\n{sentiment_caption}\n\n", - "module": "emotional", + "module": "focused", + "type": "perspective", "tags": ["emotion", "sentiment", "mood", "affective"], "description": "A perspective focused on analyzing the emotional tone conveyed by an image, providing insights into mood and sentiment through descriptive language.", "deprecated": false, diff --git a/workspace/perspective_library/graph_caption.json b/workspace/perspective_library/graph_caption.json index 8577f134..05e67c60 100644 --- a/workspace/perspective_library/graph_caption.json +++ b/workspace/perspective_library/graph_caption.json @@ -58,7 +58,8 @@ } ], "context_template": "\n{short_caption}\n\nTags: {tags_list}\n\n", - "module": "graph", + "module": "core", + "type": "perspective", "tags": ["graph", "caption", "analysis"], "description": "Graph caption analysis", "deprecated": false, diff --git a/workspace/perspective_library/locality_graph.json b/workspace/perspective_library/locality_graph.json index e3b02613..b9001640 100644 --- a/workspace/perspective_library/locality_graph.json +++ b/workspace/perspective_library/locality_graph.json @@ -63,7 +63,8 @@ } ], "context_template": "\n{composition_summary}\nNodes: {nodes}\nEdges: {edges}\n", - "module": "graph", + "module": "core", + "type": "perspective", "tags": ["graph", "locality", "analysis"], "description": "Graph locality analysis", "deprecated": false, diff --git a/workspace/perspective_library/out_of_frame.json b/workspace/perspective_library/out_of_frame.json index 72225fc8..d35d470e 100644 --- a/workspace/perspective_library/out_of_frame.json +++ b/workspace/perspective_library/out_of_frame.json @@ -46,7 +46,8 @@ } ], "context_template": "\n{narrative_possibilities}\n\n", - "module": "speculative", + "module": "creative", + "type": "perspective", "tags": ["speculative", "imagination", "beyond-frame"], "description": "Speculative interpretation of what might exist beyond the boundaries of the image", "deprecated": false, diff --git a/workspace/perspective_library/poetic_metaphor.json b/workspace/perspective_library/poetic_metaphor.json index 6283ebfc..75888f7c 100644 --- a/workspace/perspective_library/poetic_metaphor.json +++ b/workspace/perspective_library/poetic_metaphor.json @@ -46,7 +46,8 @@ } ], "context_template": "\n{poetic_description}\n\n", - "module": "artistic", + "module": "creative", + "type": "perspective", "tags": ["poetic", "metaphor", "imagery", "figurative"], "description": "Poetic metaphor analysis", "deprecated": false, diff --git a/workspace/perspective_library/simple_temporarium.json b/workspace/perspective_library/simple_temporarium.json index 6cd1ce82..efefaa28 100644 --- a/workspace/perspective_library/simple_temporarium.json +++ b/workspace/perspective_library/simple_temporarium.json @@ -52,7 +52,8 @@ } ], "context_template": "\n{temporal_caption}\n\n", - "module": "speculative", + "module": "creative", + "type": "perspective", "tags": ["time", "historical", "simplified", "era", "indicators"], "description": "A simplified version of the Temporarium perspective that focuses on basic temporal analysis with less complexity and reasoning steps.", "deprecated": false, diff --git a/workspace/perspective_library/storytelling.json b/workspace/perspective_library/storytelling.json index 83fe9ca5..d7504e44 100644 --- a/workspace/perspective_library/storytelling.json +++ b/workspace/perspective_library/storytelling.json @@ -46,7 +46,8 @@ } ], "context_template": "\n{plot_elements}\n\n", - "module": "narrative", + "module": "creative", + "type": "perspective", "tags": ["storytelling", "narrative", "creative", "plot", "characters"], "description": "A narrative-focused perspective that constructs a cohesive story from visual elements, including scene setting, character development, plot, and thematic analysis.", "deprecated": false, diff --git a/workspace/perspective_library/synthesized_caption.json b/workspace/perspective_library/synthesized_caption.json index d3ff7cbd..e69f5690 100644 --- a/workspace/perspective_library/synthesized_caption.json +++ b/workspace/perspective_library/synthesized_caption.json @@ -53,6 +53,7 @@ ], "context_template": "\n{short_caption}\n\nTags: {synthesis_tags}\n\n", "module": "core", + "type": "synthesizer", "tags": ["synthesis", "integration", "comprehensive", "multi-perspective"], "description": "A meta-perspective that integrates insights from multiple other perspectives to create a comprehensive, cohesive analysis with multiple levels of detail and explicit reasoning.", "deprecated": false, diff --git a/workspace/perspective_library/temporarium.json b/workspace/perspective_library/temporarium.json index 031e0c7c..f902af43 100644 --- a/workspace/perspective_library/temporarium.json +++ b/workspace/perspective_library/temporarium.json @@ -76,7 +76,8 @@ } ], "context_template": "\n{detailed_caption}\n\n", - "module": "speculative", + "module": "creative", + "type": "perspective", "tags": ["time", "historical", "futuristic", "epoch", "continuity", "speculative"], "description": "A perspective focused on temporal analysis, examining historical or futuristic elements, epoch context, historical continuity, and temporal speculation with chain-of-thought reasoning.", "deprecated": false, diff --git a/workspace/perspective_library/time_tags.json b/workspace/perspective_library/time_tags.json index 248df58b..accce702 100644 --- a/workspace/perspective_library/time_tags.json +++ b/workspace/perspective_library/time_tags.json @@ -58,7 +58,8 @@ ], "context_template": "\nPeriod: {time_period_tags}\nCategory: {temporal_category}\nQualities: {time_quality_tags}\n\n", - "module": "speculative", + "module": "focused", + "type": "perspective", "tags": ["time", "tagging", "classification", "historical", "periods"], "description": "A tagging-focused perspective that categorizes images based on time periods, temporal indicators, and time-related qualities for easier image classification.", "deprecated": false, From 27291c5bb800b75305940cbb9499560f00534700 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 07:04:55 -0500 Subject: [PATCH 19/24] Add 3 i2v caption perspectives Signed-off-by: jphillips --- .../video/i2storyboard_2beat.json | 68 +++++++++++++++++ .../video/i2storyboard_3beat.json | 73 +++++++++++++++++++ .../perspective_library/video/i2video.json | 73 +++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 workspace/perspective_library/video/i2storyboard_2beat.json create mode 100644 workspace/perspective_library/video/i2storyboard_3beat.json create mode 100644 workspace/perspective_library/video/i2video.json diff --git a/workspace/perspective_library/video/i2storyboard_2beat.json b/workspace/perspective_library/video/i2storyboard_2beat.json new file mode 100644 index 00000000..90c2649c --- /dev/null +++ b/workspace/perspective_library/video/i2storyboard_2beat.json @@ -0,0 +1,68 @@ +{ + "name": "i2storyboard_2beat", + "display_name": "Image-to-Storyboard (2-Beat)", + "version": "1", + "prompt": "Analyze the image and generate a **two-beat storyboard prompt**, capturing a compelling narrative progression. Each beat should:\n\n1. **Identify a distinct moment** within the image that can transition into another.\n2. **Describe the key subject(s) and their action or state** in a visually engaging way.\n3. **Establish the setting, mood, and atmosphere** to enhance storytelling.\n4. **Define a clear transition between the two beats**, ensuring narrative flow.\n5. **Use cinematic framing** to guide visual composition.\n\nEach beat should be short and impactful, maintaining strong **visual clarity and storytelling flow**.", + "schema_fields": [ + { + "name": "beat_1", + "type": "str", + "description": "The first major moment in the storyboard—describes the initial state, action, or tension.", + "is_list": false + }, + { + "name": "beat_2", + "type": "str", + "description": "The second major moment—describes the transformation, reaction, or escalation from Beat 1.", + "is_list": false + }, + { + "name": "key_subjects", + "type": "str", + "description": "A concise description of the primary characters or objects driving the scene.", + "is_list": false + }, + { + "name": "setting_and_mood", + "type": "str", + "description": "A description of the environment and its emotional tone to reinforce storytelling.", + "is_list": false + }, + { + "name": "transition", + "type": "str", + "description": "A short description of how Beat 1 transitions into Beat 2 visually or thematically.", + "is_list": false + }, + { + "name": "cinematic_framing", + "type": "str", + "description": "Suggested camera angles, movement, or framing techniques to enhance visual storytelling.", + "is_list": false + }, + { + "name": "final_storyboard_prompt", + "type": "str", + "description": "A refined, structured prompt that integrates both beats and transitions smoothly.", + "is_list": false + } + ], + "table_columns": [ + { + "name": "Component", + "style": "cyan" + }, + { + "name": "Description", + "style": "green" + } + ], + "context_template": "\n{final_storyboard_prompt}\n", + "module": "creative", + "type": "perspective", + "tags": ["storyboard", "video", "narrative"], + "description": "A perspective that generates a two-beat storyboard prompt for video generation.", + "deprecated": false, + "priority": 50 + } + \ No newline at end of file diff --git a/workspace/perspective_library/video/i2storyboard_3beat.json b/workspace/perspective_library/video/i2storyboard_3beat.json new file mode 100644 index 00000000..8ed795a3 --- /dev/null +++ b/workspace/perspective_library/video/i2storyboard_3beat.json @@ -0,0 +1,73 @@ +{ + "name": "i2storyboard_3beat", + "display_name": "Image-to-Storyboard (3-Beat)", + "version": "1", + "prompt": "Analyze the image and generate a **three-beat storyboard prompt**, capturing a compelling narrative sequence. Each beat should:\n\n1. **Define a distinct moment** that progresses naturally into the next.\n2. **Describe the key subject(s), action, and state** for visual clarity.\n3. **Establish setting, mood, and atmosphere** to enhance storytelling.\n4. **Ensure smooth narrative and visual transitions** between beats.\n5. **Use cinematic framing** to guide visual composition.\n\nEach beat must be short yet impactful, maintaining strong **visual clarity, narrative flow, and cinematic appeal**.", + "schema_fields": [ + { + "name": "beat_1", + "type": "str", + "description": "The first key moment—sets the stage, introduces the subject, and establishes context.", + "is_list": false + }, + { + "name": "beat_2", + "type": "str", + "description": "The second key moment—presents a shift, action, or escalation in the scene.", + "is_list": false + }, + { + "name": "beat_3", + "type": "str", + "description": "The final key moment—concludes the sequence, resolving tension or setting up further events.", + "is_list": false + }, + { + "name": "key_subjects", + "type": "str", + "description": "A concise description of the primary characters or objects driving the scene.", + "is_list": false + }, + { + "name": "setting_and_mood", + "type": "str", + "description": "A description of the environment and its emotional tone to reinforce storytelling.", + "is_list": false + }, + { + "name": "transition", + "type": "str", + "description": "A short description of how each beat flows into the next.", + "is_list": false + }, + { + "name": "cinematic_framing", + "type": "str", + "description": "Suggested camera angles, movement, or framing techniques to enhance visual storytelling.", + "is_list": false + }, + { + "name": "final_storyboard_prompt", + "type": "str", + "description": "A refined, structured prompt that integrates all beats and transitions smoothly.", + "is_list": false + } + ], + "table_columns": [ + { + "name": "Component", + "style": "cyan" + }, + { + "name": "Description", + "style": "green" + } + ], + "context_template": "\n{final_storyboard_prompt}\n", + "module": "creative", + "type": "perspective", + "tags": ["storyboard", "video", "narrative"], + "description": "A perspective that generates a three-beat storyboard prompt for video generation.", + "deprecated": false, + "priority": 50 +} diff --git a/workspace/perspective_library/video/i2video.json b/workspace/perspective_library/video/i2video.json new file mode 100644 index 00000000..68e2c446 --- /dev/null +++ b/workspace/perspective_library/video/i2video.json @@ -0,0 +1,73 @@ +{ + "name": "i2video", + "display_name": "Image to Video Prompt", + "version": "1", + "prompt": "Craft a high-quality, dense video caption optimized for video generation. The caption should be vivid, concise (one to two sentences), and include:\n\n1. **Core Scene**: Identify the main subject and setting. Ensure the scene has dynamic potential (e.g., action, transformation, movement).\n\n2. **Subject Details**: Describe key visual traits of the subject(s), including clothing, physical features, and expressions that enhance visual interest.\n\n3. **Environmental Layers**: Capture foreground, midground, and background details to ensure depth and spatial clarity.\n\n4. **Action Sequence**: Define the subject's movement or events in a way that emphasizes realistic physics, momentum, or cinematic flow.\n\n5. **Mood & Atmosphere**: Establish the tone using descriptive words that evoke emotions (e.g., 'ominous storm brewing,' 'serene sunset glow').\n\n6. **Artistic Style & Cinematography**: Specify the visual aesthetic (e.g., 'photorealistic cyberpunk city with neon reflections') and include relevant camera directions (e.g., 'dynamic tracking shot from below').\n\nThe final caption must be **short yet densely packed with visual and cinematic cues**, avoiding generic or vague descriptions. Ensure natural phrasing and an engaging flow.", + "schema_fields": [ + { + "name": "core_scene", + "type": "str", + "description": "A brief but clear definition of the main subject and setting, ensuring visual dynamism.", + "is_list": false + }, + { + "name": "subject_details", + "type": "str", + "description": "Distinctive features of the subject, including appearance, attire, posture, or expressions.", + "is_list": false + }, + { + "name": "environmental_layers", + "type": "str", + "description": "Layered description of foreground, midground, and background to establish depth.", + "is_list": false + }, + { + "name": "action_sequence", + "type": "str", + "description": "Specific, dynamic movements or events occurring in the scene.", + "is_list": false + }, + { + "name": "mood_and_atmosphere", + "type": "str", + "description": "Descriptive elements that establish the emotional tone and ambiance.", + "is_list": false + }, + { + "name": "artistic_style", + "type": "str", + "description": "The visual style and cinematographic choices, such as lighting, color schemes, and perspective.", + "is_list": false + }, + { + "name": "camera_directions", + "type": "str", + "description": "Optional cinematic techniques like tracking shots, zooms, or slow-motion effects.", + "is_list": false + }, + { + "name": "final_caption", + "type": "str", + "description": "A refined, short, yet highly descriptive video caption integrating all elements into a seamless flow.", + "is_list": false + } + ], + "table_columns": [ + { + "name": "Component", + "style": "cyan" + }, + { + "name": "Description", + "style": "green" + } + ], + "context_template": "\n{final_caption}\n", + "module": "creative", + "type": "perspective", + "tags": ["video", "caption", "video_generation"], + "description": "A perspective that generates a high-quality, dense video caption optimized for video generation.", + "deprecated": false, + "priority": 50 +} \ No newline at end of file From 9022e7bdb01b0596533c2245f9dd7dd1aaab8940 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 09:47:42 -0500 Subject: [PATCH 20/24] Add lots of perspective docs, organize library Signed-off-by: jphillips --- doc/static/generate_perspective.png | Bin 0 -> 620259 bytes workspace/perspective_library/README.md | 128 ++++++++++++++++++ workspace/perspective_library/core/README.md | 67 +++++++++ .../{ => core}/art_critic.json | 0 .../{ => core}/graph_caption.json | 0 .../{ => core}/locality_graph.json | 0 .../core/style_preset.json | 67 +++++++++ .../{ => core}/synthesized_caption.json | 0 .../perspective_library/creative/README.md | 61 +++++++++ .../{ => creative}/out_of_frame.json | 0 .../{ => creative}/poetic_metaphor.json | 0 .../{ => creative}/simple_temporarium.json | 0 .../{ => creative}/storytelling.json | 0 .../{ => creative}/temporarium.json | 0 workspace/perspective_library/niche/README.md | 54 ++++++++ .../{ => niche}/custom_caption.json | 2 +- .../{ => niche}/emotional_sentiment.json | 2 +- .../{ => niche}/time_tags.json | 2 +- workspace/perspective_library/video/README.md | 62 +++++++++ .../video/instruct_i2video.json | 85 ++++++++++++ 20 files changed, 527 insertions(+), 3 deletions(-) create mode 100644 doc/static/generate_perspective.png create mode 100644 workspace/perspective_library/README.md create mode 100644 workspace/perspective_library/core/README.md rename workspace/perspective_library/{ => core}/art_critic.json (100%) rename workspace/perspective_library/{ => core}/graph_caption.json (100%) rename workspace/perspective_library/{ => core}/locality_graph.json (100%) create mode 100644 workspace/perspective_library/core/style_preset.json rename workspace/perspective_library/{ => core}/synthesized_caption.json (100%) create mode 100644 workspace/perspective_library/creative/README.md rename workspace/perspective_library/{ => creative}/out_of_frame.json (100%) rename workspace/perspective_library/{ => creative}/poetic_metaphor.json (100%) rename workspace/perspective_library/{ => creative}/simple_temporarium.json (100%) rename workspace/perspective_library/{ => creative}/storytelling.json (100%) rename workspace/perspective_library/{ => creative}/temporarium.json (100%) create mode 100644 workspace/perspective_library/niche/README.md rename workspace/perspective_library/{ => niche}/custom_caption.json (98%) rename workspace/perspective_library/{ => niche}/emotional_sentiment.json (98%) rename workspace/perspective_library/{ => niche}/time_tags.json (99%) create mode 100644 workspace/perspective_library/video/README.md create mode 100644 workspace/perspective_library/video/instruct_i2video.json diff --git a/doc/static/generate_perspective.png b/doc/static/generate_perspective.png new file mode 100644 index 0000000000000000000000000000000000000000..7d62a9a8bf664eb5ea244712e7b9d8b40e0bb097 GIT binary patch literal 620259 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

~J14RRo&!TyK5B_c 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ξ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 literal 0 HcmV?d00001 diff --git a/workspace/perspective_library/README.md b/workspace/perspective_library/README.md new file mode 100644 index 00000000..c413bec8 --- /dev/null +++ b/workspace/perspective_library/README.md @@ -0,0 +1,128 @@ +# GraphCap Perspective Library + +## Overview + +The Perspective Library is a collection of specialized analytical frameworks for image understanding and captioning. Each perspective provides a unique lens through which to analyze and describe visual content, from objective factual descriptions to creative interpretations, temporal analyses, and specialized domain-specific insights. + +Think of a perspective as a unique way of looking at and describing an image - just as a photographer, art critic, and child might describe the same photograph differently. The Perspective Library organizes these different viewpoints into a structured, modular system that can be used individually or in combination to generate rich, multi-faceted image descriptions. + +For a comprehensive conceptual overview of perspectives, see the [Perspectives Concept Documentation](../../doc/concepts/perspectives.rst). + +## Library Structure + +The Perspective Library is organized into modules, each containing perspectives with related focuses: + +- **[Core](./core/)**: Fundamental perspectives forming the backbone of the image analysis pipeline, providing objective, structured analysis from complementary angles. These represent our "gold standard" for image captioning. + +- **[Creative](./creative/)**: Perspectives designed to generate "controlled hallucinations" - creative extensions beyond what's directly visible in the image while remaining plausibly connected to the visual content. + +- **[Video](./video/)**: Specialized perspectives for transforming static images into rich, dynamic prompts for video generation, focusing on motion potential, narrative progression, and cinematic elements. + +- **[Niche](./niche/)**: Focused analytical perspectives targeting specific dimensions of visual content, extracting specialized information optimized for particular use cases or domains. + +Each module contains a README with detailed information about its specific perspectives and their applications. + +## Using Perspectives + +Perspectives can be used in several ways: + +### 1. Through the GraphCap UI + +The easiest way to use perspectives is through the GraphCap web interface: + +1. Select an image from your dataset +2. Choose a perspective from the right hand panel +3. Generate the analysis +4. View the structured output with all fields + +![Perspective Generation](../../doc/static/generate_perspective.png) + +## Creating New Perspectives + +To create a new perspective: + +1. **Determine the Module**: Decide which module your perspective belongs to (core, creative, video, niche), or create a new module if needed. + +2. **Create the JSON File**: Create a new JSON file in the appropriate module directory with the following structure: + +```json +{ + "name": "my_perspective", + "display_name": "My Perspective", + "version": "1", + "prompt": "Your detailed prompt for the perspective...", + "schema_fields": [ + { + "name": "field_name", + "type": "str", + "description": "Description of this field.", + "is_list": false + }, + // Additional fields... + ], + "table_columns": [ + { + "name": "Column Name", + "style": "cyan" + }, + { + "name": "Value", + "style": "green" + } + ], + "context_template": "\n{field_name}\n\n", + "module": "your_module", + "type": "perspective", + "tags": ["relevant", "tags", "here"], + "description": "A concise description of your perspective.", + "deprecated": false, + "priority": 50 +} +``` + +3. **Structure Your Prompt**: Craft a clear, detailed prompt that guides the AI to produce structured output in the desired format. Make sure it: + - Clearly defines the analytical focus + - Specifies what elements to look for + - Provides a structured format for responses + - Maintains objectivity or clearly specifies where interpretation is allowed + +4. **Define Schema Fields**: Create fields that capture the structured output of your perspective. Each field should have: + - A clear name + - Type (str, int, float, dict) + - Description + - Whether it's a list or a single value + - For complex fields, nested field definitions + +5. **Test Your Perspective**: Before committing, test your perspective with a variety of images to ensure it consistently produces high-quality, useful output. + +6. **Document Your Perspective**: Update the module's README.md to include your new perspective, its purpose, and use cases. + +For more detailed guidance on creating effective perspectives, refer to the [Perspectives Concept Documentation](../../doc/concepts/perspectives.rst). + +## Integration with Other Systems + +Perspectives can be integrated with: + +- **Training Data Generation**: Use perspectives to create rich, structured annotations for ML training +- **Content Management Systems**: Enhance image metadata with perspective analyses +- **Creative Tools**: Generate prompts and inspiration from perspective outputs +- **Search Systems**: Enable sophisticated image retrieval based on perspective-generated attributes + +## Best Practices + +- **Combine Complementary Perspectives**: Pair factual perspectives with interpretative ones for comprehensive analysis +- **Match Perspectives to Use Cases**: Select perspectives based on your specific needs +- **Version Control**: When updating perspectives, increment the version number and document changes +- **Validate Outputs**: Periodically review perspective outputs to ensure quality and accuracy + +## Contributing + +Contributions to the Perspective Library are welcome! To contribute: + +1. Fork the repository +2. Create your perspective following the guidelines above +3. Add appropriate documentation +4. Submit a pull request with a clear description of your new perspective + +For more information on contributing, see the [Contributing Guide](../../CONTRIBUTING.md). + diff --git a/workspace/perspective_library/core/README.md b/workspace/perspective_library/core/README.md new file mode 100644 index 00000000..63df1661 --- /dev/null +++ b/workspace/perspective_library/core/README.md @@ -0,0 +1,67 @@ +# Core Perspectives Module + +## Overview + +The Core Perspectives module contains fundamental perspectives that form the backbone of the Open Model Initiative (OMI) pipeline. These perspectives represent our "gold standard" for image analysis and captioning, providing comprehensive, structured, and objective analysis of visual content from complementary angles. Unlike specialized perspectives that focus on specific aspects or creative interpretations, core perspectives are designed to extract factual, verifiable information with high precision and reliability. + +These perspectives are particularly valuable for: + +- Building robust foundation models for image understanding +- Creating high-quality, structured training datasets +- Supporting objective image search and retrieval +- Establishing baseline annotations against which specialized analyses can be compared +- Powering downstream applications that require reliable image understanding + +## Core Perspectives + +| Perspective | Description | Primary Focus | Use Cases | +|-------------|-------------|--------------|-----------| +| **Graph Caption** | Structured analysis generating categorized tags with confidence scores, short captions, verification, and dense descriptions. | Objective content analysis with confidence scoring | Training data generation, searchable image databases, content verification | +| **Locality Graph** | Spatial relationship analysis capturing objects as nodes and their relationships as edges in a visual composition graph. | Explicit spatial relationships between visual elements | Scene understanding, layout analysis, relational datasets | +| **Art Critic** | Formal analysis examining visual elements, technical execution, and stylistic choices with objective, observable language. | Objective formal analysis without interpretation | Visual style datasets, art analysis, aesthetic categorization | +| **Synthesized Caption** | Integration of multiple perspectives into cohesive analysis with explicit reasoning and multiple levels of detail. | Multi-perspective synthesis with structured reasoning | Comprehensive image understanding, dataset enrichment, explainable AI training | +| **Structured Style Presets** | Generation of detailed style specifications with theme, color palette, camera settings, lighting, texture, and mood. | Structured aesthetic style specification | Style transfer, generation guidance, aesthetic categorization | + +## The Value of Core Perspectives + +The core perspectives collectively provide a comprehensive foundation for image understanding through several key principles: + +1. **Structured Objectivity**: Each perspective focuses on observable elements that can be reliably identified and verified, creating annotations with high agreement rates among human evaluators. + +2. **Complementary Analysis Angles**: The perspectives approach visual content from different analytical frameworks (graph-based, spatial, formal, synthetic), ensuring complete coverage of relevant information. + +3. **Confidence Quantification**: Where applicable, elements include confidence scoring to indicate reliability, supporting applications that require understanding of model certainty. + +4. **Multi-granular Analysis**: From concise tags to detailed descriptions, the perspectives provide annotations at multiple levels of detail suitable for different downstream tasks. + +5. **Explicit Reasoning**: The analysis includes clear explanation of the reasoning process, supporting applications that require explainability and transparency. + +## Dataset Applications + +These core perspectives are particularly valuable for dataset creation in several contexts: + +### Foundation Model Training + +The structured, objective annotations provided by core perspectives serve as high-quality training data for foundation models, establishing reliable correlations between visual content and language descriptions. + +### Benchmark Standards + +The multi-faceted nature of core perspectives makes them ideal for creating evaluation benchmarks that assess model performance across different dimensions of image understanding. + +### Multimodal Retrieval Systems + +The granular, structured annotations (particularly tags with confidence scores and spatial relationships) enable sophisticated image retrieval systems that can search based on specific visual attributes and relationships. + +### Explainable AI Development + +The explicit reasoning and structured analysis approach supports the development of explainable AI systems that can articulate the basis for their visual interpretations. + +## Integration Guidelines + +When using core perspectives for dataset creation: + +1. Use Graph Caption and Locality Graph for foundational object and relationship identification +2. Apply Art Critic for formal analysis of visual elements and composition +3. Leverage Synthesized Caption to integrate insights across perspectives with explicit reasoning +4. Utilize Style Presets for aesthetic categorization and style specification +5. Combine core perspectives with specialized perspectives for comprehensive dataset enrichment diff --git a/workspace/perspective_library/art_critic.json b/workspace/perspective_library/core/art_critic.json similarity index 100% rename from workspace/perspective_library/art_critic.json rename to workspace/perspective_library/core/art_critic.json diff --git a/workspace/perspective_library/graph_caption.json b/workspace/perspective_library/core/graph_caption.json similarity index 100% rename from workspace/perspective_library/graph_caption.json rename to workspace/perspective_library/core/graph_caption.json diff --git a/workspace/perspective_library/locality_graph.json b/workspace/perspective_library/core/locality_graph.json similarity index 100% rename from workspace/perspective_library/locality_graph.json rename to workspace/perspective_library/core/locality_graph.json diff --git a/workspace/perspective_library/core/style_preset.json b/workspace/perspective_library/core/style_preset.json new file mode 100644 index 00000000..af15b7e7 --- /dev/null +++ b/workspace/perspective_library/core/style_preset.json @@ -0,0 +1,67 @@ +{ + "name": "style_preset", + "display_name": "Structured Style Presets", + "version": "1", + "prompt": "Generate a **structured style preset** that defines a unique visual and thematic quality. Each preset should be concise yet richly descriptive, covering:\n\n1. **Theme**: Clearly state the overarching aesthetic or concept.\n2. **Color Palette**: Define the primary color tones, contrast, and saturation.\n3. **Camera Type & Film Stock**: Specify the camera style, film stock, or digital settings used to achieve the look.\n4. **Lighting**: Describe the lighting setup that enhances the mood (e.g., high-key, soft diffused, chiaroscuro).\n5. **Texture & Rendering**: Highlight key textures, grain, or surface qualities that define the preset.\n6. **Vibe**: Summarize the emotional tone and intended effect.\n\nThe result should be structured as a **formatted preset block**, ensuring clarity and usability.", + "schema_fields": [ + { + "name": "theme", + "type": "str", + "description": "The central artistic or conceptual theme defining the preset.", + "is_list": false + }, + { + "name": "color_palette", + "type": "str", + "description": "The dominant colors, contrast, and saturation levels that shape the aesthetic.", + "is_list": false + }, + { + "name": "camera_and_film", + "type": "str", + "description": "The type of camera, film stock, or digital settings that define the visual style.", + "is_list": false + }, + { + "name": "lighting", + "type": "str", + "description": "Description of the lighting setup and how it interacts with the scene.", + "is_list": false + }, + { + "name": "texture_and_rendering", + "type": "str", + "description": "Key textures, grain, or material properties that contribute to the look.", + "is_list": false + }, + { + "name": "vibe", + "type": "str", + "description": "The overall emotional tone or impact of the preset.", + "is_list": false + }, + { + "name": "final_preset", + "type": "str", + "description": "A structured, formatted preset encapsulating all key elements.", + "is_list": false + } + ], + "table_columns": [ + { + "name": "Component", + "style": "cyan" + }, + { + "name": "Description", + "style": "green" + } + ], + "context_template": "\n{final_preset}\n", + "module": "core", + "type": "perspective", + "tags": ["style", "preset", "aesthetic", "cinematic"], + "description": "A perspective that generates structured style presets for detailed, thematic image and video generation.", + "deprecated": false, + "priority": 50 +} diff --git a/workspace/perspective_library/synthesized_caption.json b/workspace/perspective_library/core/synthesized_caption.json similarity index 100% rename from workspace/perspective_library/synthesized_caption.json rename to workspace/perspective_library/core/synthesized_caption.json diff --git a/workspace/perspective_library/creative/README.md b/workspace/perspective_library/creative/README.md new file mode 100644 index 00000000..6411c2c9 --- /dev/null +++ b/workspace/perspective_library/creative/README.md @@ -0,0 +1,61 @@ +# Creative Perspectives Module + +## Overview + +The Creative Perspectives module contains a collection of specialized perspectives designed to generate "controlled hallucinations" from images. Unlike factual perspectives that focus on objectively describing what's visible, creative perspectives extend beyond the frame, exploring imaginative interpretations, narratives, and speculative elements that might not be directly observable but are plausibly connected to the visual content. + +These perspectives are particularly valuable for: + +- Generating rich, imaginative training data for creative AI applications +- Exploring potential narratives and context beyond what's visually present +- Creating diverse interpretations of the same visual content +- Supporting creative writing, storytelling, and content generation workflows +- Developing more nuanced understanding of visual media through multiple interpretative lenses + +## Creative Perspectives + +| Perspective | Description | Primary Focus | Use Cases | +|-------------|-------------|--------------|-----------| +| **Temporarium** | A temporal analysis perspective examining historical or futuristic elements with chain-of-thought reasoning about epochs, continuity, and temporal speculation. | Time-related aspects and temporal dimensions | Historical datasets, timeline creation, period piece generation | +| **Simple Temporarium** | A simplified version of Temporarium focusing on basic temporal analysis with less complexity and reasoning steps. | Simplified time analysis | Educational datasets, basic historical labeling | +| **Out of Frame** | Speculative interpretation of what might exist beyond the visible boundaries of the image. | Spatial and narrative extension | Scene completion, environment building, world-building datasets | +| **Storytelling** | Constructs cohesive narratives from visual elements, including scene setting, character development, plot, and themes. | Narrative construction | Story generation, creative writing prompts, screenplay development | +| **Poetic Metaphor** | Creates poetic interpretations using metaphor, imagery, and figurative language to evoke deeper meaning. | Figurative and symbolic interpretation | Poetry generation, artistic description, emotional datasets | + +## The Value of Controlled Hallucinations + +While the term "hallucination" is often considered negative in AI contexts, controlled and intentional creative extensions can be extremely valuable. The perspectives in this module are designed to produce *plausible* creative interpretations that: + +1. **Remain grounded** in the visual evidence present in the image +2. **Explicitly separate** factual observation from creative extension +3. **Apply consistent reasoning** to develop interpretations +4. **Follow structured frameworks** for different types of creative analysis + +## Dataset Applications + +These creative perspectives are particularly valuable for dataset creation in several contexts: + +### Training Data Diversity + +When training generative models, having diverse interpretations of the same content helps create more nuanced and versatile outputs. Creative perspectives can significantly expand the range of textual descriptions associated with images. + +### Cross-Modal Learning + +For models that need to understand relationships between visual content and creative text (such as image generation from creative prompts), these perspectives provide valuable bridging data. + +### Educational Content + +In educational contexts, these perspectives can help generate explanatory content that goes beyond simple descriptions, helping learners understand historical context, narrative structure, or symbolic interpretation. + +### Creative Applications + +For applications focused on creative writing, storytelling, or artistic content generation, these perspectives provide structured approaches to deriving creative content from visual stimuli. + +## Integration Guidelines + +When using creative perspectives for dataset creation: + +1. Consider combining them with factual perspectives for a balanced approach +2. Use appropriate metadata to indicate which aspects are observational vs. interpretative +3. Apply filtering or human review when very high factual accuracy is required +4. Experiment with perspective combinations to achieve different creative effects diff --git a/workspace/perspective_library/out_of_frame.json b/workspace/perspective_library/creative/out_of_frame.json similarity index 100% rename from workspace/perspective_library/out_of_frame.json rename to workspace/perspective_library/creative/out_of_frame.json diff --git a/workspace/perspective_library/poetic_metaphor.json b/workspace/perspective_library/creative/poetic_metaphor.json similarity index 100% rename from workspace/perspective_library/poetic_metaphor.json rename to workspace/perspective_library/creative/poetic_metaphor.json diff --git a/workspace/perspective_library/simple_temporarium.json b/workspace/perspective_library/creative/simple_temporarium.json similarity index 100% rename from workspace/perspective_library/simple_temporarium.json rename to workspace/perspective_library/creative/simple_temporarium.json diff --git a/workspace/perspective_library/storytelling.json b/workspace/perspective_library/creative/storytelling.json similarity index 100% rename from workspace/perspective_library/storytelling.json rename to workspace/perspective_library/creative/storytelling.json diff --git a/workspace/perspective_library/temporarium.json b/workspace/perspective_library/creative/temporarium.json similarity index 100% rename from workspace/perspective_library/temporarium.json rename to workspace/perspective_library/creative/temporarium.json diff --git a/workspace/perspective_library/niche/README.md b/workspace/perspective_library/niche/README.md new file mode 100644 index 00000000..fecbcc58 --- /dev/null +++ b/workspace/perspective_library/niche/README.md @@ -0,0 +1,54 @@ +# Niche Analysis Perspectives Module + +## Overview + +The Niche Analysis Perspectives module contains specialized perspectives designed for focused, targeted analysis of particular aspects of images. Unlike broader perspectives that provide comprehensive descriptions, niche perspectives drill down into specific dimensions of visual content, extracting specialized information optimized for particular use cases or domains. + +These perspectives are particularly valuable for: + +- Extracting specific types of information from visual content +- Enhancing datasets with specialized metadata +- Supporting domain-specific applications and research +- Enriching broader analyses with targeted insights +- Creating training data for specialized machine learning models + +## Niche Perspectives + +| Perspective | Description | Primary Focus | Use Cases | +|-------------|-------------|--------------|-----------| +| **Emotional Sentiment** | Analyzes the emotional tone conveyed by images, providing insights into mood and sentiment through descriptive language. | Affective dimensions and emotional impact | Sentiment analysis datasets, emotional tagging, mood-based recommendations | +| **Time Tags** | Categorizes images based on time periods, temporal indicators, and time-related qualities for historical or fantasy classification. | Temporal characteristics and historical context | Historical archives, period piece datasets, timeline construction | + +## The Value of Specialized Analysis + +While broader perspectives provide comprehensive coverage, niche perspectives offer several unique advantages: + +1. **Depth over Breadth**: By focusing on a single dimension of analysis, niche perspectives can provide much deeper insights into specific aspects of images. +2. **Specialized Vocabulary**: These perspectives employ domain-specific terminology and frameworks appropriate to their focus area. +3. **Structured Metadata**: The outputs are optimized for classification, tagging, and metadata generation within specific domains. +4. **Complementary Insights**: When combined with broader perspectives, they enrich the overall understanding with specialized knowledge. + +## Dataset Applications + +These niche perspectives are particularly valuable for dataset creation in several contexts: + +### Enhanced Metadata + +The structured outputs from niche perspectives can significantly enhance image datasets with rich, specialized metadata that supports advanced search, filtering, and analysis. + +### Domain-Specific Training Data + +For machine learning models focused on specific tasks (emotion recognition, temporal classification), these perspectives generate high-quality labeled data optimized for the target domain. + +### Multi-dimensional Analysis + +By applying multiple niche perspectives alongside broader ones, dataset creators can build multi-layered understanding of visual content that captures both general characteristics and specialized aspects. + +## Integration Guidelines + +When using niche perspectives for dataset creation: + +1. Consider what specific dimensions of analysis are most relevant to your use case +2. Combine multiple niche perspectives for multi-faceted specialized analysis +3. Pair niche perspectives with broader ones for comprehensive coverage +4. Use the structured outputs to enhance search, filtering, and retrieval capabilities diff --git a/workspace/perspective_library/custom_caption.json b/workspace/perspective_library/niche/custom_caption.json similarity index 98% rename from workspace/perspective_library/custom_caption.json rename to workspace/perspective_library/niche/custom_caption.json index 46623e68..520a3a37 100644 --- a/workspace/perspective_library/custom_caption.json +++ b/workspace/perspective_library/niche/custom_caption.json @@ -28,7 +28,7 @@ } ], "context_template": "\n{caption}\n\n", - "module": "core", + "module": "niche", "type": "custom", "tags": ["customizable", "general-purpose", "flexible"], "description": "A customizable perspective that allows users to provide their own instructions for image analysis, supporting versatile use cases and custom analysis approaches.", diff --git a/workspace/perspective_library/emotional_sentiment.json b/workspace/perspective_library/niche/emotional_sentiment.json similarity index 98% rename from workspace/perspective_library/emotional_sentiment.json rename to workspace/perspective_library/niche/emotional_sentiment.json index 516fb30e..151509e4 100644 --- a/workspace/perspective_library/emotional_sentiment.json +++ b/workspace/perspective_library/niche/emotional_sentiment.json @@ -28,7 +28,7 @@ } ], "context_template": "\n{sentiment_caption}\n\n", - "module": "focused", + "module": "niche", "type": "perspective", "tags": ["emotion", "sentiment", "mood", "affective"], "description": "A perspective focused on analyzing the emotional tone conveyed by an image, providing insights into mood and sentiment through descriptive language.", diff --git a/workspace/perspective_library/time_tags.json b/workspace/perspective_library/niche/time_tags.json similarity index 99% rename from workspace/perspective_library/time_tags.json rename to workspace/perspective_library/niche/time_tags.json index accce702..d24bca34 100644 --- a/workspace/perspective_library/time_tags.json +++ b/workspace/perspective_library/niche/time_tags.json @@ -58,7 +58,7 @@ ], "context_template": "\nPeriod: {time_period_tags}\nCategory: {temporal_category}\nQualities: {time_quality_tags}\n\n", - "module": "focused", + "module": "niche", "type": "perspective", "tags": ["time", "tagging", "classification", "historical", "periods"], "description": "A tagging-focused perspective that categorizes images based on time periods, temporal indicators, and time-related qualities for easier image classification.", diff --git a/workspace/perspective_library/video/README.md b/workspace/perspective_library/video/README.md new file mode 100644 index 00000000..dba3600e --- /dev/null +++ b/workspace/perspective_library/video/README.md @@ -0,0 +1,62 @@ +# Video Perspectives Module + +## Overview + +The Video Perspectives module contains specialized perspectives designed to transform static images into rich, dynamic prompts for video generation. Unlike traditional image captioning, these perspectives focus on identifying and enhancing motion potential, temporal progression, and cinematic elements that can effectively guide the generation of video content from still images. + +These perspectives are particularly valuable for: + +- Creating high-quality prompts for text-to-video and image-to-video generation models +- Developing storyboards and narrative sequences from single images +- Extracting dynamic elements from static visuals +- Enhancing creative workflows for filmmakers, animators, and content creators +- Building datasets that bridge still imagery with video content + +## Video Perspectives + +| Perspective | Description | Primary Focus | Use Cases | +|-------------|-------------|--------------|-----------| +| **Image to Video Prompt** | Generates dense, visually rich captions optimized for video generation with emphasis on action, depth, and cinematography. | Comprehensive video prompt generation | Video generation from images, motion prompt datasets | +| **Image-to-Storyboard (2-Beat)** | Creates a two-beat narrative progression based on a static image, with clear transitions between moments. | Two-stage narrative progression | Simple storyboarding, before/after sequences, transition datasets | +| **Image-to-Storyboard (3-Beat)** | Builds a three-beat narrative sequence with beginning, middle, and end progression. | Three-stage narrative progression | Complete narrative arcs, sequential storytelling datasets | +| **Image to Video with Custom Instructions** | Integrates user instructions with image analysis to create tailored video generation prompts. | Customized video prompt generation | Guided video creation, specialized motion datasets | + +## The Value of Dynamic Interpretation + +While still images capture a single moment in time, effective video generation requires understanding: + +1. **Implied Motion**: What movements are suggested by the static elements? +2. **Narrative Progression**: How might the scene develop over time? +3. **Cinematic Language**: What camera movements and transitions would enhance the visual storytelling? +4. **Temporal Context**: What came before this moment, and what might follow? + +The perspectives in this module systematically extract and enhance these dynamic elements, creating structured outputs that serve as bridges between static and temporal media. + +## Dataset Applications + +These video perspectives are particularly valuable for dataset creation in several contexts: + +### Video Generation Training + +These perspectives create ideal training pairs that link static images with rich prompts specifically optimized for video generation models. This bridges the gap between image and video domains. + +### Storyboarding Datasets + +For applications focused on sequential visual storytelling, these perspectives generate structured narrative progressions with clear beats and transitions that can be used to train storyboarding or sequential image generation models. + +### Cinematic Education + +In educational contexts, these perspectives help illustrate how static compositions imply motion and how to effectively translate visual elements into cinematic language. + +### Motion Prompt Engineering + +By systematically breaking down the elements that contribute to effective motion description, these perspectives help build datasets for researching and improving prompt engineering for video generation. + +## Integration Guidelines + +When using video perspectives for dataset creation: + +1. Pair with traditional image captions to create multi-modal training examples +2. Consider using different beat-count perspectives for varying complexity levels +3. Use the structured fields to train specialized video generation aspects (e.g., just camera movements) +4. For instruction-tuned video models, the custom instruction perspective provides valuable paired examples diff --git a/workspace/perspective_library/video/instruct_i2video.json b/workspace/perspective_library/video/instruct_i2video.json new file mode 100644 index 00000000..d0ceaed1 --- /dev/null +++ b/workspace/perspective_library/video/instruct_i2video.json @@ -0,0 +1,85 @@ +{ + "name": "instruct_i2video", + "display_name": "Image to Video with Custom Instructions", + "version": "1", + "prompt": "Analyze the image and extract key visual elements. Then, integrate the provided custom instructions into the video generation prompt to enhance relevance and specificity. The final caption should be concise (one to two sentences) yet highly descriptive, incorporating:\n\n1. **Core Scene**: Identify the main subject and setting with dynamic potential (e.g., action, transformation, movement).\n\n2. **Subject Details**: Describe key visual traits of the subject(s), including clothing, physical features, and expressions.\n\n3. **Environmental Layers**: Capture foreground, midground, and background details to ensure depth and spatial clarity.\n\n4. **Action Sequence**: Define the subject's movement or events in a way that emphasizes realistic physics, momentum, or cinematic flow.\n\n5. **Mood & Atmosphere**: Establish the tone using descriptive words that evoke emotions (e.g., 'ominous storm brewing,' 'serene sunset glow').\n\n6. **Artistic Style & Cinematography**: Specify the visual aesthetic (e.g., 'photorealistic cyberpunk city with neon reflections') and include relevant camera directions (e.g., 'dynamic tracking shot from below').\n\nThe final caption must seamlessly **merge insights from the custom instructions** with the image analysis, ensuring a **natural, engaging, and highly optimized** prompt for video generation.", + "schema_fields": [ + { + "name": "image_analysis", + "type": "str", + "description": "A breakdown of key visual elements in the image, including main subjects, setting, and composition.", + "is_list": false + }, + { + "name": "instruction_integration", + "type": "str", + "description": "A structured plan for incorporating the custom instructions into the video prompt while preserving coherence.", + "is_list": false + }, + { + "name": "core_scene", + "type": "str", + "description": "A brief but clear definition of the main subject and setting, ensuring visual dynamism.", + "is_list": false + }, + { + "name": "subject_details", + "type": "str", + "description": "Distinctive features of the subject, including appearance, attire, posture, or expressions.", + "is_list": false + }, + { + "name": "environmental_layers", + "type": "str", + "description": "Layered description of foreground, midground, and background to establish depth.", + "is_list": false + }, + { + "name": "action_sequence", + "type": "str", + "description": "Specific, dynamic movements or events occurring in the scene.", + "is_list": false + }, + { + "name": "mood_and_atmosphere", + "type": "str", + "description": "Descriptive elements that establish the emotional tone and ambiance.", + "is_list": false + }, + { + "name": "artistic_style", + "type": "str", + "description": "The visual style and cinematographic choices, such as lighting, color schemes, and perspective.", + "is_list": false + }, + { + "name": "camera_directions", + "type": "str", + "description": "Optional cinematic techniques like tracking shots, zooms, or slow-motion effects.", + "is_list": false + }, + { + "name": "final_caption", + "type": "str", + "description": "A refined, short, yet highly descriptive video caption integrating both the image analysis and custom instructions.", + "is_list": false + } + ], + "table_columns": [ + { + "name": "Component", + "style": "cyan" + }, + { + "name": "Description", + "style": "green" + } + ], + "context_template": "\n{final_caption}\n", + "module": "creative", + "type": "perspective", + "tags": ["video", "caption", "video_generation", "custom_integration"], + "description": "A perspective that generates a high-quality, dense video caption by analyzing an image and incorporating custom user instructions.", + "deprecated": false, + "priority": 50 +} From 99f810741a059c501c4951a05ec827ddcb81a858 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 10:13:26 -0500 Subject: [PATCH 21/24] Resolve critical lints Signed-off-by: jphillips --- .../src/features/perspectives/services/api.ts | 28 +++-- .../features/perspectives/services/utils.ts | 108 ++++++++++-------- .../server/server/utils/resizing.py | 7 +- 3 files changed, 81 insertions(+), 62 deletions(-) diff --git a/graphcap_studio/src/features/perspectives/services/api.ts b/graphcap_studio/src/features/perspectives/services/api.ts index 114bee62..4f86ae88 100644 --- a/graphcap_studio/src/features/perspectives/services/api.ts +++ b/graphcap_studio/src/features/perspectives/services/api.ts @@ -7,17 +7,19 @@ import { API_ENDPOINTS } from "../constants/index"; import { - CaptionRequest, CaptionRequestSchema, - CaptionResponse, CaptionResponseSchema, - ModuleListResponse, ModuleListResponseSchema, - ModulePerspectivesResponse, ModulePerspectivesResponseSchema, - Perspective, PerspectiveListResponseSchema, } from "../types"; +import type { + CaptionRequest, + CaptionResponse, + ModuleListResponse, + ModulePerspectivesResponse, + Perspective, +} from "../types"; import { ensureWorkspacePath, getGraphCapServerUrl, handleApiError } from "./utils"; /** @@ -138,22 +140,26 @@ export const perspectivesApi = { if (!response.ok) { // Check if we got HTML instead of JSON const contentType = response.headers.get("content-type"); - if (contentType && contentType.includes("text/html")) { - throw new Error(`Received HTML response instead of JSON. Status: ${response.status}. This typically indicates a routing issue or server error.`); + if (contentType?.includes("text/html")) { + throw new Error( + `Received HTML response instead of JSON. Status: ${response.status}. This typically indicates a routing issue or server error.`, + ); } - + await handleApiError(response, `Failed to fetch perspectives for module '${moduleName}'`); } // Check content type before parsing const contentType = response.headers.get("content-type"); - if (!contentType || !contentType.includes("application/json")) { + if (!contentType?.includes("application/json")) { console.error(`Unexpected content type: ${contentType}`); - throw new Error(`Expected JSON response but got ${contentType || "unknown content type"}`); + throw new Error( + `Expected JSON response but got ${contentType ?? "unknown content type"}`, + ); } const data = await response.json(); - + // Use looser validation to handle the complex fields // We'll validate but ignore validation errors to allow the data through try { diff --git a/graphcap_studio/src/features/perspectives/services/utils.ts b/graphcap_studio/src/features/perspectives/services/utils.ts index 46884f4d..ca78209b 100644 --- a/graphcap_studio/src/features/perspectives/services/utils.ts +++ b/graphcap_studio/src/features/perspectives/services/utils.ts @@ -6,7 +6,7 @@ */ import { DEFAULTS } from "@/features/perspectives/constants/index"; -import { ServerConnection } from "@/features/perspectives/types"; +import type { ServerConnection } from "@/features/perspectives/types"; import { SERVER_IDS } from "@/features/server-connections/constants"; /** @@ -18,14 +18,15 @@ export function getGraphCapServerUrl(connections: ServerConnection[]): string { ); // Get URL from connection, environment variable, or default - const serverUrl = graphcapServerConnection?.url || - import.meta.env.VITE_GRAPHCAP_SERVER_URL || - import.meta.env.VITE_API_URL || + const serverUrl = + graphcapServerConnection?.url ?? + import.meta.env.VITE_GRAPHCAP_SERVER_URL ?? + import.meta.env.VITE_API_URL ?? DEFAULTS.SERVER_URL; - + // Log the server URL being used for debugging console.debug(`Using GraphCap server URL: ${serverUrl}`); - + return serverUrl; } @@ -57,6 +58,39 @@ export function isUrl(path: string): boolean { return path.startsWith("http://") || path.startsWith("https://"); } +/** + * Parse JSON error data into a readable error message + */ +function parseJsonErrorData(errorData: Record): { + message: string; + details: Record; +} { + let message = ""; + + // FastAPI error format + if (errorData.detail) { + if (typeof errorData.detail === "string") { + message = errorData.detail; + } else if (Array.isArray(errorData.detail)) { + // Handle validation errors + message = errorData.detail + .map( + (err: { loc: string[]; msg: string }) => + `${err.loc.join(".")}: ${err.msg}`, + ) + .join(", "); + } else { + message = JSON.stringify(errorData.detail); + } + } else if (errorData.message && typeof errorData.message === "string") { + message = errorData.message; + } else { + message = JSON.stringify(errorData); + } + + return { message, details: errorData }; +} + /** * Handle API error responses */ @@ -65,46 +99,25 @@ export async function handleApiError( defaultMessage: string, ): Promise { let errorMessage = `${defaultMessage}: ${response.status}`; - let errorDetails = null; + let errorDetails: Record | null = null; try { - const contentType = response.headers.get("content-type") || ""; + const contentType = response.headers.get("content-type") ?? ""; - // Handle different content types appropriately + // Handle response based on content type if (contentType.includes("application/json")) { - // JSON response - parse and extract error details const errorData = await response.json(); - - // FastAPI error format - if (errorData.detail) { - if (typeof errorData.detail === "string") { - errorMessage = errorData.detail; - } else if (Array.isArray(errorData.detail)) { - // Handle validation errors - errorMessage = errorData.detail - .map((err: any) => `${err.loc.join(".")}: ${err.msg}`) - .join(", "); - } else { - errorMessage = JSON.stringify(errorData.detail); - } - errorDetails = errorData; - } else if (errorData.message) { - errorMessage = errorData.message; - errorDetails = errorData; - } else { - errorMessage = JSON.stringify(errorData); - errorDetails = errorData; - } + const parsedError = parseJsonErrorData(errorData); + errorMessage = parsedError.message; + errorDetails = parsedError.details; } else if (contentType.includes("text/html")) { - // HTML response - likely a server error page or redirect const textError = await response.text(); - // Extract just a small portion to avoid huge error messages - const excerpt = textError.substring(0, 200) + (textError.length > 200 ? "..." : ""); + const excerpt = + textError.substring(0, 200) + (textError.length > 200 ? "..." : ""); errorMessage = `${defaultMessage}: Received HTML response (Status: ${response.status})`; errorDetails = { htmlExcerpt: excerpt }; console.warn("Received HTML response instead of expected JSON:", excerpt); } else { - // Other content type - try to get text const textError = await response.text(); if (textError) { errorMessage = textError.substring(0, 500); // Limit size @@ -112,28 +125,29 @@ export async function handleApiError( } } } catch (e) { - // If we can't parse the error, use the status text console.error("Error parsing API error response", e); errorMessage = `${defaultMessage}: ${response.statusText} (Status: ${response.status})`; - errorDetails = { parseError: e instanceof Error ? e.message : "Unknown error" }; + errorDetails = { + parseError: e instanceof Error ? e.message : "Unknown error", + }; } - // Create a more informative error - console.error(`API Error: ${errorMessage}`, { - status: response.status, + // Log error details + console.error(`API Error: ${errorMessage}`, { + status: response.status, url: response.url, - details: errorDetails + details: errorDetails, }); - - // Create an error with additional properties - const error = new Error(errorMessage) as Error & { - status?: number; - details?: any; + + // Create and throw error with additional properties + const error = new Error(errorMessage) as Error & { + status?: number; + details?: Record | null; url?: string; }; error.status = response.status; error.details = errorDetails; error.url = response.url; - + throw error; } diff --git a/servers/inference_server/server/server/utils/resizing.py b/servers/inference_server/server/server/utils/resizing.py index 16378432..822779fb 100644 --- a/servers/inference_server/server/server/utils/resizing.py +++ b/servers/inference_server/server/server/utils/resizing.py @@ -6,10 +6,11 @@ and video resolutions while maintaining aspect ratio. """ -from loguru import logger from enum import Enum -from typing import Tuple, Union, Optional, Dict, Any from pathlib import Path +from typing import Any, Dict, Optional, Tuple, Union + +from loguru import logger try: from PIL import Image, ImageFile @@ -50,7 +51,6 @@ def resize_image( resolution: Union[ResolutionPreset, Tuple[int, int]], maintain_aspect_ratio: bool = True, upscale: bool = False, - output_format: Optional[str] = None, ) -> Image.Image: """ Resize an image to a target resolution while maintaining aspect ratio. @@ -60,7 +60,6 @@ def resize_image( resolution: Target resolution as ResolutionPreset enum or (width, height) tuple maintain_aspect_ratio: If True, preserve aspect ratio; if False, force to exact dimensions upscale: If True, allow upscaling of images smaller than target resolution - output_format: Output format (e.g., 'JPEG', 'PNG'). If None, uses input format. Returns: Resized PIL Image object From b2796d24bb5b73d45a2233ea780d6fcf3b8a0f72 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 11:54:49 -0500 Subject: [PATCH 22/24] Merge module and filter action panels Signed-off-by: jphillips --- .../PerspectiveManagementPanel.tsx | 205 ++++++++++++------ .../PerspectiveModuleFilter.tsx | 167 ++++++++++++++ .../components/PerspectiveManagement/index.ts | 3 + 3 files changed, 303 insertions(+), 72 deletions(-) create mode 100644 graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModuleFilter.tsx diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx index f32497f1..b461064e 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveManagementPanel.tsx @@ -3,13 +3,23 @@ * Perspective Management Panel * * This component displays a panel for managing perspectives and modules + * using an accordion-based UI for better organization and toggleable options. */ import { LoadingSpinner } from "@/components/ui/status/LoadingSpinner"; -import { Box, Tabs } from "@chakra-ui/react"; -import { Link } from "@tanstack/react-router"; +import { useColorModeValue } from "@/components/ui/theme"; +import { + Box, + Flex, + Text, +} from "@chakra-ui/react"; +import { useEffect, useState } from "react"; +import { usePerspectivesData } from "../../context/PerspectivesDataContext"; import { usePerspectiveModules } from "../../hooks"; -import { PerspectiveFilterPanel } from "./PerspectiveFilterPanel"; +import { PerspectiveModuleFilter } from "./PerspectiveModuleFilter"; + +// Local storage key for accordion state +const ACCORDION_STATE_KEY = "graphcap-perspective-accordion-state"; /** * Panel component for perspective management @@ -17,13 +27,71 @@ import { PerspectiveFilterPanel } from "./PerspectiveFilterPanel"; export function PerspectiveManagementPanel() { // Use the perspective modules hook to get real data const { modules, isLoading, error, hasModules } = usePerspectiveModules(); + + // Get perspective visibility control from context + const { + isPerspectiveVisible, + togglePerspectiveVisibility, + hiddenPerspectives, + perspectives, + setAllPerspectivesVisible + } = usePerspectivesData(); + + // State to track which accordion panels are open + const [openPanels, setOpenPanels] = useState>({}); + + // Load accordion state on component mount + useEffect(() => { + try { + const savedState = localStorage.getItem(ACCORDION_STATE_KEY); + if (savedState) { + setOpenPanels(JSON.parse(savedState)); + } else if (modules.length > 0) { + // Default: open all panels + const initialState: Record = {}; + for (const module of modules) { + initialState[module.name] = true; + } + setOpenPanels(initialState); + } + } catch (error) { + console.error("Error loading accordion state:", error); + } + }, [modules]); + + // Save accordion state when it changes + useEffect(() => { + if (Object.keys(openPanels).length > 0) { + try { + localStorage.setItem(ACCORDION_STATE_KEY, JSON.stringify(openPanels)); + } catch (error) { + console.error("Error saving accordion state:", error); + } + } + }, [openPanels]); + + // Toggle accordion panel + const togglePanel = (moduleName: string) => { + setOpenPanels(prev => ({ + ...prev, + [moduleName]: !prev[moduleName] + })); + }; + + // Theme colors + const bgColor = useColorModeValue("white", "#1A202C"); + const textColor = useColorModeValue("gray.800", "white"); + const mutedTextColor = useColorModeValue("gray.500", "gray.400"); + const buttonBorderColor = useColorModeValue("blue.500", "blue.400"); + const buttonColor = useColorModeValue("blue.500", "blue.400"); + const buttonHoverBg = useColorModeValue("blue.50", "blue.900"); // Handle loading state if (isLoading) { return ( - + - Loading perspectives... + Loading perspectives... ); } @@ -31,81 +99,74 @@ export function PerspectiveManagementPanel() { // Handle error state if (error) { return ( - + Error loading perspectives: - {error.message} + {error.message} ); } - return ( - - - - Modules - Visibility - - + // Count visible perspectives + const totalPerspectives = perspectives.length; + const visibleCount = totalPerspectives - hiddenPerspectives.length; - - - - Perspective Modules - - {!hasModules ? ( - No perspectives found. - ) : ( - - {modules.map((module) => ( - - - {module.display_name} - - - - {module.perspectives?.map((perspective) => { - // Extract perspective ID from the full name - const perspectiveId = perspective.name.includes("/") - ? perspective.name.split("/").pop() ?? perspective.name - : perspective.name; - - return ( - - - {perspective.display_name} - - - ); - })} - - - ))} - - )} + return ( + + + Perspective Modules + + {visibleCount} of {totalPerspectives} visible + + + + {!hasModules ? ( + No perspectives found. + ) : ( + + + {modules.map((module) => ( + + ))} + + + {/* Show All button at the bottom */} + + + Show All - - - - - + - + )} ); } \ No newline at end of file diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModuleFilter.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModuleFilter.tsx new file mode 100644 index 00000000..e437ecbf --- /dev/null +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModuleFilter.tsx @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: Apache-2.0 +/** + * Perspective Module Filter + * + * This component displays a single module as an accordion item with checkboxes + * for toggling the visibility of perspectives within the module. + */ + +import { useColorModeValue } from "@/components/ui/theme/color-mode"; +import type { Perspective } from "@/features/perspectives/types"; +import { Box } from "@chakra-ui/react"; +import { Link } from "@tanstack/react-router"; + +type PerspectiveModuleFilterProps = { + readonly moduleName: string; + readonly displayName: string; + readonly perspectives: Perspective[]; + readonly isOpen: boolean; + readonly onTogglePanel: (moduleName: string) => void; + readonly isPerspectiveVisible: (perspectiveName: string) => boolean; + readonly togglePerspectiveVisibility: (perspectiveName: string) => void; +}; + +export function PerspectiveModuleFilter({ + moduleName, + displayName, + perspectives, + isOpen, + onTogglePanel, + isPerspectiveVisible, + togglePerspectiveVisibility, +}: PerspectiveModuleFilterProps) { + // Theme colors + const headerBgColor = useColorModeValue("gray.50", "#252E3F"); + const borderColor = useColorModeValue("gray.200", "#2D3748"); + const hoverBgColor = useColorModeValue("gray.100", "#2D3748"); + const textColor = useColorModeValue("gray.800", "white"); + const bgColor = useColorModeValue("white", "#1A202C"); + const mutedTextColor = useColorModeValue("gray.500", "gray.400"); + const checkboxActiveBg = useColorModeValue("blue.500", "blue.400"); + const checkboxBorderColor = useColorModeValue("gray.300", "gray.600"); + const itemHoverBg = useColorModeValue("gray.50", "#2A3749"); + + return ( + + onTogglePanel(moduleName)} + > + + {displayName} + + + ▼ + + + + {perspectives?.map((perspective) => { + // Extract perspective ID from the full name + const perspectiveId = perspective.name.includes("/") + ? perspective.name.split("/").pop() ?? perspective.name + : perspective.name; + + return ( + + + togglePerspectiveVisibility(perspective.name)} + style={{ display: "none" }} + /> + + {isPerspectiveVisible(perspective.name) && ( + + ✓ + + )} + + + + {perspective.display_name} + + + ); + })} + + + ); +} diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/index.ts b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/index.ts index 0bbe6f9d..2efe2459 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/index.ts +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/index.ts @@ -5,3 +5,6 @@ export { ErrorDisplay } from './ErrorDisplay'; export { LoadingDisplay } from './LoadingDisplay'; export { PerspectiveEditor } from './PerspectiveEditor/PerspectiveEditor'; export { SchemaValidationError } from './SchemaValidationError'; +export { PerspectiveModuleFilter } from './PerspectiveModuleFilter'; +export { PerspectiveManagementPanel } from './PerspectiveManagementPanel'; +export { PerspectiveFilterPanel } from './PerspectiveFilterPanel'; From a78354f3039bd0939cca7afe60ad175c7ea90fa8 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 12:04:21 -0500 Subject: [PATCH 23/24] Add quick module toggles Signed-off-by: jphillips --- .../PerspectiveModuleFilter.tsx | 183 +++++++++++++++--- 1 file changed, 154 insertions(+), 29 deletions(-) diff --git a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModuleFilter.tsx b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModuleFilter.tsx index e437ecbf..808298cc 100644 --- a/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModuleFilter.tsx +++ b/graphcap_studio/src/features/perspectives/components/PerspectiveManagement/PerspectiveModuleFilter.tsx @@ -8,8 +8,9 @@ import { useColorModeValue } from "@/components/ui/theme/color-mode"; import type { Perspective } from "@/features/perspectives/types"; -import { Box } from "@chakra-ui/react"; +import { Box, Flex } from "@chakra-ui/react"; import { Link } from "@tanstack/react-router"; +import { useMemo } from "react"; type PerspectiveModuleFilterProps = { readonly moduleName: string; @@ -40,6 +41,31 @@ export function PerspectiveModuleFilter({ const checkboxActiveBg = useColorModeValue("blue.500", "blue.400"); const checkboxBorderColor = useColorModeValue("gray.300", "gray.600"); const itemHoverBg = useColorModeValue("gray.50", "#2A3749"); + const buttonColor = useColorModeValue("blue.500", "blue.400"); + + // Compute the module's visibility state + const moduleVisibilityState = useMemo(() => { + if (!perspectives || perspectives.length === 0) return { checked: false, indeterminate: false }; + + const visibleCount = perspectives.filter(p => isPerspectiveVisible(p.name)).length; + + if (visibleCount === 0) return { checked: false, indeterminate: false }; + if (visibleCount === perspectives.length) return { checked: true, indeterminate: false }; + return { checked: false, indeterminate: true }; + }, [perspectives, isPerspectiveVisible]); + + // Toggle all perspectives in the module + const toggleAllPerspectives = () => { + // If all are visible or indeterminate, hide all; otherwise show all + const shouldShow = !moduleVisibilityState.checked && !moduleVisibilityState.indeterminate; + + for (const perspective of perspectives) { + // Only toggle if the current state doesn't match what we want + if (isPerspectiveVisible(perspective.name) !== shouldShow) { + togglePerspectiveVisibility(perspective.name); + } + } + }; return ( - onTogglePanel(moduleName)} > + {/* Module toggle checkbox */} + e.stopPropagation()} + > + + + {moduleVisibilityState.checked && ( + + ✓ + + )} + {moduleVisibilityState.indeterminate && ( + + )} + + + + {/* Accordion toggle button */} + onTogglePanel(moduleName)} + mr={2} + > + {displayName} + + ▼ + + + + {/* View module button */} - {displayName} + + → + - - ▼ - - + + {/* Checkbox for toggling visibility */} + + {/* Perspective name (not a link) */} + + {perspective.display_name} + + + {/* View perspective button */} - {perspective.display_name} + + → + - + ); })} From 760d9f7360b02aa17bbe1ad9f9b42be534bead84 Mon Sep 17 00:00:00 2001 From: jphillips Date: Wed, 19 Mar 2025 12:07:07 -0500 Subject: [PATCH 24/24] cleanup Signed-off-by: jphillips --- .cursor/rules/task.mdc | 171 +---------------------------------------- 1 file changed, 2 insertions(+), 169 deletions(-) diff --git a/.cursor/rules/task.mdc b/.cursor/rules/task.mdc index c1689c67..f3aefb0d 100644 --- a/.cursor/rules/task.mdc +++ b/.cursor/rules/task.mdc @@ -3,172 +3,5 @@ description: Current Task for the Agent globs: alwaysApply: true --- -### Is your feature request related to a problem? -Currently perspectives are loaded from a flat directory from files with minimal metadata. We should add support for perspective directories to be able to toggle on and off different modules. We should also allow support for loading and writing to perspectives in a certain instance to allow for prototyping without comitting new code. - -### Describe the solution you'd like -- Add directory loading of perspectives -- Add support for a local perspective directory -- Add additional metadata tags to perspective schema -- Add ability to add and edit perspectives to help with iteration -- Add route to ui for viewing, testing, and authoring new perspectives -- Add basic versioning ui -- Add graceful handling of deprecated / removed perspectives - -## Current State Analysis - -1. The `load_all_perspectives` function in `perspective_loader.py` already recursively searches for JSON files using `config_dir.rglob("*.json")`. -2. While it finds files in subdirectories, it doesn't appear to organize them in a hierarchical structure. -3. The loader attempts to load each JSON file as a perspective but doesn't handle modules or grouping. -4. The current implementation uses a flat dictionary to store perspectives by name. - -## Issues to Address - -1. The current code doesn't have a concept of perspective modules/groups. -2. There's no mechanism to toggle modules on/off. -3. No support for local perspective directory for prototyping. -4. Missing metadata for categorization and organization. -5. No versioning or handling of deprecated perspectives. - -## Implementation Plan - -### 1. Enhanced Perspective Metadata Structure - -We need to extend the `PerspectiveConfig` model to include: - -```python -class PerspectiveConfig(BaseModel): - """Configuration for a perspective loaded from JSON.""" - # Existing fields - name: str - display_name: str - version: str - prompt: str - schema_fields: List[SchemaField] - table_columns: List[Dict[str, str]] - context_template: str - - # New fields - module: str = Field(default="default", description="Module this perspective belongs to") - tags: List[str] = Field(default_factory=list, description="Tags for categorizing perspectives") - description: str = Field(default="", description="Detailed description of the perspective") - deprecated: bool = Field(default=False, description="Whether this perspective is deprecated") - replacement: Optional[str] = Field(default=None, description="Name of perspective that replaces this one") - priority: int = Field(default=100, description="Priority for sorting (lower is higher priority)") -``` - -### 2. Hierarchical Perspective Loading - -Create a new data structure to represent module-based perspectives: - -```python -class PerspectiveModule: - """Represents a module of related perspectives.""" - name: str - display_name: str - enabled: bool - perspectives: Dict[str, JsonPerspectiveProcessor] - - def toggle(self, enabled: bool) -> None: - """Toggle this module on or off.""" - self.enabled = enabled -``` - -Modify the perspective loader to organize perspectives by module: - -```python -def load_all_perspectives(config_dir: Union[str, Path]) -> Dict[str, PerspectiveModule]: - """Load perspectives organized by module.""" - # Implementation details -``` - -### 3. Local Perspective Directory Support - -Create a mechanism to support local perspectives alongside the main ones: - -```python -def get_perspective_directories() -> List[Path]: - """Get all directories where perspectives can be found.""" - dirs = [WORKSPACE_PERSPECTIVES_DIR] - - # Check for local perspective directory - local_dir = Path.home() / ".graphcap" / "perspectives" - if local_dir.exists(): - dirs.append(local_dir) - - return dirs -``` - -### 4. Configuration Update for Module Control - -Create a configuration file to control module enablement: - -```json -{ - "modules": { - "core": {"enabled": true}, - "experimental": {"enabled": false}, - "deprecated": {"enabled": false} - }, - "local_override": true -} -``` - -### 5. Testing Plan - -#### Unit Tests - -1. **Schema Loading Test**: Verify that perspectives with the new metadata fields load correctly. -2. **Module Structure Test**: Ensure perspectives are properly organized into modules. -3. **Directory Structure Test**: Test that the loader correctly handles nested directory structures. -4. **Local Override Test**: Verify that local perspectives can override workspace perspectives. -5. **Toggling Test**: Ensure that modules can be toggled on and off. - -#### Integration Tests - -1. **API Integration Test**: Test that the API correctly returns perspectives based on module enablement. -2. **UI Integration Test**: Test that the UI correctly displays perspectives organized by module. -3. **Versioning Test**: Test that versioning information is correctly displayed and used. - -#### Test Data Structure - -Create a test directory structure: -``` -test_perspectives/ -├── core/ -│ ├── base_caption.json -│ └── custom_caption.json -├── experimental/ -│ ├── new_technique.json -│ └── beta_feature.json -└── local/ - └── prototype_caption.json -``` - -## UI Component for Perspective Management - -Develop a React component for managing perspectives: -- Allow viewing all perspectives organized by module -- Enable toggling modules on/off -- Provide UI for testing perspectives -- Include version management interface -- Display deprecation warnings for deprecated perspectives - -## Implementation Steps - -1. Update the `PerspectiveConfig` model with new metadata fields -2. Implement the hierarchical perspective loading structure -3. Add local perspective directory support -4. Create configuration mechanism for module control -5. Implement tests for all new functionality -6. Develop UI components for perspective management -7. Add APIs for perspective CRUD operations - -## Potential Challenges - -1. **Backward Compatibility**: Ensure old perspectives still work with the new system -2. **Performance**: Loading many perspectives from nested directories might impact startup time -3. **Conflict Resolution**: Handle conflicts between workspace and local perspectives -4. **Schema Evolution**: Support for evolving perspective schemas across versions - -This plan addresses all the requirements in the task while maintaining compatibility with the existing codebase. The approach enhances the perspective loader to support modular organization, local development, versioning, and deprecation handling. +# Task +Insert the task for the agent. \ No newline at end of file

9`aB@V(y2+q>`NpMncN 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 z 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%0DB*DUkkWE$=qZ)@R;m;92F`<+X_t43Qd-8bPV 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