Crea un agente de canalización de consultas de LlamaIndex

Agent Runtime te permite desarrollar e implementar agentes con la plantilla de canalizaciones de consultas de LlamaIndex. Con la clase LlamaIndexQueryPipelineAgent en Agent Platform SDK, puedes crear agentes diseñados para la generación mejorada por recuperación (RAG).

En este documento, se explica cómo desarrollar un agente de LlamaIndex Query Pipeline, lo que incluye definir el modelo, configurar un recuperador y sintetizar respuestas.

Para obtener más información sobre cómo administrar los agentes implementados, consulta Administra agentes implementados.

Antes de comenzar

Asegúrate de que tu entorno esté configurado con los pasos que se indican en Configura tu entorno.

Define y configura un modelo

Define y configura un modelo para que lo use tu agente de canalización de consultas de LlamaIndex:

  1. Especifica el modelo que quieres usar:

    model = "gemini-3.5-flash"
    
  2. Opcional: Especifica los parámetros del modelo:

    model_kwargs = {
        # vertexai_config (dict): By providing the region and project_id parameters,
        # you can enable model usage through Agent Platform.
        "vertexai_config": {
            "project": "PROJECT_ID",
            "location": "LOCATION"
        },
        # temperature (float): The sampling temperature controls the degree of
        # randomness in token selection.
        "temperature": 0.28,
        # context_window (int): The context window of the model.
        # If not provided, the default context window is 200000.
        "context_window": 200000,
        # max_tokens (int): Token limit determines the maximum
        # amount of text output from one prompt. If not provided,
        # the default max_tokens is 256.
        "max_tokens": 256,
    }
    
  3. Crea un LlamaIndexQueryPipelineAgent con los siguientes parámetros de configuración del modelo:

    from vertexai.preview import reasoning_engines
    
    agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
        model=model,                # Required.
        model_kwargs=model_kwargs,  # Optional.
    )
    
  4. Si ejecutas el código en un entorno interactivo (como la terminal o un notebook de Colab), puedes consultar al agente:

    response = agent.query(input="What is Paul Graham's life in college?")
    
    print(response)
    

    Deberías recibir una respuesta similar a la que figura a continuación:

    {'message': {'role': 'assistant',
      'additional_kwargs': {},
      'blocks': [{'block_type': 'text',
        'text': "Unfortunately, there's not a lot of publicly available information about Paul Graham's personal life in college. ..."}]},
      'raw': {'content': {'parts': [{'video_metadata': None,
          'thought': None,
          'code_execution_result': None,
          'executable_code': None,
          'file_data': None,
          'function_call': None,
          'function_response': None,
          'inline_data': None,
          'text': "Unfortunately, there's not a lot of publicly available information about Paul Graham's personal life in college. ..."}],
        'role': 'model'},
        'citation_metadata': None,
        'finish_message': None,
        'token_count': None,
        'avg_logprobs': -0.1468650027438327,
        'finish_reason': 'STOP',
        'grounding_metadata': None,
        'index': None,
        'logprobs_result': None,
        'safety_ratings': [{'blocked': None,
          'category': 'HARM_CATEGORY_HATE_SPEECH',
          'probability': 'NEGLIGIBLE',
          'probability_score': 0.022949219,
          'severity': 'HARM_SEVERITY_NEGLIGIBLE',
          'severity_score': 0.014038086},
        {'blocked': None,
          'category': 'HARM_CATEGORY_DANGEROUS_CONTENT',
          'probability': 'NEGLIGIBLE',
          'probability_score': 0.056640625,
          'severity': 'HARM_SEVERITY_NEGLIGIBLE',
          'severity_score': 0.029296875},
        {'blocked': None,
          'category': 'HARM_CATEGORY_HARASSMENT',
          'probability': 'NEGLIGIBLE',
          'probability_score': 0.071777344,
          'severity': 'HARM_SEVERITY_NEGLIGIBLE',
          'severity_score': 0.024047852},
        {'blocked': None,
          'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
          'probability': 'NEGLIGIBLE',
          'probability_score': 0.103515625,
          'severity': 'HARM_SEVERITY_NEGLIGIBLE',
          'severity_score': 0.05102539}],
        'usage_metadata': {'cached_content_token_count': None,
        'candidates_token_count': 222,
        'prompt_token_count': 10,
        'total_token_count': 232}},
      'delta': None,
      'logprobs': None,
      'additional_kwargs': {}}
    

