Schlagwortarchiv für: Python

KI trifft Datenschutz: Unsere ChatGPT-Lösung für Unternehmenswissen

Frontend unserer scieneers-internen Chat-Applikation

Jeder kennt ChatGPT – ein Chatbot, der Antworten auf fast jede Frage liefert. Doch in vielen Firmen ist die Nutzung offiziell noch nicht erlaubt oder wird nicht bereitgestellt. Dabei kann ChatGPT komplett datenschutzkonform und sicher betrieben werden und Mitarbeitenden einen einfachen Zugang zu internem Firmenwissen ermöglichen. Basierend auf Erfahrungen aus zahlreichen Retrieval-Augmented Generation (RAG)-Projekten haben wir ein modulares System entwickelt, das speziell auf die Bedürfnisse mittelständischer Unternehmen und Organisationen zugeschnitten ist. In diesem Beitrag stellen wir unseren leichtgewichtigen und anpassbaren Chatbot vor, der einen datenschutzkonformen Zugriff auf Unternehmenswissen ermöglicht.

1. Eigene Wissensquellen nutzen

Der Kern unseres RAG-Systems liegt darin, dass ein LLM auf die unternehmensspezifische Wissensquellen zugreifen kann. Dem Chatbot können verschiedene Datenquellen zur Verfügung gestellt werden:

1. Nutzerspezifische Dokumente:

  • Mitarbeitende können eigene Dateien hochladen, z. B. PDF-Dokumente, Word-Dateien, Excel-Tabellen oder sogar Videos. Diese werden im Hintergrund verarbeitet und stehen nach kurzer Zeit dauerhaft zum Chatten zur Verfügung.
  • Der Verarbeitungsstatus ist jederzeit einsehbar, damit transparent bleibt, wann die Inhalte für Anfragen genutzt werden können.
  • Beispiel: Ein Vertriebsmitarbeitender lädt eine Excel-Tabelle mit Preisinformationen hoch. Das System kann daraufhin Fragen zu den Preisen spezifischer Produkte beantworten.

2. Globale unternehmensinterne Wissensquellen:

  • Das System kann auf zentrale Dokumente aus Plattformen wie SharePoint, OneDrive oder dem Intranet zugreifen. Diese Daten sind für alle Nutzenden zugänglich.
  • Beispiel: Ein Mitarbeitender möchte nach den Regelungen zur betrieblichen Altersvorsorge suchen. Da die entsprechende Betriebsvereinbarung zugänglich ist, kann der Chatbot die korrekte Antwort geben.

3. Gruppenspezifische Wissensquellen:

  • Es ist auch möglich, dass Informationen / Dokumente nur für spezifische Teams oder Abteilungen zugänglich gemacht werden.
  • Beispiel: Nur das HR-Team hat Zugriff auf Richtlinien zum Onboarding. Das System kann Fragen dazu nur HR-Mitarbeitenden beantworten.

Auch wenn Nutzende mit allen verfügbaren Datenquellen arbeiten, stellt das System im Hintergrund sicher, dass nur für eine Anfrage relevante Informationen genutzt werden, um Antworten zu generieren. Durch intelligente Filtermechanismen werden irrelevante Inhalte automatisch ausgeblendet.

Nutzende haben jedoch die Möglichkeit, explizit festzulegen, welche Wissensquellen berücksichtigt werden sollen. Sie können beispielsweise wählen, ob eine Anfrage auf aktuelle Quartalszahlen oder auf allgemeine HR-Richtlinien zugreifen soll. Dadurch wird vermieden, dass irrelevante oder veraltete Informationen in die Antwort einfließen.

2. Feedback-Prozess und kontinuierliche Verbesserung

Ein zentraler Bestandteil unserer RAG-Lösung ist die Möglichkeit, systematisch Feedback der Nutzenden zu erfassen, um die Qualität des Systems verbessern zu können, indem Schwachstellen identifiziert werden. Eine Schwachstelle könnten beispielsweise Dokumente mit uneinheitlichem Format darstellen, wie schlecht gescannte PDFs oder Tabellen mit mehreren verschachtelten Ebenen, die fehlerhaft interpretiert werden.

Nutzende können leichtgewichtig zu jeder Nachricht Feedback geben, indem sie die “Daumen hoch/runter”-Icons nutzen und einen optionalen Kommentar hinzufügen. Dieses Feedback kann entweder von Admins manuell ausgewertet oder durch automatisierte Analysen verarbeitet werden, um gezielt Optimierungspotenziale im System zu identifizieren.

3. Budgetmanagement – Kontrolle über Nutzung und Kosten

Die datenschutzkonforme Nutzung von LLMs im Zusammenhang mit eigenen Wissensquellen bietet Unternehmen enorme Möglichkeiten, bringt aber zugegebenermaßen auch Kosten mit sich. Ein durchdachtes Budgetmanagement hilft, Ressourcen fair und effizient zu nutzen und Kosten im Blick zu behalten.

