spec - Infernet ML
Description: Infernet ML Documentation

Skip to content

# Module: `spec`

## `CPUCore`

Bases: `BaseModel`

Attributes:

Name | Type | Description
--- | --- | ---
`id` | `int` | The id of the core, e.g. 0
`frequency` | `float` | The frequency of the core
`max_frequency` | `float` | The maximum frequency of the core
`min_frequency` | `float` | The minimum frequency of the core

Source code in `src/infernet_ml/utils/spec.py`

    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    class CPUCore(BaseModel):
        """
        CPUCore: Class representation for the CPU core information

        Attributes:
            id (int): The id of the core, e.g. 0
            frequency (float): The frequency of the core
            max_frequency (float): The maximum frequency of the core
            min_frequency (float): The minimum frequency of the core
        """

        id: int
        frequency: float
        max_frequency: Optional[float] = None
        min_frequency: Optional[float] = None

## `CPUInfo`

Bases: `BaseModel`

Attributes:

Name | Type | Description
--- | --- | ---
`model` | `str` | The model of the CPU, e.g. Intel(R) Core(TM) i7-7700HQ CPU
`architecture` | `str` | The architecture of the CPU, e.g. x86_64
`byte_order` | `str` | The byte order of the CPU, e.g. Little Endian
`vendor_id` | `str` | The vendor id of the CPU, e.g. GenuineIntel
`num_cores` | `int` | The number of cores in the CPU
`cores` | `List[CPUCore]` | The list of cores in the CPU

Source code in `src/infernet_ml/utils/spec.py`

    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    class CPUInfo(BaseModel):
        """
        CPUInfo: Class representation for the CPU information

        Attributes:
            model (str): The model of the CPU, e.g. Intel(R) Core(TM) i7-7700HQ CPU
            architecture (str): The architecture of the CPU, e.g. x86_64
            byte_order (str): The byte order of the CPU, e.g. Little Endian
            vendor_id (str): The vendor id of the CPU, e.g. GenuineIntel
            num_cores (int): The number of cores in the CPU
            cores (List[CPUCore]): The list of cores in the CPU
        """

        model: str
        architecture: str
        byte_order: str
        vendor_id: str
        num_cores: int

        cores: List[CPUCore]

        @classmethod
        def read_from_linux(cls) -> CPUInfo:
            """
            Reads the CPU information from a Linux system

            Returns:
                CPUInfo: The CPU information
            """
            os.system("lscpu -J > /tmp/lscpu.json")
            model, num_cores, vendor_id, byte_order, architecture = "", 0, "", "", ""

            with open("/tmp/lscpu.json") as f:
                lscpu = json.load(f)
                for info in lscpu["lscpu"]:
                    if "model name" in info["field"].lower():
                        model = info["data"]
                    if "cpu(s):" == info["field"].lower():
                        num_cores = info["data"]
                    if "vendor id" in info["field"].lower():
                        vendor_id = info["data"]
                    if "byte order" in info["field"].lower():
                        byte_order = info["data"]
                    if "architecture" in info["field"].lower():
                        architecture = info["data"]

            cpu_info = []
            try:
                processor = None
                with open("/proc/cpuinfo", "r") as f:
                    for line in f:
                        if "processor" in line:
                            processor = int(line.split(":")[1].strip())
                        if "cpu MHz" in line:
                            frequency = float(line.split(":")[1].strip())
                            if processor is not None:
                                cpu_info.append(CPUCore(id=processor, frequency=frequency))

            except FileNotFoundError:
                print("/proc/cpuinfo not found.")

            return cls(
                model=model,
                num_cores=num_cores,
                vendor_id=vendor_id,
                byte_order=byte_order,
                architecture=architecture,
                cores=cpu_info,
            )

        @classmethod
        def read_from_darwin(cls) -> CPUInfo:
            """
            Reads the CPU information from a Darwin system

            Returns:
                CPUInfo: The CPU information
            """
            os.system("sysctl -a > /tmp/sysctl_info")
            model, num_cores, vendor_id, byte_order, architecture = "", 0, "", "", ""

            with open("/tmp/sysctl_info") as f:
                for line in f:
                    if line.startswith("machdep.cpu.brand_string"):
                        model = line.split(":")[1].strip()
                    if line.startswith("machdep.cpu.core_count"):
                        num_cores = int(line.split(":")[1].strip())
                    if line.startswith("machdep.cpu.brand_string"):
                        vendor_id = line.split(":")[1].strip()
                    if line.startswith("hw.byteorder"):
                        byte_order = line.split(":")[1].strip()

            architecture = subprocess.check_output(["uname", "-m"]).decode("utf-8").strip()
            frequency_ = (
                subprocess.check_output(["sysctl", "-n", "hw.cpufrequency"])
                .decode("utf-8")
                .strip()
            )
            frequency = float(frequency_) if frequency_ else 0.0

            cpu_info = []
            try:
                # Get the number of CPU cores
                num_cores = int(
                    subprocess.check_output(["sysctl", "-n", "hw.ncpu"]).strip()
                )
                for core_id in range(num_cores):
                    cpu_info.append(CPUCore(id=core_id, frequency=frequency))

            except subprocess.CalledProcessError as e:
                print(f"Error retrieving CPU information: {e}")

            return cls(
                model=model,
                num_cores=num_cores,
                vendor_id=vendor_id,
                byte_order=byte_order,
                architecture=architecture,
                cores=cpu_info,
            )

        @classmethod
        def read_from_system(cls) -> CPUInfo:
            """
            Reads the CPU information from the system. Automatically detects the OS and
            reads the CPU information accordingly.

            Returns:
                CPUInfo: The CPU information
            """
            match platform.system().lower():
                case "linux":
                    return cls.read_from_linux()
                case "darwin":
                    return cls.read_from_darwin()
                case _:
                    return cls.read_from_linux()

### `read_from_darwin()` `classmethod`

Reads the CPU information from a Darwin system

Returns:

Name | Type | Description
--- | --- | ---
`CPUInfo` | `CPUInfo` | The CPU information

