Result models
Every object the Pictograph Python SDK returns, with its fields and types, generated from the released package and linked to its source.
On this page
- What each call returns
- Models
- AnnotateReport
- Annotation
- AnnotationComment
- AnnotationCommentReaction
- AnnotationFailure
- AnnotationImportFailure
- AnnotationImportReport
- AnyModel
- ApiKey
- AugmentFailure
- AugmentReport
- AugmentationFrameworkSetting
- AugmentationProfile
- AugmentationProfiles
- BBoxAnnotation
- BatchFailure
- BatchJob
- BatchQuote
- BatchResult
- BoundingBox
- BulkActionResult
- BulkDeleteResult
- BulkSaveFailure
- BulkSaveResult
- BulkUploadFailure
- BulkUploadResult
- ClassAttribute
- CopyToDatasetResult
- CreatedApiKey
- CreatedDeployment
- CreatedWebhookEndpoint
- CreditBalance
- CreditEstimate
- CreditLedgerEntry
- Dataset
- DatasetClass
- DatasetDeleteResult
- DatasetImportProgress
- DatasetInsights
- DatasetRestoreEstimate
- DatasetSource
- DatasetStorageStatus
- DatasetStorageTransition
- DeleteClassResult
- DeleteResult
- Deployment
- DeploymentComputeOption
- DeploymentComputeOptions
- DeploymentComputePrecision
- DeploymentMetrics
- DeploymentQuote
- DeploymentRegion
- DeploymentRuntime
- Directory
- DirectoryStats
- DirectoryTreeNode
- DownloadFailure
- DownloadReport
- DuplicateGroup
- DuplicateMember
- EmbeddingBackfill
- EngineBuild
- EngineBuildModel
- EvalClassMetrics
- EvalConfusionMatrix
- EvalImagePerformance
- EvalOverallMetrics
- EvaluationCompute
- EvaluationComputeGpu
- EvaluationComputeOptions
- EvaluationComputePrecision
- Export
- Image
- ImageSplit
- ImageStatus
- ImportJob
- InsightsDimensions
- InsightsOrientation
- InsightsSize
- InsightsStatusCounts
- Job
- KeypointAnnotation
- LimitCheckResult
- MergeClassResult
- Model
- ModelConfidence
- ModelConfidenceBuckets
- ModelEvaluation
- ModelFileEntry
- ModelFileManifest
- ModelPredictResult
- ModelVersionEntry
- ModelVersionsPayload
- NearDuplicatesResult
- Notification
- OperationUsage
- Organization
- OrganizationInvite
- OrganizationMember
- OrientedBoxGeometry
- Point
- PolygonAnnotation
- PolygonGeometry
- PolylineAnnotation
- PolylineGeometry
- PromptResult
- PublicDataset
- PublicDatasetImport
- PublicImportSource
- PublicModel
- PublicModelDetail
- PublicOrganization
- RemoteDataset
- RenameClassResult
- RunLogBranchCounts
- RunLogEventName
- RunLogPage
- RunLogRecord
- RunLogStreamSummary
- RunLogSummary
- Sam3Prediction
- SaveResult
- SimilarImage
- SimilarQuote
- SkeletonJoint
- SkeletonTemplate
- TaggedImage
- Task
- TaskContribution
- TaskContributions
- TileFailure
- TileReport
- ToolCard
- ToolClass
- ToolCost
- ToolInput
- ToolMode
- ToolOutput
- ToolParameter
- ToolRelated
- ToolRun
- ToolSummary
- TrainingClassSupport
- TrainingClassSupportEntry
- TrainingQuote
- TrainingQuoteBalance
- TrainingQuoteBlock
- TrainingQuoteEstimate
- TrainingQuoteTier
- TrainingRun
- TrainingRunWarning
- UploadFailure
- UploadReport
- UsageByOperation
- ValidationResult
- VideoExtractionJob
- VideoMetadata
- VideoUploadInfo
- WebhookDelivery
- WebhookEndpoint
- Workflow
- WorkflowCompute
- WorkflowComputeGpu
- WorkflowComputeOptions
- WorkflowComputePrecision
- WorkflowEndpoint
- WorkflowIssue
- WorkflowLive
- WorkflowLiveEvent
- WorkflowLiveMeasure
- WorkflowLiveModel
- WorkflowLiveOutputs
- WorkflowNodeCard
- WorkflowNodeCatalog
- WorkflowNodeField
- WorkflowRun
- WorkflowRunCompute
- WorkflowRunCreated
- WorkflowRunLiveView
- WorkflowRunRecording
- WorkflowRunSource
- WorkflowRunSummary
- WorkflowRunWrites
- WorkflowTemplate
- WorkflowValidation
- WorkflowWrittenAnnotations
- WorkflowWrittenEventCapture
- WorkflowWrittenPassiveCapture
- WorkflowWrittenWebhook
Generated from pictograph 1.69.199, released November 9, 2026. Each definition links to its source at v1.69.199.
What each call returns
| Call | Returns |
|---|---|
client.annotation_comments.create() |
AnnotationComment |
client.annotation_comments.delete() |
None |
client.annotation_comments.list() |
Sequence[AnnotationComment] |
client.annotation_comments.react() |
AnnotationComment |
client.annotation_comments.reply() |
AnnotationComment |
client.annotation_comments.resolve() |
AnnotationComment |
client.annotation_comments.unreact() |
AnnotationComment |
client.annotation_comments.update() |
AnnotationComment |
client.annotations.bulk_save() |
BulkSaveResult |
client.annotations.delete() |
DeleteResult |
client.annotations.delete_class() |
DeleteClassResult |
client.annotations.get() |
list[Annotation] |
client.annotations.import_coco() |
AnnotationImportReport |
client.annotations.import_pascal_voc() |
AnnotationImportReport |
client.annotations.import_yolo() |
AnnotationImportReport |
client.annotations.merge_class() |
MergeClassResult |
client.annotations.rename_class() |
RenameClassResult |
client.annotations.save() |
SaveResult |
client.api_keys.create() |
CreatedApiKey |
client.api_keys.get() |
ApiKey |
client.api_keys.list() |
list[ApiKey] |
client.api_keys.revoke() |
None |
client.api_keys.update() |
ApiKey |
client.auto_annotate.batch() |
BatchJob |
client.auto_annotate.box() |
PromptResult |
client.auto_annotate.cancel_batch() |
BatchJob |
client.auto_annotate.dataset() |
AnnotateReport |
client.auto_annotate.get_batch() |
BatchJob |
client.auto_annotate.point() |
PromptResult |
client.auto_annotate.quote() |
BatchQuote |
client.auto_annotate.quote_similar() |
SimilarQuote |
client.auto_annotate.similar() |
BatchJob |
client.auto_annotate.text() |
PromptResult |
client.auto_annotate.wait_for_batch() |
BatchJob |
client.batch.copy() |
BatchResult |
client.batch.copy_to_dataset() |
CopyToDatasetResult |
client.batch.delete() |
BatchResult |
client.batch.move() |
BatchResult |
client.batch.update() |
BatchResult |
client.connectors.cancel_import() |
ImportJob |
client.connectors.check_limits() |
LimitCheckResult |
client.connectors.get_import() |
ImportJob |
client.connectors.import_() |
ImportJob |
client.connectors.validate() |
ValidationResult |
client.connectors.wait_for_import() |
ImportJob |
client.credits.balance() |
CreditBalance |
client.credits.estimate() |
CreditEstimate |
client.credits.history() |
list[CreditLedgerEntry] |
client.credits.iter() |
OffsetPager[CreditLedgerEntry] |
client.credits.usage_by_operation() |
UsageByOperation |
client.datasets.archive() |
Dataset |
client.datasets.as_pytorch() |
PictographTorchDataset |
client.datasets.backfill_embeddings() |
EmbeddingBackfill |
client.datasets.create() |
Dataset |
client.datasets.delete() |
DatasetDeleteResult |
client.datasets.download() |
DownloadReport |
client.datasets.freeze() |
DatasetStorageTransition |
client.datasets.get() |
Dataset |
client.datasets.get_public_import() |
PublicDatasetImport |
client.datasets.import_public() |
PublicDatasetImport |
client.datasets.insights() |
DatasetInsights |
client.datasets.iter() |
OffsetPager[Dataset] |
client.datasets.list() |
list[Dataset] |
client.datasets.near_duplicates() |
NearDuplicatesResult |
client.datasets.restore() |
DatasetStorageTransition |
client.datasets.storage_status() |
DatasetStorageStatus |
client.datasets.unarchive() |
Dataset |
client.datasets.update() |
Dataset |
client.datasets.wait_for_public_import() |
PublicDatasetImport |
client.datasets.wait_for_storage() |
DatasetStorageStatus |
client.deployments.bulk_delete() |
BulkDeleteResult |
client.deployments.bulk_pause() |
BulkActionResult |
client.deployments.bulk_resume() |
BulkActionResult |
client.deployments.compute_options() |
DeploymentComputeOptions |
client.deployments.connect() |
DeploymentClient[Any] |
client.deployments.create() |
CreatedDeployment |
client.deployments.delete() |
None |
client.deployments.get() |
Deployment |
client.deployments.iter() |
OffsetPager[Deployment] |
client.deployments.list() |
list[Deployment] |
client.deployments.pause() |
Deployment |
client.deployments.quote() |
DeploymentQuote |
client.deployments.resume() |
Deployment |
client.deployments.update() |
Deployment |
client.deployments.wait_until_active() |
Deployment |
client.directories.create() |
Directory |
client.directories.delete() |
None |
client.directories.list() |
Sequence[Directory] |
client.directories.rename() |
Directory |
client.directories.stats() |
DirectoryStats |
client.directories.tree() |
Sequence[DirectoryTreeNode] |
client.explore.dataset() |
PublicDataset |
client.explore.datasets() |
list[PublicDataset] |
client.explore.iter_datasets() |
OffsetPager[PublicDataset] |
client.explore.iter_models() |
OffsetPager[PublicModel] |
client.explore.model() |
PublicModelDetail |
client.explore.models() |
list[PublicModel] |
client.exports.bulk_delete() |
BulkDeleteResult |
client.exports.create() |
Export |
client.exports.delete() |
None |
client.exports.download() |
Path |
client.exports.get() |
Export |
client.exports.iter() |
OffsetPager[Export] |
client.exports.list() |
list[Export] |
client.exports.wait_for_completion() |
Export |
client.images.assign_splits() |
dict[str, int] |
client.images.augment() |
AugmentReport |
client.images.bulk_tag() |
int |
client.images.bulk_upload() |
BulkUploadResult |
client.images.delete() |
None |
client.images.download() |
Path |
client.images.download_bundle() |
Path |
client.images.get() |
Image |
client.images.iter() |
CursorPager[Image] |
client.images.list() |
list[Image] |
client.images.review() |
ImageStatus |
client.images.set_split() |
ImageSplit | None |
client.images.tile() |
TileReport |
client.images.upload() |
Image |
client.images.upload_from_directory() |
UploadReport |
client.jobs.cancel() |
Job |
client.jobs.get() |
Job |
client.jobs.list() |
OffsetPager[Job] |
client.jobs.wait() |
Job |
client.model_evaluations.cancel() |
ModelEvaluation |
client.model_evaluations.compute_options() |
EvaluationComputeOptions |
client.model_evaluations.create() |
ModelEvaluation |
client.model_evaluations.evaluate() |
ModelEvaluation |
client.model_evaluations.get() |
ModelEvaluation |
client.model_evaluations.iter() |
OffsetPager[ModelEvaluation] |
client.model_evaluations.list() |
list[ModelEvaluation] |
client.model_evaluations.report() |
dict[str, Any] |
client.model_evaluations.wait_for_completion() |
ModelEvaluation |
client.models.bulk_delete() |
BulkDeleteResult |
client.models.delete() |
None |
client.models.download() |
Path |
client.models.download_file() |
Path |
client.models.files() |
ModelFileManifest |
client.models.fork() |
Model |
client.models.get() |
Model |
client.models.iter() |
OffsetPager[Model] |
client.models.list() |
list[Model] |
client.models.load() |
AnyModel |
client.models.predict() |
ModelPredictResult |
client.models.set_current_version() |
ModelVersionsPayload |
client.models.update() |
Model |
client.models.versions() |
ModelVersionsPayload |
client.notifications.delete() |
None |
client.notifications.list() |
list[Notification] |
client.notifications.mark_all_read() |
int |
client.notifications.mark_read() |
None |
client.notifications.unread_count() |
int |
client.organizations.invite() |
OrganizationInvite |
client.organizations.list_invites() |
list[OrganizationInvite] |
client.organizations.list_members() |
list[OrganizationMember] |
client.organizations.me() |
Organization |
client.organizations.remove_member() |
None |
client.organizations.revoke_invite() |
None |
client.organizations.update() |
Organization |
client.organizations.update_member_role() |
dict[str, Any] |
client.sam3.predict() |
Sam3Prediction |
client.search.by_similarity() |
list[SimilarImage] |
client.search.by_tag() |
list[TaggedImage] |
client.tasks.contributions() |
TaskContributions |
client.tasks.iter() |
OffsetPager[Task] |
client.tasks.list() |
list[Task] |
client.tools.describe() |
ToolCard |
client.tools.list() |
list[ToolSummary] |
client.training.augmentation_profiles() |
AugmentationProfiles |
client.training.bulk_cancel() |
BulkActionResult |
client.training.cancel() |
TrainingRun |
client.training.create() |
TrainingRun |
client.training.get() |
TrainingRun |
client.training.iter() |
OffsetPager[TrainingRun] |
client.training.list() |
list[TrainingRun] |
client.training.quote() |
TrainingQuote |
client.training.wait_for_completion() |
TrainingRun |
client.video.extract_frames() |
VideoExtractionJob |
client.video.get_extraction() |
VideoExtractionJob |
client.video.probe() |
VideoMetadata |
client.video.upload() |
VideoUploadInfo |
client.video.wait_for_extraction() |
VideoExtractionJob |
client.webhooks.create() |
CreatedWebhookEndpoint |
client.webhooks.delete() |
None |
client.webhooks.deliveries() |
Sequence[WebhookDelivery] |
client.webhooks.event_types() |
list[str] |
client.webhooks.get() |
WebhookEndpoint |
client.webhooks.list() |
Sequence[WebhookEndpoint] |
client.webhooks.replay() |
None |
client.webhooks.rotate_secret() |
CreatedWebhookEndpoint |
client.webhooks.test() |
dict[str, Any] |
client.webhooks.update() |
WebhookEndpoint |
client.workflows.bulk_cancel_runs() |
BulkActionResult |
client.workflows.bulk_delete() |
BulkDeleteResult |
client.workflows.cancel_run() |
None |
client.workflows.compute_options() |
WorkflowComputeOptions |
client.workflows.connect() |
DeploymentClient[Any] |
client.workflows.create() |
Workflow |
client.workflows.delete() |
None |
client.workflows.deploy() |
Workflow |
client.workflows.get() |
Workflow |
client.workflows.get_run() |
WorkflowRun |
client.workflows.iter_live_log() |
Iterator[RunLogRecord] |
client.workflows.iter_run_log() |
Iterator[RunLogRecord] |
client.workflows.iter_runs() |
OffsetPager[WorkflowRunSummary] |
client.workflows.list() |
Sequence[Workflow] |
client.workflows.list_runs() |
Sequence[WorkflowRunSummary] |
client.workflows.live_log() |
RunLogPage |
client.workflows.live_log_summary() |
RunLogSummary |
client.workflows.nodes() |
WorkflowNodeCatalog |
client.workflows.pause() |
Workflow |
client.workflows.resume() |
Workflow |
client.workflows.run() |
WorkflowRunCreated | WorkflowRun WorkflowRunCreated, WorkflowRun |
client.workflows.run_log() |
RunLogPage |
client.workflows.run_log_summary() |
RunLogSummary |
client.workflows.templates() |
Sequence[WorkflowTemplate] |
client.workflows.update() |
Workflow |
client.workflows.update_endpoint() |
Workflow |
client.workflows.upload_source() |
str |
client.workflows.validate() |
WorkflowValidation |
client.workflows.wait_for_run() |
WorkflowRun |
client.workflows.wait_until_live() |
Workflow |
client.workflows.watch_run() |
DeploymentStream[Any] |
Models
AnnotateReport
class AnnotateReport(BaseModel):
"""Outcome of an AutoAnnotate.dataset call."""
dataset_name: str
images_attempted: int = 0
images_processed: int = 0
images_skipped: int = 0
images_capped: int = 0
annotations_added: int = 0
failures: list[AnnotationFailure] = []
job_id: str | None = None
job_status: str | None = None
@property
def success(self) -> bool: ...
Annotation
Annotation = (
BBoxAnnotation
| PolygonAnnotation
| PolylineAnnotation
| KeypointAnnotation
)
AnnotationComment
class AnnotationComment(BaseModel):
"""One comment on an annotation."""
id: str
annotation_id: str
body: str
resolved: bool = False
parent_comment_id: str | None = None
is_edited: bool = False
is_deleted: bool = False
resolved_by: str | None = None
resolved_by_name: str | None = None
resolved_at: datetime | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
user_id: str | None = None
author_name: str | None = None
author_username: str | None = None
author_avatar_url: str | None = None
is_mine: bool = False
reactions: list[AnnotationCommentReaction] = []
AnnotationCommentReaction
class AnnotationCommentReaction(BaseModel):
"""A grouped reaction tally on a comment (one entry per reaction key)."""
reaction: str
count: int = 0
reacted: bool = False
AnnotationFailure
class AnnotationFailure(BaseModel):
"""One image that failed to auto-annotate in AutoAnnotate.dataset."""
image_filename: str
reason: str
error_type: str | None = None
code: str | None = None
AnnotationImportFailure
class AnnotationImportFailure(BaseModel):
"""One image whose imported annotations could not be saved."""
image_filename: str
reason: str
AnnotationImportReport
class AnnotationImportReport(BaseModel):
"""Outcome of an Annotations.import_coco / `import_pascal_voc` / `import_yolo` call."""
dataset_name: str
images_matched: int = 0
images_saved: int = 0
annotations_saved: int = 0
unmatched_files: list[str] = []
failures: list[AnnotationImportFailure] = []
unconverted: list[str] = []
@property
def success(self) -> bool: ...
AnyModel
AnyModel = (
DetectionModel
| InstanceSegmentationModel
| SemanticSegmentationModel
| KeypointModel
| ClassificationModel
)
ApiKey
class ApiKey(BaseModel):
"""API key metadata returned by list/get/update endpoints."""
id: str
organization_id: str
name: str
# First 12 characters (e.g., 'pk_live_abc1') - safe to log.
key_prefix: str
role: Literal['viewer', 'member', 'admin', 'owner']
rate_limit: int
is_active: bool
last_used_at: datetime | None = None
expires_at: datetime | None = None
created_at: datetime
AugmentFailure
class AugmentFailure(BaseModel):
"""One source image that failed to augment (kind in `reason`)."""
image_id: str
filename: str
reason: str
AugmentReport
class AugmentReport(BaseModel):
"""Outcome of an Images.augment run."""
source: str
target: str
source_images: int = 0
originals_copied: int = 0
variants_created: int = 0
annotations_written: int = 0
skipped_empty: int = 0
failures: list[AugmentFailure] = []
@property
def success(self) -> bool: ...
AugmentationFrameworkSetting
class AugmentationFrameworkSetting(BaseModel):
"""One of a pipeline's own augmentation settings (`config["augmentation"]["framework"]`)."""
key: str
default: float
min: float
max: float
label: str = ''
step: float | None = None
AugmentationProfile
class AugmentationProfile(BaseModel):
"""What one pipeline's `config["augmentation"]` takes, and what it applies by default."""
# The ops it takes.
available_ops: list[str] = []
# The ops it applies when a run sends none.
default_ops: list[dict[str, Any]] = []
# Its own settings, with their ranges.
framework: list[AugmentationFrameworkSetting] = []
note: str = ''
AugmentationProfiles
class AugmentationProfiles(BaseModel):
"""Every pipeline's training-time augmentation (`training.augmentation_profiles`)."""
# By `pipeline_type`.
profiles: dict[str, AugmentationProfile] = {}
BBoxAnnotation
class BBoxAnnotation(BaseModel):
"""Bounding-box annotation - axis-aligned by default, optionally ROTATED."""
# Unique within the image; a UUID is generated when omitted.
id: str = ...
# Class name, case-sensitive; use one of the dataset's classes.
name: str
type: Literal['bbox'] = 'bbox'
bounding_box: BoundingBox
# Present only on a rotated box; bounding_box is then its axis-aligned enclosure.
# Training uses bounding_box either way.
oriented_box: OrientedBoxGeometry | None = None
confidence: float = 1.0
created_by: str | None = None
attributes: dict[str, object] | list[object] = []
BatchFailure
class BatchFailure(BaseModel):
"""One image that failed within a batch operation."""
id: str
reason: str
BatchJob
class BatchJob(BaseModel):
"""Snapshot of an auto-annotate batch job's progress."""
job_id: str
status: Literal['pending', 'running', 'completed', 'failed', 'cancelled']
# 0-100. 100 only at terminal state.
progress: int = 0
total_images: int = 0
processed_images: int = 0
total_annotations_added: int = 0
failed_images: int = 0
error_message: str | None = None
# Only on the response that started the job: the deposit taken, in micro-USD.
estimated_credits: int | None = None
completed_at: datetime | None = None
BatchQuote
class BatchQuote(BaseModel):
"""What a batch job would cost: the deposit `batch()` would take."""
total_images: int
# The cost, in micro-USD.
estimated_credits: int
# Total SAHI tile passes priced.
sahi_tiles: int = 0
# T4 containers the job runs on.
containers: int = 0
# Your remaining balance (µUSD).
remaining_credits: int = 0
# Whether the balance covers the estimate.
sufficient: bool = True
# Image ceiling for a single job.
max_images: int = 5000
# True when this configuration is past the ceiling and must be split.
exceeds_max_images: bool = False
BatchResult
class BatchResult(BaseModel):
"""Outcome of a batch operation."""
success: bool
processed: int
failed: list[BatchFailure] = []
affected_directories: list[str] = []
renamed: int = 0
operation: str | None = None
BoundingBox
class BoundingBox(BaseModel):
"""A bounding box: top-left corner + size, absolute pixels."""
x: float
y: float
# Width in pixels (strictly positive).
w: float
# Height in pixels (strictly positive).
h: float
BulkActionResult
class BulkActionResult(BaseModel):
"""What a bulk change (pause, resume, cancel) did."""
# Ids this call changed.
succeeded: list[str] = []
# Ids not found, or not in a state it could change.
not_found: list[str] = []
# How many were changed.
count: int = 0
BulkDeleteResult
class BulkDeleteResult(BaseModel):
"""What a bulk delete removed."""
# Ids that existed and were deleted.
succeeded: list[str] = []
# Ids that were not found.
not_found: list[str] = []
# How many were deleted.
count: int = 0
# The same as succeeded.
@property
def deleted(self) -> list[str]: ...
BulkSaveFailure
class BulkSaveFailure(BaseModel):
"""One image that could not be saved in a Annotations.bulk_save call."""
image_id: str
error: str
BulkSaveResult
class BulkSaveResult(BaseModel):
"""Outcome of Annotations.bulk_save."""
saved: list[SaveResult]
failed: list[BulkSaveFailure]
# Number of images successfully saved.
@property
def saved_count(self) -> int: ...
BulkUploadFailure
class BulkUploadFailure(BaseModel):
"""One file that couldn't be registered in a Images.bulk_upload call (e.g. a filename that already exists in the target directory)."""
filename: str
error: str
directory_path: str = '/'
BulkUploadResult
class BulkUploadResult(BaseModel):
"""Outcome of Images.bulk_upload."""
succeeded: list[Image]
failed: list[BulkUploadFailure]
# Number of files successfully uploaded + registered.
@property
def count(self) -> int: ...
ClassAttribute
class ClassAttribute(BaseModel):
"""A class-level ONTOLOGY attribute definition."""
name: str
# Input control: text | number | select | checkbox.
type: Literal['text', 'number', 'select', 'checkbox'] = 'text'
# Allowed values for a 'select' attribute.
values: list[str] | None = None
CopyToDatasetResult
class CopyToDatasetResult(BaseModel):
"""Outcome of pictograph.resources.batch.Batch.copy_to_dataset."""
success: bool
processed: int
failed: list[BatchFailure] = []
affected_directories: list[str] = []
renamed: int = 0
operation: str | None = None
target_dataset: str
classes_added: list[str] = []
CreatedApiKey
class CreatedApiKey(BaseModel):
"""Response from ApiKeys.create - includes the secret one time only."""
# The full secret. The API returns it only here - store it securely (Settings can
# reveal it again, once per sign-in).
api_key: str
key_id: str
key_prefix: str
name: str
role: Literal['viewer', 'member', 'admin', 'owner']
rate_limit: int
expires_at: datetime | None = None
created_at: datetime
CreatedDeployment
class CreatedDeployment(BaseModel):
"""What `create` returns: the deployment and its token, shown once."""
deployment: Deployment
# The deployment's bearer token. The API returns it only here; a member can reveal
# it again in the app.
auth_token: str
CreatedWebhookEndpoint
class CreatedWebhookEndpoint(BaseModel):
"""An endpoint and its signing secret (from create or a rotation)."""
endpoint: WebhookEndpoint
# The signing secret; the app shows it again under Settings → Webhooks.
secret: str
CreditBalance
class CreditBalance(BaseModel):
"""An organization's compute wallet, in micro-USD (µUSD)."""
# The plan's monthly allowance.
included_allowance_micro_usd: int = 0
# Allowance and prepaid credit left to spend this period.
included_remaining_micro_usd: int = 0
# Monthly spend cap, allowance included; equals the allowance with pay-as-you-go
# off.
budget_micro_usd: int = 0
# Spent this period.
period_spend_micro_usd: int = 0
# Spent beyond the allowance this period.
period_overage_micro_usd: int = 0
# Left under the spend cap this period.
budget_remaining_micro_usd: int = 0
# Start of the current billing period.
period_start: datetime | None = None
# When the monthly allowance resets next.
credits_reset_at: datetime | None = None
# DEPRECATED: whole-dollar remaining credit. Use included_remaining_micro_usd.
credits_remaining: int = 0
# DEPRECATED: whole-dollar monthly allowance. Use included_allowance_micro_usd.
credits_monthly_allowance: int = 0
# The last 20 ledger entries, newest first.
recent_history: list[CreditLedgerEntry] = []
# Monthly included allowance in USD (`included_allowance_micro_usd / 1e6`).
@property
def allowance_usd(self) -> float: ...
# Remaining overage budget in USD (`budget_remaining_micro_usd / 1e6`).
@property
def budget_remaining_usd(self) -> float: ...
# Overage budget cap in USD (`budget_micro_usd / 1e6`).
@property
def budget_usd(self) -> float: ...
# Overage incurred this period in USD (`period_overage_micro_usd / 1e6`).
@property
def overage_usd(self) -> float: ...
# Remaining included allowance in USD (`included_remaining_micro_usd / 1e6`).
@property
def remaining_usd(self) -> float: ...
# Total spend this period in USD (`period_spend_micro_usd / 1e6`).
@property
def spend_usd(self) -> float: ...
CreditEstimate
class CreditEstimate(BaseModel):
"""What a planned operation would cost, in micro-USD (µUSD), and whether the balance covers it."""
operation: str
# The unit priced, such as 'minute', 'image' or 'run'.
unit: str
quantity: int
# Price per unit.
micro_usd_per_unit: int = 0
# `micro_usd_per_unit * quantity`.
total_micro_usd: int = 0
# What the organization could spend when this was estimated.
remaining_micro_usd: int = 0
# Whether the balance covers `total_micro_usd`.
sufficient: bool = False
# DEPRECATED: whole-dollar per-unit cost. Use micro_usd_per_unit.
credits_per_unit: int = 0
# DEPRECATED: whole-dollar total cost. Use total_micro_usd.
total_credits: int = 0
# DEPRECATED: whole-dollar floor on total. No longer used (always 0).
minimum: int = 0
# DEPRECATED: whole-dollar remaining balance. Use remaining_micro_usd.
credits_remaining: int = 0
# Per-unit cost in USD (`micro_usd_per_unit / 1e6`).
@property
def per_unit_usd(self) -> float: ...
# Spendable compute credit in USD (`remaining_micro_usd / 1e6`).
@property
def remaining_usd(self) -> float: ...
# Total estimated cost in USD (`total_micro_usd / 1e6`).
@property
def total_usd(self) -> float: ...
CreditLedgerEntry
class CreditLedgerEntry(BaseModel):
"""A single entry in the organization's credit ledger."""
id: str
# Operation slug, such as 'training_a10g' or 'sam3_auto_annotation'.
operation: str
# Micro-USD: negative for a charge, positive for a top-up, reset or refund.
amount: int
# What could be spent right after this entry, in micro-USD.
balance_after: int | None = None
description: str | None = None
metadata: dict[str, Any] | None = None
created_at: datetime
Dataset
class Dataset(BaseModel):
"""A Pictograph dataset - a group of images sharing an annotation config."""
id: str
# The organization that owns it.
organization_id: str | None = None
name: str
# Its URL slug: pictograph.io/datasets/<organization>/<slug>.
slug: str | None = None
description: str | None = None
annotation_types: list[str] = ['bbox']
# Its classes; empty until it has any.
classes: list[DatasetClass] = []
# Images, archived ones excluded.
image_count: int = 0
# Images at the complete stage.
completed_image_count: int = 0
# Archived images (restorable).
archived_image_count: int = 0
# Bytes of its images, archived ones excluded.
total_size: int = 0
# Listed on Explore, readable by anyone.
is_public: bool = False
is_archived: bool = False
archived_at: datetime | None = None
# Where its images are stored: standard or coldline (cold storage).
storage_class: str = 'standard'
# Its license, a catalog id such as 'mit' or 'cc-by-4.0' ('custom': the terms are in
# license_custom_text).
license_id: str | None = None
# A custom license's terms (on get, not on list rows).
license_custom_text: str | None = None
# Its dataset card, in markdown (on get, not on list rows).
readme: str | None = None
# Where an imported dataset came from (on get, not on list rows).
source: DatasetSource | None = None
# Its Hugging Face mirror (e.g. 'pictograph/a2d2') while the mirror is live (on get,
# not on list rows).
hf_repo: str | None = None
# The image paths it shows on every card and page, in order; [] = automatic, the
# best-annotated images (on get, not on list rows).
hero_images: list[str] | None = None
# Its images, only from `datasets.get(..., include_images=True)`.
images: list[Image] | None = None
created_at: datetime
updated_at: datetime | None = None
DatasetClass
class DatasetClass(BaseModel):
"""A class definition stored on the dataset's config."""
name: str
# The annotation type it's for: bbox, polygon, polyline, keypoint or tag.
type: str | None = None
# Hex color, such as '#e6194b'. Omitted on a write, one is assigned from the class
# palette.
color: str | None = None
# The attributes an annotation of this class may carry.
attributes: list[ClassAttribute] | None = None
# A keypoint class's joint template (nodes and 0-indexed edges).
skeleton: SkeletonTemplate | None = None
DatasetDeleteResult
class DatasetDeleteResult(BaseModel):
"""What `datasets.delete` removed."""
id: str
name: str
deleted: bool = True
# Images deleted.
images_deleted: int = 0
# Directories deleted.
directories_deleted: int = 0
# Stored files deleted.
files_deleted: int = 0
# Stored files kept because an imported copy of the dataset still uses them.
files_kept: int = 0
DatasetImportProgress
class DatasetImportProgress(BaseModel):
"""Per-dataset progress row inside an ImportJob."""
name: str | None = None
dataset_id: str | None = None
status: Optional[Literal['pending', 'processing', 'completed', 'error', 'cancelled']] = None
imported: int = 0
failed: int = 0
DatasetInsights
class DatasetInsights(BaseModel):
"""Dataset Health / Insights - headline totals, class balance, and more."""
total_images: int = 0
total_annotations: int = 0
annotated_images: int = 0
unannotated_images: int = 0
avg_annotations_per_image: float = 0.0
total_bytes: int = 0
status_counts: InsightsStatusCounts = ...
class_annotation_counts: dict[str, int] = {}
class_image_counts: dict[str, int] = {}
type_counts: dict[str, int] = {}
annotation_density: dict[str, int] = {}
dimensions: InsightsDimensions = ...
model_confidence: ModelConfidence | None = None
DatasetRestoreEstimate
class DatasetRestoreEstimate(BaseModel):
"""Price quote (integer micro-USD) for restoring a cold dataset."""
operation: str = 'dataset_restore'
cold_bytes: int = 0
cold_image_count: int = 0
days_in_cold: float = 0.0
min_storage_days: float = 90.0
monthly_savings_micro_usd: int = 0
retrieval_micro_usd: int = 0
early_delete_micro_usd: int = 0
operations_micro_usd: int = 0
total_micro_usd: int = 0
DatasetSource
class DatasetSource(BaseModel):
"""Where an imported dataset came from - its credit line."""
# The source dataset's name, e.g. 'A2D2'.
name: str | None = None
# Where the original is published.
url: str | None = None
# Who made it.
author: str | None = None
DatasetStorageStatus
class DatasetStorageStatus(BaseModel):
"""Cold-storage state of a dataset (`GET /developer/datasets/{id}/storage`)."""
storage_class: str = 'standard'
storage_state: str = 'idle'
cold_since: datetime | None = None
cold_bytes: int = 0
cold_image_count: int = 0
storage_job_id: str | None = None
restore_estimate: DatasetRestoreEstimate | None = None
DatasetStorageTransition
class DatasetStorageTransition(BaseModel):
"""Acknowledgement that a freeze/restore background job started."""
job_id: str
storage_state: str
quoted_micro_usd: int | None = None
DeleteClassResult
class DeleteClassResult(BaseModel):
"""Outcome of Annotations.delete_class."""
dataset_id: str
name: str
config_updated: bool
images_updated: int
annotations_removed: int
DeleteResult
class DeleteResult(BaseModel):
"""Outcome of Annotations.delete."""
image_id: str
deleted_count: int
Deployment
class Deployment(BaseModel):
"""A model inference deployment: provisioning, active, paused, failed or terminated."""
id: str
organization_id: str
model_id: str
version_id: str | None = None
name: str
readme: str | None = None
status: Literal['draft', 'provisioning', 'active', 'paused', 'failed', 'terminated']
region: str | None = None
compute_type: Literal['cpu', 'gpu'] = 'gpu'
gpu_type: str | None = None
precision: str = 'fp32'
min_containers: int
max_containers: int
scaledown_window: int
rate_limit_rpm: int | None = None
endpoint_url: str | None = None
auth_token_prefix: str | None = None
inference_config: dict[str, Any] = {}
engine_build: EngineBuild | None = None
error_message: str | None = None
cost_rate_per_min: int = 0
cost_per_hour_micro_usd: int | None = None
max_cost_per_hour_micro_usd: int | None = None
transfer_per_gib_micro_usd: int | None = None
accrued_cost_micro_usd: int = 0
uptime_seconds: int = 0
transfer_bytes: int = 0
transfer_cost_micro_usd: int = 0
metrics: DeploymentMetrics | None = None
runtime: DeploymentRuntime | None = None
stream_limit: int = 0
region_fallback: bool = False
logged: bool | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
started_at: datetime | None = None
paused_at: datetime | None = None
DeploymentComputeOption
class DeploymentComputeOption(BaseModel):
"""A GPU tier a deployment runs on: its container and its price (one container)."""
key: str
label: str
compute_type: Literal['cpu', 'gpu'] = 'gpu'
gpu_type: str | None = None
is_gpu: bool = True
description: str = ''
vram_gb: int | None = None
cpu_cores: float | None = None
memory_gib: float | None = None
rate_per_min_micro_usd: int
cost_per_hour_micro_usd: int | None = None
DeploymentComputeOptions
class DeploymentComputeOptions(BaseModel):
"""What a deployment may run with: the regions (and the one these prices are for), each GPU tier (its container and price there) and each precision its engine is built at, the default first."""
region: str | None = None
regions: list[DeploymentRegion] = []
options: list[DeploymentComputeOption] = []
precisions: list[DeploymentComputePrecision] = []
transfer_per_gib_micro_usd: int | None = None
DeploymentComputePrecision
class DeploymentComputePrecision(BaseModel):
"""A precision a deployment's TensorRT engine can be built at, with its label."""
precision: str
label: str
description: str = ''
DeploymentMetrics
class DeploymentMetrics(BaseModel):
"""The requests a deployment has served."""
requests: int = 0
errors: int = 0
avg_latency_ms: float = 0.0
error_rate: float = 0.0
last_request_at: datetime | None = None
DeploymentQuote
class DeploymentQuote(BaseModel):
"""What a deployment costs while it is up, before creating it, in micro-USD."""
rate_per_min_micro_usd: int
container_cost_per_hour_micro_usd: int | None = None
cost_per_hour_micro_usd: int
cost_per_day_micro_usd: int
warm_cost_per_hour_micro_usd: int | None = None
warm_cost_per_day_micro_usd: int | None = None
max_cost_per_hour_micro_usd: int | None = None
transfer_per_gib_micro_usd: int | None = None
scale_to_zero: bool
billing_note: str
DeploymentRegion
class DeploymentRegion(BaseModel):
"""A region a deployment can run in."""
id: str
label: str
location: str = ''
ping_url: str | None = None
DeploymentRuntime
class DeploymentRuntime(BaseModel):
"""What an `active` deployment is doing right now, as Pictograph read it at `checked_at`."""
state: str
containers: int = 0
creating: int = 0
streams: int = 0
fallback: int = 0
waiting_since: datetime | None = None
checked_at: datetime | None = None
Directory
class Directory(BaseModel):
"""A single virtual directory in a dataset."""
id: str
dataset_id: str
organization_id: str | None = None
name: str
parent_directory_id: str | None = None
full_path: str
image_count: int = 0
nested_image_count: int = 0
created_by: str | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
DirectoryStats
class DirectoryStats(BaseModel):
"""Aggregate image statistics for a directory (and, by default, its subdirectories)."""
total_directories: int
total_images: int
total_size_bytes: int
directories_by_status: dict[str, int] = {}
DirectoryTreeNode
class DirectoryTreeNode(BaseModel):
"""A node in the hierarchical directory tree (children nested recursively)."""
id: str
name: str
full_path: str
image_count: int = 0
nested_image_count: int = 0
children: list[DirectoryTreeNode] = []
DownloadFailure
class DownloadFailure(BaseModel):
"""Single failed download - collected and returned, not raised."""
filename: str
kind: Literal['image', 'annotation']
reason: str
DownloadReport
class DownloadReport(BaseModel):
"""Result of a Datasets.download invocation."""
dataset_id: str
images_downloaded: int = 0
annotations_downloaded: int = 0
failures: list[DownloadFailure] = []
truncated: bool = False
@property
def success(self) -> bool: ...
@property
def total_attempted(self) -> int: ...
DuplicateGroup
class DuplicateGroup(BaseModel):
"""A cluster of near-duplicate images - keep one, the rest are redundant."""
members: list[DuplicateMember] = []
size: int = 0
max_similarity: float = 0.0
DuplicateMember
class DuplicateMember(BaseModel):
"""One image in a near-duplicate cluster (the metadata a review UI needs)."""
id: str
filename: str = ''
# Its directory in the dataset.
directory_path: str = ''
status: str = ''
annotation_count: int = 0
# The image's address in its dataset - pass it as `image` to any per-image call.
@property
def path(self) -> str: ...
EmbeddingBackfill
class EmbeddingBackfill(BaseModel):
"""What pictograph.resources.datasets.Datasets.backfill_embeddings queued."""
queued: int = 0
missing: int = 0
remaining: int = 0
EngineBuild
class EngineBuild(BaseModel):
"""The TensorRT engines a workflow run or a deployment builds: `state` is `"building"`, then `"built"`. `None` on the run or deployment when every engine was already built."""
state: str
models: list[EngineBuildModel] = []
EngineBuildModel
class EngineBuildModel(BaseModel):
"""One model's TensorRT engine build: which model, at what precision, and how far along."""
model_id: str
name: str | None = None
precision: str
state: str
started_at: datetime | None = None
estimate_s: float | None = None
build_s: float | None = None
EvalClassMetrics
class EvalClassMetrics(BaseModel):
"""Per-class metrics. Detection/instance-seg carry `ap`; semantic-seg carries pixel `iou` / `dice`."""
class_name: str
tp: int
fp: int
fn: int
support: int
precision: float
recall: float
f1: float
ap: float = 0.0
iou: float | None = None
dice: float | None = None
EvalConfusionMatrix
class EvalConfusionMatrix(BaseModel):
"""Confusion matrix (rows = ground truth, cols = predicted). Class-agnostic + IoU-matched for detection; per-pixel for semantic-seg; true-vs-predicted for classification."""
iou_threshold: float | None = None
labels: list[str] = []
grid: list[list[int]] = []
EvalImagePerformance
class EvalImagePerformance(BaseModel):
"""Per-image detection tallies used to rank the best- and worst-performing images."""
image_id: str
filename: str | None = None
# Its directory in the dataset.
directory_path: str | None = None
tp: int
fp: int
fn: int
gt_count: int
pred_count: int
predictions: list[dict[str, Any]] | None = None
ground_truth: list[dict[str, Any]] | None = None
miou: float | None = None
# The image's address in its dataset - pass it as `image` to any per-image call.
@property
def path(self) -> str | None: ...
EvalOverallMetrics
class EvalOverallMetrics(BaseModel):
"""Micro-averaged detection metrics pooled across all classes."""
tp: int
fp: int
fn: int
precision: float
recall: float
f1: float
macro_f1: float
map: float | None = 0.0
accuracy: float | None = None
miou: float | None = None
mean_dice: float | None = None
pixel_accuracy: float | None = None
mean_pixel_accuracy: float | None = None
frequency_weighted_iou: float | None = None
EvaluationCompute
class EvaluationCompute(BaseModel):
"""What an evaluation runs on: a GPU and the precision of the model's TensorRT engine."""
gpu: str = 't4'
precision: str = 'fp32'
EvaluationComputeGpu
class EvaluationComputeGpu(BaseModel):
"""A GPU an evaluation may run on, as pictograph.resources.model_evaluations.ModelEvaluations.compute_options lists it."""
gpu: str
label: str
vram_gb: int | None = None
description: str = ''
cost_per_hour_micro_usd: int = 0
EvaluationComputeOptions
class EvaluationComputeOptions(BaseModel):
"""What an evaluation may run on: each GPU with its memory and hourly price, each precision, the default."""
gpus: list[EvaluationComputeGpu] = []
precisions: list[EvaluationComputePrecision] = []
default: EvaluationCompute = ...
EvaluationComputePrecision
class EvaluationComputePrecision(BaseModel):
"""A precision the model's TensorRT engine can be built at, with its label."""
precision: str
label: str
description: str = ''
Export
class Export(BaseModel):
"""A dataset export - produced asynchronously, downloaded as a ZIP."""
id: str
dataset_id: str
dataset_name: str
name: str
format: Literal['pictograph', 'darwin', 'coco', 'yolo', 'yolo_obb', 'yolo_pose', 'dota', 'pascal_voc', 'cvat', 'datumaro', 'labelme', 'csv']
include_images: bool = False
# Only these classes' annotations; None for all.
class_filter: list[str] | None = None
# Only images at this stage; None for all.
status_filter: str | None = None
status: Literal['pending', 'processing', 'completed', 'failed']
# Why it failed.
error_message: str | None = None
# ZIP size in bytes.
file_size: int | None = None
image_count: int | None = None
annotation_count: int | None = None
created_at: datetime
# After this, the ZIP may be deleted.
expires_at: datetime | None = None
# Signed download URL; on get and list, not on create.
download_url: str | None = None
organization_id: str | None = None
Image
class Image(BaseModel):
"""An image within a Pictograph dataset."""
id: str
# Its dataset's id.
dataset_id: str | None = None
filename: str
# Its labeling stage.
status: Literal['new', 'annotate', 'review', 'complete'] = 'new'
# train, val or test; None if unassigned.
split: Optional[Literal['train', 'val', 'test']] = None
annotation_count: int = 0
# The lowest confidence among its annotations, 0 to 1 (1.0 for hand-drawn);
# `images.list(min_confidence_lt=...)` filters by it for a review queue. None for
# images saved before it was recorded.
min_confidence: float | None = None
# File size in bytes.
file_size: int = 0
# Width in pixels; None if unknown.
width: int | None = None
# Height in pixels; None if unknown.
height: int | None = None
# Stored MIME type, e.g. 'image/png'.
content_type: str | None = None
# Its directory in the dataset (`/` for the root).
directory_path: str | None = None
# Tags set by people (`images.bulk_tag` writes them), not auto-tags.
tags: list[str] = []
# True when archived; delete with `permanent=True` to remove it for good.
is_archived: bool = False
# URL of the full image; fetching it needs your X-API-Key (`images.download` saves
# it to disk).
image_url: str | None = None
# CDN URL of a thumbnail, about 200 px.
thumbnail_url: str | None = None
# API URL of its annotations, as JSON.
annotation_url: str | None = None
created_at: datetime
# The image's address in its dataset - pass it as `image` to any per-image call.
@property
def path(self) -> str: ...
ImageSplit
ImageSplit = Literal['train', 'val', 'test']
ImageStatus
ImageStatus = Literal['new', 'annotate', 'review', 'complete']
ImportJob
class ImportJob(BaseModel):
"""Snapshot of an import operation - totals + per-dataset breakdown."""
import_id: str
status: Literal['processing', 'completed', 'error', 'cancelled']
progress: float = 0.0
total_images: int = 0
imported_images: int = 0
failed_images: int = 0
current_dataset: str = ''
datasets: list[DatasetImportProgress] = []
InsightsDimensions
class InsightsDimensions(BaseModel):
"""Image-dimension insights (ranges, orientation split, size cloud)."""
min_width: int | None = None
max_width: int | None = None
avg_width: int | None = None
min_height: int | None = None
max_height: int | None = None
avg_height: int | None = None
orientation: InsightsOrientation = ...
sizes: list[InsightsSize] = []
distinct_size_count: int = 0
images_with_dimensions: int = 0
images_missing_dimensions: int = 0
InsightsOrientation
class InsightsOrientation(BaseModel):
"""Image counts by orientation."""
landscape: int = 0
portrait: int = 0
square: int = 0
InsightsSize
class InsightsSize(BaseModel):
"""One distinct image size and how many images share it."""
w: int
h: int
count: int
InsightsStatusCounts
class InsightsStatusCounts(BaseModel):
"""Image counts by labeling stage (new → complete)."""
new: int = 0
annotate: int = 0
review: int = 0
complete: int = 0
Job
class Job(BaseModel):
"""One job, whatever kind of work it is."""
id: str
type: str
status: str
progress: float | None = None
name: str | None = None
dataset_id: str | None = None
error: str | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
completed_at: datetime | None = None
cancel_path: str | None = None
detail: dict[str, Any] = {}
# True while the job is queued or running.
@property
def active(self) -> bool: ...
# True when Jobs.cancel can stop this job.
@property
def cancellable(self) -> bool: ...
KeypointAnnotation
class KeypointAnnotation(BaseModel):
"""Single-point annotation (e.g., facial landmarks, joint locations)."""
# Unique within the image; a UUID is generated when omitted.
id: str = ...
# Class name, case-sensitive; use one of the dataset's classes.
name: str
type: Literal['keypoint'] = 'keypoint'
keypoint: Point
confidence: float = 1.0
created_by: str | None = None
attributes: dict[str, object] | list[object] = []
# Which object the point belongs to, 1-based within the image: points sharing an
# instance_id are one object's joints, each named for its joint. None: a lone
# landmark.
instance_id: int | None = None
LimitCheckResult
class LimitCheckResult(BaseModel):
"""Outcome of Connectors.check_limits."""
allowed: bool
current_images: int
image_limit: int
images_after_import: int
current_storage_bytes: int
storage_limit_bytes: int
storage_after_import_bytes: int
exceeded: Optional[Literal['images', 'storage', 'both']] = None
MergeClassResult
class MergeClassResult(BaseModel):
"""Outcome of Annotations.merge_class."""
dataset_id: str
source_name: str
target_name: str
images_updated: int
annotations_updated: int
config_updated: bool
Model
class Model(BaseModel):
"""A trained computer vision model."""
id: str
organization_id: str
name: str
# Its URL name, unique in the organization.
slug: str | None = None
description: str | None = None
# Its model card, in Markdown.
readme: str | None = None
# Its license's catalog id (such as 'mit'), or 'custom' with license_custom_text.
license_id: str | None = None
# The license's text, when license_id is 'custom'.
license_custom_text: str | None = None
# How many people starred it.
star_count: int = 0
model_type: Literal['object_detection', 'semantic_segmentation', 'instance_segmentation', 'classification', 'keypoint_detection']
# Its architecture, such as 'yolox-s' or 'rfdetr-base'.
architecture: str | None = None
visibility: Literal['private', 'public']
status: Literal['training', 'ready', 'failed', 'archived']
# Its validation scores from training (mAP, precision, recall), once ready.
metrics: dict[str, Any] | None = None
# Its classes in index order, as `{"classes": [name, ...]}`.
class_mapping: dict[str, Any] | None = None
# Its training settings, including its input `image_width` and `image_height` (local
# inference reads them).
training_config: dict[str, Any] | None = None
version: str = '1.0.0'
# When set, this model was fine-tuned from another.
parent_model_id: str | None = None
# When set, this model was imported from a public model.
forked_from_model_id: str | None = None
# Its weights' precision. 'fp16': half-precision weights with fp32 inputs and
# outputs, about half the size and faster on a GPU.
precision: Literal['fp32', 'fp16'] = 'fp32'
created_at: datetime
updated_at: datetime
ModelConfidence
class ModelConfidence(BaseModel):
"""Active-learning rollup: how many images carry a low-confidence model prediction (min annotation confidence < 1.0), and how uncertain they are. Use it to size a human-review queue, then page it with `client.images.list(dataset_id, min_confidence_lt=...)`."""
flagged: int = 0
lowest: float | None = None
avg_flagged: float | None = None
buckets: ModelConfidenceBuckets = ...
ModelConfidenceBuckets
class ModelConfidenceBuckets(BaseModel):
"""Image counts by model-confidence band (active-learning review buckets)."""
lt50: int = 0
b50_70: int = 0
b70_90: int = 0
b90_100: int = 0
ModelEvaluation
class ModelEvaluation(BaseModel):
"""A model-evaluation run + its metric summary."""
id: str
organization_id: str
model_id: str
dataset_id: str
export_id: str | None = None
status: Literal['pending', 'running', 'completed', 'failed', 'cancelled']
progress: int = 0
iou_threshold: float = 0.5
confidence_threshold: float = 0.5
total_images: int = 0
evaluated_images: int = 0
failed_images: int = 0
overall_metrics: EvalOverallMetrics | None = None
per_class_metrics: list[EvalClassMetrics] | None = None
confusion_matrix: EvalConfusionMatrix | None = None
worst_images: list[EvalImagePerformance] | None = None
best_images: list[EvalImagePerformance] | None = None
seg_metrics: dict[str, Any] | None = None
config: dict[str, Any] | None = None
error_message: str | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
started_at: datetime | None = None
completed_at: datetime | None = None
precision: str = 'fp32'
gpu_type: str = 't4'
version_id: str | None = None
engine_build: dict[str, Any] | None = None
ModelFileEntry
class ModelFileEntry(BaseModel):
"""One downloadable artifact in a model's file manifest."""
version_id: str
name: str
kind: str
format: str
size_bytes: int | None = None
content_type: str | None = None
updated_at: datetime | None = None
runtime: str | None = None
precision: str | None = None
target_key: str | None = None
toolchain_version: str | None = None
stale: bool = False
artifact_id: str | None = None
ModelFileManifest
class ModelFileManifest(BaseModel):
"""A model's complete version + file manifest (`models.files`)."""
versions: list[ModelVersionEntry] = []
files: list[ModelFileEntry] = []
pinned_version_id: str | None = None
ModelPredictResult
class ModelPredictResult(BaseModel):
"""Result of a remote single-image test inference (`models.predict`)."""
success: bool = True
annotations: list[dict[str, Any]] = []
tags: list[str] = []
tag_scores: list[float] = []
model_type: Optional[Literal['object_detection', 'semantic_segmentation', 'instance_segmentation', 'classification', 'keypoint_detection']] = None
inference_seconds: float = 0.0
ModelVersionEntry
class ModelVersionEntry(BaseModel):
"""One version in a model's file manifest (`models.files`)."""
version_id: str
version_number: int | None = None
version_label: str | None = None
created_at: datetime | None = None
status: str | None = None
is_latest: bool = False
is_current: bool = False
precision: str = 'fp32'
training_run_id: str | None = None
architecture: str | None = None
metrics: dict[str, Any] = {}
export_name: str | None = None
pipeline_provenance: dict[str, Any] | None = None
ModelVersionsPayload
class ModelVersionsPayload(BaseModel):
"""`models.versions`: every version, and which one serves."""
versions: list[ModelVersionEntry] = []
current_version_id: str | None = None
pinned_version_id: str | None = None
latest_version_id: str | None = None
NearDuplicatesResult
class NearDuplicatesResult(BaseModel):
"""Near-duplicate clusters for a dataset + headline data-curation counts."""
groups: list[DuplicateGroup] = []
group_count: int = 0
duplicate_image_count: int = 0
redundant_count: int = 0
analyzed: int = 0
total_images: int = 0
sample_limit: int = 0
sample_capped: bool = False
pairs_capped: bool = False
threshold: float = 0.0
directory_path: str | None = None
Notification
class Notification(BaseModel):
"""One of your notifications: a training run that finished, an export that is ready."""
id: str
organization_id: str
user_id: str | None = None
# Event type, such as 'training_completed' or 'export_completed'.
type: str
title: str
message: str | None = None
metadata: dict[str, Any] | None = None
read: bool = False
created_at: datetime
OperationUsage
class OperationUsage(BaseModel):
"""Aggregated compute spend for a single operation slug over a window."""
# Operation slug, such as 'training_a10g'.
operation: str
# Total spend on this operation (µUSD).
total_micro_usd: int = 0
# Charges for this operation.
event_count: int = 0
# Total spend on this operation in USD (`total_micro_usd / 1e6`).
@property
def total_usd(self) -> float: ...
Organization
class Organization(BaseModel):
"""An organization: its plan, its plan's limits, and its member and invite counts."""
id: str
name: str
slug: str
description: str | None = None
is_public: bool | None = None
# Its plan.
subscription_tier: Union[Literal['free', 'core', 'pro', 'team', 'enterprise'], str]
# DEPRECATED: whole dollars left this period. Use credits.balance().
credits_remaining: int
# DEPRECATED: the monthly allowance in whole dollars. Use credits.balance().
credits_monthly_allowance: int
credits_reset_at: datetime | None = None
# Members its plan allows, pending invites included.
max_users: int
# Images its plan allows.
max_images: int
# Storage its plan allows, in bytes.
max_storage_bytes: int
member_count: int
pending_invite_count: int
created_at: datetime
updated_at: datetime
OrganizationInvite
class OrganizationInvite(BaseModel):
"""A pending / accepted / expired / revoked / declined invite."""
id: str
organization_id: str
email: str
role: Literal['admin', 'member', 'annotator', 'viewer']
status: Literal['pending', 'accepted', 'expired', 'revoked', 'declined']
invited_by: str | None = None
expires_at: datetime
created_at: datetime
OrganizationMember
class OrganizationMember(BaseModel):
"""One member of the organization."""
# Membership id: update_member_role and remove_member take it.
id: str
user_id: str
email: str | None = None
full_name: str | None = None
role: Literal['owner', 'admin', 'member', 'annotator', 'viewer']
joined_at: datetime
OrientedBoxGeometry
class OrientedBoxGeometry(BaseModel):
"""A rotated rectangle: a centre, extents along the box's OWN axes, and an angle."""
# Centre x, absolute image pixels.
cx: float
# Centre y, absolute image pixels.
cy: float
# Extent along the box's own +x axis.
w: float
# Extent along the box's own +y axis.
h: float
# Rotation in degrees, clockwise, [0, 360).
angle: float = 0.0
Point
class Point(BaseModel):
"""A 2D point in absolute pixel coordinates."""
x: float
y: float
PolygonAnnotation
class PolygonAnnotation(BaseModel):
"""Polygon annotation, optionally with holes (multi-path)."""
# Unique within the image; a UUID is generated when omitted.
id: str = ...
# Class name, case-sensitive; use one of the dataset's classes.
name: str
type: Literal['polygon'] = 'polygon'
# Enclosing rectangle; computed on save when omitted.
bounding_box: BoundingBox | None = None
polygon: PolygonGeometry
confidence: float = 1.0
created_by: str | None = None
attributes: dict[str, object] | list[object] = []
PolygonGeometry
class PolygonGeometry(BaseModel):
"""Polygon geometry: one or more rings, filled by the even-odd rule."""
# List of rings, filled by the even-odd rule: a ring within another is a hole, a
# ring outside the others is another piece of the same object. Put the main outline
# first. Each ring needs >= 3 points.
paths: list[list[Point]]
PolylineAnnotation
class PolylineAnnotation(BaseModel):
"""Open polyline annotation (e.g., road centerlines, lanes)."""
# Unique within the image; a UUID is generated when omitted.
id: str = ...
# Class name, case-sensitive; use one of the dataset's classes.
name: str
type: Literal['polyline'] = 'polyline'
# Enclosing rectangle; computed on save when omitted.
bounding_box: BoundingBox | None = None
polyline: PolylineGeometry
confidence: float = 1.0
created_by: str | None = None
attributes: dict[str, object] | list[object] = []
PolylineGeometry
class PolylineGeometry(BaseModel):
"""Open path: an ordered list of points connected by line segments."""
# Ordered list of points (>= 2). Does not close.
path: list[Point]
PromptResult
class PromptResult(BaseModel):
"""Outcome of a single SAM3 prompt (point / box / text)."""
status: Literal['success', 'no_detection', 'below_threshold']
annotations: list[Annotation] = []
# Confidence score for the primary detection (point/box only).
score: float | None = None
# GPU inference time, in seconds.
inference_time: float | None = None
PublicDataset
class PublicDataset(BaseModel):
"""A dataset in the public catalog, as Explore lists it."""
id: str
name: str
slug: str | None = None
description: str | None = None
organization: PublicOrganization | None = None
# Images in the dataset.
image_count: int = 0
annotation_count: int = 0
annotation_types: list[str] = []
# Its classes. A list row carries the first few; the detail has them all.
classes: list[DatasetClass] = []
class_count: int = 0
# What its images most often show.
top_auto_tags: list[str] = []
# The license it was published under (e.g. 'cc-by-4.0').
license_id: str | None = None
star_count: int = 0
is_fork: bool = False
# Its Hugging Face mirror, if any.
hf_repo: str | None = None
# Its dataset card (detail only).
readme: str | None = None
published_at: datetime | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
# The qualified public name `"<organization>/<dataset>"` an import takes.
@property
def ref(self) -> str: ...
PublicDatasetImport
class PublicDatasetImport(BaseModel):
"""An import of a public dataset into your organization."""
import_id: str
status: Union[Literal['pending', 'running', 'completed', 'failed', 'cancelled'], str]
# The copy in your organization.
dataset_id: str | None = None
# The copy's name (a name your organization already used is suffixed '(imported)').
dataset_name: str | None = None
source: PublicImportSource | None = None
total_images: int = 0
# Images copied so far.
image_count: int = 0
# 0-100.
progress: float = 0.0
error: str | None = None
created_at: datetime | None = None
completed_at: datetime | None = None
# It finished, one way or another.
@property
def done(self) -> bool: ...
PublicImportSource
class PublicImportSource(BaseModel):
"""What an import copied from."""
organization: str | None = None
dataset: str | None = None
dataset_id: str | None = None
PublicModel
class PublicModel(BaseModel):
"""A ready model in the public catalog, as Explore lists it."""
id: str
name: str
slug: str | None = None
description: str | None = None
organization: PublicOrganization | None = None
model_type: str
architecture: str | None = None
precision: str | None = None
# Its classes, in index order (`{'classes': [...]}`).
class_mapping: dict[str, Any] | None = None
# Its evaluation scores.
metrics: dict[str, Any] = {}
training_config: dict[str, Any] | None = None
license_id: str | None = None
star_count: int = 0
weights_size_bytes: int | None = None
is_fork: bool = False
hf_repo: str | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
# Its class names, in index order.
@property
def classes(self) -> list[str]: ...
# The qualified public name `"<organization>/<model>"` `models.fork` takes.
@property
def ref(self) -> str: ...
PublicModelDetail
class PublicModelDetail(BaseModel):
"""One public model, as its own Explore page shows it (`explore.model`)."""
id: str
name: str
slug: str | None = None
description: str | None = None
organization: PublicOrganization | None = None
model_type: str
architecture: str | None = None
precision: str | None = None
# Its classes, in index order (`{'classes': [...]}`).
class_mapping: dict[str, Any] | None = None
# Its evaluation scores.
metrics: dict[str, Any] = {}
training_config: dict[str, Any] | None = None
license_id: str | None = None
star_count: int = 0
weights_size_bytes: int | None = None
is_fork: bool = False
hf_repo: str | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
# Its model card, in Markdown.
readme: str | None = None
# The license's text, when license_id is 'custom'.
license_custom_text: str | None = None
PublicOrganization
class PublicOrganization(BaseModel):
"""The organization that published a dataset or a model."""
id: str | None = None
name: str
slug: str
RemoteDataset
class RemoteDataset(BaseModel):
"""One dataset as listed by the source provider's validate call."""
id: str
name: str
slug: str
image_count: int = 0
version: int | None = None
RenameClassResult
class RenameClassResult(BaseModel):
"""Outcome of Annotations.rename_class."""
dataset_id: str
old_name: str
new_name: str
images_updated: int
annotations_updated: int
config_updated: bool
RunLogBranchCounts
class RunLogBranchCounts(BaseModel):
"""How a Condition block split a stream's records: `passed` (true branch), `failed` (false)."""
passed: int = 0
failed: int = 0
RunLogEventName
class RunLogEventName(BaseModel):
"""What a person reads for a log record's trigger: its event's name and kind (`WorkflowLiveEvent`'s)."""
name: str
kind: str
RunLogPage
class RunLogPage(BaseModel):
"""One page of a run's log: its `records`, and `next_cursor` until the last page."""
stream: Literal['frames', 'events', 'stats']
order: Literal['asc', 'desc'] = 'asc'
records: list[RunLogRecord] = []
next_cursor: str | None = None
log_frames: bool = True
event_names: dict[str, RunLogEventName] = {}
RunLogRecord
class RunLogRecord(BaseModel):
"""One record of a run's log: a frame, an event (a trigger firing, a capture and its upload) or stats."""
ts: datetime
engine_run: str
seq: int
record_index: int
type: str | None = None
source: str | None = None
frame: int | None = None
pts: float | None = None
image: str | None = None
image_id: str | None = None
image_index: int | None = None
image_width: int | None = None
image_height: int | None = None
annotation_count: int | None = None
classes: list[str] = []
track_ids: list[str] = []
condition: bool | None = None
min_confidence: float | None = None
max_confidence: float | None = None
latency_total_ms: float | None = None
latency_engine_ms: float | None = None
latency_inference_ms: float | None = None
model_name: str | None = None
model_task: str | None = None
event_id: str | None = None
trigger: str | None = None
sequence: int | None = None
capture_kind: str | None = None
capture_ok: bool | None = None
capture_detail: str | None = None
capture_name: str | None = None
capture_uri: str | None = None
capture_bytes: int | None = None
clock_suspect: bool | None = None
rule_values: dict[str, Any] | None = None
values_text: str | None = None
sources: list[dict[str, Any]] | None = None
pictograph: dict[str, Any] | None = None
tag_confidences: Any = None
measures: Any = None
extra: dict[str, Any] | None = None
message: dict[str, Any] | None = None
RunLogStreamSummary
class RunLogStreamSummary(BaseModel):
"""One stream of a run's log: its record count, first and last record times, and with a Condition block, each branch's count (`condition`)."""
count: int = 0
first_ts: datetime | None = None
last_ts: datetime | None = None
condition: RunLogBranchCounts | None = None
RunLogSummary
class RunLogSummary(BaseModel):
"""What a run logged, per stream (`frames` / `events` / `stats`), counted from the log."""
log_frames: bool = True
streams: dict[str, RunLogStreamSummary] = {}
Sam3Prediction
class Sam3Prediction(BaseModel):
"""SAM3's answer to one prompt on an image you sent. Nothing was saved."""
status: Literal['success', 'no_detection', 'below_threshold']
annotations: list[Annotation] = []
# Confidence score for the primary detection (point/box only).
score: float | None = None
# GPU inference time, in seconds.
inference_time: float | None = None
prompt: Literal['text', 'box', 'point']
# The upright image's width in pixels.
width: int
# The upright image's height in pixels.
height: int
# SHA-256 of the image's bytes: an image is charged once, by this.
image_sha256: str | None = None
# The minimum score applied (the prompt's default when none was given).
confidence_threshold: float | None = None
# True when the image held more matches than fit in GPU memory, so only the most
# confident came back; `confidence_threshold` says where the cut fell.
degraded: bool = False
SaveResult
class SaveResult(BaseModel):
"""Outcome of Annotations.save."""
image_id: str
previous_count: int
new_count: int
status: str
SimilarImage
class SimilarImage(BaseModel):
"""One result from pictograph.resources.search.Search.by_similarity."""
id: str
filename: str
# Its directory in the dataset.
directory_path: str = '/'
status: Literal['new', 'annotate', 'review', 'complete']
annotation_count: int
# Its auto-tags, by kind: objects, scenes and attributes.
auto_tags: dict[str, Any] = {}
similarity: float
# The image's address in its dataset - pass it as `image` to any per-image call.
@property
def path(self) -> str: ...
SimilarQuote
class SimilarQuote(BaseModel):
"""What an "Annotate similar" job would run and cost: the checks AutoAnnotate.similar makes (the examples, the target class, whether SAM3 can read the example image, the images in scope) and its estimate."""
# Images the job would label (at most `max_images`).
total_images: int
# Other images in the scope, before the cap.
total_in_scope: int = 0
# True when the scope holds more than `max_images`.
capped: bool = False
# Image ceiling for a single job.
max_images: int = 2000
# The estimate, in micro-USD; the job starts only if the balance covers it.
estimated_credits: int
# T4 containers the job would run on.
containers: int = 0
# Your remaining balance (µUSD).
remaining_credits: int = 0
# Whether the balance covers the estimate.
sufficient: bool = True
# Example polygons the job would learn from.
examples: int = 0
# The class each match is labelled as.
target_class: str = ''
# polygon, bbox or obb.
output_type: str = 'polygon'
# directory or dataset.
scope: str = 'directory'
# The example image's folder.
directory: str = '/'
SkeletonJoint
class SkeletonJoint(BaseModel):
"""One joint of a keypoint class's template: the joint's own class name, and a suggested position on the unit square (where the app places it; not a constraint)."""
name: str
x: float = 0.5
y: float = 0.5
SkeletonTemplate
class SkeletonTemplate(BaseModel):
"""A keypoint class's joint template."""
nodes: list[SkeletonJoint]
edges: list[tuple[int, int]] = []
TaggedImage
class TaggedImage(BaseModel):
"""One result from pictograph.resources.search.Search.by_tag."""
id: str
dataset_id: str
filename: str
# Its directory in the dataset.
directory_path: str = '/'
status: Literal['new', 'annotate', 'review', 'complete']
annotation_count: int
# Its auto-tags, by kind: objects, scenes and attributes.
auto_tags: dict[str, Any] = {}
# The image's address in its dataset - pass it as `image` to any per-image call.
@property
def path(self) -> str: ...
Task
class Task(BaseModel):
"""One annotation task in the organization (list item)."""
id: str
# The dataset the task's images belong to.
dataset_id: str
# Dataset name (may be null if renamed/removed).
dataset: str | None = None
title: str
# 'annotate' or 'review'.
kind: str
# 'open' or 'done'.
status: str
created_at: datetime
# Number of images frozen into the task.
image_count: int
# Number of org members the task is assigned to.
assignee_count: int
TaskContribution
class TaskContribution(BaseModel):
"""One annotator's contribution to a task."""
user_id: str
full_name: str
email: str | None = None
avatar_url: str | None = None
# Whether this person is a task assignee (vs a non-assignee contributor).
is_assignee: bool
# Measured active editing time on the task's images (seconds).
active_seconds: int
# Distinct task images this person annotated or authored.
images_worked: int
# Task images they last-saved that are now at 'complete'.
images_completed: int
# Annotations on images they most recently authored.
annotations_added: int
# `active_seconds` as minutes (float), for display.
@property
def active_minutes(self) -> float: ...
TaskContributions
class TaskContributions(BaseModel):
"""Per-annotator contribution breakdown for a task, with rollup totals."""
task_id: str
contributors: list[TaskContribution]
contributor_count: int
# Total images frozen into the task.
total_images: int
# Task images at status 'complete' (any annotator).
images_complete: int
# Sum of every annotator's active editing time (seconds).
total_active_seconds: int
# `total_active_seconds` as minutes (float), for display.
@property
def total_active_minutes(self) -> float: ...
TileFailure
class TileFailure(BaseModel):
"""One source image that failed to tile (kind in `reason`)."""
image_id: str
filename: str
reason: str
TileReport
class TileReport(BaseModel):
"""Outcome of an Images.tile run."""
source: str
target: str
source_images: int = 0
tiles_created: int = 0
empty_tiles: int = 0
annotations_written: int = 0
failures: list[TileFailure] = []
@property
def success(self) -> bool: ...
ToolCard
class ToolCard(BaseModel):
"""Everything an agent needs to call one vision tool."""
tool: str
kind: str
id: str | None = None
name: str
task: str | None = None
status: str | None = None
summary: str = ''
about: str | None = None
classes: list[ToolClass] = []
facts: dict[str, Any] = {}
parameters: list[ToolParameter] = []
output: ToolOutput | None = None
modes: list[ToolMode] = []
related: list[ToolRelated] = []
notes: list[str] = []
ToolClass
class ToolClass(BaseModel):
"""A class a tool predicts, and the annotation type it comes back as."""
name: str
type: str | None = None
ToolCost
class ToolCost(BaseModel):
"""What one way of running a tool costs."""
summary: str = ''
micro_usd: int | None = None
per: str | None = None
estimate: bool = False
options: list[dict[str, Any]] = []
@property
def free(self) -> bool: ...
# `micro_usd` in dollars, or `None` when the price depends.
@property
def usd(self) -> float | None: ...
ToolInput
class ToolInput(BaseModel):
"""Whether one way of running a tool accepts one kind of input."""
kind: str
supported: bool = False
note: str | None = None
ToolMode
class ToolMode(BaseModel):
"""One way of running a tool (`hosted`, `local`, `endpoint`, `file`, ...)."""
mode: str
title: str = ''
description: str = ''
inputs: list[ToolInput] = []
limits: dict[str, Any] = {}
requires: list[str] = []
writes: bool | str = False
cost: ToolCost = ...
returns: str | None = None
run: ToolRun = ...
ToolOutput
class ToolOutput(BaseModel):
"""The shape of ONE prediction: prose, its JSON Schema, and an example."""
type: str | None = None
description: str = ''
coordinates: str | None = None
json_schema: dict[str, Any] | None = None
example: dict[str, Any] | None = None
ToolParameter
class ToolParameter(BaseModel):
"""A parameter a tool takes, with the bounds the API enforces."""
name: str
type: str = 'string'
default: Any = None
minimum: float | None = None
maximum: float | None = None
choices: list[str] = []
applies_to: list[str] = []
description: str = ''
ToolRelated
class ToolRelated(BaseModel):
"""Another tool tied to this one (a model's endpoint, a workflow's models)."""
tool: str
relation: str = ''
ToolRun
class ToolRun(BaseModel):
"""The exact call for one way of running a tool, in each interface that has one."""
cli: str | None = None
python: str | None = None
http: str | None = None
ToolSummary
class ToolSummary(BaseModel):
"""One row of `client.tools.list()`."""
tool: str
kind: str
id: str | None = None
name: str
task: str | None = None
status: str | None = None
summary: str = ''
TrainingClassSupport
class TrainingClassSupport(BaseModel):
"""How much of each class a run would train on."""
pipeline_type: str
# "annotations", or "images" for classification.
unit: str
# What this pipeline trains on, in words.
trains_on: str
# "assigned" (the images' own train/val/test) or "random" (the trainer makes one).
split: str
# The export's images that still exist.
images: int = 0
# The images the export names.
export_images: int | None = None
classes: list[TrainingClassSupportEntry] = []
untrainable: list[str] = []
# Classification: images with more than one selected tag (dropped).
multi_tag_images: int = 0
TrainingClassSupportEntry
class TrainingClassSupportEntry(BaseModel):
"""One class of a run, counted the way the trainer will count it in this export."""
name: str
# Units (`unit`) of this class across the whole export.
support: int = 0
# Units in the train split - only when the images' assigned split is used.
train: int | None = None
val: int | None = None
test: int | None = None
# Whether the run would train it (a class the train split does not supervise is left
# out of the model, or refused for keypoints).
trainable: bool
# When not trainable: "no_training_data" or "not_in_train_split".
reason: str | None = None
TrainingQuote
class TrainingQuote(BaseModel):
"""A training run checked and priced without starting it (Training.quote)."""
dataset_id: str
dataset_name: str
export_id: str
export_name: str
image_count: int | None = None
annotation_count: int | None = None
pipeline_type: Literal['yolox', 'sm_pytorch', 'classification', 'rfdetr_detection', 'rfdetr_segmentation', 'rfdetr_keypoint']
# What was asked for, `"auto"` included.
requested_gpu_type: str
# The tier the run would use.
gpu_type: str
# Whether the config's predicted peak memory fits `gpu_type`; `None` when the
# pipeline has no estimate.
fits: bool | None = None
# What `gpu_type="auto"` resolves to for this config.
recommended_gpu_type: str | None = None
# The auto-select decision behind `recommended_gpu_type`.
gpu_autoselect: dict[str, Any] | None = None
tiers: list[TrainingQuoteTier] = []
epochs: int
# The classes it would train.
classes: list[str] = []
class_support: TrainingClassSupport | None = None
# Images the export names that were deleted since it was taken.
deleted_images: int | None = None
estimate: TrainingQuoteEstimate
balance: TrainingQuoteBalance
can_start: bool
blocking: list[TrainingQuoteBlock] = []
# The config the run would be stored with.
config: dict[str, Any] = {}
TrainingQuoteBalance
class TrainingQuoteBalance(BaseModel):
"""The org's spendable balance against what starting a run needs."""
budget_remaining_micro_usd: int
required_to_start_micro_usd: int
covers_estimate: bool
TrainingQuoteBlock
class TrainingQuoteBlock(BaseModel):
"""Something that keeps a valid run from starting."""
# "insufficient_credits", "forbidden" or "key_without_creator".
code: str
message: str
TrainingQuoteEstimate
class TrainingQuoteEstimate(BaseModel):
"""The run's estimated cost; the charge is the GPU time it uses."""
minutes: int
micro_usd_per_minute: int
total_micro_usd: int
note: str = ''
TrainingQuoteTier
class TrainingQuoteTier(BaseModel):
"""One GPU tier a run can use, priced, and whether the config's predicted peak fits."""
gpu_type: str
total_mib: int
# `None` when the pipeline has no memory estimate (YOLOX).
fits: bool | None = None
micro_usd_per_minute: int
TrainingRun
class TrainingRun(BaseModel):
"""A single training job."""
id: str
organization_id: str
name: str
# The dataset it trained on.
dataset_id: str | None = None
# The export it trained on.
export_id: str | None = None
# The model it made, once completed.
model_id: str | None = None
pipeline_type: Literal['yolox', 'sm_pytorch', 'classification', 'rfdetr_detection', 'rfdetr_segmentation', 'rfdetr_keypoint']
gpu_type: Optional[Literal['a10g', 'a100', 'h100', 'auto']] = None
status: Literal['pending', 'queued', 'running', 'completed', 'failed', 'cancelled']
# 0-100 percent.
progress: int = 0
current_epoch: int = 0
total_epochs: int | None = None
metrics: dict[str, Any] = {}
config: dict[str, Any] = {}
eta_seconds: int | None = None
# Seconds of GPU time the run used, once it completes.
training_time_seconds: int | None = None
error_message: str | None = None
# What was left out of the model and why, such as a class the train split doesn't
# supervise; None when nothing was.
warnings: list[TrainingRunWarning] | None = None
started_at: datetime | None = None
completed_at: datetime | None = None
created_at: datetime
created_by: str | None = None
TrainingRunWarning
class TrainingRunWarning(BaseModel):
"""Something a training run's prep left out of the model, and why."""
code: str
# The warning, in words.
message: str
classes: list[dict[str, Any]] = []
# What the per-split counts are in: "annotations", "pixels" or "images".
unit: str | None = None
UploadFailure
class UploadFailure(BaseModel):
"""One file that failed to upload in Images.upload_from_directory."""
path: Path
reason: str
UploadReport
class UploadReport(BaseModel):
"""Outcome of an Images.upload_from_directory call."""
dataset_name: str
images_attempted: int = 0
images_uploaded: int = 0
images_skipped: int = 0
failures: list[UploadFailure] = []
@property
def success(self) -> bool: ...
UsageByOperation
class UsageByOperation(BaseModel):
"""Per-operation compute-spend breakdown over a rolling window."""
# Window: 'day' | 'week' | 'month' | 'all'.
range: str
# ISO timestamp the window starts at.
since: str | None = None
operations: list[OperationUsage] = []
# Total spend across the window (µUSD).
total_micro_usd: int = 0
# Charges across the window.
total_events: int = 0
# Total spend across the window in USD (`total_micro_usd / 1e6`).
@property
def total_usd(self) -> float: ...
ValidationResult
class ValidationResult(BaseModel):
"""Outcome of Connectors.validate."""
valid: bool
workspace: str = ''
datasets: list[RemoteDataset] = []
error: str | None = None
VideoExtractionJob
class VideoExtractionJob(BaseModel):
"""Snapshot of a frame-extraction job."""
job_id: str
status: Literal['processing', 'complete', 'failed']
progress: int = 0
frames_extracted: int = 0
total_frames: int = 0
error: str | None = None
# The directory the frames went into, once it succeeds.
directory_path: str | None = None
# Set when the image quota cut the frames short; the job still completes.
warning: str | None = None
# The frames' image ids, once the job is complete.
image_ids: list[str] | None = None
VideoMetadata
class VideoMetadata(BaseModel):
"""Probe result for an uploaded video."""
duration_seconds: float
# The video's frame rate.
native_fps: float
width: int
height: int
# Frames at its own rate.
frame_count: int
VideoUploadInfo
class VideoUploadInfo(BaseModel):
"""An uploaded video: `video` is the handle pictograph.resources.video.Video.probe and pictograph.resources.video.Video.extract_frames take."""
upload_url: str
video: str
WebhookDelivery
class WebhookDelivery(BaseModel):
"""One event's delivery to an endpoint, with its retries."""
id: str
endpoint_id: str
organization_id: str
event_type: str
# Sent to your endpoint as X-Pictograph-Delivery-Id.
delivery_id: str
# pending (being tried), delivered, failed or dead_letter (out of retries).
status: Literal['pending', 'delivered', 'failed', 'dead_letter']
# Tries so far.
attempts: int = 0
# What the last try got back.
last_status_code: int | None = None
# The last try's error.
last_error: str | None = None
# When it's tried next.
next_retry_at: datetime | None = None
created_at: datetime | None = None
# When it was delivered.
delivered_at: datetime | None = None
WebhookEndpoint
class WebhookEndpoint(BaseModel):
"""A registered outbound webhook destination."""
id: str
organization_id: str
url: str
description: str | None = None
# The events it's sent; empty means every event.
event_types: list[str] = []
# Whether it's sent deliveries; turned off after many failures.
enabled: bool = True
# Goes up by one at each rotation.
secret_version: int = 1
# The secret's first characters.
secret_prefix: str | None = None
# Failed deliveries in a row; 0 after a success.
consecutive_failures: int = 0
# Why it was turned off.
disabled_reason: str | None = None
# The names of its custom headers (their values are never returned).
auth_header_names: list[str] | None = None
# When it was last sent a delivery.
last_delivery_at: datetime | None = None
created_at: datetime | None = None
Workflow
class Workflow(BaseModel):
"""A saved node-graph workflow."""
id: str
organization_id: str
name: str
description: str | None = None
readme: str | None = None
graph: dict[str, Any] = {}
template_key: str | None = None
status: Literal['draft', 'ready', 'archived'] = 'draft'
compute: WorkflowCompute = WorkflowCompute(gpu='t4')
last_run_id: str | None = None
validation: list[WorkflowIssue] = []
endpoint: WorkflowEndpoint | None = None
endpoint_token: str | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
WorkflowCompute
class WorkflowCompute(BaseModel):
"""What a workflow's runs run on: its GPU."""
gpu: str = 't4'
WorkflowComputeGpu
class WorkflowComputeGpu(BaseModel):
"""A GPU a workflow may run on, as pictograph.resources.workflows.Workflows.compute_options lists it."""
gpu: str
label: str
vram_gb: int | None = None
description: str = ''
rate_per_min_micro_usd: int = 0
cost_per_hour_micro_usd: int = 0
WorkflowComputeOptions
class WorkflowComputeOptions(BaseModel):
"""A workflow's compute choices, priced in one region: each GPU with its memory and price, each precision a Model block may take, the default, and every region."""
gpus: list[WorkflowComputeGpu] = []
precisions: list[WorkflowComputePrecision] = []
default: WorkflowCompute = WorkflowCompute(gpu='t4')
region: str | None = None
regions: list[DeploymentRegion] = []
transfer_per_gib_micro_usd: int | None = None
WorkflowComputePrecision
class WorkflowComputePrecision(BaseModel):
"""A precision a Model block may take (its config's `precision`)."""
precision: str
label: str
description: str = ''
WorkflowEndpoint
class WorkflowEndpoint(BaseModel):
"""A workflow's endpoint: where its file and dataset runs and its live streams run, in its region."""
id: str
status: Literal['draft', 'provisioning', 'active', 'paused', 'failed', 'terminated']
region: str | None = None
gpu_type: str | None = None
min_containers: int = 0
max_containers: int = 1
scaledown_window: int = 60
endpoint_url: str | None = None
auth_token_prefix: str | None = None
error_message: str | None = None
engine_build: EngineBuild | None = None
stream_limit: int = 0
run_limit: int = 0
region_fallback: bool = False
streams: bool = True
deployed: bool = False
logged: bool | None = None
live: WorkflowLive = ...
live_outputs: WorkflowLiveOutputs | None = None
runtime: DeploymentRuntime | None = None
cost_per_hour_micro_usd: int = 0
max_cost_per_hour_micro_usd: int = 0
transfer_per_gib_micro_usd: int | None = None
accrued_cost_micro_usd: int = 0
uptime_seconds: int = 0
transfer_bytes: int = 0
transfer_cost_micro_usd: int = 0
created_at: datetime | None = None
started_at: datetime | None = None
paused_at: datetime | None = None
updated_at: datetime | None = None
WorkflowIssue
class WorkflowIssue(BaseModel):
"""One issue with a graph: `severity` `"error"` (a run would be refused) or `"warning"`, its `code` and `message`, and its block (`node_id`; None for the whole graph)."""
code: str
message: str
node_id: str | None = None
severity: str = 'error'
WorkflowLive
class WorkflowLive(BaseModel):
"""What a workflow's live stream runs and draws: its models, lines and zones, classes (each with its drawing colour and annotation type) and the events it offers (`events`)."""
models: list[WorkflowLiveModel] = []
measures: list[WorkflowLiveMeasure] = []
classes: list[str] = []
class_colors: dict[str, str] = {}
class_types: dict[str, str] = {}
events: list[WorkflowLiveEvent] = []
WorkflowLiveEvent
class WorkflowLiveEvent(BaseModel):
"""An event a workflow offers: Event capture and a webhook pick it by `key`, and its log names it by `trigger`. Passive capture is one too (kind `"passive"`)."""
trigger: str
key: str
kind: str
name: str
WorkflowLiveMeasure
class WorkflowLiveMeasure(BaseModel):
"""A line or zone of a workflow's live stream, as each frame's `measures` names it (by `id`)."""
id: str
name: str
kind: str
measure: str
label: str
color: str | None = None
WorkflowLiveModel
class WorkflowLiveModel(BaseModel):
"""A model a workflow's live stream runs: one per Model block's model at its precision."""
model_id: str
name: str
precision: str = 'fp32'
model_type: str | None = None
WorkflowLiveOutputs
class WorkflowLiveOutputs(BaseModel):
"""What a workflow endpoint's live outputs did, every outcome counted."""
events: int = 0
deliveries: int = 0
saved: int = 0
not_saved: int = 0
skipped: int = 0
since: datetime | None = None
last_not_saved_reason: str | None = None
last_not_saved_at: datetime | None = None
WorkflowNodeCard
class WorkflowNodeCard(BaseModel):
"""One block type: the port it takes (`inputs`) and emits (`output`; None for a sink), a new block's config (`new_block`), its settings (`fields`) and its validation `rules`."""
type: str
label: str
summary: str
inputs: list[str] = []
output: str | None = None
new_block: dict[str, Any] = {}
fields: list[WorkflowNodeField] = []
rules: list[str] = []
WorkflowNodeCatalog
class WorkflowNodeCatalog(BaseModel):
"""Every block type (`nodes`, in the editor's order) and how a graph is written (`graph`)."""
graph: dict[str, Any] = {}
nodes: list[WorkflowNodeCard] = []
WorkflowNodeField
class WorkflowNodeField(BaseModel):
"""One setting of a block's config: its `key`, JSON `type`, whether a run needs it (`True`, or when, in words), its `default`, allowed `values`, a `note` and nested `fields`."""
key: str
type: str
required: bool | str = False
default: Any = None
values: list[Any] | None = None
note: str = ''
fields: list[WorkflowNodeField] | None = None
WorkflowRun
class WorkflowRun(BaseModel):
"""One execution of a workflow over a source."""
id: str
organization_id: str
workflow_id: str
status: Literal['queued', 'processing', 'completed', 'error', 'cancelled']
progress: float = 0.0
frames_total: int | None = None
frames_done: int = 0
sample_fps: float | None = None
step_results: dict[str, Any] = {}
condition_results: dict[str, Any] = {}
artifacts: list[dict[str, Any]] = []
warnings: list[str] = []
final_micro_usd: int | None = None
error: str | None = None
dispatch_note: str | None = None
endpoint_id: str | None = None
has_log: bool = False
compute: WorkflowRunCompute = ...
engine_build: EngineBuild | None = None
source: WorkflowRunSource | None = None
stream_session: str | None = None
outputs: WorkflowRunWrites | None = None
live_view: WorkflowRunLiveView | None = None
recording: WorkflowRunRecording | None = None
result: dict[str, Any] | None = None
created_at: datetime | None = None
completed_at: datetime | None = None
WorkflowRunCompute
class WorkflowRunCompute(BaseModel):
"""What a run ran with: its GPU and the precision its model ran at."""
gpu: str = 't4'
precision: str = 'fp32'
WorkflowRunCreated
class WorkflowRunCreated(BaseModel):
"""What `run` returns at once: the new run's id. The run is billed as its endpoint's uptime; its share lands on `final_micro_usd` when it ends."""
run_id: str
status_url: str | None = None
WorkflowRunLiveView
class WorkflowRunLiveView(BaseModel):
"""A video, dataset or export run's live view: `stream` and `overlay` as the run started (`watch_run`'s stream switches them), and `session` once the run is dispatched."""
stream: bool = False
overlay: bool = True
session: str | None = None
WorkflowRunRecording
class WorkflowRunRecording(BaseModel):
"""A stream run's annotated video: `state` is `"saved"` (whole), `"partial"` (up to where it stopped) or `"none"`, with `detail` saying why; `bytes`, `parts` and `at` (when it was made)."""
state: Literal['saved', 'partial', 'none']
bytes: int | None = None
parts: int | None = None
at: datetime | None = None
detail: str | None = None
WorkflowRunSource
class WorkflowRunSource(BaseModel):
"""What a run ran over: `kind` is `"video"`, `"image"`, `"dataset"`, `"export"` or `"stream"`, and a stream's `via` is `"whip"` (video sent to it, such as a browser's camera), `"rtsp"` or `"whep"` (a camera it pulled). Strings, so a kind added later reads as itself."""
kind: str
via: str | None = None
name: str | None = None
input: dict[str, Any] | None = None
WorkflowRunSummary
class WorkflowRunSummary(BaseModel):
"""A run as `client.workflows.list_runs` lists it."""
id: str
status: Literal['queued', 'processing', 'completed', 'error', 'cancelled']
created_at: datetime | None = None
completed_at: datetime | None = None
runtime_seconds: float | None = None
cost_micro_usd: int = 0
cost_settled: bool = False
frames_done: int = 0
frames_total: int | None = None
progress: float = 0.0
artifact_count: int = 0
has_log: bool = False
compute: WorkflowRunCompute = ...
engine_build: EngineBuild | None = None
source: WorkflowRunSource | None = None
stream_session: str | None = None
outputs: WorkflowRunWrites | None = None
live_view: WorkflowRunLiveView | None = None
recording: WorkflowRunRecording | None = None
error: str | None = None
WorkflowRunWrites
class WorkflowRunWrites(BaseModel):
"""What a run writes beside its log, as resolved when it started."""
annotated_video: bool = False
annotations: WorkflowWrittenAnnotations | None = None
passive_capture: WorkflowWrittenPassiveCapture | None = None
event_capture: WorkflowWrittenEventCapture | None = None
webhook: WorkflowWrittenWebhook | None = None
WorkflowTemplate
class WorkflowTemplate(BaseModel):
"""A template from the app's "New workflow" list, with its graph; `client.workflows.create(name, template_key=key)` starts from it."""
key: str
title: str
description: str
graph: dict[str, Any] = {}
WorkflowValidation
class WorkflowValidation(BaseModel):
"""Whether a run of a graph would start: `valid` when no issue is an error, and every issue."""
valid: bool
issues: list[WorkflowIssue] = []
# The issues that stop a run.
@property
def errors(self) -> list[WorkflowIssue]: ...
WorkflowWrittenAnnotations
class WorkflowWrittenAnnotations(BaseModel):
"""Where a run writes annotations, and which frames."""
dataset: str
dataset_name: str = ''
directory: str = '/'
new_folder_each_run: bool = False
folder: str = '/'
only_with_detections: bool = True
min_interval_s: float | None = None
WorkflowWrittenEventCapture
class WorkflowWrittenEventCapture(BaseModel):
"""Where a run writes event captures: its events and the capture interval."""
dataset: str
dataset_name: str = ''
directory: str = '/'
new_folder_each_run: bool = False
folder: str = '/'
events: list[str] = []
min_interval_s: float = 1.0
WorkflowWrittenPassiveCapture
class WorkflowWrittenPassiveCapture(BaseModel):
"""Where a run writes passive captures, and how often."""
dataset: str
dataset_name: str = ''
directory: str = '/'
new_folder_each_run: bool = False
folder: str = '/'
every_s: float = 10.0
WorkflowWrittenWebhook
class WorkflowWrittenWebhook(BaseModel):
"""The webhook endpoint a run sends to, and the events it sends."""
endpoint: str
events: list[str] = []