Ferramentas LangChain: Guia completo para criar e usar ferramentas LLM personalizadas + exemplos de código 2025
Aprenda a criar e utilizar ferramentas LangChain para aprimorar a integração da IA com sistemas externos, melhorando a automação e a funcionalidade.

LangChain Ferramentas são soluções baseadas em Python que permitem a interação perfeita entre grandes modelos de linguagem (LLMs) e sistemas externos, como APIs e bancos de dados. Ao facilitar chamadas de funções estruturadas, essas ferramentas capacitam os LLMs a executar tarefas como buscar dados em tempo real, executar consultas ou automatizar fluxos de trabalho. Essa abordagem preenche a lacuna entre o raciocínio da IA e resultados acionáveis, tornando-a ideal para cenários que exigem atualizações em tempo real ou integração de sistemas.
As ferramentas LangChain são particularmente eficazes para aplicações como bots de atendimento ao cliente, sistemas de suporte técnico e assistentes financeiros. Os desenvolvedores podem escolher entre dois métodos de criação: @tool decorador para simplicidade ou o BaseTool subclasse para personalização avançada. Ambas as abordagens enfatizam assinaturas de funções claras, tratamento robusto de erros e validação precisa de entradas para garantir confiabilidade.
Para equipes que buscam uma alternativa ao desenvolvimento personalizado, plataformas como Nó latente simplificar a automação com conectores pré-construídos e fluxos de trabalho visuais. Por exemplo, integrando ferramentas como Noção, WhatsApp, ou planilhas do Google torna-se simples, sem a necessidade de codificação extensa. Isso reduz o tempo de desenvolvimento e a sobrecarga de manutenção, permitindo que as equipes se concentrem na entrega de soluções impactantes.
Criando um personalizado Langchain ferramenta
Arquitetura da ferramenta LangChain e componentes principais
As ferramentas LangChain são construídas sobre uma estrutura que transforma funções Python em interfaces que podem ser chamadas por modelos de linguagem de grande porte (LLMs). Essa configuração permite uma interação fluida entre modelos de IA e sistemas externos. A seguir, exploraremos os principais componentes que permitem o funcionamento eficaz dessas ferramentas.
Principais componentes das ferramentas LangChain
A funcionalidade das ferramentas LangChain é suportada por cinco componentes essenciais. Cada um desempenha um papel distinto para garantir uma operação perfeita e uma comunicação confiável entre as ferramentas e os LLMs:
- Assinatura de Função
A assinatura da função serve como um modelo para a interface da ferramenta. Ela define os parâmetros que a ferramenta aceita e o que ela gera como saída. As dicas de tipo do Python desempenham um papel fundamental na formação dessa assinatura, ajudando os LLMs a identificar a ferramenta certa para tarefas específicas. O nome da função atua como um identificador único, orientando o LLM a selecionar a ferramenta correta durante a execução. - Descrições das ferramentas
As descrições de ferramentas proporcionam aos LLMs uma compreensão clara da função de cada ferramenta. Escritas em linguagem simples e natural, elas explicam quando e como a ferramenta deve ser usada, juntamente com o tipo de resultados que ela proporciona. Descrições claras e concisas são essenciais para evitar falhas de comunicação ou uso incorreto da ferramenta. - Esquema de Parâmetros
O esquema de parâmetros define as regras e a estrutura para a entrada da ferramenta. Usando dicas de tipo do Python, os desenvolvedores podem criar esquemas que especificam restrições, valores padrão e regras de validação personalizadas. Isso garante que os dados de entrada sejam formatados corretamente, reduzindo o risco de erros de tempo de execução e melhorando a confiabilidade geral. - Tratamento de devoluções
Este componente determina como a saída de uma ferramenta é processada e retornada ao LLM. As ferramentas podem produzir saídas em diversos formatos, como texto simples, dados estruturados ou objetos complexos. O formato de retorno é fundamental para garantir que o LLM possa utilizar os resultados de forma eficaz em seu fluxo de trabalho mais amplo. - Tratamento de erros
O tratamento de erros é um aspecto crucial, embora frequentemente negligenciado. Ferramentas devem estar equipadas para gerenciar problemas como falhas de rede, limites de taxa ou entradas inválidas. Um gerenciamento de erros eficaz garante que uma única falha não interrompa a operação inteira de um agente, o que é especialmente importante em ambientes de produção.
Métodos de subclasse Decorator vs. BaseTool
O LangChain oferece duas abordagens principais para a criação de ferramentas, cada uma adaptada a diferentes níveis de complexidade e casos de uso. Esses métodos são: @tool decorador e o BaseTool subclasse.
- A construção do XNUMXº e XNUMXº pavimentos pôde ocorrer de forma simultânea, pois não houve necessidade de aguardar a cura do concreto – permitindo que todas as frentes de trabalho e especialistas em pisos ESD atuassem nos dois níveis ao mesmo tempo.
@tooldecorador
Esta abordagem foi projetada para simplicidade. Ela permite que os desenvolvedores convertam rapidamente funções Python em ferramentas compatíveis com LangChain com o mínimo de esforço. O decorador lida automaticamente com tarefas como geração de esquema, validação de parâmetros e encapsulamento básico de erros. É ideal para operações simples, como chamadas de API, cálculos simples ou transformações de dados, que dispensam gerenciamento de estado ou inicialização complexa. - A construção do XNUMXº e XNUMXº pavimentos pôde ocorrer de forma simultânea, pois não houve necessidade de aguardar a cura do concreto – permitindo que todas as frentes de trabalho e especialistas em pisos ESD atuassem nos dois níveis ao mesmo tempo.
BaseToolSubclasse
Para necessidades mais avançadas, oBaseToolO método subclass oferece ampla personalização. É adequado para ferramentas que exigem lógica complexa, operações com estado ou tratamento avançado de erros. Os desenvolvedores podem implementar inicialização personalizada, operações assíncronas e tipos de retorno mais complexos. Embora esse método envolva mais codificação, ele oferece a flexibilidade necessária para ferramentas de nível de produção, especialmente aquelas que envolvem autenticação, conexões persistentes ou lógica de negócios detalhada.
Escolhendo a abordagem certa
A escolha entre esses métodos depende da complexidade da ferramenta e do uso pretendido. Ferramentas simples geralmente começam com a abordagem do decorador e podem posteriormente evoluir para implementações baseadas em subclasses, à medida que os requisitos aumentam. No entanto, para ferramentas que exigem tratamento robusto de erros ou integração com sistemas complexos, começar com a BaseTool subclasse pode economizar tempo e evitar desafios arquitetônicos mais tarde.
Criando ferramentas personalizadas com validação adequada
Ao criar ferramentas personalizadas, é essencial focar na validação rigorosa de entradas, no tratamento eficaz de erros e na documentação clara. Esses elementos garantem que as ferramentas funcionem de forma confiável e se integrem perfeitamente a grandes modelos de linguagem (LLMs).
Como criar uma ferramenta básica
A construção do XNUMXº e XNUMXº pavimentos pôde ocorrer de forma simultânea, pois não houve necessidade de aguardar a cura do concreto – permitindo que todas as frentes de trabalho e especialistas em pisos ESD atuassem nos dois níveis ao mesmo tempo. @tool O decorator oferece um método simples para criar ferramentas LangChain. Ele gera esquemas automaticamente e realiza validações básicas, tornando-o ideal para operações simples.
Aqui está um exemplo de uma ferramenta de consulta do clima:
<span class="hljs-keyword">from</span> langchain.tools <span class="hljs-keyword">import</span> tool
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">Optional</span>
<span class="hljs-keyword">import</span> requests
<span class="hljs-meta">@tool</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">get_weather_data</span>(<span class="hljs-params">city: <span class="hljs-built_in">str</span>, country_code: <span class="hljs-type">Optional</span>[<span class="hljs-built_in">str</span>] = <span class="hljs-string">"US"</span></span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-string">"""
Fetch current weather information for a specified city.
Args:
city: The name of the city to get weather for.
country_code: Two-letter country code (default: US).
Returns:
Weather information as a formatted string.
"""</span>
<span class="hljs-keyword">try</span>:
api_key = <span class="hljs-string">"your_api_key_here"</span>
url = <span class="hljs-string">"http://api.openweathermap.org/data/2.5/weather"</span>
params = {
<span class="hljs-string">"q"</span>: <span class="hljs-string">f"<span class="hljs-subst">{city}</span>,<span class="hljs-subst">{country_code}</span>"</span>,
<span class="hljs-string">"appid"</span>: api_key,
<span class="hljs-string">"units"</span>: <span class="hljs-string">"imperial"</span>
}
response = requests.get(url, params=params, timeout=<span class="hljs-number">10</span>)
response.raise_for_status()
data = response.json()
temp = data[<span class="hljs-string">"main"</span>][<span class="hljs-string">"temp"</span>]
description = data[<span class="hljs-string">"weather"</span>][<span class="hljs-number">0</span>][<span class="hljs-string">"description"</span>]
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Current weather in <span class="hljs-subst">{city}</span>: <span class="hljs-subst">{temp}</span>°F, <span class="hljs-subst">{description}</span>"</span>
<span class="hljs-keyword">except</span> requests.exceptions.RequestException <span class="hljs-keyword">as</span> e:
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Error fetching weather data: <span class="hljs-subst">{<span class="hljs-built_in">str</span>(e)}</span>"</span>
<span class="hljs-keyword">except</span> KeyError <span class="hljs-keyword">as</span> e:
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Invalid response format: missing <span class="hljs-subst">{<span class="hljs-built_in">str</span>(e)}</span>"</span>
Para cenários mais avançados, como aqueles que exigem inicialização personalizada ou manipulação de estados internos, o BaseTool subclasse fornece maior flexibilidade:
<span class="hljs-keyword">from</span> langchain.tools <span class="hljs-keyword">import</span> BaseTool
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">Type</span>
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel, Field
<span class="hljs-keyword">class</span> <span class="hljs-title class_">DatabaseQueryInput</span>(<span class="hljs-title class_ inherited__">BaseModel</span>):
query: <span class="hljs-built_in">str</span> = Field(description=<span class="hljs-string">"SQL query to execute"</span>)
table: <span class="hljs-built_in">str</span> = Field(description=<span class="hljs-string">"Target table name"</span>)
<span class="hljs-keyword">class</span> <span class="hljs-title class_">DatabaseQueryTool</span>(<span class="hljs-title class_ inherited__">BaseTool</span>):
name = <span class="hljs-string">"database_query"</span>
description = <span class="hljs-string">"Execute SQL queries against the company database"</span>
args_schema: <span class="hljs-type">Type</span>[BaseModel] = DatabaseQueryInput
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self, connection_string: <span class="hljs-built_in">str</span></span>):
<span class="hljs-built_in">super</span>().__init__()
<span class="hljs-variable language_">self</span>.connection_string = connection_string
<span class="hljs-variable language_">self</span>.connection = <span class="hljs-literal">None</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_run</span>(<span class="hljs-params">self, query: <span class="hljs-built_in">str</span>, table: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-variable language_">self</span>.connection:
<span class="hljs-variable language_">self</span>.connection = <span class="hljs-variable language_">self</span>._establish_connection()
<span class="hljs-comment"># Execute query with proper validation</span>
<span class="hljs-keyword">return</span> <span class="hljs-variable language_">self</span>._execute_safe_query(query, table)
Melhores práticas para nomes e descrições de ferramentas
Escolher nomes claros e descritivos para as ferramentas ajuda os LLMs a entender sua finalidade e uso. Use verbos orientados para a ação nos nomes das ferramentas (por exemplo, search_documents em vez de docs) e evitar abreviações que possam confundir o LLM. A consistência entre as ferramentas relacionadas é igualmente importante; por exemplo, nomear várias ferramentas de API como api_get_user, api_create_user e api_delete_user cria um agrupamento lógico.
As descrições devem ser concisas e escritas na voz ativa, descrevendo claramente o propósito da ferramenta, as entradas necessárias e os resultados esperados. Compare estes dois exemplos:
<span class="hljs-comment"># Poor description</span>
<span class="hljs-meta">@tool</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">calc</span>(<span class="hljs-params">x: <span class="hljs-built_in">float</span>, y: <span class="hljs-built_in">float</span></span>) -> <span class="hljs-built_in">float</span>:
<span class="hljs-string">"""Does math stuff"""</span>
<span class="hljs-keyword">return</span> x + y
<span class="hljs-comment"># Effective description</span>
<span class="hljs-meta">@tool</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">add_numbers</span>(<span class="hljs-params">first_number: <span class="hljs-built_in">float</span>, second_number: <span class="hljs-built_in">float</span></span>) -> <span class="hljs-built_in">float</span>:
<span class="hljs-string">"""
Add two numbers together and return the sum.
Use this tool when you need to perform basic addition of numeric values.
Both inputs must be numbers (integers or decimals).
Args:
first_number: The first number to add.
second_number: The second number to add.
Returns:
The sum of the two input numbers.
"""</span>
<span class="hljs-keyword">return</span> first_number + second_number
Digitação de parâmetros e validação de entrada
A digitação precisa de parâmetros é fundamental para evitar problemas de tempo de execução e orientar as interações do LLM. As dicas de tipo do Python e os modelos do Pydantic funcionam bem juntos para impor a validação.
Validação de tipo básica exemplo:
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">List</span>, <span class="hljs-type">Dict</span>, <span class="hljs-type">Optional</span>, <span class="hljs-type">Union</span>
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">from</span> enum <span class="hljs-keyword">import</span> Enum
<span class="hljs-keyword">class</span> <span class="hljs-title class_">Priority</span>(<span class="hljs-built_in">str</span>, Enum):
LOW = <span class="hljs-string">"low"</span>
MEDIUM = <span class="hljs-string">"medium"</span>
HIGH = <span class="hljs-string">"high"</span>
<span class="hljs-meta">@tool</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">create_task</span>(<span class="hljs-params">
title: <span class="hljs-built_in">str</span>,
description: <span class="hljs-type">Optional</span>[<span class="hljs-built_in">str</span>] = <span class="hljs-literal">None</span>,
priority: Priority = Priority.MEDIUM,
due_date: <span class="hljs-type">Optional</span>[datetime] = <span class="hljs-literal">None</span>,
tags: <span class="hljs-type">List</span>[<span class="hljs-built_in">str</span>] = []
</span>) -> <span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Union</span>[<span class="hljs-built_in">str</span>, <span class="hljs-built_in">int</span>]]:
<span class="hljs-string">"""
Create a new task in the project management system.
Args:
title: Task title (required, max 100 characters).
description: Detailed task description (optional).
priority: Task priority level (low, medium, high).
due_date: When the task should be completed (ISO format).
tags: List of tags to categorize the task.
Returns:
Dictionary containing a task ID and a confirmation message.
"""</span>
<span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(title) > <span class="hljs-number">100</span>:
<span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Title must be 100 characters or less"</span>)
<span class="hljs-keyword">if</span> due_date <span class="hljs-keyword">and</span> due_date < datetime.now():
<span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Due date cannot be in the past"</span>)
task_id = generate_task_id()
<span class="hljs-keyword">return</span> {
<span class="hljs-string">"task_id"</span>: task_id,
<span class="hljs-string">"message"</span>: <span class="hljs-string">f"Task '<span class="hljs-subst">{title}</span>' created successfully"</span>
}
Validação avançada usando modelos Pydantic:
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel, Field, validator
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">List</span>
<span class="hljs-keyword">import</span> re
<span class="hljs-keyword">class</span> <span class="hljs-title class_">EmailInput</span>(<span class="hljs-title class_ inherited__">BaseModel</span>):
recipients: <span class="hljs-type">List</span>[<span class="hljs-built_in">str</span>] = Field(description=<span class="hljs-string">"List of email addresses"</span>)
subject: <span class="hljs-built_in">str</span> = Field(description=<span class="hljs-string">"Email subject line"</span>, max_length=<span class="hljs-number">200</span>)
body: <span class="hljs-built_in">str</span> = Field(description=<span class="hljs-string">"Email body content"</span>)
<span class="hljs-meta"> @validator(<span class="hljs-params"><span class="hljs-string">'recipients'</span></span>)</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">validate_emails</span>(<span class="hljs-params">cls, v</span>):
email_pattern = <span class="hljs-string">r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'</span>
<span class="hljs-keyword">for</span> email <span class="hljs-keyword">in</span> v:
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> re.<span class="hljs-keyword">match</span>(email_pattern, email):
<span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">f"Invalid email address: <span class="hljs-subst">{email}</span>"</span>)
<span class="hljs-keyword">return</span> v
<span class="hljs-meta"> @validator(<span class="hljs-params"><span class="hljs-string">'subject'</span></span>)</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">validate_subject</span>(<span class="hljs-params">cls, v</span>):
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> v.strip():
<span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Subject cannot be empty"</span>)
<span class="hljs-keyword">return</span> v.strip()
<span class="hljs-meta">@tool</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">send_email</span>(<span class="hljs-params">email_data: EmailInput</span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-string">"""
Send an email to specified recipients with validation.
All email addresses are validated before sending.
The subject line is required and cannot be empty.
"""</span>
<span class="hljs-comment"># Send validated email</span>
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Email sent to <span class="hljs-subst">{<span class="hljs-built_in">len</span>(email_data.recipients)}</span> recipients"</span>
Tratamento de erros e gerenciamento de exceções
Após a validação das entradas, um tratamento de erros robusto torna-se crucial para garantir que os fluxos de trabalho permaneçam intactos mesmo quando surgem problemas. Um tratamento de erros bem projetado evita que uma única falha interrompa todo o processo e fornece feedback útil para depuração.
Aqui está um exemplo de um decorador para padronizar o tratamento de erros em todas as ferramentas:
<span class="hljs-keyword">import</span> logging
<span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">def</span> <span class="hljs-title function_">handle_tool_errors</span>(<span class="hljs-params">func</span>):
<span class="hljs-string">"""Decorator to standardize error handling across tools."""</span>
<span class="hljs-meta"> @wraps(<span class="hljs-params">func</span>)</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):
<span class="hljs-keyword">try</span>:
<span class="hljs-keyword">return</span> func(*args, **kwargs)
<span class="hljs-keyword">except</span> requests.exceptions.Timeout <span class="hljs-keyword">as</span> e:
logging.error(<span class="hljs-string">f"Timeout occurred: <span class="hljs-subst">{e}</span>"</span>)
<span class="hljs-keyword">return</span> <span class="hljs-string">"Request timed out"</span>
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
logging.error(<span class="hljs-string">f"An error occurred: <span class="hljs-subst">{e}</span>"</span>)
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Error: <span class="hljs-subst">{e}</span>"</span>
<span class="hljs-keyword">return</span> wrapper
sbb-itb-23997f1
Integração de ferramentas com agentes e fluxos de trabalho
Integrar as ferramentas do LangChain com agentes envolve selecionar as ferramentas certas e garantir a execução tranquila das tarefas.
Conectando ferramentas a agentes
Veja um exemplo de configuração de um agente com diversas ferramentas adaptadas para um cenário de atendimento ao cliente:
<span class="hljs-keyword">from</span> langchain.agents <span class="hljs-keyword">import</span> initialize_agent, AgentType
<span class="hljs-keyword">from</span> langchain.llms <span class="hljs-keyword">import</span> OpenAI
<span class="hljs-keyword">from</span> langchain.tools <span class="hljs-keyword">import</span> tool
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime
<span class="hljs-meta">@tool</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">lookup_order_status</span>(<span class="hljs-params">order_id: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-string">"""
Retrieve the current status of a customer order using its ID.
Args:
order_id: The unique identifier for the order (e.g., ORD-12345).
Returns:
Information about the order status, including shipping details.
"""</span>
<span class="hljs-comment"># Simulated API call</span>
api_response = requests.get(<span class="hljs-string">f"https://api.company.com/orders/<span class="hljs-subst">{order_id}</span>"</span>)
<span class="hljs-keyword">if</span> api_response.status_code == <span class="hljs-number">200</span>:
data = api_response.json()
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Order <span class="hljs-subst">{order_id}</span>: <span class="hljs-subst">{data[<span class="hljs-string">'status'</span>]}</span> - Expected delivery: <span class="hljs-subst">{data[<span class="hljs-string">'delivery_date'</span>]}</span>"</span>
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Order <span class="hljs-subst">{order_id}</span> not found in system"</span>
<span class="hljs-meta">@tool</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">process_refund_request</span>(<span class="hljs-params">order_id: <span class="hljs-built_in">str</span>, reason: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-string">"""
Handle a customer refund request.
Args:
order_id: The order ID for which the refund is requested.
reason: The reason provided by the customer for requesting the refund.
Returns:
Confirmation of the refund request along with a reference number.
"""</span>
refund_id = <span class="hljs-string">f"REF-<span class="hljs-subst">{datetime.now().strftime(<span class="hljs-string">'%Y%m%d'</span>)}</span>-<span class="hljs-subst">{order_id[-<span class="hljs-number">5</span>:]}</span>"</span>
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Refund initiated for <span class="hljs-subst">{order_id}</span>. Reference: <span class="hljs-subst">{refund_id}</span>. Processing time: 3-5 business days."</span>
<span class="hljs-comment"># Initialize the agent with tools</span>
llm = OpenAI(temperature=<span class="hljs-number">0</span>)
tools = [lookup_order_status, process_refund_request]
agent = initialize_agent(
tools=tools,
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=<span class="hljs-literal">True</span>,
max_iterations=<span class="hljs-number">3</span>
)
<span class="hljs-comment"># The agent selects the appropriate tool based on user input</span>
response = agent.run(<span class="hljs-string">"I need to check order ORD-67890 and request a refund because the item arrived damaged"</span>)
Neste exemplo, o agente usa a consulta de entrada para determinar quais ferramentas ativar. Quando várias ferramentas estão disponíveis, organizá-las em grupos especializados pode aumentar a precisão e a eficiência. Por exemplo, as ferramentas podem ser agrupadas com base em sua função, como tarefas relacionadas a pedidos ou produtos:
<span class="hljs-keyword">from</span> langchain.agents <span class="hljs-keyword">import</span> AgentExecutor
<span class="hljs-keyword">from</span> langchain.tools <span class="hljs-keyword">import</span> BaseTool
<span class="hljs-keyword">class</span> <span class="hljs-title class_">CustomerServiceAgent</span>:
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>):
<span class="hljs-variable language_">self</span>.order_tools = [lookup_order_status, process_refund_request, additional_order_tool]
<span class="hljs-variable language_">self</span>.product_tools = [additional_product_tool, additional_product_tool_2]
<span class="hljs-keyword">def</span> <span class="hljs-title function_">route_to_specialist</span>(<span class="hljs-params">self, query: <span class="hljs-built_in">str</span></span>) -> AgentExecutor:
<span class="hljs-keyword">if</span> <span class="hljs-string">"order"</span> <span class="hljs-keyword">in</span> query.lower() <span class="hljs-keyword">or</span> <span class="hljs-string">"refund"</span> <span class="hljs-keyword">in</span> query.lower():
<span class="hljs-keyword">return</span> initialize_agent(<span class="hljs-variable language_">self</span>.order_tools, llm, AgentType.ZERO_SHOT_REACT_DESCRIPTION)
<span class="hljs-keyword">elif</span> <span class="hljs-string">"product"</span> <span class="hljs-keyword">in</span> query.lower() <span class="hljs-keyword">or</span> <span class="hljs-string">"inventory"</span> <span class="hljs-keyword">in</span> query.lower():
<span class="hljs-keyword">return</span> initialize_agent(<span class="hljs-variable language_">self</span>.product_tools, llm, AgentType.ZERO_SHOT_REACT_DESCRIPTION)
<span class="hljs-keyword">else</span>:
<span class="hljs-comment"># Default to general tools</span>
<span class="hljs-keyword">return</span> initialize_agent(<span class="hljs-variable language_">self</span>.order_tools[:<span class="hljs-number">2</span>], llm, AgentType.ZERO_SHOT_REACT_DESCRIPTION)
Esse método garante que as consultas sejam encaminhadas para as ferramentas mais relevantes, criando uma experiência do usuário mais otimizada.
Padrões de ferramentas avançados para fluxos de trabalho complexos
Para fluxos de trabalho que exigem múltiplas chamadas de API independentes ou consultas a bancos de dados, a execução assíncrona pode aumentar significativamente a eficiência. Em vez de processar tarefas uma após a outra, os padrões assíncronos permitem que as tarefas sejam executadas em paralelo:
<span class="hljs-keyword">import</span> asyncio
<span class="hljs-keyword">from</span> langchain.tools <span class="hljs-keyword">import</span> tool
<span class="hljs-keyword">import</span> aiohttp
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">List</span>
<span class="hljs-meta">@tool</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">fetch_user_data_async</span>(<span class="hljs-params">user_id: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-string">"""
Retrieve a user's profile asynchronously.
Args:
user_id: The unique identifier for the user.
Returns:
Profile details as a JSON string.
"""</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> aiohttp.ClientSession() <span class="hljs-keyword">as</span> session:
<span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> session.get(<span class="hljs-string">f"https://api.userservice.com/users/<span class="hljs-subst">{user_id}</span>"</span>) <span class="hljs-keyword">as</span> response:
<span class="hljs-keyword">if</span> response.status == <span class="hljs-number">200</span>:
data = <span class="hljs-keyword">await</span> response.json()
<span class="hljs-keyword">return</span> <span class="hljs-string">f"User <span class="hljs-subst">{user_id}</span>: <span class="hljs-subst">{data[<span class="hljs-string">'name'</span>]}</span>, <span class="hljs-subst">{data[<span class="hljs-string">'email'</span>]}</span>, <span class="hljs-subst">{data[<span class="hljs-string">'subscription_tier'</span>]}</span>"</span>
<span class="hljs-keyword">return</span> <span class="hljs-string">f"User <span class="hljs-subst">{user_id}</span> not found"</span>
<span class="hljs-meta">@tool</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">fetch_usage_metrics_async</span>(<span class="hljs-params">user_id: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-string">"""
Obtain usage statistics for a user asynchronously.
Args:
user_id: The identifier for the user.
Returns:
Usage details, including API call count and storage usage.
"""</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> aiohttp.ClientSession() <span class="hljs-keyword">as</span> session:
<span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> session.get(<span class="hljs-string">f"https://api.analytics.com/usage/<span class="hljs-subst">{user_id}</span>"</span>) <span class="hljs-keyword">as</span> response:
<span class="hljs-keyword">if</span> response.status == <span class="hljs-number">200</span>:
data = <span class="hljs-keyword">await</span> response.json()
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Usage for <span class="hljs-subst">{user_id}</span>: <span class="hljs-subst">{data[<span class="hljs-string">'api_calls'</span>]}</span> calls, <span class="hljs-subst">{data[<span class="hljs-string">'storage_gb'</span>]}</span>GB storage"</span>
<span class="hljs-keyword">return</span> <span class="hljs-string">f"No usage data for <span class="hljs-subst">{user_id}</span>"</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">parallel_user_analysis</span>(<span class="hljs-params">user_ids: <span class="hljs-type">List</span>[<span class="hljs-built_in">str</span>]</span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">str</span>]:
<span class="hljs-string">"""Execute multiple asynchronous tasks for user data retrieval."""</span>
tasks = []
<span class="hljs-keyword">for</span> user_id <span class="hljs-keyword">in</span> user_ids:
tasks.append(fetch_user_data_async(user_id))
tasks.append(fetch_usage_metrics_async(user_id))
results = <span class="hljs-keyword">await</span> asyncio.gather(*tasks)
<span class="hljs-keyword">return</span> results
Essa abordagem não só economiza tempo como também garante que o sistema possa lidar com fluxos de trabalho complexos de forma eficiente.
Para tarefas que exigem contexto em múltiplas interações, ferramentas com estado podem ser utilizadas. Essas ferramentas retêm informações, permitindo análises cumulativas e melhor rastreamento:
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">Dict</span>, <span class="hljs-type">Any</span>
<span class="hljs-keyword">import</span> json
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">from</span> langchain.tools <span class="hljs-keyword">import</span> BaseTool
<span class="hljs-keyword">class</span> <span class="hljs-title class_">StatefulAnalyticsTool</span>(<span class="hljs-title class_ inherited__">BaseTool</span>):
name = <span class="hljs-string">"analytics_tracker"</span>
description = <span class="hljs-string">"Track and analyze user behavior patterns across multiple interactions"</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self</span>):
<span class="hljs-built_in">super</span>().__init__()
<span class="hljs-variable language_">self</span>.session_data: <span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>] = {}
<span class="hljs-variable language_">self</span>.interaction_count = <span class="hljs-number">0</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_run</span>(<span class="hljs-params">self, action: <span class="hljs-built_in">str</span>, data: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-variable language_">self</span>.interaction_count += <span class="hljs-number">1</span>
<span class="hljs-keyword">if</span> action == <span class="hljs-string">"track_event"</span>:
event_data = json.loads(data)
event_type = event_data.get(<span class="hljs-string">"type"</span>)
<span class="hljs-keyword">if</span> event_type <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> <span class="hljs-variable language_">self</span>.session_data:
<span class="hljs-variable language_">self</span>.session_data[event_type] = []
<span class="hljs-variable language_">self</span>.session_data[event_type].append({
<span class="hljs-string">"timestamp"</span>: datetime.now().isoformat(),
<span class="hljs-string">"data"</span>: event_data,
<span class="hljs-string">"interaction_number"</span>: <span class="hljs-variable language_">self</span>.interaction_count
})
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Tracked <span class="hljs-subst">{event_type}</span> event. Total interactions: <span class="hljs-subst">{self.interaction_count}</span>"</span>
<span class="hljs-keyword">elif</span> action == <span class="hljs-string">"analyze_patterns"</span>:
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-variable language_">self</span>.session_data:
<span class="hljs-keyword">return</span> <span class="hljs-string">"No data collected yet for analysis"</span>
patterns = {}
<span class="hljs-keyword">for</span> event_type, events <span class="hljs-keyword">in</span> <span class="hljs-variable language_">self</span>.session_data.items():
patterns[event_type] = {
<span class="hljs-string">"count"</span>: <span class="hljs-built_in">len</span>(events),
<span class="hljs-string">"frequency"</span>: <span class="hljs-built_in">len</span>(events) / <span class="hljs-variable language_">self</span>.interaction_count
}
<span class="hljs-keyword">return</span> <span class="hljs-string">f"Behavior patterns: <span class="hljs-subst">{json.dumps(patterns, indent=<span class="hljs-number">2</span>)}</span>"</span>
<span class="hljs-keyword">return</span> <span class="hljs-string">"Unknown action. Use 'track_event' or 'analyze_patterns'"</span>
Considerações de produção para ferramentas LangChain
A transição das ferramentas LangChain do desenvolvimento para a produção exige uma abordagem criteriosa para enfrentar os desafios de desempenho, segurança e manutenção. Essas considerações são cruciais para garantir que as ferramentas operem com eficiência e segurança em ambientes reais.
Otimizando o desempenho da ferramenta
Os gargalos de desempenho em ambientes de produção geralmente surgem de respostas lentas de API externa, lógica ineficiente ou operações síncronas excessivas . Esses problemas são especialmente pronunciados quando as ferramentas lidam com altos volumes de solicitações simultâneas ou interagem com APIs que impõem limites de taxa.
Uma maneira de melhorar o desempenho é por meio de padrões de execução assíncronos, que permite que as ferramentas processem múltiplas solicitações simultaneamente. Essa abordagem é particularmente eficaz para operações com E/S limitada, como demonstrado no exemplo a seguir:
<span class="hljs-keyword">import</span> asyncio
<span class="hljs-keyword">import</span> aiohttp
<span class="hljs-keyword">from</span> langchain.tools <span class="hljs-keyword">import</span> StructuredTool
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel
<span class="hljs-keyword">class</span> <span class="hljs-title class_">BatchAPITool</span>(<span class="hljs-title class_ inherited__">BaseModel</span>):
<span class="hljs-string">"""Optimized tool for handling multiple API requests concurrently."""</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">fetch_data_batch</span>(<span class="hljs-params">self, endpoints: <span class="hljs-built_in">list</span>[<span class="hljs-built_in">str</span>]</span>) -> <span class="hljs-built_in">dict</span>:
<span class="hljs-string">"""Process multiple API endpoints concurrently with error handling."""</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> aiohttp.ClientSession(
timeout=aiohttp.ClientTimeout(total=<span class="hljs-number">10</span>),
connector=aiohttp.TCPConnector(limit=<span class="hljs-number">20</span>)
) <span class="hljs-keyword">as</span> session:
tasks = [<span class="hljs-variable language_">self</span>._fetch_single(session, url) <span class="hljs-keyword">for</span> url <span class="hljs-keyword">in</span> endpoints]
results = <span class="hljs-keyword">await</span> asyncio.gather(*tasks, return_exceptions=<span class="hljs-literal">True</span>)
<span class="hljs-keyword">return</span> {
<span class="hljs-string">"successful"</span>: [r <span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> results <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-built_in">isinstance</span>(r, Exception)],
<span class="hljs-string">"failed"</span>: [<span class="hljs-built_in">str</span>(r) <span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> results <span class="hljs-keyword">if</span> <span class="hljs-built_in">isinstance</span>(r, Exception)],
<span class="hljs-string">"total_processed"</span>: <span class="hljs-built_in">len</span>(results)
}
<span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">_fetch_single</span>(<span class="hljs-params">self, session: aiohttp.ClientSession, url: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">dict</span>:
<span class="hljs-keyword">try</span>:
<span class="hljs-keyword">async</span> <span class="hljs-keyword">with</span> session.get(url) <span class="hljs-keyword">as</span> response:
<span class="hljs-keyword">if</span> response.status == <span class="hljs-number">200</span>:
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> response.json()
<span class="hljs-keyword">return</span> {<span class="hljs-string">"error"</span>: <span class="hljs-string">f"HTTP <span class="hljs-subst">{response.status}</span>"</span>}
<span class="hljs-keyword">except</span> asyncio.TimeoutError:
<span class="hljs-keyword">return</span> {<span class="hljs-string">"error"</span>: <span class="hljs-string">"Request timeout"</span>}
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
<span class="hljs-keyword">return</span> {<span class="hljs-string">"error"</span>: <span class="hljs-string">f"Request failed: <span class="hljs-subst">{<span class="hljs-built_in">str</span>(e)}</span>"</span>}
<span class="hljs-comment"># Create the structured tool with async support</span>
batch_tool = StructuredTool.from_function(
func=BatchAPITool().fetch_data_batch,
name=<span class="hljs-string">"batch_api_processor"</span>,
description=<span class="hljs-string">"Process multiple API endpoints concurrently for improved performance"</span>
)
Além da execução assíncrona, limitação de taxa e armazenamento em cache são componentes essenciais de uma estratégia de produção robusta. A limitação de taxa impede que as ferramentas excedam as cotas da API, enquanto o armazenamento em cache reduz a frequência de chamadas de API, armazenando respostas por um período específico.
Limitação de taxa com recuo exponencial
Para lidar com APIs com limitação de taxa com elegância, é importante implementar estratégias de espera exponencial. O exemplo a seguir demonstra um decorador que repete solicitações com atrasos crescentes:
<span class="hljs-keyword">import</span> random
<span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps
<span class="hljs-keyword">import</span> asyncio
<span class="hljs-keyword">def</span> <span class="hljs-title function_">rate_limited_retry</span>(<span class="hljs-params">max_retries=<span class="hljs-number">3</span>, base_delay=<span class="hljs-number">1.0</span></span>):
<span class="hljs-string">"""Decorator for handling rate limits with exponential backoff."""</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">decorator</span>(<span class="hljs-params">func</span>):
<span class="hljs-meta"> @wraps(<span class="hljs-params">func</span>)</span>
<span class="hljs-keyword">async</span> <span class="hljs-keyword">def</span> <span class="hljs-title function_">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):
<span class="hljs-keyword">for</span> attempt <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(max_retries + <span class="hljs-number">1</span>):
<span class="hljs-keyword">try</span>:
<span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> func(*args, **kwargs)
<span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
<span class="hljs-keyword">if</span> <span class="hljs-string">"rate limit"</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">str</span>(e).lower() <span class="hljs-keyword">and</span> attempt < max_retries:
delay = base_delay * (<span class="hljs-number">2</span> ** attempt) + random.uniform(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>)
<span class="hljs-keyword">await</span> asyncio.sleep(delay)
<span class="hljs-keyword">continue</span>
<span class="hljs-keyword">raise</span> e
<span class="hljs-keyword">return</span> {<span class="hljs-string">"error"</span>: <span class="hljs-string">"Max retries exceeded"</span>}
<span class="hljs-keyword">return</span> wrapper
<span class="hljs-keyword">return</span> decorator
Estratégias de cache
O cache pode melhorar significativamente a responsividade e reduzir chamadas de API, armazenando dados acessados com frequência. Veja um exemplo de um sistema de cache simples:
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime, timedelta
<span class="hljs-keyword">from</span> typing <span class="hljs-keyword">import</span> <span class="hljs-type">Dict</span>, <span class="hljs-type">Any</span>, <span class="hljs-type">Optional</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">ToolCache</span>:
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self, default_ttl_minutes: <span class="hljs-built_in">int</span> = <span class="hljs-number">15</span></span>):
<span class="hljs-variable language_">self</span>.cache: <span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Dict</span>[<span class="hljs-built_in">str</span>, <span class="hljs-type">Any</span>]] = {}
<span class="hljs-variable language_">self</span>.default_ttl = timedelta(minutes=default_ttl_minutes)
<span class="hljs-keyword">def</span> <span class="hljs-title function_">get</span>(<span class="hljs-params">self, key: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-type">Optional</span>[<span class="hljs-type">Any</span>]:
<span class="hljs-keyword">if</span> key <span class="hljs-keyword">in</span> <span class="hljs-variable language_">self</span>.cache:
entry = <span class="hljs-variable language_">self</span>.cache[key]
<span class="hljs-keyword">if</span> datetime.now() < entry[<span class="hljs-string">"expires"</span>]:
<span class="hljs-keyword">return</span> entry[<span class="hljs-string">"data"</span>]
<span class="hljs-keyword">else</span>:
<span class="hljs-keyword">del</span> <span class="hljs-variable language_">self</span>.cache[key]
<span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">set</span>(<span class="hljs-params">self, key: <span class="hljs-built_in">str</span>, data: <span class="hljs-type">Any</span>, ttl_minutes: <span class="hljs-type">Optional</span>[<span class="hljs-built_in">int</span>] = <span class="hljs-literal">None</span></span>) -> <span class="hljs-literal">None</span>:
ttl = timedelta(minutes=ttl_minutes) <span class="hljs-keyword">if</span> ttl_minutes <span class="hljs-keyword">else</span> <span class="hljs-variable language_">self</span>.default_ttl
<span class="hljs-variable language_">self</span>.cache[key] = {
<span class="hljs-string">"data"</span>: data,
<span class="hljs-string">"expires"</span>: datetime.now() + ttl
}
<span class="hljs-comment"># Global cache instance</span>
tool_cache = ToolCache()
Ao combinar essas técnicas — execução assíncrona, limitação de taxa e armazenamento em cache — as ferramentas LangChain podem alcançar um desempenho mais suave e confiável em ambientes de produção.
Segurança no Desenvolvimento de Ferramentas
Embora o desempenho seja um foco fundamental, a segurança é igualmente crítica ao implantar ferramentas LangChain em produção. As ferramentas frequentemente acessam sistemas externos com permissões elevadas, o que as torna vulneráveis a riscos como validação de entrada insuficiente e acesso excessivamente permissivo.
Validação de entrada com pidantico Modelos
Os modelos Pydantic fornecem uma base sólida para a validação de entradas. Ao impor regras rígidas, eles ajudam a evitar que dados maliciosos ou inválidos comprometam o sistema. Veja um exemplo de um modelo de entrada seguro:
<span class="hljs-keyword">from</span> pydantic <span class="hljs-keyword">import</span> BaseModel, Field
<span class="hljs-keyword">class</span> <span class="hljs-title class_">SecureAPIRequest</span>(<span class="hljs-title class_ inherited__">BaseModel</span>):
<span class="hljs-string">"""Secure input model with comprehensive validation."""</span>
endpoint: <span class="hljs-built_in">str</span> = Field(..., regex=<span class="hljs-string">r'^[a-zA-Z0-9/_-]+$'</span>, max_length=<span class="hljs-number">200</span>)
user_id: <span class="hljs-built_in">str</span> = Field(..., regex=<span class="hljs-string">r'^[a-zA-Z0-9-]+$'</span>)
<span class="hljs-comment"># Additional fields and validators can be added here to further secure inputs</span>
Protegendo ferramentas de API
O exemplo a seguir demonstra uma ferramenta de API segura que incorpora validação de entrada e verificações de segurança adicionais:
<span class="hljs-keyword">def</span> <span class="hljs-title function_">create_secure_api_tool</span>():
<span class="hljs-string">"""Create API tool with built-in security validation."""</span>
<span class="hljs-keyword">def</span> <span class="hljs-title function_">secure_api_call</span>(<span class="hljs-params">request: SecureAPIRequest</span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-comment"># Additional security checks</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> _is_authorized_user(request.user_id):
<span class="hljs-keyword">return</span> <span class="hljs-string">"Error: Unauthorized access attempt"</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> _is_allowed_endpoint(request.endpoint):
<span class="hljs-keyword">return</span> <span class="hljs-string">"Error: Endpoint not permitted"</span>
<span class="hljs-keyword">try</span>:
<span class="hljs-comment"># Perform the actual API call with validated inputs</span>
result = _execute_api_request(request)
<span class="hljs-keyword">return</span> _sanitize_response(result)
<span class="hljs-keyword">except</span> Exception:
<span class="hljs-comment"># Never expose internal error details</span>
<span class="hljs-keyword">return</span> <span class="hljs-string">"Error: Request processing failed"</span>
<span class="hljs-keyword">return</span> StructuredTool.from_function(
func=secure_api_call,
name=<span class="hljs-string">"secure_api_tool"</span>,
description=<span class="hljs-string">"Execute API requests with comprehensive security validation"</span>
)
Sanitizando respostas de API
Para evitar que informações confidenciais sejam expostas, as respostas devem ser higienizadas antes de serem devolvidas:
<span class="hljs-keyword">def</span> <span class="hljs-title function_">_sanitize_response</span>(<span class="hljs-params">response: <span class="hljs-built_in">dict</span></span>) -> <span class="hljs-built_in">str</span>:
<span class="hljs-string">"""Remove sensitive information from API responses."""</span>
sensitive_keys = [<span class="hljs-string">'password'</span>, <span class="hljs-string">'token'</span>, <span class="hljs-string">'secret'</span>, <span class="hljs-string">'key'</span>, <span class="hljs-string">'credential'</span>]
<span class="hljs-keyword">def</span> <span class="hljs-title function_">clean_dict</span>(<span class="hljs-params">obj</span>):
<span class="hljs-keyword">if</span> <span class="hljs-built_in">isinstance</span>(obj, <span class="hljs-built_in">dict</span>):
<span class="hljs-keyword">return</span> {k: clean_dict(v) <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> obj.items()
<span class="hljs-keyword">if</span> k.lower() <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> sensitive_keys}
<span class="hljs-keyword">elif</span> <span class="hljs-built_in">isinstance</span>(obj, <span class="hljs-built_in">list</span>):
<span class="hljs-keyword">return</span> [clean_dict(item) <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> obj]
<span class="hljs-keyword">return</span> obj
cleaned = clean_dict(response)
<span class="hljs-keyword">return</span> <span class="hljs-built_in">str</span>(cleaned)[:<span class="hljs-number">1000</span>] <span class="hljs-comment"># Limit response size</span>
Gerenciamento de permissão
O gerenciamento de permissões deve aderir ao princípio do menor privilégio, garantindo que as ferramentas tenham acesso apenas aos recursos necessários para suas tarefas. Controles de acesso baseados em funções podem restringir ainda mais ações não autorizadas, aumentando a segurança geral. .
Nó latenteAbordagem de Integração Visual da
As ferramentas LangChain frequentemente exigem codificação manual e manutenção contínua, o que pode consumir muito tempo e recursos. O Latenode, por outro lado, simplifica esse processo com seus conectores pré-construídos para centenas de serviços, eliminando a necessidade de codificação personalizada na maioria das integrações comuns.
Desenvolvimento Latenode vs. LangChain Manual
O contraste entre a criação de ferramentas personalizadas do LangChain e o uso do design visual do fluxo de trabalho do Latenode é impressionante, principalmente em termos de tempo e complexidade de desenvolvimento. Por exemplo, criar uma ferramenta personalizada para o Planilhas Google normalmente envolve programação extensiva para tarefas como tratamento de erros, autenticação e validação de dados. Com o Latenode, a mesma funcionalidade pode ser alcançada por meio de uma interface intuitiva de arrastar e soltar.
Considere um fluxo de trabalho projetado para processar o feedback do cliente e atualizar uma planilha. Normalmente, isso exigiria ferramentas separadas para processamento de dados, autenticação de API e manipulação de planilhas. O Latenode simplifica isso em uma sequência visual como: Webhook → OpenAI GPT-4 → Planilhas Google. Cada conector nesta cadeia vem com autenticação e gerenciamento de erros integrados, eliminando grande parte do esforço manual.
O Latenode oferece suporte à integração com mais de 300 aplicativos e mais de 200 modelos de IA, abrangendo uma ampla gama de necessidades de automação empresarial sem a necessidade de código personalizado. Essa abordagem é especialmente benéfica para equipes que buscam soluções confiáveis sem o peso adicional da manutenção contínua. Ao otimizar os processos de desenvolvimento e manutenção, o Latenode facilita a transição para uma gestão eficiente do sistema.
Além de acelerar o desenvolvimento, esta plataforma reduz significativamente os desafios associados à manutenção de ferramentas personalizadas.
Reduzindo a sobrecarga e melhorando a manutenibilidade
O desenvolvimento de ferramentas programáticas frequentemente envolve a depuração de chamadas de funções complexas e o gerenciamento da análise de parâmetros, o que pode ser um processo tedioso e sujeito a erros. O Latenode elimina esses obstáculos ao permitir interações entre o LLM e o sistema por meio de seu design de fluxo de trabalho visual, tornando as integrações acessíveis até mesmo para quem não é desenvolvedor.
Recursos como histórico de execução integrado e reexecuções de cenários permitem que as equipes diagnostiquem e corrijam problemas rapidamente, sem a necessidade de reconstruir fluxos de trabalho inteiros. Isso elimina grande parte das suposições normalmente associadas à depuração de ferramentas personalizadas.
Além disso, o AI Code Copilot da Latenode aumenta a flexibilidade, permitindo que as equipes gerem e editem JavaScript diretamente nos fluxos de trabalho. Esse recurso preenche a lacuna entre o design visual e a lógica personalizada, permitindo que as equipes adicionem funcionalidades personalizadas sem alternar entre diferentes ambientes de desenvolvimento. Essa integração perfeita ajuda as equipes a se concentrarem na criação de soluções de automação enxutas e eficazes.
A manutenção é ainda mais simplificada, pois o Latenode gerencia automaticamente alterações de API, atualizações de autenticação e confiabilidade do conector. Isso poupa as equipes da tarefa contínua de monitorar atualizações de API externas e revisar implementações personalizadas, reduzindo a sobrecarga a longo prazo.
Conectores pré-construídos para integrações mais rápidas
Os conectores pré-construídos da Latenode oferecem às equipes uma maneira mais rápida e eficiente de integrar sistemas externos, minimizando os requisitos de manutenção. Essas integrações são projetadas para gerenciar automaticamente o tratamento de erros e as atualizações de API, economizando tempo e esforço valiosos.
A biblioteca de conectores da plataforma inclui ferramentas de negócios populares como Notion, Stripe, Whatsapp, Telegrame LinkedIn. Cada conector vem com autenticação pré-configurada e suporta casos de uso comuns, garantindo uma operação tranquila mesmo com a evolução das APIs.
Para automação de mensagens pessoais, o Latenode vai além das integrações de API padrão. Ele permite a automação para plataformas como WhatsApp, LinkedIn e Telegram, permitindo um alcance personalizado e fluxos de trabalho semelhantes aos de CRM. Implementar funcionalidades como ferramentas personalizadas do LangChain seria altamente complexo devido aos desafios de autenticação e conformidade.
Além disso, o banco de dados integrado do Latenode oferece gerenciamento estruturado de dados diretamente nos fluxos de trabalho. Em conjunto com a automação headless do navegador, ele suporta cenários de automação complexos que, de outra forma, exigiriam diversas ferramentas personalizadas e serviços externos.
Para equipes que estão considerando a decisão de construir ou comprar, o modelo de precificação da Latenode — baseado no tempo de execução em vez de cobranças por tarefa — costuma ser uma opção mais econômica. Isso pode gerar economias significativas em comparação com os custos de desenvolvimento e manutenção de ferramentas personalizadas da LangChain.
Perguntas
Qual é a diferença entre usar o decorador @tool e subclassificar BaseTool para criar ferramentas LangChain?
A construção do XNUMXº e XNUMXº pavimentos pôde ocorrer de forma simultânea, pois não houve necessidade de aguardar a cura do concreto – permitindo que todas as frentes de trabalho e especialistas em pisos ESD atuassem nos dois níveis ao mesmo tempo. @tool O decorator oferece uma maneira simples de transformar funções Python em ferramentas LangChain. Ao simplesmente encapsular uma função, ele atribui automaticamente atributos-chave, como o nome e a descrição da ferramenta, extraindo esses detalhes do nome e da docstring da função. Isso o torna uma excelente escolha para criar ferramentas simples ou para testar ideias rapidamente.
Para cenários que exigem mais complexidade, a subclassificação BaseTool é a melhor opção. Este método oferece maior flexibilidade, permitindo definir atributos personalizados, implementar validação avançada, gerenciar erros e projetar comportamentos mais complexos. É particularmente adequado para ferramentas que precisam atender a requisitos de nível de produção ou lidar com fluxos de trabalho complexos.
Em essência, o @tool O decorador é perfeito para configurações rápidas e fáceis, enquanto BaseTool é a escolha certa para construir ferramentas mais avançadas e confiáveis.
Como o Latenode torna a integração de sistemas externos mais fácil em comparação à criação de ferramentas personalizadas no LangChain?
O Latenode agiliza o processo de integração de sistemas externos por meio de seu design de fluxo de trabalho visual, eliminando a necessidade de codificação manual. Sua interface amigável de arrastar e soltar permite conexões perfeitas entre agentes de IA, APIs e serviços externos, evitando as tarefas frequentemente complexas de validação de parâmetros e tratamento de erros que acompanham o desenvolvimento de ferramentas personalizadas do LangChain.
Ao automatizar tarefas críticas, como tratamento de erros e configuração do sistema, o Latenode não só reduz o tempo de configuração, como também a probabilidade de erros de codificação. Isso o torna a escolha perfeita para quem busca integrações rápidas e confiáveis, especialmente se não tiver experiência avançada em programação. Com o Latenode, os usuários podem dedicar seus esforços à criação Soluções baseadas em IA em vez de solucionar problemas de código.
Quais são as melhores práticas para implantar ferramentas LangChain de forma segura e eficiente na produção?
Para implantar ferramentas LangChain de forma segura e eficiente em um ambiente de produção, comece focando em validação de entrada e saídaIsso ajuda a proteger contra ataques de injeção e outras vulnerabilidades de segurança. Garanta que as permissões sejam configuradas para fornecer apenas o acesso mínimo necessário para a funcionalidade, reduzindo riscos potenciais. Incorporando registro e monitoramento é igualmente crucial, pois permite que você identifique e resolva rapidamente quaisquer problemas que possam surgir.
Outra etapa fundamental é a preparação para o potencial uso indevido, implementando filtragem e validação de saída para manter a precisão e a integridade dos dados. Para aumentar a confiabilidade do sistema, integre limitação de taxa para controlar o tráfego e mecanismos de tratamento de erros para gerenciar problemas inesperados sem causar interrupções. Seguindo essas medidas, você pode criar um ambiente seguro e estável para suas ferramentas LangChain, mantendo o desempenho ideal.
Posts Relacionados do Blog