Source code in `src/infernet_ml/utils/spec.py`

    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    @classmethod
    def read_from_darwin(cls) -> CPUInfo:
        """
        Reads the CPU information from a Darwin system

        Returns:
            CPUInfo: The CPU information
        """
        os.system("sysctl -a > /tmp/sysctl_info")
        model, num_cores, vendor_id, byte_order, architecture = "", 0, "", "", ""

        with open("/tmp/sysctl_info") as f:
            for line in f:
                if line.startswith("machdep.cpu.brand_string"):
                    model = line.split(":")[1].strip()
                if line.startswith("machdep.cpu.core_count"):
                    num_cores = int(line.split(":")[1].strip())
                if line.startswith("machdep.cpu.brand_string"):
                    vendor_id = line.split(":")[1].strip()
                if line.startswith("hw.byteorder"):
                    byte_order = line.split(":")[1].strip()

        architecture = subprocess.check_output(["uname", "-m"]).decode("utf-8").strip()
        frequency_ = (
            subprocess.check_output(["sysctl", "-n", "hw.cpufrequency"])
            .decode("utf-8")
            .strip()
        )
        frequency = float(frequency_) if frequency_ else 0.0

        cpu_info = []
        try:
            # Get the number of CPU cores
            num_cores = int(
                subprocess.check_output(["sysctl", "-n", "hw.ncpu"]).strip()
            )
            for core_id in range(num_cores):
                cpu_info.append(CPUCore(id=core_id, frequency=frequency))

        except subprocess.CalledProcessError as e:
            print(f"Error retrieving CPU information: {e}")

        return cls(
            model=model,
            num_cores=num_cores,
            vendor_id=vendor_id,
            byte_order=byte_order,
            architecture=architecture,
            cores=cpu_info,
        )

### `read_from_linux()` `classmethod`

Reads the CPU information from a Linux system

Returns:

Name | Type | Description
--- | --- | ---
`CPUInfo` | `CPUInfo` | The CPU information

Source code in `src/infernet_ml/utils/spec.py`

    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    @classmethod
    def read_from_linux(cls) -> CPUInfo:
        """
        Reads the CPU information from a Linux system

        Returns:
            CPUInfo: The CPU information
        """
        os.system("lscpu -J > /tmp/lscpu.json")
        model, num_cores, vendor_id, byte_order, architecture = "", 0, "", "", ""

        with open("/tmp/lscpu.json") as f:
            lscpu = json.load(f)
            for info in lscpu["lscpu"]:
                if "model name" in info["field"].lower():
                    model = info["data"]
                if "cpu(s):" == info["field"].lower():
                    num_cores = info["data"]
                if "vendor id" in info["field"].lower():
                    vendor_id = info["data"]
                if "byte order" in info["field"].lower():
                    byte_order = info["data"]
                if "architecture" in info["field"].lower():
                    architecture = info["data"]

        cpu_info = []
        try:
            processor = None
            with open("/proc/cpuinfo", "r") as f:
                for line in f:
                    if "processor" in line:
                        processor = int(line.split(":")[1].strip())
                    if "cpu MHz" in line:
                        frequency = float(line.split(":")[1].strip())
                        if processor is not None:
                            cpu_info.append(CPUCore(id=processor, frequency=frequency))

        except FileNotFoundError:
            print("/proc/cpuinfo not found.")

        return cls(
            model=model,
            num_cores=num_cores,
            vendor_id=vendor_id,
            byte_order=byte_order,
            architecture=architecture,
            cores=cpu_info,
        )

### `read_from_system()` `classmethod`

Reads the CPU information from the system. Automatically detects the OS and reads the CPU information accordingly.

Returns:

Name | Type | Description
--- | --- | ---
`CPUInfo` | `CPUInfo` | The CPU information

Source code in `src/infernet_ml/utils/spec.py`

    541
    542
    543
    544
    545
    546
    547
    548
    549
    550
    551
    552
    553
    554
    555
    556
    @classmethod
    def read_from_system(cls) -> CPUInfo:
        """
        Reads the CPU information from the system. Automatically detects the OS and
        reads the CPU information accordingly.

        Returns:
            CPUInfo: The CPU information
        """
        match platform.system().lower():
            case "linux":
                return cls.read_from_linux()
            case "darwin":
                return cls.read_from_darwin()
            case _:
                return cls.read_from_linux()

## `ComputeId`

Bases: `StrEnum`

Enum for the different types of compute capabilities within Ritual's

services.

Attributes:

Name | Type | Description
--- | --- | ---
`ML` |  | Machine Learning Compute
`ZK` |  | Zero Knowledge Compute
`TEE` |  | Trusted Execution Environment Compute

Source code in `src/infernet_ml/utils/spec.py`

    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    class ComputeId(StrEnum):
        """
        ComputeId: Enum for the different types of compute capabilities within Ritual's
            services.

        Attributes:
            ML: Machine Learning Compute
            ZK: Zero Knowledge Compute
            TEE: Trusted Execution Environment Compute
        """

        ML = "ml"
        ZK = "zk"
        TEE = "tee"

## `DiskInfo`

Bases: `BaseModel`

Attributes:

Name | Type | Description
--- | --- | ---
`filesystem` | `str` | The filesystem of the disk, e.g. ext4
`mount_point` | `str` | The mount point of the disk, e.g. /
`size` | `int` | The size of the disk in bytes
`used` | `int` | The used space on the disk in bytes
`available` | `int` | The available space on the disk in bytes

