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": "Schlage drei Namen für ein Café vor."}]}
]
}' 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="Schlage drei Namen für ein Café vor.",
)
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: "Schlage drei Namen für ein Café vor.",
});
console.log(resp.text);{
"candidates": [
{
"content": {
"role": "model",
"parts": [{ "text": "1. «Bohne und Dampf» 2. «Morgendlicher Mahlgrad» 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 geeignet sindAuthorization: Beareroderx-api-key. Für die Kompatibilität mit Google wird auch?key=in der Adresse akzeptiert, mit der niedrigsten Priorität;?api_key=wird mit 400 abgelehnt. Wir empfehlen einen Header, damit der Schlüssel nicht in die Logs gelangt.
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/modelsAnfrageinhalt
- contentsarrayerforderlich
Nachrichten mit
role(user/model) undparts: text, inlineData/fileData, functionCall/functionResponse. Als Anhänge eignen sich die vom Modell unterstützten Eingaben. - 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. Zulässige 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 istresponseModalities— ausschließlich["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. Textmodelle akzeptieren außerdem{"googleSearch": {}}und{"urlContext": {}}: einzeln oder gemeinsam im Arraytools. Weder Google Search noch URL context dürfen zusammen mitfunctionDeclarationsin einer Anfrage verwendet werden. Für Bilder in der Ausgabe stehen ausschließlich clientseitige Funktionen zur Verfügung. Weitere integrierte Tools und explicit cache werden nicht unterstützt. Search/URL context können eine Reservierung anhand des vollständigen Eingabelimits erfordern; die tatsächlich angefallenentoolUsePromptTokenCountwerden als Eingabetokens gezählt. - toolConfigobjectoptional
functionCallingConfig: mode (AUTO/ANY/NONE/VALIDATED/MODE_UNSPECIFIED), allowedFunctionNames.
Wenn das Modell ein Feld, einen Anhang oder eine Tool-Kombination nicht unterstützt, wird die Anfrage vor der Reservierung abgelehnt; es wird nichts abgebucht. Sie erhalten HTTP 400 mit status INVALID_ARGUMENT und der Klasse invalid_request (in ErrorInfo.reason — INVALID_REQUEST). Ungültiges JSON, Fehler in Pfadparametern und anderen Prüfungen liefern ebenfalls 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
Für Gemini-Modelle mit Unterstützung für die jeweilige Eingabe gilt: parts[].inlineData enthält mimeType und nicht leere base64-Daten; eine PDF-Datei muss eine echte PDF-Datei sein. fileData enthält eine öffentliche https-Adresse in fileUri und den MIME-Typ der Datei. Für YouTube kann der MIME-Typ weggelassen werden. http, private Adressen, gs:// und Objekte der Google Files API werden nicht unterstützt; auch Uploads über die Google Files API sind nicht möglich. Bei Video können Sie videoMetadata: startOffset/endOffset als Zeichenfolge in Sekunden angeben (zum Beispiel 1.5s) und fps mit einem Wert größer als 0 und höchstens 24 angeben. Größe des Anfrageinhalts, Kontext, zulässige Eingabe und 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"},
)
# Nur einmal senden. Prüfen Sie nach einem Timeout die Request ID in Ihrem Nutzungsverlauf, bevor Sie es erneut versuchen.
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
# Geben Sie eine echte lokale PDF-, Audio- oder Videodatei und den unterstützten MIME-Typ an.
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. Textmodelle akzeptieren außerdem {"googleSearch": {}} und {"urlContext": {}}: einzeln oder gemeinsam im Array tools. Weder Google Search noch URL context dürfen zusammen mit functionDeclarations in einer Anfrage verwendet werden. Für Bilder in der Ausgabe stehen ausschließlich clientseitige Funktionen zur Verfügung. Weitere integrierte Tools und explicit cache werden nicht unterstützt. Search/URL context können eine Reservierung anhand des vollständigen Eingabelimits erfordern; die tatsächlich angefallenen toolUsePromptTokenCount werden als Eingabetokens gezählt.
{"tools": [{"googleSearch": {}}, {"urlContext": {}}]}Bilder in der Ausgabe
Bilder in einer Gemini-Antwort unterstützt ausschließlich gemini-3.1-flash-image. Dies ist eine separate Funktion gegenüber /v1/images/generations: Andere Bildmodelle funktionieren hier nicht. Dieses Modell unterstützt bis zu 131072 Eingabetokens und bis zu 32768 Antworttokens; die vollständigen Kosten der längstmöglichen Antwort werden vorab reserviert.
responseModalities — eine nicht leere Menge aus TEXT/IMAGE ohne Duplikate. 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. Die Eingabe dieses Modells besteht aus Text und inline PNG/JPEG/WebP; PDF/audio/video/fileData und die integrierten 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"},
)
# Nur einmal senden. Prüfen Sie nach einem Timeout die Request ID in Ihrem Nutzungsverlauf, bevor Sie es erneut versuchen.
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 im Morgengrauen"}]}],
"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 einschließlich thoughtSignature unverändert zurück und anschließend functionResponse mit demselben name und id, sofern die id in 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"},
)
# Nur einmal senden. Prüfen Sie nach einem Timeout die Request ID in Ihrem Nutzungsverlauf, bevor Sie es erneut versuchen.
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): # Begrenzen Sie die Tool-Schleife; senden Sie eine Anfrage mit unklarem Ergebnis nicht erneut.
reply = generate("gemini-3.8-flash", {"contents": contents, "tools": tools})
content = reply["candidates"][0]["content"]
contents.append(content) # Behalten Sie ALLE ursprünglichen parts und thoughtSignature unverändert bei.
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.