importar subproceso, sys subproceso.check_call(
[sys.executable, “-m”, “pip”, “install”, “-qU”, “google-genai”]stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) importar getpass, json, textwrap, os, time desde google importar genai desde google.genai importar tipos si “GOOGLE_API_KEY” no está en os.environ: os.environ[“GOOGLE_API_KEY”] = getpass.getpass(“Ingrese su clave API de Gemini: “) client = genai.Client(api_key=os.environ[“GOOGLE_API_KEY”]) TOOL_COMBO_MODEL = “gemini-3-flash-preview” MAPS_MODEL = “gemini-2.5-flash” DIVIDER = “=” * 72 def encabezado(título: cadena): print(f”\n{DIVIDER}”) print(f” {título}”) print(DIVIDER) def wrap(texto: cadena, ancho: int = 80): para línea en text.splitlines(): print(textwrap.fill(línea, ancho=ancho) if line.strip() else “”) def describe_parts(respuesta): partes = respuesta.candidatos[0].content.parts fc_ids = {} para i, parte en enumerar(partes): prefijo = f” Parte {i:2d}:” if hasattr(part, “tool_call”) y part.tool_call: tc = part.tool_call print(f”{prefix} [toolCall] type={tc.tool_type} id={tc.id}”) si hasattr(part, “tool_response”) y part.tool_response: tr = part.tool_response print(f”{prefix} [toolResponse] type={tr.tool_type} id={tr.id}”) si hasattr(part, “executable_code”) y part.executable_code: code = part.executable_code.code[:90].replace(“\n”, ” ↵ “) print(f”{prefijo} [executableCode] {código}…”) si hasattr(part, “code_execution_result”) y part.code_execution_result: out = (part.code_execution_result.output o “”)[:90]
imprimir(f”{prefijo} [codeExecResult] {out}”) si hasattr(part, “function_call”) y part.function_call: fc = part.function_call fc_ids[fc.name] = fc.id print(f”{prefijo} [functionCall] nombre={fc.name} id={fc.id}”) print(f” └─ args: {dict(fc.args)}”) if hasattr(part, “text”) y part.text: snippet = part.text[:110].replace(“\n”, ” “) print(f”{prefijo} [text] {snippet}…”) if hasattr(part, “think_signature”) and part.think_signature: print(f” └─ think_signature present ✓”) return fc_ids header(“DEMO 1: Combine la búsqueda de Google + una función personalizada en una sola solicitud”) print(“”” Esta demostración muestra la nueva característica emblemática: pasar AMBOS una herramienta integrada (Búsqueda de Google) y una declaración de función personalizada en una sola llamada API. Gemini hará lo siguiente: 1 → Busque en la web información en tiempo real, luego solicite nuestra función personalizada para obtener datos meteorológicos. Turno 2 → Proporcionamos la respuesta de la función Gemini sintetiza todo: • google_search y function_declarations van en el MISMO objeto de herramienta • include_server_side_tool_invocations debe ser Verdadero (en ToolConfig) • Devuelve TODAS las partes (incluidas las firmas de pensamiento) en turnos posteriores “””) get_weather_func = tipos.FunctionDeclaration( name=”getWeather”, descripción=”Obtiene el clima actual para una ciudad solicitada.”, parámetros=types.Schema( type=”OBJECT”, properties={ “ciudad”: tipos.Schema( type=”STRING”, descripción=”La ciudad y el estado, por ejemplo, Utqiagvik, Alaska”, ), }, requerido=[“city”]), ) print(“▶ Turno 1: Envío de mensaje con Búsqueda de Google + herramientas getWeather…\n”) respuesta_1 = client.models.generate_content( model=TOOL_COMBO_MODEL,contents=( “¿Cuál es la ciudad más septentrional de los Estados Unidos? ” “¿Cómo está el clima allí hoy?”), config=types.GenerateContentConfig( tools=[
types.Tool(
google_search=types.GoogleSearch(),
function_declarations=[get_weather_func]), ], tool_config=types.ToolConfig( include_server_side_tool_invocations=True, ), ), ) print(” Piezas devueltas por el modelo:\n”) fc_ids = describe_parts(response_1) function_call_id = fc_ids.get(“getWeather”) print(f”\n ✅ ID de llamada de función capturada para getWeather: {function_call_id}”) print(“\n▶ Turno 2: Devolver el resultado de la función y solicitar la síntesis final…\n”) historial = [
types.Content(
role=”user”,
parts=[
types.Part(
text=(
“What is the northernmost city in the United States? ”
“What’s the weather like there today?”
)
)
]), respuesta_1.candidatos[0].contenido, tipos.Contenido( rol=”usuario”, partes=[
types.Part(
function_response=types.FunctionResponse(
name=”getWeather”,
response={“response”: “Very cold. 22°F / -5.5°C with strong Arctic winds.”},
id=function_call_id,
)
)
]), ]respuesta_2 = client.models.generate_content( modelo=TOOL_COMBO_MODEL, contenidos=historial, config=types.GenerateContentConfig( herramientas=[
types.Tool(
google_search=types.GoogleSearch(),
function_declarations=[get_weather_func]), ], tool_config=types.ToolConfig( include_server_side_tool_invocations=True, ), ), ) print(” ✅ Respuesta final sintetizada:\n”) para parte en respuesta_2.candidates[0].content.parts: si hasattr(part, “texto”) y part.text: wrap(part.text)
[sys.executable, “-m”, “pip”, “install”, “-qU”, “google-genai”]stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, ) importar getpass, json, textwrap, os, time desde google importar genai desde google.genai importar tipos si “GOOGLE_API_KEY” no está en os.environ: os.environ[“GOOGLE_API_KEY”] = getpass.getpass(“Ingrese su clave API de Gemini: “) client = genai.Client(api_key=os.environ[“GOOGLE_API_KEY”]) TOOL_COMBO_MODEL = “gemini-3-flash-preview” MAPS_MODEL = “gemini-2.5-flash” DIVIDER = “=” * 72 def encabezado(título: cadena): print(f”\n{DIVIDER}”) print(f” {título}”) print(DIVIDER) def wrap(texto: cadena, ancho: int = 80): para línea en text.splitlines(): print(textwrap.fill(línea, ancho=ancho) if line.strip() else “”) def describe_parts(respuesta): partes = respuesta.candidatos[0].content.parts fc_ids = {} para i, parte en enumerar(partes): prefijo = f” Parte {i:2d}:” if hasattr(part, “tool_call”) y part.tool_call: tc = part.tool_call print(f”{prefix} [toolCall] type={tc.tool_type} id={tc.id}”) si hasattr(part, “tool_response”) y part.tool_response: tr = part.tool_response print(f”{prefix} [toolResponse] type={tr.tool_type} id={tr.id}”) si hasattr(part, “executable_code”) y part.executable_code: code = part.executable_code.code[:90].replace(“\n”, ” ↵ “) print(f”{prefijo} [executableCode] {código}…”) si hasattr(part, “code_execution_result”) y part.code_execution_result: out = (part.code_execution_result.output o “”)[:90]
imprimir(f”{prefijo} [codeExecResult] {out}”) si hasattr(part, “function_call”) y part.function_call: fc = part.function_call fc_ids[fc.name] = fc.id print(f”{prefijo} [functionCall] nombre={fc.name} id={fc.id}”) print(f” └─ args: {dict(fc.args)}”) if hasattr(part, “text”) y part.text: snippet = part.text[:110].replace(“\n”, ” “) print(f”{prefijo} [text] {snippet}…”) if hasattr(part, “think_signature”) and part.think_signature: print(f” └─ think_signature present ✓”) return fc_ids header(“DEMO 1: Combine la búsqueda de Google + una función personalizada en una sola solicitud”) print(“”” Esta demostración muestra la nueva característica emblemática: pasar AMBOS una herramienta integrada (Búsqueda de Google) y una declaración de función personalizada en una sola llamada API. Gemini hará lo siguiente: 1 → Busque en la web información en tiempo real, luego solicite nuestra función personalizada para obtener datos meteorológicos. Turno 2 → Proporcionamos la respuesta de la función Gemini sintetiza todo: • google_search y function_declarations van en el MISMO objeto de herramienta • include_server_side_tool_invocations debe ser Verdadero (en ToolConfig) • Devuelve TODAS las partes (incluidas las firmas de pensamiento) en turnos posteriores “””) get_weather_func = tipos.FunctionDeclaration( name=”getWeather”, descripción=”Obtiene el clima actual para una ciudad solicitada.”, parámetros=types.Schema( type=”OBJECT”, properties={ “ciudad”: tipos.Schema( type=”STRING”, descripción=”La ciudad y el estado, por ejemplo, Utqiagvik, Alaska”, ), }, requerido=[“city”]), ) print(“▶ Turno 1: Envío de mensaje con Búsqueda de Google + herramientas getWeather…\n”) respuesta_1 = client.models.generate_content( model=TOOL_COMBO_MODEL,contents=( “¿Cuál es la ciudad más septentrional de los Estados Unidos? ” “¿Cómo está el clima allí hoy?”), config=types.GenerateContentConfig( tools=[
types.Tool(
google_search=types.GoogleSearch(),
function_declarations=[get_weather_func]), ], tool_config=types.ToolConfig( include_server_side_tool_invocations=True, ), ), ) print(” Piezas devueltas por el modelo:\n”) fc_ids = describe_parts(response_1) function_call_id = fc_ids.get(“getWeather”) print(f”\n ✅ ID de llamada de función capturada para getWeather: {function_call_id}”) print(“\n▶ Turno 2: Devolver el resultado de la función y solicitar la síntesis final…\n”) historial = [
types.Content(
role=”user”,
parts=[
types.Part(
text=(
“What is the northernmost city in the United States? ”
“What’s the weather like there today?”
)
)
]), respuesta_1.candidatos[0].contenido, tipos.Contenido( rol=”usuario”, partes=[
types.Part(
function_response=types.FunctionResponse(
name=”getWeather”,
response={“response”: “Very cold. 22°F / -5.5°C with strong Arctic winds.”},
id=function_call_id,
)
)
]), ]respuesta_2 = client.models.generate_content( modelo=TOOL_COMBO_MODEL, contenidos=historial, config=types.GenerateContentConfig( herramientas=[
types.Tool(
google_search=types.GoogleSearch(),
function_declarations=[get_weather_func]), ], tool_config=types.ToolConfig( include_server_side_tool_invocations=True, ), ), ) print(” ✅ Respuesta final sintetizada:\n”) para parte en respuesta_2.candidates[0].content.parts: si hasattr(part, “texto”) y part.text: wrap(part.text)