# Welcome to Plexe Source: https://docs.plexe.ai/pages/introduction/welcome Build ML models from natural language in minutes Plexe revolutionizes machine learning development by enabling you to create and deploy high-quality models using natural language instructions. Our intelligent agent system handles data preparation, code generation, training, and deployment—dramatically reducing the complexity of machine learning workflows. ## Plexe Ecosystem Open-source library for direct integration into your Python applications. Full control with maximum flexibility. Hosted solution with intuitive UI and REST API. Zero infrastructure management with built-in scaling. ### Choose Your Path **Python Library (`plexe`)** * Integrate directly with Python code via `pip install plexe` * Control your own compute resources and data * Bring your preferred LLM provider credentials * Ideal for: developers, data scientists, ML engineers **Plexe Platform (`console.plexe.ai` / `api.plexe.ai`)** * Access via web interface or REST API * Let us manage infrastructure, scaling, and deployments * Simplified authentication and billing * Ideal for: product teams, analysts, organizations seeking enterprise-grade ML ## How It Works Plexe's multi-agent system powered by Large Language Models works through a sequential process: 1. **Planning:** Analyzes your intent and data to develop a model-building strategy 2. **Code Generation:** Creates appropriate ML code using popular libraries (scikit-learn, PyTorch, TensorFlow) 3. **Execution & Refinement:** Runs the generated code, evaluates results, and iteratively improves performance 4. **Deployment:** Packages the model for inference or deploys it to production infrastructure ## Key Benefits * **Natural Language Interface:** Describe what you want, not how to build it * **Rapid Iteration:** Test ideas and create models in minutes instead of days * **No ML Expertise Required:** Leverage state-of-the-art ML without specialized knowledge * **Production-Ready Code:** Generate clean, documented, and maintainable ML workflows * **Full Transparency:** Examine and customize all generated code Ready to start building? Choose your preferred approach: * [**Python Library Quickstart**](/library/tutorials/quickstart) * [**Platform API Quickstart**](/platform/tutorials/quickstart_api) # Callbacks and Logging Source: https://docs.plexe.ai/pages/library/explanation/callbacks_logging Monitor and interact with the Plexe model building process through callbacks and logging. Plexe provides robust capabilities for monitoring and interacting with the model building process through its callback system and logging features. These tools give you visibility into what's happening during model creation and allow you to integrate with external systems. ## The Callback System Callbacks in Plexe let you hook into key points in the model building lifecycle. They're useful for: * Logging progress and results * Integrating with experiment tracking systems * Implementing custom monitoring solutions * Saving artifacts * Event triggering for workflows ### Callback Lifecycle Events The `Callback` base class defines four key methods that are triggered at different points: 1. **`on_build_start(info)`**: Called once when `model.build()` begins 2. **`on_iteration_start(info)`**: Called at the start of each build iteration 3. **`on_iteration_end(info)`**: Called at the end of each build iteration 4. **`on_build_end(info)`**: Called once when the entire build process completes The `info` parameter provides context about the current state, including: * The model's intent and configuration * The current iteration number * The datasets being used * Current schemas * Performance metrics (in `on_iteration_end`) ### Built-in Callbacks #### Chain of Thought Callback This callback is automatically added when you set `chain_of_thought=True` in `model.build()`. It captures the detailed reasoning steps and decision-making process of the AI agents. ```python import plexe model = plexe.Model(intent="Predict customer churn") model.build( datasets=[df], chain_of_thought=True # Enables verbose output ) ``` The output shows the step-by-step thought process of the agents, including: * Problem analysis * Solution planning * Code development * Debugging * Evaluation #### MLflow Callback This integrates with MLflow, a popular platform for tracking ML experiments: ```python import plexe from plexe.callbacks import MLFlowCallback # Set up MLflow callback mlflow_callback = MLFlowCallback( tracking_uri="http://localhost:5000", experiment_name="Customer Churn Models" ) # Build model with MLflow tracking model = plexe.Model(intent="Predict customer churn") model.build( datasets=[df], callbacks=[mlflow_callback] ) ``` The MLflow callback: * Creates runs for each iteration * Logs parameters (intent, provider, iteration number) * Records metrics (accuracy, RMSE, etc.) * Saves artifacts (code, model files) * Tags runs with relevant metadata ### Creating Custom Callbacks You can create your own callbacks by subclassing `Callback`: ```python import plexe from plexe.callbacks import Callback import time class TimingCallback(Callback): def __init__(self): self.start_time = None self.iteration_times = {} def on_build_start(self, info): self.start_time = time.time() print(f"Build started for model with intent: {info.intent[:50]}...") def on_iteration_start(self, info): iteration = info.iteration self.iteration_times[iteration] = time.time() print(f"Starting iteration {iteration + 1}") def on_iteration_end(self, info): iteration = info.iteration duration = time.time() - self.iteration_times[iteration] print(f"Iteration {iteration + 1} completed in {duration:.2f} seconds") # Check for metrics if available if hasattr(info, "node") and info.node and hasattr(info.node, "performance"): perf = info.node.performance if perf: print(f" Performance: {perf.name} = {perf.value:.4f}") def on_build_end(self, info): total_time = time.time() - self.start_time print(f"Build finished in {total_time:.2f} seconds") if hasattr(info, "model"): print(f"Final model state: {info.model.get_state()}") ``` Usage: ```python # Create and use the custom callback timing_callback = TimingCallback() model.build(datasets=[df], callbacks=[timing_callback]) ``` ## Logging System In addition to callbacks, Plexe has a built-in logging system for observing the inner workings of the library. ### Configuring Logging You can configure Plexe's logging system to adjust verbosity: ```python import plexe import logging # Set up logging with desired verbosity plexe.configure_logging(level=logging.DEBUG) ``` For more control over logging format: ```python import logging from plexe.config import configure_logging # Create a custom handler handler = logging.StreamHandler() handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) # Configure with more options configure_logging( level=logging.INFO, file="plexe_build.log" # Optional: also log to a file ) ``` ### Logging Levels * **DEBUG**: Very detailed information, useful for diagnosing problems * **INFO**: Confirmation that things are working as expected * **WARNING**: Indication of potential issues * **ERROR**: Serious problems that prevented operations * **CRITICAL**: Very serious errors ### Log Output Destinations By default, Plexe logs to the console (stdout), but you can redirect logs: ```python import logging from plexe.config import configure_logging # Configure Plexe logging to a file configure_logging( level=logging.DEBUG, file="plexe_build.log" # Will create a file handler automatically ) ``` ## Integrating Callbacks and Logging For comprehensive monitoring, combine callbacks and logging: ```python import plexe import logging from plexe.callbacks import MLFlowCallback # Set up logging plexe.configure_logging(level=logging.INFO) # Set up MLflow callback mlflow_callback = MLFlowCallback( tracking_uri="http://localhost:5000", experiment_name="Customer Churn Models" ) # Create custom callback timing_callback = TimingCallback() # Build with both systems model = plexe.Model(intent="Predict customer churn") model.build( datasets=[df], callbacks=[mlflow_callback, timing_callback], chain_of_thought=True # Also get agent reasoning steps ) ``` This approach gives you: 1. Standard logging for library operations 2. MLflow integration for experiment tracking 3. Custom timing logs for performance monitoring 4. Detailed agent reasoning via chain-of-thought ## Best Practices 1. **Start Simple**: Begin with `chain_of_thought=True` to see what's happening 2. **Use Callbacks for Integration**: Connect Plexe to your existing ML infrastructure 3. **Create Custom Callbacks**: Build callbacks tailored to your workflow needs 4. **Adjust Log Levels**: Set appropriate verbosity based on your needs 5. **Combine Approaches**: Use both logging and callbacks for comprehensive monitoring By leveraging Plexe's callback system and logging capabilities, you can gain insights into the model building process, track experiments systematically, and integrate Plexe into your broader ML workflows. # Core Concepts Source: https://docs.plexe.ai/pages/library/explanation/concepts Understand the fundamental concepts behind the Plexe Python library. The Plexe Python library (`plexe`) provides a powerful way to build machine learning models using natural language. Understanding these core concepts will help you use it effectively. ## Model (`plexe.Model`) This is the central class you interact with. A `Model` object represents a machine learning task and, once built, the resulting trained model. * **Initialization:** You create a `Model` by specifying its `intent` and optionally its `input_schema`, `output_schema`, and `constraints`. * **State:** A `Model` progresses through states: `DRAFT` (initial), `BUILDING` (during `build()` call), `READY` (successfully built), `ERROR` (build failed). * **Building:** The `build()` method triggers the agentic workflow to generate, train, and evaluate the model based on the intent and provided data. * **Prediction:** The `predict()` method uses the trained model (once `READY`) to make predictions on new data. * **Persistence:** `save_model()` and `load_model()` allow you to store and retrieve trained models. ## Intent The `intent` is a natural language string describing *what* you want the machine learning model to do. It's the primary instruction given to the Plexe agent system. * **Example:** `"Predict the likelihood of customer churn based on their recent activity and subscription plan."` * **Clarity is Key:** A clear and specific intent leads to better model planning and results. Include context about the goal, inputs, and outputs if possible. ## Schemas (`input_schema`, `output_schema`) Schemas define the structure and data types of the model's expected inputs and outputs. * **Purpose:** They ensure data consistency and help the agents understand the data format. * **Formats:** Can be provided as Pydantic models (recommended) or Python dictionaries. * **Inference:** If not provided, Plexe attempts to infer schemas from the `datasets` supplied during the `build` call, using LLM analysis to identify the likely target variable(s). Explicitly defining schemas is often more reliable. ## Build Process (`model.build()`) This method orchestrates the core model creation workflow. * **Inputs:** Requires `datasets` (list of Pandas DataFrames or `DatasetGenerator` objects) and a `provider` configuration (LLM to use). Optional arguments include `max_iterations`, `timeout`, `callbacks`, etc. * **Agent System (`PlexeAgent`):** Internally, `build` invokes a multi-agent system (`PlexeAgent`) comprising specialized roles: * **Orchestrator:** Manages the overall workflow, delegating tasks. * **ML Researcher:** Analyzes the problem, proposes solution plans. * **ML Engineer:** Writes and refines the model training code based on the plan. * **ML Ops Engineer:** Generates the inference code for the final model. * **(Tool Agents):** Smaller, specialized agents perform tasks like metric selection, schema inference, code validation, and execution using defined "tools". * **Iteration:** The system may try multiple approaches (`max_iterations`) to find the best model according to the selected performance metric. Each attempt involves planning, code generation, execution, and evaluation. * **Output:** Updates the `Model` object's state (`READY` or `ERROR`), populates its `predictor`, `metric`, `metadata`, `artifacts`, and source code attributes. ## Provider (`provider`, `ProviderConfig`) Specifies the Large Language Model(s) (LLMs) used by the agent system. * **Simple String:** `"openai/gpt-4o-mini"` or `"anthropic/claude-3-haiku-20240307"`. Uses this model for most agent tasks. * **`ProviderConfig` Object:** Allows assigning different models to different agent roles (Orchestrator, Researcher, Engineer, Ops, Tool) for fine-grained control over cost and capability. * **Dependencies:** Relies on [LiteLLM](https://docs.litellm.ai/docs/) for multi-provider support. Requires appropriate API keys set as environment variables. ## Datasets (`datasets`, `DatasetGenerator`) Data used for training and evaluation. * **Input:** Pass data to `model.build()` as a list containing Pandas DataFrames. * **`DatasetGenerator`:** A class (`plexe.DatasetGenerator`) can be used to define requirements for a dataset, including generating synthetic data based on a schema or augmenting existing data using an LLM provider. Pass instances of this class in the `datasets` list if needed. ## Callbacks (`plexe.Callback`, `MLFlowCallback`) Classes that allow you to hook into the `build()` process lifecycle (`on_build_start`, `on_iteration_start`, `on_iteration_end`, `on_build_end`). * **Purpose:** Used for logging, monitoring, custom artifact handling, etc. * **Built-in:** Includes `MLFlowCallback` for easy integration with MLflow tracking. The `ChainOfThoughtModelCallback` provides verbose agent step logging when `chain_of_thought=True` is set in `build()`. * **Custom:** You can create your own callbacks by inheriting from `plexe.Callback`. ## Constraints (`plexe.Constraint`) Represents rules or conditions that a model's input/output pairs should satisfy. Constraints enable you to specify business rules and validation criteria for your model's behavior. * **Definition:** Create constraints with a `condition` function that takes input and output data and returns a boolean * **Composability:** Combine constraints using logical operators (`&` for AND, `|` for OR, `~` for NOT) * **Usage Example:** ```python # Constraint ensuring price predictions are positive positive_price = Constraint( condition=lambda inputs, outputs: outputs["price"] > 0, description="Predicted prices must be positive" ) # Constraint requiring predictions to have a confidence value has_confidence = Constraint( condition=lambda inputs, outputs: "confidence" in outputs, description="Predictions must include a confidence score" ) # Combined constraint valid_model = positive_price & has_confidence # Apply constraints when creating a model model = Model(intent="...", constraints=[valid_model]) ``` # Datasets and Schemas Source: https://docs.plexe.ai/pages/library/explanation/datasets_schemas How Plexe handles data inputs and defines the structure of ML models. In Plexe, datasets and schemas work together to define what data your model consumes and what outputs it produces. Understanding how these components interact is key to creating effective models. ## Datasets Datasets provide the training data for your models. Plexe offers flexible options for working with data: ### Pandas DataFrames The most common way to provide data to Plexe is through Pandas DataFrames, which offer a tabular structure that's ideal for machine learning: ```python import pandas as pd import plexe # Load data into a DataFrame df = pd.read_csv("customer_data.csv") # Create a model and build it with the DataFrame model = plexe.Model(intent="Predict customer churn") model.build(datasets=[df]) ``` When using DataFrames: * Plexe works with one or more DataFrames (pass them as a list) * It automatically analyzes columns to understand data types and identify potential targets * For multiple DataFrames, Plexe can detect relationships between them based on column names and data ### DatasetGenerator For cases where you have limited or no existing data, you can use the `DatasetGenerator` class to create synthetic training data: ```python from plexe import DatasetGenerator from pydantic import BaseModel # Define schema for synthetic data class CustomerData(BaseModel): age: int subscription_months: int monthly_spend: float churn: bool # Create a generator for synthetic data generator = DatasetGenerator( description="Generate customer data with churn information", provider="openai/gpt-4o-mini", # Specify LLM provider for generation schema=CustomerData ) # Generate data (specify number of samples) generator.generate(num_samples=100) # Use the generator when building the model model = plexe.Model(intent="Predict customer churn") model.build(datasets=[generator]) ``` The `DatasetGenerator`: * Creates realistic synthetic data based on the schema and description * Requires a provider specification for the LLM that will generate the data * Can augment existing data by passing an existing DataFrame in the constructor * Explicitly generates samples with the `generate()` method before model building ## Schemas Schemas define the structure and validation rules for inputs and outputs of your model. Plexe supports two ways to define schemas: ### Dictionary-Based Schemas The simplest way to define schemas is with Python dictionaries mapping field names to types: ```python import plexe # Create a model with dictionary schemas model = plexe.Model( intent="Predict house prices", input_schema={ "square_footage": float, "bedrooms": int, "bathrooms": float, "location": str }, output_schema={ "price": float } ) ``` Dictionary schemas: * Are intuitive and quick to define * Support basic Python types (`int`, `float`, `str`, `bool`) * Are automatically converted to Pydantic models internally ### Pydantic Models For more complex schemas with validation rules, descriptions, or nested structures, Pydantic models provide greater flexibility: ```python import plexe from pydantic import BaseModel, Field from typing import List, Optional # Define input schema class PropertyFeatures(BaseModel): square_footage: float = Field(description="Total area in square feet", gt=0) bedrooms: int = Field(description="Number of bedrooms", ge=0) bathrooms: float = Field(description="Number of bathrooms (e.g., 2.5)", ge=0) location: str = Field(description="Neighborhood or area") amenities: Optional[List[str]] = Field(default=None, description="List of property amenities") # Define output schema class PricePrediction(BaseModel): price: float = Field(description="Predicted sale price in USD", gt=0) confidence: Optional[float] = Field(default=None, description="Prediction confidence score (0-1)") # Create model with Pydantic schemas model = plexe.Model( intent="Predict house prices based on property features", input_schema=PropertyFeatures, output_schema=PricePrediction ) ``` Pydantic schemas: * Provide rich validation (min/max values, regex patterns, etc.) * Support field descriptions that help the ML Engineer agent understand the data * Handle complex nested structures and optional fields * Enable detailed documentation ## Schema Inference If you don't provide explicit schemas but do provide datasets, Plexe will attempt to infer the schemas: ```python import pandas as pd import plexe # Load data df = pd.read_csv("housing_data.csv") # Create model without schemas model = plexe.Model(intent="Predict house prices based on property features") # Build with data - schemas will be inferred model.build(datasets=[df]) # Access the inferred schemas print("Inferred input schema:", model.input_schema) print("Inferred output schema:", model.output_schema) ``` During schema inference: 1. Plexe analyzes the DataFrame columns to determine types 2. It uses the model intent and column names to identify likely target variables 3. Input features and output targets are separated based on this analysis ## How Plexe Uses Schemas and Datasets Internally When you call `model.build()`: 1. **Schema Analysis**: Plexe examines the provided schemas (or infers them) to understand the data structure 2. **Data Exploration**: The ML agent explores the datasets to understand patterns, distributions, and relationships 3. **Feature Engineering**: The agent determines which transformations or feature engineering steps are needed 4. **Model Selection**: Based on the schemas and data, the agent selects appropriate ML algorithms 5. **Training**: The model is trained on the provided data 6. **Validation**: Plexe ensures the trained model adheres to the output schema ## Best Practices * **Provide Explicit Schemas** when possible for clarity and more accurate model building * **Use Descriptive Field Names** that clearly communicate the meaning of each field * **Add Field Descriptions** in Pydantic models to guide the ML agent * **Clean Your Data** before passing to Plexe for better results * **Ensure Representative Data** to help Plexe build more accurate models # LLM Providers Source: https://docs.plexe.ai/pages/library/explanation/providers Understanding the role of LLM providers in the Plexe Python library. The Plexe Python library uses Large Language Models (LLMs) as the foundation for its AI agent system. These models power the planning, code generation, analysis, and refinement capabilities that enable Plexe to build ML models from natural language. ## Supported Provider Types Plexe supports various LLM providers through integration with common APIs, giving you flexibility in choosing which models to use for different aspects of the model building process. ### Standard Providers These are the primary LLM providers supported by Plexe: * **OpenAI**: Models like GPT-4o, GPT-4o-mini * **Anthropic**: Claude models (Haiku, Sonnet, Opus) * **Google**: Gemini models * **Cohere**: Command models * **Local Models**: Through providers like Ollama for self-hosting ## Provider Formats When specifying a provider, use the format `"vendor/model_name"`: ```python # OpenAI example model.build(datasets=datasets, provider="openai/gpt-4o-mini") # Anthropic example model.build(datasets=datasets, provider="anthropic/claude-3-sonnet-20240229") # Ollama (local) example model.build(datasets=datasets, provider="ollama/llama3") ``` ## Provider Configuration ### Default Provider If you don't specify a provider, Plexe uses a default provider optimized for model building tasks. ### Custom Provider Configuration For more advanced use cases, Plexe allows setting different LLM providers for different agent roles through the `ProviderConfig` class. This lets you optimize for performance in critical stages like code writing while using faster/cheaper models for more routine tasks. ```python # Import ProviderConfig from internal module from plexe.internal.common.provider import ProviderConfig # Create a custom provider configuration provider_config = ProviderConfig( default_provider="openai/gpt-4o-mini", research_provider="openai/gpt-4o", # For complex planning engineer_provider="openai/gpt-4o", # For code generation orchestrator_provider="anthropic/claude-3-sonnet-20240229", ops_provider="anthropic/claude-3-sonnet-20240229", tool_provider="openai/gpt-4o-mini" # For internal tools/helpers ) # Use the custom configuration model.build(datasets=datasets, provider=provider_config) ``` ## Environment Variables for API Keys Plexe uses environment variables to securely handle API keys. Set the appropriate environment variable for your chosen provider: ```bash # OpenAI export OPENAI_API_KEY="your_openai_api_key" # Anthropic export ANTHROPIC_API_KEY="your_anthropic_api_key" # Google Gemini export GEMINI_API_KEY="your_gemini_api_key" ``` ## Provider Selection Strategies ### Cost Optimization If you're primarily concerned with minimizing costs: * Use more economical models like `"openai/gpt-4o-mini"` or similar for most roles * Reserve more powerful models only for the engineer role which handles code generation * Example: `provider_config = ProviderConfig(default_provider="openai/gpt-4o-mini", engineer_provider="openai/gpt-4o")` ### Performance Optimization If you prioritize quality and performance: * Use the most capable models for research and engineering roles * Example: `provider_config = ProviderConfig(default_provider="anthropic/claude-3-sonnet-20240229", research_provider="anthropic/claude-3-opus-20240229", engineer_provider="anthropic/claude-3-opus-20240229")` ### Private Deployment For organizations with data privacy requirements: * Configure with locally-hosted models through providers like Ollama * Example: `provider_config = ProviderConfig(default_provider="ollama/llama3")` ## Internal Provider Handling When you call `model.build()` with a provider configuration: 1. **Initialization**: Plexe validates the provider configuration 2. **Role Assignment**: Appropriate models are assigned to each agent based on the configuration 3. **API Integration**: Plexe handles the API calls to the various providers 4. **Fallbacks**: If a specific role provider fails, Plexe can fall back to the default provider By understanding how providers work in Plexe, you can optimize your model building process for your specific requirements, whether prioritizing cost efficiency, performance quality, or specialized capabilities. # Configure LLM Providers Source: https://docs.plexe.ai/pages/library/how-to/configure_llm_provider Specify which Large Language Model providers and models Plexe should use for its agent system. Plexe utilizes Large Language Models (LLMs) extensively through its agent system to perform tasks like planning, code generation, analysis, and schema inference. You can configure which LLM provider and model Plexe uses. ## Setting API Keys Before configuring providers, ensure the necessary API keys are set as environment variables. Plexe uses [LiteLLM](https://docs.litellm.ai/docs/providers) to connect to various providers. ```bash # Example for OpenAI export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" # Example for Anthropic export ANTHROPIC_API_KEY="YOUR_ANTHROPIC_API_KEY" # Example for Google Gemini export GEMINI_API_KEY="YOUR_GEMINI_API_KEY" # Example for Cohere export COHERE_API_KEY="YOUR_COHERE_API_KEY" # ... and so on for other providers supported by LiteLLM ``` ## Specifying the Provider in `model.build()` The `provider` argument in `model.build()` controls which LLM is used. ### Simple Provider String You can provide a single string in the format `"vendor/model_name"`. This model will be used for all agent tasks by default. ```python import plexe import pandas as pd # --- Prepare Data & Model --- # (Assume df and model are defined as in previous examples) try: df = pd.read_csv("housing_data.csv") except FileNotFoundError: df = pd.DataFrame({ # Dummy data 'square_footage': [1500, 2100, 1800, 2500, 1200], 'bedrooms': [3, 4, 3, 5, 2], 'bathrooms': [2, 2.5, 2, 3, 1.5], 'price': [300000, 450000, 380000, 550000, 250000] }) datasets = [df] model = plexe.Model(intent="Predict house prices") # -------------------------- # Use OpenAI's gpt-4o-mini (default if provider is omitted) model.build(datasets=datasets, provider="openai/gpt-4o-mini") # Use Anthropic's Claude 3 Sonnet # model.build(datasets=datasets, provider="anthropic/claude-3-sonnet-20240229") # Use Ollama's Llama 3 (requires Ollama server running) # model.build(datasets=datasets, provider="ollama/llama3") ``` Plexe defaults to `"openai/gpt-4o-mini"` if the `provider` argument is omitted. ### Using `ProviderConfig` for Granular Control For more advanced control, you can specify different models for different agent roles using the `ProviderConfig` class. This allows you to use potentially stronger models for complex tasks like planning or coding, and faster/cheaper models for simpler tasks like tool usage or review. The roles you can configure are: * `default_provider`: Fallback provider if a specific role isn't set. * `orchestrator_provider`: For the main agent managing the workflow. * `research_provider`: For the agent planning the ML solution. * `engineer_provider`: For the agent writing the training code. * `ops_provider`: For the agent writing the inference code. * `tool_provider`: For agents performing internal tool calls (like schema inference, metric selection). ```python import plexe import pandas as pd from plexe.internal.common.provider import ProviderConfig # Import the config class # --- Prepare Data & Model --- # (Assume df and model are defined as in previous examples) try: df = pd.read_csv("housing_data.csv") except FileNotFoundError: df = pd.DataFrame({ # Dummy data 'square_footage': [1500, 2100, 1800, 2500, 1200], 'bedrooms': [3, 4, 3, 5, 2], 'bathrooms': [2, 2.5, 2, 3, 1.5], 'price': [300000, 450000, 380000, 550000, 250000] }) datasets = [df] model = plexe.Model(intent="Predict house prices") # -------------------------- # Define a provider configuration # Use GPT-4o for core engineering/research, Claude Sonnet for orchestration/ops, GPT-4o-mini for tools provider_config = ProviderConfig( default_provider="openai/gpt-4o-mini", # Fallback orchestrator_provider="anthropic/claude-3-sonnet-20240229", research_provider="openai/gpt-4o", engineer_provider="openai/gpt-4o", ops_provider="anthropic/claude-3-sonnet-20240229", tool_provider="openai/gpt-4o-mini" ) # Build the model using the specific configuration model.build( datasets=datasets, provider=provider_config, # Pass the config object max_iterations=1 ) print(f"Model build finished using ProviderConfig. State: {model.get_state()}") # You can check which providers were actually used in the model metadata if model.get_state() == plexe.internal.common.utils.model_state.ModelState.READY: metadata = model.get_metadata() print("\nProviders Used:") print(f" Orchestrator: {metadata.get('orchestrator_provider')}") print(f" Research: {metadata.get('research_provider')}") print(f" Engineer: {metadata.get('engineer_provider')}") print(f" Ops: {metadata.get('ops_provider')}") print(f" Tool: {metadata.get('tool_provider')}") ``` {/* Info component with proper JSX syntax */} Using `ProviderConfig` allows optimizing for cost and capability by assigning different models to roles based on their complexity. Refer to your LLM provider's documentation for model identifiers and capabilities. # Installation Source: https://docs.plexe.ai/pages/library/how-to/install_plexe Learn how to install the Plexe Python library with different dependency sets. Install the `plexe` library using pip. Choose the installation method that best suits your needs. ## Standard Installation This installs the core `plexe` library along with common dependencies needed for most tasks, excluding large deep learning libraries. ```bash pip install plexe ``` This includes libraries like `pandas`, `scikit-learn`, `xgboost`, `litellm`, and `smolagents`. ## Lightweight Installation For minimal dependencies, suitable if you only need the basic structure or plan to install other dependencies manually. ```bash pip install plexe[lightweight] ``` This installs only the absolute minimum required packages to run the core agent logic, without data handling or specific ML libraries. Use this if you are managing dependencies tightly in a constrained environment. ## Installation with Deep Learning Support To include optional deep learning libraries like TensorFlow and PyTorch (CPU versions by default), use the `[all]` extra. This is needed if you expect Plexe to generate models using these frameworks. ```bash pip install plexe[all] ``` This installs everything in the standard installation plus `tensorflow-cpu` and `torch`. {/* Note component with proper JSX syntax */} If you require GPU support for TensorFlow or PyTorch, you will need to install the appropriate GPU-enabled versions separately *after* installing `plexe[all]`. Consult the official TensorFlow and PyTorch documentation for GPU installation instructions specific to your system and CUDA version. ## Verifying Installation After installation, you can verify it by importing `plexe` in a Python interpreter: ```python import plexe print(f"Plexe library imported successfully.") # You can also check the internal configuration for available packages from plexe.config import config print(f"Allowed packages: {config.code_generation.allowed_packages}") print(f"Deep learning available: {config.code_generation.deep_learning_available}") ``` ## Setting API Keys Remember to set the necessary API keys for your chosen LLM provider(s) as environment variables. ```bash export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" # or export ANTHROPIC_API_KEY="YOUR_ANTHROPIC_API_KEY" # etc. ``` Refer to the [LiteLLM Providers documentation](https://docs.litellm.ai/docs/providers) for the correct environment variable names. # Provide I/O Schemas Source: https://docs.plexe.ai/pages/library/how-to/provide_schemas Define the expected structure of your model inputs and outputs using Pydantic models or dictionaries. Specifying input and output schemas helps Plexe understand the data your model will work with and what it should produce. While Plexe can often infer schemas if you provide data during the `build` process, explicitly defining them provides clarity and ensures the generated model adheres to your requirements. You can provide schemas during `plexe.Model` initialization using either Pydantic models or Python dictionaries. ## Using Pydantic Models Pydantic models offer robust type validation and are the recommended way to define schemas. ```python import plexe from pydantic import BaseModel, Field from typing import List # Define input schema using Pydantic class HouseFeaturesInput(BaseModel): square_footage: float = Field(description="Total area in square feet") bedrooms: int = Field(description="Number of bedrooms") bathrooms: float = Field(description="Number of bathrooms (e.g., 2.5)") zip_code: str = Field(description="Postal code of the property") # Define output schema using Pydantic class HousePriceOutput(BaseModel): predicted_price: float = Field(description="Estimated market price of the house") # Initialize the model with Pydantic schemas model = plexe.Model( intent="Predict house prices based on property features.", input_schema=HouseFeaturesInput, output_schema=HousePriceOutput ) print("Model initialized with Pydantic schemas.") # You can access the schemas later: # print(model.input_schema.model_json_schema()) # print(model.output_schema.model_json_schema()) ``` ## Using Dictionaries You can also define schemas using simple Python dictionaries mapping field names to their types. ```python import plexe # Define input schema as a dictionary input_schema_dict = { "square_footage": float, "bedrooms": int, "bathrooms": float, "zip_code": str } # Define output schema as a dictionary output_schema_dict = { "predicted_price": float } # Initialize the model with dictionary schemas model = plexe.Model( intent="Predict house prices based on property features.", input_schema=input_schema_dict, output_schema=output_schema_dict ) print("Model initialized with dictionary schemas.") # Plexe converts these dictionaries into Pydantic models internally # print(model.input_schema.model_json_schema()) # print(model.output_schema.model_json_schema()) ``` {/* Note component with proper JSX syntax */} When using dictionaries, Plexe currently supports basic Python types like `int`, `float`, `str`, and `bool`. For more complex types or validation rules, use Pydantic models directly. ## Schema Inference If you don't provide `input_schema` or `output_schema` but *do* provide `datasets` during the `model.build()` call, Plexe will attempt to infer the schemas: 1. **Identify Target:** An LLM analyzes the column names and your `intent` to identify the most likely target variable(s) for the output schema. 2. **Determine Types:** Data types are inferred from the provided Pandas DataFrame(s). 3. **Construct Schemas:** Inferred input and output schemas are created. ```python import plexe import pandas as pd # --- Prepare Data --- try: df = pd.read_csv("housing_data.csv") except FileNotFoundError: df = pd.DataFrame({ # Dummy data 'square_footage': [1500, 2100, 1800, 2500, 1200], 'bedrooms': [3, 4, 3, 5, 2], 'bathrooms': [2, 2.5, 2, 3, 1.5], 'price': [300000, 450000, 380000, 550000, 250000] }) datasets = [df] # -------------------- # Initialize model WITHOUT schemas model_infer = plexe.Model( intent="Predict house prices based on square footage, bedrooms, and bathrooms." ) print("Model initialized without explicit schemas.") # Build the model - schemas will be inferred here model_infer.build( datasets=datasets, provider="openai/gpt-4o-mini", max_iterations=1 # Keep low for quick example ) print(f"Build finished. Inferred Input Schema: {plexe.internal.common.utils.pydantic_utils.format_schema(model_infer.input_schema)}") print(f"Build finished. Inferred Output Schema: {plexe.internal.common.utils.pydantic_utils.format_schema(model_infer.output_schema)}") ``` While schema inference is convenient, providing explicit schemas is generally recommended for clarity and control, especially for complex models or specific data validation requirements. # Save and Load Models Source: https://docs.plexe.ai/pages/library/how-to/save_load_models Persist trained Plexe models to disk and load them back for later use. Once you have successfully built a `plexe.Model` (`model.state == ModelState.READY`), you can save its state, including the trained predictor, source code, artifacts, and metadata, to a file. You can then load this file later to reuse the model without rebuilding it. Plexe saves models as `.tar.gz` archives. ## Saving a Model Use the `plexe.save_model()` function. ```python import plexe import pandas as pd import os # --- Build a model first (Example steps) --- # (Assume df and model are defined and built successfully) try: df = pd.read_csv("housing_data.csv") except FileNotFoundError: df = pd.DataFrame({ # Dummy data 'square_footage': [1500, 2100, 1800, 2500, 1200], 'bedrooms': [3, 4, 3, 5, 2], 'bathrooms': [2, 2.5, 2, 3, 1.5], 'price': [300000, 450000, 380000, 550000, 250000] }) datasets = [df] model = plexe.Model(intent="Predict house prices") model.build(datasets=datasets, max_iterations=1) # --------------------------------------------- # Check if the model is ready before saving if model.get_state() == plexe.internal.common.utils.model_state.ModelState.READY: # Define a path for the saved model archive # It's good practice to include the model identifier or name model_filename = f"house_price_model_{model.identifier}.tar.gz" save_directory = "./saved_models" os.makedirs(save_directory, exist_ok=True) # Ensure directory exists full_save_path = os.path.join(save_directory, model_filename) try: # Save the model saved_path = plexe.save_model(model, full_save_path) print(f"Model successfully saved to: {saved_path}") except Exception as e: print(f"Error saving model: {e}") else: print("Model is not in READY state, cannot save.") ``` {/* Note component with proper JSX syntax */} The `save_model` function requires the full path including the `.tar.gz` extension. It will create the necessary parent directories if they don't exist. The saved archive contains: * Metadata (intent, state, metrics, identifier) * Schemas (input, output) * Code (trainer source, predictor source) * Artifacts (serialized model files, e.g., `.joblib`, `.pkl`, `.pt`) * Constraints (if any were defined) ## Loading a Model Use the `plexe.load_model()` function, providing the path to the `.tar.gz` archive. ```python import plexe import os # Assuming 'full_save_path' is the path where the model was saved previously # Example: full_save_path = "./saved_models/house_price_model_model-....tar.gz" saved_model_path = full_save_path # Replace with your actual path if running separately if 'full_save_path' in locals() and os.path.exists(saved_model_path): try: # Load the model from the archive loaded_model = plexe.load_model(saved_model_path) print(f"\nModel loaded successfully from: {saved_model_path}") print(f"Loaded model intent: {loaded_model.intent}") print(f"Loaded model state: {loaded_model.get_state()}") # The loaded model is ready for prediction if it was saved in a READY state if loaded_model.get_state() == plexe.internal.common.utils.model_state.ModelState.READY: # Example prediction with the loaded model input_data = { "square_footage": 1750.0, "bedrooms": 3, "bathrooms": 2.0 } prediction = loaded_model.predict(input_data) print(f"Prediction using loaded model: {prediction}") else: print("Loaded model is not in READY state.") except ValueError as e: print(f"Error loading model: {e} - File not found or invalid.") except Exception as e: print(f"An unexpected error occurred during loading: {e}") else: print("\nSaved model path not found or not defined. Skipping loading example.") ``` Loading a model reconstructs the `plexe.Model` instance, including its state, predictor, and associated data, allowing you to immediately use it for inference or further inspection. # Use Datasets for Building Models Source: https://docs.plexe.ai/pages/library/how-to/use_datasets Provide training and validation data to the model build process using Pandas DataFrames or DatasetGenerator. The `model.build()` method requires data to train and evaluate the machine learning model. You can provide this data in two main ways: 1. **List of Pandas DataFrames:** The simplest way for tabular data. 2. **List of `plexe.DatasetGenerator` objects:** Useful for generating synthetic data or augmenting existing datasets. ## Using Pandas DataFrames If your data is already loaded into Pandas DataFrames, pass a list containing these DataFrames to the `datasets` argument of `model.build()`. ```python import plexe import pandas as pd # Load your data into DataFrames try: train_df = pd.read_csv("train_data.csv") # val_df = pd.read_csv("validation_data.csv") # Optional validation set except FileNotFoundError: print("Warning: Data files not found, using dummy data.") train_df = pd.DataFrame({ 'feature1': [1, 2, 3, 4, 5], 'feature2': [10, 12, 11, 14, 13], 'target': [0, 1, 0, 1, 0] }) # val_df = pd.DataFrame({ # Dummy validation data # 'feature1': [6, 7], 'feature2': [15, 16], 'target': [1, 0] # }) # --- Define Model --- model = plexe.Model( intent="Classify target based on feature1 and feature2." # Schemas might be inferred if not provided explicitly ) # -------------------- # Provide the DataFrame(s) in a list datasets_to_use = [train_df] # datasets_to_use = [train_df, val_df] # If you have a separate validation set print("Building model using Pandas DataFrame(s)...") model.build( datasets=datasets_to_use, provider="openai/gpt-4o-mini", max_iterations=1 ) print(f"Model build finished. State: {model.get_state()}") ``` Plexe will internally assign default names (like `dataset_0`, `dataset_1`) to these DataFrames and use them during the build process. If schemas are not provided, they will be inferred from these DataFrames. ## Using `DatasetGenerator` The `DatasetGenerator` class allows you to define requirements for a dataset, potentially generating synthetic data or augmenting existing data using an LLM provider. **Use Case 1: Generating purely synthetic data** ```python import plexe from pydantic import BaseModel # Define the desired schema for synthetic data class SyntheticDataSchema(BaseModel): user_query: str intent_category: str sentiment_score: float # Create a DatasetGenerator instance synthetic_dataset_gen = plexe.DatasetGenerator( description="Generate synthetic user support queries with intent and sentiment.", provider="openai/gpt-4o-mini", # LLM used for generation schema=SyntheticDataSchema # data=None # No existing data provided ) # Generate synthetic samples (this happens during the build process) # The 'num_samples' argument inside build tells the generator how many to create. # Note: The old API had a .generate() method, the new API integrates generation # directly into the .build() call using the DatasetGenerator object. # (Actual generation mechanism within build needs confirmation from codebase analysis, # assuming it uses the generator object passed in datasets) # --- Define Model --- model = plexe.Model( intent="Classify user query intent and predict sentiment.", input_schema={"user_query": str}, output_schema={"intent_category": str, "sentiment_score": float} ) # -------------------- print("Building model using DatasetGenerator for synthetic data...") # Pass the generator object in the list model.build( datasets=[synthetic_dataset_gen], # Pass the generator here provider="openai/gpt-4o-mini", max_iterations=1 # Add num_samples if required by the internal build logic using DatasetGenerator # e.g., build_args={"synthetic_dataset_gen_0": {"num_samples": 500}} ??? -> Needs clarification from code how generation count is passed ) print(f"Model build finished. State: {model.get_state()}") ``` **Use Case 2: Augmenting existing data** You can provide an existing DataFrame to `DatasetGenerator` and potentially use it as a base for generating more samples (although the exact augmentation mechanism within `build` needs confirmation). ```python import plexe import pandas as pd from pydantic import BaseModel # --- Load existing data --- try: existing_df = pd.read_csv("partial_data.csv") except FileNotFoundError: print("Warning: Partial data file not found, using dummy data.") existing_df = pd.DataFrame({'text': ['good service', 'bad experience'], 'label': [1, 0]}) # -------------------------- # Define schema matching existing data class TextFeedback(BaseModel): text: str label: int # Create generator, providing existing data augmented_dataset_gen = plexe.DatasetGenerator( description="User feedback text for classification, augmenting existing samples.", provider="openai/gpt-4o-mini", schema=TextFeedback, data=existing_df # Provide existing data here ) # --- Define Model --- model = plexe.Model( intent="Classify user feedback text.", input_schema={"text": str}, output_schema={"label": int} ) # -------------------- print("Building model using DatasetGenerator with existing data...") model.build( datasets=[augmented_dataset_gen], # Pass the generator provider="openai/gpt-4o-mini", max_iterations=1 # Again, clarification needed on how augmentation count is controlled within build. ) print(f"Model build finished. State: {model.get_state()}") ``` Choose the method that best fits how your data is structured and whether you need synthetic data generation capabilities. # API Reference Source: https://docs.plexe.ai/pages/library/reference/api Complete reference documentation for the Plexe Python library API. This page provides comprehensive reference documentation for the core classes and functions in the Plexe Python library. ## Core Classes ### `Model` The primary class in the Plexe library, representing a machine learning model. ```python class Model: def __init__( self, intent: str, input_schema: Type[BaseModel] | Dict[str, type] = None, output_schema: Type[BaseModel] | Dict[str, type] = None, constraints: List[Constraint] = None, distributed: bool = False ) ``` **Parameters:** | Parameter | Type | Description | | | --------------- | ------------------ | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | | `intent` | `str` | Natural language description of what the model should do. | | | `input_schema` | \`Type\[BaseModel] | Dict\[str, type]\` | Schema defining input data structure. Can be a dictionary or Pydantic model. Default: `None`. | | `output_schema` | \`Type\[BaseModel] | Dict\[str, type]\` | Schema defining output data structure. Can be a dictionary or Pydantic model. Default: `None`. | | `constraints` | `List[Constraint]` | List of constraints the model should adhere to. Default: `None`. | | | `distributed` | `bool` | Whether to use distributed execution (Ray) when building. Default: `False`. | | **Methods:** #### `build` ```python def build( self, datasets: List[Union[pd.DataFrame, DatasetGenerator]], provider: Union[str, ProviderConfig] = "openai/gpt-4o-mini", timeout: Optional[int] = None, max_iterations: Optional[int] = None, run_timeout: int = 1800, callbacks: Optional[List[Callback]] = None, verbose: bool = False, chain_of_thought: bool = True ) -> None ``` Builds the model using the provided datasets and configuration. **Parameters:** | Parameter | Type | Description | | ------------------ | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `datasets` | `List[Union[pd.DataFrame, DatasetGenerator]]` | List of pandas DataFrames or DatasetGenerator objects for training data. | | `provider` | `Union[str, ProviderConfig]` | LLM provider to use, either as a string ("openai/gpt-4o-mini") or ProviderConfig object. Default: "openai/gpt-4o-mini". | | `timeout` | `Optional[int]` | Maximum total time (in seconds) for the entire build process (all iterations). | | `max_iterations` | `Optional[int]` | Maximum number of iterations to attempt. | | `run_timeout` | `int` | Maximum time (in seconds) for each individual training run. Default: 1800 (30 minutes). | | `callbacks` | `Optional[List[Callback]]` | List of callback objects for monitoring the build process. | | `verbose` | `bool` | Whether to display detailed agent logs. Default: `False`. | | `chain_of_thought` | `bool` | Whether to enable verbose output of agent reasoning. Default: `True`. | **Returns:** `None` **Note:** At least one of `timeout` or `max_iterations` must be provided. #### `predict` ```python def predict( self, x: Dict[str, Any], validate_input: bool = False, validate_output: bool = False ) -> Dict[str, Any] ``` Makes a prediction using the trained model. **Parameters:** | Parameter | Type | Description | | ----------------- | ---------------- | ------------------------------------------------------------ | | `x` | `Dict[str, Any]` | Input data for prediction. | | `validate_input` | `bool` | Whether to validate input against schema. Default: `False`. | | `validate_output` | `bool` | Whether to validate output against schema. Default: `False`. | **Returns:** `Dict[str, Any]` - Prediction result #### `get_state` ```python def get_state(self) -> str ``` Returns the current state of the model. **Returns:** `str` representing model state: `"draft"`, `"building"`, `"ready"`, or `"error"` #### `get_metadata` ```python def get_metadata(self) -> Dict[str, Any] ``` Returns metadata about the model. **Returns:** Dictionary containing metadata #### `get_metrics` ```python def get_metrics(self) -> Optional[Dict[str, Any]] ``` Returns metrics for the trained model if available. **Returns:** Dictionary containing metrics or `None` #### `describe` ```python def describe(self) -> ModelDescription ``` Returns a detailed description of the model. **Returns:** `ModelDescription` object ### `DatasetGenerator` Class for generating synthetic data or augmenting existing data. ```python class DatasetGenerator: def __init__( self, description: str, provider: str, schema: Type[BaseModel] | Dict[str, type] = None, data: pd.DataFrame = None ) -> None def generate(self, num_samples: int): """Generates synthetic data if a provider is available.""" ``` **Constructor Parameters:** | Parameter | Type | Description | | | ------------- | ------------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------- | | `description` | `str` | Human-readable description of the dataset. | | | `provider` | `str` | LLM provider used for synthetic data generation. | | | `schema` | \`Type\[BaseModel] | Dict\[str, type]\` | The schema the data should match, if any. Default: `None`. | | `data` | `pd.DataFrame` | A dataset of real data on which to base the generation, if available. Default: `None`. | | **Methods:** | Method | Description | | ---------------------------- | --------------------------------------------------------- | | `generate(num_samples: int)` | Generates the specified number of synthetic data samples. | | `data` property | Returns the dataset as a pandas DataFrame. | ### `Callback` Base class for callbacks that monitor the build process. ```python class Callback: def on_build_start(self, info: BuildStateInfo) -> None: pass def on_iteration_start(self, info: BuildStateInfo) -> None: pass def on_iteration_end(self, info: BuildStateInfo) -> None: pass def on_build_end(self, info: BuildStateInfo) -> None: pass ``` See [Callbacks Reference](/library/reference/callbacks) for more details. ### `Constraint` Represents rules or conditions that the model should satisfy. ```python class Constraint: def __init__(self, condition: Callable[[Any, Any], bool], description: str) ``` **Parameters:** | Parameter | Type | Description | | ------------- | ---------------------------- | --------------------------------------------- | | `condition` | `Callable[[Any, Any], bool]` | Function that evaluates the constraint. | | `description` | `str` | Human-readable description of the constraint. | ## Core Functions ### `save_model` ```python def save_model(model: Model, path: str | Path) -> str ``` Saves a trained model to a tar archive. **Parameters:** | Parameter | Type | Description | | | --------- | ------- | ------------------ | ------------------------------------------------------------ | | `model` | `Model` | The model to save. | | | `path` | \`str | Path\` | Path where the model should be saved. Must end with .tar.gz. | **Returns:** `str` - Path where the model was saved ### `load_model` ```python def load_model(path: str | Path) -> Model ``` Instantiate a model from a tar archive. **Parameters:** | Parameter | Type | Description | | | --------- | ----- | ----------- | ----------------------------------------------- | | `path` | \`str | Path\` | Path to the saved model archive (.tar.gz file). | **Returns:** `Model` - The loaded model ### `configure_logging` ```python def configure_logging( level: Union[str, int] = logging.INFO, file: Optional[str] = None ) -> None ``` Configures logging for the Plexe library. **Parameters:** | Parameter | Type | Description | | --------- | ----------------- | ----------------------------------------------------------------------------------------- | | `level` | `Union[str, int]` | Logging level (from `logging` module or as string). | | `file` | `Optional[str]` | Path to a log file. If provided, logs will be written to this file in addition to stdout. | **Returns:** `None` ## Enums and Constants ### `ModelState` Enum representing the possible states of a model. The `get_state()` method returns the string value. ```python class ModelState(Enum): DRAFT = "draft" # Initial state, before building BUILDING = "building" # During the build process READY = "ready" # Build complete, model ready for use ERROR = "error" # Build failed ``` Note: When checking model state, compare against the string values: ```python if model.get_state() == "ready": # Ready to make predictions ``` ## Provider Configuration ### `ProviderConfig` Class for configuring different LLM providers for different agent roles (imported from `plexe.internal.common.provider`). ```python from plexe.internal.common.provider import ProviderConfig class ProviderConfig: def __init__( self, default_provider: str, orchestrator_provider: Optional[str] = None, research_provider: Optional[str] = None, engineer_provider: Optional[str] = None, ops_provider: Optional[str] = None, tool_provider: Optional[str] = None ) ``` **Parameters:** | Parameter | Type | Description | | ----------------------- | --------------- | ------------------------------------------------------------------------ | | `default_provider` | `str` | Default provider for all roles (e.g., "openai/gpt-4o-mini"). | | `orchestrator_provider` | `Optional[str]` | Provider for the orchestrator agent (coordinates the overall process). | | `research_provider` | `Optional[str]` | Provider for the research agent (analyzes problems and plans solutions). | | `engineer_provider` | `Optional[str]` | Provider for the engineer agent (generates training code). | | `ops_provider` | `Optional[str]` | Provider for the ops agent (generates inference code). | | `tool_provider` | `Optional[str]` | Provider for tool agents (performs specialized tasks). | ## Performance Metrics ### `Metric` Class representing a performance metric for a model. ```python class Metric: def __init__( self, name: str, value: float = None, comparator: MetricComparator = None, is_worst: bool = False ) ``` **Parameters:** | Parameter | Type | Description | | ------------ | ------------------ | --------------------------------------------------------------------------------- | | `name` | `str` | Name of the metric (e.g., "accuracy", "rmse"). | | `value` | `float` | Numeric value of the metric. Default: `None`. | | `comparator` | `MetricComparator` | Comparison logic for determining which metric values are better. Default: `None`. | | `is_worst` | `bool` | Whether this is the worst possible value for the metric. Default: `False`. | ### `MetricComparator` Encapsulates comparison logic for metrics. ```python class MetricComparator: def __init__( self, comparison_method: ComparisonMethod, target: float = None, epsilon: float = 1e-9 ) ``` **Parameters:** | Parameter | Type | Description | | ------------------- | ------------------ | --------------------------------------------------------------------------------- | | `comparison_method` | `ComparisonMethod` | The method used to compare metrics (HIGHER\_IS\_BETTER, LOWER\_IS\_BETTER, etc.). | | `target` | `float` | The target value for TARGET\_IS\_BETTER comparisons. Default: `None`. | | `epsilon` | `float` | Small value used for floating point comparisons. Default: `1e-9`. | ## Type Hints The library uses the following type hints: ```python SchemaType = Union[Dict[str, Any], Type[BaseModel]] DatasetType = Union[pd.DataFrame, DatasetGenerator] ProviderType = Union[str, ProviderConfig] ``` ## Usage Example ```python import plexe import pandas as pd # Load data df = pd.read_csv("housing.csv") # Create model model = plexe.Model( intent="Predict house prices based on features", input_schema={"square_footage": float, "bedrooms": int, "bathrooms": float}, output_schema={"price": float} ) # Build model model.build( datasets=[df], provider="openai/gpt-4o-mini", max_iterations=3, timeout=600, run_timeout=180, chain_of_thought=True, verbose=False ) # Make prediction prediction = model.predict({"square_footage": 2000, "bedrooms": 3, "bathrooms": 2}) print(f"Predicted price: {prediction}") # Save model save_path = plexe.save_model(model, "housing_model.tar.gz") # Load model loaded_model = plexe.load_model(save_path) ``` For more details on specific components, see the other reference sections: * [Callbacks Reference](/library/reference/callbacks) * [Datasets Reference](/library/reference/datasets) * [Exceptions Reference](/library/reference/exceptions) # Callbacks Reference Source: https://docs.plexe.ai/pages/library/reference/callbacks Detailed reference documentation for the callback system in the Plexe Python library. Plexe provides a flexible callback system that allows you to monitor and interact with the model building process. This reference documents all built-in callbacks and provides information on creating custom callbacks. ## Base Callback Class All callbacks inherit from the `Callback` base class: ```python class Callback: def on_build_start(self, info: BuildStateInfo) -> None: """Called once at the beginning of model.build()""" pass def on_iteration_start(self, info: BuildStateInfo) -> None: """Called at the start of each iteration""" pass def on_iteration_end(self, info: BuildStateInfo) -> None: """Called at the end of each iteration""" pass def on_build_end(self, info: BuildStateInfo) -> None: """Called once at the end of model.build()""" pass ``` ## BuildStateInfo The `BuildStateInfo` dataclass provides context about the current state of the build process and is passed to all callback methods: ```python @dataclass class BuildStateInfo: # Common identification fields intent: str """The natural language description of the model's intent.""" provider: str """The provider (LLM) used for generating the model.""" # Schema fields input_schema: Optional[Type[BaseModel]] = None """The input schema for the model.""" output_schema: Optional[Type[BaseModel]] = None """The output schema for the model.""" run_timeout: Optional[int] = None """Maximum time in seconds for each individual training run.""" max_iterations: Optional[int] = None """Maximum number of iterations for the model building process.""" timeout: Optional[int] = None """Maximum total time in seconds for the entire model building process.""" # Iteration fields iteration: int = 0 """Current iteration number (0-indexed).""" # Dataset fields datasets: Optional[Dict[str, TabularConvertible]] = None """Dictionary of datasets used for training.""" # Current node being evaluated node: Optional[Node] = None """The solution node being evaluated in the current iteration.""" ``` | Attribute | Type | Description | | ---------------- | ----------------------------------------- | ------------------------------------------------------------------- | | `intent` | `str` | The natural language description of the model's intent | | `provider` | `str` | The provider (LLM) used for generating the model | | `input_schema` | `Optional[Type[BaseModel]]` | The input schema for the model | | `output_schema` | `Optional[Type[BaseModel]]` | The output schema for the model | | `run_timeout` | `Optional[int]` | Maximum time in seconds for each individual training run | | `max_iterations` | `Optional[int]` | Maximum number of iterations for the model building process | | `timeout` | `Optional[int]` | Maximum total time in seconds for the entire model building process | | `iteration` | `int` | Current iteration number (0-indexed) | | `datasets` | `Optional[Dict[str, TabularConvertible]]` | Dictionary of datasets used for training | | `node` | `Optional[Node]` | The solution node being evaluated in the current iteration | ## Built-in Callbacks ### `ChainOfThoughtModelCallback` This callback logs detailed steps of the agent's reasoning during the build process: ```python class ChainOfThoughtModelCallback(Callback): def __init__( self, emitter: Optional[Emitter] = None, include_code: bool = True ) ``` | Parameter | Type | Description | | -------------- | ------------------- | ------------------------------------------------------------------------------------- | | `emitter` | `Optional[Emitter]` | Object that handles outputting the chain of thought logs. Default: `ConsoleEmitter()` | | `include_code` | `bool` | Whether to include generated code in the logs. Default: `True` | This callback is automatically added when `chain_of_thought=True` is set in `model.build()`. **Example:** ```python import plexe from plexe.callbacks import ChainOfThoughtModelCallback, ConsoleEmitter # Create custom emitter if needed (otherwise uses default) emitter = ConsoleEmitter() callback = ChainOfThoughtModelCallback(emitter=emitter, include_code=True) model = plexe.Model(intent="Predict house prices") model.build( datasets=[df], callbacks=[callback] ) ``` ### `MLFlowCallback` Integrates with MLflow for experiment tracking: ```python class MLFlowCallback(Callback): def __init__( self, tracking_uri: Optional[str] = None, experiment_name: Optional[str] = None, run_name_prefix: str = "plexe_", log_code: bool = True, log_artifacts: bool = True ) ``` | Parameter | Type | Description | | ----------------- | --------------- | --------------------------------------------------------------------- | | `tracking_uri` | `Optional[str]` | MLflow tracking server URI. Default: `None` (uses default MLflow URI) | | `experiment_name` | `Optional[str]` | MLflow experiment name. Default: `None` (uses/creates "Default") | | `run_name_prefix` | `str` | Prefix for MLflow run names. Default: `"plexe_"` | | `log_code` | `bool` | Whether to log generated code as artifacts. Default: `True` | | `log_artifacts` | `bool` | Whether to log model artifacts. Default: `True` | **Example:** ```python import plexe from plexe.callbacks import MLFlowCallback # Initialize MLflow callback mlflow_callback = MLFlowCallback( tracking_uri="http://localhost:5000", experiment_name="Housing Price Models", run_name_prefix="housing_" ) model = plexe.Model(intent="Predict house prices") model.build( datasets=[df], callbacks=[mlflow_callback] ) ``` {/* TensorBoardCallback and JSONLogCallback are not included in the current version of the library */} {/* If you need additional logging functionality, you can create custom callbacks as described below */} ## Creating Custom Callbacks You can create custom callbacks by subclassing `Callback` and implementing the desired methods: ```python import plexe from plexe.callbacks import Callback, BuildStateInfo import time class TimingCallback(Callback): def __init__(self): self.start_time = None self.iteration_start_times = {} def on_build_start(self, info: BuildStateInfo) -> None: self.start_time = time.time() print(f"Build started at {time.strftime('%H:%M:%S')}") def on_iteration_start(self, info: BuildStateInfo) -> None: iteration = info.iteration + 1 # 1-based for output self.iteration_start_times[iteration] = time.time() print(f"Iteration {iteration} started at {time.strftime('%H:%M:%S')}") def on_iteration_end(self, info: BuildStateInfo) -> None: iteration = info.iteration + 1 # 1-based for output iteration_time = time.time() - self.iteration_start_times[iteration] status = "succeeded" if not (info.node and info.node.exception_was_raised) else "failed" print(f"Iteration {iteration} {status} in {iteration_time:.2f} seconds") if info.node and info.node.performance: print(f" Performance: {info.node.performance.name} = {info.node.performance.value:.4f}") def on_build_end(self, info: BuildStateInfo) -> None: total_time = time.time() - self.start_time print(f"Build finished in {total_time:.2f} seconds") print(f"Final state: {info.model.get_state().name}") ``` ## Using Multiple Callbacks You can use multiple callbacks simultaneously: ```python import plexe from plexe.callbacks import MLFlowCallback # Create callback instances mlflow_callback = MLFlowCallback(experiment_name="Housing Models") timing_callback = TimingCallback() # Custom callback from above # Use all callbacks together model = plexe.Model(intent="Predict house prices") model.build( datasets=[df], callbacks=[mlflow_callback, timing_callback], chain_of_thought=True # This adds ChainOfThoughtModelCallback automatically ) ``` ## Callback Execution Order When multiple callbacks are provided: 1. All callbacks' `on_build_start` methods are called in the order they appear in the list 2. For each iteration: a. All callbacks' `on_iteration_start` methods are called in order b. The iteration runs c. All callbacks' `on_iteration_end` methods are called in order 3. All callbacks' `on_build_end` methods are called in order ## Emitters for Chain of Thought The `ChainOfThoughtModelCallback` uses a `ChainOfThoughtEmitter` to output the chain of thought logs. Built-in emitters include: ### `ConsoleEmitter` Outputs logs to the console (stdout). ### `LoggingEmitter` Sends logs to the Python logging system. ### `MultiEmitter` Combines multiple emitters into one. ### Creating Custom Emitters You can create custom emitters by subclassing `ChainOfThoughtEmitter`: ```python from plexe.internal.common.utils.chain_of_thought.emitters import ChainOfThoughtEmitter class CustomEmitter(ChainOfThoughtEmitter): def emit_thought(self, role: str, thought: str) -> None: # Custom logic for emitting thoughts formatted = f"[{role}] {thought}" # Do something with formatted message # e.g., send to logging service, web socket, etc. def emit_code(self, role: str, code: str, language: str = None) -> None: # Custom logic for emitting code formatted = f"[{role} CODE ({language})] {code}" # Handle code blocks specially ``` ## Best Practices * **Choose callbacks based on your needs:** Use MLflow for experiment tracking, TensorBoard for visualization, or custom callbacks for specialized logging * **Limit callback overhead:** Complex callbacks can slow down the build process * **Combine callbacks strategically:** Multiple callbacks can provide different views of the same process * **Handle exceptions gracefully:** Callbacks should catch their own exceptions to avoid disrupting the build process # Datasets Reference Source: https://docs.plexe.ai/pages/library/reference/datasets Detailed reference documentation for dataset handling in the Plexe Python library. Plexe provides flexible options for working with datasets. This reference documents how to prepare, provide, and generate data for model building. ## Supported Dataset Types Plexe accepts two types of objects in the `datasets` parameter of `model.build()`: 1. **Pandas DataFrames:** For providing tabular data directly 2. **DatasetGenerator objects:** For generating synthetic data or augmenting existing data ## Using Pandas DataFrames Pandas DataFrames are the most common way to provide data to Plexe. ### Basic Usage ```python import pandas as pd import plexe # Load data df = pd.read_csv("customer_data.csv") # Build model with DataFrame model = plexe.Model(intent="Predict customer churn") model.build(datasets=[df]) ``` ### Multiple DataFrames You can provide multiple DataFrames for more complex scenarios: ```python # Load data from multiple sources customers_df = pd.read_csv("customers.csv") transactions_df = pd.read_csv("transactions.csv") # Build model with multiple DataFrames model = plexe.Model(intent="Predict customer lifetime value") model.build(datasets=[customers_df, transactions_df]) ``` When multiple DataFrames are provided, Plexe's ML Engineer agent will attempt to determine relationships between them based on column names and data types. ### DataFrame Requirements While Plexe is flexible, following these guidelines helps ensure optimal results: * **Clean Data:** Remove or impute missing values when possible * **Appropriate Types:** Ensure columns have appropriate data types * **Meaningful Names:** Use descriptive column names * **Reasonable Size:** Keep DataFrames under a few million rows for optimal performance ## DatasetGenerator The `DatasetGenerator` class allows you to generate synthetic data or augment existing data using LLMs. ### Class Definition ```python class DatasetGenerator: def __init__( self, description: str, provider: str, schema: Type[BaseModel] | Dict[str, type] = None, data: pd.DataFrame = None ) -> None def generate(self, num_samples: int): """Generates synthetic data if a provider is available.""" ``` | Parameter | Type | Description | | | ------------- | ------------------ | -------------------------------------------------------------------- | -------------------------------------------------------------------------------- | | `description` | `str` | Human-readable description of the dataset | | | `provider` | `str` | LLM provider used for synthetic data generation | | | `schema` | \`Type\[BaseModel] | Dict\[str, type]\` | The schema the data should match, if any. Can be a Pydantic model or dictionary. | | `data` | `pd.DataFrame` | A dataset of real data on which to base the generation, if available | | ### Generating Synthetic Data To generate completely synthetic data: ```python import plexe from plexe import DatasetGenerator from pydantic import BaseModel, Field # Define schema for synthetic data class CustomerData(BaseModel): age: int = Field(ge=18, le=100, description="Customer age in years") income: float = Field(ge=0, description="Annual income in USD") has_subscription: bool = Field(description="Whether customer has a subscription") subscription_type: str = Field(description="Type of subscription (if any)") churn: bool = Field(description="Whether customer churned within 3 months") # Create generator generator = DatasetGenerator( description=""" Generate realistic customer data for a subscription service. Customers can have different income levels and subscription types. Older customers with higher incomes tend to churn less. Subscription types include 'basic', 'premium', and 'enterprise'. """, provider="openai/gpt-4o-mini", schema=CustomerData ) # Generate synthetic data generator.generate(num_samples=100) # Use generator with model model = plexe.Model(intent="Predict customer churn") model.build(datasets=[generator]) ``` ### Augmenting Existing Data To augment an existing but limited dataset: ```python import pandas as pd import plexe from plexe import DatasetGenerator from pydantic import BaseModel, Field # Define schema matching existing data class ProductReview(BaseModel): product_id: str = Field(description="Unique product identifier") review_text: str = Field(description="Customer review text") rating: int = Field(ge=1, le=5, description="Star rating (1-5)") sentiment: str = Field(description="Sentiment classification (positive, neutral, negative)") # Load limited existing data existing_reviews = pd.read_csv("limited_reviews.csv") # Create generator with existing data generator = DatasetGenerator( description=""" Generate additional product reviews following the patterns in the existing data. Reviews should be diverse in length and tone. Rating should generally correlate with sentiment (high ratings for positive sentiment). """, provider="anthropic/claude-3-sonnet-20240229", schema=ProductReview, data=existing_reviews ) # Generate additional samples based on existing data generator.generate(num_samples=200) # Use generator with model model = plexe.Model(intent="Classify review sentiment") model.build(datasets=[generator]) ``` ## Generation Parameters The generation process is controlled internally based on the `description` and `schema` provided. The description should give clear guidance about: * The general nature of the data * Important patterns or correlations * Distributions of values * Constraints beyond what's defined in the schema * Relationships between fields ## Dataset Schema Details When defining a schema for the `DatasetGenerator`, use Pydantic's `Field` attributes to provide rich information: ```python from pydantic import BaseModel, Field from typing import List, Optional from datetime import date class FinancialTransaction(BaseModel): transaction_id: str = Field(description="Unique transaction identifier") amount: float = Field( gt=0, description="Transaction amount in USD" ) category: str = Field( description="Transaction category (e.g., 'food', 'transport', 'housing')" ) date: date = Field( description="Transaction date" ) recurring: bool = Field( description="Whether this is a recurring transaction" ) tags: Optional[List[str]] = Field( default=None, description="Optional tags for the transaction" ) notes: Optional[str] = Field( default=None, description="Optional additional notes" ) ``` ## Combining DataFrame and Generator You can use both types together in the `datasets` parameter: ```python # Prepare real and synthetic data sources real_data = pd.read_csv("real_customers.csv") synthetic_generator = DatasetGenerator( description="Generate additional customer data to supplement real data", provider="openai/gpt-4o-mini", schema=CustomerSchema ) # Generate synthetic data synthetic_generator.generate(num_samples=100) # Combine both in the datasets parameter model.build(datasets=[real_data, synthetic_generator]) ``` ## Data Conversion Internals Internally, Plexe performs several steps when working with data: 1. **DataFrame Validation:** Ensures DataFrames have the expected structure 2. **Schema Inference:** If not provided explicitly, infers schemas from the data 3. **Type Conversion:** Ensures data types match schema requirements 4. **Data Splitting:** Automatically splits data for training and validation 5. **Synthetic Generation:** Executes when `DatasetGenerator` objects are provided 6. **Feature Engineering:** The ML Engineer agent determines appropriate transformations based on the data ## Schema Inference If input/output schemas aren't explicitly provided, but datasets are, Plexe attempts to: 1. Determine data types from the DataFrame columns 2. Identify the likely target (output) variable(s) based on the model intent 3. Classify remaining columns as input features ## Best Practices 1. **Provide Clear Schemas:** Explicit schemas help guide the model building process 2. **Clean Your Data:** Remove irrelevant columns, handle missing values 3. **Use Descriptive Names:** Clear column names help Plexe understand the data 4. **Include Domain Knowledge:** Add rich descriptions to schema fields 5. **Combine Approaches:** Use real data when available and synthetic data when needed ## Performance Considerations * **Memory Usage:** Large DataFrames consume more memory * **Generation Time:** Synthetic data generation can take time, especially for complex schemas * **LLM Costs:** Data generation involves LLM API calls, which may incur costs By leveraging these options for dataset handling, you can provide Plexe with the data it needs to build effective machine learning models, even in scenarios where limited data is available. # Exceptions Reference Source: https://docs.plexe.ai/pages/library/reference/exceptions Comprehensive guide to exception handling in the Plexe Python library. Plexe defines several exception types to provide clear information about errors that may occur during model building and usage. This reference documents all exception classes, their meanings, and how to handle them effectively. ## Exception Hierarchy Plexe's exceptions inherit from a base `PlexeError` class: ``` Exception └── PlexeError ├── SpecificationError │ ├── InsufficientSpecificationError │ ├── AmbiguousSpecificationError │ └── InvalidSchemaError ├── InstructionError ├── ConstraintError └── PlexeRuntimeError (also inherits from RuntimeError) └── CodeExecutionError ``` Note: This hierarchy reflects the current implementation and may expand in future versions. ## Base Exception ### `PlexeError` Base exception for all Plexe-specific exceptions. ```python class PlexeError(Exception): """Base class for all Plexe-specific exceptions.""" pass ``` ## Specification Errors ### `SpecificationError` Base class for errors related to model specification. ```python class SpecificationError(PlexeError): """Base class for errors related to model specification.""" pass ``` ### `InsufficientSpecificationError` Raised when the natural language specification is insufficiently detailed. ```python class InsufficientSpecificationError(SpecificationError): """Raised when the natural language specification is insufficiently detailed.""" pass ``` **Example:** ```python # Intent too vague raise InsufficientSpecificationError("Intent 'analyze data' is too vague. Please provide more specific details about the task.") ``` ### `AmbiguousSpecificationError` Raised when the natural language specification is ambiguous or contradictory. ```python class AmbiguousSpecificationError(SpecificationError): """Raised when the natural language specification is ambiguous or contradictory.""" pass ``` **Example:** ```python # Contradictory intent raise AmbiguousSpecificationError("Intent contains contradictory requirements: maximize both precision and recall.") ``` ### `InvalidSchemaError` Raised when the input or output schema is invalid. ```python class InvalidSchemaError(SpecificationError): """Raised when the input or output schema is invalid.""" pass ``` **Example:** ```python # Invalid schema type raise InvalidSchemaError("Schema must be a dictionary or a Pydantic model.") # Missing required fields raise InvalidSchemaError("Required field 'id' missing from input schema.") ``` ## Instruction Errors ### `InstructionError` Base class for errors related to instructions provided for model building. ```python class InstructionError(PlexeError): """Base class for errors related to instructions provided for model building.""" pass ``` **Example:** ```python # Invalid instruction raise InstructionError("Unable to interpret instruction for model building.") ``` ## Constraint Errors ### `ConstraintError` Base class for errors related to constraints. ```python class ConstraintError(PlexeError): """Base class for errors related to constraints.""" pass ``` **Example:** ```python # Constraint violation raise ConstraintError("Model output violates constraint: price must be positive.") ``` ## Runtime Errors ### `PlexeRuntimeError` Base class for runtime errors during model execution or training. ```python class PlexeRuntimeError(PlexeError, RuntimeError): """Base class for runtime errors during model execution or training.""" pass ``` ### `CodeExecutionError` Raised when code execution fails for reasons other than timeout. ```python class CodeExecutionError(PlexeRuntimeError): """Raised when code execution fails for reasons other than timeout.""" pass ``` **Example:** ```python # Syntax error raise CodeExecutionError("Syntax error in generated code: Missing colon after parameters") # Runtime error raise CodeExecutionError("Runtime error while executing training code: shapes (60,1) and (50,1) not aligned") ``` ## Handling Exceptions Note: The list of exception classes above represents the current implementation. In future versions, additional exception types may be added to provide more specific error information. ### Basic Exception Handling ```python import plexe from plexe.exceptions import PlexeError, CodeExecutionError try: model = plexe.Model(intent="Predict customer churn") model.build(datasets=[df]) except CodeExecutionError as e: print(f"Error executing generated code: {e}") except PlexeError as e: print(f"Plexe error: {e}") except Exception as e: print(f"Unexpected error: {e}") ``` ### Specific Exception Handling ```python import plexe from plexe.exceptions import ( SpecificationError, InvalidSchemaError, CodeExecutionError, PlexeRuntimeError ) try: model = plexe.Model(intent="Predict customer churn") model.build(datasets=[df]) except InvalidSchemaError as e: print(f"Schema error: {e}") # Handle schema issues except CodeExecutionError as e: print(f"Code execution error: {e}") # Handle generated code issues except SpecificationError as e: print(f"Specification error: {e}") # Handle specification issues except PlexeRuntimeError as e: print(f"Runtime error: {e}") # Handle runtime issues ``` ### Prediction Error Handling ```python import plexe from plexe.exceptions import PlexeError, PlexeRuntimeError try: prediction = model.predict(input_data) except PlexeRuntimeError as e: print(f"Runtime error during prediction: {e}") except PlexeError as e: print(f"Error during prediction: {e}") ``` ## Best Practices 1. **Catch Specific Exceptions:** Target the most specific exception class that makes sense for your use case. 2. **Log Detailed Information:** Include full exception details in logs for debugging. 3. **Graceful Degradation:** When possible, handle errors in a way that allows your application to continue functioning. 4. **User-Friendly Messages:** Transform technical error details into actionable user messages. 5. **Retry Strategies:** Implement retries for transient errors like LLM provider issues. By understanding Plexe's exception hierarchy, you can write more robust code that gracefully handles potential errors in your machine learning workflows. # Distributed Training with Ray Source: https://docs.plexe.ai/pages/library/tutorials/distributed_training Leverage Ray for distributed and parallel model building with Plexe. Plexe can utilize [Ray](https://www.ray.io/) to distribute parts of the model building process, potentially speeding up execution, especially when exploring multiple solution candidates (`max_iterations` > 1) or when individual training runs are computationally intensive. ## Prerequisites 1. **Install Ray:** If you haven't already, install Ray. You might need specific dependencies depending on your environment (e.g., for cluster support). ```bash pip install ray # Or for dashboard and cluster utilities: # pip install ray[default] ``` 2. **Install Plexe with Ray support:** Ensure you have the necessary Plexe dependencies. ```bash pip install plexe[all] # Or ensure 'smolagents[ray]' is included if installing manually ``` 3. **(Optional) Ray Cluster:** For true distribution, you need a running Ray cluster. You can start one locally or connect to a remote cluster. See the [Ray documentation](https://docs.ray.io/en/latest/cluster/getting-started.html) for setup instructions. If no cluster is running, Ray will typically utilize multiple cores on your local machine. ## Enabling Distributed Execution To enable distributed execution with Ray, simply set the `distributed=True` flag when initializing the `plexe.Model`. ```python import plexe import pandas as pd # Optional: Import Ray if you need to manually initialize or connect # import ray # --- Prepare Data (as in Quickstart) --- try: df = pd.read_csv("housing_data.csv") except FileNotFoundError: df = pd.DataFrame({ # Dummy data 'square_footage': [1500, 2100, 1800, 2500, 1200], 'bedrooms': [3, 4, 3, 5, 2], 'bathrooms': [2, 2.5, 2, 3, 1.5], 'price': [300000, 450000, 380000, 550000, 250000] }) datasets = [df] # ----------------------------------------- # --- Optional: Initialize Ray manually --- # If you need to connect to a specific cluster or configure local resources # if not ray.is_initialized(): # ray.init(address='auto') # Connects to running cluster or starts local one # # Or ray.init(address='ray://:10001') for remote cluster # print(f"Ray initialized: {ray.is_initialized()}") # ----------------------------------------- # Define the model and enable distributed execution model = plexe.Model( intent="Predict house prices based on property features.", input_schema={"square_footage": float, "bedrooms": int, "bathrooms": float}, output_schema={"price": float}, distributed=True # Enable Ray integration ) print("Model defined with distributed=True. Ray will be used if available.") # Build the model - Plexe will now attempt to use Ray for execution print("Starting distributed model build...") model.build( datasets=datasets, provider="openai/gpt-4o-mini", max_iterations=4, # Try multiple iterations to see potential parallelism chain_of_thought=True ) print(f"Distributed model build finished. Model state: {model.get_state()}") # Prediction and other methods work the same way if model.get_state() == plexe.internal.common.utils.model_state.ModelState.READY: prediction = model.predict({ "square_footage": 1900.0, "bedrooms": 3, "bathrooms": 2.0 }) print(f"Prediction: {prediction}") # --- Optional: Shutdown Ray manually --- # if ray.is_initialized(): # ray.shutdown() # print("Ray shut down.") # --------------------------------------- ``` ## How it Works When `distributed=True` is set: 1. **Executor Selection:** Plexe checks if Ray is available and initialized. If yes, it uses the `RayExecutor` for running the generated training code; otherwise, it falls back to the default `ProcessExecutor`. 2. **Task Distribution:** The `RayExecutor` submits the training code execution as a remote task (`@ray.remote`) to the Ray cluster (or local Ray instance). 3. **Parallelism:** If `max_iterations` in `model.build()` is greater than 1, and the Ray cluster has sufficient resources (CPUs/GPUs), Ray can potentially execute multiple training iterations in parallel, significantly speeding up the exploration of different model candidates. 4. **Results:** Results (metrics, artifacts, logs, exceptions) are collected from the Ray tasks and integrated back into the Plexe model building process. {/* Note component with proper JSX syntax */} The degree of speedup depends on the number of iterations, the computational cost of each training run, and the resources available in your Ray cluster (or on your local machine). Tasks involving LLM calls for planning or code generation are typically not distributed via Ray in the current implementation. ## Configuration (Advanced) While `distributed=True` is the primary switch, advanced Ray configuration (like cluster address, resource limits) can be managed through Ray's standard initialization methods (`ray.init(...)`) or configuration files before initializing the `plexe.Model`. Plexe itself reads some Ray configurations from its internal config (`plexe.config.config.ray`) which might be relevant in specific deployment scenarios, but direct `ray.init()` is the most common way to configure the connection. # Quickstart Source: https://docs.plexe.ai/pages/library/tutorials/quickstart Build your first ML model using the Plexe Python library in minutes. This tutorial guides you through the essential steps to install the `plexe` library, define a model using natural language, build it using your data, and make predictions. ## 1. Installation First, install the `plexe` library using pip. You can choose between a standard installation, a lightweight version (without deep learning dependencies), or include all optional dependencies. ```bash {{ label: "Standard Installation" }} pip install plexe ``` ```bash {{ label: "Lightweight Installation" }} pip install plexe[lightweight] ``` ```bash {{ label: "Include Deep Learning" }} pip install plexe[all] ``` ## 2. Set Up Environment Variables Plexe uses Large Language Models (LLMs) under the hood via the [LiteLLM](https://docs.litellm.ai/docs/providers) library. You need to configure API keys for the LLM provider you want to use. Set them as environment variables: ```bash # Example for OpenAI export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" # Example for Anthropic # export ANTHROPIC_API_KEY="YOUR_ANTHROPIC_API_KEY" ``` Plexe defaults to `openai/gpt-4o-mini` if no provider is specified. ## 3. Prepare Your Data For this example, let's assume you have a CSV file named `housing_data.csv` with features like `square_footage`, `bedrooms`, `bathrooms`, and a target column `price`. ```python import pandas as pd # Load your data (replace with your actual data loading) try: df = pd.read_csv("housing_data.csv") print("Dataset loaded successfully:") print(df.head()) except FileNotFoundError: print("Error: housing_data.csv not found. Please create a sample CSV.") # Create a dummy DataFrame for demonstration if file not found df = pd.DataFrame({ 'square_footage': [1500, 2100, 1800, 2500, 1200], 'bedrooms': [3, 4, 3, 5, 2], 'bathrooms': [2, 2.5, 2, 3, 1.5], 'price': [300000, 450000, 380000, 550000, 250000] }) print("Using dummy data:") print(df.head()) # Ensure your DataFrame is ready datasets = [df] ``` ## 4. Define and Build the Model Import the `plexe` library and create a `Model` instance. Define your goal using the `intent` parameter. You can also specify input and output schemas, though Plexe can often infer them. ```python import plexe import logging # Optional: Configure logging for more details # plexe.configure_logging(level=logging.DEBUG) # Define the model's intent # Input and output schemas can often be inferred if data is provided model = plexe.Model( intent="Predict house prices based on square footage, bedrooms, and bathrooms." # Optionally define schemas: # input_schema={"square_footage": float, "bedrooms": int, "bathrooms": float}, # output_schema={"price": float} ) # Build the model # This process involves LLM calls, code generation, and execution. # It might take a few minutes depending on complexity and provider. print("Starting model build...") model.build( datasets=datasets, provider="openai/gpt-4o-mini", # Specify your preferred LLM provider max_iterations=5, # Try up to 5 different model approaches timeout=600, # Set a maximum of 10 minutes for the entire process run_timeout=180, # Maximum 3 minutes per individual run chain_of_thought=True, # Show detailed reasoning steps (default: True) verbose=False # Don't show detailed agent logs (default: False) ) print(f"Model build finished. Model state: {model.get_state()}") ``` {/* Note component with proper JSX syntax */} The `build` process involves multiple steps orchestrated by AI agents: planning, code generation, execution, analysis, and potentially fixing code. Enabling `chain_of_thought=True` provides verbose output showing these steps. ## 5. Make Predictions Once the model state is `READY`, you can use the `predict` method. ```python if model.get_state() == "ready": # Prepare input data as a dictionary input_data = { "square_footage": 1900.0, "bedrooms": 3, "bathrooms": 2.0 } print(f"\nMaking prediction for input: {input_data}") prediction = model.predict(input_data) print(f"Predicted price: {prediction}") # Example with validation # prediction_validated = model.predict(input_data, validate_input=True, validate_output=True) # print(f"Validated prediction: {prediction_validated}") else: print("\nModel is not ready for prediction. Check logs for errors.") ``` ## 6. Inspect the Model You can get metadata and a description of the built model. ```python if model.get_state() == "ready": print("\nModel Metadata:") print(model.get_metadata()) print("\nModel Metrics:") print(model.get_metrics()) print("\nModel Description:") # The describe() method returns a detailed object, print its text representation print(model.describe().as_text()) # Or use as_markdown() or to_dict() / to_json() # print(model.describe().as_markdown()) else: print("\nModel information not available as it's not in READY state.") ``` ## 7. Save and Load (Optional) Persist your trained model for later use. ```python import os if model.get_state() == "ready": model_filename = f"{model.identifier}.tar.gz" save_path = plexe.save_model(model, model_filename) print(f"\nModel saved to: {save_path}") # Load the model later if os.path.exists(save_path): loaded_model = plexe.load_model(save_path) print(f"Model loaded successfully. Intent: {loaded_model.intent}") # You can now use loaded_model.predict() else: print("Saved model file not found for loading example.") ``` That's it! You've built, trained, and used a machine learning model using natural language with the `plexe` library. Explore the other tutorials and guides to learn about more advanced features. # Using Callbacks Source: https://docs.plexe.ai/pages/library/tutorials/using_callbacks Instrument the model building process using built-in and custom callbacks Plexe provides a callback system that allows you to hook into various stages of the `model.build()` process. This is useful for logging, monitoring, custom artifact handling, or triggering external processes. ## The Callback System Callbacks are classes that inherit from `plexe.Callback` and implement one or more of the following methods: * `on_build_start(info: BuildStateInfo)`: Called once at the beginning of the `build` process. * `on_build_end(info: BuildStateInfo)`: Called once at the end of the `build` process (after success or error). * `on_iteration_start(info: BuildStateInfo)`: Called at the start of each model building iteration (solution attempt). * `on_iteration_end(info: BuildStateInfo)`: Called at the end of each model building iteration. The `BuildStateInfo` object passed to these methods contains contextual information like the model intent, provider used, schemas, datasets, current iteration number, and the current solution `Node` being evaluated (especially relevant in `on_iteration_end`). ## Built-in Callbacks Plexe includes some useful built-in callbacks: ### `MLFlowCallback` This callback logs parameters, metrics, and artifacts from the build process to an [MLflow Tracking](https://mlflow.org/docs/latest/tracking.html) server. **Prerequisites:** 1. Install MLflow: `pip install mlflow` 2. Have an MLflow tracking server running or use local file logging. **Usage:** ```python import plexe import pandas as pd from plexe.callbacks import MLFlowCallback # Import the callback # --- Prepare Data (as in Quickstart) --- try: df = pd.read_csv("housing_data.csv") except FileNotFoundError: df = pd.DataFrame({ # Dummy data 'square_footage': [1500, 2100, 1800, 2500, 1200], 'bedrooms': [3, 4, 3, 5, 2], 'bathrooms': [2, 2.5, 2, 3, 1.5], 'price': [300000, 450000, 380000, 550000, 250000] }) datasets = [df] # ----------------------------------------- # --- Define Model (as in Quickstart) --- model = plexe.Model( intent="Predict house prices based on square footage, bedrooms, and bathrooms." ) # ----------------------------------------- # Configure MLflow tracking URI (local example) # Replace with your tracking server URI if applicable (e.g., "http://localhost:5000") mlflow_tracking_uri = "file:./mlruns" mlflow_experiment_name = "Plexe_House_Pricing" # Instantiate the callback mlflow_callback = MLFlowCallback( tracking_uri=mlflow_tracking_uri, experiment_name=mlflow_experiment_name ) print(f"Configured MLflow logging to: {mlflow_tracking_uri}, Experiment: {mlflow_experiment_name}") # Build the model, passing the callback instance print("Starting model build with MLflow logging...") model.build( datasets=datasets, provider="openai/gpt-4o-mini", max_iterations=3, # Keep low for quick example callbacks=[mlflow_callback], # Pass the callback here chain_of_thought=False # Optional: disable default console logging if desired ) print(f"Model build finished. Check MLflow UI for experiment '{mlflow_experiment_name}'.") print(f"You can start the local MLflow UI with: mlflow ui --backend-store-uri {mlflow_tracking_uri}") # You can now inspect the runs in the MLflow UI. Each iteration # will be logged as a separate run within the specified experiment. ``` {/* Info component with proper JSX syntax */} The `MLFlowCallback` logs: * **Parameters:** Intent, provider, schemas, timeouts, iteration number. * **Metrics:** Performance metrics (e.g., accuracy, RMSE) reported by the agent for each iteration, execution time. * **Artifacts:** Training code (`trainer_source.py`), model artifacts saved by the training script. * **Tags:** Provider used, whether an exception occurred during the iteration. ## Creating Custom Callbacks You can create your own callbacks by subclassing `plexe.Callback`. **Example: A simple callback to print iteration progress.** ```python import plexe import pandas as pd from plexe.callbacks import Callback, BuildStateInfo # Import base class and info object # --- Prepare Data & Model (as before) --- try: df = pd.read_csv("housing_data.csv") except FileNotFoundError: df = pd.DataFrame({ # Dummy data 'square_footage': [1500, 2100, 1800, 2500, 1200], 'bedrooms': [3, 4, 3, 5, 2], 'bathrooms': [2, 2.5, 2, 3, 1.5], 'price': [300000, 450000, 380000, 550000, 250000] }) datasets = [df] model = plexe.Model(intent="Predict house prices based on square footage, bedrooms, and bathrooms.") # --------------------------------------- # Define a custom callback class ProgressPrinterCallback(Callback): def on_build_start(self, info: BuildStateInfo) -> None: print(f"🚀 Starting build for intent: '{info.intent[:50]}...'") if info.max_iterations: print(f"Max iterations: {info.max_iterations}") def on_iteration_start(self, info: BuildStateInfo) -> None: print(f"\n--- Iteration {info.iteration + 1} Start ---") def on_iteration_end(self, info: BuildStateInfo) -> None: print(f"--- Iteration {info.iteration + 1} End ---") if info.node: # Check if node info is available if info.node.performance: print(f" Performance ({info.node.performance.name}): {info.node.performance.value:.4f}") else: print(" Performance: Not available") if info.node.exception_was_raised: print(f" Status: Failed ({type(info.node.exception).__name__})") else: print(" Status: Success") else: print(" Node info not available for this iteration.") def on_build_end(self, info: BuildStateInfo) -> None: print(f"\n✅ Build process finished.") # Instantiate the custom callback progress_callback = ProgressPrinterCallback() # Build the model with the custom callback model.build( datasets=datasets, provider="openai/gpt-4o-mini", max_iterations=2, callbacks=[progress_callback], # Add custom callback chain_of_thought=False # Disable default verbose logging ) ``` By implementing custom callbacks, you can integrate Plexe's model building process seamlessly into your existing workflows and monitoring systems. # Authentication Source: https://docs.plexe.ai/pages/platform/explanation/authentication Understanding authentication and security in the Plexe Platform. ## Authentication Overview The Plexe Platform uses a robust authentication system to secure access to your resources and services. This page explains how authentication works, how to manage API keys, and best practices for security. ## Authentication Methods ### API Keys For programmatic access to the Plexe API, API keys are the primary authentication method. API keys: * Are long, random strings prefixed with `plx_sk_` * Must be included in the `x-api-key` header of all API requests * Have specific permission levels assigned when created * Can be revoked or rotated at any time * Are tied to your account for usage tracking and billing Example API request with authentication: ```bash curl -X GET https://api.plexe.ai/models \ -H "x-api-key: plx_sk_12345abcdef67890ghijklmnop" ``` ### Console Authentication For access to the [Plexe Console](https://console.plexe.ai), the following authentication methods are supported: 1. **Email/Password:** Standard account credentials 2. **OAuth Providers:** Sign in with Google, GitHub, etc. (if enabled) The Console uses secure, token-based authentication with automatic session expiration for security. ## Managing API Keys ### Creating API Keys API keys can be created in two ways: 1. **Via the Console:** * Navigate to the Settings → API Keys section * Click "Create New API Key" * Assign a descriptive name and required permissions * Copy the key immediately (it will only be shown once) 2. **Via the API:** * You can programmatically create API keys using an existing key with appropriate permissions * See the [Manage API Keys](/platform/how-to/manage_api_keys) guide for details ## Security Features ### TLS Encryption All communication with the Plexe Platform (both API and Console) is encrypted using TLS (HTTPS). This ensures that your data and authentication credentials are protected in transit. ### Key Visibility For security, full API keys are only displayed once at creation time. After that, the Console will only show a truncated version (first few and last few characters). ### Access Logs The Platform maintains comprehensive logs of authentication attempts and API key usage. These can be viewed in the Console for security monitoring and auditing. ### Rate Limiting To protect against brute force and denial of service attacks, the API implements rate limiting. If you exceed the allowed request rate, you'll receive a `429 Too Many Requests` status code. ### Session Management For Console users, sessions automatically expire after periods of inactivity. Sensitive actions may require re-authentication for additional security. ## Authentication Errors Common authentication-related errors you may encounter: | HTTP Status | Error Code | Description | | ----------- | -------------------------- | ----------------------------------------------------- | | 401 | `invalid_key` | API key is invalid or malformed | | 401 | `expired_key` | API key has expired | | 401 | `revoked_key` | API key has been revoked | | 403 | `insufficient_permissions` | API key lacks required permissions for this operation | | 429 | `rate_limit_exceeded` | Too many requests in a given time period | ## Example Authentication Workflows ### API Key Authentication in Python ```python import requests import os # Best practice: Load API key from environment variable api_key = os.environ.get("PLEXE_API_KEY") if not api_key: raise ValueError("PLEXE_API_KEY environment variable not set") # Set up headers with authentication headers = { "x-api-key": api_key, "Content-Type": "application/json" } # Make authenticated request response = requests.get( "https://api.plexe.ai/models", headers=headers ) # Check for authentication errors if response.status_code == 401: print("Authentication failed: Invalid or expired API key") elif response.status_code == 403: print("Permission denied: Your API key doesn't have access to this resource") else: # Process successful response print(f"Success! Found {len(response.json())} models") ``` ### API Key Rotation Best Practice ```python import requests import os import json from datetime import datetime # Current and new API keys (latter will be obtained from API response) current_api_key = os.environ.get("PLEXE_API_KEY") new_api_key = None # Headers for the request to create new key headers = { "x-api-key": current_api_key, "Content-Type": "application/json" } # Step 1: Create a new API key try: create_response = requests.post( "https://api.plexe.ai/auth/api-keys", headers=headers, json={ "name": "Rotated Key " + datetime.now().strftime("%Y-%m-%d"), "permission_level": "read_write" } ) if create_response.status_code == 200: result = create_response.json() new_api_key = result.get("key") key_id = result.get("key_id") print(f"Created new API key with ID: {key_id}") else: print(f"Failed to create new key: {create_response.text}") exit(1) # Step 2: Verify the new key works verify_headers = { "x-api-key": new_api_key, "Content-Type": "application/json" } verify_response = requests.get( "https://api.plexe.ai/models", headers=verify_headers ) if verify_response.status_code == 200: print("New key verified working!") # Step 3: Revoke the old key # First, list keys to find the old key ID list_response = requests.get( "https://api.plexe.ai/auth/api-keys", headers=verify_headers ) if list_response.status_code == 200: keys = list_response.json().get("keys", []) old_keys = [k for k in keys if k["key_id"] != key_id] if old_keys: old_key_id = old_keys[0]["key_id"] revoke_response = requests.delete( f"https://api.plexe.ai/auth/api-keys/{old_key_id}", headers=verify_headers ) if revoke_response.status_code == 200: print("Old key successfully revoked") else: print(f"Failed to revoke old key: {revoke_response.text}") else: print("No old keys found to revoke") else: print(f"Failed to list keys: {list_response.text}") else: print(f"New key verification failed: {verify_response.text}") print("Keeping old key active") except Exception as e: print(f"Error during key rotation: {e}") ``` ## Enterprise Authentication Features Enterprise SSO integration is on our roadmap. Please contact Plexe's support team if you need specific authentication solutions for your organization. ## Further Reading * [Manage API Keys](/platform/how-to/manage_api_keys) - Step-by-step guide for API key management * [Manage Account](/platform/how-to/manage_account) - How to manage your account settings * [Billing Explanation](/platform/explanation/billing) - Understand how authentication relates to billing # Platform Concepts Source: https://docs.plexe.ai/pages/platform/explanation/concepts Core concepts and architecture of the Plexe Platform. ## What is the Plexe Platform? The Plexe Platform is a managed service providing a full-featured, scalable system for creating, managing, and deploying machine learning models. It offers both a web-based Console UI and a comprehensive REST API. While the Plexe library is designed for users who want to integrate model creation directly into their Python workflows, the Platform provides a service-oriented approach with additional features for deployment, management, and monitoring. ## Key Components The Plexe Platform consists of several interconnected components: ### Console UI The web-based interface at [console.plexe.ai](https://console.plexe.ai) where users can: * Create and manage models visually * Upload and analyze datasets * Monitor model training * View metrics and logs * Manage deployments * Handle API keys and account settings ### REST API Available at [api.plexe.ai](https://api.plexe.ai), the REST API provides programmatic access to all platform features, allowing for integration with applications, scripts, and workflows. All actions possible in the Console UI can also be performed via the API. ### Model Building System The core engine that powers model creation, using multi-agent AI systems to: * Analyze user intent and data * Generate appropriate ML code * Execute training processes * Evaluate models * Produce optimized inference code ### Serving Infrastructure Once a model is built, it can be deployed to Plexe's serving infrastructure, which provides: * Scalable inference endpoints * Load balancing * Monitoring and logging * High availability * Performance optimization ### Storage System Manages various types of data and artifacts: * User data uploads * Trained models and artifacts * Inference logs * Analytics data ## Core Workflow The standard workflow for using the Plexe Platform follows these steps: 1. **Authentication:** Access the platform using API keys or Console UI login 2. **Data Upload:** Provide your training data (optional but recommended) 3. **Model Building:** Define your model requirements using natural language 4. **Status Monitoring:** Track the model building progress 5. **Deployment:** Deploy successful models for production use 6. **Inference:** Use deployed models to make predictions via API 7. **Monitoring & Maintenance:** Monitor performance and update as needed ## Key Concepts ### Models A **model** in the Plexe Platform represents a specific ML solution created to address your needs. Each model has: * A unique name * One or more versions (iterations) * Associated metadata * Performance metrics * Input/output schemas ### Versions Each model can have multiple **versions**, representing different iterations or updates. Each version: * Has unique metrics and characteristics * Can be deployed independently * Maintains its own artifacts and code ### Deployments A **deployment** makes a specific model version available for inference. Deployments: * Have a unique URL endpoint * Can be scaled up or down * Can be monitored for performance and usage * Can be updated or rolled back ### API Keys **API keys** are used for authentication with the Plexe API. Each key: * Has specific permissions (read-only or read-write) * Is associated with your account * Can be revoked if compromised * Is used to track usage and credit consumption ## Architecture Overview At a high level, the Plexe Platform architecture follows a microservices approach: 1. **API Gateway:** Handles authentication, rate limiting, and request routing 2. **Auth Service:** Manages accounts, permissions, and API keys 3. **Data Service:** Handles data uploads, storage, and pre-processing 4. **Model Service:** Coordinates model building and versioning 5. **Execution Service:** Runs the generated code in secure environments 6. **Inference Service:** Handles prediction requests to deployed models 7. **Billing Service:** Tracks usage and manages credits ## Differences from the Python Library While the Plexe Platform builds on the same core technology as the Python library, there are some key differences: | Feature | Python Library | Platform | | ------------------ | ---------------------------------------- | ------------------------------------------- | | **Environment** | Runs in your local or custom environment | Fully managed cloud environment | | **Infrastructure** | You manage compute resources | Plexe manages all infrastructure | | **Scalability** | Limited by your local resources | Auto-scaling based on demand | | **Authentication** | Environment variables for API keys | JWT tokens & API key management | | **Persistence** | Manual save/load to files | Automatic versioning and storage | | **Deployment** | Manual integration with your services | One-click deployment to endpoints | | **Monitoring** | Basic callbacks and logging | Comprehensive monitoring & alerting | | **Collaboration** | Code-based sharing | Team access and permissions | | **Billing** | Pay only for LLM API usage | Platform subscription & usage-based billing | ## Security Model The Plexe Platform implements several security measures: 1. **Authentication:** API keys and user authentication (JWT tokens) 2. **Authorization:** Role-based permissions for API keys 3. **Isolation:** Secure execution environments for code generation and training 4. **Encryption:** Data encryption in transit and at rest 5. **Monitoring:** Logging of access patterns and usage ## Deployment Options The Platform can be deployed in different configurations depending on your needs: * **Hosted Service:** The standard managed offering at api.plexe.ai * **Enterprise Mode:** For self-hosted deployments without authentication requirements. Please contact us at [vdubey@plexe.ai](mailto:vdubey@plexe.ai). ## Next Steps Now that you understand the core concepts of the Plexe Platform, you can: * Learn how to [manage your account](/platform/how-to/manage_account) * Explore how to [work with API keys](/platform/how-to/manage_api_keys) * See how to [upload data](/platform/how-to/upload_data_api) for your models * Follow the [quickstart tutorial](/platform/tutorials/quickstart_api) to build your first model # Build Models via API Source: https://docs.plexe.ai/pages/platform/how-to/build_model_api Initiate and configure machine learning model builds using the Plexe Platform REST API. You can start the automated model building process on the Plexe Platform by making a `POST` request to the model creation endpoint. **Base URL:** `https://api.plexe.ai` ## Prerequisites * You have a Plexe Platform account and a valid [API Key](/platform/how-to/manage_api_keys). * (Optional but Recommended) You have [uploaded your data](/platform/how-to/upload_data_api) and have the resulting `upload_id`(s). ## Authentication Include your API key in the `x-api-key` header. ```python import requests import os import json api_key = os.getenv("PLEXE_API_KEY") if not api_key: raise ValueError("Please set the PLEXE_API_KEY environment variable.") base_url = "https://api.plexe.ai" headers = { "x-api-key": api_key, "Content-Type": "application/json" } ``` ## Starting a Build Job Make a `POST` request to the endpoint for creating models, typically including the desired model name in the path (e.g., `/models/{model_name}`). The request body contains the core configuration for the build: * **`goal`**: (Required) Natural language description of the model's goal. * **`upload_id`**: (Required if not using purely synthetic generation based on goal/schema alone) Reference to your data. This could be: * An ID obtained from the data upload process. * A publicly accessible URL to a dataset (CSV, JSON, etc. - check API reference for supported URL types). * **`input_schema`**: (Optional) Dictionary defining the input features and types (e.g., `{"feature1": "float", "feature2": "str"}`). Plexe will try to infer if omitted and `upload_id` is provided. * **`output_schema`**: (Optional) Dictionary defining the output prediction(s) and types (e.g., `{"prediction": "int", "probability": "float"}`). Plexe will try to infer if omitted. * **`metric`**: (Optional) Suggest a primary metric to optimize (e.g., `"accuracy"`, `"rmse"`, `"f1"`). Plexe will select an appropriate default if omitted. * **`max_iterations`**: (Optional) Maximum number of different modeling approaches the agent system should try (default might be 1 or 3, check API reference). Higher values increase build time and cost but may yield better models. * **`provider`**: (Optional) Specify the LLM provider/model to use (e.g., `"openai/gpt-4o-mini"`). Uses the platform default if omitted. See [Configure LLM Providers](/library/how-to/configure_llm_provider) (concepts apply similarly here). ```python model_name = "customer-churn-predictor-v1" # Choose a unique name for your model upload_id = "YOUR_UPLOAD_ID" # Replace with the ID from your data upload build_payload = { "goal": "Predict customer churn based on usage patterns like login frequency, support tickets, and subscription duration.", "upload_id": upload_id, # Use the ID obtained from data upload # Optionally provide schemas if inference is not desired or needs guidance # "input_schema": { # "login_frequency_last_30d": "int", # "support_tickets_last_90d": "int", # "subscription_months": "int", # "plan_type": "str" # }, # "output_schema": { # "churn_prediction": "int" # e.g., 1 for churn, 0 for no churn # }, "metric": "f1", # Optimize for F1 score "max_iterations": 5 # Try up to 5 approaches } print(f"Starting build for model: {model_name}") try: response = requests.post( f"{base_url}/models/{model_name}", headers=headers, json=build_payload ) response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx) build_result = response.json() model_id = build_result.get("model_id") # Typically format: name:version or similar print("\nBuild request submitted successfully!") print(f" Model ID: {model_id}") print(f" Initial Status: {build_result.get('status')}") print(f"Monitor progress using the status endpoint.") # Store model_id for status checking and inference later # Example: store model_name and model_version if ID is like "name:version" if model_id and ':' in model_id: m_name, m_version = model_id.split(':', 1) print(f" Model Name: {m_name}, Model Version: {m_version}") else: # Handle cases where model_id format might differ print(" Could not parse model name/version from model_id.") except requests.exceptions.HTTPError as http_err: print(f"HTTP error occurred: {http_err}") print(f"Response Text: {http_err.response.text}") except requests.exceptions.ConnectionError as conn_err: print(f"Connection error occurred: {conn_err}") except Exception as err: print(f"Other error occurred: {err}") ``` ## Checking Build Status After submitting a build request, you'll want to monitor its progress. Use the status endpoint to check on your model's build status: ```python def check_build_status(model_name, model_version): """Check the status of a model build""" try: status_url = f"{base_url}/models/{model_name}/{model_version}/status" response = requests.get( status_url, headers=headers ) response.raise_for_status() status_data = response.json() # Print current status information print(f"Model: {model_name} (Version: {model_version})") print(f"Status: {status_data.get('status')}") print(f"Updated: {status_data.get('updated_at')}") # If there's an error message, display it if status_data.get('error_message'): print(f"Error: {status_data.get('error_message')}") return status_data except requests.exceptions.HTTPError as http_err: print(f"HTTP error occurred: {http_err}") return None except Exception as err: print(f"Error checking status: {err}") return None # Example usage after getting model_name and model_version from the build response if model_id and ':' in model_id: m_name, m_version = model_id.split(':', 1) status = check_build_status(m_name, m_version) ``` Once your model's status is `"completed"`, you can proceed to making inferences with it using the [deployed model inference API](/platform/how-to/use_deployed_model). # Manage Your Account Source: https://docs.plexe.ai/pages/platform/how-to/manage_account Sign up, view account details, and monitor credit usage on the Plexe Platform. Manage your Plexe Platform account through the web console. ## Signing Up 1. Go to the [Plexe Console](https://console.plexe.ai). 2. Follow the on-screen instructions to sign up using your preferred method (e.g., email/password, Google, GitHub - depending on supported providers). 3. Verify your email address if required. ## Viewing Account Details Once logged in, you can typically find your account details in a dedicated "Account" or "Settings" section of the console. This usually includes: * **User ID:** Your unique identifier within the Plexe system. * **Email:** The email address associated with your account. * **Name:** Your display name. * **Username:** Your assigned username. * **Account Status:** Whether your account is active. ## Monitoring Usage and Credits Plexe Platform operations, such as model building and inference, consume compute resources, which are measured in credits. * **Available Credits:** Check your current credit balance in the "Billing" or "Usage" section of the console. You start with a certain number of free credits (if applicable) or credits obtained through a subscription/purchase. * **Consumption:** This section usually shows your credit consumption over time or per operation. Operations like building complex models or running many inferences will consume more credits. * **Billing:** Details about your subscription plan, payment methods, and invoices can typically be found here. {/* Info component with proper JSX syntax */} Specific credit costs for operations (e.g., credits per build iteration, credits per inference call) should be available in the "Billing" section or pricing page. The platform automatically deducts credits as you use services. If your balance reaches zero, you may need to purchase more credits or upgrade your plan to continue using paid features. Refer to the [Billing Explanation](/platform/explanation/billing) page for more details on how credits and consumption work. ## Managing Account via API You can also view your account details and usage information through the API: ```python import requests import os api_key = os.getenv("PLEXE_API_KEY") if not api_key: raise ValueError("Please set the PLEXE_API_KEY environment variable.") base_url = "https://api.plexe.ai" headers = { "x-api-key": api_key, "Content-Type": "application/json" } # Get user profile with usage information try: response = requests.get( f"{base_url}/usage/profile", headers=headers ) response.raise_for_status() profile = response.json() print(f"User ID: {profile.get('user_id')}") print(f"Email: {profile.get('email')}") print(f"Name: {profile.get('name')}") print(f"Credits Available: {profile.get('usage', {}).get('credits', 0)}") print(f"Consumption: {profile.get('usage', {}).get('consumption', 0)}") except requests.exceptions.HTTPError as http_err: print(f"HTTP error occurred: {http_err}") except Exception as err: print(f"Error occurred: {err}") ``` The `/usage/current` endpoint can also be used to get just your current credit usage without the profile information. # Upload Data via API Source: https://docs.plexe.ai/pages/platform/how-to/upload_data_api Upload your datasets to the Plexe Platform using the REST API. To build models on the Plexe Platform using your own data, you first need to upload it. The API typically provides a mechanism to upload files, often involving pre-signed URLs for direct S3 uploads. **Base URL:** `https://api.plexe.ai` The Plexe Platform uses a secure upload mechanism with pre-signed URLs to protect your data during transfer. This allows you to upload files directly to secure cloud storage without exposing your API key in the process. For more details on the API endpoints, refer to the [Data Management API Reference](/platform/reference/endpoints/data). ## Authentication Ensure you have your API key included in the `x-api-key` header. ```python import requests import os import json api_key = os.getenv("PLEXE_API_KEY") if not api_key: raise ValueError("Please set the PLEXE_API_KEY environment variable.") base_url = "https://api.plexe.ai" headers = { "x-api-key": api_key, "Content-Type": "application/json" # Usually for control requests } ``` ## Upload Process (Using Pre-signed URLs) This is typically a multi-step process: 1. **Request Upload URL:** Tell the API you want to upload a file and get a secure, temporary URL to upload directly to storage (usually S3). 2. **Upload File:** Use the provided URL to upload your file data. 3. **Confirm Upload:** Notify the API that the upload to the storage location is complete. ### Step 1: Request Pre-signed Upload URL Make a `POST` request to the upload initiation endpoint (e.g., `/uploads`). Provide the filename and content type. ```python file_path = "path/to/your/training_data.csv" # Replace with your file path file_name = os.path.basename(file_path) content_type = "text/csv" # Adjust based on your file type (e.g., 'application/json', 'application/octet-stream') print(f"Requesting upload URL for: {file_name}") try: init_response = requests.post( f"{base_url}/uploads", headers=headers, json={"filename": file_name, "content_type": content_type} ) init_response.raise_for_status() upload_info = init_response.json() presigned_url = upload_info.get("presigned_url") temp_upload_id = upload_info.get("upload_id") s3_key = upload_info.get("key") if not presigned_url or not temp_upload_id or not s3_key: raise ValueError("Incomplete upload information received from API.") print(f"Successfully obtained upload URL. Temporary Upload ID: {temp_upload_id}") except requests.exceptions.RequestException as e: print(f"Error requesting upload URL: {e}") if e.response is not None: print(f"Response: {e.response.text}") presigned_url, temp_upload_id, s3_key = None, None, None except (ValueError, json.JSONDecodeError) as e: print(f"Error processing API response: {e}") presigned_url, temp_upload_id, s3_key = None, None, None ``` ### Step 2: Upload File to Pre-signed URL Use the `presigned_url` obtained in Step 1 to `PUT` your file data. **Note:** Do *not* include your `x-api-key` header in this request; authentication is handled by the pre-signed URL itself. The `Content-Type` header *must* match the one you specified when requesting the URL. ```python if presigned_url: print(f"Uploading {file_name} to S3...") try: with open(file_path, 'rb') as f: upload_response = requests.put( presigned_url, data=f, headers={'Content-Type': content_type} ) upload_response.raise_for_status() print("File successfully uploaded to S3.") upload_succeeded = True except FileNotFoundError: print(f"Error: Local file not found at {file_path}") upload_succeeded = False except requests.exceptions.RequestException as e: print(f"Error uploading file to S3: {e}") if e.response is not None: print(f"Response: {e.response.text}") upload_succeeded = False else: print("Skipping file upload due to previous error.") upload_succeeded = False ``` ### Step 3: Confirm Upload Completion Notify the Plexe API that the file upload to the pre-signed URL is complete using the temporary `upload_id` and `s3_key`. ```python upload_id = None # Final ID will be set here if upload_succeeded and temp_upload_id and s3_key: print("Confirming upload status with Plexe API...") try: confirm_response = requests.post( f"{base_url}/uploads/status", headers=headers, json={ "upload_id": temp_upload_id, "filename": file_name, "s3_key": s3_key } ) confirm_response.raise_for_status() upload_status = confirm_response.json() final_upload_id = upload_status.get("upload_id") final_status = upload_status.get("status") if final_status == "complete" and final_upload_id: upload_id = final_upload_id # Store the final ID for use in model building print(f"Upload confirmed successfully! Final Upload ID: {upload_id}") else: print(f"Upload confirmation failed or status not complete: {upload_status}") except requests.exceptions.RequestException as e: print(f"Error confirming upload: {e}") if e.response is not None: print(f"Response: {e.response.text}") except json.JSONDecodeError as e: print(f"Error processing confirmation response: {e}") else: print("Skipping upload confirmation due to previous error.") if upload_id: print(f"\nData upload process complete. Use Upload ID '{upload_id}' when building models.") else: print("\nData upload process failed or was skipped.") ``` You can now use the final `upload_id` when submitting model build requests that require this dataset. For example: ```python # Example of how to use the upload_id in a model build request if upload_id: model_build_data = { "upload_id": upload_id, # Use the upload_id returned from the upload process "goal": "Predict customer churn based on usage patterns", # Natural language description of your model's purpose "metric": "f1_score" # The metric to optimize for } try: model_name = "customer_churn_model" model_build_response = requests.post( f"{base_url}/models/{model_name}", headers=headers, json=model_build_data ) model_build_response.raise_for_status() build_result = model_build_response.json() print(f"Model build initiated successfully: {build_result}") except requests.exceptions.RequestException as e: print(f"Error initiating model build: {e}") if e.response is not None: print(f"Response: {e.response.text}") ``` You can upload multiple files and reference them by their respective `upload_id`s for different model building tasks. # Use Deployed Models Source: https://docs.plexe.ai/pages/platform/how-to/use_deployed_model Learn how to make predictions with deployed models on the Plexe Platform. After you've built and deployed a model on the Plexe Platform, you can use its API endpoint to make predictions (inferences). This guide explains how to interact with deployed models to get predictions for your data. ## Prerequisites * A model that has been successfully deployed (status: `READY`) * The deployment ID or endpoint URL * A valid API key with appropriate permissions * The input schema for your model (what data format it expects) ## Getting the Endpoint URL Before making predictions, you need to know your model's endpoint URL. You can obtain this in several ways: ### From the Console 1. Log in to [Plexe Console](https://console.plexe.ai) 2. Navigate to **Models** → **Deployments** 3. Select your deployment 4. Copy the endpoint URL from the **Overview** tab ### Via the API When you deploy a model on the Plexe Platform, you'll be able to get the inference URL from the model status. The URL will be in the format: ``` https://api.plexe.ai/models/{model_name}/{model_version}/infer ``` Where: * `{model_name}` is the name of your model * `{model_version}` is the version number of your model ## Making Single Predictions For predictions with a single data point, use the simple prediction endpoint. ### Using cURL ```bash curl -X POST https://api.plexe.ai/models/{model_name}/{model_version}/infer \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "feature1": "value1", "feature2": 42, "feature3": true }' ``` The response will contain the prediction result: ```json { "request_id": "req_789012", "result": { "predicted_class": "category_b", "confidence": 0.87 }, "model_id": "model_789xyz", "model_version": "1", "processing_time_ms": 28 } ``` ### Using Python ```python import requests import json API_KEY = "YOUR_API_KEY" MODEL_NAME = "your_model_name" MODEL_VERSION = "1" # Typically "1" for the first version BASE_URL = "https://api.plexe.ai" def get_prediction(input_data): """ Get a prediction from a deployed model. Args: input_data (dict): The input data matching the model's expected schema Returns: dict: The prediction result """ headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } endpoint = f"{BASE_URL}/models/{MODEL_NAME}/{MODEL_VERSION}/infer" try: response = requests.post( endpoint, headers=headers, data=json.dumps(input_data) ) response.raise_for_status() # Raise exception for error status codes return response.json() except requests.exceptions.RequestException as e: print(f"Error making prediction: {e}") if hasattr(e, 'response') and e.response is not None: print(f"Response: {e.response.text}") return None # Example usage input_data = { "square_footage": 1950, "bedrooms": 3, "bathrooms": 2.5, "location": "suburban" } result = get_prediction(input_data) if result: print(f"Prediction result: {result['result']}") print(f"Request ID: {result['request_id']}") print(f"Processing time: {result['processing_time_ms']} ms") ``` ### Using JavaScript ```javascript async function getPrediction(inputData) { const apiKey = "YOUR_API_KEY"; const modelName = "your_model_name"; const modelVersion = "1"; // Typically "1" for the first version const endpoint = `https://api.plexe.ai/models/${modelName}/${modelVersion}/infer`; try { const response = await fetch(endpoint, { method: 'POST', headers: { 'x-api-key': apiKey, 'Content-Type': 'application/json' }, body: JSON.stringify(inputData) }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return await response.json(); } catch (error) { console.error("Error making prediction:", error); return null; } } // Example usage const inputData = { square_footage: 1950, bedrooms: 3, bathrooms: 2.5, location: "suburban" }; getPrediction(inputData) .then(result => { if (result) { console.log("Prediction result:", result.result); console.log("Request ID:", result.request_id); console.log("Processing time:", result.processing_time_ms, "ms"); } }); ``` ## Making Batch Predictions For making predictions with multiple data points at once, use the batch predictions endpoint. This is more efficient than making multiple individual requests. ### Using cURL ```bash curl -X POST "https://api.plexe.ai/models/{model_name}/{model_version}/predictions" \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '[ { "feature1": "value1", "feature2": 42, "feature3": true }, { "feature1": "value2", "feature2": 35, "feature3": false } ]' ``` ### Using Python ```python def get_batch_predictions(input_data_list): """ Get batch predictions from a deployed model. Args: input_data_list (list): List of input data objects Returns: list: List of prediction results """ headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } endpoint = f"{BASE_URL}/models/{MODEL_NAME}/{MODEL_VERSION}/predictions" try: response = requests.post( endpoint, headers=headers, data=json.dumps(input_data_list) ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f"Error making batch predictions: {e}") if hasattr(e, 'response') and e.response is not None: print(f"Response: {e.response.text}") return None # Example usage batch_input_data = [ { "square_footage": 1950, "bedrooms": 3, "bathrooms": 2.5, "location": "suburban" }, { "square_footage": 1200, "bedrooms": 2, "bathrooms": 1, "location": "urban" } ] batch_results = get_batch_predictions(batch_input_data) if batch_results: for i, result in enumerate(batch_results): print(f"Prediction {i+1}: {result['prediction']}") ``` {/* Input validation API endpoints will be available in a future release. For now, we recommend implementing validation in your client application before sending requests to the model. */} ## Handling Errors ### Common Error Codes | HTTP Status | Error Code | Description | | ----------- | ------------------------ | --------------------------------------------------- | | 400 | `invalid_input` | Input doesn't match model schema | | 401 | `unauthorized` | Missing or invalid API key | | 403 | `forbidden` | API key doesn't have permission for this deployment | | 404 | `not_found` | Deployment ID doesn't exist | | 429 | `rate_limit_exceeded` | Too many requests in the allowed time period | | 500 | `prediction_error` | Error occurred during model prediction | | 503 | `deployment_unavailable` | Deployment is not in READY state | ### Error Response Format ```json { "error": { "code": "invalid_input", "message": "Input validation failed", "details": { "feature2": "must be a number between 0 and 100" } }, "request_id": "req_789012" } ``` ### Python Error Handling Example ```python import requests import json import time API_KEY = "YOUR_API_KEY" MODEL_NAME = "your_model_name" MODEL_VERSION = "1" BASE_URL = "https://api.plexe.ai" def get_prediction_with_retry(input_data, max_retries=3, initial_backoff=1): """ Get a prediction with retry logic for transient errors. Args: input_data (dict): The input data max_retries (int): Maximum number of retry attempts initial_backoff (float): Initial backoff time in seconds (doubles each retry) Returns: dict: The prediction result or None if failed """ headers = { "x-api-key": API_KEY, "Content-Type": "application/json" } endpoint = f"{BASE_URL}/models/{MODEL_NAME}/{MODEL_VERSION}/infer" backoff = initial_backoff for attempt in range(max_retries + 1): try: response = requests.post( endpoint, headers=headers, data=json.dumps(input_data), timeout=10 # 10-second timeout ) # If successful, return the result if response.status_code == 200: return response.json() # Handle different error types if response.status_code == 400: # Bad request - no point retrying error_data = response.json().get("error", {}) print(f"Input validation error: {error_data.get('message')}") print(f"Details: {error_data.get('details')}") return None elif response.status_code == 429: # Rate limit - should retry with backoff if attempt < max_retries: print(f"Rate limit exceeded. Retrying in {backoff} seconds...") time.sleep(backoff) backoff *= 2 # Exponential backoff continue else: print("Maximum retries reached. Rate limit still exceeded.") return None elif response.status_code in (503, 504): # Service unavailable or gateway timeout - retry if attempt < max_retries: print(f"Service temporarily unavailable. Retrying in {backoff} seconds...") time.sleep(backoff) backoff *= 2 continue else: print("Maximum retries reached. Service still unavailable.") return None # Other errors try: error_data = response.json().get("error", {}) print(f"Error: {error_data.get('code')} - {error_data.get('message')}") except: print(f"HTTP Error: {response.status_code} - {response.text}") return None except requests.exceptions.Timeout: if attempt < max_retries: print(f"Request timed out. Retrying in {backoff} seconds...") time.sleep(backoff) backoff *= 2 continue else: print("Maximum retries reached. Requests still timing out.") return None except requests.exceptions.RequestException as e: print(f"Request error: {e}") return None return None # Should not reach here but just in case ``` {/* Advanced features such as explanation requests and field filtering will be available in a future release. */} ## Best Practices 1. **Input Validation**: Validate inputs before sending to avoid unnecessary API calls 2. **Error Handling**: Implement robust error handling with retries for transient errors 3. **Logging**: Log request IDs and responses for troubleshooting 4. **Batch Processing**: Use the batch predictions endpoint (`/predictions`) for processing multiple inputs efficiently 5. **Rate Limiting**: Manage your request rate to avoid hitting rate limits 6. **Monitoring**: Track latency and error rates for your production deployments 7. **Caching**: Consider caching prediction results for identical inputs 8. **Timeouts**: Set appropriate timeouts for your application's needs ## Performance Optimization 1. **Batch When Possible**: Use batch predictions for multiple inputs 2. **Minimize Payload Size**: Only include required fields in your requests 3. **Connection Pooling**: Reuse HTTP connections for multiple requests 4. **Use CDNs**: If serving model in user-facing applications, consider a CDN in front of your API calls 5. **Regional Endpoints**: Use the endpoint closest to your application (if multiple regions are supported) ## Security Considerations 1. **API Key Management**: Rotate keys regularly and use the principle of least privilege 2. **Input Sanitization**: Validate and sanitize all inputs before sending to the API 3. **TLS/HTTPS**: Always use HTTPS (the API will reject HTTP requests) 4. **Response Handling**: Don't expose full API responses to end users 5. **Rate Limiting**: Implement your own rate limiting to avoid service disruption # Authentication API Source: https://docs.plexe.ai/pages/platform/reference/endpoints/auth API reference for authentication, API keys, and user management on the Plexe Platform. This document provides detailed information about the authentication endpoints of the Plexe Platform API. ## API Keys ### Create API Key Creates a new API key for your account. ```http POST /auth/api-keys ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | #### Request Body ```json { "name": "Production Backend Key", "permission_level": "read_write" } ``` | Parameter | Type | Required | Description | | ------------------ | ------ | -------- | --------------------------------------------- | | `name` | string | Yes | Descriptive name for the API key | | `permission_level` | string | Yes | Permission level: `read_only` or `read_write` | #### Response ```json { "key_id": "key_abc123def456", "name": "Production Backend Key", "key": "plx_sk_987654321abcdefg...", // Full key shown ONLY once "permission_level": "read_write", "created_at": "2024-05-01T12:00:00Z", "expires_at": "2024-07-30T12:00:00Z", // Or null if no expiration "created_by": "user@example.com" } ``` {/* Warning component with proper JSX syntax */} The full API key value (`key` field) is displayed only once when the key is created. Store it securely as you won't be able to retrieve it again. ### List API Keys Returns a list of all API keys for your account. ```http GET /auth/api-keys ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | #### Query Parameters | Parameter | Type | Required | Description | | --------- | ------- | -------- | -------------------------------------------------------- | | `status` | string | No | Filter by status: `active` or `revoked` | | `limit` | integer | No | Maximum number of keys to return (default: 20, max: 100) | | `offset` | integer | No | Number of keys to skip for pagination (default: 0) | #### Response ```json { "keys": [ { "key_id": "key_abc123def456", "name": "Production Backend Key", "key_prefix": "plx_sk_9876", // First 4 digits + last 4 digits for identification "key_suffix": "defg", "permission_level": "read_write", "created_at": "2024-05-01T12:00:00Z", "expires_at": "2024-07-30T12:00:00Z", "last_used_at": "2024-05-10T15:22:43Z", "status": "active", "created_by": "user@example.com" }, { "key_id": "key_ghi789jkl012", "name": "Development Key", "key_prefix": "plx_sk_1234", "key_suffix": "zyxw", "permission_level": "admin", "created_at": "2024-04-15T09:30:00Z", "expires_at": null, "last_used_at": "2024-05-11T08:17:22Z", "status": "active", "created_by": "admin@example.com" } ], "pagination": { "total": 5, "limit": 20, "offset": 0, "has_more": false } } ``` ### Get API Key Retrieves details for a specific API key. ```http GET /auth/api-keys/{keyId} ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ----------------------------- | | `keyId` | string | Yes | ID of the API key to retrieve | #### Response ```json { "key_id": "key_abc123def456", "name": "Production Backend Key", "key_prefix": "plx_sk_9876", "key_suffix": "defg", "permission_level": "read_write", "created_at": "2024-05-01T12:00:00Z", "expires_at": "2024-07-30T12:00:00Z", "last_used_at": "2024-05-10T15:22:43Z", "status": "active", "created_by": "user@example.com", "usage_stats": { "requests_last_24h": 156, "requests_last_7d": 1287, "requests_last_30d": 4583 } } ``` ### Update API Key Updates the name or expiration of an API key. ```http PATCH /auth/api-keys/{keyId} ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | --------------------------- | | `keyId` | string | Yes | ID of the API key to update | #### Request Body ```json { "name": "Updated Name", "expiration_days": 180 // Updates expiration to 180 days from now } ``` | Parameter | Type | Required | Description | | ----------------- | ------- | -------- | ------------------------------------------------- | | `name` | string | No | New name for the API key | | `expiration_days` | integer | No | New expiration period (in days) from current date | #### Response ```json { "key_id": "key_abc123def456", "name": "Updated Name", "key_prefix": "plx_sk_9876", "key_suffix": "defg", "permission_level": "read_write", "created_at": "2024-05-01T12:00:00Z", "expires_at": "2024-10-28T12:00:00Z", // Updated expiration "last_used_at": "2024-05-10T15:22:43Z", "status": "active", "created_by": "user@example.com" } ``` {/* Note component with proper JSX syntax */} You cannot change the permission level of an existing key. Create a new key with the desired permissions instead. ### Revoke API Key Revokes (invalidates) an API key, preventing its further use. ```http DELETE /auth/api-keys/{keyId} ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | --------------------------- | | `keyId` | string | Yes | ID of the API key to revoke | #### Response ```json { "key_id": "key_abc123def456", "status": "revoked", "revoked_at": "2024-05-11T14:30:45Z" } ``` {/* Warning component with proper JSX syntax */} Revoking an API key is permanent and cannot be undone. Applications using the revoked key will immediately lose access. ## User Management The following endpoint is available to retrieve user information for the currently authenticated user. ### Get Current User Returns information about the currently authenticated user. ```http GET /auth/user ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | #### Response ```json { "user_id": "user_abc123", "email": "user@example.com", "name": "Example User", "user_name": "user", "credits": 1000, "consumption": 50, "is_active": true, "has_api_key": true } ``` Multi-Factor Authentication will be available in a future release. ## Error Codes | HTTP Status | Error Code | Description | | ----------- | ------------------- | ------------------------ | | 400 | `invalid_request` | The request was invalid | | 401 | `unauthorized` | Authentication failed | | 403 | `forbidden` | Insufficient permissions | | 404 | `not_found` | Resource not found | | 409 | `resource_exists` | Resource already exists | | 422 | `validation_failed` | Validation failed | | 429 | `rate_limited` | Too many requests | | 500 | `server_error` | Internal server error | ## Rate Limits Authentication endpoints have rate limits to prevent abuse: * Key creation: 10 requests per hour * Authentication attempts: 10 failed attempts per 15 minutes Exceeding these limits will result in a `429 Too Many Requests` response. # Data Management API Source: https://docs.plexe.ai/pages/platform/reference/endpoints/data API reference for uploading, managing, and querying datasets on the Plexe Platform. This document outlines the RESTful API endpoints for managing data uploads and querying datasets in the Plexe Platform. ## Uploads ### Get All Uploads Retrieves a list of all data uploads associated with your account. ```http GET /uploads ``` #### Query Parameters | Parameter | Type | Required | Description | | --------- | ------- | -------- | ---------------------------------------------------------------- | | `limit` | integer | No | Maximum number of uploads to return (default: 20, max: 100) | | `offset` | integer | No | Number of uploads to skip for pagination (default: 0) | | `status` | string | No | Filter by status: `pending`, `complete`, `failed`, `processing` | | `sort` | string | No | Field to sort by: `created_at`, `status` (default: `created_at`) | | `order` | string | No | Sort direction: `asc` or `desc` (default: `desc`) | #### Response ```json { "uploads": [ { "upload_id": "upload_abc123def456", "name": "Customer Dataset", "description": "Monthly customer data for churn analysis", "created_at": "2024-05-01T12:00:00Z", "status": "complete", "files": [ { "filename": "customers.csv", "size_bytes": 1024000, "rows": 5000, "columns": 12 }, { "filename": "transactions.csv", "size_bytes": 2048000, "rows": 15000, "columns": 8 } ], "created_by": "user@example.com" }, { "upload_id": "upload_ghi789jkl012", "name": "Product Inventory", "description": null, "created_at": "2024-04-28T09:30:00Z", "status": "complete", "files": [ { "filename": "inventory.csv", "size_bytes": 512000, "rows": 3000, "columns": 10 } ], "created_by": "user@example.com" } ], "pagination": { "total": 15, "limit": 20, "offset": 0, "has_more": false } } ``` ### Get Upload Details Retrieves detailed information about a specific upload. ```http GET /uploads/{upload_id} ``` #### Path Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | ---------------------------- | | `upload_id` | string | Yes | ID of the upload to retrieve | #### Response ```json { "upload_id": "upload_abc123def456", "name": "Customer Dataset", "description": "Monthly customer data for churn analysis", "created_at": "2024-05-01T12:00:00Z", "status": "complete", "files": [ { "filename": "customers.csv", "size_bytes": 1024000, "rows": 5000, "columns": 12, "column_info": [ {"name": "customer_id", "type": "string", "nullable": false, "unique": true}, {"name": "name", "type": "string", "nullable": false, "unique": false}, {"name": "email", "type": "string", "nullable": false, "unique": true}, {"name": "age", "type": "integer", "nullable": true, "unique": false}, {"name": "signup_date", "type": "date", "nullable": false, "unique": false}, {"name": "last_purchase", "type": "date", "nullable": true, "unique": false}, {"name": "purchase_count", "type": "integer", "nullable": false, "unique": false}, {"name": "lifetime_value", "type": "float", "nullable": false, "unique": false}, {"name": "churn", "type": "boolean", "nullable": false, "unique": false}, {"name": "country", "type": "string", "nullable": false, "unique": false}, {"name": "plan_type", "type": "string", "nullable": false, "unique": false}, {"name": "referral_source", "type": "string", "nullable": true, "unique": false} ], "preview_url": "https://api.plexe.ai/uploads/upload_abc123def456/files/customers.csv/preview", "s3_key": "uploads/user123/customers.csv", "content_type": "text/csv", "created_at": "2024-05-01T12:00:00Z" }, { "filename": "transactions.csv", "size_bytes": 2048000, "rows": 15000, "columns": 8, "column_info": [ {"name": "transaction_id", "type": "string", "nullable": false, "unique": true}, {"name": "customer_id", "type": "string", "nullable": false, "unique": false}, {"name": "date", "type": "date", "nullable": false, "unique": false}, {"name": "amount", "type": "float", "nullable": false, "unique": false}, {"name": "product_id", "type": "string", "nullable": false, "unique": false}, {"name": "quantity", "type": "integer", "nullable": false, "unique": false}, {"name": "discount", "type": "float", "nullable": true, "unique": false}, {"name": "payment_method", "type": "string", "nullable": false, "unique": false} ], "preview_url": "https://api.plexe.ai/uploads/upload_abc123def456/files/transactions.csv/preview", "s3_key": "uploads/user123/transactions.csv", "content_type": "text/csv", "created_at": "2024-05-01T12:00:00Z" } ], "created_by": "user@example.com", "models_using_this": [ { "model_id": "model_mno345pqr678", "model_name": "Customer Churn Predictor", "version": "1" } ] } ``` ### Create Upload Initiates a new upload by requesting a pre-signed S3 URL. ```http POST /data/upload ``` #### Request Body ```json { "name": "Customer Dataset", "description": "Monthly customer data for churn analysis", "files": [ { "filename": "customers.csv", "content_type": "text/csv", "size_bytes": 1024000 }, { "filename": "transactions.csv", "content_type": "text/csv", "size_bytes": 2048000 } ] } ``` | Parameter | Type | Required | Description | | ---------------------- | ------- | -------- | ---------------------------------- | | `name` | string | No | Display name for the upload | | `description` | string | No | Description of the upload | | `files` | array | Yes | List of files to upload | | `files[].filename` | string | Yes | Name of the file | | `files[].content_type` | string | Yes | MIME type of the file | | `files[].size_bytes` | integer | No | Expected size of the file in bytes | #### Response ```json { "upload_id": "upload_abc123def456", "name": "Customer Dataset", "description": "Monthly customer data for churn analysis", "status": "pending", "created_at": "2024-05-01T12:00:00Z", "files": [ { "filename": "customers.csv", "presigned_url": "https://s3.amazonaws.com/plexe-uploads/...", "s3_key": "uploads/user123/customers.csv", "content_type": "text/csv" }, { "filename": "transactions.csv", "presigned_url": "https://s3.amazonaws.com/plexe-uploads/...", "s3_key": "uploads/user123/transactions.csv", "content_type": "text/csv" } ], "expires_at": "2024-05-01T13:00:00Z" } ``` After receiving the pre-signed URLs, you must upload each file directly to the provided S3 URLs using HTTP PUT requests. ### Update Upload Status Confirms completion of file uploads to S3 and updates the upload status. ```http POST /uploads/status ``` #### Request Body ```json { "upload_id": "upload_abc123def456", "status": "complete", "files": [ { "filename": "customers.csv", "s3_key": "uploads/user123/customers.csv" }, { "filename": "transactions.csv", "s3_key": "uploads/user123/transactions.csv" } ] } ``` | Parameter | Type | Required | Description | | ------------------ | ------ | -------- | -------------------------------------------------------- | | `upload_id` | string | Yes | ID of the upload to update | | `status` | string | Yes | New status: `complete` to confirm all files are uploaded | | `files` | array | Yes | List of files that were uploaded | | `files[].filename` | string | Yes | Name of the file | | `files[].s3_key` | string | Yes | S3 key of the uploaded file | #### Response ```json { "upload_id": "upload_abc123def456", "status": "processing", "message": "Files uploaded successfully. Processing data...", "estimated_completion": "2024-05-01T12:05:00Z" } ``` After confirming the uploads, the system will process the files (validating, parsing, etc.) and update the status to `complete` when finished. ### Delete Upload Deletes an upload and its associated files. ```http DELETE /uploads/{upload_id} ``` #### Path Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | -------------------------- | | `upload_id` | string | Yes | ID of the upload to delete | #### Response ```json { "upload_id": "upload_abc123def456", "status": "deleted", "deleted_at": "2024-05-02T09:15:00Z" } ``` {/* Warning component with proper JSX syntax */} You cannot delete an upload that is currently being used by a model. Unbind models from the dataset first. ### Get File Preview Retrieves a preview of a file's contents. ```http GET /data/uploads/{upload_id}/files/{filename}/preview ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | #### Path Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | ------------------------------------ | | `upload_id` | string | Yes | ID of the upload containing the file | | `filename` | string | Yes | Name of the file to preview | #### Query Parameters | Parameter | Type | Required | Description | | --------- | ------- | -------- | -------------------------------------------------------- | | `limit` | integer | No | Maximum number of rows to return (default: 10, max: 100) | | `offset` | integer | No | Number of rows to skip (default: 0) | #### Response For CSV files: ```json { "filename": "customers.csv", "total_rows": 5000, "returned_rows": 10, "columns": ["customer_id", "name", "email", "age", "signup_date", "last_purchase", "purchase_count", "lifetime_value", "churn", "country", "plan_type", "referral_source"], "data": [ ["C001", "John Doe", "john@example.com", "34", "2023-01-15", "2024-04-20", "12", "1250.50", "false", "US", "premium", "search"], ["C002", "Jane Smith", "jane@example.com", "28", "2023-02-01", "2024-04-18", "8", "895.75", "false", "CA", "basic", "referral"], ["C003", "Bob Johnson", "bob@example.com", "45", "2023-01-20", "2024-03-15", "3", "350.25", "true", "UK", "premium", "ads"], // ... more rows ] } ``` For JSON files: ```json { "filename": "customers.json", "total_rows": 5000, "returned_rows": 3, "data": [ { "customer_id": "C001", "name": "John Doe", "email": "john@example.com", "age": 34, "signup_date": "2023-01-15", "last_purchase": "2024-04-20", "purchase_count": 12, "lifetime_value": 1250.50, "churn": false, "country": "US", "plan_type": "premium", "referral_source": "search" }, // ... more records ] } ``` ### Get Dataset Versions ```http GET /uploads/datasets/{dataset_name}/versions ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | Retrieves all versions of a specific dataset. #### Path Parameters | Parameter | Type | Required | Description | | -------------- | ------ | -------- | ------------------- | | `dataset_name` | string | Yes | Name of the dataset | #### Response ```json { "dataset_name": "customer-data", "versions": [ { "version": "v2.0", "upload_id": "upload_def789ghi012", "created_at": "2024-05-15T10:00:00Z", "status": "complete", "file_count": 3, "total_size_bytes": 2048000 }, { "version": "v1.0", "upload_id": "upload_abc123def456", "created_at": "2024-05-01T12:00:00Z", "status": "complete", "file_count": 2, "total_size_bytes": 1536000 } ] } ``` ## Data Analysis ### Analyze Dataset Performs automated analysis on an uploaded dataset. ```http POST /data/analyze ``` #### Request Body ```json { "upload_id": "upload_abc123def456", "files": ["customers.csv"], "analysis_type": "comprehensive" } ``` | Parameter | Type | Required | Description | | --------------- | ------ | -------- | --------------------------------------------------------------- | | `upload_id` | string | Yes | ID of the upload to analyze | | `files` | array | No | Specific files to analyze (if omitted, analyzes all files) | | `analysis_type` | string | No | Type of analysis: `basic` or `comprehensive` (default: `basic`) | #### Response ```json { "job_id": "job_stu345vwx678", "status": "pending", "estimated_completion": "2024-05-01T12:10:00Z" } ``` This initiates an asynchronous job. You can check the job status using the Jobs API. ### Get Analysis Results Retrieves the results of a completed dataset analysis. ```http GET /data/analysis/{job_id} ``` #### Path Parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------- | | `job_id` | string | Yes | ID of the analysis job | #### Response ```json { "job_id": "job_stu345vwx678", "upload_id": "upload_abc123def456", "status": "completed", "created_at": "2024-05-01T12:00:00Z", "completed_at": "2024-05-01T12:08:30Z", "files": [ { "filename": "customers.csv", "stats": { "rows": 5000, "columns": 12, "missing_values": { "age": 120, "last_purchase": 450, "referral_source": 230 }, "column_types": { "customer_id": "string", "name": "string", "email": "string", "age": "integer", "signup_date": "date", "last_purchase": "date", "purchase_count": "integer", "lifetime_value": "float", "churn": "boolean", "country": "string", "plan_type": "string", "referral_source": "string" }, "summary": { "age": {"min": 18, "max": 85, "mean": 42.7, "median": 39}, "purchase_count": {"min": 0, "max": 50, "mean": 8.2, "median": 6}, "lifetime_value": {"min": 0, "max": 12500.75, "mean": 950.25, "median": 725.50} }, "categorical_counts": { "country": {"US": 2500, "CA": 1000, "UK": 800, "other": 700}, "plan_type": {"basic": 3000, "premium": 1800, "enterprise": 200}, "churn": {"true": 850, "false": 4150} } }, "correlations": [ {"feature1": "lifetime_value", "feature2": "purchase_count", "correlation": 0.75}, {"feature1": "age", "feature2": "lifetime_value", "correlation": 0.45}, {"feature1": "churn", "feature2": "last_purchase", "correlation": -0.60} ], "insights": [ { "type": "missing_data", "message": "The 'last_purchase' column has 9% missing values, primarily for customers with churn=true.", "severity": "medium" }, { "type": "outliers", "message": "The 'lifetime_value' column contains 12 potential outliers (>3 std. deviations).", "severity": "low" }, { "type": "imbalance", "message": "The target variable 'churn' is imbalanced (17% positive, 83% negative).", "severity": "high" } ], "visualizations": [ { "type": "histogram", "title": "Age Distribution", "data_url": "https://api.plexe.ai/data/visualizations/viz_yza123bcd456", "thumbnail_url": "https://api.plexe.ai/data/visualizations/viz_yza123bcd456/thumbnail" }, { "type": "bar_chart", "title": "Churn by Country", "data_url": "https://api.plexe.ai/data/visualizations/viz_efg789hij012", "thumbnail_url": "https://api.plexe.ai/data/visualizations/viz_efg789hij012/thumbnail" } ] } ], "recommendations": [ { "type": "preprocessing", "message": "Consider imputing missing 'age' values (currently 2.4% missing).", "importance": "medium" }, { "type": "feature_engineering", "message": "Create a 'days_since_last_purchase' feature from 'last_purchase' date.", "importance": "high" }, { "type": "modeling", "message": "Use SMOTE or class weighting to handle the imbalanced 'churn' target.", "importance": "high" } ] } ``` ## Data Querying ### Create Data Session Creates a session for querying a dataset. ```http POST /data/sessions ``` #### Headers | Header | Value | Description | | --------------- | ------------------ | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | | `Content-Type` | `application/json` | Required | #### Request Body ```json { "upload_id": "upload_abc123def456", "name": "Customer Analysis Session", "expiration_hours": 24 } ``` | Parameter | Type | Required | Description | | ------------------ | ------- | -------- | --------------------------------------------------- | | `upload_id` | string | Yes | ID of the upload to query | | `name` | string | No | Session name for reference | | `expiration_hours` | integer | No | Hours until session expires (default: 24, max: 168) | #### Response ```json { "session_id": "session_klm345nop678", "name": "Customer Analysis Session", "upload_id": "upload_abc123def456", "status": "ready", "created_at": "2024-05-01T14:00:00Z", "expires_at": "2024-05-02T14:00:00Z", "files": ["customers.csv", "transactions.csv"] } ``` ### Query Dataset Queries a dataset using natural language or SQL. ```http POST /data/query ``` #### Headers | Header | Value | Description | | --------------- | ------------------ | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | | `Content-Type` | `application/json` | Required | #### Request Body Natural language query: ```json { "query_type": "natural_language", "query": "Show me the average lifetime value by country for customers who haven't churned", "max_results": 100 } ``` SQL query: ```json { "query_type": "sql", "query": "SELECT country, AVG(lifetime_value) as avg_ltv FROM customers WHERE churn = false GROUP BY country ORDER BY avg_ltv DESC", "max_results": 100 } ``` | Parameter | Type | Required | Description | | ------------- | ------- | -------- | -------------------------------------------------------------- | | `query_type` | string | Yes | Type of query: `natural_language` or `sql` | | `query` | string | Yes | The query to execute | | `max_results` | integer | No | Maximum number of results to return (default: 100, max: 10000) | #### Response ```json { "query_id": "query_qrs901tuv234", "result_type": "table", "columns": ["country", "avg_ltv"], "rows": [ ["US", 1050.75], ["CA", 925.50], ["UK", 880.25], ["other", 750.80] ], "row_count": 4, "truncated": false, "execution_time_ms": 125, "generated_sql": "SELECT country, AVG(lifetime_value) as avg_ltv FROM customers WHERE churn = false GROUP BY country ORDER BY avg_ltv DESC" } ``` For visualization results: ```json { "query_id": "query_wxy567zab890", "result_type": "visualization", "visualization_type": "bar_chart", "title": "Average Lifetime Value by Country (Non-churned Customers)", "data": { "labels": ["US", "CA", "UK", "other"], "datasets": [ { "label": "Average Lifetime Value", "data": [1050.75, 925.50, 880.25, 750.80] } ] }, "execution_time_ms": 185, "generated_sql": "SELECT country, AVG(lifetime_value) as avg_ltv FROM customers WHERE churn = false GROUP BY country ORDER BY avg_ltv DESC" } ``` ### Get Query History Retrieves the history of queries for a data session. ```http GET /data/sessions/{session_id}/queries ``` #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | ---------------------- | | `session_id` | string | Yes | ID of the data session | #### Response ```json { "queries": [ { "query_id": "query_qrs901tuv234", "query_type": "natural_language", "query": "Show me the average lifetime value by country for customers who haven't churned", "executed_at": "2024-05-01T14:05:00Z", "execution_time_ms": 125 }, { "query_id": "query_wxy567zab890", "query_type": "natural_language", "query": "Visualize the distribution of purchase counts", "executed_at": "2024-05-01T14:10:00Z", "execution_time_ms": 185 } ] } ``` ### End Data Session Ends a data session, releasing resources. ```http DELETE /data/sessions/{session_id} ``` #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | ----------------------------- | | `session_id` | string | Yes | ID of the data session to end | #### Response ```json { "session_id": "session_klm345nop678", "status": "ended", "ended_at": "2024-05-01T15:00:00Z" } ``` ## Data Export ### Export Dataset Initiates an export job for a dataset. ```http POST /data/export ``` #### Request Body ```json { "upload_id": "upload_abc123def456", "files": ["customers.csv"], "format": "csv", "include_headers": true, "email_notification": true } ``` | Parameter | Type | Required | Description | | -------------------- | ------- | -------- | ------------------------------------------------------------------ | | `upload_id` | string | Yes | ID of the upload to export | | `files` | array | No | Specific files to export (if omitted, exports all) | | `format` | string | No | Export format: `csv`, `json`, `parquet` (default: original format) | | `include_headers` | boolean | No | Whether to include headers (CSV only, default: true) | | `email_notification` | boolean | No | Whether to send email when export is ready (default: false) | #### Response ```json { "export_id": "export_cde456fgh789", "status": "processing", "created_at": "2024-05-01T16:00:00Z", "estimated_completion": "2024-05-01T16:05:00Z" } ``` ### Get Export Status Checks the status of an export job. ```http GET /data/export/{export_id} ``` #### Path Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | -------------------- | | `export_id` | string | Yes | ID of the export job | #### Response ```json { "export_id": "export_cde456fgh789", "status": "completed", "created_at": "2024-05-01T16:00:00Z", "completed_at": "2024-05-01T16:04:30Z", "files": [ { "filename": "customers.csv", "size_bytes": 1048576, "download_url": "https://api.plexe.ai/data/export/export_cde456fgh789/customers.csv", "expires_at": "2024-05-08T16:04:30Z" } ] } ``` ### Download Exported File Downloads an exported file. ```http GET /data/export/{export_id}/{filename} ``` #### Path Parameters | Parameter | Type | Required | Description | | ----------- | ------ | -------- | ---------------------------- | | `export_id` | string | Yes | ID of the export job | | `filename` | string | Yes | Name of the file to download | #### Response The file contents as a binary stream with appropriate content type header. ## Error Codes | HTTP Status | Error Code | Description | | ----------- | -------------------------- | ------------------------------------------ | | 400 | `invalid_request` | The request was invalid | | 401 | `unauthorized` | Authentication failed | | 403 | `insufficient_permissions` | Insufficient permissions for the operation | | 404 | `not_found` | Resource not found | | 409 | `resource_conflict` | Resource conflict (e.g., duplicate name) | | 413 | `payload_too_large` | Upload size exceeds limits | | 422 | `validation_failed` | Validation failed | | 429 | `rate_limited` | Too many requests | | 500 | `server_error` | Internal server error | | 503 | `service_unavailable` | Service temporarily unavailable | ## Limits The Data Management API has the following limits: | Resource | Limit | | ------------------------- | ---------------- | | Maximum file size | 5 GB per file | | Maximum upload size | 20 GB per upload | | Maximum files per upload | 50 files | | Active data sessions | 5 per user | | Queries per minute | 30 per session | | Maximum query result size | 100 MB | | Export retention period | 7 days | These limits may vary based on your account tier. # Models API Source: https://docs.plexe.ai/pages/platform/reference/endpoints/models API reference for building, managing, and using machine learning models on the Plexe Platform. The Models API provides endpoints for creating, managing, and using machine learning models on the Plexe Platform. ## Models Endpoints ### List Models ```http GET /models ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | Retrieves a list of all models in your account. #### Query Parameters | Parameter | Type | Required | Description | | ---------- | ------- | -------- | -------------------------------------------------------------- | | `limit` | integer | No | Maximum number of models to return (default: 20, max: 100) | | `offset` | integer | No | Number of models to skip (default: 0) | | `status` | string | No | Filter by status: `DRAFT`, `BUILDING`, `READY`, `ERROR` | | `sort_by` | string | No | Field to sort by: `created_at`, `name` (default: `created_at`) | | `sort_dir` | string | No | Sort direction: `asc` or `desc` (default: `desc`) | #### Response ```json { "models": [ { "model_name": "customer-churn-predictor", "model_version": "v1.0", "name": "Customer Churn Predictor", "intent": "Predict customer churn based on usage patterns", "status": "READY", "deployment_status": "DEPLOYED", "created_at": "2023-06-15T08:15:45Z", "updated_at": "2023-06-15T10:30:12Z" }, { "model_name": "product-recommendation-engine", "model_version": "v2.1", "name": "Product Recommendation Engine", "intent": "Recommend products based on purchase history", "status": "BUILDING", "deployment_status": null, "created_at": "2023-06-16T14:22:33Z", "updated_at": "2023-06-16T14:22:33Z" } ], "pagination": { "total": 15, "limit": 20, "offset": 0, "has_more": false } } ``` ### Get Model ```http GET /models/{model_name} ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | Retrieves detailed information about a specific model. #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | ------------------------ | | `model_name` | string | Yes | Name of the model to get | #### Response ```json { "model_name": "customer-churn-predictor", "model_version": "v1.0", "name": "Customer Churn Predictor", "intent": "Predict customer churn based on usage patterns", "description": "Model predicts likelihood of customer churn in the next 30 days", "status": "READY", "deployment_status": "DEPLOYED", "endpoint": "https://api.plexe.ai/models/customer-churn-predictor/v1.0/infer", "metrics": { "accuracy": 0.92, "precision": 0.88, "recall": 0.85, "f1_score": 0.86 }, "dataset_id": "ds_stu901vwx234", "input_schema": { "usage_minutes": "float", "subscription_months": "integer", "support_tickets": "integer", "plan_type": "string" }, "output_schema": { "churn_probability": "float" }, "created_at": "2023-06-15T08:15:45Z", "updated_at": "2023-06-15T10:30:12Z", "created_by": "user_yza567bcd890", "tags": ["production", "customer-retention"] } ``` ### Create Model ```http POST /models/{model_name} ``` #### Headers | Header | Value | Description | | --------------- | ------------------ | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | | `Content-Type` | `application/json` | Required | Initiates the process of building a new model. This is an asynchronous operation that returns a job ID for tracking progress. #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | ---------------------- | | `model_name` | string | Yes | Name for the new model | #### Request Body ```json { "intent": "Predict customer churn based on usage patterns", "name": "Customer Churn Predictor", "description": "Model predicts likelihood of customer churn in the next 30 days", "dataset_id": "ds_stu901vwx234", "input_schema": { "usage_minutes": "float", "subscription_months": "integer", "support_tickets": "integer", "plan_type": "string" }, "output_schema": { "churn_probability": "float" }, "tags": ["production", "customer-retention"] } ``` | Field | Type | Required | Description | | --------------- | ------ | -------- | -------------------------------------------------- | | `intent` | string | Yes | Natural language description of the model purpose | | `name` | string | No | Display name for the model (default: generated) | | `description` | string | No | Detailed description of the model | | `dataset_id` | string | Yes | ID of the dataset to use for training | | `input_schema` | object | No | Schema of input fields (inferred if not provided) | | `output_schema` | object | No | Schema of output fields (inferred if not provided) | | `tags` | array | No | List of tags for organizing models | #### Response ```json { "job_id": "job_def456ghi789", "status": "PENDING", "model_name": "customer-churn-predictor", "model_version": "v1.0", "created_at": "2023-06-16T15:00:00Z" } ``` ### Deploy Model ```http POST /models/{model_name}/deploy ``` #### Headers | Header | Value | Description | | --------------- | ------------------ | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | | `Content-Type` | `application/json` | Required | Deploys a model, making it available for predictions. This is an asynchronous operation. #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | --------------------------- | | `model_name` | string | Yes | Name of the model to deploy | #### Request Body ```json { "environment": "production", "replicas": 2, "auto_scale": true } ``` | Field | Type | Required | Description | | ------------- | ------- | -------- | ------------------------------------------------ | | `environment` | string | No | Deployment environment (default: `production`) | | `replicas` | integer | No | Number of replicas to deploy (default: 1) | | `auto_scale` | boolean | No | Whether to enable auto-scaling (default: `true`) | #### Response ```json { "deployment_id": "dep_pqr678stu901", "model_name": "customer-churn-predictor", "model_version": "v1.0", "status": "DEPLOYING", "endpoint": "https://api.plexe.ai/predict/dep_pqr678stu901", "environment": "production", "replicas": 2, "auto_scale": true, "created_at": "2023-06-16T15:10:00Z" } ``` ### Make Prediction ```http POST /models/{model_name}/{model_version}/infer ``` #### Headers | Header | Value | Description | | -------------- | ------------------ | ----------------------------- | | `x-api-key` | `YOUR_API_KEY` | Required. Your API access key | | `Content-Type` | `application/json` | Required | Makes a prediction using a deployed model. #### Path Parameters | Parameter | Type | Required | Description | | --------------- | ------ | -------- | --------------------------- | | `model_name` | string | Yes | Name of the model to use | | `model_version` | string | Yes | Version of the model to use | #### Request Body Input data matching the model's input schema. Example: ```json { "usage_minutes": 120.5, "subscription_months": 8, "support_tickets": 2, "plan_type": "premium" } ``` #### Response Output data matching the model's output schema. Example: ```json { "request_id": "req_vwx234yza567", "result": { "churn_probability": 0.27 }, "model_name": "customer-churn-predictor", "model_version": "v1.0", "created_at": "2023-06-16T15:15:00Z" } ``` ### Get Model Status ```http GET /models/{model_name}/{model_version}/status ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | Gets the current status of a specific model version. #### Path Parameters | Parameter | Type | Required | Description | | --------------- | ------ | -------- | -------------------- | | `model_name` | string | Yes | Name of the model | | `model_version` | string | Yes | Version of the model | #### Response ```json { "model_name": "customer-churn-predictor", "model_version": "v1.0", "status": "READY", "deployment_status": "DEPLOYED", "last_updated": "2023-06-16T15:15:00Z", "build_progress": 100 } ``` ### Update Model ```http PATCH /models/{model_name} ``` #### Headers | Header | Value | Description | | --------------- | ------------------ | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | | `Content-Type` | `application/json` | Required | Updates metadata for an existing model. #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | --------------------------- | | `model_name` | string | Yes | Name of the model to update | #### Request Body ```json { "name": "Enhanced Customer Churn Predictor", "description": "Updated model with improved accuracy", "tags": ["production", "customer-retention", "v2"] } ``` | Field | Type | Required | Description | | ------------- | ------ | -------- | ------------------------------ | | `name` | string | No | New display name for the model | | `description` | string | No | New description of the model | | `tags` | array | No | Updated list of tags | #### Response ```json { "model_name": "customer-churn-predictor", "model_version": "v1.0", "name": "Enhanced Customer Churn Predictor", "description": "Updated model with improved accuracy", "tags": ["production", "customer-retention", "v2"], "updated_at": "2023-06-16T16:00:00Z" } ``` ### Delete Model ```http DELETE /models/{model_name} ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | Deletes a model and its deployments. #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | --------------------------- | | `model_name` | string | Yes | Name of the model to delete | #### Response ```json { "model_name": "customer-churn-predictor", "model_version": "v1.0", "status": "DELETED", "deleted_at": "2023-06-16T17:00:00Z" } ``` ### Retrain Model ```http POST /models/{model_name}/retrain ``` #### Headers | Header | Value | Description | | -------------- | ------------------ | ----------------------------- | | `x-api-key` | `YOUR_API_KEY` | Required. Your API access key | | `Content-Type` | `application/json` | Required | Initiates retraining of an existing model with new data or updated configuration. #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | ---------------------------- | | `model_name` | string | Yes | Name of the model to retrain | #### Request Body ```json { "upload_id": "upload_def789ghi012", "goal": "Updated goal with new requirements", "metric": "accuracy", "max_iterations": 3 } ``` | Field | Type | Required | Description | | ---------------- | ------- | -------- | ------------------------------------ | | `upload_id` | string | No | ID of new dataset for retraining | | `goal` | string | No | Updated natural language description | | `metric` | string | No | Primary metric to optimize | | `max_iterations` | integer | No | Maximum training iterations | #### Response ```json { "job_id": "job_rst456uvw789", "status": "PENDING", "model_name": "customer-churn-predictor", "new_version": "v2.0", "created_at": "2023-06-20T10:00:00Z" } ``` ### Get Build Logs ```http GET /models/build-logs ``` #### Headers | Header | Value | Description | | ----------- | -------------- | ----------------------------- | | `x-api-key` | `YOUR_API_KEY` | Required. Your API access key | Retrieves build logs for model training processes. #### Query Parameters | Parameter | Type | Required | Description | | --------- | ------- | -------- | ------------------------------------------------------ | | `limit` | integer | No | Maximum number of log entries to return (default: 100) | | `offset` | integer | No | Number of log entries to skip (default: 0) | | `job_id` | string | No | Filter logs by specific build job ID | #### Response ```json { "logs": [ { "job_id": "job_def456ghi789", "model_name": "customer-churn-predictor", "timestamp": "2023-06-16T15:05:00Z", "level": "INFO", "message": "Starting model training with dataset ds_stu901vwx234" }, { "job_id": "job_def456ghi789", "model_name": "customer-churn-predictor", "timestamp": "2023-06-16T15:08:30Z", "level": "INFO", "message": "Training completed. Model accuracy: 92.5%" } ], "pagination": { "total": 45, "limit": 100, "offset": 0, "has_more": false } } ``` ## Model Versions ### List Model Versions ```http GET /models/{model_name}/versions ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | Lists all versions of a specific model. #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | -------------------------------------- | | `model_name` | string | Yes | Name of the model to list versions for | #### Response ```json { "model_name": "customer-churn-predictor", "model_version": "v1.0", "versions": [ { "version_id": "ver_bcd890efg123", "version": 3, "status": "READY", "metrics": { "accuracy": 0.94, "precision": 0.92, "recall": 0.90, "f1_score": 0.91 }, "created_at": "2023-06-20T09:00:00Z" }, { "version_id": "ver_hij456klm789", "version": 2, "status": "READY", "metrics": { "accuracy": 0.92, "precision": 0.88, "recall": 0.85, "f1_score": 0.86 }, "created_at": "2023-06-17T14:00:00Z" }, { "version_id": "ver_nop012qrs345", "version": 1, "status": "READY", "metrics": { "accuracy": 0.89, "precision": 0.85, "recall": 0.82, "f1_score": 0.83 }, "created_at": "2023-06-16T15:00:00Z" } ] } ``` ### Create Model Version ```http POST /models/{model_name}/versions ``` #### Headers | Header | Value | Description | | --------------- | ------------------ | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | | `Content-Type` | `application/json` | Required | Creates a new version of an existing model. This is useful for iterative model improvement. #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | --------------------------------------- | | `model_name` | string | Yes | Name of the model to create version for | #### Request Body ```json { "dataset_id": "ds_tuv678wxy901", "intent": "Predict customer churn with added seasonality factor", "input_schema": { "usage_minutes": "float", "subscription_months": "integer", "support_tickets": "integer", "plan_type": "string", "season": "string" } } ``` | Field | Type | Required | Description | | --------------- | ------ | -------- | ------------------------------------------------ | | `dataset_id` | string | Yes | ID of the dataset to use for training | | `intent` | string | No | Updated intent (defaults to original if omitted) | | `input_schema` | object | No | Updated input schema (defaults to original) | | `output_schema` | object | No | Updated output schema (defaults to original) | #### Response ```json { "job_id": "job_zab234cde567", "status": "PENDING", "model_name": "customer-churn-predictor", "model_version": "v1.0", "version_id": "ver_fgh890ijk123", "version": 4, "created_at": "2023-06-21T10:00:00Z" } ``` ## Model Deployments ### List Deployments ```http GET /models/{model_name}/deployments ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | Lists all active deployments for a model. #### Path Parameters | Parameter | Type | Required | Description | | ------------ | ------ | -------- | ----------------------------------------- | | `model_name` | string | Yes | Name of the model to list deployments for | #### Response ```json { "model_name": "customer-churn-predictor", "model_version": "v1.0", "deployments": [ { "deployment_id": "dep_lmn456opq789", "environment": "production", "status": "ACTIVE", "version_id": "ver_bcd890efg123", "version": 3, "endpoint": "https://api.plexe.ai/predict/dep_lmn456opq789", "replicas": 2, "auto_scale": true, "created_at": "2023-06-20T10:00:00Z" }, { "deployment_id": "dep_rst012uvw345", "environment": "staging", "status": "ACTIVE", "version_id": "ver_hij456klm789", "version": 2, "endpoint": "https://api.plexe.ai/predict/dep_rst012uvw345", "replicas": 1, "auto_scale": false, "created_at": "2023-06-19T16:00:00Z" } ] } ``` ### Undeploy Model ```http DELETE /models/{model_name}/deployments/{deployment_id} ``` #### Headers | Header | Value | Description | | --------------- | -------------- | ------------------------------- | | `Authorization` | `Bearer TOKEN` | Required. Your API access token | Removes a specific deployment of a model. #### Path Parameters | Parameter | Type | Required | Description | | --------------- | ------ | -------- | ------------------------------ | | `model_id` | string | Yes | ID of the model | | `deployment_id` | string | Yes | ID of the deployment to remove | #### Response ```json { "model_name": "customer-churn-predictor", "model_version": "v1.0", "deployment_id": "dep_rst012uvw345", "status": "UNDEPLOYING", "undeployed_at": "2023-06-21T11:00:00Z" } ``` ### Describe Model ```http GET /models/{model_name}/{model_version}/describe ``` #### Headers | Header | Value | Description | | ----------- | -------------- | ----------------------------- | | `x-api-key` | `YOUR_API_KEY` | Required. Your API access key | Gets detailed information and metadata about a specific model version. #### Path Parameters | Parameter | Type | Required | Description | | --------------- | ------ | -------- | -------------------- | | `model_name` | string | Yes | Name of the model | | `model_version` | string | Yes | Version of the model | #### Response ```json { "model_name": "customer-churn-predictor", "model_version": "v1.0", "description": "Detailed model description and capabilities", "input_schema": { "usage_minutes": "float", "subscription_months": "integer", "support_tickets": "integer", "plan_type": "string" }, "output_schema": { "churn_probability": "float" }, "performance_metrics": { "accuracy": 0.92, "precision": 0.88, "recall": 0.85, "f1_score": 0.86 }, "training_info": { "dataset_size": 10000, "training_time_minutes": 15, "algorithm": "ensemble", "feature_importance": { "usage_minutes": 0.45, "support_tickets": 0.30, "subscription_months": 0.15, "plan_type": 0.10 } } } ``` ## Batch Predictions ### Batch Predictions ```http POST /models/{model_name}/{model_version}/predictions ``` #### Headers | Header | Value | Description | | -------------- | ------------------ | ----------------------------- | | `x-api-key` | `YOUR_API_KEY` | Required. Your API access key | | `Content-Type` | `application/json` | Required | Makes batch predictions using a deployed model by sending an array of input data. #### Path Parameters | Parameter | Type | Required | Description | | --------------- | ------ | -------- | --------------------------- | | `model_name` | string | Yes | Name of the model to use | | `model_version` | string | Yes | Version of the model to use | #### Request Body Array of input objects matching the model's input schema. Example: ```json [ { "credit_score": 42, "employment_type": "sample string", "infrastructure_score": 42, "years_employed": 3.14, "payment_to_income_ratio": 3.14, "population_growth_trend": "sample string", "loan_year": 42, "permit_fees_aed": 42, "market_conditions": "sample string", "land_area_sqm": 42, "interest_rate_percent": 3.14, "land_value_aed": 42, "debt_to_income_ratio": 3.14, "monthly_income_aed": 42, "construction_delay_months": 3.14, "loan_to_value_ratio": 3.14, "market_activity_level": "sample string", "borrower_age": 42, "loan_term_years": 42, "building_area_sqm": 42, "monthly_payment_aed": 42, "cost_overrun_percentage": 3.14, "distance_to_center_km": 3.14, "district": "sample string", "building_type": "sample string", "estimated_monthly_rental_aed": 42 }, { "credit_score": 45, "employment_type": "full-time", "infrastructure_score": 38, "years_employed": 2.5, "payment_to_income_ratio": 2.8 // ... additional fields for second prediction } ] ``` #### Response Array of prediction results corresponding to each input: ```json [ { "prediction": { "loan_approval_probability": 0.85, "risk_score": 0.15 } }, { "prediction": { "loan_approval_probability": 0.72, "risk_score": 0.28 } } ] ``` ## Error Codes | HTTP Status | Error Code | Description | | ----------- | --------------------- | ---------------------------------------- | | 400 | `invalid_request` | Malformed request or missing parameters | | 401 | `unauthorized` | Missing or invalid API key | | 403 | `forbidden` | Insufficient permissions for operation | | 404 | `not_found` | Model, deployment, or resource not found | | 409 | `conflict` | Resource conflict (e.g., duplicate name) | | 422 | `validation_error` | Invalid input data or schema | | 429 | `rate_limit_exceeded` | API rate limit exceeded | | 500 | `internal_error` | Server-side error | | 503 | `service_unavailable` | Service temporarily unavailable | For all API errors, the response will include details about the error and, where appropriate, suggestions for resolution. # Introduction Source: https://docs.plexe.ai/pages/platform/reference/introduction Overview of the Plexe Platform API endpoints and authentication. The Plexe Platform API provides programmatic access to the Plexe machine learning platform, allowing you to build, deploy, and use ML models without managing infrastructure. ## Base URL All API endpoints are accessible via this base URL: ``` https://api.plexe.ai ``` ## Authentication All API requests require authentication using an API key. You have two options for authentication: Option 1: Include your key in the `Authorization` header as a Bearer token: ```bash curl -X GET https://api.plexe.ai/models/list \ -H "Authorization: Bearer YOUR_API_KEY_HERE" ``` Option 2: Include your key in the `x-api-key` header: ```bash curl -X GET https://api.plexe.ai/models/list \ -H "x-api-key: YOUR_API_KEY_HERE" ``` You can generate API keys in the [Plexe Console](https://console.plexe.ai) under Settings > API Keys. See the [Manage API Keys](/platform/how-to/manage_api_keys) guide for details. ## Request Format For endpoints that accept data (POST, PUT, PATCH), provide a JSON-formatted request body with the appropriate Content-Type header: ```bash curl -X POST https://api.plexe.ai/models/build \ -H "Authorization: Bearer YOUR_API_KEY_HERE" \ -H "Content-Type: application/json" \ -d '{ "name": "My Model", "intent": "Predict customer churn" }' ``` ## Response Format All responses are returned in JSON format. Successful responses include the requested data, while error responses include an error message and relevant details. The HTTP status code indicates the result of the operation. Example success response: ```json { "model_id": "mdl_abc123def456", "name": "Customer Churn Predictor", "status": "READY", "created_at": "2023-06-15T08:15:45Z" } ``` Example error response: ```json { "error": { "code": "invalid_request", "message": "Missing required field: intent", "status": 400 } } ``` ## Rate Limits The API enforces rate limits to ensure fair usage. Current limits are: * **Basic tier**: 100 requests per minute * **Pro tier**: 500 requests per minute * **Enterprise tier**: Custom limits available When you exceed the rate limit, you'll receive a `429 Too Many Requests` response with a `Retry-After` header indicating how many seconds to wait before retrying. ## Pagination List endpoints (those returning multiple items) support pagination using the `limit` and `offset` query parameters: ```bash curl -X GET https://api.plexe.ai/models?limit=10&offset=20 \ -H "x-api-key: YOUR_API_KEY_HERE" ``` Paginated responses include metadata about the total count and pagination: ```json { "models": [ ... ], "pagination": { "total": 45, "limit": 10, "offset": 20, "has_more": true } } ``` ## API Categories The Plexe Platform API is organized into these main categories: 1. **[Authentication](/platform/reference/endpoints/auth)**: Managing API keys and user access 2. **[Data Management](/platform/reference/endpoints/data)**: Uploading, retrieving, and managing datasets 3. **[Model Management](/platform/reference/endpoints/models)**: Building, deploying, and managing ML models ## Using the API For a step-by-step guide on using the API, see the [Platform API Quickstart](/platform/tutorials/quickstart_api) tutorial. ## API Versioning The current API version is `v1`. We maintain backward compatibility within a major version. When breaking changes are necessary, we'll introduce a new major version (e.g., `v2`) while continuing to support the previous version for a reasonable transition period. ## Client Libraries We provide official client libraries for several programming languages: * **Python**: `pip install plexe-client` * **JavaScript/TypeScript**: `npm install @plexe/client` * **Java**: Available via Maven Central * **Go**: `go get github.com/plexe-ai/plexe-go-client` Example using the Python client: ```python from plexe_client import PlexeClient client = PlexeClient(api_key="YOUR_API_KEY_HERE") # List models models = client.models.list() print(models) # Get a specific model model = client.models.get("mdl_abc123def456") print(model) ``` ## Need Help? If you need assistance with the API: * Check our [FAQ](/platform/reference/faq) * Join our [Discord community](https://discord.gg/SefZDepGMv) * Contact our support team at [support@plexe.ai](mailto:support@plexe.ai) # Quickstart Source: https://docs.plexe.ai/pages/platform/tutorials/quickstart_api Build, deploy, and use your first model using the Plexe Platform REST API. This tutorial walks you through the essential steps to create and use a machine learning model with the Plexe Platform API. **Base URL:** `https://api.plexe.ai` ## Prerequisites 1. **Account:** Sign up at [console.plexe.ai](https://console.plexe.ai) 2. **API Key:** Generate one from your account settings 3. **HTTP Client:** Such as `curl`, Postman, or Python with `requests` ## 1. Authentication All API requests require your API key in the `x-api-key` header: ```python import requests, os, time, json # Load API key from environment api_key = os.getenv("PLEXE_API_KEY") if not api_key: raise ValueError("Please set the PLEXE_API_KEY environment variable.") headers = { "x-api-key": api_key, "Content-Type": "application/json" } base_url = "https://api.plexe.ai" ``` ## 2. Upload Data While optional, providing data yields better results. Use a pre-signed URL approach: ```python # Request pre-signed URL file_path = "housing_data.csv" file_name = os.path.basename(file_path) try: # Get upload URL response = requests.post( f"{base_url}/uploads", headers=headers, json={"filename": file_name, "content_type": "text/csv"} ) response.raise_for_status() upload_info = response.json() presigned_url = upload_info.get("presigned_url") temp_upload_id = upload_info.get("upload_id") s3_key = upload_info.get("key") # Upload file to S3 with open(file_path, 'rb') as f: requests.put(presigned_url, data=f, headers={'Content-Type': 'text/csv'}).raise_for_status() # Confirm upload completion confirm_response = requests.post( f"{base_url}/uploads/status", headers=headers, json={"upload_id": temp_upload_id, "filename": file_name, "s3_key": s3_key} ) confirm_response.raise_for_status() upload_id = confirm_response.json().get("upload_id") print(f"Upload confirmed. ID: {upload_id}") except Exception as e: print(f"Upload error: {e}") # Fallback to public dataset upload_id = "https://raw.githubusercontent.com/plotly/datasets/master/housing_new-york.csv" ``` The two-step upload process (pre-signed URL → direct upload) enables secure and efficient handling of large files. ## 3. Build the Model Submit a build request with your model name, goal, and data reference: ```python model_name = "api-quickstart-housing" response = requests.post( f"{base_url}/models/{model_name}", headers=headers, json={ "goal": "Predict house prices in USD based on sqft, beds, baths.", "upload_id": upload_id, "metric": "rmse" # Optional: suggest optimization metric } ) response.raise_for_status() model_id = response.json().get("model_id") print(f"Build requested. Model ID: {model_id}") ``` ## 4. Monitor Build Status Model building happens asynchronously. Poll until complete: ```python if model_id: # Extract name and version from model_id (format: name:version) m_name, m_version = model_id.split(':') status = "pending" # Poll until completed or failed while status in ["pending", "processing", "building"]: time.sleep(15) # Wait between checks try: response = requests.get( f"{base_url}/models/{m_name}/{m_version}/status", headers=headers ) response.raise_for_status() status_result = response.json() status = status_result.get("status") print(f"Status: {status}") if status == "completed": print("Build successful!") break elif status == "failed": print(f"Build failed: {status_result.get('error', 'Unknown error')}") model_id = None break except Exception as e: print(f"Status check error: {e}") time.sleep(30) # Longer wait on error ``` ## 5. Make Predictions Once the model is ready, use the inference endpoint: ```python if model_id and status == "completed": try: # Prepare sample input matching your data schema prediction = requests.post( f"{base_url}/models/{m_name}/{m_version}/infer", headers=headers, json={ "sqft": 1950.0, "beds": 3, "baths": 2.5 } ).json() print(f"Prediction result: {prediction}") except Exception as e: print(f"Inference error: {e}") ``` This completes the basic API workflow. Explore the [Platform API Reference](/platform/reference/introduction) for details on all available endpoints and parameters.