Skip to main content

Using the Chariot SDK

The Chariot SDK provides programmatic access to query and analyze Inference Store data. It's ideal for complex filtering, automated workflows, and custom analysis that goes beyond what the UI offers.

Basic Querying

Getting All Inferences

from chariot.inference_store import models, inference

# Create a basic filter request
inference_filter = models.NewGetInferencesRequest()
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Pagination

Pagination is best practice to avoid large queries and excessive data transfer at a given time.

from chariot.inference_store import models, inference

# Create pagination settings
pagination = models.Pagination(
limit=5,
offset=5,
sort=models.PaginationSortField.CREATED_AT,
direction=models.PaginationSortDirection.ASCENDING,
)

# Create filter with pagination
inference_filter = models.NewGetInferencesRequest(pagination=pagination)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Counting Inferences

Get the total count of inferences matching your filter:

from chariot.inference_store import models, inference

inference_filter = models.NewGetInferencesRequest()
count = inference.count_inferences(model_id=model_id, request_body=inference_filter)
print(f"Total inferences: {count}")

Get Single Inference

Retrieve details about a specific inference:

from chariot.inference_store import inference

# Get inference with presigned URL for data download
single_inference = inference.get_inference(
model_id=model_id,
inference_id=inference_id,
presign=True
)

if single_inference:
print(f"Inference action: {single_inference.inference_action}")
print(f"Data hash: {single_inference.data_hash}")
print(f"Metadata count: {len(single_inference.metadata) if single_inference.metadata else 0}")
if single_inference.presigned_url:
print(f"Data download URL: {single_inference.presigned_url}")

Metadata Filtering

Single Metadata Filter

Filter by a single metadata constraint:

from chariot.inference_store import models, inference

# Filter for inferences where organization != "striveworks"
metadata_filter = [
models.MetadataFilter(
key="organization",
type=models.MetadataFilterType.STRING,
operator=models.MetadataFilterOperator.NOT_EQUAL,
value="striveworks"
)
]

base_filter = models.BaseInferenceFilter(metadata_filter=metadata_filter)
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Multiple Metadata Filters

Filter by multiple metadata constraints (AND logic):

from chariot.inference_store import models, inference

metadata_filter = [
models.MetadataFilter(
key="organization",
type=models.MetadataFilterType.STRING,
operator=models.MetadataFilterOperator.NOT_EQUAL,
value="competitor"
),
models.MetadataFilter(
key="frame_number",
type=models.MetadataFilterType.INT,
operator=models.MetadataFilterOperator.LESS,
value="1000"
),
]

base_filter = models.BaseInferenceFilter(metadata_filter=metadata_filter)
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

JSON Metadata Filtering

Filter by nested JSON metadata using dot notation:

from chariot.inference_store import models, inference

# For JSON metadata like: {"camera_settings": {"iso": 400, "shutter": "1/60"}}
# Use dot notation to filter on nested values
metadata_filter = [
models.MetadataFilter(
key="camera_settings.iso", # Use dot notation for nested JSON
type=models.MetadataFilterType.JSON_INT,
operator=models.MetadataFilterOperator.GREATER_OR_EQUAL,
value="200"
)
]

base_filter = models.BaseInferenceFilter(metadata_filter=metadata_filter)
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Using the IN Operator

Filter for inferences where metadata values are in a specific set:

from chariot.inference_store import models, inference

# Filter for specific camera IDs
camera_ids = ["camera-1", "camera-2", "camera-3"]
formatted_values = models.MetadataFilter.form_values_for_in_operator(
values_type=models.MetadataFilterType.STRING,
values=camera_ids
)

metadata_filter = [
models.MetadataFilter(
key="camera_id",
type=models.MetadataFilterType.STRING,
operator=models.MetadataFilterOperator.IN,
value=formatted_values
)
]

base_filter = models.BaseInferenceFilter(metadata_filter=metadata_filter)
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Metadata Statistics and Distribution

Querying for statistics of metadata in the Inference Store can help you better understand your production data:

from chariot.inference_store import models, metadata

# Get overall metadata key-type counts
key_type_counts = metadata.get_metadata_key_type_counts(model_id=model_id)
print("Available metadata keys:")
for key, type_counts in key_type_counts.counts.items():
for metadata_type, count in type_counts.items():
print(f" {key} ({metadata_type}): {count} inferences")

# Analyze specific metadata distributions
stats_request = models.NewGetMetadataStatisticsRequest(
key="confidence_score",
type=models.MetadataStatisticsType.FLOAT,
distribution_bin_count=10
)
stats = metadata.get_metadata_statistics(model_id=model_id, request_body=stats_request)
print("Confidence Score Statistics:")
print(f"Count: {stats.count}")
print(f"Min: {stats.min}, Max: {stats.max}")
print("Distribution:")
for bin_range, count in stats.distribution.items():
print(f" {bin_range}: {count}")

