diff --git a/docs/robots.txt b/docs/robots.txt new file mode 100644 index 0000000..162c3e1 --- /dev/null +++ b/docs/robots.txt @@ -0,0 +1,42 @@ +User-agent: * +Disallow: /tutorials/pruning-sparsity/ +Disallow: /tutorials/nvidia-jetson/ +Disallow: /tutorials/training-tips-best-results/ +Disallow: /tutorials/hyperparameter-evolution/ +Disallow: /callbacks/ +Disallow: /config/ +Disallow: /tutorials/transfer-learning-froze-layers/ +Disallow: /environments/Docker-Quickstart/ +Disallow: /tutorials/model-ensembling/ +Disallow: /tutorials/test-time-augmentation/ +Disallow: /quick-start/ +Disallow: /FAQ/augmentation/ +Disallow: /environments/AWS-Quickstart/ +Disallow: /tutorials/pytorch-hub/ +Disallow: /tutorials/torchscript-onnx-coreml-export/ +Disallow: /tasks/tracking/ +Disallow: /cfg/ +Disallow: /tasks/detection/ +Disallow: /tutorials/train-custom-datasets/ +Disallow: /cli/ +Disallow: /tasks/classification/ +Disallow: /tutorials/multi-gpu-training/ +Disallow: /engine/ +Disallow: /tasks/segmentation/ +Disallow: /predict/ +Disallow: /python/ +Disallow: /python +Disallow: /environments/GCP-Quickstart/ +Disallow: /cli +Disallow: /tutorials/comet-logging/ +Disallow: /cfg +Disallow: /tutorials/architecture-summary/ +Disallow: /tutorials/clearml-logging/ +Disallow: /sdk/ +Disallow: /tutorials/roboflow/ +Disallow: /tutorials/training-tips-best-results +Disallow: /package-framework/mock_detector/ +Disallow: /package-framework/ +Disallow: /tutorials/weights-and-biasis-logging/ +Disallow: /tutorials/pruning-sparsity +Disallow: /tutorials/train-custom-datasets diff --git a/mkdocs.yml b/mkdocs.yml index 15449ec..a524c85 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -88,6 +88,9 @@ extra: extra_css: - stylesheets/style.css +extra_files: + - robots.txt + markdown_extensions: # Div text decorators - admonition @@ -123,22 +126,23 @@ plugins: # Primary navigation nav: - - Home: index.md - - Quickstart: quickstart.md - - Modes: - - modes/index.md - - Train: modes/train.md - - Val: modes/val.md - - Predict: modes/predict.md - - Export: modes/export.md - - Track: modes/track.md - - Benchmark: modes/benchmark.md - - Tasks: - - tasks/index.md - - Detect: tasks/detect.md - - Segment: tasks/segment.md - - Classify: tasks/classify.md - - Pose: tasks/pose.md + - Home: + - index.md + - Quickstart: quickstart.md + - Modes: + - modes/index.md + - Train: modes/train.md + - Val: modes/val.md + - Predict: modes/predict.md + - Export: modes/export.md + - Track: modes/track.md + - Benchmark: modes/benchmark.md + - Tasks: + - tasks/index.md + - Detect: tasks/detect.md + - Segment: tasks/segment.md + - Classify: tasks/classify.md + - Pose: tasks/pose.md - Usage: - CLI: usage/cli.md - Python: usage/python.md diff --git a/ultralytics/__init__.py b/ultralytics/__init__.py index df036d9..2278f09 100644 --- a/ultralytics/__init__.py +++ b/ultralytics/__init__.py @@ -1,6 +1,6 @@ # Ultralytics YOLO 🚀, AGPL-3.0 license -__version__ = '8.0.84' +__version__ = '8.0.85' from ultralytics.hub import start from ultralytics.yolo.engine.model import YOLO diff --git a/ultralytics/hub/utils.py b/ultralytics/hub/utils.py index 61d252c..c86060a 100644 --- a/ultralytics/hub/utils.py +++ b/ultralytics/hub/utils.py @@ -6,7 +6,6 @@ import sys import threading import time from pathlib import Path -from random import random import requests from tqdm import tqdm @@ -114,7 +113,7 @@ def smart_request(method, url, retry=3, timeout=30, thread=True, code=-1, verbos if (time.time() - t0) > timeout: break r = requests_with_progress(func_method, func_url, **func_kwargs) # i.e. get(url, data, json, files) - if r.status_code == 200: + if r.status_code < 300: # return codes in the 2xx range are generally considered "good" or "successful" break try: m = r.json().get('message', 'No JSON message.') @@ -142,66 +141,72 @@ def smart_request(method, url, retry=3, timeout=30, thread=True, code=-1, verbos return func(*args, **kwargs) -class Traces: +class Events: + """ + A class for collecting anonymous event analytics. Event analytics are enabled when sync=True in settings and + disabled when sync=False. Run 'yolo settings' to see and update settings YAML file. + + Attributes: + url (str): The GA4 Measurement Protocol URL. + rate_limit (float): The rate limit in seconds for sending events. + metadata (dict): A dictionary containing metadata about the environment. + enabled (bool): A flag to enable or disable Events based on certain conditions. + """ + + url = 'https://www.google-analytics.com/mp/collect?measurement_id=G-X8NCJYTQXM&api_secret=QLQrATrNSwGRFRLE-cbHJw' def __init__(self): """ - Initialize Traces for error tracking and reporting if tests are not currently running. - Sets the rate limit, timer, and metadata attributes, and determines whether Traces are enabled. + Initializes the Events object with default values for events, rate_limit, and metadata. """ - self.rate_limit = 60.0 # rate limit (seconds) + self.events = [] # events list + self.rate_limit = 10.0 # rate limit (seconds) self.t = 0.0 # rate limit timer (seconds) self.metadata = { - 'sys_argv_name': Path(sys.argv[0]).name, + 'cli': Path(sys.argv[0]).name == 'yolo', 'install': 'git' if is_git_dir() else 'pip' if is_pip_package() else 'other', 'python': platform.python_version(), - 'release': __version__, - 'environment': ENVIRONMENT} + 'version': __version__, + 'env': ENVIRONMENT} self.enabled = \ SETTINGS['sync'] and \ RANK in (-1, 0) and \ not TESTS_RUNNING and \ ONLINE and \ (is_pip_package() or get_git_origin_url() == 'https://github.com/ultralytics/ultralytics.git') - self._reset_usage() - def __call__(self, cfg, all_keys=False, traces_sample_rate=1.0): + def __call__(self, cfg): """ - Sync traces data if enabled in the global settings. + Attempts to add a new event to the events list and send events if the rate limit is reached. Args: - cfg (IterableSimpleNamespace): Configuration for the task and mode. - all_keys (bool): Sync all items, not just non-default values. - traces_sample_rate (float): Fraction of traces captured from 0.0 to 1.0. + cfg: The configuration object containing mode and task information. """ - - # Increment usage - self.usage['modes'][cfg.mode] = self.usage['modes'].get(cfg.mode, 0) + 1 - self.usage['tasks'][cfg.task] = self.usage['tasks'].get(cfg.task, 0) + 1 - - t = time.time() # current time - if not self.enabled or random() > traces_sample_rate: - # Traces disabled or not randomly selected, do nothing - return - elif (t - self.t) < self.rate_limit: - # Time is under rate limiter, do nothing + if not self.enabled: + # Events disabled, do nothing return - else: - # Time is over rate limiter, send trace now - trace = {'uuid': SETTINGS['uuid'], 'usage': self.usage.copy(), 'metadata': self.metadata} - # Send a request to the HUB API to sync analytics - smart_request('post', f'{HUB_API_ROOT}/v1/usage/anonymous', json=trace, code=3, retry=0, verbose=False) + # Attempt to add to events + if len(self.events) < 25: # Events list limited to 25 events (drop any events past this) + params = {**self.metadata, **{'task': cfg.task}} + if cfg.mode == 'export': + params['format'] = cfg.format + self.events.append({'name': cfg.mode, 'params': params}) + + # Check rate limit + t = time.time() + if (t - self.t) < self.rate_limit: + # Time is under rate limiter, wait to send + return - # Reset usage and rate limit timer - self._reset_usage() - self.t = t + # Time is over rate limiter, send now + data = {'client_id': SETTINGS['uuid'], 'events': self.events} # SHA-256 anonymized UUID hash and events list + smart_request('post', self.url, json=data, retry=0, code=3) # equivalent to requests.post(self.url, json=data) - def _reset_usage(self): - """Reset the usage dictionary by initializing keys for each task and mode with a value of 0.""" - from ultralytics.yolo.cfg import MODES, TASKS - self.usage = {'tasks': {k: 0 for k in TASKS}, 'modes': {k: 0 for k in MODES}} + # Reset events and rate limit timer + self.events = [] + self.t = t # Run below code on hub/utils init ------------------------------------------------------------------------------------- -traces = Traces() +events = Events() diff --git a/ultralytics/yolo/utils/__init__.py b/ultralytics/yolo/utils/__init__.py index 92f4646..620ddb9 100644 --- a/ultralytics/yolo/utils/__init__.py +++ b/ultralytics/yolo/utils/__init__.py @@ -670,7 +670,7 @@ def get_settings(file=SETTINGS_YAML, version='0.0.3'): 'datasets_dir': str(datasets_root / 'datasets'), # default datasets directory. 'weights_dir': str(root / 'weights'), # default weights directory. 'runs_dir': str(root / 'runs'), # default runs directory. - 'uuid': hashlib.sha256(str(uuid.getnode()).encode()).hexdigest(), # anonymized uuid hash + 'uuid': hashlib.sha256(str(uuid.getnode()).encode()).hexdigest(), # SHA-256 anonymized UUID hash 'sync': True, # sync analytics to help with YOLO development 'api_key': '', # Ultralytics HUB API key (https://hub.ultralytics.com/) 'settings_version': version} # Ultralytics settings version diff --git a/ultralytics/yolo/utils/callbacks/base.py b/ultralytics/yolo/utils/callbacks/base.py index 94da2b2..638f6af 100644 --- a/ultralytics/yolo/utils/callbacks/base.py +++ b/ultralytics/yolo/utils/callbacks/base.py @@ -196,16 +196,16 @@ def add_integration_callbacks(instance): instance (Trainer, Predictor, Validator, Exporter): An object with a 'callbacks' attribute that is a dictionary of callback lists. """ - from .clearml import callbacks as clearml_callbacks - from .comet import callbacks as comet_callbacks - from .hub import callbacks as hub_callbacks - from .mlflow import callbacks as mf_callbacks - from .neptune import callbacks as neptune_callbacks - from .raytune import callbacks as tune_callbacks - from .tensorboard import callbacks as tb_callbacks - from .wb import callbacks as wb_callbacks - - for x in clearml_callbacks, comet_callbacks, hub_callbacks, tb_callbacks, mf_callbacks, tune_callbacks, wb_callbacks, neptune_callbacks: + from .clearml import callbacks as clearml_cb + from .comet import callbacks as comet_cb + from .hub import callbacks as hub_cb + from .mlflow import callbacks as mlflow_cb + from .neptune import callbacks as neptune_cb + from .raytune import callbacks as tune_cb + from .tensorboard import callbacks as tensorboard_cb + from .wb import callbacks as wb_cb + + for x in clearml_cb, comet_cb, hub_cb, mlflow_cb, neptune_cb, tune_cb, tensorboard_cb, wb_cb: for k, v in x.items(): if v not in instance.callbacks[k]: # prevent duplicate callbacks addition instance.callbacks[k].append(v) # callback[name].append(func) diff --git a/ultralytics/yolo/utils/callbacks/hub.py b/ultralytics/yolo/utils/callbacks/hub.py index f467dae..3617a5a 100644 --- a/ultralytics/yolo/utils/callbacks/hub.py +++ b/ultralytics/yolo/utils/callbacks/hub.py @@ -3,7 +3,7 @@ import json from time import time -from ultralytics.hub.utils import PREFIX, traces +from ultralytics.hub.utils import PREFIX, events from ultralytics.yolo.utils import LOGGER from ultralytics.yolo.utils.torch_utils import get_flops, get_num_params @@ -61,23 +61,23 @@ def on_train_end(trainer): def on_train_start(trainer): - """Run traces on train start.""" - traces(trainer.args, traces_sample_rate=1.0) + """Run events on train start.""" + events(trainer.args) def on_val_start(validator): - """Runs traces on validation start.""" - traces(validator.args, traces_sample_rate=1.0) + """Runs events on validation start.""" + events(validator.args) def on_predict_start(predictor): - """Run traces on predict start.""" - traces(predictor.args, traces_sample_rate=1.0) + """Run events on predict start.""" + events(predictor.args) def on_export_start(exporter): - """Run traces on export start.""" - traces(exporter.args, traces_sample_rate=1.0) + """Run events on export start.""" + events(exporter.args) callbacks = { diff --git a/ultralytics/yolo/utils/checks.py b/ultralytics/yolo/utils/checks.py index 23738ff..f34f7db 100644 --- a/ultralytics/yolo/utils/checks.py +++ b/ultralytics/yolo/utils/checks.py @@ -128,10 +128,11 @@ def check_latest_pypi_version(package_name='ultralytics'): Returns: (str): The latest version of the package. """ - requests.packages.urllib3.disable_warnings() # Disable the InsecureRequestWarning - response = requests.get(f'https://pypi.org/pypi/{package_name}/json', verify=False) - if response.status_code == 200: - return response.json()['info']['version'] + with contextlib.suppress(Exception): + requests.packages.urllib3.disable_warnings() # Disable the InsecureRequestWarning + response = requests.get(f'https://pypi.org/pypi/{package_name}/json', timeout=3) + if response.status_code == 200: + return response.json()['info']['version'] return None