Gemini GenerateContent

使用 Gemini 原生的 contents 请求格式。

POST/v1beta/models/{model}:generateContent

Gemini 原生

进阶用法与完整流程 · 参数与透传

Headers请求头

左右滑动查看完整参数表

请求头
参数名类型必填说明默认值 / 示例
Authorizationstring必填

平台 API Key,使用 Bearer 认证。

示例
Bearer YOUR_API_KEY
Content-Typestring必填

请求体编码格式。

示例
application/json

Path Parameters路径参数

左右滑动查看完整参数表

路径参数
参数名类型必填说明默认值 / 示例
modelstring必填

账户可用且支持 Gemini 原生协议的模型 ID。

示例
MODEL_ID

Query Parameters查询参数

左右滑动查看完整参数表

查询参数
参数名类型必填说明默认值 / 示例
altstring可选

仅 :streamGenerateContent 流式调用使用 sse;普通 :generateContent 无需设置。

示例
sse

Request Body请求体

application/json

左右滑动查看完整参数表

请求体
参数名类型必填说明默认值 / 示例
contentsarray<object>必填

按顺序排列的对话内容。

—
contents[] 的子字段 2
contents[] 子字段
参数名类型必填说明默认值 / 示例
rolestring可选

user 表示用户,model 表示模型;单轮用户输入可省略。

可选值usermodel
—
partsarray<object>必填

消息的文本、媒体或函数内容块。

—
contents[].parts[] 的子字段 6
contents[].parts[] 子字段
参数名类型必填说明默认值 / 示例
textstring可选

文本内容;每个 part 使用一种内容类型。

—
inlineDataobject可选

直接内嵌的图片、音频等媒体。

—
contents[].parts[].inlineData 的子字段 2
contents[].parts[].inlineData 子字段
参数名类型必填说明默认值 / 示例
mimeTypestring必填

媒体 MIME 类型,例如 image/png。

—
datastring必填

原始媒体文件的 Base64 编码数据。

—
fileDataobject可选

可由模型访问的媒体文件。

—
contents[].parts[].fileData 的子字段 2
contents[].parts[].fileData 子字段
参数名类型必填说明默认值 / 示例
mimeTypestring可选

媒体 MIME 类型。

—
fileUristring必填

模型可访问的文件 URI;需所选模型支持。

—
functionCallobject可选

模型发起的函数调用;用于回传历史。

—
contents[].parts[].functionCall 的子字段 3
contents[].parts[].functionCall 子字段
参数名类型必填说明默认值 / 示例
namestring必填

函数名称。

—
argsobject必填

函数参数。

—
idstring可选

函数调用标识;若存在应原样回传。

—
functionResponseobject可选

用户端执行后的函数结果。

—
contents[].parts[].functionResponse 的子字段 3
contents[].parts[].functionResponse 子字段
参数名类型必填说明默认值 / 示例
namestring必填

对应函数名称。

—
responseobject必填

函数执行结果。

—
idstring可选

对应调用标识。

—
thoughtSignaturestring可选

模型返回的思考签名;若响应中存在,多轮请求按原值回传。

—
generationConfigobject可选

采样、输出格式与模态配置。

—
generationConfig 的子字段 18
generationConfig 子字段
参数名类型必填说明默认值 / 示例
temperaturenumber可选

采样温度;有效范围由模型决定。

—
topPnumber可选

核采样阈值。

—
topKinteger可选

采样候选 Token 数;需模型支持。

—
maxOutputTokensinteger可选

最大输出 Token 数。

—
candidateCountinteger可选

候选回复数量;需模型支持。

—
stopSequencesarray<string>可选

自定义停止字符串。

—
responseMimeTypestring可选

输出 MIME 类型,例如 text/plain 或 application/json。

—
responseSchemaobject可选

结构化响应 Schema;需设置兼容的 responseMimeType。

—
responseJsonSchemaobject可选

