Das Rückgrat dieser Anwendung sind die Agenten und ihre Interaktionen. Insgesamt hatten wir zwei verschiedene Arten von Agenten:
- Benutzeragenten: Agenten, die jedem Benutzer zugeordnet sind. Sie sind hauptsächlich damit beauftragt, eingehende Nachrichten in die bevorzugte Sprache des Benutzers zu übersetzen.
- Aya-Agenten: Verschiedene mit Aya verbundene Agenten, jeder mit seiner eigenen spezifischen Rolle/Aufgabe
Benutzeragenten
Die UserAgent-Klasse wird verwendet, um einen Agenten zu definieren, der jedem Benutzerteil des Chatrooms zugeordnet wird. Einige der von der UserAgent-Klasse implementierten Funktionen:
1. Übersetzen Sie eingehende Nachrichten in die bevorzugte Sprache des Benutzers
2. Diagramm aktivieren/aufrufen, wenn ein Benutzer eine Nachricht sendet
3. Pflegen Sie einen Chatverlauf, um der Übersetzungsaufgabe einen Kontext zu geben und eine kontextbezogene Übersetzung zu ermöglichen
class UserAgent(object):def __init__(self, llm, userid, user_language):
self.llm = llm
self.userid = userid
self.user_language = user_language
self.chat_history = ()
immediate = ChatPromptTemplate.from_template(USER_SYSTEM_PROMPT2)
self.chain = immediate | llm
def set_graph(self, graph):
self.graph = graph
def send_text(self,textual content:str, debug = False):
message = ChatMessage(message = HumanMessage(content material=textual content), sender = self.userid)
inputs = {"messages": (message)}
output = self.graph.invoke(inputs, debug = debug)
return output
def display_chat_history(self, content_only = False):
for i in self.chat_history:
if content_only == True:
print(f"{i.sender} : {i.content material}")
else:
print(i)
def invoke(self, message:BaseMessage) -> AIMessage:
output = self.chain.invoke({'message':message.content material, 'user_language':self.user_language})
return output
Die Implementierung von UserAgent besteht größtenteils aus standardmäßigem LangChain/LangGraph-Code:
- Definieren Sie eine LangChain-Kette (eine Eingabeaufforderungsvorlage + LLM), die für die eigentliche Übersetzung verantwortlich ist.
- Definieren Sie eine send_text-Funktion, die verwendet wird, um den Graphen aufzurufen, wenn ein Benutzer eine neue Nachricht senden möchte
Die Leistung dieses Agenten hängt größtenteils von der Übersetzungsqualität des LLM ab, da die Übersetzung das Hauptziel dieses Agenten ist. Und die LLM-Leistung kann bei der Übersetzung erheblich variieren, insbesondere abhängig von den beteiligten Sprachen. Bestimmte ressourcenarme Sprachen sind in den Trainingsdaten einiger Modelle nicht intestine dargestellt, was sich auf die Übersetzungsqualität dieser Sprachen auswirkt.
Aya-Agenten
Für Aya haben wir tatsächlich ein System von separaten Agenten, die alle zum Gesamtassistenten beitragen. Konkret haben wir
- AyaSupervisor: Kontrollagent, der den Betrieb der anderen Aya-Agenten überwacht.
- AyaQuery: Agent zum Ausführen von RAG-basierten Fragenbeantwortungen
- AyaSummarizer: Agent zum Generieren von Chat-Zusammenfassungen und Durchführen der Aufgabenidentifizierung
- AyaTranslator: Agent zum Übersetzen von Nachrichten ins Englische
class AyaTranslator(object):def __init__(self, llm) -> None:
self.llm = llm
immediate = ChatPromptTemplate.from_template(AYA_TRANSLATE_PROMPT)
self.chain = immediate | llm
def invoke (self, message: str) -> AIMessage:
output = self.chain.invoke({'message':message})
return output
class AyaQuery(object):
def __init__(self, llm, retailer, retriever) -> None:
self.llm = llm
self.retriever = retriever
self.retailer = retailer
qa_prompt = ChatPromptTemplate.from_template(AYA_AGENT_PROMPT)
self.chain = qa_prompt | llm
def invoke(self, query : str) -> AIMessage:
context = format_docs(self.retriever.invoke(query))
rag_output = self.chain.invoke({'query':query, 'context':context})
return rag_output
class AyaSupervisor(object):
def __init__(self, llm):
immediate = ChatPromptTemplate.from_template(AYA_SUPERVISOR_PROMPT)
self.chain = immediate | llm
def invoke(self, message : str) -> str:
output = self.chain.invoke(message)
return output.content material
class AyaSummarizer(object):
def __init__(self, llm):
message_length_prompt = ChatPromptTemplate.from_template(AYA_SUMMARIZE_LENGTH_PROMPT)
self.length_chain = message_length_prompt | llm
immediate = ChatPromptTemplate.from_template(AYA_SUMMARIZER_PROMPT)
self.chain = immediate | llm
def invoke(self, message : str, agent : UserAgent) -> str:
size = self.length_chain.invoke(message)
strive:
size = int(size.content material.strip())
besides:
size = 0
chat_history = agent.chat_history
if size == 0:
messages_to_summarize = (chat_history(i).content material for i in vary(len(chat_history)))
else:
messages_to_summarize = (chat_history(i).content material for i in vary(min(len(chat_history), size)))
print(size)
print(messages_to_summarize)
messages_to_summarize = "n ".be a part of(messages_to_summarize)
output = self.chain.invoke(messages_to_summarize)
output_content = output.content material
print(output_content)
return output_content
Die meisten dieser Agenten haben eine ähnliche Struktur und bestehen hauptsächlich aus einer LangChain-Kette, die aus einer benutzerdefinierten Eingabeaufforderung und einem LLM besteht. Ausnahmen sind der AyaQuery-Agent, der über einen zusätzlichen Vektordatenbank-Retriever zur Implementierung von RAG verfügt, und AyaSummarizer, in dem mehrere LLM-Funktionen implementiert sind.
Überlegungen zum Entwurf
Rolle des AyaSupervisor-Agenten: Beim Entwurf des Diagramms hatten wir eine feste Kante, die vom Supervisor-Knoten zu den Benutzerknoten führte. Das bedeutete, dass alle Nachrichten, die den Supervisor-Knoten erreichten, an die Benutzerknoten selbst weitergeleitet wurden. In Fällen, in denen Aya angesprochen wurde, Wir mussten sicherstellen, dass nur eine einzige endgültige Ausgabe von Aya an die Benutzer gesendet wurde. Wir wollten nicht, dass Zwischennachrichten, falls überhaupt, die Benutzer erreichen. Daher hatten wir den AyaSupervisor-Agenten, der als einziger Kontaktpunkt für den Aya-Agenten fungierte. Dieser Agent warfare hauptsächlich dafür verantwortlich, die Absicht der eingehenden Nachricht zu interpretieren, die Nachricht an den entsprechenden aufgabenspezifischen Agenten weiterzuleiten und dann die endgültige Nachricht auszugeben, die mit den Benutzern geteilt werden sollte.
Design von AyaSummarizer: Der AyaSummarizer-Agent ist im Vergleich zu den anderen Aya-Agenten etwas komplexer, da er einen zweistufigen Prozess durchführt. Im ersten Schritt ermittelt der Agent zunächst die Anzahl der Nachrichten, die zusammengefasst werden müssen. Dabei handelt es sich um einen LLM-Aufruf mit eigener Eingabeaufforderung. Sobald wir im zweiten Schritt die Anzahl der zusammenzufassenden Nachrichten kennen, sammeln wir die erforderlichen Nachrichten und übergeben sie an den LLM, um die eigentliche Zusammenfassung zu erstellen. Zusätzlich zur Zusammenfassung identifiziert der LLM in diesem Schritt selbst auch alle in den Nachrichten enthaltenen Aktionselemente und listet sie separat auf.
Im Großen und Ganzen gab es additionally drei Aufgaben: die Länge der zusammenzufassenden Nachrichten bestimmen, Nachrichten zusammenfassen, Aktionspunkte identifizieren. Da sich die erste Aufgabe für das LLM ohne explizite Beispiele jedoch als etwas schwierig erwies, entschied ich mich dafür, dies als separaten LLM-Aufruf zu machen und die beiden letzten Aufgaben dann als eigenen LLM-Aufruf zu kombinieren.
Möglicherweise ist es möglich, den zusätzlichen LLM-Anruf zu eliminieren und alle drei Aufgaben in einem Anruf zu kombinieren. Mögliche Optionen sind:
- Bereitstellung sehr detaillierter Beispiele, die alle drei Aufgaben in einem Schritt abdecken
- Generierung vieler Beispiele, um ein LLM tatsächlich zu optimieren und diese Aufgabe intestine erfüllen zu können
Rolle von AyaTranslator: Eines der Ziele in Bezug auf Aya warfare es, es zu einem mehrsprachigen KI-Assistenten zu machen, der in der bevorzugten Sprache des Benutzers kommunizieren kann. Es wäre jedoch schwierig, intern innerhalb der Aya-Agenten verschiedene Sprachen zu handhaben. Insbesondere wenn die Eingabeaufforderung der Aya-Agenten auf Englisch und die Benutzernachricht in einer anderen Sprache ist, könnte dies möglicherweise zu Problemen führen. Um solche Situationen zu vermeiden, sollten Sie als Filterschritt Folgendes tun: Wir haben alle eingehenden Benutzernachrichten an Aya ins Englische übersetzt. Infolgedessen wurde die gesamte interne Arbeit innerhalb der Aya-Agentengruppe auf Englisch erledigt, einschließlich der Ausgabe. Wir mussten die Aya-Ausgabe nicht wieder in die Originalsprache übersetzen, denn wenn die Nachricht die Benutzer erreicht, kümmern sich die Benutzeragenten um die Übersetzung der Nachricht in ihre jeweils zugewiesene Sprache.