LangChain Tools: Vollständige Anleitung zum Erstellen und Verwenden benutzerdefinierter LLM-Tools + Codebeispiele 2025
Lernen Sie, wie Sie LangChain-Tools erstellen und einsetzen, um die KI-Integration mit externen Systemen zu verbessern und so Automatisierung und Funktionalität zu steigern.

LangChain Tools sind Python-basierte Lösungen, die eine nahtlose Interaktion zwischen Large Language Models (LLMs) und externen Systemen wie APIs und Datenbanken ermöglichen. Durch die Unterstützung strukturierter Funktionsaufrufe ermöglichen diese Tools LLMs die Durchführung von Aufgaben wie dem Abrufen von Live-Daten, der Ausführung von Abfragen oder der Automatisierung von Workflows. Dieser Ansatz schließt die Lücke zwischen KI-Argumentation und umsetzbaren Ergebnissen und eignet sich ideal für Szenarien, die Echtzeit-Updates oder Systemintegration erfordern.
LangChain-Tools eignen sich besonders für Anwendungen wie Kundenservice-Bots, technische Supportsysteme und Finanzassistenten. Entwickler können zwischen zwei Erstellungsmethoden wählen: @tool Dekorateur für Einfachheit oder die BaseTool Unterklasse für erweiterte Anpassung. Beide Ansätze legen Wert auf klare Funktionssignaturen, robuste Fehlerbehandlung und präzise Eingabevalidierung, um Zuverlässigkeit zu gewährleisten.
Für Teams, die eine Alternative zur kundenspezifischen Entwicklung suchen, bieten Plattformen wie Latenknoten Vereinfachen Sie die Automatisierung mit vorgefertigten Konnektoren und visuellen Workflows. Beispielsweise können Sie Tools wie Notion, WhatsAppden Google Blätter wird unkompliziert, ohne dass umfangreiches Programmieren erforderlich ist. Dies reduziert Entwicklungszeit und Wartungsaufwand, sodass sich die Teams auf die Bereitstellung wirkungsvoller Lösungen konzentrieren können.
Erstellen einer benutzerdefinierten Langkette Werkzeug
Architektur und Kernkomponenten des LangChain-Tools
LangChain-Tools basieren auf einem strukturierten Framework, das Python-Funktionen in Schnittstellen transformiert, die von großen Sprachmodellen (LLMs) aufgerufen werden können. Dieses Setup ermöglicht eine reibungslose Interaktion zwischen KI-Modellen und externen Systemen. Im Folgenden untersuchen wir die Kernkomponenten, die den effektiven Betrieb dieser Tools ermöglichen.
Schlüsselkomponenten der LangChain-Tools
Die Funktionalität der LangChain-Tools wird durch fünf kritische Komponenten unterstützt. Jede spielt eine besondere Rolle bei der Gewährleistung eines reibungslosen Betriebs und einer zuverlässigen Kommunikation zwischen Tools und LLMs:
- Funktionssignatur
Die Funktionssignatur dient als Vorlage für die Benutzeroberfläche des Tools. Sie definiert die vom Tool akzeptierten Parameter und seine Ausgabe. Python-Typhinweise spielen eine entscheidende Rolle bei der Gestaltung dieser Signatur und helfen LLMs, das richtige Tool für bestimmte Aufgaben zu finden. Der Funktionsname dient als eindeutige Kennung und leitet das LLM bei der Ausführung zur Auswahl des richtigen Tools. - Werkzeugbeschreibungen
Werkzeugbeschreibungen vermitteln LLMs ein klares Verständnis der Funktion eines Werkzeugs. In einfacher, natürlicher Sprache verfasst, erklären sie, wann und wie das Werkzeug eingesetzt werden sollte und welche Ergebnisse es liefert. Klare und prägnante Beschreibungen sind unerlässlich, um Missverständnisse oder falsche Werkzeuganwendung zu vermeiden. - Parameterschema
Das Parameterschema definiert die Regeln und die Struktur für die Eingabe des Tools. Mithilfe von Python-Typhinweisen können Entwickler Schemata erstellen, die Einschränkungen, Standardwerte und benutzerdefinierte Validierungsregeln festlegen. Dadurch wird sichergestellt, dass die Eingabedaten korrekt formatiert sind, was das Risiko von Laufzeitfehlern reduziert und die allgemeine Zuverlässigkeit verbessert. - Retourenabwicklung
Diese Komponente bestimmt, wie die Ausgabe eines Tools verarbeitet und an das LLM zurückgegeben wird. Tools können Ausgaben in verschiedenen Formen erzeugen, z. B. als Klartext, strukturierte Daten oder komplexe Objekte. Das Rückgabeformat ist entscheidend, um sicherzustellen, dass das LLM die Ergebnisse effektiv in seinem Workflow nutzen kann. - Fehlerbehandlung
Die Fehlerbehandlung ist ein wichtiger, aber oft übersehener Aspekt. Tools müssen in der Lage sein, Probleme wie Netzwerkausfälle, Ratenbegrenzungen oder ungültige Eingaben zu bewältigen. Effektives Fehlermanagement stellt sicher, dass ein einzelner Fehler nicht den Betrieb eines gesamten Agenten stört, was besonders in Produktionsumgebungen wichtig ist.
Decorator vs. BaseTool-Unterklassenmethoden
LangChain bietet zwei Hauptansätze zur Erstellung von Tools, die jeweils auf unterschiedliche Komplexitätsstufen und Anwendungsfälle zugeschnitten sind. Diese Methoden sind die @tool Dekorateur und der BaseTool Unterklasse.
- Die
@toolDekorateur
Dieser Ansatz ist auf Einfachheit ausgelegt. Er ermöglicht Entwicklern die schnelle Konvertierung von Python-Funktionen in LangChain-kompatible Tools mit minimalem Aufwand. Der Dekorator übernimmt Aufgaben wie Schemagenerierung, Parametervalidierung und grundlegende Fehlerumbrüche automatisch. Er eignet sich ideal für einfache Operationen wie API-Aufrufe, einfache Berechnungen oder Datentransformationen, bei denen keine Zustandsverwaltung oder komplexe Initialisierung erforderlich ist. - Die
BaseToolUnterklasse
Für erweiterte AnforderungenBaseToolDie Subclass-Methode bietet umfangreiche Anpassungsmöglichkeiten. Sie eignet sich für Tools, die komplexe Logik, zustandsbehaftete Operationen oder erweiterte Fehlerbehandlung erfordern. Entwickler können benutzerdefinierte Initialisierung, asynchrone Operationen und komplexere Rückgabetypen implementieren. Diese Methode erfordert zwar mehr Programmierung, bietet aber die nötige Flexibilität für Tools auf Produktionsebene, insbesondere für Tools mit Authentifizierung, persistenten Verbindungen oder detaillierter Geschäftslogik.
Die Wahl des richtigen Ansatzes
Die Wahl zwischen diesen Methoden hängt von der Komplexität des Tools und dem Verwendungszweck ab. Einfache Tools beginnen oft mit dem Dekorator-Ansatz und können später, wenn die Anforderungen steigen, zu unterklassenbasierten Implementierungen weiterentwickelt werden. Für Tools, die jedoch eine robuste Fehlerbehandlung oder die Integration in komplexe Systeme erfordern, beginnend mit dem BaseTool Unterklassen können Zeit sparen und spätere architektonische Herausforderungen vermeiden.
Erstellen benutzerdefinierter Tools mit ordnungsgemäßer Validierung
Beim Erstellen benutzerdefinierter Tools ist es wichtig, auf eine strenge Eingabevalidierung, eine effektive Fehlerbehandlung und eine klare Dokumentation zu achten. Diese Elemente gewährleisten eine zuverlässige Leistung der Tools und eine nahtlose Integration in große Sprachmodelle (LLMs).
So erstellen Sie ein Basiswerkzeug
Die @tool Decorator bietet eine einfache Methode zum Erstellen von LangChain-Tools. Es generiert automatisch Schemata und übernimmt die grundlegende Validierung und ist somit ideal für einfache Vorgänge.
Hier ist ein Beispiel für ein Tool zur Wettersuche:
<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>
Für komplexere Szenarien, wie etwa solche, die eine benutzerdefinierte Initialisierung oder die Handhabung interner Zustände erfordern, ist die BaseTool Unterklasse bietet mehr Flexibilität:
<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)
Best Practices für Werkzeugnamen und -beschreibungen
Die Wahl klarer und beschreibender Namen für Werkzeuge hilft LLMs, deren Zweck und Verwendung zu verstehen. Verwenden Sie handlungsorientierte Verben in Werkzeugnamen (z. B. search_documents statt docs) und vermeiden Sie Abkürzungen, die das LLM verwirren könnten. Konsistenz zwischen verwandten Tools ist ebenso wichtig; zum Beispiel die Benennung mehrerer API-Tools als api_get_user, api_create_user und api_delete_user erstellt eine logische Gruppierung.
Beschreibungen sollten prägnant und im Aktiv verfasst sein und den Zweck des Tools, die erforderlichen Eingaben und die erwarteten Ergebnisse klar umreißen. Vergleichen Sie diese beiden Beispiele:
<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
Parametertypisierung und Eingabevalidierung
Die genaue Parametertypisierung ist entscheidend, um Laufzeitprobleme zu vermeiden und LLM-Interaktionen zu steuern. Die Typhinweise von Python und die Pydantic-Modelle arbeiten gut zusammen, um die Validierung zu erzwingen.
Grundlegende Typvalidierung Beispiel:
<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>
}
Erweiterte Validierung unter Verwendung von Pydantic-Modellen:
<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>
Fehlerbehandlung und Ausnahmeverwaltung
Sobald die Eingaben validiert sind, ist eine robuste Fehlerbehandlung entscheidend, um sicherzustellen, dass die Arbeitsabläufe auch bei auftretenden Problemen intakt bleiben. Eine gut konzipierte Fehlerbehandlung verhindert, dass ein einzelner Fehler den gesamten Prozess unterbricht, und liefert hilfreiches Feedback für die Fehlerbehebung.
Hier ist ein Beispiel für einen Dekorator zur Standardisierung der Fehlerbehandlung über verschiedene Tools hinweg:
<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
Integrieren von Tools mit Agenten und Workflows
Die Integration von LangChain-Tools mit Agenten umfasst die Auswahl der richtigen Tools und die Gewährleistung einer reibungslosen Ausführung der Aufgaben.
Verbinden von Tools mit Agenten
Hier ist ein Beispiel für die Einrichtung eines Agenten mit mehreren Tools, die auf ein Kundendienstszenario zugeschnitten sind:
<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>)
In diesem Beispiel verwendet der Agent die Eingabeabfrage, um zu bestimmen, welche Tools aktiviert werden sollen. Wenn mehrere Tools verfügbar sind, kann deren Organisation in spezialisierten Gruppen sowohl die Genauigkeit als auch die Effizienz verbessern. Beispielsweise können Tools nach ihrer Funktion gruppiert werden, z. B. nach auftrags- oder produktbezogenen Aufgaben:
<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)
Diese Methode stellt sicher, dass Abfragen an die relevantesten Tools weitergeleitet werden, wodurch eine optimierte Benutzererfahrung entsteht.
Erweiterte Tool-Muster für komplexe Arbeitsabläufe
Bei Workflows, die mehrere unabhängige API-Aufrufe oder Datenbankabfragen erfordern, kann die asynchrone Ausführung die Effizienz erheblich steigern. Anstatt Aufgaben nacheinander abzuarbeiten, ermöglichen asynchrone Muster die parallele Ausführung von Aufgaben:
<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
Dieser Ansatz spart nicht nur Zeit, sondern stellt auch sicher, dass das System komplexe Arbeitsabläufe effizient bewältigen kann.
Für Aufgaben, die Kontext über mehrere Interaktionen hinweg erfordern, können zustandsorientierte Tools verwendet werden. Diese Tools speichern Informationen und ermöglichen so eine kumulative Analyse und ein besseres Tracking:
<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>
Produktionsüberlegungen für LangChain-Tools
Die Überführung von LangChain-Tools von der Entwicklung in die Produktion erfordert einen durchdachten Ansatz, um Herausforderungen in Bezug auf Leistung, Sicherheit und Wartung zu bewältigen. Diese Überlegungen sind entscheidend, um sicherzustellen, dass die Tools in realen Umgebungen effizient und sicher funktionieren.
Optimierung der Werkzeugleistung
Leistungsengpässe in Produktionsumgebungen entstehen oft durch langsame externe API-Antworten, ineffiziente Logik oder übermäßige synchrone Vorgänge [1].[2].Diese Probleme treten besonders dann auf, wenn die Tools eine große Anzahl gleichzeitiger Anfragen verarbeiten oder mit APIs interagieren, die Ratenbegrenzungen erzwingen.
Eine Möglichkeit zur Leistungssteigerung besteht darin, asynchrone Ausführungsmuster, wodurch Tools mehrere Anfragen gleichzeitig verarbeiten können. Dieser Ansatz ist besonders effektiv für E/A-gebundene Operationen, wie das folgende Beispiel zeigt:
<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>
)
Zusätzlich zur asynchronen Ausführung Ratenbegrenzung und Caching sind wesentliche Bestandteile einer robusten Produktionsstrategie. Durch Ratenbegrenzung wird verhindert, dass Tools API-Kontingente überschreiten, während Caching die Häufigkeit von API-Aufrufen reduziert, indem Antworten für eine bestimmte Zeit gespeichert werden.
Ratenbegrenzung mit exponentiellem Backoff
Um ratenbegrenzte APIs reibungslos zu handhaben, ist die Implementierung exponentieller Backoff-Strategien wichtig. Das folgende Beispiel zeigt einen Dekorator, der Anfragen mit zunehmender Verzögerung wiederholt:
<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
Caching-Strategien
Durch Caching kann die Reaktionsfähigkeit deutlich verbessert und die Anzahl der API-Aufrufe reduziert werden, indem häufig abgerufene Daten gespeichert werden. Hier ist ein Beispiel für ein einfaches Caching-System:
<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()
Durch die Kombination dieser Techniken – asynchrone Ausführung, Ratenbegrenzung und Caching – können LangChain-Tools eine reibungslosere und zuverlässigere Leistung in Produktionsumgebungen erzielen.
Sicherheit in der Tool-Entwicklung
Während die Leistung im Mittelpunkt steht, ist die Sicherheit beim Einsatz von LangChain-Tools in der Produktion ebenso wichtig. Tools greifen häufig mit erhöhten Berechtigungen auf externe Systeme zu und sind dadurch anfällig für Risiken wie unzureichende Eingabevalidierung und zu freizügige Zugriffe.
Eingabevalidierung mit Pydantik Models
Pydantic-Modelle bieten eine robuste Grundlage für die Validierung von Eingaben. Durch die Durchsetzung strenger Regeln verhindern sie, dass schädliche oder ungültige Daten das System gefährden. Hier ist ein Beispiel für ein sicheres Eingabemodell:
<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>
Sichern von API-Tools
Das folgende Beispiel zeigt ein sicheres API-Tool, das Eingabevalidierung und zusätzliche Sicherheitsüberprüfungen umfasst:
<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>
)
Bereinigen von API-Antworten
Um zu verhindern, dass vertrauliche Informationen offengelegt werden, sollten Antworten vor der Rücksendung bereinigt werden:
<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>
Berechtigungsverwaltung
Das Berechtigungsmanagement sollte dem Prinzip der geringsten Privilegien folgen und sicherstellen, dass Tools nur auf die für ihre Aufgaben erforderlichen Ressourcen zugreifen können. Rollenbasierte Zugriffskontrollen können unbefugte Aktionen weiter einschränken und so die allgemeine Sicherheit erhöhen. [1].[3]..
LatenknotenVisueller Integrationsansatz
LangChain-Tools erfordern oft manuelle Programmierung und laufende Wartung, was zeit- und ressourcenintensiv sein kann. Latenode hingegen vereinfacht diesen Prozess mit seinen vorgefertigten Konnektoren zu Hunderten von Diensten und macht so bei den meisten gängigen Integrationen die individuelle Programmierung überflüssig.
Latenode vs. manuelle LangChain-Entwicklung
Der Unterschied zwischen der Erstellung benutzerdefinierter LangChain-Tools und der Nutzung des visuellen Workflow-Designs von Latenode ist eklatant, insbesondere hinsichtlich Entwicklungszeit und Komplexität. Beispielsweise erfordert die Entwicklung eines benutzerdefinierten Tools für Google Sheets in der Regel umfangreiches Coding für Aufgaben wie Fehlerbehandlung, Authentifizierung und Datenvalidierung. Mit Latenode lässt sich die gleiche Funktionalität über eine intuitive Drag-and-Drop-Oberfläche erreichen.
Stellen Sie sich einen Workflow vor, der Kundenfeedback verarbeitet und eine Tabelle aktualisiert. Normalerweise wären dafür separate Tools für die Datenverarbeitung, API-Authentifizierung und Tabellenbearbeitung erforderlich. Latenode vereinfacht dies in einer visuellen Sequenz wie: Webhook → OpenAI GPT-4 → Google Tabellen. Jeder Konnektor in dieser Kette verfügt über integrierte Authentifizierung und Fehlerverwaltung, wodurch ein Großteil des manuellen Aufwands entfällt.
Latenode unterstützt die Integration mit über 300 Apps und mehr als 200 KI-Modellen und deckt damit ein breites Spektrum an Geschäftsautomatisierungsanforderungen ab, ohne dass benutzerdefinierter Code erforderlich ist. Dieser Ansatz ist besonders vorteilhaft für Teams, die zuverlässige Lösungen ohne den zusätzlichen Aufwand laufender Wartung suchen. Durch die Optimierung der Entwicklungs- und Wartungsprozesse erleichtert Latenode den Übergang zu einem effizienten Systemmanagement.
Diese Plattform beschleunigt nicht nur die Entwicklung, sondern reduziert auch die Herausforderungen im Zusammenhang mit der Wartung individuell erstellter Tools erheblich.
Reduzierung des Overheads und Verbesserung der Wartbarkeit
Die Entwicklung programmatischer Tools erfordert häufig das Debuggen komplexer Funktionsaufrufe und die Verwaltung der Parameteranalyse, was ein mühsamer und fehleranfälliger Prozess sein kann. Latenode beseitigt diese Hürden, indem es durch sein visuelles Workflow-Design die Interaktion zwischen LLM und System ermöglicht und Integrationen auch für Nicht-Entwickler zugänglich macht.
Funktionen wie der integrierte Ausführungsverlauf und die Wiederholung von Szenarien ermöglichen es Teams, Probleme schnell zu diagnostizieren und zu beheben, ohne ganze Workflows neu erstellen zu müssen. Dadurch entfällt ein Großteil des Rätselratens, das normalerweise mit dem Debuggen benutzerdefinierter Tools verbunden ist.
Darüber hinaus erhöht Latenodes AI Code Copilot die Flexibilität, indem es Teams ermöglicht, JavaScript direkt in Workflows zu generieren und zu bearbeiten. Diese Funktion schließt die Lücke zwischen visuellem Design und benutzerdefinierter Logik und ermöglicht es Teams, maßgeschneiderte Funktionen hinzuzufügen, ohne zwischen verschiedenen Entwicklungsumgebungen wechseln zu müssen. Diese nahtlose Integration hilft Teams, sich auf die Entwicklung schlanker und effektiver Automatisierungslösungen zu konzentrieren.
Die Wartung wird weiter vereinfacht, da Latenode API-Änderungen, Authentifizierungsupdates und die Zuverlässigkeit des Connectors automatisch übernimmt. Dies erspart den Teams die laufende Überwachung externer API-Updates und die Überarbeitung benutzerdefinierter Implementierungen und reduziert so den langfristigen Aufwand.
Vorgefertigte Konnektoren für schnellere Integrationen
Die vorgefertigten Konnektoren von Latenode bieten Teams eine schnellere und effizientere Möglichkeit, externe Systeme zu integrieren und gleichzeitig den Wartungsaufwand zu minimieren. Diese Integrationen sind so konzipiert, dass sie die Fehlerbehandlung und API-Updates automatisch verwalten und so wertvolle Zeit und Mühe sparen.
Die Connector-Bibliothek der Plattform umfasst beliebte Business-Tools wie Notion, StripeWhatsApp Telegramund LinkedIn. Jeder Connector verfügt über eine vorkonfigurierte Authentifizierung und unterstützt gängige Anwendungsfälle, sodass auch bei der Weiterentwicklung der APIs ein reibungsloser Betrieb gewährleistet ist.
Für die Automatisierung persönlicher Messenger geht Latenode über Standard-API-Integrationen hinaus. Es ermöglicht die Automatisierung für Plattformen wie WhatsApp, LinkedIn und Telegram und ermöglicht so personalisierte Outreach- und CRM-ähnliche Workflows. Die Implementierung von Funktionen wie benutzerdefinierten LangChain-Tools wäre aufgrund der Herausforderungen bei Authentifizierung und Compliance äußerst komplex.
Darüber hinaus ermöglicht die integrierte Datenbank von Latenode strukturiertes Datenmanagement direkt in Workflows. In Kombination mit der Headless-Browser-Automatisierung unterstützt sie komplexe Automatisierungsszenarien, die sonst mehrere benutzerdefinierte Tools und externe Dienste erfordern würden.
Für Teams, die sich zwischen Eigenentwicklung und Kauf entscheiden, erweist sich das Preismodell von Latenode – basierend auf der Ausführungszeit statt auf Einzelkosten – oft als kostengünstigere Option. Dies kann zu erheblichen Einsparungen im Vergleich zu den Entwicklungs- und Wartungskosten kundenspezifischer LangChain-Tools führen.
FAQs
Was ist der Unterschied zwischen der Verwendung des @tool-Dekorators und der Unterklassenbildung von BaseTool zum Erstellen von LangChain-Tools?
Die @tool Decorator bietet eine einfache Möglichkeit, Python-Funktionen in LangChain-Tools umzuwandeln. Durch einfaches Wrapping einer Funktion werden automatisch wichtige Attribute wie Name und Beschreibung des Tools zugewiesen, wobei diese Details aus dem Funktionsnamen und dem Docstring der Funktion abgerufen werden. Dies macht es zu einer hervorragenden Wahl für die Erstellung einfacher Tools oder zum schnellen Testen von Ideen.
Für Szenarien, die mehr Komplexität erfordern, Unterklassen BaseTool ist die bessere Option. Diese Methode bietet mehr Flexibilität und ermöglicht die Definition benutzerdefinierter Attribute, die Implementierung erweiterter Validierungen, die Verwaltung von Fehlern und die Entwicklung komplexerer Verhaltensweisen. Sie eignet sich besonders für Tools, die Produktionsanforderungen erfüllen oder komplexe Workflows verarbeiten müssen.
Im Wesentlichen ist die @tool Decorator ist perfekt für schnelle und einfache Setups, während BaseTool ist die erste Wahl für die Entwicklung fortschrittlicherer und zuverlässigerer Tools.
Wie erleichtert Latenode die Integration externer Systeme im Vergleich zur Entwicklung benutzerdefinierter Tools in LangChain?
Latenode optimiert den Prozess der Integration externer Systeme durch seine visuelles Workflow-Design, wodurch manuelles Codieren überflüssig wird. Die benutzerfreundliche Drag-and-Drop-Oberfläche ermöglicht nahtlose Verbindungen zwischen KI-Agenten, APIs und externen Diensten und umgeht die oft kniffligen Aufgaben der Parametervalidierung und Fehlerbehandlung, die mit der Entwicklung benutzerdefinierter LangChain-Tools einhergehen.
Durch die Automatisierung kritischer Aufgaben wie Fehlerbehandlung und Systemkonfiguration verkürzt Latenode nicht nur die Einrichtungszeit, sondern reduziert auch die Wahrscheinlichkeit von Programmierfehlern. Dies macht es zur perfekten Wahl für alle, die schnelle und zuverlässige Integrationen suchen, insbesondere wenn ihnen fortgeschrittene Programmierkenntnisse fehlen. Mit Latenode können sich Benutzer auf die Erstellung von KI-gestützte Lösungen anstatt Code zu beheben.
Was sind die Best Practices für den sicheren und effizienten Einsatz von LangChain-Tools in der Produktion?
Um LangChain-Tools sicher und effizient in einer Produktionsumgebung einzusetzen, konzentrieren Sie sich zunächst auf Eingabe- und AusgabevalidierungDies schützt vor Injection-Angriffen und anderen Sicherheitslücken. Stellen Sie sicher, dass die Berechtigungen so konfiguriert sind, dass nur der für die Funktionalität erforderliche Mindestzugriff gewährt wird, um potenzielle Risiken zu reduzieren. Integrieren Protokollierung und Überwachung ist ebenso wichtig, da Sie so alle auftretenden Probleme schnell erkennen und beheben können.
Ein weiterer wichtiger Schritt ist die Vorbereitung auf potenziellen Missbrauch durch die Implementierung Ausgabefilterung und -validierung um die Datengenauigkeit und -integrität zu gewährleisten. Um die Systemzuverlässigkeit zu erhöhen, integrieren Ratenbegrenzung den Verkehr zu regeln und Fehlerbehandlungsmechanismen um unerwartete Probleme zu bewältigen, ohne Unterbrechungen zu verursachen. Indem Sie diese Maßnahmen befolgen, können Sie eine sichere und stabile Umgebung für Ihre LangChain-Tools schaffen und gleichzeitig eine optimale Leistung aufrechterhalten.
Ähnliche Blog-Beiträge