JSON Schema 形式的响应约束;不与 responseSchema 同时使用,需模型支持。

—
presencePenaltynumber可选

是否出现过某个 Token 的惩罚系数;需模型支持。

—
frequencyPenaltynumber可选

Token 频率惩罚系数;需模型支持。

—
seedinteger可选

随机种子,不保证所有模型完全确定性。

—
responseLogprobsboolean可选

是否返回对数概率;需模型支持。

—
logprobsinteger可选

返回的候选概率数量;需模型支持。

—
responseModalitiesarray<string>可选

所需输出模态,例如 ["TEXT"];媒体输出需模型支持。

—
thinkingConfigobject可选

思考设置;由具体模型决定可用字段。

—
generationConfig.thinkingConfig 的子字段 3
generationConfig.thinkingConfig 子字段
参数名类型必填说明默认值 / 示例
includeThoughtsboolean可选

是否请求思考摘要。

—
thinkingBudgetinteger可选

思考 Token 预算;范围由模型决定。

—
thinkingLevelstring可选

模型支持的思考等级;不要与预算配置盲目混用。

—
speechConfigobject可选

语音生成配置;仅限支持音频输出的模型。

—
imageConfigobject可选

图像生成配置;仅限支持图像输出的模型。

—
safetySettingsarray<object>可选

按伤害类别设置安全阈值;可用取值随模型而异。

—
safetySettings[] 的子字段 2
safetySettings[] 子字段
参数名类型必填说明默认值 / 示例
categorystring必填

安全类别,例如 HARM_CATEGORY_HATE_SPEECH。

—
thresholdstring必填

阻断阈值,例如 BLOCK_MEDIUM_AND_ABOVE。

—
toolsarray<object>可选

模型可使用的工具。

—
tools[] 的子字段 3
tools[] 子字段
参数名类型必填说明默认值 / 示例
functionDeclarationsarray<object>可选

函数定义列表。

—
tools[].functionDeclarations[] 的子字段 3
tools[].functionDeclarations[] 子字段
参数名类型必填说明默认值 / 示例
namestring必填

函数名称。

—
descriptionstring可选

函数用途。

—
parametersobject可选

函数参数的 Schema。

—
googleSearchobject可选

启用搜索工具的配置;需模型支持。

—
codeExecutionobject可选

启用代码执行工具的配置;需模型支持。

—
toolConfigobject可选

工具调用策略。

—
toolConfig 的子字段 1
toolConfig 子字段
参数名类型必填说明默认值 / 示例
functionCallingConfigobject可选

函数调用配置。

—
toolConfig.functionCallingConfig 的子字段 2
toolConfig.functionCallingConfig 子字段
参数名类型必填说明默认值 / 示例
modestring可选

调用模式。

可选值AUTOANYNONE
—
allowedFunctionNamesarray<string>可选

限制可调用函数名;需配合对应 mode。

—
systemInstructionobject可选

系统指令。

—
systemInstruction 的子字段 1
systemInstruction 子字段
参数名类型必填说明默认值 / 示例
partsarray<object>必填

系统文本块。

—
systemInstruction.parts[] 的子字段 1
systemInstruction.parts[] 子字段
参数名类型必填说明默认值 / 示例
textstring必填

系统提示文本。

—
cachedContentstring可选

已创建缓存内容的资源名称;需账户、模型和缓存能力支持。

—

使用说明

  • 模型 ID 写在 URL 路径中;Gemini 原生请求使用 contents 和 parts。
  • 流式调用将动作改为 :streamGenerateContent,并添加 ?alt=sse;响应为 text/event-stream。
  • 媒体、工具、结构化输出与思考选项均需对应模型支持;下方为文本响应说明样例。

流式请求与 SSE 消费

先将 MODEL_ID 替换为账户可用且支持相应能力的模型,并设置环境变量 KEDANG_API_KEY。流式、工具、图像和结构化输出分别依赖模型能力。以下 Python 示例可单独保存运行,API Key 仅在服务端读取。

