Ein­füh­rung in die Agenten

Illus­tra­tion des Autors. LLMs wer­den oft mit exter­nem Spei­cher über die RAG-Archi­tek­tur erwei­tert. Agen­ten erwei­tern die­ses Kon­zept auf Gedächt­nis, Argu­men­ta­tion, Werk­zeuge, Ant­wor­ten und Aktionen

Zu Beginn des Vor­trags wer­den wir ver­schie­dene Bei­spiele für LLM-Agen­ten unter­su­chen. Obwohl das Thema viel dis­ku­tiert wird, nut­zen nur wenige aktiv Agen­ten; oft sind das, was wir als Agen­ten wahr­neh­men, ein­fach große Sprach­mo­delle. Betrach­ten wir eine so ein­fa­che Auf­gabe wie die Suche nach Fuß­ball­spiel­ergeb­nis­sen und deren Spei­che­rung als CSV-Datei. Wir kön­nen meh­rere ver­füg­bare Tools vergleichen:

  • GPT‑4 mit Suche und Plug­ins: wie Sie im Chat­ver­lauf hier nach­le­sen kön­nen, schei­terte GPT‑4 auf­grund von Codefehlern
  • AutoGPT über https://evo.ninja/ konnte zumin­dest eine Art von CSV gene­rie­ren (aller­dings nicht ideal):
  • AgentGPT durch https://agentgpt.reworkd.ai/: beschlos­sen, diese Auf­gabe als einen Gene­ra­tor für syn­the­ti­sche Daten zu behan­deln, was nicht das ist, wonach wir gefragt haben, siehe den Chat­ver­lauf hier

Da die ver­füg­ba­ren Tools nicht beson­ders gut sind, soll­ten wir von den ers­ten Prin­zi­pien ler­nen, wie man Agen­ten von Grund auf neu erstellt. Ich ver­wende den Blog-Arti­kel von Lilian als Refe­renz für die Struk­tur, füge aber auch eigene Bei­spiele hinzu.

Schritt 1: Planung

Der visu­elle Unter­schied zwi­schen der ein­fa­chen „Input-Output“-LLM-Verwendung und sol­chen Tech­ni­ken wie einer Gedan­ken­kette, einer Gedan­ken­kette mit Selbst­kon­sis­tenz, einem Gedankenbaum

Viel­leicht sind Sie schon ein­mal auf ver­schie­dene Tech­ni­ken gesto­ßen, die dar­auf abzie­len, die Leis­tung gro­ßer Sprach­mo­delle zu ver­bes­sern, z. B. indem man ihnen Tipps gibt oder sie sogar scherz­haft bedroht. Eine beliebte Tech­nik ist die „Gedan­ken­kette“, bei der das Modell auf­ge­for­dert wird, Schritt für Schritt zu den­ken und sich selbst zu kor­ri­gie­ren. Die­ser Ansatz hat sich zu fort­ge­schrit­te­ne­ren Ver­sio­nen wie der „Gedan­ken­kette mit Selbst­kon­sis­tenz“ und dem ver­all­ge­mei­ner­ten „Gedan­ken­baum“ wei­ter­ent­wi­ckelt, bei dem meh­rere Gedan­ken erstellt, neu bewer­tet und zu einem Ergeb­nis zusam­men­ge­fasst werden.

In die­sem Tuto­rium ver­wende ich vor allem Lang­smith, eine Platt­form für die Erstel­lung von LLM-Anwen­dun­gen. Wäh­rend der Erstel­lung des Gedan­ken­baums spei­chere ich zum Bei­spiel meine Unter­prompts im Prompt-Repo­si­tory 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ön­nen in die­sem Notiz­buch das Ergeb­nis einer sol­chen Argu­men­ta­tion sehen. Der Punkt, den ich hier anspre­chen möchte, ist der rich­tige Pro­zess für die Defi­ni­tion Ihrer Argu­men­ta­ti­ons­schritte und deren Ver­sio­nie­rung in einem LLMOps-Sys­tem wie Lang­smith. Sie kön­nen auch andere Bei­spiele für beliebte Schluss­fol­ge­rungs­tech­ni­ken in öffent­li­chen Repo­si­to­ries wie ReAct oder Self-ask mit Suche sehen:

prompt = hub.pull("hwchase17/react")
prompt = hub.pull("hwchase17/self-ask-with-search")

