Skip to content

Latest commit

 

History

History
343 lines (261 loc) · 12.1 KB

File metadata and controls

343 lines (261 loc) · 12.1 KB

Interfaze Python SDK

The official Interfaze SDK for Python

Docs · limits · pricing · dashboard · TypeScript / JavaScript SDK

Install

pip install interfaze
# or: uv add interfaze · poetry add interfaze

Setup

from interfaze import Interfaze

interfaze = Interfaze(api_key="sk_...")  # or set INTERFAZE_API_KEY and call Interfaze()

Async is identical via AsyncInterfaze - every call becomes await-able.

Your first request

This guide will get you started with your first request to Interfaze, which follows the Chat Completions API standard.

import json
from interfaze import Interfaze, response_format

interfaze = Interfaze()

res = interfaze.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Extract the details from this ID."},
                {"type": "image_url", "image_url": {"url": "https://r2public.jigsawstack.com/interfaze/examples/id.jpg"}},
            ],
        },
    ],
    response_format=response_format(
        {
            "type": "object",
            "properties": {
                "first_name": {"type": "string"},
                "last_name": {"type": "string"},
                "dob": {"type": "string", "description": "Date of birth on the ID"},
                "licence_number": {"type": "string"},
            },
            "required": ["first_name", "last_name", "dob", "licence_number"],
        },
        "id_card",
    ),
)

id_card = json.loads(res.choices[0].message.content or "{}")
print(id_card)
print("OCR result:", res.precontext[0].result if res.precontext else None)  # the raw OCR that produced it

Precontext

Alongside the answer, a response carries precontext - the raw metadata Interfaze produced while answering:

for p in res.precontext or []:
    print(p.name, p.result)  # e.g. "ocr" -> { text, boxes, confidence, … }

Chat

res = interfaze.chat.completions.create(
    messages=[{"role": "user", "content": "Which US public companies reported earnings today?"}],
)

res.choices[0].message.content

The result is a standard ChatCompletion with precontext and reasoning added (a web search backs the answer here).

Streaming

Stream the reply as it's generated; the final completion still carries precontext and reasoning.

stream = interfaze.chat.completions.stream(
    messages=[{"role": "user", "content": "Summarize this week's top AI research and cite your sources."}],
)

for text in stream.text_deltas():
    print(text, end="", flush=True)

final = stream.get_final_completion()  # .precontext (the sources), .reasoning

text_deltas() yields display-ready text - the inline <think>/<precontext> side-channels are stripped and returned structured on get_final_completion(). Iterate the stream directly (for event in stream) for typed events, or create(stream=True) for the raw chunk iterator.

Structured output

response_format() takes a JSON Schema and normalizes it for Interfaze:

import json
from interfaze import inputs, response_format

res = interfaze.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Extract this receipt."},
                inputs.image("https://jigsawstack.com/preview/vocr-example.jpg"),
            ],
        },
    ],
    response_format=response_format(
        {
            "type": "object",
            "properties": {
                "merchant": {"type": "string"},
                "total": {"type": "number"},
                "items": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {"name": {"type": "string"}, "price": {"type": "number"}},
                    },
                },
            },
            "required": ["merchant", "total", "items"],
        },
        "receipt",
    ),
)

receipt = json.loads(res.choices[0].message.content or "{}")  # {"merchant": ..., "total": ..., "items": [...]}

message.content comes back as a JSON string, so parse it - and keep the root an object, since a non-object root is wrapped under a result key. Prefer Pydantic? Use interfaze.chat.completions.parse(response_format=YourModel, …) and read choices[0].message.parsed.

Tools and function calling

Interfaze supports tools - define tools, read message.tool_calls, run them, then pass the results back for the final answer.

import json

def get_weather(city: str) -> str:
    return json.dumps({"city": city, "temp_c": 21, "condition": "clear"})

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather for a city.",
            "parameters": {
                "type": "object",
                "properties": {"city": {"type": "string", "description": "e.g. Tokyo"}},
                "required": ["city"],
            },
        },
    },
]

messages = [{"role": "user", "content": "What's the weather in Tokyo?"}]
res = interfaze.chat.completions.create(messages=messages, tools=tools, tool_choice="auto")

message = res.choices[0].message
messages.append(message.model_dump())  # the assistant turn, carrying any tool_calls

for call in message.tool_calls or []:
    args = json.loads(call.function.arguments)
    messages.append({"role": "tool", "tool_call_id": call.id, "content": get_weather(args["city"])})

final = interfaze.chat.completions.create(messages=messages, tools=tools, tool_choice="auto")

Reasoning

Ask for reasoning with reasoning_effort; the text comes back on res.reasoning.