Source code in `src/infernet_ml/utils/spec.py`

    582
    583
    584
    585
    586
    587
    588
    589
    590
    591
    592
    593
    594
    595
    596
    597
    598
    599
    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    class DiskInfo(BaseModel):
        """
        DiskInfo: Class representation for the Disk information

        Attributes:
            filesystem (str): The filesystem of the disk, e.g. ext4
            mount_point (str): The mount point of the disk, e.g. /
            size (int): The size of the disk in bytes
            used (int): The used space on the disk in bytes
            available (int): The available space on the disk in bytes
        """

        filesystem: str
        mount_point: str
        size: int
        used: int
        available: int

        @classmethod
        def read_from_system(cls) -> List[DiskInfo]:
            """
            Reads the disk information from the system

            Returns:
                List[DiskInfo]: The disk information
            """
            os.system("df > /tmp/df_info")
            disk_info = []
            with open("/tmp/df_info") as f:
                for line in f:
                    if line.startswith("Filesystem") or line.startswith("map"):
                        continue
                    fields = line.split()
                    match platform.system().lower():
                        case "linux":
                            disk_info.append(
                                cls(
                                    filesystem=fields[0],
                                    mount_point=fields[5],
                                    size=int(fields[1]),
                                    used=int(fields[2]),
                                    available=int(fields[3]),
                                )
                            )
                        case "darwin":
                            disk_info.append(
                                cls(
                                    filesystem=fields[0],
                                    mount_point=fields[8],
                                    size=int(fields[1]),
                                    used=int(fields[2]),
                                    available=int(fields[3]),
                                )
                            )
            return disk_info

### `read_from_system()` `classmethod`

Reads the disk information from the system

Returns:

Type | Description
--- | ---
`List[DiskInfo]` | List[DiskInfo]: The disk information

Source code in `src/infernet_ml/utils/spec.py`

    600
    601
    602
    603
    604
    605
    606
    607
    608
    609
    610
    611
    612
    613
    614
    615
    616
    617
    618
    619
    620
    621
    622
    623
    624
    625
    626
    627
    628
    629
    630
    631
    632
    633
    634
    635
    636
    @classmethod
    def read_from_system(cls) -> List[DiskInfo]:
        """
        Reads the disk information from the system

        Returns:
            List[DiskInfo]: The disk information
        """
        os.system("df > /tmp/df_info")
        disk_info = []
        with open("/tmp/df_info") as f:
            for line in f:
                if line.startswith("Filesystem") or line.startswith("map"):
                    continue
                fields = line.split()
                match platform.system().lower():
                    case "linux":
                        disk_info.append(
                            cls(
                                filesystem=fields[0],
                                mount_point=fields[5],
                                size=int(fields[1]),
                                used=int(fields[2]),
                                available=int(fields[3]),
                            )
                        )
                    case "darwin":
                        disk_info.append(
                            cls(
                                filesystem=fields[0],
                                mount_point=fields[8],
                                size=int(fields[1]),
                                used=int(fields[2]),
                                available=int(fields[3]),
                            )
                        )
        return disk_info

## `GPUHardwareCapability`

Bases: `BaseModel`

Source code in `src/infernet_ml/utils/spec.py`

    694
    695
    696
    697
    698
    699
    700
    701
    702
    703
    704
    705
    706
    707
    708
    709
    710
    711
    712
    713
    714
    715
    716
    717
    718
    719
    720
    721
    722
    723
    724
    725
    726
    727
    728
    729
    730
    731
    732
    733
    734
    735
    736
    737
    738
    739
    740
    741
    742
    743
    744
    745
    746
    747
    748
    749
    750
    751
    752
    753
    754
    755
    756
    757
    758
    759
    class GPUHardwareCapability(BaseModel):
        capability_id: Literal[HardwareCapabilityId.GPU] = HardwareCapabilityId.GPU
        driver_version: str
        cuda_version: str
        gpu_info: List[GPUInfo]

        @classmethod
        def read_from_system(cls) -> Optional[GPUHardwareCapability]:
            """
            Reads the GPU hardware capability from the system

            Returns:
                Optional[GPUHardwareCapability]: The GPU hardware capability
            """
            import subprocess
            import xml.etree.ElementTree as ET

            def parse_memory(mem_str: str | None) -> int:
                if mem_str is None:
                    return 0
                value_, unit = mem_str.split()
                value = int(value_)
                if unit == "MiB":
                    return value * 1024 * 1024
                elif unit == "GiB":
                    return value * 1024 * 1024 * 1024
                return value

            try:
                result = subprocess.run(
                    ["nvidia-smi", "-q", "-x"], capture_output=True, text=True
                )

                if result.returncode != 0:
                    log.info("could not run nvidia-smi, skipping GPU info")
                    return None
            except FileNotFoundError:
                log.info("nvidia-smi not found, skipping GPU info")
                return None

            root = ET.fromstring(result.stdout)

            driver_version = root.findtext("driver_version")
            cuda_version = root.findtext("cuda_version")

            def _find(gpu: Element, field: str) -> str | None:
                f = gpu.find(field)
                if f is None:
                    return None
                return f.text

            gpu_info = [
                GPUInfo(
                    name=gpu.findtext("product_name", "N/A"),
                    memory_total=parse_memory(_find(gpu, "fb_memory_usage/total")),
                    memory_used=parse_memory(_find(gpu, "fb_memory_usage/used")),
                    cuda_device_id=int(gpu.findtext("minor_number", "-1")),
                )
                for gpu in root.findall("gpu")
            ]

            return cls(
                driver_version=driver_version or "N/A",
                cuda_version=cuda_version or "N/A",
                gpu_info=gpu_info,
            )

### `read_from_system()` `classmethod`

Reads the GPU hardware capability from the system

Returns:

Type | Description
--- | ---
`Optional[GPUHardwareCapability]` | Optional[GPUHardwareCapability]: The GPU hardware capability

