Uma estrutura multiagente dinâmica simples baseada em agentes atômicos e instrutor. Usa o poder do Pydantic para validação e serialização de dados e esquemas.
compor Agentes feitos de um prompt do sistema, com uma linguagem compartilhada de Chamadas de Função ou então mutações GraphQL
um roteador usa um LLM para processar prompts de usuário 'compostos' complexos e encaminhá-los automaticamente para a melhor sequência de seus agentes
gerar via OpenAI ou AWS Bedrock ou groq
nota: o !! framework is at an early stage !!
- alterações importantes serão indicadas pelo aumento da versão secundária (a maior ainda está em zero).
Uma estrutura de agentes baseada em LLM usando uma abordagem de programação orientada a agentes para orquestrar agentes usando uma linguagem compartilhada.
A linguagem do agente pode ser baseada em chamada de função ou em GraphQL .
A estrutura é genérica e permite que os agentes sejam definidos em termos de nome, descrição, chamadas de entrada aceitas e chamadas de saída permitidas.
Os agentes se comunicam indiretamente por meio de um quadro negro. A linguagem é composta por chamadas (de função ou mutação GraphQL): cada agente especifica o que entende como entrada e quais chamadas ele é capaz de gerar. Desta forma, os agentes podem compreender a produção uns dos outros.
Um roteador recebe o prompt do usuário e gera um plano de execução do agente.
O plano de execução utiliza a melhor sequência dos agentes mais adequados para lidar com o prompt do usuário.
O roteador reescreve o prompt do usuário para se adequar a cada agente, o que melhora a qualidade e evita saídas indesejadas.
observação: Opcionalmente, o roteador pode ser executado separadamente, permitindo feedback humano no circuito sobre o plano de execução gerado pelo roteador. Desta forma, o usuário pode colaborar mais com o roteador, antes que os agentes generativos sejam realmente executados.
Finalmente, a saída é retornada na forma de uma lista ordenada de chamadas (Function ou GraphQL).
Para ler mais sobre essa abordagem, você pode ver este artigo do Medium.
framework is at an early stage
. O Avaliador não está implementado atualmente. Ao integrar, dependendo do tipo de Definições de Agente utilizadas, o cliente precisa:
Este é um construtor de mundo de demonstração 'Sim Life'. Ele usa 3 agentes (Creature Creature, Vegetation Creator, Relationship Creator) para processar as solicitações do usuário. Os agentes são definidos em termos de funções. A saída é uma série de chamadas de função que podem ser implementadas pelo cliente, para construir o mundo Sim Life.
A função AddCreature:
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 ),
]
)
A função AddCreatureRelationship:
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" ],
),
],
)
O agente Creature Creator é definido declarativamente em termos de:
Os agentes podem colaborar e trocar informações indiretamente, reutilizando as mesmas definições de função através de um quadro negro.
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
Notas sobre o agente Creature Creator:
function_add_relationship
. Veja o código-fonte de exemplo para obter mais detalhes. Este é um construtor de mundo de demonstração 'Sim Life'. Ele usa 3 agentes (Creature Creature, Vegetation Creator, Relationship Creator) para processar as solicitações do usuário. Os agentes são definidos declarativamente em termos do esquema de entrada GraphQL e permitem mutações geradas. A saída é uma série de mutações GraphQL que podem ser executadas pelo cliente, para construir o mundo Sim Life.
O esquema GraphQL:
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 !
}
...
As mutações GraphQL que queremos que os Agentes gerem são distintas para cada agente:
Agente criador de criaturas:
type Mutation {
addCreature ( input : CreatureInput ! ): Creature !
}
input CreatureInput {
creature_name : String !
allowed_terrain : TerrainType !
age : Int !
icon_name : IconType !
}
Agente Criador de Vegetação:
type Mutation {
addVegetation ( input : VegetationInput ! ): Vegetation !
}
input VegetationInput {
vegetation_name : String !
icon_name : IconType !
allowed_terrain : TerrainType !
}
O agente Creature Creator é definido declarativamente em termos de:
Um agente é basicamente uma composição de esquemas de entrada e saída, juntamente com um prompt.
Os agentes colaboram e trocam informações indiretamente por meio de um quadro negro, reutilizando os mesmos esquemas GraphQL e chamadas de mutação.
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
Notas sobre este agente:
creature_mutations_graphql
do arquivo "creature.mutations.graphql".creature_mutations_graphql
).creatures_graphql
do arquivo "creature.graphql".Os agentes podem ser usados juntos para formar um chatbot:
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 )
nota: se
given_user_prompt
não estiver definido, entãorun_chat_loop()
aguardará a entrada do usuário no teclado
Veja o código-fonte de exemplo para obter mais detalhes.
ENTRADA DO USUÁRIO:
Add a sheep that eats grass
SAÍDA:
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 )
Como a estrutura possui um roteador dinâmico, ela pode lidar com prompts 'compostos' mais complexos, como:
Adicione uma vaca que come grama. Adicione um humano – a vaca alimenta o humano. Adicione um alienígena que come o humano. O humano também come vacas.
O roteador descobre quais agentes usar, em que ordem executá-los e qual prompt enviar para cada agente.
Opcionalmente, o roteador pode ser reexecutado com feedback do usuário sobre seu plano gerado, antes de realmente executar os agentes.
Os agentes recomendados são então executados em ordem, construindo seus resultados no quadro compartilhado.
Finalmente, a estrutura combina as chamadas resultantes e as retorna ao cliente.
ENTRADA DO USUÁRIO:
Add a sheep that eats grass
SAÍDA:
['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', ' }', '}']
Instale Python 3.11 e poesia
Instale dependências.
poetry install
Para OpenAI:
export OPENAI_API_KEY="xxx"
Adicione isso ao seu script de inicialização do shell ( ~/.zprofile
ou similar)
Carregar no terminal atual:
source ~/.zprofile
Roteiro de teste:
./test.sh
Veja o código-fonte de exemplo para obter mais detalhes.