Opcional: Personaliza tu modelo

La plantilla LlamaIndexQueryPipelineAgent usa Google GenAI de forma predeterminada para proporcionar acceso a todos los modelos fundamentales disponibles en Google Cloud. Para usar un modelo que no está disponible a través de Google GenAI, define model_builder= de la siguiente manera:

from typing import Optional

def model_builder(
    *,
    model_name: str,                      # Required. The name of the model
    model_kwargs: Optional[dict] = None,  # Optional. The model keyword arguments.
    **kwargs,                             # Optional. The remaining keyword arguments to be ignored.
):

Para obtener una lista de los modelos de chat compatibles con LlamaIndexQueryPipeline y sus capacidades, consulta Integraciones de LLM disponibles. Cada modelo de chat usa su propio conjunto de valores admitidos para model= y model_kwargs=.

IA generativa de Google

La IA generativa de Google se instala de forma predeterminada cuando configuras tu entorno y se usa automáticamente en LlamaIndexQueryPipelineAgent cuando omites model_builder.

from vertexai.preview import reasoning_engines

agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
    model=model,                # Required.
    model_kwargs=model_kwargs,  # Optional.
)

Anthropic

  1. Sigue la documentación de Anthropic para configurar una cuenta y, luego, instala el paquete llama-index-llms-anthropic.

  2. Define model_builder para devolver el modelo Anthropic:

    def model_builder(*, model_name: str, model_kwargs = None, **kwargs):
        from llama_index.llms.anthropic import Anthropic
    
        return Anthropic(model=model_name, **model_kwargs)
    
  3. Usa el modelo de Anthropic en LlamaIndexQueryPipelineAgent:

    from vertexai.preview import reasoning_engines
    
    agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
        model="claude-3-opus-20240229",           # Required.
        model_builder=model_builder,              # Required.
        model_kwargs={
            "api_key": "ANTHROPIC_API_KEY",    # Required.
            "temperature": 0.28,                  # Optional.
        },
    )
    

OpenAILike

Puedes usar OpenAILike con la API de ChatCompletions de Gemini.

  1. Sigue la documentación de OpenAILike para instalar el paquete:

    pip install llama-index-llms-openai-like
    
  2. Define un model_builder que devuelva el modelo OpenAILike:

    def model_builder(
        *,
        model_name: str,
        model_kwargs = None,
        project: str,   # Specified via vertexai.init
        location: str,  # Specified via vertexai.init
        **kwargs,
    ):
        import google.auth
        from llama_index.llms.openai_like import OpenAILike
    
        # Note: the credential lives for 1 hour by default.
        # After expiration, it must be refreshed.
        creds, _ = google.auth.default(scopes=["https://www.googleapis.com/auth/cloud-platform"])
        auth_req = google.auth.transport.requests.Request()
        creds.refresh(auth_req)
    
        if model_kwargs is None:
            model_kwargs = {}
    
        endpoint = f"https://{location}-aiplatform.googleapis.com"
        api_base = f'{endpoint}/v1beta1/projects/{project}/locations/{location}/endpoints/openapi'
    
        return OpenAILike(
            model=model_name,
            api_base=api_base,
            api_key=creds.token,
            **model_kwargs,
        )
    
  3. Usa el modelo en LlamaIndexQueryPipelineAgent:

    from vertexai.preview import reasoning_engines
    
    agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
        model="google/gemini-3.5-flash",  # Or "meta/llama3-405b-instruct-maas"
        model_builder=model_builder,        # Required.
        model_kwargs={
            "temperature": 0,               # Optional.
            "max_retries": 2,               # Optional.
        },
    )
    

Cómo definir y usar un recuperador