Source code in `src/infernet_ml/utils/spec.py`

    700
    701
    702
    703
    704
    705
    706
    707
    708
    709
    710
    711
    712
    713
    714
    715
    716
    717
    718
    719
    720
    721
    722
    723
    724
    725
    726
    727
    728
    729
    730
    731
    732
    733
    734
    735
    736
    737
    738
    739
    740
    741
    742
    743
    744
    745
    746
    747
    748
    749
    750
    751
    752
    753
    754
    755
    756
    757
    758
    759
    @classmethod
    def read_from_system(cls) -> Optional[GPUHardwareCapability]:
        """
        Reads the GPU hardware capability from the system

        Returns:
            Optional[GPUHardwareCapability]: The GPU hardware capability
        """
        import subprocess
        import xml.etree.ElementTree as ET

        def parse_memory(mem_str: str | None) -> int:
            if mem_str is None:
                return 0
            value_, unit = mem_str.split()
            value = int(value_)
            if unit == "MiB":
                return value * 1024 * 1024
            elif unit == "GiB":
                return value * 1024 * 1024 * 1024
            return value

        try:
            result = subprocess.run(
                ["nvidia-smi", "-q", "-x"], capture_output=True, text=True
            )

            if result.returncode != 0:
                log.info("could not run nvidia-smi, skipping GPU info")
                return None
        except FileNotFoundError:
            log.info("nvidia-smi not found, skipping GPU info")
            return None

        root = ET.fromstring(result.stdout)

        driver_version = root.findtext("driver_version")
        cuda_version = root.findtext("cuda_version")

        def _find(gpu: Element, field: str) -> str | None:
            f = gpu.find(field)
            if f is None:
                return None
            return f.text

        gpu_info = [
            GPUInfo(
                name=gpu.findtext("product_name", "N/A"),
                memory_total=parse_memory(_find(gpu, "fb_memory_usage/total")),
                memory_used=parse_memory(_find(gpu, "fb_memory_usage/used")),
                cuda_device_id=int(gpu.findtext("minor_number", "-1")),
            )
            for gpu in root.findall("gpu")
        ]

        return cls(
            driver_version=driver_version or "N/A",
            cuda_version=cuda_version or "N/A",
            gpu_info=gpu_info,
        )

## `GPUInfo`

Bases: `BaseModel`

Attributes:

Name | Type | Description
--- | --- | ---
`name` | `str` | The name of the GPU, e.g. NVIDIA GeForce GTX 1080
`memory_total` | `int` | The total memory of the GPU in bytes
`memory_used` | `int` | The used memory of the GPU in bytes
`cuda_device_id` | `Optional[int]` | The CUDA device id of the GPU

Source code in `src/infernet_ml/utils/spec.py`

    639
    640
    641
    642
    643
    644
    645
    646
    647
    648
    649
    650
    651
    652
    653
    class GPUInfo(BaseModel):
        """
        GPUInfo: Class representation for the GPU information

        Attributes:
            name (str): The name of the GPU, e.g. NVIDIA GeForce GTX 1080
            memory_total (int): The total memory of the GPU in bytes
            memory_used (int): The used memory of the GPU in bytes
            cuda_device_id (Optional[int]): The CUDA device id of the GPU
        """

        name: str
        memory_total: int
        memory_used: int
        cuda_device_id: Optional[int] = None

## `GenericHardwareCapability`

Bases: `BaseModel`

Source code in `src/infernet_ml/utils/spec.py`

    673
    674
    675
    676
    677
    678
    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    class GenericHardwareCapability(BaseModel):
        capability_id: Literal[HardwareCapabilityId.Base] = HardwareCapabilityId.Base
        os_info: OSInfo
        cpu_info: CPUInfo
        disk_info: List[DiskInfo]

        @classmethod
        def read_from_system(cls) -> "GenericHardwareCapability":
            """
            Reads the generic hardware capability from the system

            Returns:
                GenericHardwareCapability: The generic hardware capability
            """
            return cls(
                os_info=OSInfo.read_from_system(),
                cpu_info=CPUInfo.read_from_system(),
                disk_info=DiskInfo.read_from_system(),
            )

### `read_from_system()` `classmethod`

Reads the generic hardware capability from the system

Returns:

Name | Type | Description
--- | --- | ---
`GenericHardwareCapability` | `'GenericHardwareCapability'` | The generic hardware capability

Source code in `src/infernet_ml/utils/spec.py`

    679
    680
    681
    682
    683
    684
    685
    686
    687
    688
    689
    690
    691
    @classmethod
    def read_from_system(cls) -> "GenericHardwareCapability":
        """
        Reads the generic hardware capability from the system

        Returns:
            GenericHardwareCapability: The generic hardware capability
        """
        return cls(
            os_info=OSInfo.read_from_system(),
            cpu_info=CPUInfo.read_from_system(),
            disk_info=DiskInfo.read_from_system(),
        )

## `HardwareCapabilityId`

Bases: `StrEnum`

Enum for the different types of hardware capabilities within

Ritual's services..

Attributes:

Name | Type | Description
--- | --- | ---
`Base` |  | Generic Hardware Capability, contains information about the OS, CPU, and disk
`GPU` |  | Graphics Processing Unit
`TEE` |  | Trusted Execution Environment

Source code in `src/infernet_ml/utils/spec.py`

    656
    657
    658
    659
    660
    661
    662
    663
    664
    665
    666
    667
    668
    669
    670
    class HardwareCapabilityId(StrEnum):
        """
        HardwareCapabilityType: Enum for the different types of hardware capabilities within
            Ritual's services..

        Attributes:
            Base: Generic Hardware Capability, contains information about the OS, CPU, and
                disk
            GPU: Graphics Processing Unit
            TEE: Trusted Execution Environment
        """

        Base = "base"
        GPU = "gpu"
        TEE = "tee"

## `MLComputeCapability`

Bases: `BaseModel`

Class for the machine learning compute capabilities within

Ritual's services.

Attributes:

Name | Type | Description
--- | --- | ---
`id` | `Literal[ML]` | The type of compute capability
`type` | `MLType` | The type of machine learning model that can be supported
`task` | `List[MLTask]` | The list of machine learning tasks that can be supported
`models` | `List[BroadcastedArtifact] | List[CSSModel]` | The list of models that can be supported
`cached_models` | `List[BroadcastedArtifact]` | The list of cached models that can be supported
`inference_engine` | `Optional[str]` | The inference engine that can be supported
`inference_engine_version` | `Optional[str]` | The inference engine version that can be supported

