from sixtydb import SixtyDBClient# Simple initializationclient = SixtyDBClient('your-api-key')# With custom base URLclient = SixtyDBClient('your-api-key', base_url='https://api.60db.ai')# Get all voicesvoices = client.get_voices()# Get all languageslanguages = client.get_languages()
Supply a context string to enable server-side LLM polishing — proper nouns, filler removal, and punctuation are cleaned on the response text:
with open('audio.mp3', 'rb') as audio_file: result = client.speech_to_text( audio_file, language='hi', diarize=True, context='Cricket coaching session. Players: Arjun Mehta, Ishaan Verma. Discussing batting technique.', ) print(result['text'])
Omit context entirely to skip refinement. Note: this is the REST shape — the WebSocket streaming endpoint takes a {general, text, terms} object instead.
response = client.chat.completion( model='60db-tiny', messages=[{'role': 'user', 'content': 'How can I improve my English?'}])print(response['choices'][0]['message']['content'])# Streamingfor chunk in client.chat.completion( messages=[{'role': 'user', 'content': 'Tell me a short story'}], stream=True): print(chunk['choices'][0]['delta'].get('content') or '', end='')# Text correction modefixed = client.chat.completion( text='hello how r u', dictionary=[{'term': 'u', 'replacement': 'you'}], app_context='email')# OpenAI-style aliasresponse = client.chat.completions.create(model='60db-tiny', messages=[...])
client.memory.ingest(text='I prefer vegetarian food', type='user', infer=True)client.memory.extract_document('handbook.pdf', collection='company_handbook', type='knowledge')results = client.memory.search(query='What are my dietary preferences?', max_results=5)ctx = client.memory.context(query='What do you know about me?', top_k=8)print(ctx['data']['prompt_ready'])usage = client.memory.usage()
Scores content against a rubric you define, and parses conversational turns.
A classifier, not a generator — every answer is a probability distribution over
your options.Authenticated with the same 60db API key as the rest of the SDK — the client
you already constructed works; there is no separate Judge credential.
run = client.judge.evaluate( state=call_transcript, questions={ "tone": { "type": "choice", "instructions": "How did the agent come across?", "criteria": { "professional": "Calm, courteous, takes ownership", "dismissive": "Brushes the caller off", "unknown": "Not enough of the call to tell", # always add an escape hatch }, }, "satisfaction": {"type": "score", "criteria": ["Angry", "Neutral", "Happy"]}, "resolved": {"type": "noul", "instructions": "Was it solved?"}, },)run["answers"]["tone"]["choice"] # 'dismissive'run["answers"]["tone"]["probabilities"] # {'dismissive': 0.86, 'professional': 0.11, ...}run["answers"]["satisfaction"]["score"] # 1.87 — weighted, not an indexrun["answers"]["resolved"]["noul"] # 0.28 — probability of true, not a confidencerun["min_confidence"] # under 0.85 → send to a humanrun["credits_charged"]
turn = client.judge.extract( text="move my 10am appointment to friday", schema={ "intents": {"booking": "Wants to arrange or change a booking"}, "operations": {"reschedule": "Move an existing booking"}, "entities": {"date": "A calendar date", "time": "A clock time"}, # "responsePaths": {"confirm": "Read the change back"} ← selects the v2 model },)turn["intent"]["label"] # 'booking'turn["entities"] # [{'label': 'date', 'text': 'friday', 'start': 28, 'end': 34, ...}]
start/end are Unicode code point offsets. Slice
"".join(list(text)[start:end]), not text[start:end] — the naive version
lands in the wrong place once the turn contains an emoji.
page = client.judge.runs.list(needs_review=True, limit=20)page["runs"] # only runs the judge was under 85% sure aboutpage["pagination"] # {'total': ..., 'limit': ..., 'has_more': ...}client.judge.runs.get(run_id) # one run, with what was sent and returnedclient.judge.runs.delete(run_id)
Billed per input token. The upstream re-encodes the shared content once per
question, so a 10-question rubric costs ten times the transcript. Context is
200,000 tokens per question; an over-long request raises a 400 before anything
is charged (in practice the 512 KiB whole-request cap binds first).Failed runs — 429 busy, 503 unavailable, 400 invalid rubric — are
refunded automatically.