Native annotations are documented in annotation format. They are not automatically converted to JSON objects by the API. Function-call schemas are also separate from final-response constraints:
function.strict is accepted but does not enforce argument validity. function.arguments is a string that can contain invalid JSON; parse it and validate it against your function schema before execution.
Request a JSON Schema response
Installperceptron>=0.4.0 and jsonschema, and set PERCEPTRON_API_KEY. This example constrains the answer and validates it locally before use:
Define the response with Pydantic
Pydantic v2 can generate the JSON Schema and validate the response with the same Python model. Install it withpip install "pydantic>=2,<3", then run this after defining client and the image messages above:
extra="forbid" rejects unexpected fields, and the literal types restrict allowed values. model_validate_json raises ValidationError for malformed JSON or values that do not match the model. Handle that failure before storing the result or using it in another workflow.
Use regex for a short answer
Run this after the client and image messages above. Passregex directly to the SDK’s message API:
Combine tools with a constrained final answer
A request cannot declare non-empty functiontools together with a json_schema response format or regex. The SDK raises BadRequestError for this combination before sending the request.
First complete the tool loop. Append every tool result to the conversation. Then request the final answer with your response constraint and omit tools, tool_choice, and parallel_tool_calls for that request. The completed tool history can remain in messages.
Save the function-calling example as inventory.py. Its run() function returns the completed conversation, including the lookup results and assistant answer. Save the following as inventory_report.py in the same directory:
PERCEPTRON_API_KEY set as in the function-calling guide, install the dependencies and run the report script:
Validate completed streams
Withstream=True, individual delta.content chunks can end inside a JSON string or annotation tag. Use stream.get_final_completion() to assemble the response, check response.complete and the finish reason, then parse and validate the final text. Treat finish_reason: "length", API errors, or a lost connection as incomplete output.
The SDK requests usage by default for Perceptron streams. Usage can arrive in a final chunk with choices: []; the assembled completion includes it. If you process chunks directly, consume usage independently of choice deltas. The video tracking stream example demonstrates streaming; replace annotation parsing with JSON or regex validation for constrained responses.