Comprendi e conteggia i token

Gemini e altri modelli di AI generativa elaborano input e output con una granularità chiamata token.

Per i modelli Gemini, un token equivale a circa 4 caratteri. 100 token equivalgono a circa 60-80 parole in inglese.

Informazioni sui token

I token possono essere singoli caratteri come z o intere parole come cat. Le parole lunghe vengono suddivise in più token. L'insieme di tutti i token utilizzati dal modello è chiamato vocabolario e il processo di suddivisione del testo in token è chiamato tokenizzazione.

Quando la fatturazione è abilitata, il costo di una chiamata all'API Gemini è determinato in parte dal numero di token di input e output, quindi sapere come contare i token può essere utile.

Puoi provare a conteggiare i token nel nostro Colab.

Visualizza su ai.google.dev Prova un notebook Colab Visualizza il notebook su GitHub

Contare i token

Tutti gli input e gli output dell'API Gemini sono tokenizzati, inclusi testo, file di immagini e altre modalità non testuali.

Puoi contare i token nei seguenti modi:

  • Chiama count_tokens con l'input della richiesta.
    Restituisce il numero totale di token solo nell'input.
    Puoi effettuare questa chiamata prima di inviare l'input al modello per controllare le dimensioni delle richieste.

  • Utilizza l'attributo usage_metadata sull'oggetto response dopo aver chiamato generate_content.
    Restituisce il numero totale di token sia nell'input che nell'output: total_token_count.

    Restituisce anche i conteggi dei token di input e output separatamente: prompt_token_count (token di input) e candidates_token_count (token di output).

    Se utilizzi un modello di pensiero, i token utilizzati durante il processo di pensiero vengono restituiti in thoughts_token_count. Se utilizzi la memorizzazione nella cache del contesto, il conteggio dei token memorizzati nella cache sarà in cached_content_token_count.

Contare i token di testo

Se chiami count_tokens con un input solo di testo, restituisce il conteggio dei token del testo nell'input solo (total_tokens). Puoi effettuare questa chiamata prima di chiamare generate_content per controllare le dimensioni delle tue richieste.

Un'altra opzione è chiamare generate_content e poi utilizzare l'attributo usage_metadata nell'oggetto response per ottenere quanto segue:

  • I conteggi separati dei token dell'input (prompt_token_count), dei contenuti memorizzati nella cache (cached_content_token_count) e dell'output (candidates_token_count)
  • Il conteggio dei token per il processo di pensiero (thoughts_token_count)
  • Il numero totale di token sia nell'input sia nell'output (total_token_count)

Python

from google import genai

client = genai.Client()
prompt = "The quick brown fox jumps over the lazy dog."

total_tokens = client.models.count_tokens(
    model="gemini-3.5-flash", contents=prompt
)
print("total_tokens: ", total_tokens)

response = client.models.generate_content(
    model="gemini-3.5-flash", contents=prompt
)

print(response.usage_metadata)

JavaScript

import { GoogleGenAI } from '@google/genai';

const ai = new GoogleGenAI({});
const prompt = "The quick brown fox jumps over the lazy dog.";

async function main() {
  const countTokensResponse = await ai.models.countTokens({
    model: "gemini-3.5-flash",
    contents: prompt,
  });
  console.log(countTokensResponse.totalTokens);

  const generateResponse = await ai.models.generateContent({
    model: "gemini-3.5-flash",
    contents: prompt,
  });
  console.log(generateResponse.usageMetadata);
}

await main();

Go

ctx := context.Background()
client, err := genai.NewClient(ctx, nil)

// Convert prompt to a slice of *genai.Content using the helper.
contents := []*genai.Content{
  genai.NewContentFromText(prompt, genai.RoleUser),
}
countResp, err := client.Models.CountTokens(ctx, "gemini-3.5-flash", contents, nil)
if err != nil {
  return err
}
fmt.Println("total_tokens:", countResp.TotalTokens)

