Interacting with Tesseracts

Viewing running Tesseracts

To list all running Tesseracts:

$ tesseract ps

The output is a table showing each container’s ID, name, version, host port, project ID, and description:

┏━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ID            Name       Version  Host Port  Project ID              Description                               ┃
┡━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 997fca92ea37  vectoradd  1.2.3    56434      tesseract-afn60xa27hih  Simple tesseract that adds two vectors.\n │
└──────────────┴───────────┴─────────┴───────────┴────────────────────────┴───────────────────────────────────────────┘
  • Host Port — the port to use when calling the Tesseract’s endpoints.

  • Project ID — pass this to tesseract teardown to stop all containers in that project.

Invoking a Tesseract

Every Tesseract’s core operation is apply — this could be a neural network forward pass, a simulation step, or any other computation.

$ tesseract run vectoradd apply @examples/vectoradd/example_inputs.json
{"result":{"object_type":"array","shape":[3],"dtype":"float64","data":{"buffer":[5.0,7.0,9.0],"encoding":"json"}}}

Where example_inputs.json contains:

example_inputs.json
{
  "inputs": {
    "a": {
      "object_type": "array",
      "shape": [3],
      "dtype": "int64",
      "data": {
        "buffer": [1, 2, 3],
        "encoding": "json"
      }
    },
    "b": {
      "object_type": "array",
      "shape": [3],
      "dtype": "int64",
      "data": {
        "buffer": [4, 5, 6],
        "encoding": "json"
      }
    }
  }
}

The @ prefix tells the CLI to read input from a file. For small payloads, you can also pass JSON inline:

$ tesseract run vectoradd apply '{"inputs": {"a": ..., "b": ...}}'

Make sure the Tesseract is running (docker ps), or launch it with tesseract serve vectoradd.

Then call its /apply endpoint:

$ curl http://<tesseract-address>:<port>/apply \ # Replace with actual address
  -H "Content-Type: application/json" \
  -d @examples/vectoradd/example_inputs.json
{"result":{"object_type":"array","shape":[3],"dtype":"float64","data":{"buffer":[5.0,7.0,9.0],"encoding":"json"}}}

Where the payload posted to /apply is:

example_inputs.json
{
  "inputs": {
    "a": {
      "object_type": "array",
      "shape": [3],
      "dtype": "int64",
      "data": {
        "buffer": [1, 2, 3],
        "encoding": "json"
      }
    },
    "b": {
      "object_type": "array",
      "shape": [3],
      "dtype": "int64",
      "data": {
        "buffer": [4, 5, 6],
        "encoding": "json"
      }
    }
  }
}
>>> import numpy as np
>>> from tesseract_core import Tesseract
>>>
>>> a = np.array([1.0, 2.0, 3.0])
>>> b = np.array([4.0, 5.0, 6.0])
>>>
>>> with Tesseract.from_image(image="vectoradd") as vectoradd:
>>>     vectoradd.apply({"a": a, "b": b})
{'result': array([5., 7., 9.])}

The Tesseract context manager starts the container locally and tears it down when the context exits.

Tip

To connect to a remote Tesseract, use Tesseract.from_url(...).

This Tesseract returns the vector sum a + b in the result output field.

Optional endpoints and differentiation

If a Tesseract is differentiable, its derivative endpoints work the same way. For example, computing the Jacobian of result with respect to a at \(a = (1,2,3)\), \(b = (4,5,6)\):

$ tesseract run vectoradd jacobian @examples/vectoradd/example_jacobian_inputs.json
{"result":{"a":{"object_type":"array","shape":[3,3],"dtype":"float64","data":{"buffer":[[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]],"encoding":"json"}}}}
$ curl -d @examples/vectoradd/example_jacobian_inputs.json \
  -H "Content-Type: application/json" \
  http://<tesseract-address>:<port>/jacobian
{"result":{"a":{"object_type":"array","shape":[3,3],"dtype":"float64","data":{"buffer":[[1.0,0.0,0.0],[0.0,1.0,0.0],[0.0,0.0,1.0]],"encoding":"json"}}}}

The payload we posted contains information about which inputs and outputs we want to consider when computing derivatives:

example_jacobian_inputs.json
{
  "inputs": {
    "a": {
      "object_type": "array",
      "shape": [3],
      "dtype": "int64",
      "data": {
        "buffer": [1, 2, 3],
        "encoding": "json"
      }
    },
    "b": {
      "object_type": "array",
      "shape": [3],
      "dtype": "int64",
      "data": {
        "buffer": [4, 5, 6],
        "encoding": "json"
      }
    }
  },
  "jac_inputs": ["a"],
  "jac_outputs": ["result"]
}
>>> import numpy as np
>>> from tesseract_core import Tesseract
>>>
>>> a = np.array([1.0, 2.0, 3.0])
>>> b = np.array([4.0, 5.0, 6.0])
>>>
>>> with Tesseract.from_image("vectoradd") as vectoradd:
>>>     vectoradd.jacobian({"a": a, "b": b}, jac_inputs=["a"], jac_outputs=["result"])
{'result': {'a': array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])}}

The output is a 3x3 identity matrix, as expected.

To check which endpoints a Tesseract supports, use the /docs endpoint of a running Tesseract, tesseract apidoc, or the Python SDK:

>>> with Tesseract.from_image("vectoradd") as vectoradd:
...     print(vectoradd.available_endpoints)
['apply', 'jacobian', 'health']

OpenAPI schemas for programmatic parsing

Each Tesseract has a unique input/output signature. To retrieve the schema programmatically:

$ tesseract run vectoradd openapi-schema
$ curl <tesseract-address>:<port>/openapi.json
>>> from tesseract_core import Tesseract
>>> with Tesseract.from_image("vectoradd") as vectoradd:
>>>     schema = vectoradd.openapi_schema

Schemas are returned in OpenAPI format, designed for programmatic parsing. For a human-readable view, use the /docs endpoint of a running Tesseract or run tesseract apidoc <tesseract-name>.

The OpenAPI schema includes all endpoints, though they are all derived from the /apply input/output schemas.