Source code in `src/infernet_ml/utils/spec.py`

    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    class MLComputeCapability(BaseModel):
        """
        MLComputeCapability: Class for the machine learning compute capabilities within
            Ritual's services.

        Attributes:
            id (Literal[ComputeId.ML]): The type of compute capability
            type (MLType): The type of machine learning model that can be supported
            task (List[MLTask]): The list of machine learning tasks that can be supported
            models (List[BroadcastedArtifact] | List[CSSModel]): The list of models that can
                be supported
            cached_models (List[BroadcastedArtifact]): The list of cached models that can
                be supported
            inference_engine (Optional[str]): The inference engine that can be supported
            inference_engine_version (Optional[str]): The inference engine version that can
                be supported
        """

        id: Literal[ComputeId.ML] = ComputeId.ML
        type: MLType
        task: List[MLTask]
        models: List[BroadcastedArtifact] | List[CSSModel] = []
        cached_models: List[BroadcastedArtifact] = []
        inference_engine: Optional[str] = None
        inference_engine_version: Optional[str] = None

        @classmethod
        def onnx_compute(
            cls,
            models: Optional[List[BroadcastedArtifact]] = None,
            cached_models: Optional[List[BroadcastedArtifact]] = None,
        ) -> MLComputeCapability:
            """
            Utility function to generate an ONNX compute capability.

            Args:
                models (Optional[List[BroadcastedArtifact]]): The list of models that can be
                    supported
                cached_models (Optional[List[BroadcastedArtifact]]): The list of cached
                    models

            Returns:
                MLComputeCapability: The ONNX compute capability
            """
            models = models or []
            cached_models = cached_models or []
            return cls(
                type=MLType.ONNX,
                task=[],
                models=models,
                cached_models=cached_models,
            )

        @classmethod
        def llama_cpp_compute(
            cls, models: Optional[List[CachedArtifact]] = None
        ) -> MLComputeCapability:
            """
            Utility function to generate a llama.cpp compute capability.

            Args:
                models (Optional[List[CachedArtifact]]): The list of models that can be
                    supported

            Returns:
                MLComputeCapability: The llama.cpp compute capability
            """
            try:
                version = " ".join(
                    subprocess.check_output(
                        shlex.split("llama-server --version"), stderr=subprocess.STDOUT
                    )
                    .decode("utf-8")
                    .strip()
                    .split("\n")
                )
            except subprocess.CalledProcessError as e:
                version = e.output.decode("utf-8")
            __models = cast(List[BroadcastedArtifact], models or [])
            return cls(
                type=MLType.LLAMA_CPP,
                task=[MLTask.TextGeneration],
                models=__models,
                cached_models=__models,
                inference_engine="llama_cpp",
                inference_engine_version=version,
            )

        @classmethod
        def torch_compute(
            cls,
            models: Optional[List[BroadcastedArtifact]] = None,
            cached_models: Optional[List[BroadcastedArtifact]] = None,
        ) -> MLComputeCapability:
            """
            Utility function to generate a Torch compute capability.

            Args:
                models (Optional[List[BroadcastedArtifact]]): The list of models that can be
                    supported
                cached_models (Optional[List[BroadcastedArtifact]]): The list of cached
                    models

            Returns:
                MLComputeCapability: The torch compute capability
            """
            models = models or []
            cached_models = cached_models or []
            return cls(
                type=MLType.TORCH,
                task=[],
                models=models,
                cached_models=cached_models,
            )

        @classmethod
        def hf_client_compute(
            cls,
        ) -> MLComputeCapability:
            """
            Utility function to generate a Huggingface client compute capability.
            """
            return cls(
                type=MLType.HF_CLIENT,
                task=[
                    MLTask.TextGeneration,
                    MLTask.TextClassification,
                    MLTask.TokenClassification,
                    MLTask.Summarization,
                ],
            )

        @classmethod
        def tgi_client_compute(
            cls,
        ) -> MLComputeCapability:
            """
            Utility function to generate a TGI client compute capability.
            """
            return cls(
                type=MLType.TGI_CLIENT,
                task=[MLTask.TextGeneration],
            )

        @classmethod
        def css_compute(
            cls,
            models: Optional[List[CSSModel]] = None,
        ) -> MLComputeCapability:
            """
            Utility function to generate a CSS compute capability.

            Args:
                models (Optional[List[CSSModel]]): The list of models that can be supported

            Returns:
                MLComputeCapability: The CSS compute capability
            """
            models = models or []
            return cls(
                type=MLType.CSS,
                task=[],
                models=models,
            )

### `css_compute(models=None)` `classmethod`

Utility function to generate a CSS compute capability.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`models` | `Optional[List[CSSModel]]` | The list of models that can be supported | `None`

Returns:

Name | Type | Description
--- | --- | ---
`MLComputeCapability` | `MLComputeCapability` | The CSS compute capability

Source code in `src/infernet_ml/utils/spec.py`

    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    @classmethod
    def css_compute(
        cls,
        models: Optional[List[CSSModel]] = None,
    ) -> MLComputeCapability:
        """
        Utility function to generate a CSS compute capability.

        Args:
            models (Optional[List[CSSModel]]): The list of models that can be supported

        Returns:
            MLComputeCapability: The CSS compute capability
        """
        models = models or []
        return cls(
            type=MLType.CSS,
            task=[],
            models=models,
        )

### `hf_client_compute()` `classmethod`

Utility function to generate a Huggingface client compute capability.

Source code in `src/infernet_ml/utils/spec.py`

    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    @classmethod
    def hf_client_compute(
        cls,
    ) -> MLComputeCapability:
        """
        Utility function to generate a Huggingface client compute capability.
        """
        return cls(
            type=MLType.HF_CLIENT,
            task=[
                MLTask.TextGeneration,
                MLTask.TextClassification,
                MLTask.TokenClassification,
                MLTask.Summarization,
            ],
        )

### `llama_cpp_compute(models=None)` `classmethod`

Utility function to generate a llama.cpp compute capability.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`models` | `Optional[List[CachedArtifact]]` | The list of models that can be supported | `None`