文本增量成功结束异常处理
candidates[].content.parts[].textfinishReason=STOP 后 EOFHTTP 错误、error 事件、截断或缺少结束标记均停止处理

SSE 以空行分帧,多行 data: 用换行连接;不能把任意网络分块直接当作 JSON。示例读取文本增量;流式工具参数需要按调用 ID 或内容块索引累积后再解析,下面的工具示例采用非流式两步调用。

展开 Python:请求、解析事件与处理结束状态
Python
# 安装依赖:python -m pip install requests
import base64
import json
import os
from pathlib import Path
from urllib.parse import quote
import requests

BASE_URL = "https://ai.kedang.net"
MODEL_ID = "MODEL_ID"  # 替换为账户可用、支持当前能力的模型


def request_json(path, body, extra_headers=None):
    headers = {"Authorization": "Bearer " + os.environ["KEDANG_API_KEY"]}
    headers.update(extra_headers or {})
    response = requests.post(BASE_URL + path, headers=headers, json=body, timeout=120)
    response.raise_for_status()
    result = response.json()
    if result.get("error"):
        raise RuntimeError(result["error"])
    return result

def sse_lines(chunks):
    """增量解码 UTF-8,并跨网络分块正确识别 LF、CR 和 CRLF。"""
    import codecs
    decoder = codecs.getincrementaldecoder("utf-8")()
    line, skip_lf = [], False
    for chunk in chunks:
        for char in decoder.decode(chunk):
            if skip_lf:
                skip_lf = False
                if char == "\n":
                    continue
            if char in ("\r", "\n"):
                yield "".join(line)
                line = []
                skip_lf = char == "\r"
            else:
                line.append(char)
    decoder.decode(b"", final=True)  # 不接受 EOF 处截断的 UTF-8 字符。
    if line:
        yield "".join(line)


def iter_sse(lines):
    """只在空行处派发完整 SSE 帧。"""
    event, data_lines = "message", []
    first_line = True
    for line in lines:
        if first_line:
            line = line.removeprefix("\ufeff")
            first_line = False
        if line == "":
            if data_lines:
                yield event, "\n".join(data_lines)
            event, data_lines = "message", []
            continue
        if line.startswith(":"):
            continue  # 心跳或注释
        field, separator, value = line.partition(":")
        if separator and value.startswith(" "):
            value = value[1:]
        if field == "event":
            event = value or "message"
        elif field == "data":
            data_lines.append(value)
    # EOF 前没有空行的半帧不能当作完整事件;由下层检查终止事件。

def stream_text(events):
    completed = False
    for event, data in events:
        if data.strip() == "[DONE]":
            break
        item = json.loads(data)
        if event == "error" or item.get("error"):
            raise RuntimeError(item)
        if item.get("promptFeedback", {}).get("blockReason"):
            raise RuntimeError(item["promptFeedback"])
        # 本示例读取第一个候选;多候选请求需按 index 分别累积。
        candidates = item.get("candidates", [])
        for candidate in candidates:
            if candidate.get("index", 0) != 0:
                continue
            for part in candidate.get("content", {}).get("parts", []):
                if "text" in part and not part.get("thought", False):
                    yield part["text"]
            reason = candidate.get("finishReason")
            if reason:
                if reason != "STOP":
                    raise RuntimeError("输出未完整完成:" + reason)
                completed = True
        # 原生 SSE 不要求 [DONE];STOP 后读到正常 EOF 即可结束。
    if not completed:
        raise RuntimeError("流结束但没有收到候选的 STOP 终止原因。")

