文字生成
POST /v1beta/interactions
Gemini Interactions API 根據文字輸入產生文字輸出,採用 Google Gemini Interactions API 的請求與回應格式。
- 原生 Gemini Interactions API 格式
- 支援純文字輸入與多輪對話
- 支援串流與非串流回應
圖像、影片、音訊與文件分析請參閱檔案分析。
路由前提
本頁為 Interactions 協定範例。目前本地網關程式只註冊 Gemini generateContent 路由,沒有註冊 /v1beta/interactions;只有部署環境另外提供此路由時才能執行本頁範例。一般 Gemini 客戶端請見 Gemini CLI,圖像生成請見 Nano Banana。若收到 404,不要只替換 URL:兩種協定的請求與回包不同。
原生文字快速入門
一般 Tokatlas Gemini 路由請先使用此範例。從帳戶可用模型選擇 Gemini 文字模型,填入請求 URL,並選擇下方任一語言執行。只有後面的 Python 文字提取範例需要使用 MODEL_ID 環境變數。
python3 -m pip install requests
export API_KEY='YOUR_TOKATLAS_API_KEY'
export MODEL_ID='YOUR_ENABLED_GEMINI_TEXT_MODEL_ID'執行方式見多語言範例說明。先設定 API_KEY,並替換模型、檔案網址及 ID 占位值;四種方式會顯示相同請求的原始回應。
curl --fail-with-body --silent --show-error --max-time 180 \
--request POST \
--url "https://api.tokatlas.ai/v1beta/models/YOUR_ENABLED_GEMINI_TEXT_MODEL_ID:generateContent" \
--header "x-goog-api-key: $API_KEY" \
--header "Content-Type: application/json" \
--data '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Reply with OK only."
}
]
}
]
}'import os
import requests
headers = {
'x-goog-api-key': os.environ["API_KEY"],
'Content-Type': 'application/json',
}
payload = {'contents': [{'role': 'user', 'parts': [{'text': 'Reply with OK only.'}]}]}
response = requests.request(
'POST', 'https://api.tokatlas.ai/v1beta/models/YOUR_ENABLED_GEMINI_TEXT_MODEL_ID:generateContent', headers=headers,
json=payload,
timeout=180,
)
response.raise_for_status()
print(response.text)if (!process.env.API_KEY) throw new Error("Set API_KEY first.");
const response = await fetch("https://api.tokatlas.ai/v1beta/models/YOUR_ENABLED_GEMINI_TEXT_MODEL_ID:generateContent", {
method: "POST",
headers: {
"x-goog-api-key": process.env.API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"contents": [
{
"role": "user",
"parts": [
{
"text": "Reply with OK only."
}
]
}
]
}),
signal: AbortSignal.timeout(180_000),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
console.log(await response.text());import java.net.URI;
import java.net.http.*;
import java.time.Duration;
public class Example {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("API_KEY");
if (apiKey == null || apiKey.isBlank()) {
throw new IllegalArgumentException("Set API_KEY first.");
}
String payload = String.join("\n",
"{",
" \"contents\": [",
" {",
" \"role\": \"user\",",
" \"parts\": [",
" {",
" \"text\": \"Reply with OK only.\"",
" }",
" ]",
" }",
" ]",
"}"
);
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30)).build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.tokatlas.ai/v1beta/models/YOUR_ENABLED_GEMINI_TEXT_MODEL_ID:generateContent"))
.timeout(Duration.ofSeconds(180))
.header("x-goog-api-key", apiKey)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException("HTTP " + response.statusCode() + ": "
+ response.body());
}
System.out.println(response.body());
}
}以下 Python 版本另外示範從回應中提取純文字。存為 gemini_text.py,執行 python3 gemini_text.py:
import os
from urllib.parse import quote
import requests
model = quote(os.environ["MODEL_ID"], safe="")
response = requests.post(
"https://api.tokatlas.ai/v1beta/models/" + model + ":generateContent",
headers={"x-goog-api-key": os.environ["API_KEY"]},
json={"contents": [{"role": "user", "parts": [{"text": "Reply with OK only."}]}]},
timeout=120,
)
response.raise_for_status()
body = response.json()
texts = [part["text"] for candidate in body.get("candidates", [])
for part in candidate.get("content", {}).get("parts", [])
if part.get("text") and not part.get("thought")]
if not texts:
raise RuntimeError(f"No text returned: {body}")
print("\n".join(texts))以下為另外提供 Interactions 路由時的協定參考,請勿混用兩種請求格式。
端點
https://api.tokatlas.ai/v1beta/interactions串流範例同時使用 ?alt=sse 與請求本文的 stream: true;只改 URL 不等於已啟用串流。
身分驗證
所有端點均需要 API 金鑰驗證。請在請求標頭中加入金鑰:
x-goog-api-key: YOUR_API_KEY
Content-Type: application/json重要
請勿將真實 API 金鑰提交至程式碼儲存庫,或公開於用戶端程式碼中。
請求本文
| 參數 | 類型 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
model | string | 是 | - | 要使用的 Gemini 模型 |
input | string, array, or object | 是 | - | 使用者輸入:純文字、內容區塊或對話步驟 |
system_instruction | string | 否 | - | 引導模型行為的系統提示 |
generation_config | object | 否 | - | 生成參數,例如 temperature 與 thinking_level |
previous_interaction_id | string | 否 | - | 多輪對話中前一次互動的 ID |
store | boolean | 否 | true | 是否在伺服器端儲存對話狀態 |
stream | boolean | 否 | false | 是否透過 SSE 傳回串流回應 |
model
以下為截至 2026-10-03 核對的官方現行型號。先依API 使用入門查詢帳戶可用模型,再將完整 ID 填入 model;官方已發布不代表您的 Tokatlas 帳戶已開通。
gemini-3.8-flash— Gemini 3.8 Flashgemini-3.5-flash-lite— Gemini 3.5 Flash-Litegemini-3.1-pro-preview— Gemini 3.1 Pro (preview)
input
互動中的使用者輸入。文字對話可使用純文字或對話步驟。
純文字:單輪文字生成最簡單的形式:
"How does AI work?"對話步驟:用於無狀態多輪對話(搭配 store: false):
[
{
"type": "user_input",
"content": [{"type": "text", "text": "I have 2 dogs in my house."}]
}
]圖像、影片、音訊與文件輸入請參閱檔案分析。
system_instruction
用於設定模型行為、個性與指令的系統提示。
{
"system_instruction": "You are a cat. Your name is Neko.",
"input": "Hello there"
}generation_config
覆寫預設生成參數。
| 欄位 | 類型 | 說明 |
|---|---|---|
temperature | number | 輸出隨機程度,數值越高,輸出越有創意。 |
thinking_level | string | 思考深度:控制成本、延遲與推理品質。常見值:"low"、"medium"、"high"。 |
思考
Gemini 模型通常預設啟用思考,在回應前進行推理。可使用 generation_config 中的 thinking_level,調整成本、延遲與推理能力之間的取捨。
思考程度設定範例:
{
"model": "gemini-3.7-flash",
"input": "How does AI work?",
"generation_config": {
"thinking_level": "low"
}
}溫度設定範例:
{
"model": "gemini-3.7-flash",
"input": "Explain how AI works",
"generation_config": {
"temperature": 1.0
}
}previous_interaction_id
傳入前一次互動回應的 id,即可接續多輪對話。API 會在伺服器端管理對話歷史,無須重新傳送先前的輪次。
{
"model": "gemini-3.7-flash",
"input": "How many paws are in my house?",
"previous_interaction_id": "INTERACTION_ID_FROM_PREVIOUS_RESPONSE"
}先確認路由支援儲存,且前一次互動以 store: true 建立並仍可存取。
由伺服器管理對話
使用 previous_interaction_id 時,Interactions API 會在伺服器端處理對話狀態,無須手動管理歷史紀錄。
store
控制是否在伺服器端儲存互動,以供後續參照。
true(預設):伺服器儲存互動,使用previous_interaction_id接續對話false:無狀態模式,必須自行管理並在input中重新傳送完整對話歷史
無狀態模式
使用 store: false 時,必須原樣保留並重新傳送模型產生的所有步驟(包含 thought 與 function_call),因為其中含有接續對話所需的簽章。
stream
是否透過 SSE 逐步傳回串流回應。
true:邊生成邊傳回回應片段false:一次傳回完整回應(預設)
回應
| 欄位 | 類型 | 說明 |
|---|---|---|
id | string | 互動唯一識別碼 |
model | string | 處理請求的模型 |
steps | array | 依序排列的互動步驟(使用者輸入、模型輸出、工具呼叫等) |
status | string | 互動狀態,例如 completed 或 requires_action |
讀取文字
從 steps 中選取 type: "model_output",再讀取其 content 中的 text 區塊。不要假設原始 HTTP 回應含有 SDK 的 output_text 便利屬性。工具呼叫與思考步驟須另行處理並保留。
steps[]
每個步驟代表互動中的一個輪次或動作。
| 欄位 | 類型 | 說明 |
|---|---|---|
type | string | 步驟類型:user_input、model_output、thought、function_call 等 |
content | array | 輸入/模型輸出步驟的內容;工具步驟使用其專屬欄位 |
使用範例
基本文字生成
{
"model": "gemini-3.7-flash",
"input": "How does AI work?"
}系統指令
{
"model": "gemini-3.7-flash",
"system_instruction": "You are a cat. Your name is Neko.",
"input": "Hello there"
}思考設定
{
"model": "gemini-3.7-flash",
"input": "How does AI work?",
"generation_config": {
"thinking_level": "low"
}
}有狀態多輪對話
第 1 輪:
{
"model": "gemini-3.7-flash",
"input": "I have 2 dogs in my house."
}第 2 輪(將第 1 輪回應的 id 作為 previous_interaction_id):
{
"model": "gemini-3.7-flash",
"input": "How many paws are in my house?",
"previous_interaction_id": "INTERACTION_ID_FROM_TURN_1"
}無狀態多輪對話
第 1 輪:
{
"model": "gemini-3.7-flash",
"store": false,
"input": [
{
"type": "user_input",
"content": [{"type": "text", "text": "I have 2 dogs in my house."}]
}
]
}第 2 輪需以程式組合歷史。下列片段中的 first_response 是第 1 輪解析後的回應物件,first_input 是第 1 輪送出的輸入陣列;將 payload 送至相同端點。
history = [*first_input, *first_response["steps"]]
history.append({
"type": "user_input",
"content": [{"type": "text", "text": "How many paws are in my house?"}],
})
payload = {"model": "gemini-3.7-flash", "store": False, "input": history}串流輸出
{
"model": "gemini-3.7-flash",
"input": "Explain how AI works",
"stream": true
}請求範例
執行方式見多語言範例說明。先設定 API_KEY,並替換模型、檔案網址及 ID 占位值;四種方式會顯示相同請求的原始回應。
curl --fail-with-body --silent --show-error --max-time 180 \
--request POST \
--url "https://api.tokatlas.ai/v1beta/interactions" \
--header "x-goog-api-key: $API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "gemini-3.7-flash",
"input": "How does AI work?"
}'import os
import requests
headers = {
'x-goog-api-key': os.environ["API_KEY"],
'Content-Type': 'application/json',
}
payload = {'model': 'gemini-3.7-flash', 'input': 'How does AI work?'}
response = requests.request(
'POST', 'https://api.tokatlas.ai/v1beta/interactions', headers=headers,
json=payload,
timeout=180,
)
response.raise_for_status()
print(response.text)if (!process.env.API_KEY) throw new Error("Set API_KEY first.");
const response = await fetch("https://api.tokatlas.ai/v1beta/interactions", {
method: "POST",
headers: {
"x-goog-api-key": process.env.API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"model": "gemini-3.7-flash",
"input": "How does AI work?"
}),
signal: AbortSignal.timeout(180_000),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
console.log(await response.text());import java.net.URI;
import java.net.http.*;
import java.time.Duration;
public class Example {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("API_KEY");
if (apiKey == null || apiKey.isBlank()) {
throw new IllegalArgumentException("Set API_KEY first.");
}
String payload = String.join("\n",
"{",
" \"model\": \"gemini-3.7-flash\",",
" \"input\": \"How does AI work?\"",
"}"
);
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30)).build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.tokatlas.ai/v1beta/interactions"))
.timeout(Duration.ofSeconds(180))
.header("x-goog-api-key", apiKey)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException("HTTP " + response.statusCode() + ": "
+ response.body());
}
System.out.println(response.body());
}
}package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
func main() {
url := "https://api.tokatlas.ai/v1beta/interactions"
payload := map[string]interface{}{
"model": "gemini-3.7-flash",
"input": "How does AI work?",
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("x-goog-api-key", os.Getenv("API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}串流請求
執行方式見多語言範例說明。先設定 API_KEY,並替換模型、檔案網址及 ID 占位值;四種方式會顯示相同請求的原始回應。
curl --fail-with-body --silent --show-error --max-time 180 \
--request POST \
--url "https://api.tokatlas.ai/v1beta/interactions?alt=sse" \
--header "x-goog-api-key: $API_KEY" \
--header "Content-Type: application/json" \
--no-buffer \
--data '{
"model": "gemini-3.7-flash",
"input": "Explain how AI works",
"stream": true
}'import os
import requests
headers = {
'x-goog-api-key': os.environ["API_KEY"],
'Content-Type': 'application/json',
}
payload = {'model': 'gemini-3.7-flash', 'input': 'Explain how AI works', 'stream': True}
response = requests.request(
'POST', 'https://api.tokatlas.ai/v1beta/interactions?alt=sse', headers=headers,
json=payload,
stream=True,
timeout=180,
)
response.raise_for_status()
for line in response.iter_lines():
if line:
print(line.decode("utf-8"), flush=True)if (!process.env.API_KEY) throw new Error("Set API_KEY first.");
const response = await fetch("https://api.tokatlas.ai/v1beta/interactions?alt=sse", {
method: "POST",
headers: {
"x-goog-api-key": process.env.API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"model": "gemini-3.7-flash",
"input": "Explain how AI works",
"stream": true
}),
signal: AbortSignal.timeout(180_000),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
for await (const chunk of response.body) {
process.stdout.write(chunk);
}import java.net.URI;
import java.net.http.*;
import java.time.Duration;
public class Example {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("API_KEY");
if (apiKey == null || apiKey.isBlank()) {
throw new IllegalArgumentException("Set API_KEY first.");
}
String payload = String.join("\n",
"{",
" \"model\": \"gemini-3.7-flash\",",
" \"input\": \"Explain how AI works\",",
" \"stream\": true",
"}"
);
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30)).build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.tokatlas.ai/v1beta/interactions?alt=sse"))
.timeout(Duration.ofSeconds(180))
.header("x-goog-api-key", apiKey)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<java.io.InputStream> response = client.send(
request, HttpResponse.BodyHandlers.ofInputStream());
try (java.io.InputStream input = response.body()) {
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException("HTTP " + response.statusCode() + ": "
+ new String(input.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8));
}
input.transferTo(System.out);
}
}
}多輪請求
先執行第一輪請求並確認成功,再使用互動 ID 發送第二輪。
第一輪:建立互動
執行方式見多語言範例說明。先設定 API_KEY,並替換模型、檔案網址及 ID 占位值;四種方式會顯示相同請求的原始回應。
curl --fail-with-body --silent --show-error --max-time 180 \
--request POST \
--url "https://api.tokatlas.ai/v1beta/interactions" \
--header "x-goog-api-key: $API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "gemini-3.7-flash",
"store": true,
"input": "I have 2 dogs in my house."
}'import os
import requests
headers = {
'x-goog-api-key': os.environ["API_KEY"],
'Content-Type': 'application/json',
}
payload = {'model': 'gemini-3.7-flash', 'store': True, 'input': 'I have 2 dogs in my house.'}
response = requests.request(
'POST', 'https://api.tokatlas.ai/v1beta/interactions', headers=headers,
json=payload,
timeout=180,
)
response.raise_for_status()
print(response.text)if (!process.env.API_KEY) throw new Error("Set API_KEY first.");
const response = await fetch("https://api.tokatlas.ai/v1beta/interactions", {
method: "POST",
headers: {
"x-goog-api-key": process.env.API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"model": "gemini-3.7-flash",
"store": true,
"input": "I have 2 dogs in my house."
}),
signal: AbortSignal.timeout(180_000),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
console.log(await response.text());import java.net.URI;
import java.net.http.*;
import java.time.Duration;
public class Example {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("API_KEY");
if (apiKey == null || apiKey.isBlank()) {
throw new IllegalArgumentException("Set API_KEY first.");
}
String payload = String.join("\n",
"{",
" \"model\": \"gemini-3.7-flash\",",
" \"store\": true,",
" \"input\": \"I have 2 dogs in my house.\"",
"}"
);
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30)).build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.tokatlas.ai/v1beta/interactions"))
.timeout(Duration.ofSeconds(180))
.header("x-goog-api-key", apiKey)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException("HTTP " + response.statusCode() + ": "
+ response.body());
}
System.out.println(response.body());
}
}第二輪:接續互動
複製第一輪回應最外層的 id,替換下方 YOUR_PREVIOUS_INTERACTION_ID,再執行一次。不要使用步驟或工具呼叫的 ID。
curl --fail-with-body --silent --show-error --max-time 180 \
--request POST \
--url "https://api.tokatlas.ai/v1beta/interactions" \
--header "x-goog-api-key: $API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "gemini-3.7-flash",
"store": true,
"previous_interaction_id": "YOUR_PREVIOUS_INTERACTION_ID",
"input": "How many paws are in my house?"
}'import os
import requests
headers = {
'x-goog-api-key': os.environ["API_KEY"],
'Content-Type': 'application/json',
}
payload = {'model': 'gemini-3.7-flash',
'store': True,
'previous_interaction_id': 'YOUR_PREVIOUS_INTERACTION_ID',
'input': 'How many paws are in my house?'}
response = requests.request(
'POST', 'https://api.tokatlas.ai/v1beta/interactions', headers=headers,
json=payload,
timeout=180,
)
response.raise_for_status()
print(response.text)if (!process.env.API_KEY) throw new Error("Set API_KEY first.");
const response = await fetch("https://api.tokatlas.ai/v1beta/interactions", {
method: "POST",
headers: {
"x-goog-api-key": process.env.API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"model": "gemini-3.7-flash",
"store": true,
"previous_interaction_id": "YOUR_PREVIOUS_INTERACTION_ID",
"input": "How many paws are in my house?"
}),
signal: AbortSignal.timeout(180_000),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
console.log(await response.text());import java.net.URI;
import java.net.http.*;
import java.time.Duration;
public class Example {
public static void main(String[] args) throws Exception {
String apiKey = System.getenv("API_KEY");
if (apiKey == null || apiKey.isBlank()) {
throw new IllegalArgumentException("Set API_KEY first.");
}
String payload = String.join("\n",
"{",
" \"model\": \"gemini-3.7-flash\",",
" \"store\": true,",
" \"previous_interaction_id\": \"YOUR_PREVIOUS_INTERACTION_ID\",",
" \"input\": \"How many paws are in my house?\"",
"}"
);
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(30)).build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.tokatlas.ai/v1beta/interactions"))
.timeout(Duration.ofSeconds(180))
.header("x-goog-api-key", apiKey)
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() < 200 || response.statusCode() >= 300) {
throw new IllegalStateException("HTTP " + response.statusCode() + ": "
+ response.body());
}
System.out.println(response.body());
}
}回應範例
非串流 (stream: false)
{
"id": "interaction_abc123",
"model": "gemini-3.7-flash",
"steps": [
{
"type": "model_output",
"content": [
{
"type": "text",
"text": "Artificial intelligence (AI) refers to computer systems designed to perform tasks that typically require human intelligence..."
}
]
}
],
"status": "completed"
}串流 (stream: true)
當 stream 為 true,API 會傳回 SSE 串流。每個事件包含部分文字輸出的增量。請監聽 event_type 為 "step.delta" 且 delta.type 為 "text" 的事件。
event: step.delta
data: {"event_type":"step.delta","index":0,"delta":{"type":"text","text":"Artificial"}}
event: step.delta
data: {"event_type":"step.delta","index":0,"delta":{"type":"text","text":" intelligence"}}
event: step.delta
data: {"event_type":"step.delta","index":0,"delta":{"type":"text","text":" (AI) refers to..."}}
event: interaction.completed
data: {"event_type":"interaction.completed","interaction":{"id":"interaction_abc123","model":"gemini-3.7-flash"}}