Time-Based Filtering

Get inferences within a time window:

from chariot.inference_store import models, inference

time_window_filter = models.TimeWindowFilter(
start="2024-01-01T00:00:00Z",
end="2025-01-01T00:00:00Z"
)

base_filter = models.BaseInferenceFilter(time_window_filter=time_window_filter)
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Location-Based Filtering

Circular Area

Get inferences within a circular area:

from chariot.inference_store import models, inference

# Location filtering requires latitude/longitude in the inference metadata:
# {"key": "latitude", "type": "float", "value": "<value>"},
# {"key": "longitude", "type": "float", "value": "<value>"}

lat, lon = 30.266666, -97.733330

location_filter = models.GeolocationFilter(
gps_coordinates_circle=models.GeoCircle(
center=models.GeoPoint(latitude=lat, longitude=lon),
radius=1000 # radius in meters
)
)

base_filter = models.BaseInferenceFilter(location_filter=location_filter)
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Rectangular Area

Get inferences within a rectangular area:

from chariot.inference_store import models, inference

lat, lon = 30.266666, -97.733330

location_filter = models.GeolocationFilter(
gps_coordinates_rectangle=models.GeoRectangle(
p1=models.GeoPoint(latitude=lat - 0.01, longitude=lon - 0.01),
p2=models.GeoPoint(latitude=lat + 0.01, longitude=lon + 0.01),
)
)

base_filter = models.BaseInferenceFilter(location_filter=location_filter)
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Inference Content Filtering

Use the DeconstructedInferenceFilter to filter based on inference contents, specifically confidence scores and labels.

By Labels and Confidence Scores

Filter inferences by their detection results:

from chariot.inference_store import models, inference

# Filter for inferences containing specific labels with minimum confidence
deconstructed_filter = models.DeconstructedInferenceFilter(
labels=["car", "truck", "bus"],
minimum_score=0.8,
maximum_score=1.0
)

base_filter = models.BaseInferenceFilter(deconstructed_inference_filter=deconstructed_filter)
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Advanced Result Filtering Options

The DeconstructedInferenceFilter supports additional options to control how results are returned:

  • return_top_n (bool): Return only the top N elements within an inference with the highest confidence scores
  • top_n (int): Defines N when return_top_n is requested. Defaults to 1
  • return_only_matches (bool): Return only the inference elements that match the label and score filters, rather than all elements from matching inferences
  • return_only_null (bool): Return only inferences with no detections. Cannot be combined with other label or score filters
  • return_any_matches (bool): Return only inferences with detections. Cannot be combined with other label or score filters

Filtering by Data Properties

Data Source and Data Hash are two first-class fields that provide additional information about the data used in inference requests. Both fields can be used for filtering.

By Data Source

Get inferences with a particular data source:

from chariot.inference_store import models, inference


base_filter = models.BaseInferenceFilter(data_source_filter="camera-1")
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

By Data Hash

Each inference stored gets a hash computed from the input data. This is useful for finding duplicates or doing reverse lookups:

from chariot.inference_store import models, inference, metadata

# Get data hash from binary data
with open("image.jpg", "rb") as f:
data = f.read()
data_hash = metadata.get_data_hash(data)

base_filter = models.BaseInferenceFilter(data_hash_filter=data_hash)
inference_filter = models.NewGetInferencesRequest(filters=base_filter)
inferences = inference.filter_inferences(model_id=model_id, request_body=inference_filter)

Performance Tips

  • Use pagination for large result sets: Implement pagination to prevent memory exhaustion and improve response times. Loading thousands of inferences at once can cause memory issues and slow network transfers. Pagination keeps memory usage relatively constant and allows for progressive data processing by processing results in manageable batches.
  • Filters before retrieving data: Apply filtering within the query request rather than filtering results after retrieval. Database-level filtering is significantly faster than downloading all data and filtering in application code. It reduces network traffic and leverages database indexing for optimal performance.
  • Use presigned URLs sparingly: Only set presign=True when you actually need to download the inference input data. Generating presigned URLs adds computational overhead on the server and increases response payload size. Reserve this option for when you plan to download the actual data files.
  • Use time windows to limit scope: Include time boundaries in your queries to reduce the search space, especially for models with a large number of inferences.
  • Count before fetching large results: Use count_inferences() to understand result size before fetching data, especially for exploratory queries. Knowing result size helps you choose appropriate pagination settings and avoid accidentally triggering very large downloads that could impact performance or exceed memory limits.