Gemini generateContent
MarkdownFormato nativo do Google Gemini: para Gemini CLI, Google GenAI SDK e clientes REST.
Guia completo
https://api.ailoot.ai/v1beta/models/{model}:generateContentcurl "https://api.ailoot.ai/v1beta/models/gemini-3.8-flash:generateContent" \
-H "x-goog-api-key: $AILOOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [
{"role": "user", "parts": [{"text": "Crie três nomes para um café."}]}
]
}' from google import genai
from google.genai import types
import os
client = genai.Client(
api_key=os.environ["AILOOT_API_KEY"],
http_options=types.HttpOptions(base_url="https://api.ailoot.ai"), # sem /v1beta
)
resp = client.models.generate_content(
model="gemini-3.8-flash",
contents="Crie três nomes para um café.",
)
print(resp.text)import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({
apiKey: process.env.AILOOT_API_KEY,
httpOptions: { baseUrl: "https://api.ailoot.ai" }, // sem /v1beta
});
const resp = await ai.models.generateContent({
model: "gemini-3.8-flash",
contents: "Crie três nomes para um café.",
});
console.log(resp.text);{
"candidates": [
{
"content": {
"role": "model",
"parts": [{ "text": "1. «Grão e Vapor» 2. «Moagem Matinal» 3. «Café da Esquina»" }]
},
"finishReason": "STOP"
}
],
"usageMetadata": {
"promptTokenCount": 9,
"candidatesTokenCount": 27,
"totalTokenCount": 36
},
"modelVersion": "gemini-3.8-flash"
}Autorização
- x-goog-api-keyheaderobrigatório
Chave
sk-…. Também são aceitesAuthorization: Beareroux-api-key. Para compatibilidade com o Google, também é aceite?key=no endereço — com a prioridade mais baixa;?api_key=é rejeitado com 400. Recomendamos o cabeçalho: assim, a chave não fica nos registos.
Caminho
- modelstringobrigatório
ID de um modelo com o formato Gemini, por exemplo
gemini-3.8-flashougemini-3.1-pro. No total, 27.
https://api.ailoot.ai/v1beta/models/{model}:streamGenerateContent?alt=ssehttps://api.ailoot.ai/v1beta/modelsCorpo do pedido
- contentsarrayobrigatório
Mensagens com
role(user/model) eparts: text, inlineData/fileData, functionCall/functionResponse. Os anexos têm de ser de tipos aceites pelo modelo como entrada. - systemInstructionobjectopcional
Instrução de sistema em texto:
{"parts": [{"text": "…"}]}. - generationConfigobjectopcional
generationConfigaceitatemperature,topP,topK,maxOutputTokens,thinkingConfig,responseMimeType(text/plainouapplication/json),responseSchemaouresponseJsonSchema(objeto JSON),stopSequences(array de cadeias de caracteres),candidateCount: 1, um inteiroseed, os valores numéricospresencePenaltyefrequencyPenalty. Os intervalos e as capacidades permitidos dependem do modelo exato; para uma resposta JSON, escolha uma forma de esquema suportada eapplication/json. Nos modelos de texto,responseModalities— apenas["TEXT"]. - safetySettingsarrayopcional
Objetos com os campos obrigatórios
categoryethreshold, o campo opcionalmethod. Os valores têm de ser suportados pelo modelo exato. - toolsarrayopcional
As
functionDeclarationsdo cliente são executadas pela sua aplicação. Os modelos de texto também aceitam{"googleSearch": {}}e{"urlContext": {}}: em separado ou em conjunto no arraytools. Nem Google Search nem URL context podem ser combinados comfunctionDeclarationsno mesmo pedido. Para imagens na saída, apenas estão disponíveis funções do cliente. As outras ferramentas incorporadas e a cache explícita não são suportadas. Search/URL context podem exigir uma reserva com base no limite total de entrada; os valores efetivos detoolUsePromptTokenCountsão contabilizados como tokens de entrada. - toolConfigobjectopcional
functionCallingConfig: mode (AUTO/ANY/NONE/VALIDATED/MODE_UNSPECIFIED), allowedFunctionNames.
Se o modelo não suportar um campo, um anexo ou uma combinação de ferramentas, o pedido é rejeitado antes da reserva — não há qualquer débito. Receberá HTTP 400 com status INVALID_ARGUMENT e a classe invalid_request (em ErrorInfo.reason — INVALID_REQUEST). JSON inválido, erros nos parâmetros do caminho e noutras validações também devolvem 400; leia o texto do erro e o Request ID. As capacidades dependem do modelo: consulte os seus formatos e entradas no catálogo.
PDF, áudio, vídeo e ligações
Nos modelos Gemini que suportam o tipo de entrada correspondente, parts[].inlineData contém mimeType e dados base64 não vazios; o PDF tem de ser um PDF válido. fileData contém um endereço público httpsno campo fileUri e o MIME do tipo de ficheiro. Para YouTube, pode omitir o MIME. http, endereços privados, gs:// e objetos Google Files API não são suportados, tal como o carregamento através da Google Files API. Para vídeo, pode acrescentar videoMetadata: startOffset/endOffset como cadeia de caracteres em segundos (por exemplo, 1.5s) e fps superior a 0 e não superior a 24. O tamanho do corpo, o contexto, a entrada permitida e o limite de resposta são validados de acordo com o modelo e o formato.
| Entrada | Tipos MIME suportados |
|---|---|
| Imagens inline | image/png, image/jpeg, image/webp |
| Documentos | application/pdf; text/plain, text/html, text/css, text/csv, text/xml, text/rtf, text/markdown, text/javascript, application/x-javascript, text/x-python, application/x-python |
| Áudio | audio/wav, audio/mp3, audio/mpeg, audio/aiff, audio/aac, audio/ogg, audio/flac |
| Vídeo | video/mp4, video/mpeg, video/mov, video/quicktime, video/avi, video/x-flv, video/mpg, video/webm, video/wmv, video/3gpp |
import json, os, urllib.request
def generate(model, payload):
req = urllib.request.Request(
"https://api.ailoot.ai/v1beta/models/" + model + ":generateContent",
data=json.dumps(payload).encode(),
headers={"x-goog-api-key": os.environ["AILOOT_API_KEY"],
"Content-Type": "application/json"},
)
# Envie uma única vez. Em caso de timeout, consulte o ID do pedido no histórico de utilização antes de tentar novamente.
with urllib.request.urlopen(req, timeout=300) as response:
print("Request ID:", response.headers.get("X-Request-ID"))
return json.load(response)
import base64, pathlib, sys
# Indique um ficheiro local real em formato PDF, áudio ou vídeo e o respetivo tipo MIME suportado.
path, mime = pathlib.Path(sys.argv[1]), sys.argv[2]
payload = {"contents": [{"role": "user", "parts": [
{"text": "Descreva brevemente o conteúdo do ficheiro."},
{"inlineData": {"mimeType": mime,
"data": base64.b64encode(path.read_bytes()).decode()}},
]}]}
print(generate("gemini-3.8-flash", payload))
# Anexo alternativo: {"fileData": {"mimeType": mime, "fileUri": public_https_url}}
# Para um URL real do YouTube: {"fileData": {"fileUri": youtube_url}}Search e URL context
As functionDeclarations do cliente são executadas pela sua aplicação. Os modelos de texto também aceitam {"googleSearch": {}} e {"urlContext": {}}: em separado ou em conjunto no array tools. Nem Google Search nem URL context podem ser combinados com functionDeclarations no mesmo pedido. Para imagens na saída, apenas estão disponíveis funções do cliente. As outras ferramentas incorporadas e a cache explícita não são suportadas. Search/URL context podem exigir uma reserva com base no limite total de entrada; os valores efetivos de toolUsePromptTokenCount são contabilizados como tokens de entrada.
{"tools": [{"googleSearch": {}}, {"urlContext": {}}]}Imagens na saída
Apenas o modelo seguinte suporta imagens nas respostas em formato Gemini: gemini-3.1-flash-image. Esta capacidade é distinta de /v1/images/generations: os outros modelos de imagem não funcionam aqui. Este modelo aceita até 131072 tokens de entrada e até 32768 de resposta; o custo total da resposta mais longa é reservado antecipadamente.
responseModalities — conjunto não vazio de TEXT/IMAGE sem repetições. imageConfig.imageSize: 1K/2K/4K; aspectRatio: 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9, 1:4, 4:1, 1:8, 8:1. A entrada deste modelo é texto e PNG/JPEG/WebP inline; PDF/audio/video/fileData e Search/URL context incorporados não são aceites aqui. A disponibilidade e os preços para a sua chave estão no catálogo e em GET /v1/models.
import json, os, urllib.request
def generate(model, payload):
req = urllib.request.Request(
"https://api.ailoot.ai/v1beta/models/" + model + ":generateContent",
data=json.dumps(payload).encode(),
headers={"x-goog-api-key": os.environ["AILOOT_API_KEY"],
"Content-Type": "application/json"},
)
# Envie uma única vez. Em caso de timeout, consulte o ID do pedido no histórico de utilização antes de tentar novamente.
with urllib.request.urlopen(req, timeout=300) as response:
print("Request ID:", response.headers.get("X-Request-ID"))
return json.load(response)
import base64, pathlib
reply = generate("gemini-3.1-flash-image", {
"contents": [{"role": "user", "parts": [{"text": "Aguarela: um farol ao amanhecer"}]}],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {"aspectRatio": "1:1", "imageSize": "1K"},
},
})
index = 0
for candidate in reply.get("candidates", []):
for part in candidate.get("content", {}).get("parts", []):
if "text" in part:
print(part["text"])
blob = part.get("inlineData", {})
if blob.get("mimeType", "").startswith("image/") and blob.get("data"):
index += 1
extension = {"image/png": "png", "image/jpeg": "jpg",
"image/webp": "webp"}.get(blob["mimeType"], "bin")
pathlib.Path(f"gemini-image-v{index}.{extension}").write_bytes(
base64.b64decode(blob["data"]))
print("All returned images:", index)Ciclo completo de function calling
As funções são executadas pelo cliente. Devolva todo o content original do modelo com thoughtSignature sem alterações, seguido de functionResponse com o mesmo name e id, caso este exista em functionCall.
import json, os, urllib.request
def generate(model, payload):
req = urllib.request.Request(
"https://api.ailoot.ai/v1beta/models/" + model + ":generateContent",
data=json.dumps(payload).encode(),
headers={"x-goog-api-key": os.environ["AILOOT_API_KEY"],
"Content-Type": "application/json"},
)
# Envie uma única vez. Em caso de timeout, consulte o ID do pedido no histórico de utilização antes de tentar novamente.
with urllib.request.urlopen(req, timeout=300) as response:
print("Request ID:", response.headers.get("X-Request-ID"))
return json.load(response)
tools = [{"functionDeclarations": [{
"name": "multiply", "description": "Multiplicar dois números",
"parameters": {"type": "object", "properties": {
"a": {"type": "number"}, "b": {"type": "number"}},
"required": ["a", "b"]},
}]}]
contents = [{"role": "user", "parts": [{"text": "Multiplique 7 por 8 com a função"}]}]
for turn in range(4): # Limite o ciclo de ferramentas; não volte a enviar um pedido cujo resultado não esteja claro.
reply = generate("gemini-3.8-flash", {"contents": contents, "tools": tools})
content = reply["candidates"][0]["content"]
contents.append(content) # Mantenha todas (ALL) as partes originais e thoughtSignature sem alterações.
results = []
for part in content.get("parts", []):
call = part.get("functionCall")
if not call:
continue
if call["name"] != "multiply":
raise ValueError("Unexpected function")
args = call["args"]
result = {"name": call["name"], "response": {"value": args["a"] * args["b"]}}
if "id" in call:
result["id"] = call["id"]
results.append({"functionResponse": result})
if not results:
print(content)
break
contents.append({"role": "user", "parts": results})
else:
raise RuntimeError("Tool loop limit reached")Resposta
- candidates[].content.partsarray
Resposta do modelo.
- usageMetadataobject
promptTokenCount,candidatesTokenCount,totalTokenCount.