Después de definir el modelo, define el recuperador que usa el modelo para el razonamiento. Un recuperador se puede crear sobre la base de índices, pero también se puede definir de forma integral. Debes probar el recuperador de forma local.

  1. Define un recuperador que devuelva documentos pertinentes y puntuaciones de similitud:

    def retriever_builder(model, retriever_kwargs=None):
        import os
        import requests
        from llama_index.core import (
            StorageContext,
            VectorStoreIndex,
            load_index_from_storage,
        )
        from llama_index.core import SimpleDirectoryReader
        from llama_index.embeddings.vertex import VertexTextEmbedding
        import google.auth
    
        credentials, _ = google.auth.default()
        embed_model = VertexTextEmbedding(
            model_name="text-embedding-005", project="PROJECT_ID", credentials=credentials
        )
    
        data_dir = "data/paul_graham"
        essay_file = os.path.join(data_dir, "paul_graham_essay.txt")
        storage_dir = "storage"
    
        # --- Simple Download (if needed) ---
        if not os.path.exists(essay_file):
            os.makedirs(data_dir, exist_ok=True)  # Make sure the directory exists
            essay_url = "https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt"
            try:
                response = requests.get(essay_url)
                response.raise_for_status()  # Check for download errors
                with open(essay_file, "wb") as f:
                    f.write(response.content)
                print("Essay downloaded.")
            except requests.exceptions.RequestException as e:
                print(f"Download failed: {e}")
    
        # --- Build/Load Index ---
        if not os.path.exists(storage_dir):
            print("Creating new index...")
            # --- Load Data ---
            reader = SimpleDirectoryReader(data_dir)
            docs = reader.load_data()
    
            index = VectorStoreIndex.from_documents(docs, model=model, embed_model=embed_model)
            index.storage_context.persist(persist_dir=storage_dir)
        else:
            print("Loading existing index...")
            storage_context = StorageContext.from_defaults(persist_dir=storage_dir)
            index = load_index_from_storage(storage_context, embed_model=embed_model)
    
        return index.as_retriever()
    
  2. Prueba el recuperador:

    from llama_index.llms.google_genai import GoogleGenAI
    
    model = GoogleGenAI(
        model=model,
        **model_kwargs
    )
    retriever = retriever_builder(model)
    retrieved_response = retriever.retrieve("What is Paul Graham's life in College?")
    

    La respuesta recuperada debería ser similar a la siguiente:

    [
      NodeWithScore(
        node=TextNode(
          id_='692a5d5c-cd56-4ed0-8e29-ecadf6eb9933',
          embedding=None,
          metadata={'file_path': '/content/data/paul_graham/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75042, 'creation_date': '2025-03-24', 'last_modified_date': '2025-03-24'},
          excluded_embed_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'],
          excluded_llm_metadata_keys=['file_name', 'file_type', 'file_size', 'creation_date', 'last_modified_date', 'last_accessed_date'],
          relationships={
            <NodeRelationship.SOURCE: '1'>: RelatedNodeInfo(node_id='3e1c4d73-1e1d-4e83-bd16-2dae24abb231', node_type='4', metadata={'file_path': '/content/data/paul_graham/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75042, 'creation_date': '2025-03-24', 'last_modified_date': '2025-03-24'}, hash='0c3c3f46cac874b495d944dfc4b920f6b68817dbbb1699ecc955d1fafb2bf87b'), <NodeRelationship.PREVIOUS: '2'>: RelatedNodeInfo(node_id='782c5787-8753-4f65-85ed-c2833ea6d4d8', node_type='1', metadata={'file_path': '/content/data/paul_graham/paul_graham_essay.txt', 'file_name': 'paul_graham_essay.txt', 'file_type': 'text/plain', 'file_size': 75042, 'creation_date': '2025-03-24', 'last_modified_date': '2025-03-24'}, hash='b8e6463833887a8a2b13f1b5a623672819faedc1b725d9565ba003223628db0e'), <NodeRelationship.NEXT: '3'>: RelatedNodeInfo(node_id='f7d2cb7e-fa0c-40bf-b8e7-b888e36b87f9', node_type='1', metadata={}, hash='db7cc1a67fa3afd1e5f24c8c61583781ce6a00c444da8f25a5374468c17b7de0')
          },
          metadata_template='{key}: {value}',
          metadata_separator='\n',
          text='So I looked around to see what I could salvage from the wreckage of my plans, and there was Lisp...',
          mimetype='text/plain',
          start_char_idx=7166,
          end_char_idx=11549,
          metadata_separator='\n',
          text_template='{metadata_str}\n\n{content}'
        ),
        score=0.7403571819090398
      )
    ]
    
  3. Para usar el recuperador dentro de LlamaIndexQueryPipelineAgent, agrégalo en el argumento retriever_builder=:

    from vertexai.preview import reasoning_engines
    
    agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
        model=model,                          # Required.
        model_kwargs=model_kwargs,            # Optional.
        retriever_builder=retriever_builder,  # Optional.
    )
    
  4. Prueba el agente localmente con consultas de prueba:

    response = agent.query(
        input="What is Paul Graham's life in College?"
    )
    

    La respuesta es una lista de nodos con puntuaciones que se puede serializar en JSON.

    [{'node': {'id_': '692a5d5c-cd56-4ed0-8e29-ecadf6eb9933',
      'embedding': None,
      'metadata': {'file_path': '/content/data/paul_graham/paul_graham_essay.txt',
        'file_name': 'paul_graham_essay.txt',
        'file_type': 'text/plain',
        'file_size': 75042,
        'creation_date': '2025-03-12',
        'last_modified_date': '2025-03-12'},
      'excluded_embed_metadata_keys': ['file_name',
        'file_type',
        'file_size',
        'creation_date',
        'last_modified_date',
        'last_accessed_date'],
      'excluded_llm_metadata_keys': ['file_name',
        'file_type',
        'file_size',
        'creation_date',
        'last_modified_date',
        'last_accessed_date'],
      'relationships': {'1': {'node_id': '07ee9574-04c8-46c7-b023-b22ba9558a1f',
        'node_type': '1',
        'metadata': {},
        'hash': '44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a',
        'class_name': 'RelatedNodeInfo'},
        '2': {'node_id': 'ac7e54aa-6fff-40b5-a15e-89c5eb234936',
        'node_type': '1',
        'metadata': {'file_path': '/content/data/paul_graham/paul_graham_essay.txt',
          'file_name': 'paul_graham_essay.txt',
          'file_type': 'text/plain',
          'file_size': 75042,
          'creation_date': '2025-03-12',
          'last_modified_date': '2025-03-12'},
        'hash': '755327a01efe7104db771e4e6f9683417884ea6895d878da882d2b21a6b66442',
        'class_name': 'RelatedNodeInfo'},
        '3': {'node_id': '3a04be27-ac46-4acd-a8c6-031689508982',
        'node_type': '1',
        'metadata': {},
        'hash': 'db7cc1a67fa3afd1e5f24c8c61583781ce6a00c444da8f25a5374468c17b7de0',
        'class_name': 'RelatedNodeInfo'}},
      'metadata_template': '{key}: {value}',
      'metadata_separator': '\n',
      'text': 'So I looked around to see what I could salvage from the wreckage of my plans, and there was Lisp...',
      'mimetype': 'text/plain',
      'start_char_idx': 7164,
      'end_char_idx': 11547,
      'metadata_separator': '\n',
      'text_template': '{metadata_str}\n\n{content}',
      'class_name': 'TextNode'},
      'score': 0.25325886336265013,
      'class_name': 'NodeWithScore'}
    ]
    

Cómo definir y usar un sintetizador de respuestas

Después de definir tu modelo y recuperador, define el sintetizador de respuestas que genera una respuesta a partir de un LLM con una consulta del usuario y un conjunto determinado de fragmentos de texto. Puedes usar el get_response_synthesizer predeterminado o configurar el modo de respuesta.

  1. Define un sintetizador de respuestas que devuelva la respuesta:

    def response_synthesizer_builder(model, response_synthesizer_kwargs=None):
        from llama_index.core.response_synthesizers import SimpleSummarize
    
        return SimpleSummarize(llm=model)
    
  2. Sigue estos pasos para probar la función:

    response_synthesizer = response_synthesizer_builder(model=model)
    response = response_synthesizer.get_response(
        "What is Paul Graham's life in College?",
        [node.model_dump_json() for node in retrieved_response],
    )
    

    La respuesta podría ser similar a la siguiente:

    "While in a PhD program for computer science, he took art classes and worked on a book about Lisp hacking. He applied to art schools, got accepted to RISD, and later got an invitation to take the entrance exam at the Accademia di Belli Arti in Florence. He was accepted to both. He attended the Accademia, but was disappointed by the lack of instruction."
    
  3. Para usar el sintetizador de respuestas dentro de LlamaIndexQueryPipelineAgent, agrégalo en el argumento response_synthesizer_builder=:

    from vertexai.preview import reasoning_engines
    
    agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
        model=model,                                                    # Required.
        model_kwargs=model_kwargs,                                      # Optional.
        retriever_builder=retriever_builder,                            # Optional.
        response_synthesizer_builder=response_synthesizer_builder,      # Optional.
    )
    
  4. Ejecuta consultas de prueba para probar la canalización de consultas de RAG completa de forma local:

    response = agent.query(
        input="What is Paul Graham's life in College?"
    )
    

    La respuesta es un diccionario similar al siguiente:

    {
      'response': "While in college, he was drawn to McCarthy's 1960 Lisp, although he didn't fully grasp the reasons for his interest at the time. He also had a brief encounter with surplus Xerox Dandelions in the computer lab but found them too slow for his liking. \n",
      'source_nodes': [
        '{"node":{"id_":"95889c30-53c7-43d0-bf91-930dbb23bde6"...,"score":0.7077213268404997,"class_name":"NodeWithScore"}'
      ],
      'metadata': {
        '95889c30-53c7-43d0-bf91-930dbb23bde6': {
          'file_path': '/content/data/paul_graham/paul_graham_essay.txt',
          'file_name': 'paul_graham_essay.txt',
          'file_type': 'text/plain',
          'file_size': 75042,
          'creation_date': '2025-03-25',
          'last_modified_date': '2025-03-25'
        }
      }
    }
    

Opcional: Personaliza la plantilla de instrucciones

Las plantillas de instrucciones traducen la entrada del usuario en instrucciones para el modelo, lo que guía las respuestas para obtener resultados coherentes y pertinentes según el contexto. Consulta Instrucciones para obtener más detalles.

La plantilla de instrucciones predeterminada se organiza de forma secuencial en las siguientes secciones:

Sección Descripción
Opcional: Instrucción del sistema Son instrucciones para que el agente se aplique en todas las consultas.
Entrada del usuario Es la consulta del usuario que el agente debe responder.

La plantilla de instrucciones predeterminada se genera si creas el agente sin especificar tu propia plantilla de instrucciones y se verá de la siguiente manera:

from llama_index.core import prompts
from llama_index.core.base.llms import types

message_templates = [
  types.ChatMessage(role=types.MessageRole.SYSTEM, content=system_instruction),
  types.ChatMessage(role=types.MessageRole.USER, content="{input}"),
]
prompts.ChatPromptTemplate(message_templates=message_templates)

Puedes usar la plantilla de instrucciones completa cuando crees una instancia del agente, como se muestra en el siguiente ejemplo:

  from vertexai.preview import reasoning_engines

  system_instruction = "I help to find what is Paul Graham's life in College"

  agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
      model=model,
      system_instruction=system_instruction,
  )