Wie funktioniert das Budgetmanagement?

  • Individuelle und gruppenbasierte Budgets: Es wird festgelegt, wie viel Budget einzelnen Mitarbeitenden oder Teams in einem bestimmten Zeitraum zur Verfügung stehen. Dieses Budget muss nicht zwangsläufig ein Euro-Beitrag sein, sondern kann auch in eine virtuelle eigene Währung umgerechnet werden.
  • Transparenz für Nutzende: Alle Mitarbeitenden können jederzeit ihren aktuellen Budgetstatus einsehen. Das System zeigt an, wie viel des Budgets bereits verbraucht wurde und wie viel noch verfügbar ist. Wird das festgelegte Limit erreicht, pausiert der Chat automatisch, bis das Budget zurückgesetzt oder angepasst wird.

4. Sichere Authentifizierung – Schutz für sensible Daten

Ein wesentlicher Aspekt für Unternehmen ist oftmals die sichere und flexible Authentifizierung. Da RAG-Systeme oft mit sensiblen und vertraulichen Informationen arbeiten, ist ein durchdachtes Authentifizierungskonzept unverzichtbar.

  • Authentifizierungssysteme: Unsere Lösung ermöglicht die Anbindung unterschiedlicher Authentifizierungsverfahren, darunter weit verbreitete Systeme wie Microsoft Entra ID (ehemals Azure Active Directory). Dies bietet den Vorteil, bestehende Unternehmensstrukturen für die Nutzerverwaltung nahtlos einzubinden.
  • Zugriffskontrolle: Unterschiedliche Berechtigungen können auf Basis von Nutzerrollen definiert werden, z. B. für den Zugriff auf bestimmte Wissensquellen oder Funktionen.

5. Flexible Benutzeroberfläche

Unsere aktuelle Lösung vereint die meistgefragten Frontend-Features aus verschiedenen Projekten und bietet damit eine Benutzeroberfläche, die individuell anpassbar ist. Funktionen können bei Bedarf ausgeblendet oder erweitert werden, um spezifische Anforderungen zu erfüllen.

Chat-Applikation inklusive PDF-Viewer zur Anzeige von zitierten Dokumenten
  • Chat-Historie: Alle Chats werden automatisch benannt und gespeichert. Auf Wunsch können Nutzende Chats vollständig löschen – dies schließt auch ein endgültiges Entfernen aus dem System ein.
  • Zitationen: Zitationen gewährleisten, dass Informationen nachvollziehbar und überprüfbar bleiben. Gerade bei komplexen oder geschäftskritischen Fragen stärkt dies die Glaubwürdigkeit und ermöglicht es Nutzenden, die Richtigkeit und den Kontext der Antworten direkt zu überprüfen. Jede Antwort des Systems enthält Verweise auf die ursprünglichen Dokumentenquellen, beispielsweise mit Links zu der exakten Seite in einem PDF oder Absprung zur ursprünglichen Dokumentenquelle.
  • Einfache Anpassung von Prompts: Um die Systemantworten zu steuern, können Prompts über eine benutzerfreundliche Oberfläche angepasst werden – ganz ohne technisches Vorwissen.
  • Ausgabe von unterschiedlichen Medientypen: in den Antworten werden unterschiedliche Ausgabeformate, wie Codeblöcke oder Formeln, entsprechend angezeigt.

Fazit: Schneller Start, flexible Anpassung, transparente Kontrolle

Unsere Chatbot-Lösung basiert auf den Erfahrungen aus zahlreichen Projekten und ermöglicht Unternehmen, Sprachmodelle gezielt und datenschutzkonform zu nutzen. Dabei können spezifische interne Wissensquellen wie SharePoint, OneDrive oder individuelle Dokumente effizient eingebunden werden.

Dank einer flexiblen Codebasis kann das System schnell auf unterschiedliche Anwendungsfälle angepasst werden. Funktionen wie die Feedback-Integration, das Budgetmanagement und die sichere Authentifizierung sorgen dafür, dass Unternehmen jederzeit die Kontrolle behalten – über sensible Daten und auch die Kosten. Damit bietet das System nicht nur eine praxisnahe Lösung für den Umgang mit Unternehmenswissen, sondern auch die nötige Transparenz und Sicherheit für eine nachhaltige Nutzung.

Sie sind neugierig geworden? Dann zeigen wir Ihnen in einem persönlichen Gespräch gerne unser System in einer Live-Demo und beantworten Ihre Fragen. Schreiben Sie uns einfach!

Autorin

Alina Dallmann

Alina Dallmann, Data Scieneer bei scieneers GmbH
alina.dallmann@scieneers.de

Multi-Agenten-LLM-Systeme kontrollieren mit LangGraph

