Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,7 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

.DS_Store

.env*
13 changes: 13 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"python.testing.unittestArgs": [
"-v",
"-s",
"./tests",
"-p",
"test_*.py"
],
"python.testing.unittestEnabled": true,
"python.analysis.enablePytestSupport": false,
"python.testing.pytestEnabled": false,
"python.analysis.typeCheckingMode": "strict"
}
13 changes: 13 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: rapi-api
channels:
- defaults
dependencies:
- python=3.12
- ipykernel
- requests
- pandas
- matplotlib
- python-dotenv
- pyjwt
- sphinx
prefix: /Users/mari/miniconda3/envs/rapi-api
48 changes: 48 additions & 0 deletions examples/classify_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import dotenv
import os
dotenv.load_dotenv() # type: ignore

from rapidata.rapidata_client import RapidataClient
from rapidata.rapidata_client.workflow import FeatureFlags
from rapidata.rapidata_client.workflow import ClassifyWorkflow
from rapidata.rapidata_client.workflow.referee import NaiveReferee

CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
ENDPOINT = os.getenv("ENDPOINT")

if not CLIENT_ID:
raise Exception("CLIENT_ID not found in environment variables")

if not CLIENT_SECRET:
raise Exception("CLIENT_SECRET not found in environment variables")

if not ENDPOINT:
raise Exception("ENDPOINT not found in environment variables")

rapi = RapidataClient(
client_id=CLIENT_ID, client_secret=CLIENT_SECRET, endpoint=ENDPOINT
)

# Configure order
order = (
rapi.new_order(
name="Example Classify Order",
)
.workflow(
ClassifyWorkflow(
question="Who should be president?",
categories=["Kamala Harris", "Donald Trump"],
)
.referee(NaiveReferee(required_guesses=15))
.feature_flags(FeatureFlags().alert_on_fast_response(3))
)
.create()
)

# Add data
order.dataset.add_images_from_paths(["examples/data/kamala_trump.jpg"])

# Let's go!
order.submit()
# order.approve() admin only: if it doesn't auto approve and you want to manually approve
Binary file added examples/data/kamala.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/data/kamala_trump.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/data/trump.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions examples/free_text_input_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import dotenv
import os
dotenv.load_dotenv() # type: ignore

from rapidata.rapidata_client import RapidataClient
from rapidata.rapidata_client.workflow import FeatureFlags
from rapidata.rapidata_client.workflow import FreeTextWorkflow
from rapidata.rapidata_client.workflow.country_codes import CountryCodes

CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
ENDPOINT = os.getenv("ENDPOINT")

if not CLIENT_ID:
raise Exception("CLIENT_ID not found in environment variables")

if not CLIENT_SECRET:
raise Exception("CLIENT_SECRET not found in environment variables")

if not ENDPOINT:
raise Exception("ENDPOINT not found in environment variables")

rapi = RapidataClient(
client_id=CLIENT_ID, client_secret=CLIENT_SECRET, endpoint=ENDPOINT
)

order = rapi.new_order(
name="Example Video Free Text Order",
).workflow(
FreeTextWorkflow(
question="Describe the movement in this video!",
).feature_flags(
FeatureFlags().free_text_minimum_characters(15).alert_on_fast_response(5)
).target_country_codes(CountryCodes.ENGLISH_SPEAKING)
).create()

order.dataset.add_videos_from_paths([""]) # TODO: insert video path
order.submit()
38 changes: 38 additions & 0 deletions examples/ranking_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import dotenv
import os
dotenv.load_dotenv() # type: ignore

from rapidata.rapidata_client import RapidataClient
from rapidata.rapidata_client.workflow import CompareWorkflow

CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
ENDPOINT = os.getenv("ENDPOINT")

if not CLIENT_ID:
raise Exception("CLIENT_ID not found in environment variables")

if not CLIENT_SECRET:
raise Exception("CLIENT_SECRET not found in environment variables")

if not ENDPOINT:
raise Exception("ENDPOINT not found in environment variables")

rapi = RapidataClient(
client_id=CLIENT_ID, client_secret=CLIENT_SECRET, endpoint=ENDPOINT
)

order = rapi.new_order(
name="Example Compare Order",
).workflow(
CompareWorkflow(
criteria="Who should be president?",
)
.matches_until_completed(5)
.match_size(2)
).create()

order.dataset.add_images_from_paths(["examples/data/kamala.jpg", "examples/data/trump.jpg"])

order.submit()
# order.approve()
Empty file added rapidata/__init__.py
Empty file.
1 change: 1 addition & 0 deletions rapidata/rapidata_client/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .rapidata_client import RapidataClient as RapidataClient
Empty file.
Empty file.
26 changes: 26 additions & 0 deletions rapidata/rapidata_client/order/dataset/rapidata_dataset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import os
from rapidata.service import LocalFileService
from rapidata.service import RapidataService


class RapidataDataset:

def __init__(self, dataset_id: str, rapidata_service: RapidataService):
self.dataset_id = dataset_id
self.rapidata_service = rapidata_service
self.local_file_service = LocalFileService()

def add_texts(self, texts: list[str]):
self.rapidata_service.dataset.upload_text_sources(self.dataset_id, texts)

def add_images_from_paths(self, image_paths: list[str]):
image_names = [os.path.basename(image_path) for image_path in image_paths]
images = self.local_file_service.load_images(image_paths)

