Gemini generateContent
MarkdownDas native Google-Gemini-Format: für Gemini CLI, Google GenAI SDK und REST-Clients.
Vollständiger Leitfaden
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": "Denke dir drei Namen für ein Café aus."}]}
]
}' 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"), # ohne /v1beta
)
resp = client.models.generate_content(
model="gemini-3.8-flash",
contents="Denke dir drei Namen für ein Café aus.",
)
print(resp.text)import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({
apiKey: process.env.AILOOT_API_KEY,
httpOptions: { baseUrl: "https://api.ailoot.ai" }, // ohne /v1beta
});
const resp = await ai.models.generateContent({
model: "gemini-3.8-flash",
contents: "Denke dir drei Namen für ein Café aus.",
});
console.log(resp.text);{
"candidates": [
{
"content": {
"role": "model",
"parts": [{ "text": "1. «Bohne und Dampf» 2. «Morgenmahlung» 3. «Café an der Ecke»" }]
},
"finishReason": "STOP"
}
],
"usageMetadata": {
"promptTokenCount": 9,
"candidatesTokenCount": 27,
"totalTokenCount": 36
},
"modelVersion": "gemini-3.8-flash"
}Authentifizierung
- x-goog-api-keyheadererforderlich
Schlüssel
sk-…. Ebenfalls unterstützt werdenAuthorization: Beareroderx-api-key. Für die Kompatibilität mit Google wird auch?key=in der URL akzeptiert — mit der niedrigsten Priorität;?api_key=wird mit 400 abgelehnt. Wir empfehlen einen Header, damit der Schlüssel nicht in Protokollen landet.
Pfad
- modelstringerforderlich
ID eines Modells mit Gemini-Format, zum Beispiel
gemini-3.8-flashodergemini-3.1-pro. Insgesamt 27.
https://api.ailoot.ai/v1beta/models/{model}:streamGenerateContent?alt=ssehttps://api.ailoot.ai/v1beta/modelsAnfragekörper
- contentsarrayerforderlich
Nachrichten mit
role(user/model) undparts: text, inlineData/fileData, functionCall/functionResponse. Als Anhänge sind die vom Modell unterstützten Eingaben möglich. - systemInstructionobjectoptional
Systemanweisung als Text:
{"parts": [{"text": "…"}]}. - generationConfigobjectoptional
generationConfigakzeptierttemperature,topP,topK,maxOutputTokens,thinkingConfig,responseMimeType(text/plainoderapplication/json),responseSchemaoderresponseJsonSchema(JSON-Objekt),stopSequences(Array von Zeichenfolgen),candidateCount: 1, ganzzahligesseed, numerischepresencePenaltyundfrequencyPenalty. Gültige Wertebereiche und Funktionen hängen vom genauen Modell ab; wählen Sie für eine JSON-Antwort eine unterstützte Schemaform undapplication/json. Bei Textmodellen unterstütztresponseModalitiesnur["TEXT"]. - safetySettingsarrayoptional
Objekte mit den erforderlichen Feldern
categoryundthreshold, dem optionalen Feldmethod. Die Werte müssen vom genauen Modell unterstützt werden. - toolsarrayoptional
Clientseitige
functionDeclarationswerden von Ihrer Anwendung ausgeführt. Bei Textmodellen werden ausserdem{"googleSearch": {}}und{"urlContext": {}}akzeptiert: einzeln oder zusammen im Arraytools. Weder Google Search noch URL context dürfen mitfunctionDeclarationsin derselben Anfrage kombiniert werden. Bei Bildausgaben sind nur clientseitige Funktionen verfügbar. Andere integrierte Werkzeuge und explicit cache werden nicht unterstützt. Search/URL context können eine Reservierung für das gesamte Eingabelimit erfordern; die tatsächlichentoolUsePromptTokenCountwerden als Eingabetokens berücksichtigt. - toolConfigobjectoptional
functionCallingConfig: mode (AUTO/ANY/NONE/VALIDATED/MODE_UNSPECIFIED), allowedFunctionNames.
Unterstützt das Modell ein Feld, einen Anhang oder eine Werkzeugkombination nicht, wird die Anfrage vor der Reservierung abgelehnt — es wird nichts abgebucht. Die Antwort ist HTTP 400 mit status INVALID_ARGUMENT und der Klasse invalid_request (in ErrorInfo.reason — INVALID_REQUEST). Ungültiges JSON sowie Fehler bei Pfadparametern und anderen Prüfungen führen ebenfalls zu 400; lesen Sie den Fehlertext und die Request ID. Die Funktionen hängen vom Modell ab: Prüfen Sie dessen Formate und Eingaben im Katalog.
PDF, Audio, Video und Links
Bei Gemini-Modellen mit Unterstützung der jeweiligen Eingabe enthält parts[].inlineData das Feld mimeType und nicht leere base64-Daten; eine PDF-Datei muss tatsächlich im PDF-Format vorliegen. fileData enthält eine öffentliche https-Adresse in fileUri und den MIME-Typ der Datei. Bei YouTube kann der MIME-Typ weggelassen werden. http, private Adressen, gs:// und Google-Files-API-Objekte werden nicht unterstützt, ebenso wenig Uploads über die Google Files API. Bei Videos können Sie videoMetadata: startOffset/endOffset als Zeichenfolge in Sekunden (zum Beispiel 1.5s) und fps grösser als 0 und höchstens 24 hinzufügen. Die Grösse des Anfragekörpers, der Kontext, die zulässige Eingabe und das Antwortlimit werden anhand von Modell und Format geprüft.
| Eingabe | Unterstützte MIME-Typen |
|---|---|
| Inline-Bilder | image/png, image/jpeg, image/webp |
| Dokumente | 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 |
| Audio | audio/wav, audio/mp3, audio/mpeg, audio/aiff, audio/aac, audio/ogg, audio/flac |
| Video | 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"},
)
# Einmal senden. Nach einem Timeout vor einem erneuten Versuch die Request ID im Nutzungsverlauf prüfen.
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
# Eine echte lokale PDF-, Audio- oder Videodatei und ihren unterstützten MIME-Typ angeben.
path, mime = pathlib.Path(sys.argv[1]), sys.argv[2]
payload = {"contents": [{"role": "user", "parts": [
{"text": "Beschreibe kurz den Inhalt der Datei."},
{"inlineData": {"mimeType": mime,
"data": base64.b64encode(path.read_bytes()).decode()}},
]}]}
print(generate("gemini-3.8-flash", payload))
# Alternativer Anhang: {"fileData": {"mimeType": mime, "fileUri": public_https_url}}
# Für eine echte YouTube-URL: {"fileData": {"fileUri": youtube_url}}Search und URL context
Clientseitige functionDeclarations werden von Ihrer Anwendung ausgeführt. Bei Textmodellen werden ausserdem {"googleSearch": {}} und {"urlContext": {}} akzeptiert: einzeln oder zusammen im Array tools. Weder Google Search noch URL context dürfen mit functionDeclarations in derselben Anfrage kombiniert werden. Bei Bildausgaben sind nur clientseitige Funktionen verfügbar. Andere integrierte Werkzeuge und explicit cache werden nicht unterstützt. Search/URL context können eine Reservierung für das gesamte Eingabelimit erfordern; die tatsächlichen toolUsePromptTokenCount werden als Eingabetokens berücksichtigt.
{"tools": [{"googleSearch": {}}, {"urlContext": {}}]}Bilder als Ausgabe
Bilder in einer Antwort im Gemini-Format unterstützt nur gemini-3.1-flash-image. Diese Funktion ist unabhängig von /v1/images/generations: Andere Bildmodelle funktionieren hier nicht. Dieses Modell unterstützt bis zu 131072 Eingabetokens und 32768 Antworttokens; die vollständigen Kosten der längstmöglichen Antwort werden vorab reserviert.
responseModalities — eine nicht leere Menge aus TEXT/IMAGE ohne Wiederholungen. 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. Dieses Modell akzeptiert Text und Inline-PNG/JPEG/WebP; PDF/audio/video/fileData und integrierte Search/URL context werden hier nicht akzeptiert. Verfügbarkeit und Preise für Ihren Schlüssel finden Sie im Katalog und in 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"},
)
# Einmal senden. Nach einem Timeout vor einem erneuten Versuch die Request ID im Nutzungsverlauf prüfen.
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": "Aquarell: Leuchtturm bei Sonnenaufgang"}]}],
"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)Vollständiger Function-Calling-Ablauf
Die Funktionen werden vom Client ausgeführt. Geben Sie den gesamten ursprünglichen content des Modells samt thoughtSignature unverändert zurück, danach functionResponse mit demselben name und id, falls diese im functionCall vorhanden war.
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"},
)
# Einmal senden. Nach einem Timeout vor einem erneuten Versuch die Request ID im Nutzungsverlauf prüfen.
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": "Zwei Zahlen multiplizieren",
"parameters": {"type": "object", "properties": {
"a": {"type": "number"}, "b": {"type": "number"}},
"required": ["a", "b"]},
}]}]
contents = [{"role": "user", "parts": [{"text": "Multipliziere 7 mit 8 mithilfe der Funktion"}]}]
for turn in range(4): # Die Tool-Schleife begrenzen; keine Anfrage erneut senden, deren Ergebnis unklar ist.
reply = generate("gemini-3.8-flash", {"contents": contents, "tools": tools})
content = reply["candidates"][0]["content"]
contents.append(content) # Alle ursprünglichen parts (ALL) und thoughtSignature unverändert beibehalten.
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")Antwort
- candidates[].content.partsarray
Antwort des Modells.
- usageMetadataobject
promptTokenCount,candidatesTokenCount,totalTokenCount.