Skip to content

Commit 569b641

Browse files
[CVAT] Adapt exchange/recording oracles for honeypots (#2720)
* Update exchange oracle * Add wait timeout when importing GT annotations * Extract a base class for task creation * Move gt setup into the base class * Add draft implementation for points task creation * [draft] Update recording oracle * Upgrade cvat-sdk dep * [Exchnage oracle] apply some comments && small fixes * Refactor some code, fix errors * Add quality settings setup * Fix update quality settings * Use inbound bbox circle radius for point validation * Fix linter errors * Fix quality settings update call * Move common function to the base class * Expect point group annotations in points annotation task * Fix response check * Improve formatting in the log message * Use single shape mode for image_points task * Refactor recording oracle updates * [Recording oracle] update deps * Update assignment urls for skeleton tasks * Rename quality parameter * Fix linter error * [Ex oracle] Move gt dataset preparation into separate method for skeletons task * [Ex oracle] update deps * [Ex oracle] Improve handling oracle mode(dev/prod/test) * [Ex oracle] Fix test * [Recording oracle] Apply comments && small fixes && remove unused code * [Exchnage oracle] Pass job start/stop frame from Ex oracle to Rec oracle * Update recording oracle * t * [Exchange oracle] Fix tests * [Exchange oracle] Add migration * Fix test * [Exchange oracle] mark job start/stop frame as not nullable * Fix tests * [Recording oracle] Clean up the code * Update packages/examples/cvat/exchange-oracle/src/handlers/job_creation.py Co-authored-by: Maxim Zhiltsov <[email protected]> * [Recording oracle] Apply comments * [Exchnage oracle] use_bbox_size_for_points -> point_size_base * [Rec oracle] Use MT19937 generator * [Exchange oracle] Move BoxesFromPointsTaskBuilder::_prepare_gt_roi_dataset before _extract_and_upload_rois * [Exchange oracle] Fix checking which files should be uploaded to the ex oracle bucket after escrow is annotated * [Exchange oracle] Update down_revision * fix typo * [Exchange oracle] Include val_size into chunk_size * Fix some errors * Enable empty frame matching * Use the added parameter * [Recording orcale] Fix get_task_quality_report * [Ex oracle] Fix missing segment_size * [Rec oracle] Small fixes * Update packages/examples/cvat/exchange-oracle/src/cvat/api_calls.py * [Exchange oracle] Bump cvat-sdk version * Fix roi GT dataset in boxes_from_points tasks - fixed invalid image ids - removed unnecessary image reading during dataset preparation * Add more clever default for sort_images * Fix linter error, remove gt image data callback * Fix type annotation * Fix quality settings for skeletons_from_boxes * Fix GT datasets for points in skeletons_from_boxes - removed invalid mappings in the class - fixed incorrect gt point preparations - refactored some code * Simplify roi info id * Remove unused field from skeleton roi info * Allow optional joints in skeleton task manifest * Add points task meta * Basic fix for merged dataset annotations Fixes how the merged datasets get annotations for all the task types. Probably, need to change it further to use the original GT, as excluded GT annotations will be missing from the result now. * Basic fix for premature escrow validation requests * Fix incorrect GT preparation in boxes_from_points Some images might have incorrect ids in the generated COCO annotation file. Reindexing is not desirable, so clear the original image ids from roi images instead * Refactor some code * Fix linter problem * Use the original GT for final annotation merging * Fix dataset merging for the points task * Update comment * [Exchange Oracle] Move cvat timeout settings to cvat config, update .env template * [Recording Oracle] Update .env template, add some variables * Update packages/examples/cvat/exchange-oracle/src/core/config.py --------- Co-authored-by: Maxim Zhiltsov <[email protected]>
1 parent 651047c commit 569b641

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2045
-1579
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""job_start_stop_frame
2+
3+
Revision ID: 0a91b6a5f7b6
4+
Revises: 4fc740e8c6ff
5+
Create Date: 2024-11-07 08:15:00.780982
6+
7+
"""
8+
9+
import sqlalchemy as sa
10+
11+
from alembic import op
12+
13+
# revision identifiers, used by Alembic.
14+
revision = "0a91b6a5f7b6"
15+
down_revision = "4fc740e8c6ff"
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade() -> None:
21+
# ### commands auto generated by Alembic - please adjust! ###
22+
op.add_column("jobs", sa.Column("start_frame", sa.Integer(), nullable=False))
23+
op.add_column("jobs", sa.Column("stop_frame", sa.Integer(), nullable=False))
24+
# ### end Alembic commands ###
25+
26+
27+
def downgrade() -> None:
28+
# ### commands auto generated by Alembic - please adjust! ###
29+
op.drop_column("jobs", "stop_frame")
30+
op.drop_column("jobs", "start_frame")
31+
# ### end Alembic commands ###

packages/examples/cvat/exchange-oracle/poetry.lock

Lines changed: 111 additions & 76 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/examples/cvat/exchange-oracle/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ sqlalchemy-utils = "^0.41.1"
1616
alembic = "^1.11.1"
1717
httpx = "^0.24.1"
1818
pytest = "^7.2.2"
19-
cvat-sdk = "2.6.0"
19+
cvat-sdk = "^2.22.0"
2020
sqlalchemy = "^2.0.16"
2121
apscheduler = "^3.10.1"
2222
xmltodict = "^0.13.0"

packages/examples/cvat/exchange-oracle/run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from src.core.config import Config
55

66
if __name__ == "__main__":
7-
is_dev = Config.environment == "development"
7+
is_dev = Config.is_development_mode()
88
Config.validate()
99
register_in_kvstore()
1010

packages/examples/cvat/exchange-oracle/src/.env.template

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ CVAT_ADMIN_USER_ID=
6969
CVAT_INCOMING_WEBHOOKS_URL=
7070
CVAT_WEBHOOK_SECRET=
7171
CVAT_ORG_SLUG=
72+
CVAT_TASK_SEGMENT_SIZE=
73+
CVAT_MAX_JOBS_PER_TASK=
74+
CVAT_TASK_CREATION_CHECK_INTERVAL=
75+
CVAT_MAX_VALIDATION_CHECKS=
76+
CVAT_IOU_THRESHOLD=
77+
CVAT_OKS_SIGMA=
78+
CVAT_EXPORT_TIMEOUT=
79+
CVAT_IMPORT_TIMEOUT=
7280

7381
# Storage Config (S3/GCS)
7482

@@ -84,6 +92,7 @@ STORAGE_USE_SSL=
8492
# Features
8593

8694
ENABLE_CUSTOM_CLOUD_HOST=
95+
REQUEST_LOGGING_ENABLED=
8796

8897
# Core
8998

@@ -105,6 +114,7 @@ DEFAULT_API_PAGE_SIZE=
105114
LOCALHOST_RECORDING_ORACLE_ADDRESS=
106115
LOCALHOST_RECORDING_ORACLE_URL=
107116
LOCALHOST_JOB_LAUNCHER_URL=
117+
LOCALHOST_REPUTATION_ORACLE_ADDRESS=
108118
LOCALHOST_REPUTATION_ORACLE_URL=
109119

110120
# Encryption

packages/examples/cvat/exchange-oracle/src/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,5 @@ async def startup_event():
3232
logger.info("Exchange Oracle is up and running!")
3333

3434

35-
is_test = Config.environment == "test"
36-
if not is_test:
35+
if not Config.is_test_mode():
3736
setup_cron_jobs(app)

packages/examples/cvat/exchange-oracle/src/chain/escrow.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,6 @@ def get_available_webhook_types(
6767
Config.localhost.recording_oracle_address or escrow.recording_oracle
6868
).lower(): OracleWebhookTypes.recording_oracle,
6969
(
70-
Config.localhost.reputation_oracle_url or escrow.reputation_oracle
70+
Config.localhost.reputation_oracle_address or escrow.reputation_oracle
7171
).lower(): OracleWebhookTypes.reputation_oracle,
7272
}

packages/examples/cvat/exchange-oracle/src/core/annotation_meta.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88

99
class JobMeta(BaseModel):
1010
job_id: int
11+
task_id: int
1112
annotation_filename: Path
1213
annotator_wallet_address: str
1314
assignment_id: str
15+
start_frame: int
16+
stop_frame: int
1417

1518

1619
class AnnotationMeta(BaseModel):

packages/examples/cvat/exchange-oracle/src/core/config.py

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import inspect
55
import os
66
from collections.abc import Iterable
7-
from typing import ClassVar
7+
from enum import Enum
8+
from typing import ClassVar, Optional
89

910
from attrs.converters import to_bool
1011
from dotenv import load_dotenv
@@ -104,6 +105,8 @@ class LocalhostConfig(_NetworkConfig):
104105

105106
recording_oracle_address = os.environ.get("LOCALHOST_RECORDING_ORACLE_ADDRESS")
106107
recording_oracle_url = os.environ.get("LOCALHOST_RECORDING_ORACLE_URL")
108+
109+
reputation_oracle_address = os.environ.get("LOCALHOST_REPUTATION_ORACLE_ADDRESS")
107110
reputation_oracle_url = os.environ.get("LOCALHOST_REPUTATION_ORACLE_URL")
108111

109112

@@ -167,14 +170,30 @@ class CronConfig:
167170

168171

169172
class CvatConfig:
173+
# TODO: remove cvat_ prefix
170174
cvat_url = os.environ.get("CVAT_URL", "http://localhost:8080")
171175
cvat_admin = os.environ.get("CVAT_ADMIN", "admin")
172176
cvat_admin_pass = os.environ.get("CVAT_ADMIN_PASS", "admin")
173177
cvat_org_slug = os.environ.get("CVAT_ORG_SLUG", "")
174178

175179
cvat_job_overlap = int(os.environ.get("CVAT_JOB_OVERLAP", 0))
176-
cvat_job_segment_size = int(os.environ.get("CVAT_JOB_SEGMENT_SIZE", 150))
180+
cvat_task_segment_size = int(os.environ.get("CVAT_TASK_SEGMENT_SIZE", 150))
177181
cvat_default_image_quality = int(os.environ.get("CVAT_DEFAULT_IMAGE_QUALITY", 70))
182+
cvat_max_jobs_per_task = int(os.environ.get("CVAT_MAX_JOBS_PER_TASK", 1000))
183+
cvat_task_creation_check_interval = int(os.environ.get("CVAT_TASK_CREATION_CHECK_INTERVAL", 5))
184+
185+
cvat_export_timeout = int(os.environ.get("CVAT_EXPORT_TIMEOUT", 5 * 60))
186+
"Timeout, in seconds, for annotations or dataset export waiting"
187+
188+
cvat_import_timeout = int(os.environ.get("CVAT_IMPORT_TIMEOUT", 60 * 60))
189+
"Timeout, in seconds, for waiting on GT annotations import"
190+
191+
# quality control settings
192+
cvat_max_validation_checks = int(os.environ.get("CVAT_MAX_VALIDATION_CHECKS", 3))
193+
"Maximum number of attempts to run a validation check on a job after completing annotation"
194+
195+
cvat_iou_threshold = float(os.environ.get("CVAT_IOU_THRESHOLD", 0.8))
196+
cvat_oks_sigma = float(os.environ.get("CVAT_OKS_SIGMA", 0.1))
178197

179198
cvat_incoming_webhooks_url = os.environ.get("CVAT_INCOMING_WEBHOOKS_URL")
180199
cvat_webhook_secret = os.environ.get("CVAT_WEBHOOK_SECRET", "thisisasamplesecret")
@@ -220,9 +239,6 @@ class FeaturesConfig:
220239
enable_custom_cloud_host = to_bool(os.environ.get("ENABLE_CUSTOM_CLOUD_HOST", "no"))
221240
"Allows using a custom host in manifest bucket urls"
222241

223-
default_export_timeout = int(os.environ.get("DEFAULT_EXPORT_TIMEOUT", 60))
224-
"Timeout, in seconds, for annotations or dataset export waiting"
225-
226242
request_logging_enabled = to_bool(os.getenv("REQUEST_LOGGING_ENABLED", "0"))
227243
"Allow to log request details for each request"
228244

@@ -282,10 +298,25 @@ def validate(cls) -> None:
282298
raise Exception(" ".join([ex_prefix, str(ex)]))
283299

284300

301+
class Environment(str, Enum):
302+
PRODUCTION = "production"
303+
DEVELOPMENT = "development"
304+
TEST = "test"
305+
306+
@classmethod
307+
def _missing_(cls, value: str) -> Optional["Environment"]:
308+
value = value.lower()
309+
for member in cls:
310+
if member.value == value:
311+
return member
312+
313+
return None
314+
315+
285316
class Config:
286317
debug = to_bool(os.environ.get("DEBUG", "false"))
287318
port = int(os.environ.get("PORT", 8000))
288-
environment = os.environ.get("ENVIRONMENT", "development")
319+
environment = Environment(os.environ.get("ENVIRONMENT", Environment.DEVELOPMENT.value))
289320
workers_amount = int(os.environ.get("WORKERS_AMOUNT", 1))
290321
webhook_max_retries = int(os.environ.get("WEBHOOK_MAX_RETRIES", 5))
291322
webhook_delay_if_failed = int(os.environ.get("WEBHOOK_DELAY_IF_FAILED", 60))
@@ -307,6 +338,21 @@ class Config:
307338
core_config = CoreConfig
308339
encryption_config = EncryptionConfig
309340

341+
@classmethod
342+
def is_development_mode(cls) -> bool:
343+
"""Returns whether the oracle is running in development mode or not"""
344+
return cls.environment == Environment.DEVELOPMENT
345+
346+
@classmethod
347+
def is_test_mode(cls) -> bool:
348+
"""Returns whether the oracle is running in testing mode or not"""
349+
return cls.environment == Environment.TEST
350+
351+
@classmethod
352+
def is_production_mode(cls) -> bool:
353+
"""Returns whether the oracle is running in production mode or not"""
354+
return cls.environment == Environment.PRODUCTION
355+
310356
@classmethod
311357
def validate(cls) -> None:
312358
for attr_or_method in cls.__dict__:

packages/examples/cvat/exchange-oracle/src/core/manifest.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,15 @@ def validate_type(cls, values: dict[str, Any]) -> dict[str, Any]:
105105
existing_names.add(node_name.lower())
106106

107107
nodes_count = len(values["nodes"])
108-
joints = values["joints"]
109-
for joint_idx, joint in enumerate(joints):
110-
for v in joint:
111-
if not (0 <= v < nodes_count):
112-
raise ValueError(
113-
f"Skeleton '{skeleton_name}' joint #{joint_idx}: invalid value. "
114-
f"Expected a number in the range [0; {nodes_count - 1}]"
115-
)
108+
joints = values.get("joints")
109+
if joints is not None:
110+
for joint_idx, joint in enumerate(joints):
111+
for v in joint:
112+
if not (0 <= v < nodes_count):
113+
raise ValueError(
114+
f"Skeleton '{skeleton_name}' joint #{joint_idx}: invalid value. "
115+
f"Expected a number in the range [0; {nodes_count - 1}]"
116+
)
116117

117118
return values
118119

0 commit comments

Comments
 (0)