Conteúdo
Saídas estruturadas no Ollama: faça o modelo retornar JSON em um formato fixo
Ao integrar um modelo a um programa, muitas vezes precisamos de mais do que um texto: precisamos de dados que o programa consiga ler diretamente. Por exemplo, extrair o nome, o número do pedido e o tipo de problema de uma reclamação de cliente.
O parâmetro format do Ollama pode obrigar o modelo a gerar uma saída compatível com o formato JSON especificado.
A forma mais simples: pedir apenas JSON
curl http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [{ "role": "user", "content": "Liste três cidades do Brasil e suas populações em JSON" }],
"format": "json",
"stream": false
}'
A saída será um JSON válido, mas os nomes dos campos e a estrutura ficam a critério do modelo e podem variar a cada resposta.
Especifique um JSON Schema
Coloque o JSON Schema em format para definir os campos com precisão:
curl http://localhost:11434/api/chat -d '{
"model": "qwen3:8b",
"messages": [{ "role": "user", "content": "Apresente a cidade de São Paulo" }],
"format": {
"type": "object",
"properties": {
"city": { "type": "string" },
"population": { "type": "integer" },
"landmarks": { "type": "array", "items": { "type": "string" } }
},
"required": ["city", "population", "landmarks"]
},
"stream": false
}'
message.content será uma string JSON compatível com o formato.
Python: defina o formato com Pydantic
from ollama import chat
from pydantic import BaseModel
class Complaint(BaseModel):
customer_name: str
order_id: str | None
category: str # por exemplo: entrega, qualidade, reembolso, outros
urgency: int # 1~5
summary: str
email = """
Olá, sou Maria Silva. O secador de cabelo do pedido A20261012-88 chegou com a embalagem danificada,
e não funcionou quando o conectei à tomada. Vou viajar na próxima semana; por favor, providenciem a troca ou o reembolso com urgência. Obrigada.
"""
response = chat(
model="qwen3:8b",
messages=[
{"role": "system", "content": "Extraia informações do conteúdo da reclamação. category só pode ser: entrega, qualidade, reembolso, outros."},
{"role": "user", "content": email},
],
format=Complaint.model_json_schema(),
options={"temperature": 0},
)
data = Complaint.model_validate_json(response.message.content)
print(data)
print(data.urgency)
customer_name='Maria Silva' order_id='A20261012-88' category='qualidade' urgency=4 summary='Embalagem do secador de cabelo danificada e aparelho não funciona; solicita troca ou reembolso com urgência'
4
model_validate_json também valida os tipos mais uma vez, garantindo que o programa receba dados corretos.
Limite as opções: use Literal ou Enum
from typing import Literal
class Complaint(BaseModel):
category: Literal["entrega", "qualidade", "reembolso", "outros"]
Assim, o modelo só pode escolher um desses quatro valores, o que é mais confiável do que explicar as opções no prompt.
JavaScript: defina o formato com Zod
npm install ollama zod
import ollama from "ollama";
import { z } from "zod";
const Product = z.object({
name: z.string(),
price: z.number(),
tags: z.array(z.string()),
});
const response = await ollama.chat({
model: "qwen3:8b",
messages: [{ role: "user", content: "Esta capa para iPhone custa 590 reais, é resistente a quedas, leve e compatível com MagSafe" }],
format: z.toJSONSchema(Product),
});
const product = Product.parse(JSON.parse(response.message.content));
console.log(product);
(O Zod 4 inclui z.toJSONSchema; em versões anteriores do Zod 3, você pode usar o pacote zod-to-json-schema.)
Exemplo: classificação em lote
from typing import Literal
from ollama import chat
from pydantic import BaseModel
class Review(BaseModel):
sentiment: Literal["positivo", "negativo", "neutro"]
topics: list[str]
reviews = [
"A comida estava muito gostosa, mas esperei quase uma hora.",
"Os atendentes foram muito simpáticos. Voltarei!",
"O preço é razoável e o sabor também.",
]
for text in reviews:
r = chat(
model="qwen3:8b",
messages=[{"role": "user", "content": f"Analise esta avaliação: {text}"}],
format=Review.model_json_schema(),
options={"temperature": 0},
)
print(text, "→", Review.model_validate_json(r.message.content))
Extraia dados de imagens
Com um modelo de visão, você pode extrair dados estruturados de notas fiscais, cartões de visita e capturas de tela:
class BusinessCard(BaseModel):
name: str
company: str | None
title: str | None
phone: str | None
email: str | None
r = chat(
model="gemma3",
messages=[{"role": "user", "content": "Extraia as informações do cartão de visita", "images": ["./card.jpg"]}],
format=BusinessCard.model_json_schema(),
options={"temperature": 0},
)
print(BusinessCard.model_validate_json(r.message.content))
Dicas para aumentar a precisão
- Defina temperature como 0 para deixar a saída mais estável.
- Explique também o formato e o significado dos campos no prompt; não dependa apenas do schema. Por exemplo: “urgency é um número inteiro de 1 a 5; 5 indica a maior urgência”.
- Escolha nomes de campos claros e fáceis de entender (
order_idé melhor do queoid). - Defina como opcionais os campos que podem não ter dados (
str | None) para evitar que o modelo invente informações para preenchê-los. - A saída estruturada garante o formato, mas não a correção do conteúdo. Ainda é necessário validar dados importantes.
Atualizado 12 de outubro de 2026