res = interfaze.chat.completions.create(
    reasoning_effort="high",  # also accepts Interfaze's "on" / "off" / "auto"
    messages=[{"role": "user", "content": "Which region should we launch in first, and why?"}],
)

res.reasoning  # reasoning text - present with reasoning_effort and no schema

Multimodal Inputs

Interfaze handles images, PDFs, audio, video, and CSV. The simplest way is to drop a public URL into the prompt - Interfaze fetches and reads it:

interfaze.chat.completions.create(
    messages=[{"role": "user", "content": "Summarize this document: https://arxiv.org/pdf/1706.03762"}],
)

Or attach it as a content part - a file part for documents, audio, and video; image_url for images:

interfaze.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "Summarize this document."},
                {"type": "file", "file": {"filename": "paper.pdf", "file_data": "https://arxiv.org/pdf/1706.03762"}},
            ],
        },
    ],
)

file_data also takes a base64 data URI:

{"type": "file", "file": {"filename": "report.pdf", "file_data": f"data:application/pdf;base64,{base64}"}}

inputs.* is a typed shortcut that builds these parts - and turns raw bytes or a local file into a data URI for you:

from interfaze import inputs

inputs.image("https://…/photo.png")                                       # image_url part
inputs.file("https://…/report.pdf")                                       # file part
inputs.audio("https://…/call.wav")                                        # input_audio part
inputs.file(inputs.data_url(pdf_bytes, "application/pdf"), filename="report.pdf")  # from raw bytes
inputs.image(inputs.from_path("./photo.png"))                             # read a local file

Interfaze rejects image/gif and image/avif client-side.

Tasks

A task (run_task) runs one built-in tool instead of the full model - faster and cheaper, but limited to that tool and its fixed output structure. So task can't be combined with a custom response_format; reach for a full completion (like your first request) when you need the whole model or your own schema.

The tasks.* helpers are the shortest way - each takes a source and returns the raw result:

interfaze.tasks.ocr(url)
interfaze.tasks.object_detection(url)
interfaze.tasks.gui_detection(url)
interfaze.tasks.web_search(query)
interfaze.tasks.scrape(url)
interfaze.tasks.transcribe(url)
interfaze.tasks.translate(text, to="Spanish")
interfaze.tasks.forecast(csv_url, periods=30, unit="days")

For a multi-part message (text plus an input), set task on a normal create call - the result comes back on message.content:

import json

res = interfaze.chat.completions.create(
    task="ocr",
    messages=[{"role": "user", "content": [{"type": "text", "text": "Extract the total."}, inputs.image(url)]}],
)
result = json.loads(res.choices[0].message.content or "{}").get("result")  # same output as tasks.ocr()

Or a <task>…</task> system message plus an empty response schema:

import json
from interfaze import empty_task_schema

res = interfaze.chat.completions.create(
    messages=[
        {"role": "system", "content": "<task>ocr</task>"},
        {"role": "user", "content": [{"type": "text", "text": "Extract the total."}, inputs.image(url)]},
    ],
    response_format=empty_task_schema(),  # an empty JSON schema
)
result = json.loads(res.choices[0].message.content or "{}").get("result")

Guardrails

Enable safety categories with guard; a blocked request comes back as a normal completion, not an exception.

res = interfaze.chat.completions.create(
    guard=["S1", "S10", "S12_IMAGE"],
    messages=[{"role": "user", "content": "..."}],
)

A match returns the plain string unsafe S1 as message.content - so check for it. See the exported GUARD_CODES.

Client options

Set router, cache, and streaming behavior once on the client:

interfaze = Interfaze(
    show_additional_info=True,  # stream <precontext> deltas as they're produced
    bypass_moe=True,            # skip the mixture-of-experts router
    bypass_cache=True,          # skip the semantic cache
)

Errors

Interfaze re-exports typed error classes to catch and narrow on:

from interfaze import BadRequestError, InterfazeError, RateLimitError

InterfazeError is client-side (missing key, invalid guard code, stream misuse). Everything else is an APIError subclass carrying status_code and code - BadRequestError (400), AuthenticationError (401), RateLimitError (429), and so on.

Capabilities

Use case Entry point
Chat chat.completions.create
Streaming chat.completions.stream
Structured output response_format()
Reasoning reasoning_effort
Tools tools
Multimodal inputs inputs.*
OCR tasks.ocr
Object and GUI detection tasks.object_detection, tasks.gui_detection
Web search and scraping tasks.web_search, tasks.scrape
Speech to text tasks.transcribe
Translation tasks.translate
Forecasting tasks.forecast
Guardrails guard
Precontext res.precontext

License

MIT