Overview
The chat
endpoint supports structured outputs for chat completions with palmyra-x5
and palmyra-x4
models.
Structured outputs allow you to specify the response schema that the model should follow.
You can use structured outputs in one of two ways:
- Pass in a
json_schema
object in the response_format
parameter when making a request to the chat
endpoint.
- Use the
parse
method in the Python and JavaScript SDKs and pass in a Pydantic
or Zod
object.
Sample request and response
The sample request and response below shows how to use structured outputs with the chat
endpoint and the response_format
parameter.
The json_schema
object must be in JSON Schema format.
To guarantee that the model includes all the fields in the response, include the required
field in the json_schema
object.
curl -X POST https://api.writer.com/v1/chat \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $WRITER_API_KEY" \
--data '{
"model": "palmyra-x5",
"messages": [
{ "role": "system", "content": "You are a helpful cooking assistant." },
{ "role": "user", "content": "Give me a recipe for a simple pasta dish." }
],
"response_format": {
"type": "json_schema",
"json_schema": {
"schema": {
"type": "object",
"properties": {
"recipe_name": {"type": "string"},
"ingredients": {"type": "array", "items": {"type": "string"}},
"steps": {"type": "array", "items": {"type": "string"}},
"preparation_time": {"type": "string"},
"servings": {"type": "number"}
},
"required": ["recipe_name", "ingredients", "steps", "preparation_time", "servings"]
}
}
}
}'
The response from the chat
endpoint includes a message
object with the content
field set to the raw response from the model.
{
"id": "1234",
"object": "chat.completion",
"choices": [
{
"index": 0,
"finish_reason": "stop",
"message": {
"content": "{ \"recipe_name\": \"Spaghetti Aglio e Olio\", \"ingredients\": [\"12 oz spaghetti\", \"3-4 garlic cloves\", \"1/3 cup extra virgin olive oil\", \"4-6 dried red chili flakes (optional)\", \"Salt\", \"Freshly ground black pepper\", \"Grated Parmesan cheese (optional)\", \"Fresh parsley, chopped (optional)\"], \"steps\": [\"Bring a large pot of salted water to a boil. Cook the spaghetti according to the package instructions until al dente. Reserve 1 cup of pasta water before draining.\", \"In a large skillet, heat the olive oil over medium-low heat. Add the thinly sliced garlic and cook, stirring occasionally, until golden brown (about 4-5 minutes). Be careful not to burn the garlic.\", \"If using red chili flakes, add them to the skillet and cook for another minute.\", \"Add the reserved pasta water to the skillet and stir to combine.\", \"Add the cooked spaghetti to the skillet, tossing to coat the pasta in the garlic and oil mixture. Season with salt and black pepper to taste.\", \"Serve hot, topped with grated Parmesan cheese and chopped fresh parsley if desired.\"] }",
"role": "assistant",
"tool_calls": null,
"graph_data": {
"sources": null,
"status": null,
"subqueries": null
},
"llm_data": null,
"image_data": null,
"translation_data": null,
"refusal": null
},
"logprobs": null
}
],
"created": 1745948916,
"model": "palmyra-x5",
"usage": {
"prompt_tokens": 2550,
"total_tokens": 2797,
"completion_tokens": 247,
"prompt_token_details": null,
"completion_tokens_details": null
},
"system_fingerprint": "v1",
"service_tier": null
}
SDK parse methods
The Python and JavaScript SDKs provide helper parse
methods for working with structured outputs.
You can define a Pydantic
or Zod
model for the response schema, and pass it as the response_format
parameter to the parse
method.
The result from the parse
method includes a message
object with the parsed
field. This field’s value is an instance of the Pydantic
or Zod
model you passed for the response_format
parameter.
from typing import List
from pydantic import Field, BaseModel
from writerai import Writer
# Initialize the client. If you don't pass the `api_key` parameter,
# the client looks for the `WRITER_API_KEY` environment variable.
client = Writer()
# Define a Pydantic model for structured output
class Recipe(BaseModel):
recipe_name: str = Field(description="The name of the recipe")
ingredients: List[str] = Field(description="A list of ingredients for the recipe")
steps: List[str] = Field(description="A list of steps for the recipe")
preparation_time: str = Field(description="The preparation time for the recipe")
servings: int = Field(description="The number of servings for the recipe")
parsed_response = client.chat.parse(
model="palmyra-x5",
messages=[
{"role": "system", "content": "You are a helpful cooking assistant."},
{
"role": "user",
"content": "Give me a recipe for a simple pasta dish.",
},
],
response_format=Recipe,
)
parsed = parsed_response.choices[0].message.parsed
# Print the parsed response
print(f"Recipe name: {parsed.recipe_name}")
print(f"Ingredients:")
for item in parsed.ingredients:
print(f"- {item}")
print(f"Steps:")
for item in parsed.steps:
print(f"- {item}")
print(f"Preparation time: {parsed.preparation_time}")
print(f"Servings: {parsed.servings}")