Aito SDK

The Aito SDK consists of:

  • schema: Data structure for the Aito Database Schema

  • v1: The v1 API client to make requests to an Aito Database Instance

  • v2: A client for the Aito v2 API

  • requests: Request objects used in AitoClient request so that you don’t have to worry about the Aito API endpoint

  • responses: Enriched response objects returned after executing a request with the AitoClient

  • api: Different useful functions that uses an AitoClient object to interact with an Aito Database Instance

  • DataFrameHandler: Utility to read, write, and convert a Pandas DataFrame in accordance to a Aito Table Schema

Note

We highly recommend you to take a look at the quickstart guide to uploading data if you haven’t already.

AitoSchema

Before uploading data into Aito, you need to create a table with a AitoTableSchema.

You can infer a table schema from a Pandas DataFrame with infer_from_pandas_data_frame().

You can also create a table schema column-by-column and infer the AitoColumnTypeSchema with infer_from_samples().

AitoClient

The AitoClient offers different functions to send a Request object to your Aito instance.

Choosing an API version

Each Aito API version has its own package, whose meaning never changes:

from aito.v1 import Client   # the v1 API: /api/v1
from aito.v2 import Client   # the v2 API: /api/v2

aito.Client is the one name that follows the default version. It moves only on a major release of aitoai, so the major version tells you which API it is: 1.x is v2 (0.x was v1). Use aito.Client in quick experiments; in production code import the explicit version, so an upgrade cannot change the API underneath it. To stay on v1, import from aito.v1 import Client, or pin aitoai<1.

Before 0.7 the v1 client lived in aito.client and the helpers in aito.api, and the v2 client in aito.client.v2. Those paths were deprecated in 0.7 and removed in 1.0: importing one raises an ImportError that names its replacement (aito.v1, aito.v2, aito.v1.api).

The aito command-line tool still talks to the v1 API throughout 1.x (it imports aito.v1 explicitly, so the default switch does not move it). v2 support arrives as an opt-in in a 1.x minor release; the CLI’s default moves to v2 only in 2.0.

A bare pip install aitoai installs the API clients only. The command-line tool, schema inference and file conversion need pip install 'aitoai[cli]'.

AitoClientV2

The AitoClientV2 talks to the v2 API. It is a separate class from the v1 AitoClient rather than a flag on it, because the two APIs return genuinely different response shapes — the reasoning is written up in docs/v2-client-design.md.

from aito.v2 import Client

# the public read-only sandbox; use your own instance URL and key in production
client = Client('https://shared.aito.ai/db/aito-demo',
                'yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi', env='v2')

prediction = client.predict(
    from_table='invoices', where={'Description': 'cloud services'}, predict='GLCode')
print(prediction.first.value, prediction.first.probability)   # E002 0.83...

A predict ranks every value of the field; the evidence in where changes each candidate’s probability but never removes one. To return only the values actually seen with the evidence, filter on the per-candidate frequency $f with having, via query():

seen = client.query({
    'from': 'invoices',
    'where': {'Processor': 'Emily Davis'},
    'predict': 'GLCode',
    'select': ['$value', '$p', '$f'],
    'having': {'$f': {'$gte': 1}},
})
print([(hit.value, hit['$f']) for hit in seen])   # [('F001', 20)]

having filters the ranked list after scoring: the remaining $p values are not renormalised, and $f is the only field it accepts — {'$f': {'$gte' | '$gt' | '$lte' | '$lt': <number>}}. Filtering on anything else, such as $p, is a 400 request.invalid.

Querying:

Note

The named methods post to v2’s enforced named endpoints, which validate that the body matches the operation. A mismatch is a 400 naming the endpoint that wants that body, rather than a query that silently does something else.

Manipulating the database:

Note

These operations require the client to be setup with the READ-WRITE API key

Errors carry a machine-readable code, so you branch on the code rather than on the text of the message:

from aito.v2 import Error

try:
    client.delete_collection('invoices')
except Error as err:
    if not err.is_not_found:   # a 404 here is the ordinary "drop if exists" case
        raise

Responses carry the engine’s non-fatal warnings, which are the only in-band signal that the server answered a slightly different query than the one you sent:

res = client.query({'from': 'invoices', 'where': {'no_such_column': 'x'}})
for warning in res.warnings:
    print(warning.code, warning.message)

# or make it a hard failure:
strict = Client(instance_url, api_key, on_warning='raise')

Aito reports its own server-side processing time in the x-aitoai-response-time header, which is what an application should surface rather than the round trip. The parsed body does not carry it, so pass on_response:

timings = []
client = Client(instance_url, api_key,
                      on_response=lambda resp, path: timings.append(
                          (path, float(resp.headers['x-aitoai-response-time']))))

A complete runnable example — create a collection, load it, predict, explain, evaluate, drop it — is in examples/v2_quickstart.py.

AitoAPI

aito.v1.api module offers different functions that takes a Aito Client object as the first argument

Troubleshooting

The easiest way to troubleshoot the Aito SDK is by enabling the debug logging. You can enable the debug logging by:

import logging

logging.basicConfig(level=logging.DEBUG)