Skip to content

Commit

Permalink
DOCS-3334: Add back advanced modular resources, and add aliases (#3813)
Browse files Browse the repository at this point in the history
  • Loading branch information
JessamyT authored Jan 8, 2025
1 parent 480714b commit c06f0a8
Show file tree
Hide file tree
Showing 11 changed files with 375 additions and 7 deletions.
10 changes: 9 additions & 1 deletion docs/data-ai/ai/deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ description: "The Machine Learning (ML) model service allows you to deploy machi
aliases:
- /how-tos/train-deploy-ml/
- /services/ml/
- /registry/ml/
- /services/ml/upload-model/
- /services/ml/edit/
- /ml/edit/
- /manage/data/upload-model/
- /manage/ml/upload-model/
- /ml/upload-model/
- /services/ml/ml-models/
---

The Machine Learning (ML) model service allows you to deploy [machine learning models](/data-ai/ai/deploy/#deploy-your-ml-model) to your machine.
Expand Down Expand Up @@ -66,5 +74,5 @@ For other use cases, consider [creating custom functionality with a module](/ope

{{< alert title="Add support for other models" color="tip" >}}
ML models must be designed in particular shapes to work with the `mlmodel` [classification](/operate/reference/services/vision/mlmodel/) or [detection](/operate/reference/services/vision/mlmodel/) model of Viam's [vision service](/operate/reference/services/vision/).
See [ML Model Design](/registry/advanced/mlmodel-design/) to design a modular ML model service with models that work with vision.
See [ML Model Design](/operate/reference/advanced-modules/mlmodel-design/) to design a modular ML model service with models that work with vision.
{{< /alert >}}
2 changes: 1 addition & 1 deletion docs/dev/reference/glossary/part.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Part
id: part
full_link: /architecture/parts/
full_link: /operate/reference/architecture/parts/
short_description: A single-board computer, desktop, laptop, or other computer running viam-server, the hardware components attached to it, and any services or other resources running on it.
---

Expand Down
2 changes: 1 addition & 1 deletion docs/dev/reference/glossary/resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ Resources are individual, addressable elements of a machine.
Each part has local resources and can also have resources from another {{< glossary_tooltip term_id="remote-part" text="remote">}} machine part.
The capabilities of each resource are exposed through the part’s API.

Each resource on your machine implements either one of the [existing Viam APIs](/dev/reference/apis/), or a [custom interface](/registry/advanced/#new-api-subtypes).
Each resource on your machine implements either one of the [existing Viam APIs](/dev/reference/apis/), or a [custom interface](/operate/reference/advanced-modules/#new-api-subtypes).
2 changes: 1 addition & 1 deletion docs/dev/reference/sdks/use-extra-params.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ If passing an object of type `nil`, you must specify `nil` in the method call or

## Define

If `extra` information must be passed to a resource, it is handled within a new, _modular_ resource model's [custom API](/registry/) wrapper.
If `extra` information must be passed to a resource, it is handled within a new, _modular_ resource model's [custom API](/operate/get-started/other-hardware/) wrapper.

{{%expand "Click for instructions on defining a custom model to use extra params" %}}

Expand Down
2 changes: 1 addition & 1 deletion docs/operate/get-started/other-hardware/cpp-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ If you want to write a module to add support to a new type of component or servi

- If you are working with a component that doesn't fit into any of the existing component APIs, you can use the [generic component](/operate/reference/components/generic/) to build your own component API.
- If you are designing a service that doesn't fit into any of the existing service APIs, you can use the [generic service](/operate/reference/components/generic/) to build your own service API.
- It is also possible to [define an entirely new API](/registry/advanced/create-subtype/), but this is even more advanced than using `generic`.
- It is also possible to [define an entirely new API](/operate/reference/advanced-modules/create-subtype/), but this is even more advanced than using `generic`.

Most module use cases, however, benefit from implementing an existing API instead of `generic`.
{{% /alert %}}
Expand Down
53 changes: 53 additions & 0 deletions docs/operate/reference/advanced-modules/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: "Advanced Modular Resources"
linkTitle: "Advanced Modules"
type: docs
tags:
[
"server",
"rdk",
"extending viam",
"modular resources",
"components",
"services",
]
description: "Some usage may require you to define new APIs or deploy custom components using a server on a remote part"
aliases:
- /program/extend/
- /modular-resources/advanced/
- /registry/advanced/
date: "2022-01-01"
# updated: "" # When the content was last entirely checked
toc_hide: true
---

Some use cases may require advanced considerations when designing or deploying modular resources.
Depending on your needs, you may wish to define an entirely new API subtype, deploy a custom component using a server on a {{< glossary_tooltip term_id="remote-part" text="remote" >}} {{< glossary_tooltip term_id="part" text="part" >}}, or design a custom ML model.

## New API subtypes

The [component APIs](/dev/reference/apis/#component-apis) and [service APIs](/dev/reference/apis/#service-apis) provide a standard interface for controlling common hardware components and higher level functionality.
If your use case aligns closely with an existing API, you should use that API to program your new resource.

If you want to use most of an existing API but need just a few other functions, you can use the `DoCommand` endpoint together with [extra parameters](/dev/reference/sdks/use-extra-params/) to add custom functionality to an existing resource {{< glossary_tooltip term_id="subtype" text="subtype" >}}.

Or, if your resource does not fit into an existing resource subtype, you can use one of the following:

- If you are working with a component that doesn't fit into any of the existing [component APIs](/dev/reference/apis/#component-apis), you can use the [generic component](/operate/reference/components/generic/) to build your own component API.
- If you are designing a service that doesn't fit into any of the existing [service APIs](/dev/reference/apis/#service-apis), you can use the [generic service](/dev/reference/apis/services/generic/) to build your own service API.

Both generic resources use the [`DoCommand`](/dev/reference/apis/components/generic/#docommand) endpoint to enable you to make arbitrary calls as needed for your resource.

Alternatively, you can also [define a new resource subtype and an API for that subtype](/operate/reference/advanced-modules/create-subtype/) if none of the above options are a good fit for your use case.

## Custom components as remotes

Running {{< glossary_tooltip term_id="modular-resource" text="modular resources" >}} on the computer directly connected to your components is the preferred way of managing and controlling custom components.

However, if you are unable to use modular resources because you need to host `viam-server` on a non-Linux system or have an issue with compilation, you may need to [implement a custom component and register it on a server configured as a remote](/operate/reference/advanced-modules/custom-components-remotes/) on your machine.

## Design a custom ML model

When working with the [ML model service](/dev/reference/apis/services/ml/), you can deploy an [existing model](/data-ai/ai/deploy/) or [train your own model](/data-ai/ai/train/).

However, if you are writing your own {{< glossary_tooltip term_id="module" text="module" >}} that uses the ML model service together with the [vision service](/dev/reference/apis/services/vision/), you can also [design your own ML model](/operate/reference/advanced-modules/mlmodel-design/) to better match your specific use case.
107 changes: 107 additions & 0 deletions docs/operate/reference/advanced-modules/create-subtype.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
title: "Define a New Resource Subtype"
linkTitle: "New API Subtype"
weight: 30
type: "docs"
tags: ["rdk", "extending viam", "modular resources", "API"]
description: "Define a custom API for a resource that does not fit into existing component or service subtypes."
no_list: true
aliases:
- /extend/modular-resources/create/create-subtype/
- /modular-resources/advanced/create-subtype/
- /registry/advanced/create-subtype/
date: "2022-01-01"
# updated: "" # When the content was last entirely checked
---

You can define a new, custom {{< glossary_tooltip term_id="resource" text="resource" >}} _{{< glossary_tooltip term_id="subtype" text="subtype" >}}_ API if:

- You have a {{% glossary_tooltip term_id="resource" text="resource" %}} that does not fit into any of the existing {{< glossary_tooltip term_id="component" text="component" >}} or {{< glossary_tooltip term_id="service" text="service" >}} subtypes.
- You have a resource that could fit into an existing subtype, but you want to define an API with different methods and messages than the ones in the existing [APIs](/dev/reference/apis/) for that subtype.

{{% alert title="Tip" color="tip" %}}

If you want to use most of an existing API but need just a few other functions, try using the `DoCommand` endpoint and [extra parameters](/dev/reference/sdks/use-extra-params/) to add custom functionality to an existing subtype.
For example, if you have a [sensor](/operate/reference/components/sensor/) and you want to define a `Calibrate` method, you can use `DoCommand`.

If your use case uses only `DoCommand` and no other API methods, you can define a new model of [generic component](/operate/reference/components/generic/) or [generic service](/operate/reference/services/generic/).

{{% /alert %}}

## Define your new resource API

Viam uses [protocol buffers](https://protobuf.dev/) for API definition.

To define a new subtype, you need to define the methods and messages of the new API in [protobuf](https://github.com/protocolbuffers/protobuf), write code in Python or Go to implement the higher level server and client functions required, and generate all necessary [protobuf module files](https://buf.build/docs/generate/usage/).
The following steps guide you through this process in more detail:

1. Decide whether your custom subtype is a {{< glossary_tooltip term_id="component" text="component" >}} or a {{< glossary_tooltip term_id="service" text="service" >}}.
If it provides an interface to control hardware, it is a component.
If it provides higher-level functionality, it is a service.
1. Choose a name for your subtype.
For example, `gizmo`.

Determine a valid {{< glossary_tooltip term_id="api-namespace-triplet" text="API namespace triplet" >}} based on your subtype name.
You can figure out the {{< glossary_tooltip term_id="model-namespace-triplet" text="model namespace triplet" >}} later when you [create a model that implements your custom API](/operate/get-started/other-hardware/).

{{< expand "API namespace triplet and model namespace triplet example" >}}

The `viam-labs:audioout:pygame` model uses the repository name [audioout](https://github.com/viam-labs/audioout).
It implements the custom API `viam-labs:service:audioout`:

```json
{
"api": "viam-labs:service:audioout",
"model": "viam-labs:audioout:pygame"
}
```

For your custom API, your API namespace triplet might be `your-org-namespace:component:gizmo` where `your-org-namespace` is your organization namespace, found in your org settings page in the Viam app.

{{< /expand >}}

1. Create a directory for your module.
Within that, create a directory called <file>src</file>.

{{% alert title="Tip" color="tip" %}}

If you are writing your module using Python, you can use this [module generator tool](https://github.com/viam-labs/generator-viam-module) to generate stub files for the new API as well as a new {{< glossary_tooltip term_id="module" text="module" >}} that implements the new API.

{{% /alert %}}

1. Define your new API:

- [Write the proto](https://protobuf.dev/programming-guides/proto3/) methods in a `<subtype name>.proto` file inside your <file>src/proto</file> directory.
For reference:
- [Example modular component proto file](https://github.com/viamrobotics/viam-python-sdk/blob/main/examples/complex_module/src/proto/gizmo.proto)
- [Example modular service proto file](https://github.com/viam-labs/speech-service-api/blob/main/src/proto/speech.proto)
- [Built-in Viam resource proto files](https://github.com/viamrobotics/api/tree/main/proto/viam)
- And define the proto methods in a protobuf-supported language such as Python or Go in a file called `api.py` or `api.go`, respectively.
- [Example component in Python](https://github.com/viamrobotics/viam-python-sdk/blob/main/examples/complex_module/src/gizmo/api.py)
- [Example service in Python](https://github.com/viam-labs/speech-service-api/blob/main/src/speech_service_api/api.py)

1. In the root directory of your module, you need to generate some configuration files.
You will typically need the following three files for most modules, though different files are required for some advanced use cases.
See the [Buf documentation](https://buf.build/docs/generate/usage/) for instructions.

- [<file>buf.yaml</file>](https://buf.build/docs/configuration/v1/buf-gen-yaml/)
- [<file>buf.gen.yaml</file>](https://buf.build/docs/configuration/v1/buf-gen-yaml/)
- [<file>buf.lock</file>](https://buf.build/docs/configuration/v1/buf-lock/)

1. In the <file>/src/</file> directory of your module, use the protobuf compiler to [generate](https://buf.build/docs/tutorials/getting-started-with-buf-cli/#generate-code) all other necessary protocol buffer code, based on the `<subtype name>.proto` file you wrote.

- [Example generated files for a Python-based service](https://github.com/viam-labs/speech-service-api/tree/main/src/proto).
The `buf.` files were generated.
The <file>speech.proto</file> was manually written.

## Next steps

{{< cards >}}
{{% manualcard link="/operate/get-started/other-hardware/" %}}

<h4>Implement your API</h4>

Now that your resource API is defined, create a new model that implements your new API.

{{% /manualcard %}}
{{< /cards >}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
title: "Add Custom Components as Remote Machine Parts"
linkTitle: "Custom Components as Remote Parts"
weight: 99
type: "docs"
tags: ["server", "sdk"]
aliases:
- /program/extend/sdk-as-server/
- /program/extend/custom-components-remotes/
- /extend/custom-components-remotes/
- /modular-resources/advanced/custom-components-remotes/
- /registry/advanced/custom-components-remotes/
description: "If you are unable to use modular resources, you can implement custom components and register them on a server configured as a remote of your machine."
date: "2022-01-01"
# updated: "" # When the content was last entirely checked
---

Running {{< glossary_tooltip term_id="modular-resource" text="modular resources" >}} on the computer directly connected to your components is the preferred way of managing and controlling custom components.

However, if you are unable to use [modular resources](/operate/get-started/other-hardware/) because you need to host `viam-server` on a non-Linux system or have an issue with compilation, you can use a [Viam SDK](/dev/reference/sdks/) to code a custom resource implementation, host it on a server, and add it as a [remote part](/operate/reference/architecture/parts/) of your machine.

Once you have coded your custom component and configured the remote servers, you can control and monitor your component with the Viam SDKs, like any other component.

To show how to create a custom resource, the following example creates an arm as a custom component and registers the new arm model with a Viam SDK.
Then you can control it as part of your machine with the same [API methods](/dev/reference/apis/components/arm/#api) available for [arm models built into the RDK](/operate/reference/components/arm/#configuration).

## Instructions

To add a custom resource as a [remote part](/operate/reference/architecture/parts/):

{{< tabs >}}
{{% tab name="Go" %}}

1. Code a new model of a built-in resource type.
You can do this by creating a new interface that implements required methods.
The new model must implement any functions of the built-in resource type marked as required in its [RDK API definition](/dev/reference/apis/).
2. Register the custom component on a new gRPC server instance and start the server.
3. Add the server as a [remote part](/operate/reference/architecture/parts/) of your machine.
4. (Optional) [Configure a process](/manage/reference/processes/) to launch this remote server to ensure the remote server is always running alongside the rest of your machine.

Each remote server can host one or many custom components.

{{% /tab %}}
{{% tab name="Python" %}}

{{< alert title="Tip" color="tip" >}}
For more detailed instructions, see the full example in the [Python SDK documentation](https://python.viam.dev/examples/example.html#subclass-a-component).
{{< /alert >}}

1. Code a new model of a built-in resource type.
You can do this by subclassing a built in resource type like `sensor` or `arm`.
The new model must implement any methods of the built-in resource type marked as required in its [RDK API definition](/dev/reference/apis/).
1. Register the custom component on a new gRPC server instance and start the server.
You can do this with the [`viam.rpc` library](https://python.viam.dev/autoapi/viam/rpc/index.html) by creating a new `rpc.server.Server` instance.
1. Add the server as a [remote part](/operate/reference/architecture/parts/) of your machine.
1. (Optional) [Configure a process](/manage/reference/processes/) to launch this remote server to ensure the remote server is always running alongside the rest of your machine.

Each remote server can host one or many custom components.

{{% /tab %}}
{{% /tabs %}}

{{% alert title="Important" color="note" %}}

You must define all methods belonging to a built-in resource type when defining a new model.
Otherwise, the class will not instantiate.

- If you are using the Python SDK, raise an `NotImplementedError()` in the body of functions you do not want to implement or put `pass`.
- If you are using the Go SDK, return `errUnimplemented`.
- Additionally, return any values designated in the function's return signature, typed correctly.

{{% /alert %}}
Loading

0 comments on commit c06f0a8

Please sign in to comment.