Andere bemer­kens­werte Ansätze sind:

  • Refle­xion (Shinn & Labash 2023) ist ein Rah­men, der Agen­ten mit einem dyna­mi­schen Gedächt­nis und Selbst­re­fle­xi­ons­fä­hig­kei­ten aus­stat­tet, um ihre Argu­men­ta­ti­ons­fä­hig­kei­ten zu verbessern.
  • Chain of Hind­sight (CoH; Liu et al. 2023) ermu­tigt das Modell, seine eige­nen Ergeb­nisse zu ver­bes­sern, indem es ihm expli­zit eine Abfolge ver­gan­ge­ner Ergeb­nisse prä­sen­tiert, die jeweils mit Feed­back ver­se­hen sind.

Schritt 2: Speicher

Wir kön­nen ver­schie­dene Arten von Erin­ne­run­gen in unse­rem Gehirn den Kom­po­nen­ten der Archi­tek­tur der LLM-Agen­ten zuordnen
  • Sen­so­ri­sches Gedächt­nis: Diese Kom­po­nente des Gedächt­nis­ses erfasst unmit­tel­bare Sin­nes­ein­drü­cke, wie das, was wir sehen, hören oder füh­len. Im Zusam­men­hang mit Prompt-Engi­nee­ring und KI-Model­len dient ein Prompt als vor­über­ge­hen­der Input, ähn­lich wie eine kurz­zei­tige Berüh­rung oder Emp­fin­dung. Er ist der erste Reiz, der die Ver­ar­bei­tung durch das Modell auslöst.
  • Kurz­zeit­ge­dächt­nis: Das Kurz­zeit­ge­dächt­nis spei­chert Infor­ma­tio­nen vor­über­ge­hend, in der Regel im Zusam­men­hang mit einer lau­fen­den Auf­gabe oder Unter­hal­tung. In der Souf­fleur­tech­nik bedeu­tet dies, dass der jüngste Chat­ver­lauf gespei­chert wird. Die­ser Spei­cher ermög­licht es dem Agen­ten, den Kon­text und die Kohä­renz wäh­rend der gesam­ten Inter­ak­tion auf­recht­zu­er­hal­ten und sicher­zu­stel­len, dass die Ant­wor­ten mit dem aktu­el­len Dia­log über­ein­stim­men. Im Code fügen Sie ihn nor­ma­ler­weise als Gesprächs­ver­lauf 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",
)
  • Lang­fris­ti­ges Gedächt­nis: Das Lang­zeit­ge­dächt­nis spei­chert sowohl Fak­ten­wis­sen als auch Ver­fah­rens­an­wei­sun­gen. In KI-Model­len wird dies durch die Daten reprä­sen­tiert, die für das Trai­ning und die Fein­ab­stim­mung ver­wen­det wer­den. Dar­über hin­aus unter­stützt das Lang­zeit­ge­dächt­nis den Betrieb von RAG-Frame­works, indem es den Agen­ten ermög­licht, auf gelernte Infor­ma­tio­nen zuzu­grei­fen und sie in ihre Ant­wor­ten zu inte­grie­ren. Es ist eine Art umfas­sen­der Wis­sens­spei­cher, auf den Agen­ten zurück­grei­fen, um fun­dierte und rele­vante Ergeb­nisse zu erzeu­gen. Im Code fügen Sie es nor­ma­ler­weise als vek­to­ri­sierte Daten­bank 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

In der Pra­xis möch­ten Sie Ihren Agen­ten mit einer sepa­ra­ten Argu­men­ta­ti­ons­li­nie (die ein ande­res LLM, d.h. ein domä­nen­spe­zi­fi­sches oder ein ande­res ML-Modell für die Bild­klas­si­fi­zie­rung sein kann) oder mit etwas mehr regel­ba­sier­tem oder API-basier­tem ergänzen

ChatGPT-Plug­ins und Ope­nAI-API-Funk­ti­ons­auf­rufe sind gute Bei­spiele dafür, dass LLMs, die um die Fähig­keit zur Nut­zung von Tools erwei­tert wur­den, in der Pra­xis funktionieren.

  • Ein­ge­baute Lang­chain-Werk­zeuge: Lang­chain ver­fügt über eine Viel­zahl inte­grier­ter Tools, von der Inter­net­su­che und dem Arxiv-Tool­kit bis hin zu Zapier und Yahoo Finance. Für die­ses ein­fa­che Tuto­rial wer­den wir mit der Inter­net­su­che 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,
)