Returns:

Name | Type | Description
--- | --- | ---
`MLComputeCapability` | `MLComputeCapability` | The llama.cpp compute capability

Source code in `src/infernet_ml/utils/spec.py`

    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    @classmethod
    def llama_cpp_compute(
        cls, models: Optional[List[CachedArtifact]] = None
    ) -> MLComputeCapability:
        """
        Utility function to generate a llama.cpp compute capability.

        Args:
            models (Optional[List[CachedArtifact]]): The list of models that can be
                supported

        Returns:
            MLComputeCapability: The llama.cpp compute capability
        """
        try:
            version = " ".join(
                subprocess.check_output(
                    shlex.split("llama-server --version"), stderr=subprocess.STDOUT
                )
                .decode("utf-8")
                .strip()
                .split("\n")
            )
        except subprocess.CalledProcessError as e:
            version = e.output.decode("utf-8")
        __models = cast(List[BroadcastedArtifact], models or [])
        return cls(
            type=MLType.LLAMA_CPP,
            task=[MLTask.TextGeneration],
            models=__models,
            cached_models=__models,
            inference_engine="llama_cpp",
            inference_engine_version=version,
        )

### `onnx_compute(models=None, cached_models=None)` `classmethod`

Utility function to generate an ONNX compute capability.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`models` | `Optional[List[BroadcastedArtifact]]` | The list of models that can be supported | `None`
`cached_models` | `Optional[List[BroadcastedArtifact]]` | The list of cached models | `None`

Returns:

Name | Type | Description
--- | --- | ---
`MLComputeCapability` | `MLComputeCapability` | The ONNX compute capability

Source code in `src/infernet_ml/utils/spec.py`

    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    @classmethod
    def onnx_compute(
        cls,
        models: Optional[List[BroadcastedArtifact]] = None,
        cached_models: Optional[List[BroadcastedArtifact]] = None,
    ) -> MLComputeCapability:
        """
        Utility function to generate an ONNX compute capability.

        Args:
            models (Optional[List[BroadcastedArtifact]]): The list of models that can be
                supported
            cached_models (Optional[List[BroadcastedArtifact]]): The list of cached
                models

        Returns:
            MLComputeCapability: The ONNX compute capability
        """
        models = models or []
        cached_models = cached_models or []
        return cls(
            type=MLType.ONNX,
            task=[],
            models=models,
            cached_models=cached_models,
        )

### `tgi_client_compute()` `classmethod`

Utility function to generate a TGI client compute capability.

Source code in `src/infernet_ml/utils/spec.py`

    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    @classmethod
    def tgi_client_compute(
        cls,
    ) -> MLComputeCapability:
        """
        Utility function to generate a TGI client compute capability.
        """
        return cls(
            type=MLType.TGI_CLIENT,
            task=[MLTask.TextGeneration],
        )

### `torch_compute(models=None, cached_models=None)` `classmethod`

Utility function to generate a Torch compute capability.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`models` | `Optional[List[BroadcastedArtifact]]` | The list of models that can be supported | `None`
`cached_models` | `Optional[List[BroadcastedArtifact]]` | The list of cached models | `None`

Returns:

Name | Type | Description
--- | --- | ---
`MLComputeCapability` | `MLComputeCapability` | The torch compute capability

Source code in `src/infernet_ml/utils/spec.py`

    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    @classmethod
    def torch_compute(
        cls,
        models: Optional[List[BroadcastedArtifact]] = None,
        cached_models: Optional[List[BroadcastedArtifact]] = None,
    ) -> MLComputeCapability:
        """
        Utility function to generate a Torch compute capability.

        Args:
            models (Optional[List[BroadcastedArtifact]]): The list of models that can be
                supported
            cached_models (Optional[List[BroadcastedArtifact]]): The list of cached
                models

        Returns:
            MLComputeCapability: The torch compute capability
        """
        models = models or []
        cached_models = cached_models or []
        return cls(
            type=MLType.TORCH,
            task=[],
            models=models,
            cached_models=cached_models,
        )

## `MLTask`

Bases: `StrEnum`

supported. This is provided for utility & should not be used as a strict validation mechanism.

Attributes:

Name | Type | Description
--- | --- | ---
`TextGeneration` |  | Text Generation
`TextClassification` |  | Text Classification
`TokenClassification` |  | Token Classification
`Summarization` |  | Summarization
`ImageClassification` |  | Image Classification
`ImageSegmentation` |  | Image Segmentation
`ObjectDetection` |  | Object Detection

Source code in `src/infernet_ml/utils/spec.py`

    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    class MLTask(StrEnum):
        """
        MLTask: Enum for the different types of machine learning tasks that can be
        supported. This is provided for utility & should not be used as a strict
        validation mechanism.

        Attributes:
            TextGeneration: Text Generation
            TextClassification: Text Classification
            TokenClassification: Token Classification
            Summarization: Summarization
            ImageClassification: Image Classification
            ImageSegmentation: Image Segmentation
            ObjectDetection: Object Detection
        """

        TextGeneration = "text_generation"
        TextClassification = "text_classification"
        TokenClassification = "token_classification"
        Summarization = "summarization"
        ImageClassification = "image_classification"
        ImageSegmentation = "image_segmentation"
        ObjectDetection = "object_detection"

## `OSInfo`

Bases: `BaseModel`

Attributes:

Name | Type | Description
--- | --- | ---
`name` | `str` | The name of the OS, e.g. Ubuntu
`version` | `str` | The version of the OS

Source code in `src/infernet_ml/utils/spec.py`

    559
    560
    561
    562
    563
    564
    565
    566
    567
    568
    569
    570
    571
    572
    573
    574
    575
    576
    577
    578
    579
    class OSInfo(BaseModel):
        """
        OSInfo: Class representation for the OS information

        Attributes:
            name (str): The name of the OS, e.g. Ubuntu
            version (str): The version of the OS
        """

        name: str
        version: str

        @classmethod
        def read_from_system(cls) -> OSInfo:
            """
            Reads the OS information from the system

            Returns:
                OSInfo: The OS information
            """
            return cls(name=platform.system(), version=platform.version())