def main():
    path = "/v1beta/models/" + quote(MODEL_ID, safe="") + ":streamGenerateContent?alt=sse"
    body = {"contents": [{"role": "user", "parts": [{"text": "用三句话介绍杭州。"}]}]}
    headers = {"Authorization": "Bearer " + os.environ["KEDANG_API_KEY"],
               "Accept": "text/event-stream"}
    headers.update({})
    with requests.post(BASE_URL + path, headers=headers, json=body,
                       stream=True, timeout=(10, 120)) as response:
        response.raise_for_status()
        if "text/event-stream" not in response.headers.get("Content-Type", ""):
            raise RuntimeError("预期 SSE,请检查返回的 Content-Type 和错误信息。")
        events = iter_sse(sse_lines(response.iter_content(chunk_size=128)))
        for text in stream_text(events):
            print(text, end="", flush=True)
    print()

if __name__ == "__main__":
    main()

工具调用:返回结果后继续回答

第一步让模型提出工具调用,应用校验参数并执行本地函数;第二步将每个结果和原始调用上下文一起发回。示例只允许调用本地加法函数,第二轮关闭工具,避免无界循环。实际业务需自行设置允许执行的工具与轮次上限。

结果关联字段本地工具回传内容
functionResponse.name / idadd_numbers(a, b)JSON 对象 {"sum": 5}
展开 Python:完整两步工具调用
Python
# 安装依赖:python -m pip install requests
import base64
import json
import os
from pathlib import Path
from urllib.parse import quote
import requests

BASE_URL = "https://ai.kedang.net"
MODEL_ID = "MODEL_ID"  # 替换为账户可用、支持当前能力的模型


def request_json(path, body, extra_headers=None):
    headers = {"Authorization": "Bearer " + os.environ["KEDANG_API_KEY"]}
    headers.update(extra_headers or {})
    response = requests.post(BASE_URL + path, headers=headers, json=body, timeout=120)
    response.raise_for_status()
    result = response.json()
    if result.get("error"):
        raise RuntimeError(result["error"])
    return result

PARAMETERS = {
    "type": "object",
    "properties": {"a": {"type": "number"}, "b": {"type": "number"}},
    "required": ["a", "b"],
    "additionalProperties": False,
}


def run_tool(name, args):
    # 工具名和参数都先校验;只执行应用主动注册的函数。
    if name != "add_numbers" or not isinstance(args, dict) or set(args) != {"a", "b"}:
        raise ValueError("未知工具或参数不匹配")
    if any(type(args[key]) not in (int, float) for key in ("a", "b")):
        raise ValueError("a 和 b 必须为数字")
    return {"sum": args["a"] + args["b"]}

def main():
    path = "/v1beta/models/" + quote(MODEL_ID, safe="") + ":generateContent"
    # Gemini 的 Schema 子集按所选模型填写。
    parameters = {"type": "OBJECT", "properties": {
        "a": {"type": "NUMBER"}, "b": {"type": "NUMBER"}}, "required": ["a", "b"]}
    tools = [{"functionDeclarations": [{"name": "add_numbers",
              "description": "计算两个数字之和", "parameters": parameters}]}]
    contents = [{"role": "user", "parts": [{"text": "请用工具计算 2 加 3。"}]}]
    first = request_json(path, {"contents": contents, "tools": tools,
        "toolConfig": {"functionCallingConfig": {"mode": "AUTO"}}})
    model_content = first["candidates"][0]["content"]
    calls = [part["functionCall"] for part in model_content["parts"] if "functionCall" in part]
    if not calls:
        print(first)
        return
    contents.append(model_content)  # 原样保留 parts,包括 thoughtSignature。
    parts = []
    for call in calls:
        result = run_tool(call["name"], call["args"])
        response = {"name": call["name"], "response": result}
        if "id" in call:
            response["id"] = call["id"]
        parts.append({"functionResponse": response})
    contents.append({"role": "user", "parts": parts})
    second = request_json(path, {"contents": contents, "tools": tools,
        "toolConfig": {"functionCallingConfig": {"mode": "NONE"}}})
    for part in second["candidates"][0]["content"]["parts"]:
        if "text" in part and not part.get("thought", False):
            print(part["text"])

if __name__ == "__main__":
    main()