Puedes anular la plantilla de instrucciones predeterminada con tu propia plantilla de instrucciones y usarla cuando construyas el agente:

prompt_str = "Please answer {question} about {name}"
prompt_tmpl = PromptTemplate(prompt_str)

from vertexai.preview import reasoning_engines
agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
    model = model,
    prompt = prompt_tmpl,
)

agent.query(
    input={
        "name": "Paul Graham",
        "question": "What is the life in college?",
    }
)

Opcional: Personaliza la organización

Todos los componentes de LlamaIndexQueryPipeline implementan la interfaz de componente de consulta, que proporciona esquemas de entrada y salida para la organización. La clase LlamaIndexQueryPipelineAgent requiere que se compile un elemento ejecutable para que responda a las consultas. De forma predeterminada, LlamaIndexQueryPipelineAgent compila una cadena secuencial o un grafo acíclico dirigido (DAG) con Query Pipeline.

Es posible que desees personalizar la orquestación si planeas hacer alguna de las siguientes acciones:

  • Implementa un agente que extienda la canalización de RAG (por ejemplo, extender un módulo existente de Prompt, Model, Retriever o Response Synthesizer a Query Engine, Query Transformer, Output Parsers, Postprocessor/Rerankers o Custom Query Component).

  • Indica al agente que use ReAct para ejecutar herramientas y anotar cada paso con comentarios sobre por qué realizó ese paso. Para ello, anula el ejecutable predeterminado cuando crees LlamaIndexQueryPipelineAgent especificando el argumento runnable_builder=:

    from typing import Optional
    from llama_index.core.llms import function_calling
    
    def runnable_builder(
        model: function_calling.FunctionCallingLLM,
        *,
        system_instruction: Optional[str] = None,
        prompt: Optional[query.QUERY_COMPONENT_TYPE] = None,
        retriever: Optional[query.QUERY_COMPONENT_TYPE] = None,
        response_synthesizer: Optional[query.QUERY_COMPONENT_TYPE] = None,
        runnable_kwargs: Optional[Mapping[str, Any]] = None,
    ):
    

    Aquí:

    • model corresponde al modelo de chat que se muestra desde model_builder (consulta Define y configura un modelo).
    • retriever y retriever_kwargs corresponden al recuperador y a las configuraciones que se usarán (consulta Define un recuperador).
    • response_synthesizer y response_synthesizer_kwargs corresponden al sintetizador de respuestas y a las configuraciones que se usarán (consulta Cómo definir un sintetizador de respuestas).
    • system_instruction y prompt corresponden a la configuración de la instrucción (consulta Cómo personalizar la plantilla de instrucciones).
    • agent_executor_kwargs y runnable_kwargs son los argumentos de palabra clave que puedes usar para personalizar el elemento ejecutable.