In diesem zweiten Teil zu Multi-Agenten-LLM-Systemen wird es um die Umsetzung komplexer Informationsflüsse mit Hilfe von LangGraph gehen. In Teil 1 wurde generell erklärt, warum Multi-Agenten-Systeme hilfreich sind und wie sie mit AutoGen umgesetzt werden können.

LangChain ist das populärste Framework für die Entwicklung von LLM-Applikationen. Es bietet nicht nur eine riesige Auswahl vordefinierter Text-Extraktionstools, Sprachmodelle und sonstiger Tools, sondern vor allem eine Hierarchie von Klassen. Typischerweise kombiniert man ein PromptTemplate mit einem LLM und optional einem Validator in einer Chain. Am einfachsten funktioniert dies durch die Nutzung der LCEL (LangChain Expression-Language), welche zwar etwas Gewöhnung erfordert, dafür aber kompakten und standardisierten Code ermöglicht.

from langchain.output_parsers.boolean import BooleanOutputParser
from langchain.prompts import PromptTemplate
from langchain_openai import AzureChatOpenAI

prompt = PromptTemplate.from_template(
    """Decide if the user question got sufficiently answered within the chat history. Answer only with YES or NO!
Sentences like "I don't know" or "There are no information" are no sufficient answers.

chat history: {messages}

user question: {user_question}
    """
)

llm = AzureChatOpenAI(
        openai_api_version="2024-02-15-preview",
        azure_deployment="gpt-35-turbo-1106",
        streaming=True
    )

parser = BooleanOutputParser()
validator_chain = prompt | llm | parser

# Zum Aufruf der Chain müssen alle Prompt-Variablen übergeben werden
validator_chain.invoke({    
    "user_question": "Was sind die aktuellen Trends in Italien?",
    "messages": ["die aktuellen Trends Italiens sind heute Formel 1 und ChatGPT"],
}) # Returns True

Natürlich wird auch die Ausführung von Funktionen (bzw. Tools) von LangChain unterstützt. Hierfür müssen wir zunächst die auszuführende Funktion in ein LangChain-Tool umwandeln. Dies kann explizit oder via Funktionsannotation erfolgen. Der Vorteil hierbei ist, dass die notwendigen Informationen für die Nutzung in einem Sprachmodell automatisch aus den Docstrings der Funktion extrahiert werden und somit Redundanzen vermieden werden können.

from pytrends.request import TrendReq

def get_google_trends(country_name='germany', num_trends=5):
    """
    Fetches the current top trending searches for a given country from Google Trends.

    Parameters:
    - country_name (str): The english name of the country written in lower letters
    - num_trends (int): Number of top trends to fetch. Defaults to 5.

    Returns:
    - Prints the top trending searches.
    """
    pytrends = TrendReq(hl='en-US', tz=360)
    try:
        trending_searches_df = pytrends.trending_searches(pn=country_name)
        top_trends = trending_searches_df.head(num_trends)[0].to_list()
        return top_trends
    except Exception as e:
        print(f"An error occurred: {e}")

from langchain.tools import StructuredTool
google_trends_tool = StructuredTool.from_function(get_google_trends)
google_trends_tool.invoke(input={})

Anschließend muss das erstellte Tool dem Modell übergeben werden. Nutzt man ChatGPT, unterstützt das Modell natives function_calling, sodass das Tool lediglich mit Hilfe des Aufrufs bind_functions aktiviert werden muss. Nun kann das Modell einen entsprechenden Funktionsaufruf bei Bedarf triggern, um die Funktion aber auch automatisch auszuführen und die Ergebnisse dem Modell zurückzugeben, muss die Chain in einen Agenten überführt werden. Hierfür existiert eine eigene Klasse, die neben der auszuführenden Chain lediglich einen Namen und die auszuführenden Tools benötigt.

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.agents import create_openai_functions_agent
from langchain_core.utils.function_calling import convert_to_openai_function
from langchain_core.runnables import RunnablePassthrough
from langchain.agents.output_parsers.openai_functions import OpenAIFunctionsAgentOutputParser
from langchain.agents import AgentExecutor
from langchain_core.messages import HumanMessage
from langchain.agents.format_scratchpad.openai_functions import (
    format_to_openai_function_messages,
)

from langchain_community.tools.tavily_search import TavilySearchResults
tavily_tool = TavilySearchResults(max_results=5)

tools = [google_trends_tool, tavily_tool]
system_prompt = "\\nYou task is to get information on the current trends by using your tools."
prompt = ChatPromptTemplate.from_messages([
        ("system", system_prompt),
        MessagesPlaceholder(variable_name="messages"),
        MessagesPlaceholder(variable_name="agent_scratchpad"),
])
agent = create_openai_functions_agent(llm, tools, prompt)
llm_with_tools = llm.bind(functions=[convert_to_openai_function(t) for t in tools])
agent = (
    RunnablePassthrough.assign(
        agent_scratchpad=lambda x: format_to_openai_function_messages(
            x["intermediate_steps"]
        )
    )
    | prompt
    | llm_with_tools
    | OpenAIFunctionsAgentOutputParser()
)

