Skip to content

Using the SDK

Interfaces

An interface defines the shape of a function's answer, so functions answering the same kind of question can be used the same way. Every function implements exactly one. These are the interfaces in this version:

InterfaceWhat it asksvalue is
classifyChoose one label from a defined set of labels.a label key
routeChoose which candidate (a team, a tool, a screen item, or another function) should handle the input.a label key
ratePlace the input on an ordered scale of levels.the level's index, from 0; score holds the expected level
detectSay whether the input is an instance of the thing the function detects.true or false
is_supportedJudge whether an answer is supported by its sources, using only the sources.supported, partly_supported, contradicted or unsupported
equivalentJudge whether two records describe the same entity.match, possible_match or no_match
requires_escalationSay whether a person must act on the input now.true or false

The catalogue lists which functions implement each one:

import jeff

catalogue = jeff.Catalogue.shipped()

for interface in ["classify", "route", "rate", "detect", "is_supported", "equivalent", "requires_escalation"]:
    functions = [function.id for function in catalogue.implementing(interface)]

    print(f"{interface}: {len(functions)} functions, for example {functions[0]}")

The shorthand methods

Each interface has a method of the same name on the client:

text
client.classify(input, *, function=None, context=None, labels=None, on_low_confidence="return")

The same applies to route, rate, detect, is_supported, equivalent and requires_escalation, named according to each language's conventions (isSupported in Node and Java, IsSupportedAsync in C#). Each makes one call and returns one Decision. The function to call is named by any reference Functions accepts: as function among the options in Python, Node and C# (ShorthandOptions in Rust and C#), and as the second argument in Java (jeff.rate(input, "triage.urgency", options)). A function that implements another interface raises InterfaceMismatch, naming the method to use instead. The context, labels and policy work as they do when binding a function.

import os

import jeff

shop = {"company": "A furniture shop.", "channel": "email"}

message = "My wardrobe arrived with a broken door and I need it replaced before Friday."

with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client:

    team = client.route(message, function="triage.route", context=shop,
                        labels={"deliveries": "Deliveries and damaged goods", "refunds": "Refunds and returns"})

    urgency = client.rate(message, function="triage.urgency", context=shop)

    needs_human = client.requires_escalation(message, function="triage.needs_human", context=shop)

    kind = client.classify(message, function="guard.kind",
                           context={"application": "A support assistant for a furniture shop.", "source": "email body"})

    print("team:", team.value)

    print("urgency level:", urgency.value, "expected level:", round(urgency.score, 2))

    print("a person must act now:", needs_human.value)

    print("kind of text:", kind.value)

A shorthand is the quickest way to make a single call. To call the same function many times with the same context, bind it once instead: the context is then checked once, not on every call.

Without a function: dispatch

Leaving the function out hands the input to client.dispatch(input, *, interface, context=None, labels=None, router="jeff.core.router", on_low_confidence="return"), which asks a tree of trained router functions which function should answer, then calls it. The decision's route lists each router's choice. Dispatch needs the router's manifest in the client's catalogue. The catalogue included with each package contains no such router (its one router, jeff.routing.router-open, picks from a menu you send it and is called like any other function: see The swarm). With this catalogue, a shorthand without a function (or a call to dispatch) raises UnknownFunction, with a message explaining that no router is available and that a function must be specified. Over HTTP, the server can route a request itself: see Functions and /v1/decide.

Next steps

  • Graphs: several functions wired together, with conditions.
  • Escalation: what on_low_confidence can do.