Skip to content
JeffHub

Python and TypeScript clients

Call a Jeff server from Python or TypeScript, choose an adapter by name, and handle errors.

Both clients speak the same request format, refuse number-like option keys, and never retry or guess. Choose an adapter with model: on the client, or on any single call. The examples below use the base model zero-shot (jeff-latest); name an adapter, such as support-intents, to use it instead.

The clients arrive with the next Jeff release. The Python client is part of the jeff package (src/jeff/client.py) and needs only the standard library. The TypeScript client (@jeff/client, clients/typescript) has no dependencies and runs in Node 22 or later, Deno, Bun and browsers. It is not on npm yet: build it from the repository and depend on it by path.

Python

from jeff import Client
from jeff.client import choice_question, yes_no_question

jeff = Client("http://localhost:8765", model="jeff-latest")

answers = jeff.ask(
    {"company": "An online furniture shop.", "channel": "email",
     "message": "My wardrobe arrived with two doors split. I want a replacement."},
    {
        "route": choice_question(
            {"other": "Not for any of these teams", "k1": "Deliveries", "k2": "Refunds and payments"},
            "Which team should handle this message? If it covers several issues, choose the team for the most important one.",
        ),
        "needs_human": yes_no_question("Does this need a person to act on it now, rather than an automatic reply? Answer yes for complaints that could escalate, legal or safety issues, or requests an automatic system cannot resolve."),
    },
)
print(answers.choice("route").key, answers.yes_no("needs_human"))

One question at a time: jeff.choose(state, options, instructions), jeff.yes_no(state, instructions) and jeff.score(state, levels, instructions). AsyncClient has the same calls for asyncio.

TypeScript

import { Client, choiceQuestion, yesNoQuestion } from '@jeff/client';

const jeff = new Client({ url: 'http://localhost:8765', model: 'jeff-latest' });

const { route, needs_human } = await jeff.ask(
  { company: 'An online furniture shop.', channel: 'email', message: 'My wardrobe arrived with two doors split.' },
  {
    route: choiceQuestion(
      { other: 'Not for any of these teams', k1: 'Deliveries', k2: 'Refunds and payments' },
      'Which team should handle this message? If it covers several issues, choose the team for the most important one.',
    ),
    needs_human: yesNoQuestion('Does this need a person to act on it now, rather than an automatic reply? Answer yes for complaints that could escalate, legal or safety issues, or requests an automatic system cannot resolve.'),
  },
);
console.log(route.key, route.probability, needs_human);

Several adapters from one program

One client per adapter, all talking to the same server:

clauses = Client("http://localhost:8765", model="legal-clauses")
intents = clauses.with_model("support-intents")
spam = clauses.with_model("spam")

In TypeScript: jeff.withModel('spam'). Every call also takes a model argument to override the client's for that one request.

Other calls

Python TypeScript Does
prepare(state, questions) prepare(state, questions) Sends the unchanging part ahead of time; see preparing requests
decide(request) decide(request) Sends a raw request and returns the raw response
health() health() Whether the model is loaded, its name and its option limit
models() models() Every model name the server answers to, adapters included

Passing orders=2 answers every question twice, the second time with the options reversed, and averages the two. It evens out a small model's lean towards options by position, at twice the cost.

Errors

Every failure raises (Python) or throws (TypeScript) a subclass of JeffError carrying the status, the server's explanation and the request id: Unauthorised, UnknownModel, TooManyOptions, InvalidRequest, NotReady, Busy (with retry_after / retryAfter), ServerError, ConnectionFailed and ProtocolError. Retry Busy yourself if that suits you.

Next: Serving several adapters