executor = AgentExecutor(name="Analyzer", agent=agent, tools=tools)

Mit der LangChain-Version 0.1 wurde zudem LangGraph als Konzept zur Implementierung von Multi-Agenten-Systemen eingeführt. LangGraph orientiert sich an der Idee von AutoGen, organisiert die Kommunikation jedoch nicht über einen freien Nachrichtenaustausch und geteilte Chat-Historie, sondern mittels eines Graphen. Das Interface orientiert sich an der beliebten NetworkX Python-Bibliothek und ermöglicht so eine flexible Komposition von gerichteten Graphen, welche auch zyklisch sein dürfen, also Schleifen enthalten können.

Zunächst wird ein Graph mit einem definierten Status definiert. Anschließend werden Knoten und Kanten hinzugefügt und ein Startpunkt gewählt. Kanten können statisch oder durch Bedingungen bestimmt werden, wodurch der Graph seine Dynamik erhält. Sowohl die Knoten wie auch die bedingten Kanten können einfache Python-Funktionen sein oder auch mittels LLM-Call bestimmt werden. Sie erhalten dafür jeweils den aktuellen State und geben einen neuen State für den nächsten Knoten zurück. Abschließend wird der Graph mit allen Knoten und Kanten zu einem “Pregel”-Objekt kompiliert.

from langchain_core.prompts import ChatPromptTemplate
from typing import TypedDict, Annotated, Sequence
import operator
from langchain_core.messages import BaseMessage
from langgraph.graph import StateGraph, END

compliance_prompt = ChatPromptTemplate.from_messages([
    ("system", """Make sure the answer is written in the same language as the user language. 
    The answer should be well-written in a formal style. It should use gender neutral language. 
    Modify the answer if necessary.

    user question: {user_question}
    
    chat history: {answer}
    
    """)
])
        
compliance_chain = compliance_prompt | llm 
class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add] = []
    round: int = 0

workflow = StateGraph(AgentState)

def call_writer(data):
    if data.get("round") is None:
        round = 1
    else:
        round = data["round"] + 1
        
    return {"round": round, "messages": [executor.invoke(data).get("output")]}

def call_compliance(data):
    return {"messages": [compliance_chain.invoke({"user_question": data["messages"][0], "answer": data["messages"][-1]})]}

workflow.add_node("writer", call_writer)
workflow.add_node("compliance", call_compliance)

workflow.set_entry_point("writer")
workflow.add_conditional_edges(
    "compliance",
    lambda x: validator_chain.invoke({"user_question": x["messages"][0], "messages": x["messages"][1:]}) if x["round"]<2 else True,
    {
        True: END,
        Fals4e: "writer"
    }
)

workflow.add_edge('writer', 'compliance')

app = workflow.compile().with_config(run_name="Conduct Interviews")

app.invoke({"messages": [HumanMessage("Was sind die derzeit größten Trends in der Türkei?")]}) 

Dieser Pregel-Graph implementiert selbst das LangChain Runnable Interface, kann also synchron wie asynchron und als Stream- oder Batch-Operation ausgeführt werden. Typisch für LangChain wird die Komplexität selbst also möglichst vor dem Nutzer verborgen, was jedoch auch das Debugging erschwert. Sehr hilfreich ist in diesem Zug LangSmith, die von LangChain entwickelte Monitoring-Lösung. Die Integration erfordert lediglich einen API-Key, anschließend werden sämtliche Events in die Cloud gestreamt und dort in einer benutzerfreundlichen WebUI dargestellt. Diese bietet einen schnellen Einblick in sämtliche ausgeführte Operationen wie LLM-API-Calls, ausgeführte Tools und aufgetretene Fehler. Dazu werden Ausführungszeiten, generierte Tokens bzw. deren Kosten sowie zahlreiche System-Meta-Informationen getrackt.

Wer LangSmith nicht nutzen möchte oder mehr Kontrolle wünscht, kann dem Workflow einen eigenen Callback mitgeben und darin auftretende Events weiterverarbeiten. Beispielsweise eignen sich Callbacks auch, um eine eigene UI anzuschließen. Die Implementierung ist durchaus aufwändig, denn es existieren insgesamt 14 verschiedene Event-Typen, die bei Start, Ende und Fehlern von unterschiedlichen Aktionen relevant sind. In unserem Fall konnten wir leider nicht in jedem Event die gewünschten Informationen extrahieren, sondern mussten teilweise auf verlinkte Parent-Events zurückgreifen, sodass wir selbst einen Graph-Callback entwickelt haben, über den sich auch die Komplexität der versteckten Aufrufe innerhalb eines LangGraph-Calls visualisieren lässt.

Vergleich zwischen LangGraph und AutoGen