Benut­zer­de­fi­nierte Werk­zeuge: Es ist auch sehr ein­fach, eigene Werk­zeuge zu defi­nie­ren. Neh­men wir das ein­fa­che Bei­spiel eines Werk­zeugs, das die Länge einer Zei­chen­kette berech­net, aus­ein­an­der. Sie müs­sen den @tool-DeKo­ra­tor ver­wen­den, damit Lang­chain davon erfährt. Ver­ges­sen Sie auch nicht den Typ der Ein­gabe und der Aus­gabe. Aber der wich­tigste Teil ist der Funk­ti­ons­kom­men­tar zwi­schen „““ „““ – So weiß Ihr Agent, was die­ses Werk­zeug macht und ver­gleicht diese Beschrei­bung mit den Beschrei­bun­gen der ande­ren 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ön­nen Bei­spiele dafür fin­den, wie es in die­sem Skript funk­tio­niert, aber Sie kön­nen auch einen Feh­ler sehen – es zieht nicht die rich­tige Beschrei­bung der Firma Neu­rons Lab und trotz des Auf­rufs der rich­ti­gen benut­zer­de­fi­nier­ten Funk­tion der Län­gen­be­rech­nung, ist das End­ergeb­nis falsch. Ver­su­chen wir, das zu beheben!

Schritt 4: Alle zusammen

Ich biete eine sau­bere Ver­sion der Kom­bi­na­tion aller Teile der Archi­tek­tur in die­sem Skript. Beach­ten Sie, wie ein­fach wir die ein­zel­nen Teile zer­le­gen und defi­nie­ren können:

  • Alle Arten von Werk­zeu­gen (Suche, benut­zer­de­fi­nierte Werk­zeuge, etc.)
  • Alle Arten von Spei­chern (sen­so­risch als Ein­ga­be­auf­for­de­rung, kurz­fris­tig als ablauf­fä­hige Mel­dungs­his­to­rie und als Skiz­zen­block inner­halb der Ein­ga­be­auf­for­de­rung und lang­fris­tig als Abruf aus der Vektordatenbank)
  • Jede Art von Pla­nungs­stra­te­gie (als Teil eines Prompts aus dem LLMOps-System)

Die end­gül­tige Defi­ni­tion des Agen­ten wird so ein­fach aus­se­hen 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 Aus­ga­ben des Skripts sehen kön­nen (oder Sie kön­nen es selbst aus­füh­ren), löst es das Pro­blem aus dem vor­he­ri­gen Teil in Bezug auf die Werk­zeuge. Was hat sich geän­dert? Wir haben eine voll­stän­dige Archi­tek­tur defi­niert, bei der das Kurz­zeit­ge­dächt­nis eine ent­schei­dende Rolle spielt. Unser Agent ver­fügt über einen Nach­rich­ten­ver­lauf und einen Skiz­zen­block als Teil der Argu­men­ta­ti­ons­struk­tur, der es ihm ermög­licht, die rich­tige Beschrei­bung der Web­site zu fin­den und ihre Länge zu berechnen.

Fazit

Ich hoffe, dass die­ser Rund­gang durch die Kern­ele­mente der LLM-Agen­ten­ar­chi­tek­tur Ihnen hel­fen wird, funk­tio­nale Bots für die kogni­ti­ven Auf­ga­ben zu ent­wer­fen, die Sie auto­ma­ti­sie­ren möch­ten. Zum Abschluss möchte ich noch ein­mal beto­nen, wie wich­tig es ist, dass alle Ele­mente des Agen­ten vor­han­den sind. Wie wir sehen, kann ein feh­len­des Kurz­zeit­ge­dächt­nis oder eine unvoll­stän­dige Beschrei­bung eines Werk­zeugs das Den­ken des Agen­ten durch­ein­an­der brin­gen und selbst bei sehr ein­fa­chen Auf­ga­ben wie der Erstel­lung einer Zusam­men­fas­sung und der Berech­nung ihrer Länge fal­sche Ant­wor­ten lie­fern. Viel Erfolg bei Ihren KI-Pro­jek­ten und zögern Sie nicht, sich zu mel­den, wenn Sie in Ihrem Unter­neh­men Hilfe benötigen!

Quelle: medium.com