Puedes personalizar la lógica de orquestación con una canalización personalizada o ReAct:

Canalización personalizada

Para proporcionar un módulo adicional (como un posprocesador) al agente, anula el runnable_builder de LlamaIndexQueryPipelineAgent.

  1. Define un posprocesador:

    def post_processor_builder():
      from llama_index.core.postprocessor import SimilarityPostprocessor
    
      # similarity postprocessor: filter nodes below 0.7 similarity score
      return SimilarityPostprocessor(similarity_cutoff=0.7)
    
    def runnable_with_postprocessor_builder(
        model, runnable_kwargs, **kwargs
    ):
      from llama_index.core.query_pipeline import QueryPipeline
    
      pipeline = QueryPipeline(**runnable_kwargs)
      pipeline_modules = {
          "retriever": retriever_builder(model),
          "postprocessor": post_processor_builder(),
      }
      pipeline.add_modules(pipeline_modules)
      pipeline.add_link("retriever", "postprocessor")
    
      return pipeline
    
    agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
      model=model,
      runnable_builder=runnable_with_postprocessor_builder,
    )
    
  2. Consulta al agente:

    result = agent.query(input="What is Paul Graham's life in College?")
    

    El resultado debería ser similar al siguiente ejemplo:

    [
      {
        'node': {'id_': 'bb7d2942-213d-4fb3-a7cb-1a664642a7ff',
        'embedding': None,
        'metadata': {
          'file_path': '/content/data/paul_graham/paul_graham_essay.txt',
          'file_name': 'paul_graham_essay.txt',
          'file_type': 'text/plain',
          'file_size': 75042,
          'creation_date': '2025-03-25',
          'last_modified_date': '2025-03-25'
        },
        'excluded_embed_metadata_keys': [
          'file_name',
          'file_type',
          'file_size',
          'creation_date',
          'last_modified_date',
          'last_accessed_date'
        ],
        'excluded_llm_metadata_keys': [
          'file_name',
          'file_type',
          'file_size',
          'creation_date',
          'last_modified_date',
          'last_accessed_date'
        ],
        'relationships': {'1': {'node_id': 'c508cee5-5ef2-4fdf-a33d-0427dcb78b5c',
          'node_type': '4',
          'metadata': {'file_path': '/content/data/paul_graham/paul_graham_essay.txt',
            'file_name': 'paul_graham_essay.txt',
            'file_type': 'text/plain',
            'file_size': 75042,
            'creation_date': '2025-03-25',
            'last_modified_date': '2025-03-25'},
          'hash': '0c3c3f46cac874b495d944dfc4b920f6b68817dbbb1699ecc955d1fafb2bf87b',
          'class_name': 'RelatedNodeInfo'},
          '2': {'node_id': '97a84b41-62bf-4959-acae-cfd4bdfbd4d9',
          'node_type': '1',
          'metadata': {'file_path': '/content/data/paul_graham/paul_graham_essay.txt',
            'file_name': 'paul_graham_essay.txt',
            'file_type': 'text/plain',
            'file_size': 75042,
            'creation_date': '2025-03-25',
            'last_modified_date': '2025-03-25'},
          'hash': 'a7dd352be97e47e8e553ceda3d2d2c9e9d5c54adb298063c94da06167938d583',
          'class_name': 'RelatedNodeInfo'},
          '3': {'node_id': 'b984eea1-f0bc-4880-812e-3f49f1e304b8',
          'node_type': '1',
          'metadata': {},
          'hash': 'db7cc1a67fa3afd1e5f24c8c61583781ce6a00c444da8f25a5374468c17b7de0',
          'class_name': 'RelatedNodeInfo'}},
        'metadata_template': '{key}: {value}',
        'metadata_separator': '\n',
        'text': 'So I looked around to see what I could salvage from the wreckage of my plans, and there was Lisp...',
        'mimetype': 'text/plain',
        'start_char_idx': 7166,
        'end_char_idx': 11549,
        'metadata_separator': '\n',
        'text_template': '{metadata_str}\n\n{content}',
        'class_name': 'TextNode'},
        'score': 0.7403571819090398,
        'class_name': 'NodeWithScore'
      },
      {
        'node': {'id_': 'b984eea1-f0bc-4880-812e-3f49f1e304b8...'}
        'score': 0.7297395567513889,
        'class_name': 'NodeWithScore'
      }
    ]
    

