Skip to content

Latest commit

 

History

History
342 lines (240 loc) · 22.5 KB

File metadata and controls

342 lines (240 loc) · 22.5 KB

Como Projetar Bons Agentes de IA

(Clique na imagem acima para assistir ao vídeo desta lição)

Padrão de Projeto de Uso de Ferramentas

Ferramentas são interessantes porque permitem que agentes de IA tenham um conjunto mais amplo de capacidades. Em vez de o agente ter um conjunto limitado de ações que pode realizar, ao adicionar uma ferramenta, o agente pode agora executar uma ampla gama de ações. Neste capítulo, veremos o Padrão de Projeto de Uso de Ferramentas, que descreve como agentes de IA podem usar ferramentas específicas para alcançar seus objetivos.

Introdução

Nesta lição, buscamos responder às seguintes perguntas:

  • O que é o padrão de projeto de uso de ferramentas?
  • Quais são os casos de uso em que ele pode ser aplicado?
  • Quais são os elementos/blocos de construção necessários para implementar o padrão de projeto?
  • Quais são as considerações especiais para usar o Padrão de Projeto de Uso de Ferramentas para construir agentes de IA confiáveis?

Objetivos de Aprendizagem

Após concluir esta lição, você será capaz de:

  • Definir o Padrão de Projeto de Uso de Ferramentas e seu propósito.
  • Identificar casos de uso onde o Padrão de Projeto de Uso de Ferramentas é aplicável.
  • Entender os principais elementos necessários para implementar o padrão de projeto.
  • Reconhecer considerações para garantir a confiabilidade em agentes de IA que utilizam este padrão de projeto.

O que é o Padrão de Projeto de Uso de Ferramentas?

O Padrão de Projeto de Uso de Ferramentas foca em dar aos LLMs a capacidade de interagir com ferramentas externas para alcançar objetivos específicos. Ferramentas são códigos que podem ser executados por um agente para realizar ações. Uma ferramenta pode ser uma função simples, como uma calculadora, ou uma chamada de API para um serviço de terceiros como consulta de preço de ações ou previsão do tempo. No contexto de agentes de IA, as ferramentas são projetadas para serem executadas pelos agentes em resposta a chamadas de função geradas pelo modelo.

Em que casos de uso ele pode ser aplicado?

Agentes de IA podem aproveitar ferramentas para completar tarefas complexas, recuperar informações ou tomar decisões. O padrão de uso de ferramentas é frequentemente usado em cenários que requerem interação dinâmica com sistemas externos, como bancos de dados, serviços web ou interpretadores de código. Essa capacidade é útil para diversos casos de uso, incluindo:

  • Recuperação Dinâmica de Informação: Agentes podem consultar APIs externas ou bancos de dados para obter dados atualizados (por exemplo, consultar um banco de dados SQLite para análise de dados, obter preços de ações ou informações meteorológicas).
  • Execução e Interpretação de Código: Agentes podem executar códigos ou scripts para resolver problemas matemáticos, gerar relatórios ou realizar simulações.
  • Automação de Fluxo de Trabalho: Automatizar fluxos de trabalho repetitivos ou em múltiplas etapas integrando ferramentas como agendadores de tarefas, serviços de e-mail ou pipelines de dados.
  • Suporte ao Cliente: Agentes podem interagir com sistemas CRM, plataformas de tickets ou bases de conhecimento para resolver dúvidas de usuários.
  • Geração e Edição de Conteúdo: Agentes podem utilizar ferramentas como verificadores gramaticais, resumidores de texto ou avaliadores de segurança de conteúdo para auxiliar em tarefas de criação de conteúdo.

Quais são os elementos/blocos de construção necessários para implementar o padrão de uso de ferramentas?

