Passaggio 1: configura la chiave API per Google AI Studio
Per impostare la chiave API, vai su Google AI Studio e clicca sul pulsante “Create API Key”. Ricordati di copiare la chiave e incollarla in un file chiamato .env, con il seguente formato:
GOOGLE_API_KEY=replace_this_with_api_key
Se hai già lavorato con Google Cloud Platform usando lo stesso account Google, Google AI Studio ti chiederà di scegliere uno dei tuoi progetti per attivare l'API.
Per seguire questo tutorial, il codice Python deve trovarsi nella stessa cartella del file .env.
Passaggio 2: installa le dipendenze Python
Per questo progetto useremo i seguenti pacchetti:
google-genai: una libreria Python per integrare i modelli di AI generativa di Google nelle nostre applicazioni.pyautogui: una libreria multipiattaforma per controllare in modo programmatico mouse e tastiera per automatizzare attività. Nel nostro caso, la usiamo per fornire al modello AI il contenuto dello schermo.python-dotenv: una libreria per gestire le variabili d'ambiente caricandole da file .env nella nostra applicazione Python.sounddevice: una libreria Python per registrare e riprodurre suoni tramite semplici API per input e output audio.numpy: una libreria fondamentale per il calcolo numerico in Python, che offre supporto per array, matrici e molte operazioni matematiche.
Per installare le dipendenze, possiamo usare pip:
pip install google-genai pyautogui python-dotenv sounddevice numpy
In alternativa, scarichiamo il file requirements.txt dal repository GitHub che ho preparato per questo progetto e usiamolo per creare un ambiente Conda:
conda create --name gemini python=3.11
conda activate gemini
pip install -r requirements.txt
Passaggio 3: crea un chatbot testuale con la Google GenAI API
Cominciamo creando una semplice interfaccia AI da riga di comando usando il modello Gemini 2 Flash di Google con la libreria google.genai. Ti consiglio di dare un'occhiata alla documentazione ufficiale di Gemini 2.0 in caso di intoppi lungo il percorso.
Il codice completo di questo esempio è disponibile nel file text.py sul mio repository GitHub.
Creare e connettersi al client Google GenAI
Il primo passo è caricare in modo sicuro la chiave API e inizializzare il client Google GenAI. Lo script usa dotenv per caricare le variabili d'ambiente dal file .env.
Ecco come impostare il client con le credenziali necessarie:
from google import genai
from dotenv import load_dotenv
import os
# Load environment variables from a .env file
load_dotenv()
client = genai.Client(
api_key=os.getenv("GOOGLE_API_KEY"),
http_options={"api_version": "v1alpha"},
)
print("Connected to the AI model!")
Effettuare chiamate API asincrone
Quando si lavora con API come Google GenAI, spesso è necessario gestire operazioni asincrone. La programmazione asincrona consente ad altre operazioni di proseguire mentre si attendono le richieste di rete, rendendo l'applicazione più reattiva. Ciò è particolarmente importante con operazioni ad alta latenza come le richieste di rete.
In Python, la programmazione asincrona è resa possibile dalla libreria asyncio e dalla sintassi async/await.
Ecco come possiamo fare una richiesta asincrona a Google GenAI:
from google import genai
from dotenv import load_dotenv
import os
import asyncio
# Load environment variables from a .env file
load_dotenv()
async def main():
client = genai.Client(
api_key=os.getenv("GOOGLE_API_KEY"),
http_options={"api_version": "v1alpha"},
)
# Define the AI model and configuration
model_id = "gemini-2.0-flash-exp"
config = {"response_modalities": ["TEXT"]}
async with client.aio.live.connect(model=model_id, config=config) as session:
await session.send("Hello", end_of_turn=True)
# Process responses from the AI
async for response in session.receive():
if not response.server_content.turn_complete:
for part in response.server_content.model_turn.parts:
print(part.text, end="", flush=True)
# Run the main function
asyncio.run(main())
Questa versione si connette al modello AI e invia un singolo messaggio “Hello”. La risposta viene stampata parola per parola sulla console.
Renderla interattiva
Per rendere l'applicazione interattiva, consentendo all'utente di chattare con il modello AI, aggiungiamo un ciclo che permette di inviare più messaggi. Il ciclo continua finché l'utente non digita "exit".
from google import genai
from dotenv import load_dotenv
import os
import asyncio
# Load environment variables from a .env file
load_dotenv()
async def main():
client = genai.Client(
api_key=os.getenv("GOOGLE_API_KEY"),
http_options={"api_version": "v1alpha"},
)
# Define the AI model and configuration
model_id = "gemini-2.0-flash-exp"
config = {"response_modalities": ["TEXT"]}
async with client.aio.live.connect(model=model_id, config=config) as session:
while True:
message = input("> ")
print()
# Exit the loop if the user types "exit"
if message == "exit":
print("Exiting...")
break
# Send the user's message to the AI model, marking the end of the turn
await session.send(message, end_of_turn=True)
# Receive responses asynchronously and process each response
async for response in session.receive():
if not response.server_content.turn_complete:
for part in response.server_content.model_turn.parts:
print(part.text, end="", flush=True)
print()
# Run the main function
asyncio.run(main())
E questo è tutto! Con lo script qui sopra, abbiamo creato un chatbot AI da riga di comando usando la Google GenAI API. Ecco come appare:
Passaggio 4: aggiungi la modalità audio
La modalità audio consente al modello di rispondere con la voce invece che con il testo. Per adattare l'esempio precedente alla gestione delle risposte audio, dobbiamo:
- Importare
sounddeviceper la riproduzione audio enumpyper elaborare i dati audio. - Cambiare la modalità di risposta da
TEXTaAUDIO:
config = {"response_modalities": ["AUDIO"]}
- Inizializzare un flusso audio prima di connettersi al client:
with sd.OutputStream(
samplerate=24000,
channels=1,
dtype="int16",
) as audio_stream:
- Accedere ai dati audio dalla parte di risposta e aggiungerli al flusso audio per la riproduzione:
for part in response.server_content.model_turn.parts:
# Get the audio data from the response part and add it to the steam
inline_data = part.inline_data
audio_data = np.frombuffer(inline_data.data, dtype="int16")
audio_stream.write(audio_data)
Il file audio.py nel repository contiene lo script completo con queste modifiche applicate. Lo script include commenti sulle righe che sono cambiate.
Passaggio 5: aggiungi l'esecuzione di codice con gli strumenti
Una delle grandi funzionalità dei modelli di AI moderni è la capacità di chiamare autonomamente funzioni personalizzate nel nostro codice, e Gemini 2 non fa eccezione.
Il funzionamento è questo: diciamo al modello quali funzioni può chiamare registrandole come strumenti. Poi, analizzando il prompt, i nomi delle funzioni e le descrizioni, il modello deciderà se vuole effettuare una chiamata di funzione. Quando decide di farlo, invierà una risposta speciale con il nome della funzione che vuole chiamare e gli argomenti.
Per definire uno strumento, dobbiamo:
- Scrivere una funzione Python con lo stesso nome e gli stessi argomenti definiti nello schema.
- Creare lo schema della funzione, ovvero un dizionario con i metadati della funzione, come nome, descrizione testuale e specifica degli argomenti.
- Fornire lo schema della funzione al modello di AI.
- Eseguire la funzione quando il modello la richiede.
Per illustrarlo, definiamo uno strumento che possa leggere un file, consentendo al modello di rispondere a domande sui file presenti sulla nostra macchina locale.
Definire la funzione
Questa parte è semplice codice Python. Il modello si aspetta che la risposta sia un dizionario con una chiave ”result” se la funzione ha avuto successo e ”error” altrimenti.
def load_file_content(filename):
try:
with open(filename, "rt") as f:
return {
"result": f.read()
}
except Exception as e:
return {
"error": "Could not load file content",
}
Specificare lo schema
Ecco come possiamo definire uno schema per questa funzione:
load_file_content_schema = {
"name": "load_file_content",
"description": "Load the content of a file",
"parameters": {
"type": "object",
"properties": {
"filename": {
"type": "string",
"description": "The name of the file",
},
},
"required": ["filename"],
},
"output": {
"type": "string",
"description": "The text content of the file",
},
}
Forniamo quattro campi:
”name”: il nome della funzione.”description”: una descrizione testuale. Viene usata dal modello per decidere se chiamare la funzione.”properties”: descrizione degli argomenti della funzione.”output”: descrizione dell'output della funzione.
Consulta la documentazione ufficiale per maggiori informazioni sugli schemi delle funzioni.
Fornire la funzione al modello
Per far conoscere al modello la nostra funzione, forniamo lo schema della funzione nella configurazione del modello:
config = {
"tools": [{"function_declarations": [load_file_content_schema]}],
"response_modalities": ["TEXT"]
}
Elaborare la richiesta di chiamata di funzione dal modello
Quando il modello decide di effettuare una chiamata di funzione, aggiunge un tool_call alla response. Questo conterrà il nome della funzione e gli argomenti. Potrebbe contenere più richieste di chiamata, quindi dobbiamo iterare su tutte, chiamare le funzioni corrispondenti e inviare il risultato al modello:
# A dictionary mapping the function names to the actual functions
FUNCTIONS = {"load_file_content": load_file_content}
if response.tool_call is not None:
for fc in tool_call.function_calls:
f = FUNCTIONS.get(fc.name)
tool_response = types.LiveClientToolResponse(
function_responses=[
types.FunctionResponse(
name=fc.name,
id=fc.id,
response=f(**fc.args),
)
]
)
await session.send(tool_response)
L'implementazione completa di questo esempio è fornita nel file tool.py nel repository contenente lo script completo con queste modifiche applicate. Le definizioni di funzione e schema sono nel file tool_spec.py.
Accesso al web
Usando gli strumenti, possiamo anche dare al modello la possibilità di accedere al web aggiungendo lo strumento di ricerca Google:
search_tool = {"google_search": {}}
config = {
"tools": [search_tool],
"response_modalities": ["TEXT"],
}
Questo strumento è integrato, quindi non è necessario fornire una funzione.
Esecuzione di codice
Un'altra funzione integrata è l'esecuzione di codice. L'esecuzione di codice consente al modello di scrivere ed eseguire codice Python per rispondere a domande complesse, di solito legate alla matematica. Ad esempio, con questo strumento, se gli chiediamo di calcolare la somma dei primi 10 numeri primi, prima scriverà del codice Python per calcolarla, poi lo eseguirà e infine fornirà la risposta.
Per attivare lo strumento, facciamo così:
code_execution_tool = {"code_execution": {}}
config = {
"tools": [code_execution_tool],
"response_modalities": ["TEXT"],
}
Ecco un esempio del comportamento del modello con l'esecuzione di codice:
> add the first 10 prime numbers
Okay, I understand. You want me to add the first 10 prime numbers.
Here's my plan:
1. **Identify the first 10 prime numbers:** I will use a python code to find prime numbers.
2. **Sum the prime numbers:** I will also sum them using python.
3. **Report the result**
The first 10 prime numbers are 2, 3, 5, 7, 11, 13, 17, 19, 23, and 29. Their sum is 129.
Passaggio 6: crea un assistente visivo
In quest'ultima sezione, esploriamo le capacità visive di Gemini 2. L'obiettivo è creare un assistente AI in grado di comprendere il contenuto del nostro schermo e rispondere a domande al riguardo. Questo può essere utile, per esempio, quando gli chiediamo di spiegare un errore che vediamo nel terminale o di fornire informazioni su qualcosa attualmente visualizzato sullo schermo.
Negli esempi precedenti, abbiamo usato la programmazione asincrona per connetterci al modello AI e inviare dati avanti e indietro elaborando le risposte in tempo reale. Purtroppo, la versione attuale dell'SDK non supporta ancora la comunicazione in tempo reale con le immagini. Invece, forniamo i dati dell'immagine tramite un flusso richiesta-risposta. Nota che questa non è una limitazione di Gemini 2.0 in sé—è solo che l'attuale API beta non lo supporta ancora.
Inviare una richiesta sincrona a Google GenAI
Iniziamo imparando come inviare una richiesta con dati immagine alla Google GenAI API. Ecco come possiamo inviare una richiesta sincrona:
from google import genai
from dotenv import load_dotenv
import os
load_dotenv()
client = genai.Client(
api_key=os.getenv("GOOGLE_API_KEY"),
http_options={"api_version": "v1alpha"},
)
response = client.models.generate_content(
model="gemini-2.0-flash-exp",
contents=["Hello"],
)
print(response.text)
La differenza principale in questo esempio è che usiamo client.models.generate_content per inviare una richiesta all'API. Si tratta di una richiesta sincrona, il che significa che non offre un'esperienza di conversazione in tempo reale.
Inviare un'immagine
Possiamo inviare un'immagine caricandola e aggiungendola alla lista contents. Usiamo il pacchetto PIL per creare una funzione chiamata load_and_resize_image() che carica e ridimensiona l'immagine.
from PIL import Image
def load_and_resize_image(image_path):
with Image.open(image_path) as img:
aspect_ratio = img.height / img.width
new_height = int(img.width * aspect_ratio)
return img.resize((img.width, new_height), Image.Resampling.LANCZOS)
image = load_and_resize_image("example_image.jpeg")
response = client.models.generate_content(
model="gemini-2.0-flash-exp",
contents=["Describe the image", image],
)
print(response.text)
Creare l'assistente visivo AI
L'assistente visivo AI elabora un prompt testuale insieme a uno screenshot per aiutarci a rispondere a domande su ciò che c'è sullo schermo. Ho sperimentato a lungo e il modello riesce a comprendere il contenuto dello schermo anche quando sono aperte più finestre.
Il modo più semplice per fornire al modello il contenuto dello schermo è fare uno screenshot. Per questo usiamo il pacchetto pyautogui, una libreria multipiattaforma per controllare in modo programmatico mouse e tastiera per automatizzare attività. Nel nostro caso, la useremo solo per fare screenshot, anche se potremmo estenderne la funzionalità per consentire all'AI di eseguire attività sul nostro computer in autonomia.
Ecco una funzione per fare uno screenshot:
def capture_screen():
timestamp = time.strftime("%Y%m%d-%H%M%S")
filename = f"screenshot_{timestamp}.jpeg"
screenshot = pyautogui.screenshot()
screenshot = screenshot.convert("RGB")
screenshot.save(filename, format="JPEG")
return filename
Per renderlo interattivo, ripetiamo i passaggi seguenti finché l'utente non decide di uscire dall'applicazione:
- Chiedere all'utente di inserire un prompt.
- Fare uno screenshot e inviarlo al modello AI insieme al prompt.
- Mostrare il risultato all'utente.
C'è una cosa da tenere a mente con questo approccio. L'applicazione girerà nel terminale, che è anch'esso visualizzato sullo schermo. Pertanto, è meglio istruire il modello a ignorare la finestra del terminale. Questo si può fare aggiungendo una system_instruction alla configurazione:
client.models.generate_content(
model="gemini-2.0-flash-exp",
contents=[prompt, screen],
config=types.GenerateContentConfig(
system_instruction="Ignore the terminal window in the image when analyzing the image",
),
)
Mettendo tutto insieme, ecco il nostro assistente visivo AI. Il file con il codice completo è disponibile anche come vision.py nel repository.
from google import genai
from google.genai import types
from PIL import Image
import pyautogui
import time
import os
from dotenv import load_dotenv
load_dotenv()
# Initialize the GenAI client
client = genai.Client(
api_key=os.getenv("GOOGLE_API_KEY"),
http_options={"api_version": "v1alpha"},
)
def capture_screen():
timestamp = time.strftime("%Y%m%d-%H%M%S")
filename = f"screenshot_{timestamp}.jpeg"
screenshot = pyautogui.screenshot()
screenshot = screenshot.convert("RGB")
screenshot.save(filename, format="JPEG")
return filename
def load_and_resize_image(image_path):
with Image.open(image_path) as img:
aspect_ratio = img.height / img.width
new_height = int(img.width * aspect_ratio)
return img.resize((img.width, new_height), Image.Resampling.LANCZOS)
def get_genai_response(prompt):
print("Analyzing screen...")
screen = load_and_resize_image(capture_screen())
response = client.models.generate_content(
model="gemini-2.0-flash-exp",
contents=[prompt, screen],
config=types.GenerateContentConfig(
system_instruction="Ignore the terminal window in the image when analyzing the image",
),
)
return response.text
def main():
while True:
prompt = input("> ")
print()
if prompt == "exit":
break
answer = get_genai_response(prompt)
print(answer)
print()
if __name__ == "__main__":
main()
La versione attuale è un po' macchinosa: richiede che il terminale sia aperto in primo piano per poterla attivare. Un passo successivo naturale sarebbe eseguirla in background e usare input e output vocali invece del testo.
Conclusione
Abbiamo imparato a usare il modello Gemini 2.0 Flash per diverse applicazioni, come sviluppare chatbot capaci di conversazioni in tempo reale con testo e voce, abilitare il modello AI a eseguire azioni tramite chiamate di funzione e creare un assistente visivo in grado di analizzare i contenuti dello schermo del nostro computer.
Se vuoi approfondire, Google fornisce due esempi che mostrano la capacità del modello di rilevare oggetti in un'immagine fornendo i relativi riquadri di delimitazione con etichette. Questo esempio si concentra sulla comprensione spaziale 2D chiedendo al modello di identificare ed etichettare i cupcake in una foto. Gemini può anche comprendere il contesto 3D di un'immagine, come mostrato qui.
Nel complesso, Gemini 2.0 è piuttosto promettente, nonostante l'attuale versione dell'API non ci permetta ancora di sfruttarlo al massimo. Non vedo l'ora di usare appieno le capacità multimodali in tempo reale nel prossimo futuro.



Google ha annunciato di recente Gemini 2.0, con il modello Gemini 2.0 Flash al centro—una versione più veloce e più potente pensata per migliorare l'elaborazione di immagini e suoni.
In questo tutorial ti guiderò nei passaggi per usare Gemini 2.0 Flash e creare un assistente visivo che sappia leggere ciò che c'è sullo schermo e rispondere alle domande al riguardo.
Ecco una demo di ciò che costruiremo: