Ein einfaches dynamisches Multi-Agent-Framework basierend auf Atomic-Agents und Instructor. Nutzt die Leistungsfähigkeit von Pydantic zur Daten- und Schemavalidierung und Serialisierung.
Erstellen Sie Agenten aus einer Systemeingabeaufforderung mit einer gemeinsamen Sprache aus Funktionsaufrufen oder GraphQL-Mutationen
Ein Router verwendet ein LLM, um komplexe „zusammengesetzte“ Benutzeraufforderungen zu verarbeiten und sie automatisch an die beste Reihenfolge Ihrer Agenten weiterzuleiten
Generieren über OpenAI oder AWS Bedrock oder groq
Hinweis: das !! framework is at an early stage !!
- Breaking Changes werden durch Erhöhen der Nebenversion angezeigt (die Hauptversion steht immer noch auf Null).
Ein LLM-basiertes Agenten-Framework, das einen agentenorientierten Programmieransatz verwendet, um Agenten mithilfe einer gemeinsamen Sprache zu orchestrieren.
Die Agentensprache kann entweder auf Funktionsaufrufen oder auf GraphQL basieren.
Das Framework ist generisch und ermöglicht die Definition von Agenten anhand eines Namens, einer Beschreibung, akzeptierter Eingabeaufrufe und zulässiger Ausgabeaufrufe.
Die Agenten kommunizieren indirekt über eine Tafel. Die Sprache besteht aus (Funktions- oder GraphQL-Mutations-)Aufrufen: Jeder Agent gibt an, was er als Eingabe versteht und welche Aufrufe er generieren kann. Auf diese Weise können die Agenten die Ergebnisse des anderen verstehen.
Ein Router nimmt die Benutzeraufforderung entgegen und generiert einen Agentenausführungsplan.
Der Ausführungsplan verwendet die beste Reihenfolge der am besten geeigneten Agenten, um die Benutzeraufforderung zu verarbeiten.
Der Router schreibt die Benutzeraufforderung passend für jeden Agenten neu, was die Qualität verbessert und unerwünschte Ausgaben vermeidet.
Hinweis: Optional kann der Router separat ausgeführt werden, sodass ein Human-in-the-Loop-Feedback zum vom Router generierten Ausführungsplan möglich ist. Auf diese Weise kann der Benutzer stärker mit dem Router zusammenarbeiten, bevor die generativen Agenten tatsächlich ausgeführt werden.
Schließlich wird die Ausgabe in Form einer geordneten Liste von (Funktions- oder GraphQL-)Aufrufen zurückgegeben.
Weitere Informationen zu diesem Ansatz finden Sie in diesem Medium-Artikel.
framework is at an early stage
. Der Evaluator ist derzeit nicht implementiert. Bei der Integration muss der Client je nach Art der verwendeten Agentendefinitionen Folgendes tun:
Dies ist ein Demo-World-Builder „Sim Life“. Es verwendet 3 Agenten (Creature Creature, Vegetation Creator, Relationship Creator), um Benutzereingaben zu verarbeiten. Die Agenten werden funktionsmäßig definiert. Die Ausgabe ist eine Reihe von Funktionsaufrufen, die vom Client implementiert werden können, um die Sim Life-Welt aufzubauen.
Die AddCreature-Funktion:
function_add_creature = FunctionSpecSchema (
agent_name = creature_agent_name ,
function_name = "AddCreature" ,
description = "Adds a new creature to the world (not vegetation)" ,
parameters = [
ParameterSpec ( name = "creature_name" , type = ParameterType . string ),
ParameterSpec ( name = "allowed_terrain" , type = ParameterType . string , allowed_values = terrain_types ),
ParameterSpec ( name = "age" , type = ParameterType . int ),
ParameterSpec ( name = "icon_name" , type = ParameterType . string , allowed_values = creature_icons ),
]
)
Die AddCreatureRelationship-Funktion:
function_add_relationship = FunctionSpecSchema (
agent_name = relationship_agent_name ,
function_name = "AddCreatureRelationship" ,
description = "Adds a new relationship between two creatures" ,
parameters = [
ParameterSpec (
name = "from_name" , type = ParameterType . string
),
ParameterSpec (
name = "to_name" , type = ParameterType . string
),
ParameterSpec (
name = "relationship_name" ,
type = ParameterType . string ,
allowed_values = [ "eats" , "buys" , "feeds" , "sells" ],
),
],
)
Der Creature Creator-Agent wird deklarativ wie folgt definiert:
Agenten können indirekt zusammenarbeiten und Informationen austauschen, indem sie dieselben Funktionsdefinitionen über ein Blackboard wiederverwenden.
def build_creature_agent ():
agent_definition = FunctionAgentDefinition (
agent_name = "Creature Creator" ,
description = "Creates new creatures given the user prompt. Ensures that ALL creatures mentioned by the user are created." ,
accepted_functions = [ function_add_creature , function_add_relationship ],
input_schema = FunctionAgentInputSchema ,
initial_input = FunctionAgentInputSchema (
functions_allowed_to_generate = [ function_add_creature ],
previously_generated_functions = []
),
output_schema = FunctionAgentOutputSchema ,
topics = [ "creature" ]
)
return agent_definition
Hinweise zum Creature Creator-Agenten:
function_add_relationship
definierte Funktion „AddRelationship“. Weitere Einzelheiten finden Sie im Beispielquellcode. Dies ist ein Demo-World-Builder „Sim Life“. Es verwendet 3 Agenten (Creature Creature, Vegetation Creator, Relationship Creator), um Benutzereingaben zu verarbeiten. Die Agenten werden deklarativ im Sinne des GraphQL-Eingabeschemas definiert und erlauben generierte Mutationen. Das Ergebnis ist eine Reihe von GraphQL-Mutationen, die vom Client ausgeführt werden können, um die Sim Life-Welt aufzubauen.
Das GraphQL-Schema:
type Creature {
id : ID !
creature_name : String !
allowed_terrain : TerrainType !
age : Int !
icon_name : IconType !
}
type Vegetation {
id : ID !
vegetation_name : String !
icon_name : IconType !
allowed_terrain : TerrainType !
}
type Relationship {
id : ID !
from_name : String !
to_name : String !
relationship_kind : RelationshipType !
}
...
Die GraphQL-Mutationen, die die Agenten generieren sollen, sind für jeden Agenten unterschiedlich:
Creature Creator-Agent:
type Mutation {
addCreature ( input : CreatureInput ! ): Creature !
}
input CreatureInput {
creature_name : String !
allowed_terrain : TerrainType !
age : Int !
icon_name : IconType !
}
Vegetation Creator-Agent:
type Mutation {
addVegetation ( input : VegetationInput ! ): Vegetation !
}
input VegetationInput {
vegetation_name : String !
icon_name : IconType !
allowed_terrain : TerrainType !
}
Der Creature Creator-Agent wird deklarativ wie folgt definiert:
Ein Agent ist im Grunde eine Zusammenstellung von Eingabe- und Ausgabeschemata sowie einer Eingabeaufforderung.
Agenten arbeiten zusammen und tauschen Informationen indirekt über ein Blackboard aus, indem sie dieselben GraphQL-Schemata und Mutationsaufrufe wiederverwenden.
creatures_graphql = _read_schema ( "creature.graphql" )
creature_mutations_graphql = _read_schema ( "creature.mutations.graphql" )
def build_creature_agent ():
agent_definition = GraphQLAgentDefinition (
agent_name = "Creature Creator" ,
description = "Creates new creatures given the user prompt. Ensures that ALL creatures mentioned by the user are created." ,
accepted_graphql_schemas = [ creatures_graphql , creature_mutations_graphql ],
input_schema = GraphQLAgentInputSchema ,
initial_input = GraphQLAgentInputSchema (
mutations_allowed_to_generate = [ creature_mutations_graphql ],
previously_generated_mutations = []
),
output_schema = GraphQLAgentOutputSchema ,
topics = [ "creature" ]
)
return agent_definition
Hinweise zu diesem Agenten:
creature_mutations_graphql
aus der Datei „creature.mutations.graphql“ definiert sind.creature_mutations_graphql
).creatures_graphql
aus der Datei „creature.graphql“ definiert wird.Die Agenten können zusammen verwendet werden, um einen Chatbot zu bilden:
from gpt_multi_atomic_agents import functions_expert_service , config
from . import agents
def run_chat_loop ( given_user_prompt : str | None = None ) -> list :
CHAT_AGENT_DESCRIPTION = "Handles users questions about an ecosystem game like Sim Life"
agent_definitions = [
build_creature_agent (), build_relationship_agent (), build_vegatation_agent () # for more capabilities, add more agents here
]
_config = config . Config (
ai_platform = config . AI_PLATFORM_Enum . bedrock_anthropic ,
model = config . ANTHROPIC_MODEL ,
max_tokens = config . ANTHROPIC_MAX_TOKENS ,
is_debug = False
)
return functions_expert_service . run_chat_loop ( agent_definitions = agent_definitions , chat_agent_description = CHAT_AGENT_DESCRIPTION , _config = _config , given_user_prompt = given_user_prompt )
Hinweis: Wenn
given_user_prompt
nicht gesetzt ist, wartetrun_chat_loop()
auf Benutzereingaben über die Tastatur
Weitere Einzelheiten finden Sie im Beispielquellcode.
BENUTZEREINGABE:
Add a sheep that eats grass
AUSGABE:
Generated 3 function calls
[Agent: Creature Creator] AddCreature( creature_name=sheep, icon_name=sheep-icon, land_type=prairie, age=1 )
[Agent: Plant Creator] AddPlant( plant_name=grass, icon_name=grass-icon, land_type=prairie )
[Agent: Relationship Creator] AddCreatureRelationship( from_name=sheep, to_name=grass, relationship_name=eats )
Da das Framework über einen dynamischen Router verfügt, kann es komplexere „zusammengesetzte“ Eingabeaufforderungen verarbeiten, wie zum Beispiel:
Fügen Sie eine Kuh hinzu, die Gras frisst. Fügen Sie einen Menschen hinzu – die Kuh füttert den Menschen. Add und Alien, das den Menschen frisst. Der Mensch isst auch Kühe.
Der Router ermittelt, welche Agenten verwendet werden sollen, in welcher Reihenfolge sie ausgeführt werden und welche Aufforderung an jeden Agenten gesendet werden soll.
Optional kann der Router mit Benutzerfeedback zu seinem generierten Plan erneut ausgeführt werden, bevor die Agenten tatsächlich ausgeführt werden.
Die empfohlenen Agenten werden dann der Reihe nach ausgeführt und ihre Ergebnisse im gemeinsamen Blackboard zusammengestellt.
Schließlich kombiniert das Framework die resultierenden Aufrufe und gibt sie an den Client zurück.
BENUTZEREINGABE:
Add a sheep that eats grass
AUSGABE:
['mutation {n addCreature(input: {n creature_name: "sheep",n allowed_terrain: GRASSLAND,n age: 2,n icon_name: SHEEPn }) {n creature_namen allowed_terrainn agen icon_namen }n }']
['mutation {', ' addVegetation(input: {', ' vegetation_name: "Grass",', ' icon_name: GRASS,', ' allowed_terrain: LAND', ' }) {', ' vegetation_name', ' icon_name', ' allowed_terrain', ' }', '}']
['mutation {', ' addCreatureRelationship(input: {', ' from_name: "Sheep",', ' to_name: "Grass",', ' relationship_kind: EATS', ' }) {', ' id', ' }', '}']
Installieren Sie Python 3.11 und Poesie
Abhängigkeiten installieren.
poetry install
Für OpenAI:
export OPENAI_API_KEY="xxx"
Fügen Sie das Ihrem Shell-Initialisierungsskript hinzu ( ~/.zprofile
oder ähnlich)
Im aktuellen Terminal laden:
source ~/.zprofile
Testskript:
./test.sh
Weitere Einzelheiten finden Sie im Beispielquellcode.