response, err := client.Models.GenerateContent(ctx, "gemini-3.5-flash", contents, nil)
if err != nil {
  log.Fatal(err)
}
usageMetadata, err := json.MarshalIndent(response.UsageMetadata, "", "  ")
if err != nil {
  log.Fatal(err)
}
fmt.Println(string(usageMetadata))
    ```

Contare i token multi-turno (chat)

Se chiami count_tokens con la cronologia chat, viene restituito il conteggio totale dei token del testo di ogni ruolo nella chat (total_tokens).

Un'altra opzione è chiamare send_message e poi utilizzare l'attributo usage_metadata nell'oggetto response per ottenere quanto segue:

  • I conteggi separati dei token dell'input (prompt_token_count), dei contenuti memorizzati nella cache (cached_content_token_count) e dell'output (candidates_token_count)
  • Il conteggio dei token per il processo di pensiero (thoughts_token_count)
  • Il numero totale di token sia nell'input sia nell'output (total_token_count)

Per capire quanto sarà grande il tuo prossimo turno conversazionale, devi aggiungerlo alla cronologia quando chiami count_tokens.

Python

from google import genai
from google.genai import types

client = genai.Client()

chat = client.chats.create(
    model="gemini-3.5-flash",
    history=[
        types.Content(
            role="user", parts=[types.Part(text="Hi my name is Bob")]
        ),
        types.Content(role="model", parts=[types.Part(text="Hi Bob!")]),
    ],
)

print(
    client.models.count_tokens(
        model="gemini-3.5-flash", contents=chat.get_history()
    )
)

response = chat.send_message(
    message="In one sentence, explain how a computer works to a young child."
)
print(response.usage_metadata)

extra = types.UserContent(
    parts=[
        types.Part(
            text="What is the meaning of life?",
        )
    ]
)
history = [*chat.get_history(), extra]
print(client.models.count_tokens(model="gemini-3.5-flash", contents=history))

JavaScript

import { GoogleGenAI } from '@google/genai';

const ai = new GoogleGenAI({});

async function main() {
  const history = [
    { role: "user", parts: [{ text: "Hi my name is Bob" }] },
    { role: "model", parts: [{ text: "Hi Bob!" }] },
  ];
  const chat = ai.chats.create({
    model: "gemini-3.5-flash",
    history: history,
  });

  const countTokensResponse = await ai.models.countTokens({
    model: "gemini-3.5-flash",
    contents: chat.getHistory(),
  });
  console.log(countTokensResponse.totalTokens);

  const chatResponse = await chat.sendMessage({
    message: "In one sentence, explain how a computer works to a young child.",
  });
  console.log(chatResponse.usageMetadata);

  const extraMessage = {
    role: "user",
    parts: [{ text: "What is the meaning of life?" }],
  };
  const combinedHistory = [...chat.getHistory(), extraMessage];
  const combinedCountTokensResponse = await ai.models.countTokens({
    model: "gemini-3.5-flash",
    contents: combinedHistory,
  });
  console.log(
    "Combined history token count:",
    combinedCountTokensResponse.totalTokens,
  );
}

await main();

Go

ctx := context.Background()
client, err := genai.NewClient(ctx, nil)

history := []*genai.Content{
  {Role: genai.RoleUser, Parts: []*genai.Part({Text: "Hi my name is Bob"})},
  {Role: genai.RoleModel, Parts: []*genai.Part({Text: "Hi Bob!"})},
}
chat, err := client.Chats.Create(ctx, "gemini-3.5-flash", nil, history)
if err != nil {
  log.Fatal(err)
}

firstTokenResp, err := client.Models.CountTokens(ctx, "gemini-3.5-flash", chat.History(false), nil)
if err != nil {
  log.Fatal(err)
}
fmt.Println(firstTokenResp.TotalTokens)

resp, err := chat.SendMessage(ctx, genai.NewPartFromText("In one sentence, explain how a computer works to a young child."))
if err != nil {
  log.Fatal(err)
}
fmt.Printf("%#v\n", resp.UsageMetadata)

extra := genai.NewContentFromText("What is the meaning of life?", genai.RoleUser)
hist := chat.History(false)
hist = append(hist, extra)

secondTokenResp, err := client.Models.CountTokens(ctx, "gemini-3.5-flash", hist, nil)
if err != nil {
  log.Fatal(err)
}
fmt.Println(secondTokenResp.TotalTokens)

Contare i token multimodali

Tutti gli input dell'API Gemini vengono tokenizzati, inclusi testo, file immagine e altre modalità non testuali. Tieni presente i seguenti punti chiave di alto livello sulla tokenizzazione dell'input multimodale durante l'elaborazione da parte dell'API Gemini:

  • Gli input di immagini con entrambe le dimensioni <=384 pixel vengono conteggiati come 258 token. Le immagini più grandi in una o entrambe le dimensioni vengono ritagliate e scalate in base alle necessità in riquadri di 768 x 768 pixel, ognuno dei quali viene conteggiato come 258 token.

  • I file video e audio vengono convertiti in token alle seguenti tariffe fisse: video a 263 token al secondo e audio a 32 token al secondo.

Risoluzioni dei contenuti multimediali

I modelli Gemini 3 introducono un controllo granulare sull'elaborazione multimodale della visione con il parametro media_resolution. Il parametro media_resolution determina il numero massimo di token allocati per ogni immagine di input o frame video. Risoluzioni più elevate migliorano la capacità del modello di leggere testi piccoli o identificare piccoli dettagli, ma aumentano l'utilizzo di token e la latenza.

Per maggiori dettagli sul parametro e su come può influire sui calcoli dei token, consulta la guida alla risoluzione dei contenuti multimediali.

File immagine

Se chiami count_tokens con un input di testo e immagine, restituisce il conteggio dei token combinato del testo e dell'immagine solo nell'input (total_tokens). Puoi effettuare questa chiamata prima di chiamare generate_content per controllare le dimensioni delle tue richieste. Se vuoi, puoi anche chiamare count_tokens sul testo e sul file separatamente.

Un'altra opzione è chiamare generate_content e poi utilizzare l'attributo usage_metadata nell'oggetto response per ottenere quanto segue:

  • I conteggi separati dei token dell'input (prompt_token_count), dei contenuti memorizzati nella cache (cached_content_token_count) e dell'output (candidates_token_count)
  • Il conteggio dei token per il processo di pensiero (thoughts_token_count)
  • Il numero totale di token sia nell'input sia nell'output (total_token_count)

Esempio che utilizza un'immagine caricata dall'API File:

Python

from google import genai

client = genai.Client()
prompt = "Tell me about this image"
your_image_file = client.files.upload(file=media / "organ.jpg")

print(
    client.models.count_tokens(
        model="gemini-3.5-flash", contents=[prompt, your_image_file]
    )
)

response = client.models.generate_content(
    model="gemini-3.5-flash", contents=[prompt, your_image_file]
)
print(response.usage_metadata)

JavaScript

import { GoogleGenAI } from '@google/genai';

const ai = new GoogleGenAI({});
const prompt = "Tell me about this image";

async function main() {
  const organ = await ai.files.upload({
    file: path.join(media, "organ.jpg"),
    config: { mimeType: "image/jpeg" },
  });

  const countTokensResponse = await ai.models.countTokens({
    model: "gemini-3.5-flash",
    contents: createUserContent([
      prompt,
      createPartFromUri(organ.uri, organ.mimeType),
    ]),
  });
  console.log(countTokensResponse.totalTokens);

  const generateResponse = await ai.models.generateContent({
    model: "gemini-3.5-flash",
    contents: createUserContent([
      prompt,
      createPartFromUri(organ.uri, organ.mimeType),
    ]),
  });
  console.log(generateResponse.usageMetadata);
}

await main();

Go

ctx := context.Background()
client, err := genai.NewClient(ctx, nil)

file, err := client.Files.UploadFromPath(
  ctx, 
  filepath.Join(getMedia(), "organ.jpg"), 
  &genai.UploadFileConfig{
    MIMEType : "image/jpeg",
  },
)
if err != nil {
  log.Fatal(err)
}
parts := []*genai.Part{
  genai.NewPartFromText("Tell me about this image"),
  genai.NewPartFromURI(file.URI, file.MIMEType),
}
contents := []*genai.Content{
  genai.NewContentFromParts(parts, genai.RoleUser),
}

tokenResp, err := client.Models.CountTokens(ctx, "gemini-3.5-flash", contents, nil)
if err != nil {
  log.Fatal(err)
}
fmt.Println("Multimodal image token count:", tokenResp.TotalTokens)

response, err := client.Models.GenerateContent(ctx, "gemini-3.5-flash", contents, nil)
if err != nil {
  log.Fatal(err)
}
usageMetadata, err := json.MarshalIndent(response.UsageMetadata, "", "  ")
if err != nil {
  log.Fatal(err)
}
fmt.Println(string(usageMetadata))

Esempio che fornisce l'immagine come dati incorporati:

Python

from google import genai
import PIL.Image

client = genai.Client()
prompt = "Tell me about this image"
your_image_file = PIL.Image.open(media / "organ.jpg")

print(
    client.models.count_tokens(
        model="gemini-3.5-flash", contents=[prompt, your_image_file]
    )
)

response = client.models.generate_content(
    model="gemini-3.5-flash", contents=[prompt, your_image_file]
)
print(response.usage_metadata)

JavaScript

import { GoogleGenAI } from '@google/genai';

const ai = new GoogleGenAI({});
const prompt = "Tell me about this image";
const imageBuffer = fs.readFileSync(path.join(media, "organ.jpg"));

const imageBase64 = imageBuffer.toString("base64");

const contents = createUserContent([
  prompt,
  createPartFromBase64(imageBase64, "image/jpeg"),
]);

async function main() {
  const countTokensResponse = await ai.models.countTokens({
    model: "gemini-3.5-flash",
    contents: contents,
  });
  console.log(countTokensResponse.totalTokens);

  const generateResponse = await ai.models.generateContent({
    model: "gemini-3.5-flash",
    contents: contents,
  });
  console.log(generateResponse.usageMetadata);
}

await main();

Go

ctx := context.Background()
client, err := genai.NewClient(ctx, nil)

imageBytes, err := os.ReadFile("organ.jpg")
if err != nil {
    log.Fatalf("Failed to read image file: %v", err)
}
parts := []*genai.Part{
  genai.NewPartFromText("Tell me about this image"),
  {
        InlineData: &genai.Blob{
              MIMEType: "image/jpeg",
              Data:     imageBytes,
        },
  },
}
contents := []*genai.Content{
  genai.NewContentFromParts(parts, genai.RoleUser),
}

tokenResp, err := client.Models.CountTokens(ctx, "gemini-3.5-flash", contents, nil)
if err != nil {
  log.Fatal(err)
}
fmt.Println("Multimodal image token count:", tokenResp.TotalTokens)

response, err := client.Models.GenerateContent(ctx, "gemini-3.5-flash", contents, nil)
if err != nil {
  log.Fatal(err)
}
usageMetadata, err := json.MarshalIndent(response.UsageMetadata, "", "  ")
if err != nil {
  log.Fatal(err)
}
fmt.Println(string(usageMetadata))

File audio o video

Audio e video vengono convertiti in token alle seguenti tariffe fisse:

  • Video: 263 token al secondo
  • Audio: 32 token al secondo

Se chiami count_tokens con un input di testo e video/audio, viene restituito il conteggio combinato dei token del testo e del file video/audio solo nell'input (total_tokens). Puoi effettuare questa chiamata prima di chiamare generate_content per controllare le dimensioni delle tue richieste. Puoi anche chiamare facoltativamente count_tokens sul testo e sul file separatamente.

Un'altra opzione è chiamare generate_content e poi utilizzare l'attributo usage_metadata nell'oggetto response per ottenere quanto segue:

  • I conteggi separati dei token dell'input (prompt_token_count), dei contenuti memorizzati nella cache (cached_content_token_count) e dell'output (candidates_token_count)
  • Il conteggio dei token per il processo di pensiero (thoughts_token_count)
  • Il numero totale di token sia nell'input che nell'output (total_token_count).

Python

from google import genai
import time

client = genai.Client()
prompt = "Tell me about this video"
your_file = client.files.upload(file=media / "Big_Buck_Bunny.mp4")

while not your_file.state or your_file.state.name != "ACTIVE":
    print("Processing video...")
    print("File state:", your_file.state)
    time.sleep(5)
    your_file = client.files.get(name=your_file.name)

print(
    client.models.count_tokens(
        model="gemini-3.5-flash", contents=[prompt, your_file]
    )
)

response = client.models.generate_content(
    model="gemini-3.5-flash", contents=[prompt, your_file]
)
print(response.usage_metadata)

JavaScript

import { GoogleGenAI } from '@google/genai';

const ai = new GoogleGenAI({});
const prompt = "Tell me about this video";

async function main() {
  let videoFile = await ai.files.upload({
    file: path.join(media, "Big_Buck_Bunny.mp4"),
    config: { mimeType: "video/mp4" },
  });

  while (!videoFile.state || videoFile.state.toString() !== "ACTIVE") {
    console.log("Processing video...");
    console.log("File state: ", videoFile.state);
    await sleep(5000);
    videoFile = await ai.files.get({ name: videoFile.name });
  }

  const countTokensResponse = await ai.models.countTokens({
    model: "gemini-3.5-flash",
    contents: createUserContent([
      prompt,
      createPartFromUri(videoFile.uri, videoFile.mimeType),
    ]),
  });
  console.log(countTokensResponse.totalTokens);

  const generateResponse = await ai.models.generateContent({
    model: "gemini-3.5-flash",
    contents: createUserContent([
      prompt,
      createPartFromUri(videoFile.uri, videoFile.mimeType),
    ]),
  });
  console.log(generateResponse.usageMetadata);
}

await main();

Go

ctx := context.Background()
client, err := genai.NewClient(ctx, nil)

file, err := client.Files.UploadFromPath(
  ctx,
  filepath.Join(getMedia(), "Big_Buck_Bunny.mp4"),
  &genai.UploadFileConfig{
    MIMEType : "video/mp4",
  },
)
if err != nil {
  log.Fatal(err)
}

for file.State == genai.FileStateUnspecified || file.State != genai.FileStateActive {
  fmt.Println("Processing video...")
  fmt.Println("File state:", file.State)
  time.Sleep(5 * time.Second)

  file, err = client.Files.Get(ctx, file.Name, nil)
  if err != nil {
    log.Fatal(err)
  }
}

parts := []*genai.Part{
  genai.NewPartFromText("Tell me about this video"),
  genai.NewPartFromURI(file.URI, file.MIMEType),
}
contents := []*genai.Content{
  genai.NewContentFromParts(parts, genai.RoleUser),
}

tokenResp, err := client.Models.CountTokens(ctx, "gemini-3.5-flash", contents, nil)
if err != nil {
  log.Fatal(err)
}
fmt.Println("Multimodal video/audio token count:", tokenResp.TotalTokens)
response, err := client.Models.GenerateContent(ctx, "gemini-3.5-flash", contents, nil)
if err != nil {
  log.Fatal(err)
}
usageMetadata, err := json.MarshalIndent(response.UsageMetadata, "", "  ")
if err != nil {
  log.Fatal(err)
}
fmt.Println(string(usageMetadata))

Contare i token di ragionamento

Quando attivi la funzionalità di pensiero, il prezzo della risposta è la somma dei token di output e dei token di pensiero. Puoi recuperare il numero totale di token di pensiero generati dal campo thoughtsTokenCount (o dall'equivalente SDK).

Python

# ...
print("Thoughts tokens:", response.usage_metadata.thoughts_token_count)
print("Output tokens:", response.usage_metadata.candidates_token_count)

JavaScript

// ...
console.log(`Thoughts tokens: ${response.usageMetadata.thoughtsTokenCount}`);
console.log(`Output tokens: ${response.usageMetadata.candidatesTokenCount}`);

Go

// ...
fmt.Println("Thoughts tokens:", response.UsageMetadata.ThoughtsTokenCount)
fmt.Println("Output tokens:", response.UsageMetadata.CandidatesTokenCount)

I modelli di pensiero generano pensieri completi per migliorare la qualità della risposta finale, quindi restituiscono riepiloghi per fornire informazioni sul processo di pensiero. Pertanto, l'API basa i prezzi sui token di pensiero completi che il modello genera per creare un riepilogo, anche se l'API restituisce solo il riepilogo.

Per scoprire di più su come configurare il pensiero, consulta la guida Pensiero di Gemini.

Finestre contestuali

Le finestre contestuali dei modelli disponibili tramite l'API Gemini sono misurate in token. La finestra contestuale definisce la quantità di input che puoi fornire e la quantità di output che il modello può generare. Puoi determinare le dimensioni della finestra contestuale chiamando l'endpoint models.get o consultando la documentazione sui modelli.

Python

from google import genai

client = genai.Client()
model_info = client.models.get(model="gemini-3.5-flash")
print(f"{model_info.input_token_limit=}")
print(f"{model_info.output_token_limit=}")

JavaScript

import { GoogleGenAI } from '@google/genai';

const ai = new GoogleGenAI({});

async function main() {
  const modelInfo = await ai.models.get({model: 'gemini-3.5-flash'});
  console.log(modelInfo.inputTokenLimit);
  console.log(modelInfo.outputTokenLimit);
}

await main();

Go

ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
  log.Fatal(err)
}
modelInfo, err := client.ModelInfo(ctx, "models/gemini-3.5-flash")
if err != nil {
  log.Fatal(err)
}
fmt.Println("input token limit:", modelInfo.InputTokenLimit)
fmt.Println("output token limit:", modelInfo.OutputTokenLimit)