AutoGenLangGraph
ProjektstatusAls erstes Framework für Multi-Agenten-Systeme erfreut sich AutoGen großer Beliebtheit. Das Projekt wird durch Microsoft vorangetrieben, basiert aber architektonisch auf dem dünnen Fundament eines wissenschaftlichen Aufsatzes.Die Multi-Agenten-Lösung des populärsten LLM-Frameworks wurde im Januar 2024 veröffentlicht. Sie nutzt erste Erfahrungen von AutoGen und kombiniert sie mit Ansätzen aus etablierten Open-Source-Projekten (NetworkX, Pregel). LangGraph wird als eine Komponente des LangChain-Ökosystems fortgeführt.
Function CallingBei Autogen werden sämtliche Funktionsausführungen durch einen idee proxy agent ausgeführt. Entweder nativ oder für mehr Sicherheit innerhalb eines Docker Containers.In LangChain können Funktionen und Agenten selbst in Executables verwandelt werden. Das vereinfacht die Struktur, eine Kapselung von Funktionsausführung in einer separaten Sandbox wie bspw. einem Container ist derzeit nicht vorgesehen..
NachrichtenflussDie Kommunikation zwischen Agenten erfolgt innerhalb eines Gruppenchats prinzipiell frei und wird über einen group chat manager gesteuert. Dies bietet viel Flexibilität für Agenten, aber erschwert explizite Struktur.Die Kommunikation wird durch einen Graphen abgebildet. Darüber lassen sich auch spezifische Kommunikationspfade einfach und intuitiv abbilden. Durch Conditional Edges sind aber auch komplett offene Gruppengespräche zwischen Agenten abbildbar.
UsabilityAutoGen bietet mit seinen Beispielen und dem AutoGen Studio einen einfachen Einstieg in die Nutzung mehrerer Agenten. Möchte man jedoch nicht nur Prompts und Tools modifizieren, müssen die eigentlichen Agentenklassen erweitert werden, was Upgrades und Maintenance erschwert.LangChain ist ein mächtiges Framework, das versucht, Komplexität vor dem Nutzer zu verstecken, ihn dafür aber abverlangt, zahlreiche Framework-Eigenheiten zu erlernen. Der hohe Grad an Abstraktion führt jedoch gerade zu Beginn oft zu Hindernissen. Hat ein Nutzer jedoch die Spezifika von LangChain verstanden, ist der Einsatz von LangGraph einfach und intuitiv.
ReifegradAutogen eignet sich hervorragend für einen Einstieg ins Thema Multi-Agenten, jedoch ist es schwierig, produktive Use-Cases hiermit umzusetzen. Gruppenkonversationen sind wenig verlässlich und es gibt keine Unterstützung bezüglich Monitoring und Ähnlichem. Durch die geteilte Chat-Historie der Agenten werden die ausgeführten Prompts schnell lang und damit teuer und langsam.LangGraph ist eine noch junge Software auf einem gut durchdachten Fundament. Das LangChain-Ökosystem bietet zahlreiche Output-Parser und Möglichkeiten des Fehlermanagements. LangGraph bietet zudem eine genaue Kontrolle, welcher Knoten zu welchem Zeitpunkt welche Informationen verfügbar haben soll und Business-Anforderungen an den Kommunikationsfluss lassen sich flexibel abbilden. Zudem wird es durch seine Serving- und Monitoring-Infrastruktur unterstützt.

Fazit

AutoGen hat einen wertvollen Beitrag für Multi-Agenten-Systeme geleistet und eignet sich gut für erste Experimente. Wer allerdings eine genauere Kontrolle über die Kommunikation der Agenten wünscht oder eine produktive Anwendung bauen möchte, sollte eher auf LangGraph setzen. Wir selbst haben kürzlich eine existierende Anwendung von AutoGen auf LangGraph umgebaut. Während die Umsetzung der Agenten und Tools relativ einfach war, lagen die größten Aufwände in der Migration der UI-Anbindung, um via LangGraph-Callback alle notwendigen Informationen bezüglich Tool- und LLM-Nutzung abzubilden. Zudem unterstützen beide Frameworks bisher noch nicht nativ die parallele Ausführung von Agenten, wenn anschließend die Ergebnisse zusammengeführt werden sollen. Dennoch lässt sich sagen, dass sich mit LangGraph und LangSmith auch komplexe Workflows unter Einbeziehung von LLMs erstellen und betreiben lassen.

Eine Einführung in Multi-Agent-AI mit AutoGen

Nachdem 2023 große Sprachmodelle die Masse erreichten und Retrieval-Augmented-Generation-Use-Cases im Fokus der meisten Anwender lagen, rücken 2024 Agenten deutlicher ins öffentliche Blickfeld. Agenten sind (teil-)autonom arbeitende Instanzen, die es ermöglichen, Chat-Anwendungsfälle flexibler zu gestalten. Soll in einem Chat nicht immer das gleiche Dokumentenarchiv über RAG eingebunden werden, sondern je nach Use-Case unterschiedliche Informationsquellen herangezogen werden, so können Agenten beispielsweise selbstständig entscheiden, welche für eine Abfrage die richtige ist. Es können aber nicht nur Datenbanken bzw. nicht-textuelle Informationen integriert werden, sondern auch jeder IT-Prozess, von der Veröffentlichung von Inhalten auf der Website bis hin zur Erstellung und Ausführung von Softwarecode. Der Fantasie sind bezüglich dessen, was mit generativer KI möglich sein könnte, keine Grenzen gesetzt, doch die praktische Umsetzung stößt schnell auf Herausforderungen in Bezug auf Stabilität und Verlässlichkeit.

Dieser Blog-Post diskutiert, wann mehrere kollaborativ zusammenarbeitende Agenten hilfreich sein können. Er ist der erste einer Serie: In diesem werden die Bausteine eines Multi-Agenten-Systems erklärt sowie deren Umsetzung mit Autogen, der ersten Bibliothek speziell für Multi-Agenten-Setups. Der zweite Teil wird dann auf LangGraph eingehen, die kürzlich erschienene Bibliothek zur Umsetzung von Multi-Agenten-Workflows aufbauend auf die beliebte Bibliothek LangChain.

Wann benötigt man mehrere Agenten

Zunächst sollte klar gestellt werden: Mehrere Agenten helfen nicht, wenn es darum geht, eine einzige Aufgabe besonders gut zu lösen. Ist die Aufgabe hingegen gut in mehrere Teilaufgaben zerteilbar, dann können mehrere, spezialisierte Agenten, die zusammenarbeiten, ein guter Ansatz sein. Wollt ihr beispielsweise Kundenanfragen automatisch beantworten, aber das Modell trifft nicht den Kommunikationsstil des Unternehmens, solltet ihr die Zeit lieber in Fine-Tuning stecken. Wenn für die Beantwortung aber verschiedene Informationsquellen erfragt, zusammengefasst und anschließend nochmal unter Berücksichtigung der Corporate-Communication-Policy validiert werden soll, könnte die Aufteilung auf mehrere Agenten hilfreich sein.

Sprachmodelle wie ChatGPT generieren nicht nur Text, sondern wurden inzwischen auch für Function Calling gefinetuned. Auf diese Art wurde ihnen prinzipiell das Konzept von Funktionsaufrufen erklärt. Allerdings können sie derzeit selbst keine Funktionen direkt aufrufen, sondern sagen lediglich, dass sie eine bestimmte Funktion mit gewissen Parametern aufrufen würden. Die tatsächliche Ausführung der Funktion erfordert dann eine entsprechende Runtime. Kombiniert man diese mit der Intelligenz des Sprachmodells, erhält man einen Agenten, der beispielsweise selbstständig Programmcode erstellen, ausführen und anhand der Fehlermeldungen debuggen kann. Ein solcher Agent ist ein besonders mächtiges Tool, da er im Gegensatz zu einem reinen LLM nicht nur in der Lage ist einen textuellen output zu generieren, sondern darüber hinaus selbstständig Handlungen planen und ausführen kann. Grundsätzlich können derartige Agenten mit den unterschiedlichsten Tools kombiniert werden, etwa zum Suchen von Informationen aus einer Datenbank, zum Abfragen einer WebAPI, zur Analyse von Bildern oder zur Erstellung einer Website. Natürlich kann man diese sehr unterschiedlichen Tools zur Ausführung alle in einem Agenten kombinieren, und einen genrealistischen Agent bauen; jedoch muss man dann Kompromisse machen. Manche Aufgaben erfordern ein besonders gutes und teures Sprachmodell, für andere reicht ein kleines Modell mit Fine-Tuning. Selbst wenn nur ein Modell für alles genutzt wird, empfehlen sich meist unterschiedliche Konfigurationen, etwa ein niedriger Temperature-Wert für Programmieraufgaben, ein höherer für kreatives Schreiben. Darüber hinaus brauchen Agenten, die etwa Informationen aus einer Datenbank extrahieren sollen, ausführliche Informationen zu Tabellenschemata im System-Prompt, sodass unterschiedliche Tools hier stark konkurrieren würden. Zu guter Letzt stellt sich die Frage, warum ein Agent alles gleichzeitig können sollte, wenn sich in der UNIX- und Microservice-Philosophie immer wieder gezeigt hat, dass unterschiedliche Aufgaben in unterschiedlichen Teilen behandelt werden sollten.

Autogen – das erste Framework für Multi-Agent-Systeme

Autogen ist ein Framework zur Erstellung solcher Multi-Agenten-Systeme. Es basiert auf einem 2023 vorgestellten Paper und ist als Open-Source-Repository von Microsoft verfügbar. Im Autogen-Konzept sind Multi-Agenten-Systeme Gruppenkonversationen zwischen verschiedenen conversable_agent Objekte, die durch eine Python-Klasse manifestiert sind. Es gibt 3 Arten von Conversable Agents:

  • UserProxyAgent: Repräsentieren den Nutzer. Sie senden die Eingaben des Nutzers in die Konversation und geben das Ergebnis zurück. Darüber hinaus sind sie auch zuständig für das eigentliche Ausführen von Funktionen, die von anderen Agenten aufgerufen werden.
  • GroupChatManager: Verwaltet den Gesprächsfluss zwischen den Agenten. Dieser wähl zudem nach der Antwort eines Agenten den nächsten zuständigen Agenten. Dies erfolgt je nach Konfiguration entweder selbst durch den Aufruf eines Language Models oder nach einfachen Heuristiken (zufällig, round-robin).
  • AssistantAgent: Die eigentlichen inhaltlichen Agenten, welche spezifisch für die gewünschten Aufgaben konfiguriert werden.

Das Basis-Konzept besteht darin, dass ein Agent einem anderen eine Nachricht sendet, mit der optionalen Bitte um eine Antwort. Kombiniert man nun mehrere solcher Agenten in einen Gruppen-Chat, so werden die Nachrichten nicht nur einem, sondern in der Regel allen Teilnehmern weitergeleitet, sodass eine gemeinsame Chat-Historie entsteht. Auf diese Art haben Agenten einen gemeinsamen Wissenspool und können auf der Arbeit der Vorgänger aufbauen. Hierfür finden sich bei Autogen zahlreiche Beispiele, etwa um mit Hilfe eines Programmierers zunächst relevante Paper herunterzuladen und diese von einem Produktmanager anschließend daraus Produktideen generieren zu lassen. Gleichzeitig führt dieses Vorgehen bei größeren und komplexeren Gruppengesprächen dazu, dass die Chat-Historie schnell wächst und Abfragen langsamer und teurer werden.

llm_config = {"config_list": config_list_gpt4, "cache_seed": 42}
user_proxy = autogen.UserProxyAgent(
    name="User_proxy",
    system_message="A human admin.",
    code_execution_config={
        "last_n_messages": 2,
        "work_dir": "groupchat",
        "use_docker": False,
    },
    human_input_mode="TERMINATE",
)
coder = autogen.AssistantAgent(
    name="Coder",
    llm_config=llm_config,
)
pm = autogen.AssistantAgent(
    name="Product_manager",
    system_message="Creative in software product ideas.",
    llm_config=llm_config,
)
groupchat = autogen.GroupChat(agents=[user_proxy, coder, pm], messages=[], max_round=12)
manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)
user_proxy.initiate_chat(
    manager, message="Find a latest paper about gpt-4 on arxiv and find its potential applications in software.")

Für zahlreiche Applikationen wäre es nützlich, nicht eine offene Gruppendiskussion zwischen allen Agenten zu führen, sondern den Gesprächsverlauf genauer zu kontrollieren. Auch dies ist mit Autogen prinzipiell möglich und es existieren ein paar Beispiele, wie etwa ein Schachspiel, bei dem zwei Spieler einerseits mit dem Spiel, andererseits miteinander kommunizieren. Hierfür müssen speziellere AssistantAgent-Klassen erstellt werden, welche mit Hilfe von register_reply zusätzliche Antworten-Funktionen registrieren. Der erste Parameter ist dabei als ein Filter zu verstehen, für welche Art von Nachrichtensender diese Antwortfunktion genutzt werden soll. In der Antwortfunktion wird im Fall von _generate_board_reply die besondere Logik des Schachspiels abgehandelt und ein Tuple aus True und dem gewählten Zug zurückgegeben. Das True besagt, dass die Funktion eine abschließende Antwort generiert hat und entsprechend keine weiteren registrierten Antwort-Funktionen ausgeführt werden sollen.

sys_msg = """You are an AI-powered chess board agent.
You translate the user's natural language input into legal UCI moves.
You should only reply with a UCI move string extracted from the user's input."""

class BoardAgent(autogen.AssistantAgent):
    board: chess.Board
    correct_move_messages: Dict[autogen.Agent, List[Dict]]

    def __init__(self, board: chess.Board):
        super().__init__(
            name="BoardAgent",
            system_message=sys_msg,
            llm_config={"temperature": 0.0, "config_list": config_list_gpt4},
            max_consecutive_auto_reply=10,
        )
        self.register_reply(autogen.ConversableAgent, BoardAgent._generate_board_reply)
        self.board = board
        self.correct_move_messages = defaultdict(list)

    def _generate_board_reply(
        self,
        messages: Optional[List[Dict]] = None,
        sender: Optional[autogen.Agent] = None,
        config: Optional[Any] = None,
    ) -> Union[str, Dict, None]:
        message = messages[-1]
        # extract a UCI move from player's message
        reply = self.generate_reply(
            self.correct_move_messages[sender] + [message], sender, exclude=[BoardAgent._generate_board_reply]
        )
        uci_move = reply if isinstance(reply, str) else str(reply["content"])
        try:
            self.board.push_uci(uci_move)
        except ValueError as e:
            # invalid move
            return True, f"Error: {e}"
        else:
            # valid move
            m = chess.Move.from_uci(uci_move)
            display(  # noqa: F821
                chess.svg.board(
                    self.board, arrows=[(m.from_square, m.to_square)], fill={m.from_square: "gray"}, size=200
                )
            )
            self.correct_move_messages[sender].extend([message, self._message_to_dict(uci_move)])
            self.correct_move_messages[sender][-1]["role"] = "assistant"
            return True, uci_move