self.rapidata_service.dataset.upload_images(self.dataset_id, images, image_names)

def add_videos_from_paths(self, video_paths: list[str]):
video_names = [os.path.basename(video_path) for video_path in video_paths]
videos = self.local_file_service.load_videos(video_paths)

self.rapidata_service.dataset.upload_videos(self.dataset_id, videos, video_names)
71 changes: 71 additions & 0 deletions rapidata/rapidata_client/order/rapidata_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from rapidata.rapidata_client.order.dataset.rapidata_dataset import RapidataDataset
from rapidata.rapidata_client.workflow import Workflow
from rapidata.service import RapidataService


class RapidataOrder:
"""
Represents a Rapidata order.

:param name: The name of the order.
:type name: str
:param workflow: The workflow associated with the order.
:type workflow: Workflow
:param rapidata_service: The Rapidata service used to create and manage the order.
:type rapidata_service: RapidataService
"""

def __init__(
self, name: str, workflow: Workflow, rapidata_service: RapidataService
):
self.name = name
self.workflow = workflow
self.rapidata_service = rapidata_service
self.order_id = None
self._dataset = None

def create(self):
"""
Creates the order using the provided name and workflow.

:return: The created RapidataOrder instance.
:rtype: RapidataOrder
"""
self.order_id, dataset_id = self.rapidata_service.order.create_order(self.name, self.workflow.to_dict())
self._dataset = RapidataDataset(dataset_id, self.rapidata_service)
return self

def submit(self):
"""
Submits the order for processing.

:raises ValueError: If the order has not been created.
"""
if self.order_id is None:
raise ValueError("You must create the order before submitting it.")

self.rapidata_service.order.submit(self.order_id)

def approve(self):
"""
Approves the order for execution.

:raises ValueError: If the order has not been created.
"""
if self.order_id is None:
raise ValueError("You must create the order before approving it.")

self.rapidata_service.order.approve(self.order_id)

@property
def dataset(self):
"""
The dataset associated with the order.

:raises ValueError: If the order has not been submitted.
:return: The RapidataDataset instance.
:rtype: RapidataDataset
"""
if self._dataset is None:
raise ValueError("You must submit the order before accessing the dataset.")
return self._dataset
52 changes: 52 additions & 0 deletions rapidata/rapidata_client/order/rapidata_order_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from rapidata.rapidata_client.workflow import Workflow
from rapidata.rapidata_client.order.rapidata_order import RapidataOrder
from rapidata.service import RapidataService


class RapidataOrderBuilder:
"""
Builder object for creating Rapidata orders.

Use the fluent interface to set the desired configuration. Add a workflow to the order using `.workflow()` and finally call `.create()` to create the order.

:param rapidata_service: The RapidataService instance.
:type rapidata_service: RapidataService
:param name: The name of the order.
:type name: str
"""

def __init__(
self,
rapidata_service: RapidataService,
name: str,
):
self._name = name
self._rapidata_service = rapidata_service
self._workflow: Workflow | None = None

def create(self) -> RapidataOrder:
"""
Create a RapidataOrder instance based on the configured settings.

:return: The created RapidataOrder instance.
:rtype: RapidataOrder
:raises ValueError: If no workflow is provided.
"""
if self._workflow is None:
raise ValueError("You must provide a blueprint to create an order.")

return RapidataOrder(
name=self._name, workflow=self._workflow, rapidata_service=self._rapidata_service
).create()

def workflow(self, workflow: Workflow):
"""
Set the workflow for the order.

:param workflow: The workflow to be set.
:type workflow: Workflow
:return: The updated RapidataOrderBuilder instance.
:rtype: RapidataOrderBuilder
"""
self._workflow = workflow
return self
34 changes: 34 additions & 0 deletions rapidata/rapidata_client/rapidata_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from rapidata.rapidata_client.order.rapidata_order_builder import RapidataOrderBuilder
from rapidata.service import RapidataService


class RapidataClient:
"""
A client for interacting with the Rapidata API.
"""

def __init__(
self,
client_id: str,
client_secret: str,
endpoint: str = "https://api.rapidata.ai",
):
"""
Initialize the RapidataClient.

:param client_id: The client ID for authentication.
:param client_secret: The client secret for authentication.
:param endpoint: The API endpoint URL. Defaults to "https://api.rapidata.ai".
"""
self._rapidata_service = RapidataService(
client_id=client_id, client_secret=client_secret, endpoint=endpoint
)

def new_order(self, name: str) -> RapidataOrderBuilder:
"""
Create a new order using a RapidataOrderBuilder instance.

:param name: The name of the order.
:return: A RapidataOrderBuilder instance.
"""
return RapidataOrderBuilder(rapidata_service=self._rapidata_service, name=name)
6 changes: 6 additions & 0 deletions rapidata/rapidata_client/workflow/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .base_workflow import Workflow as Workflow
from .classify_workflow import ClassifyWorkflow as ClassifyWorkflow
from .compare_workflow import CompareWorkflow as CompareWorkflow
from .free_text_workflow import FreeTextWorkflow as FreeTextWorkflow
from .feature_flags import FeatureFlags as FeatureFlags
from .country_codes import CountryCodes as CountryCodes
Loading