Agente de ReAct

Para proporcionar un comportamiento de llamada de herramientas con tu propio agente de ReAct, anula runnable_builder para LlamaIndexQueryPipelineAgent.

  1. Define una función de ejemplo que muestre un tipo de cambio:

    def get_exchange_rate(
      currency_from: str = "USD",
      currency_to: str = "EUR",
      currency_date: str = "latest",
    ):
      """Retrieves the exchange rate between two currencies on a specified date.
    
      Uses the Frankfurter API (https://api.frankfurter.app/) to obtain
      exchange rate data.
    
      Args:
          currency_from: The base currency (3-letter currency code).
              Defaults to "USD" (US Dollar).
          currency_to: The target currency (3-letter currency code).
              Defaults to "EUR" (Euro).
          currency_date: The date for which to retrieve the exchange rate.
              Defaults to "latest" for the most recent exchange rate data.
              Can be specified in YYYY-MM-DD format for historical rates.
    
      Returns:
          dict: A dictionary containing the exchange rate information.
              Example: {"amount": 1.0, "base": "USD", "date": "2023-11-24",
                  "rates": {"EUR": 0.95534}}
      """
      import requests
      response = requests.get(
          f"https://api.frankfurter.app/{currency_date}",
          params={"from": currency_from, "to": currency_to},
      )
      return response.json()
    
  2. Crea un agente ReAct personalizado con herramientas:

    def runnable_with_tools_builder(model, runnable_kwargs=None, **kwargs):
      from llama_index.core.query_pipeline import QueryPipeline
      from llama_index.core.tools import FunctionTool
      from llama_index.core.agent import ReActAgent
    
      llama_index_tools = []
      for tool in runnable_kwargs.get("tools"):
          llama_index_tools.append(FunctionTool.from_defaults(tool))
      agent = ReActAgent.from_tools(llama_index_tools, llm=model, verbose=True)
      return QueryPipeline(modules = {"agent": agent})
    
    agent = reasoning_engines.LlamaIndexQueryPipelineAgent(
      model="gemini-3.5-flash",
      runnable_kwargs={"tools": [get_exchange_rate]},
      runnable_builder=runnable_with_tools_builder,
    )
    
  3. Consulta al agente:

    result = agent.query(input="What is the exchange rate between US and EURO today?")
    

    El resultado debe verse de la siguiente manera:

    {
      'response': 'The exchange rate between US and EURO today, 2025-03-19, is 1 USD to 0.91768 EUR.',
      'source_nodes': [],
      'metadata': None
    }
    

¿Qué sigue?

Guía

Conoce las cinco formas de implementar un agente en Agent Platform Runtime según tus necesidades de desarrollo.

Guía

Usar un agente de canalización de consultas de LlamaIndex con Agent Platform Runtime

Guía

Crea e implementa un agente básico, y usa Gen AI Evaluation Service para evaluarlo

Solución de problemas

Obtén información para resolver errores comunes cuando creas agentes personalizados.

Recurso

Encuentra recursos y asistencia para Google Agent Platform.