Einführung in die Agenten
Zu Beginn des Vortrags werden wir verschiedene Beispiele für LLM-Agenten untersuchen. Obwohl das Thema viel diskutiert wird, nutzen nur wenige aktiv Agenten; oft sind das, was wir als Agenten wahrnehmen, einfach große Sprachmodelle. Betrachten wir eine so einfache Aufgabe wie die Suche nach Fußballspielergebnissen und deren Speicherung als CSV-Datei. Wir können mehrere verfügbare Tools vergleichen:
- GPT‑4 mit Suche und Plugins: wie Sie im Chatverlauf hier nachlesen können, scheiterte GPT‑4 aufgrund von Codefehlern
- AutoGPT über https://evo.ninja/ konnte zumindest eine Art von CSV generieren (allerdings nicht ideal):
- AgentGPT durch https://agentgpt.reworkd.ai/: beschlossen, diese Aufgabe als einen Generator für synthetische Daten zu behandeln, was nicht das ist, wonach wir gefragt haben, siehe den Chatverlauf hier
Da die verfügbaren Tools nicht besonders gut sind, sollten wir von den ersten Prinzipien lernen, wie man Agenten von Grund auf neu erstellt. Ich verwende den Blog-Artikel von Lilian als Referenz für die Struktur, füge aber auch eigene Beispiele hinzu.
Schritt 1: Planung
Vielleicht sind Sie schon einmal auf verschiedene Techniken gestoßen, die darauf abzielen, die Leistung großer Sprachmodelle zu verbessern, z. B. indem man ihnen Tipps gibt oder sie sogar scherzhaft bedroht. Eine beliebte Technik ist die „Gedankenkette“, bei der das Modell aufgefordert wird, Schritt für Schritt zu denken und sich selbst zu korrigieren. Dieser Ansatz hat sich zu fortgeschritteneren Versionen wie der „Gedankenkette mit Selbstkonsistenz“ und dem verallgemeinerten „Gedankenbaum“ weiterentwickelt, bei dem mehrere Gedanken erstellt, neu bewertet und zu einem Ergebnis zusammengefasst werden.
In diesem Tutorium verwende ich vor allem Langsmith, eine Plattform für die Erstellung von LLM-Anwendungen. Während der Erstellung des Gedankenbaums speichere ich zum Beispiel meine Unterprompts im Prompt-Repository und lade sie:
from langchain import hub
from langchain.chains import SequentialChain
cot_step1 = hub.pull("rachnogstyle/nlw_jan24_cot_step1")
cot_step2 = hub.pull("rachnogstyle/nlw_jan24_cot_step2")
cot_step3 = hub.pull("rachnogstyle/nlw_jan24_cot_step3")
cot_step4 = hub.pull("rachnogstyle/nlw_jan24_cot_step4")
model = "gpt-3.5-turbo"
chain1 = LLMChain(
llm=ChatOpenAI(temperature=0, model=model),
prompt=cot_step1,
output_key="solutions"
)
chain2 = LLMChain(
llm=ChatOpenAI(temperature=0, model=model),
prompt=cot_step2,
output_key="review"
)
chain3 = LLMChain(
llm=ChatOpenAI(temperature=0, model=model),
prompt=cot_step3,
output_key="deepen_thought_process"
)
chain4 = LLMChain(
llm=ChatOpenAI(temperature=0, model=model),
prompt=cot_step4,
output_key="ranked_solutions"
)
overall_chain = SequentialChain(
chains=[chain1, chain2, chain3, chain4],
input_variables=["input", "perfect_factors"],
output_variables=["ranked_solutions"],
verbose=True
)
Sie können in diesem Notizbuch das Ergebnis einer solchen Argumentation sehen. Der Punkt, den ich hier ansprechen möchte, ist der richtige Prozess für die Definition Ihrer Argumentationsschritte und deren Versionierung in einem LLMOps-System wie Langsmith. Sie können auch andere Beispiele für beliebte Schlussfolgerungstechniken in öffentlichen Repositories wie ReAct oder Self-ask mit Suche sehen:
prompt = hub.pull("hwchase17/react")
prompt = hub.pull("hwchase17/self-ask-with-search")
Andere bemerkenswerte Ansätze sind:
- Reflexion (Shinn & Labash 2023) ist ein Rahmen, der Agenten mit einem dynamischen Gedächtnis und Selbstreflexionsfähigkeiten ausstattet, um ihre Argumentationsfähigkeiten zu verbessern.
- Chain of Hindsight (CoH; Liu et al. 2023) ermutigt das Modell, seine eigenen Ergebnisse zu verbessern, indem es ihm explizit eine Abfolge vergangener Ergebnisse präsentiert, die jeweils mit Feedback versehen sind.
Schritt 2: Speicher
- Sensorisches Gedächtnis: Diese Komponente des Gedächtnisses erfasst unmittelbare Sinneseindrücke, wie das, was wir sehen, hören oder fühlen. Im Zusammenhang mit Prompt-Engineering und KI-Modellen dient ein Prompt als vorübergehender Input, ähnlich wie eine kurzzeitige Berührung oder Empfindung. Er ist der erste Reiz, der die Verarbeitung durch das Modell auslöst.
- Kurzzeitgedächtnis: Das Kurzzeitgedächtnis speichert Informationen vorübergehend, in der Regel im Zusammenhang mit einer laufenden Aufgabe oder Unterhaltung. In der Souffleurtechnik bedeutet dies, dass der jüngste Chatverlauf gespeichert wird. Dieser Speicher ermöglicht es dem Agenten, den Kontext und die Kohärenz während der gesamten Interaktion aufrechtzuerhalten und sicherzustellen, dass die Antworten mit dem aktuellen Dialog übereinstimmen. Im Code fügen Sie ihn normalerweise als Gesprächsverlauf hinzu:
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain.agents import AgentExecutor
from langchain.agents import create_openai_functions_agent
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
tools = [retriever_tool]
agent = create_openai_functions_agent(
llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
message_history = ChatMessageHistory()
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: message_history,
input_messages_key="input",
history_messages_key="chat_history",
)
- Langfristiges Gedächtnis: Das Langzeitgedächtnis speichert sowohl Faktenwissen als auch Verfahrensanweisungen. In KI-Modellen wird dies durch die Daten repräsentiert, die für das Training und die Feinabstimmung verwendet werden. Darüber hinaus unterstützt das Langzeitgedächtnis den Betrieb von RAG-Frameworks, indem es den Agenten ermöglicht, auf gelernte Informationen zuzugreifen und sie in ihre Antworten zu integrieren. Es ist eine Art umfassender Wissensspeicher, auf den Agenten zurückgreifen, um fundierte und relevante Ergebnisse zu erzeugen. Im Code fügen Sie es normalerweise als vektorisierte Datenbank hinzu:
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
loader = WebBaseLoader("https://neurons-lab.com/")
docs = loader.load()
documents = RecursiveCharacterTextSplitter(
chunk_size=1000, chunk_overlap=200
).split_documents(docs)
vector = FAISS.from_documents(documents, OpenAIEmbeddings())
retriever = vector.as_retriever()
Schritt 3: Tools
ChatGPT-Plugins und OpenAI-API-Funktionsaufrufe sind gute Beispiele dafür, dass LLMs, die um die Fähigkeit zur Nutzung von Tools erweitert wurden, in der Praxis funktionieren.
- Eingebaute Langchain-Werkzeuge: Langchain verfügt über eine Vielzahl integrierter Tools, von der Internetsuche und dem Arxiv-Toolkit bis hin zu Zapier und Yahoo Finance. Für dieses einfache Tutorial werden wir mit der Internetsuche von Tavily experimentieren:
from langchain.utilities.tavily_search import TavilySearchAPIWrapper
from langchain.tools.tavily_search import TavilySearchResults
search = TavilySearchAPIWrapper()
tavily_tool = TavilySearchResults(api_wrapper=search)
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.0)
agent_chain = initialize_agent(
[retriever_tool, tavily_tool],
llm,
agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
Benutzerdefinierte Werkzeuge: Es ist auch sehr einfach, eigene Werkzeuge zu definieren. Nehmen wir das einfache Beispiel eines Werkzeugs, das die Länge einer Zeichenkette berechnet, auseinander. Sie müssen den @tool
-DeKorator verwenden, damit Langchain davon erfährt. Vergessen Sie auch nicht den Typ der Eingabe und der Ausgabe. Aber der wichtigste Teil ist der Funktionskommentar zwischen „““ „““
– So weiß Ihr Agent, was dieses Werkzeug macht und vergleicht diese Beschreibung mit den Beschreibungen der anderen Werkzeuge:
from langchain.pydantic_v1 import BaseModel, Field
from langchain.tools import BaseTool, StructuredTool, tool
@tool
def calculate_length_tool(a: str) -> int:
"""The function calculates the length of the input string."""
return len(a)
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.0)
agent_chain = initialize_agent(
[retriever_tool, tavily_tool, calculate_length_tool],
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True,
)
Sie können Beispiele dafür finden, wie es in diesem Skript funktioniert, aber Sie können auch einen Fehler sehen – es zieht nicht die richtige Beschreibung der Firma Neurons Lab und trotz des Aufrufs der richtigen benutzerdefinierten Funktion der Längenberechnung, ist das Endergebnis falsch. Versuchen wir, das zu beheben!
Schritt 4: Alle zusammen
Ich biete eine saubere Version der Kombination aller Teile der Architektur in diesem Skript. Beachten Sie, wie einfach wir die einzelnen Teile zerlegen und definieren können:
- Alle Arten von Werkzeugen (Suche, benutzerdefinierte Werkzeuge, etc.)
- Alle Arten von Speichern (sensorisch als Eingabeaufforderung, kurzfristig als ablauffähige Meldungshistorie und als Skizzenblock innerhalb der Eingabeaufforderung und langfristig als Abruf aus der Vektordatenbank)
- Jede Art von Planungsstrategie (als Teil eines Prompts aus dem LLMOps-System)
Die endgültige Definition des Agenten wird so einfach aussehen wie diese:
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: message_history,
input_messages_key="input",
history_messages_key="chat_history",
)
Wie Sie in den Ausgaben des Skripts sehen können (oder Sie können es selbst ausführen), löst es das Problem aus dem vorherigen Teil in Bezug auf die Werkzeuge. Was hat sich geändert? Wir haben eine vollständige Architektur definiert, bei der das Kurzzeitgedächtnis eine entscheidende Rolle spielt. Unser Agent verfügt über einen Nachrichtenverlauf und einen Skizzenblock als Teil der Argumentationsstruktur, der es ihm ermöglicht, die richtige Beschreibung der Website zu finden und ihre Länge zu berechnen.
Fazit
Ich hoffe, dass dieser Rundgang durch die Kernelemente der LLM-Agentenarchitektur Ihnen helfen wird, funktionale Bots für die kognitiven Aufgaben zu entwerfen, die Sie automatisieren möchten. Zum Abschluss möchte ich noch einmal betonen, wie wichtig es ist, dass alle Elemente des Agenten vorhanden sind. Wie wir sehen, kann ein fehlendes Kurzzeitgedächtnis oder eine unvollständige Beschreibung eines Werkzeugs das Denken des Agenten durcheinander bringen und selbst bei sehr einfachen Aufgaben wie der Erstellung einer Zusammenfassung und der Berechnung ihrer Länge falsche Antworten liefern. Viel Erfolg bei Ihren KI-Projekten und zögern Sie nicht, sich zu melden, wenn Sie in Ihrem Unternehmen Hilfe benötigen!
Quelle: medium.com