Esses blocos de construção permitem que o agente de IA realize uma ampla gama de tarefas. Vamos analisar os principais elementos necessários para implementar o Padrão de Uso de Ferramentas:

  • Esquemas de Funções/Ferramentas: Definições detalhadas das ferramentas disponíveis, incluindo nome da função, propósito, parâmetros necessários e resultados esperados. Esses esquemas permitem que o LLM entenda quais ferramentas estão disponíveis e como construir requisições válidas.

  • Lógica de Execução de Funções: Regula como e quando as ferramentas são invocadas com base na intenção do usuário e no contexto da conversa. Pode incluir módulos planejadores, mecanismos de roteamento ou fluxos condicionais que determinam o uso dinâmico das ferramentas.

  • Sistema de Manipulação de Mensagens: Componentes que gerenciam o fluxo conversacional entre entradas do usuário, respostas do LLM, chamadas às ferramentas e resultados das ferramentas.

  • Framework de Integração de Ferramentas: Infraestrutura que conecta o agente a várias ferramentas, sejam funções simples ou serviços externos complexos.

  • Tratamento de Erros e Validação: Mecanismos para tratar falhas na execução das ferramentas, validar parâmetros e gerenciar respostas inesperadas.

  • Gerenciamento de Estado: Acompanha o contexto da conversa, interações anteriores com ferramentas e dados persistentes para garantir consistência em interações de múltiplas etapas.

A seguir, veremos o Chamado de Função/Ferramenta com mais detalhes.

Chamado de Função/Ferramenta

Chamado de função é a principal forma pela qual capacitamos Modelos Linguísticos Grandes (LLMs) a interagirem com ferramentas. Frequentemente, você verá “Função” e “Ferramenta” usados de forma intercambiável porque “funções” (blocos de código reutilizáveis) são as “ferramentas” que agentes usam para realizar tarefas. Para que o código de uma função seja invocado, um LLM deve comparar a solicitação do usuário com a descrição das funções. Para isso, é enviado ao LLM um esquema contendo as descrições de todas as funções disponíveis. O LLM então seleciona a função mais apropriada para a tarefa e retorna seu nome e argumentos. A função selecionada é invocada, sua resposta é enviada de volta ao LLM, que usa as informações para responder à solicitação do usuário.

Para os desenvolvedores implementarem Chamado de Função para agentes, é necessário:

  1. Um modelo LLM que suporte chamado de funções
  2. Um esquema contendo descrições das funções
  3. O código para cada função descrita

Vamos usar o exemplo de obter a hora atual em uma cidade para ilustrar:

  1. Inicializar um LLM que suporte chamado de função:

    Nem todos os modelos suportam chamado de função, então é importante verificar se o LLM que você está usando suporta. Azure OpenAI suporta chamado de função. Podemos começar inicializando o cliente Azure OpenAI.

    # Inicialize o cliente Azure OpenAI
    client = AzureOpenAI(
        azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
        api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
        api_version="2024-05-01-preview"
    )
  2. Criar um Esquema de Função:

    Em seguida, definiremos um esquema JSON que contém o nome da função, a descrição do que a função faz, e os nomes e descrições dos parâmetros da função. Depois passaremos esse esquema para o cliente criado anteriormente, junto com a solicitação do usuário para encontrar a hora em San Francisco. O que é importante notar é que uma chamada de ferramenta é o que é retornado, não a resposta final para a pergunta. Como mencionado anteriormente, o LLM retorna o nome da função que selecionou para a tarefa, e os argumentos que serão passados para ela.

    # Descrição da função para o modelo ler
    tools = [
        {
            "type": "function",
            "function": {
                "name": "get_current_time",
                "description": "Get the current time in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city name, e.g. San Francisco",
                        },
                    },
                    "required": ["location"],
                },
            }
        }
    ]
    # Mensagem inicial do usuário
    messages = [{"role": "user", "content": "What's the current time in San Francisco"}] 
    
    # Primeira chamada da API: Peça ao modelo para usar a função
      response = client.chat.completions.create(
          model=deployment_name,
          messages=messages,
          tools=tools,
          tool_choice="auto",
      )
    
      # Processar a resposta do modelo
      response_message = response.choices[0].message
      messages.append(response_message)
    
      print("Model's response:")  
    
      print(response_message)
    Model's response:
    ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
  3. O código da função necessário para executar a tarefa:

    Agora que o LLM escolheu qual função precisa ser executada, o código que realiza a tarefa precisa ser implementado e executado. Podemos implementar o código para obter a hora atual em Python. Também precisaremos escrever o código para extrair o nome e os argumentos da mensagem de resposta para obter o resultado final.

      def get_current_time(location):
        """Get the current time for a given location"""
        print(f"get_current_time called with location: {location}")  
        location_lower = location.lower()
        
        for key, timezone in TIMEZONE_DATA.items():
            if key in location_lower:
                print(f"Timezone found for {key}")  
                current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
                return json.dumps({
                    "location": location,
                    "current_time": current_time
                })
      
        print(f"No timezone data found for {location_lower}")  
        return json.dumps({"location": location, "current_time": "unknown"})
    # Lidar com chamadas de função
     if response_message.tool_calls:
         for tool_call in response_message.tool_calls:
             if tool_call.function.name == "get_current_time":
    
                 function_args = json.loads(tool_call.function.arguments)
    
                 time_response = get_current_time(
                     location=function_args.get("location")
                 )
    
                 messages.append({
                     "tool_call_id": tool_call.id,
                     "role": "tool",
                     "name": "get_current_time",
                     "content": time_response,
                 })
     else:
         print("No tool calls were made by the model.")  
    
     # Segunda chamada da API: Obter a resposta final do modelo
     final_response = client.chat.completions.create(
         model=deployment_name,
         messages=messages,
     )
    
     return final_response.choices[0].message.content
     get_current_time called with location: San Francisco
     Timezone found for san francisco
     The current time in San Francisco is 09:24 AM.

