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 scorestop_n
(int): Defines N whenreturn_top_n
is requested. Defaults to 1return_only_matches
(bool): Return only the inference elements that match the label and score filters, rather than all elements from matching inferencesreturn_only_null
(bool): Return only inferences with no detections. Cannot be combined with other label or score filtersreturn_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.