### `read_from_system()` `classmethod`

Reads the OS information from the system

Returns:

Name | Type | Description
--- | --- | ---
`OSInfo` | `OSInfo` | The OS information

Source code in `src/infernet_ml/utils/spec.py`

    571
    572
    573
    574
    575
    576
    577
    578
    579
    @classmethod
    def read_from_system(cls) -> OSInfo:
        """
        Reads the OS information from the system

        Returns:
            OSInfo: The OS information
        """
        return cls(name=platform.system(), version=platform.version())

## `Resource`

Bases: `BaseModel`

Class representation for the resources of a service within Ritual's

services.

Attributes:

Name | Type | Description
--- | --- | ---
`capabilities` | `List[Capability]` | The list of capabilities of the service
`version` | `str` | The version of this specification

Source code in `src/infernet_ml/utils/spec.py`

    833
    834
    835
    836
    837
    838
    839
    840
    841
    842
    843
    844
    class Resource(BaseModel):
        """
        Resource: Class representation for the resources of a service within Ritual's
            services.

        Attributes:
            capabilities (List[Capability]): The list of capabilities of the service
            version (str): The version of this specification
        """

        capabilities: List[ServiceResources]
        version: str

## `ServiceResources`

Bases: `BaseModel`

Class representation for the resources of a service within

Ritual's services..

Attributes:

Name | Type | Description
--- | --- | ---
`service_id` | `str` | The unique identifier for the service
`hardware_capabilities` | `List[HardwareCapability]` | The list of hardware capabilities of the service
`compute_capability` | `List[ComputeCapability]` | The list of compute capabilities of the service

Source code in `src/infernet_ml/utils/spec.py`

    789
    790
    791
    792
    793
    794
    795
    796
    797
    798
    799
    800
    801
    802
    803
    804
    805
    806
    807
    808
    809
    810
    811
    812
    813
    814
    815
    816
    817
    818
    819
    820
    821
    822
    823
    824
    825
    826
    827
    828
    829
    830
    class ServiceResources(BaseModel):
        """
        ServiceResources: Class representation for the resources of a service within
            Ritual's services..

        Attributes:
            service_id (str): The unique identifier for the service
            hardware_capabilities (List[HardwareCapability]): The list of hardware
                capabilities of the service
            compute_capability (List[ComputeCapability]): The list of compute capabilities
                of the service
        """

        version: str = "0.1.0"
        service_id: str

        hardware_capabilities: List[HardwareCapability]
        compute_capability: List[ComputeCapability]

        @classmethod
        def initialize(
            cls,
            service_id: str,
            compute_capability: List[ComputeCapability],
        ) -> ServiceResources:
            """
            Initializes the service resources. Reads the hardware capabilities from the
            system.

            Args:
                service_id (str): The unique identifier for the service
                compute_capability (List[ComputeCapability]): The list of compute
                    capabilities of the service

            Returns:
                ServiceResources: The service resources
            """
            return cls(
                service_id=service_id,
                hardware_capabilities=read_hw_cap_from_system(),
                compute_capability=compute_capability,
            )

### `initialize(service_id, compute_capability)` `classmethod`

Initializes the service resources. Reads the hardware capabilities from the system.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`service_id` | `str` | The unique identifier for the service | required
`compute_capability` | `List[ComputeCapability]` | The list of compute capabilities of the service | required

Returns:

Name | Type | Description
--- | --- | ---
`ServiceResources` | `ServiceResources` | The service resources

Source code in `src/infernet_ml/utils/spec.py`

    808
    809
    810
    811
    812
    813
    814
    815
    816
    817
    818
    819
    820
    821
    822
    823
    824
    825
    826
    827
    828
    829
    830
    @classmethod
    def initialize(
        cls,
        service_id: str,
        compute_capability: List[ComputeCapability],
    ) -> ServiceResources:
        """
        Initializes the service resources. Reads the hardware capabilities from the
        system.

        Args:
            service_id (str): The unique identifier for the service
            compute_capability (List[ComputeCapability]): The list of compute
                capabilities of the service

        Returns:
            ServiceResources: The service resources
        """
        return cls(
            service_id=service_id,
            hardware_capabilities=read_hw_cap_from_system(),
            compute_capability=compute_capability,
        )

## `ZKComputeCapability`

Bases: `BaseModel`

Class for the zero knowledge compute capabilities within

Ritual's services..

Attributes:

Name | Type | Description
--- | --- | ---
`id` | `Literal[ZK]` | The type of compute capability

Source code in `src/infernet_ml/utils/spec.py`

    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    class ZKComputeCapability(BaseModel):
        """
        ZKComputeCapability: Class for the zero knowledge compute capabilities within
            Ritual's services..

        Attributes:
            id (Literal[ComputeId.ZK]): The type of compute capability
        """

        id: Literal[ComputeId.ZK] = ComputeId.ZK

## `hf_api_query_handler(any_tags=[], all_tags=[], token=None)`

Generates a handler for checking if a model is available on HuggingFace. Includes private models if the provided token is valid and has access to them.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`any_tags` | `List[str]` | List of tags to filter the models by. At least one of the tags must be present in the model's tags. | `[]`
`all_tags` | `List[str]` | List of tags to filter the models by. All of the tags must be present in the model's tags. | `[]`
`token` | `Optional[str]` | HuggingFace API token. Defaults to None. | `None`

Returns:

Name | Type | Description
--- | --- | ---
`handler` | `Callable[[str], dict[str, bool]]` | The handler function to check if a model is supported by the HF API.

