# 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.