图片输入

示例读取本地 input.png。文件格式与 MIME 类型必须一致;图片数量、大小和支持格式以所选模型为准。这里展示图片理解输入,生成图片请使用图像生成接口。

展开 Python:发送本地 PNG 图片
Python
# 安装依赖:python -m pip install requests
import base64
import json
import os
from pathlib import Path
from urllib.parse import quote
import requests

BASE_URL = "https://ai.kedang.net"
MODEL_ID = "MODEL_ID"  # 替换为账户可用、支持当前能力的模型


def request_json(path, body, extra_headers=None):
    headers = {"Authorization": "Bearer " + os.environ["KEDANG_API_KEY"]}
    headers.update(extra_headers or {})
    response = requests.post(BASE_URL + path, headers=headers, json=body, timeout=120)
    response.raise_for_status()
    result = response.json()
    if result.get("error"):
        raise RuntimeError(result["error"])
    return result

def main():
    image = base64.b64encode(Path("input.png").read_bytes()).decode("ascii")
    path = "/v1beta/models/" + quote(MODEL_ID, safe="") + ":generateContent"
    result = request_json(path, {"contents": [{"role": "user", "parts": [
        {"text": "请描述这张图片。"},
        {"inlineData": {"mimeType": "image/png", "data": image}}
    ]}]})
    for part in result["candidates"][0]["content"]["parts"]:
        if "text" in part and not part.get("thought", False):
            print(part["text"])

if __name__ == "__main__":
    main()

结构化输出

只有支持所选格式约束的模型才能使用此示例;普通 JSON 模式与严格 JSON Schema 的约束强度不同。 输出仍需处理拒绝、截断和字段类型错误。

当前协议字段应用侧校验
generationConfig.responseSchemacity 为字符串,days 为整数;仅接受完整返回结果
展开 Python:提取 JSON 对象并校验
Python
# 安装依赖:python -m pip install requests
import base64
import json
import os
from pathlib import Path
from urllib.parse import quote
import requests

BASE_URL = "https://ai.kedang.net"
MODEL_ID = "MODEL_ID"  # 替换为账户可用、支持当前能力的模型


def request_json(path, body, extra_headers=None):
    headers = {"Authorization": "Bearer " + os.environ["KEDANG_API_KEY"]}
    headers.update(extra_headers or {})
    response = requests.post(BASE_URL + path, headers=headers, json=body, timeout=120)
    response.raise_for_status()
    result = response.json()
    if result.get("error"):
        raise RuntimeError(result["error"])
    return result

SCHEMA = {
    "type": "object",
    "properties": {"city": {"type": "string"}, "days": {"type": "integer"}},
    "required": ["city", "days"],
    "additionalProperties": False,
}


def check_trip(value):
    # 业务侧仍校验结果,尤其要区分拒绝、截断和有效 JSON。
    if not isinstance(value, dict) or set(value) != {"city", "days"}:
        raise ValueError("返回对象不匹配 Schema")
    if not isinstance(value["city"], str) or type(value["days"]) is not int:
        raise ValueError("字段类型不匹配 Schema")
    return value

def main():
    path = "/v1beta/models/" + quote(MODEL_ID, safe="") + ":generateContent"
    result = request_json(path, {
        "contents": [{"role": "user", "parts": [{"text": "提取旅行信息:杭州,3 天。"}]}],
        "generationConfig": {"responseMimeType": "application/json", "responseSchema": {
            "type": "OBJECT", "properties": {"city": {"type": "STRING"}, "days": {"type": "INTEGER"}},
            "required": ["city", "days"]}}})
    candidate = result["candidates"][0]
    if candidate.get("finishReason") != "STOP":
        raise RuntimeError("未得到完整结构化结果")
    text = "".join(part.get("text", "") for part in candidate["content"]["parts"]
                   if not part.get("thought", False))
    print(check_trip(json.loads(text)))

if __name__ == "__main__":
    main()