Source code in `src/infernet_ml/utils/spec.py`

     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    def hf_api_query_handler(
        any_tags: List[str] = [], all_tags: List[str] = [], token: Optional[str] = None
    ) -> Callable[[str], dict[str, bool]]:
        """
        Generates a handler for checking if a model is available on HuggingFace. Includes
        private models if the provided token is valid and has access to them.

        Args:
            any_tags (List[str]): List of tags to filter the models by. At least one of the
                tags must be present in the model's tags.
            all_tags (List[str]): List of tags to filter the models by. All of the tags must
                be present in the model's tags.
            token (Optional[str]): HuggingFace API token. Defaults to None.

        Returns:
            handler (Callable[[str], dict[str, bool]]): The handler function to check if
                a model is supported by the HF API.
        """

        def handler(model_id: str) -> dict[str, bool]:
            try:
                info = HfApi(token=token).model_info(model_id)
                supported = True
                if all_tags:
                    # Check if all tags are present in the model's tags
                    supported = all([tag in info.tags for tag in all_tags])
                if any_tags:
                    # Check if at least one tag is present in the model's tags
                    supported = supported and any([tag in info.tags for tag in any_tags])
                return {"supported": supported}
            except Exception:
                # model_info will raise an exception if the model is not found
                return {"supported": False}

        return handler

## `null_query_handler()`

Generates a handler for checking if a model is supported by the service. This handler always returns False, and is used for services that do not advertise their supported model(s).

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`model_id` | `str` | The model id to check if it is supported. This is ignored. | required

Returns:

Name | Type | Description
--- | --- | ---
`handler` | `Callable[[str], dict[str, bool]]` | The handler function to check if a model is supported by the service.

Source code in `src/infernet_ml/utils/spec.py`

    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    def null_query_handler() -> Callable[[str], dict[str, bool]]:
        """
        Generates a handler for checking if a model is supported by the service.
        This handler always returns False, and is used for services that do not
        advertise their supported model(s).

        Args:
            model_id (str): The model id to check if it is supported. This is ignored.

        Returns:
            handler (Callable[[str], dict[str, bool]]): The handler function to check if
                a model is supported by the service.
        """

        def handler(model_id: str) -> dict[str, bool]:
            return {"supported": False}

        return handler

## `postfix_query_handler(postfix)`

Generates a handler for checking if a model has a specific postfix. The onnx & torch service use this to quickly broadcast if a model is supported by the service.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`postfix` | `str` | The postfix to check for in the model files | required

Returns:

Name | Type | Description
--- | --- | ---
`handler` | `Callable[[str], dict[str, bool]]` | The handler function to check if a model is supported by the service.

Source code in `src/infernet_ml/utils/spec.py`

    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    def postfix_query_handler(postfix: str) -> Callable[[str], dict[str, bool]]:
        """
        Generates a handler for checking if a model has a specific postfix. The onnx & torch
        service use this to quickly broadcast if a model is supported by the service.

        Args:
            postfix (str): The postfix to check for in the model files

        Returns:
            handler (Callable[[str], dict[str, bool]]): The handler function to check if
                a model is supported by the service.
        """

        def handler(model_id: str) -> dict[str, bool]:
            model = MlModelId.from_unique_id(model_id)
            if model.files[0].endswith(postfix):
                return {"supported": True}
            else:
                return {"supported": False}

        return handler

## `read_hw_cap_from_system()`

Reads the hardware capabilities from the system.

Source code in `src/infernet_ml/utils/spec.py`

    776
    777
    778
    779
    780
    781
    782
    783
    784
    785
    786
    def read_hw_cap_from_system() -> List[HardwareCapability]:
        """
        Reads the hardware capabilities from the system.

        """
        capabilities: List[HardwareCapability] = [
            GenericHardwareCapability.read_from_system()
        ]
        if gpu_capability := GPUHardwareCapability.read_from_system():
            capabilities.append(gpu_capability)
        return capabilities

## `ritual_service_specs(app, resource_generator, model_query_handler)`

Generates the service resources endpoint for Ritual's services. This endpoint is used to broadcast the capabilities of the service for routers & indexing services.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`app` | `Quart` | The Quart application | required
`resource_generator` | `Callable[[], dict[str, Any]]` | The function to generate the resources of the service | required
`model_query_handler` | `Callable[[str], dict[str, bool]]` | The function to generate the model query handler | required

Returns:

Type | Description
--- | ---
`None` | None

Source code in `src/infernet_ml/utils/spec.py`

    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    def ritual_service_specs(
        app: Quart,
        resource_generator: Callable[[], dict[str, Any]],
        model_query_handler: Callable[[str], dict[str, bool]],
    ) -> None:
        """
        Generates the service resources endpoint for Ritual's services. This endpoint is used
        to broadcast the capabilities of the service for routers & indexing services.

        Args:
            app (Quart): The Quart application
            resource_generator (Callable[[], dict[str, Any]]): The function to generate
                the resources of the service
            model_query_handler (Callable[[str], dict[str, bool]]): The function to
                generate the model query handler

        Returns:
            None
        """

        @app.route("/service-resources")
        async def service_resources_endpoint() -> Any:
            model_id = request.args.get("model_id", "")
            if not model_id:
                return resource_generator()
            try:
                return model_query_handler(model_id)
            except Exception as e:
                return {"supported": False, "error": str(e)}

## `simple_query_handler(supported_models)`

Generates a handler for checking if a model is supported by the service. This handler checks if the model id is in the list of supported models.

Parameters:

Name | Type | Description | Default
--- | --- | --- | ---
`supported_models` | `List[str]` | The list of supported models | required

Returns:

Name | Type | Description
--- | --- | ---
`handler` | `Callable[[str], dict[str, bool]]` | The handler function to check if a model is supported by the service.

Source code in `src/infernet_ml/utils/spec.py`

    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    def simple_query_handler(
        supported_models: List[str],
    ) -> Callable[[str], dict[str, bool]]:
        """
        Generates a handler for checking if a model is supported by the service. This
        handler checks if the model id is in the list of supported models.

        Args:
            supported_models (List[str]): The list of supported models

        Returns:
            handler (Callable[[str], dict[str, bool]]): The handler function to check if
                a model is supported by the service.
        """

        def handler(model_id: str) -> dict[str, bool]:
            return {"supported": model_id in supported_models}

        return handler