Python SDK (v2)

aitoai is the official Python client. It ships a client for the v2 API โ€” available since aitoai 0.7.0 โ€” alongside the v1 client, and a command-line tool. Every snippet on this page that talks to the sandbox runs as written.

Install

pip install aitoai

That installs the API clients only (requests, packaging, jsonschema, aiohttp, ndjson). The command-line tool, schema inference and file conversion need the dataframe toolchain, which is an extra (since aitoai 0.7.0):

pip install 'aitoai[cli]'

Pick the API version

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

from aito.v2 import Client      # the v2 API
from aito.v1 import Client      # the v1 API

aito.Client is the default version, and moves only on a major release of the package: since aitoai 1.0.0 it is the v2 client (0.x: v1). It is fine for a quickstart; production code should import the version it means, so an SDK upgrade cannot change the API underneath it.

The pre-0.7 paths (aito.client.AitoClient, aito.client.v2.AitoClientV2, aito.api) were removed in aitoai 1.0.0: importing one raises an ImportError that names the replacement. To stay on the v1 API, from aito.v1 import Client, or pin aitoai<1.

Connect

from aito.v2 import Client

client = Client('https://shared.aito.ai/db/aito-demo',
                'yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi', env='v2')
print(client.get_version()['version'])

The first argument is the database URL (โ€ฆ/db/<name>), not an endpoint. env selects an environment; leave it out for master. The client checks the key on construction, so a wrong URL or key fails here rather than on the first query.

Query and predict

Each operation is a method that posts to its own endpoint and returns a parsed response. A predicted value is hit.value, its probability hit.probability:

from aito.v2 import Client

client = Client('https://shared.aito.ai/db/aito-demo',
                'yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi', env='v2')

res = client.predict(from_table='invoices',
                     where={'Description': {'$match': 'cloud services'}},
                     predict='GLCode', limit=3, why=True)
top = res.first
print(top.value, round(top.probability, 3))
print(top.why['type'])             # the explanation tree, as in the curl examples

rows = client.query({'from': 'products', 'where': {'name': {'$match': 'milk'}},
                     'select': ['name', 'price'], 'limit': 2})
for row in rows:
    print(row['name'], row['price'])

The other operations follow the same shape: search, recommend, match, relate, estimate, aggregate, evaluate and batch, plus query for any body the universal _query endpoint accepts (that is also the way to send an operation the client has no method for). get_schema() reads the schema, and delete_collection(name) drops a collection.

Errors and warnings

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

from aito.v2 import Client, Error

client = Client('https://shared.aito.ai/db/aito-demo',
                'yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi', env='v2')
try:
    client.predict(from_table='invoices', predict='no_such_field')
except Error as err:
    print(err.status_code, err.code)

Responses also carry the engine's non-fatal warnings โ€” the only signal that it answered a slightly different query than the one you sent (an unknown field in where, say). They are logged by default; on_warning='raise' makes them errors:

from aito.v2 import Client

client = Client('https://shared.aito.ai/db/aito-demo',
                'yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi', env='v2')
res = client.query({'from': 'invoices', 'where': {'no_such_column': 'x'}})
for warning in res.warnings:
    print(warning.code)

Load your own data

Writes need a read-write key for your own instance (the sandbox is read-only โ€” ask for an instance). Declare a collection, upload rows in batches, then optimize once after the bulk load:

from aito.v2 import Client

client = Client('https://your-instance.aito.ai/db/your-db', '<read-write-key>')

client.create_collection('invoices', {
    'vendor': {'type': 'String'},
    'description': {'type': 'Text', 'analyzer': 'english'},
    'amount': {'type': 'Decimal'},
    'gl_code': {'type': 'String'},
})
client.upload_entries('invoices', rows, batch_size=1000)   # rows: a list of dicts
client.optimize('invoices')

To try a change without touching master, branch an environment with client.branch_env('staging') and point a client at it with env='staging'; see Environments. The SDK repository's examples/v2_quickstart.py does the whole round trip โ€” create, load, predict, explain, evaluate, drop.

Versions

aitoaiWhat changed for v2 users
0.6.0First v2 client (aito.client.v2.AitoClientV2)
0.7.0aito.v2 / aito.v1 packages and the default aito.Client; the CLI toolchain moved to the [cli] extra
1.0.0aito.Client is v2; the pre-0.7 import paths are removed (the CLI stays on v1 through 1.x)

The full history is in the changelog.