Chamado de Função está no coração da maioria, se não de todos os projetos de uso de ferramentas para agentes, porém implementá-lo do zero pode ser desafiador às vezes. Como aprendemos na Lição 2, frameworks agenticos nos fornecem blocos de construção pré-construídos para implementar o uso de ferramentas.

Exemplos de Uso de Ferramentas com Frameworks Agentes

Aqui estão alguns exemplos de como você pode implementar o Padrão de Uso de Ferramentas usando diferentes frameworks agenticos:

Semantic Kernel

Semantic Kernel é um framework de IA open-source para desenvolvedores .NET, Python e Java que trabalham com Modelos Linguísticos Grandes (LLMs). Ele simplifica o processo de usar o chamado de função descrevendo automaticamente suas funções e seus parâmetros para o modelo através de um processo chamado serialização. Também gerencia a comunicação de ida e volta entre o modelo e seu código. Outra vantagem de usar um framework agentico como o Semantic Kernel é que ele permite acessar ferramentas pré-construídas como Busca de Arquivos e Interpretador de Código.

O diagrama a seguir ilustra o processo de chamado de função com Semantic Kernel:

function calling

No Semantic Kernel, funções/ferramentas são chamadas Plugins. Podemos converter a função get_current_time que vimos anteriormente em um plugin transformando-a em uma classe com a função dentro. Também podemos importar o decorador kernel_function, que recebe a descrição da função. Quando você cria um kernel com o GetCurrentTimePlugin, o kernel automaticamente serializa a função e seus parâmetros, criando o esquema para enviar ao LLM no processo.

from semantic_kernel.functions import kernel_function

class GetCurrentTimePlugin:
    async def __init__(self, location):
        self.location = location

    @kernel_function(
        description="Get the current time for a given location"
    )
    def get_current_time(location: str = ""):
        ...
from semantic_kernel import Kernel

# Criar o kernel
kernel = Kernel()

# Criar o plugin
get_current_time_plugin = GetCurrentTimePlugin(location)

# Adicionar o plugin ao kernel
kernel.add_plugin(get_current_time_plugin)

Azure AI Agent Service

Azure AI Agent Service é um framework agentico mais recente, projetado para capacitar desenvolvedores a construir, implantar e escalar agentes de IA extensíveis, seguros e de alta qualidade sem a necessidade de gerenciar os recursos subjacentes de computação e armazenamento. É particularmente útil para aplicações empresariais, pois é um serviço totalmente gerenciado com segurança de nível empresarial.