Mit Hilfe dieser Logik lassen sich prinzipiell vielfältige Kommunikationsmuster erstellen, in der Praxis wird diese Logik insbesondere bei komplexeren Setups diese Logik aber schnell kompliziert und unübersichtlich, denn der Nachrichtenfluss wird in vielen verschiedenen Klassen zerstreut definiert und hängt von Sender und Position der Antwort-Registration ab. Soll darüber hinaus auch gesteuert werden, wer welche Informationen erhält, so muss dies gesondert innerhalb des GroupChatManagers geregelt werden, was anspruchsvolle Kommunikationsflüsse weiter erschwert.

Fazit

Multi-Agenten-Systeme sind hilfreich, wenn komplexere (teil-)autonome Systeme gebaut werden sollen. Sie ermöglichen es, für jede Teilaufgabe einen speziellen Agenten zu definieren mit Hinblick auf Prompting, Modellauswahl und Konfiguration. Autogen war das erste Framework, das Entwickler bei der Definition solcher Systeme unterstützt und bietet zahlreiche Beispiele, insbesondere für offene Gruppengespräche. Sollen jedoch ein bewusst gesteuerter Informationsfluss realisiert werden, ist Autogen aufgrund seines Designs weniger geeignet. Hierfür empfehlen wir einen Blick in den zweiten Teil dieser Blogpost Reihe: Multi-Agenten-LLM-Systeme kontrollieren mit LangGraph

Nico Kreiling, Data Scientist bei scieneers GmbH
nico.kreiling@scieneers.de

IT-Tage 2023

Erstmals durften wir bei den IT-Tagen 2023 im Dezember in Frankfurt dabei sein. Die Konferenz bietet einen vielfältigen Einblick in die IT-Welt, von Software-Architektur über Agile-Praktikten bis zum zu großen Sprachmodellen. Wir trugen mit zwei Vorträgen zu Unit-Testing und Personalisierung mit LLMs spannende Themen für Data Scientists bei.

Offshore windpark

Anomalieerkennung bei Windkraftanlagen mit Temporal Fusion Transformern für Iqony

Transformer-Architekturen haben sich als bahnbrechend im Bereich des Natural Language Processing erwiesen. Temporal Fusion Transformer nutzen diese Architektur für die Prognose von Zeitreihen und bieten dabei gegenüber klassischen Modellen Vorteile wie z.B. hohe Interpretierbarkeit und Data Fusion. Mit iqony hatten wir nun die Möglichkeit dieses Modell in der Praxis für die Anomalieerkennung bei Windkraftanlagen zu testen.

Mit scikit-learn Modelle erstellen

Um Einsteiger:innen einen Überblick über die Möglichkeiten von scikit-learn zu geben, haben wir im kürzlichen erschienenen ix-Sonderheft „Künstliche Intelligenz“ einen Artikel zum Thema „Mit scikit-learn Modelle erstellen“ veröffentlicht.

Wie implementiere ich einen “Question Answering”-Bot für Slack in Python?

Basierend auf unseren internen Dokumenten und Chat-Gesprächen haben wir mit open-source Technologien ein System gebaut, welches den Zugriff auf internes Wissen vereinfacht. Hier geben wir einen detailierten Einblick im die Implementierung.

Einführung in Unittesting mit Python für Data Scientists

Unittests können in Data-Science-Projekten sehr sinnvoll sein, um eine hohe Codequalität sicherzustellen. Um den Einstieg in das Unittesten mit Python für Data Scientists zu erleichtern, haben wir einen Artikel zu diesem Thema geschrieben, der auf Informatik Aktuell veröffentlicht wurde.

Tipps & Tricks bei der Entwicklung eines Dashboards mit Streamlit & Plotly

Wir haben mit Streamlit und plotly.express ein web-basiertes Dashboard für die Übersicht über CO2-Emissionen gebaut. Dieser Blogeintrag zeigt einige Tipps und Tricks, die wir bei der Implementierung und dem Deployment des Dashboards gelernt haben.

ifbw22

informatica feminale Baden-Württemberg 2022 – ein Rückblick

Dieses Jahr fand die informatica feminale Baden-Württemberg an der technischen Fakultät der Universität in Freiburg statt, und wir scieneers durften dort mit einem Kurs zum Thema „Visualisierungsframeworks in Python“ das Angebot für die Teilnehmerinnen mitgestalten.