Quando comparado ao desenvolvimento direto com a API LLM, o Azure AI Agent Service oferece algumas vantagens, incluindo:

  • Chamado automático de ferramentas – não é necessário analisar uma chamada de ferramenta, invocar a ferramenta e lidar com a resposta; tudo isso agora é feito no lado do servidor
  • Dados gerenciados com segurança – em vez de gerenciar seu próprio estado de conversa, você pode contar com threads para armazenar todas as informações necessárias
  • Ferramentas prontas para uso – Ferramentas que você pode usar para interagir com suas fontes de dados, como Bing, Azure AI Search e Azure Functions.

As ferramentas disponíveis no Azure AI Agent Service podem ser divididas em duas categorias:

  1. Ferramentas de Conhecimento:

  2. Ferramentas de Ação:

O Agent Service nos permite usar essas ferramentas juntas como um conjunto de ferramentas. Ele também utiliza threads que acompanham o histórico de mensagens de uma determinada conversa.

Imagine que você é um agente de vendas em uma empresa chamada Contoso. Você quer desenvolver um agente conversacional que possa responder a perguntas sobre seus dados de vendas.

A imagem a seguir ilustra como você poderia usar o Azure AI Agent Service para analisar seus dados de vendas:

Agentic Service In Action

Para usar qualquer uma dessas ferramentas com o serviço, podemos criar um cliente e definir uma ferramenta ou conjunto de ferramentas. Para implementar isso na prática, podemos usar o seguinte código Python. O LLM poderá olhar para o conjunto de ferramentas e decidir se usa a função criada pelo usuário, fetch_sales_data_using_sqlite_query, ou o Interpretador de Código pré-construído, dependendo da solicitação do usuário.

import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fetch_sales_data_functions import fetch_sales_data_using_sqlite_query # função fetch_sales_data_using_sqlite_query que pode ser encontrada em um arquivo fetch_sales_data_functions.py.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool

project_client = AIProjectClient.from_connection_string(
    credential=DefaultAzureCredential(),
    conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)

# Inicializar conjunto de ferramentas
toolset = ToolSet()

# Inicializar agente de chamada de função com a função fetch_sales_data_using_sqlite_query e adicioná-la ao conjunto de ferramentas
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset.add(fetch_data_function)

# Inicializar ferramenta Code Interpreter e adicioná-la ao conjunto de ferramentas.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset.add(code_interpreter)

agent = project_client.agents.create_agent(
    model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent", 
    toolset=toolset
)

Quais são as considerações especiais para usar o Padrão de Projeto de Uso de Ferramentas para construir agentes de IA confiáveis?

Uma preocupação comum com SQL gerado dinamicamente por LLMs é a segurança, particularmente o risco de injeção de SQL ou ações maliciosas, como apagar ou adulterar o banco de dados. Embora essas preocupações sejam válidas, elas podem ser efetivamente mitigadas configurando-se adequadamente as permissões de acesso ao banco de dados. Para a maioria dos bancos, isso envolve configurá-lo como somente leitura. Para serviços de banco de dados como PostgreSQL ou Azure SQL, o aplicativo deve ser atribuído a uma função somente leitura (SELECT).

Executar o aplicativo em um ambiente seguro amplia ainda mais a proteção. Em cenários empresariais, os dados normalmente são extraídos e transformados de sistemas operacionais para um banco de dados ou data warehouse somente leitura com um esquema amigável ao usuário. Essa abordagem garante que os dados estejam seguros, otimizados para desempenho e acessibilidade, e que o aplicativo tenha acesso restrito e somente leitura.

Códigos de Exemplo

Tem mais perguntas sobre o uso de padrões de design de ferramentas?

Junte-se ao Microsoft Foundry Discord para encontrar outros aprendizes, participar de horários de atendimento e tirar suas dúvidas sobre Agentes de IA.

Recursos Adicionais

Aula Anterior

Entendendo os Padrões de Design Agênico

Próxima Aula

Agentic RAG


Aviso Legal: Este documento foi traduzido utilizando o serviço de tradução por IA Co-op Translator. Embora nos esforcemos para garantir a precisão, esteja ciente de que traduções automáticas podem conter erros ou imprecisões. O documento original em sua língua nativa deve ser considerado a fonte autorizada. Para informações críticas, recomenda-se tradução profissional realizada por um humano. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações incorretas decorrentes do uso desta tradução.