Instale a versão mais recente com:
pip install operagents
# or use poetry
poetry add operagents
# or use pdm
pdm add operagents
# or use uv
uv pip install operagentsUm agente é um modelo humano ou um idioma que pode atuar como caracteres e usar adereços nas cenas da ópera. O agente pode se comunicar com os outros observando e agindo. Todo agente possui um back-end (por exemplo, usuário, API OpenAI) para gerar a resposta e a própria memória para armazenar as informações de longo prazo / curto prazo.
Uma cena faz parte da ópera que contém vários caracteres. Cada cena tem um fluxo e um diretor para controlar todo o processo de sessão. A cena também pode ter uma seção de preparação para fazer algum trabalho de inicialização antes do início da cena.
Um personagem é um papel na cena. Todo personagem tem um nome, uma descrição e uma lista de adereços. Quando a cena começa, um agente atua como personagem e se comunica com os outros.
O fluxo é usado para controlar a ordem da atuação dos personagens em cena.
O diretor é usado para decidir se deve encerrar a cena atual e qual cena jogar a seguir.
Um suporte é uma ferramenta que pode ser usada pelos agentes para melhorar sua atuação. Os agentes podem obter informações externas usando adereços.
A linha do tempo é o componente principal de tempo de execução da ópera para gerenciar o processo de sessão. Ele executa a sessão atual e alterna entre as sessões. A linha do tempo também registra as informações globais da ópera e pode ser compartilhada por todos os agentes.
Uma sessão indica uma única corrida da cena. Ele contém um identificador único e sua cena correspondente.
A maneira comum de usar operigentes é gravar um arquivo de configuração e executar a ópera com a ferramenta de linha de comando operagents .
Crie um arquivo config.yaml com o seguinte conteúdo básico:
# yaml-language-server: $schema=https://operagents.yyydl.top/schemas/config.schema.json
agents :
opening_scene : " "
scenes : A primeira linha é um comentário que informa ao servidor de idiomas YAML para usar o esquema a partir do URL especificado. Isso permitirá a conclusão automática e a validação em seu editor.
O esquema está relacionado à versão da estrutura de operagentes que você está usando. O URL está no formato https://operagents.yyydl.top/schemas/config-<version>.schema.json <version>.schema.json, onde <version> é a versão da estrutura, por exemplo, 0.0.1 . Se nenhuma versão for especificada, a versão mais recente (mestre) será usada.
Antes de escrever as configurações do agente e da cena, precisamos aprender sobre a configuração do modelo.
Operagentes usa modelos para gerar a entrada de contexto para o modelo de idioma. Um modelo é uma string no formato Jinja. Você pode usar a sintaxe Jinja2 com variáveis de contexto fornecidos para controlar a entrada para o modelo de idioma.
Uma configuração de modelo pode estar no seguinte formato:
Modelo de string simples
user_template : |-
{# some jinja template #}modelo com funções personalizadas
user_template :
content : |-
{# some jinja template #}
custom_functions :
function_name : module_name:function_name Se você deseja usar funções personalizadas no modelo, precisará fornecer a tecla custom_functions , que é um dicionário de nomes de funções personalizadas e seus caminhos de módulo correspondentes no formato de notação de pontos.
A seção de agents é um dicionário de agentes, onde a chave é o nome do agente e o valor é a configuração do agente.
Os agentes precisam atuar como personagem nas cenas e responder às mensagens de outras pessoas. Portanto, a primeira parte da configuração do agente é a configuração de back -end, usada para se comunicar com o modelo ou usuário de idioma. Você pode usar a tecla backend para especificar o tipo de back -end e sua configuração.
agents :
Mike :
backend :
# user as the backend (a.k.a human-agent)
type : user
John :
backend :
# openai api as the backend
type : openai
model : gpt-3.5-turbo
temperature : 0.5
api_key :
base_url :
max_retries : 2
tool_choice :
type : auto
prop_validation_error_template : |-
{# some jinja template #} Você também pode personalizar o back -end, fornecendo um caminho de objeto da classe de back -end personalizada que implementa a classe abstrata Backend .:
agents :
Mike :
backend :
type : custom
path : module_name:CustomBackend
custom_config : value # module_name.py
from typing import Self
from operagents . prop import Prop
from operagents . timeline import Timeline
from operagents . config import CustomBackendConfig
from operagents . backend import Backend , Message , GenerateResponse , GeneratePropUsage
class CustomBackend ( Backend ):
@ classmethod
def from_config ( cls , config : CustomBackendConfig ) -> Self :
return cls ()
@ overload
async def generate (
self ,
timeline : Timeline ,
messages : list [ Message ],
props : None = None ,
) -> AsyncGenerator [ GenerateResponse , None ]: ...
@ overload
async def generate (
self ,
timeline : Timeline ,
messages : list [ Message ],
props : list [ Prop ],
) -> AsyncGenerator [ GenerateResponse | GeneratePropUsage , None ]: ...
async def generate (
self , timeline : Timeline , messages : list [ Message ], props : list [ Prop ] | None = None
) -> AsyncGenerator [ GenerateResponse | GeneratePropUsage , None ]:
yield GenerateResponse ( content = "" ) A próxima parte da configuração do agente é o modelo do sistema/usuário usado para gerar a entrada de contexto para o modelo de idioma. Você pode usar a tecla system_template / user_template para especificar o modelo do sistema / usuário. Aqui está um exemplo da configuração do modelo:
agents :
John :
system_template : |-
Your name is {{ agent.name }}.
Current scene is {{ timeline.current_scene.name }}.
{% if timeline.current_scene.description -%}
{{ timeline.current_scene.description }}
{%- endif -%}
You are acting as {{ timeline.current_character.name }}.
{% if timeline.current_character.description -%}
{{ timeline.current_character.description }}
{%- endif -%}
Please continue the conversation on behalf of {{ agent.name }}({{ timeline.current_character.name }}) based on your known information and make your answer appear as natural and coherent as possible.
Please answer directly what you want to say and keep your reply as concise as possible.
user_template : |-
{% for event in timeline.past_events(agent) -%}
{% if event.type_ == "session_act" -%}
{{ event.character.agent_name }}({{ event.character.name }}): {{ event.content }}
{%- endif %}
{%- endfor %} Outra parte da configuração do agente é o sistema de resumo da sessão/modelo de usuário, usado para gerar o resumo da sessão da cena. Você pode usar a tecla session_summary_system_template / session_summary_user_template para especificar o sistema de resumo da sessão / modelo de usuário. Aqui está um exemplo da configuração do modelo:
agents :
John :
session_summary_system_template : |-
Your name is {{ agent.name }}.
Your task is to summarize the historical dialogue records according to the current scene, and summarize the most important information.
session_summary_user_template : |-
{% for event in agent.memory.get_memory_for_session(session_id) -%}
{% if event.type_ == "observe" -%}
{{ event.content }}
{%- elif event.type_ == "act" -%}
{{ agent.name }}({{ event.character.name }}): {{ event.content }}
{%- endif %}
{%- endfor %}
{% for event in timeline.session_past_events(agent, session_id) -%}
{% if event.type_ == "session_act" -%}
{{ event.character.agent_name }}({{ event.character.name }}): {{ event.content }}
{%- endif %}
{%- endfor %} A chave opening_scene é usada para especificar a cena inicial da ópera. O valor é o nome da cena de abertura.
opening_scene : " Introduction " A seção scenes é um dicionário de cenas, onde a chave é o nome da cena e o valor é a configuração da cena.
A ópera é composta por várias cenas e cada cena tem vários caracteres. Você primeiro precisa definir o nome, descrição (opcional) e caracteres da cena.
scenes :
talking :
description : " The scene is about two people talking. "
characters :
user :
agent_name : " Mike "
ai assistant :
agent_name : " John "
description : |-
You are a helpful assistant.
props : [] Os caracteres na cena devem definir a tecla agent_name , que é o nome do agente que atua como o personagem. A chave description (opcional) pode ser usada para descrever o caractere no modelo do agente. A chave props (opcional) pode ser usada para definir os adereços do caractere, consulte a configuração do suporte para obter mais detalhes.
O Flow da cena foi projetado para controlar a ordem da atuação dos personagens. Você pode especificar o tipo e os parâmetros do Flow .
Tipo de order
O tipo order é usado para predefinir a ordem da atuação dos personagens. Os personagens percorrerão a lista de pedidos até que a cena termine.
scenes :
talking :
flow :
type : order
order :
- user
- ai assistant Tipo de model
O tipo model é usado para especificar o modelo para prever o próximo caractere para agir. O modelo preverá o próximo caractere com base no contexto atual.
scenes :
talking :
flow :
type : model
backend :
type : openai
model : gpt-3.5-turbo
temperature : 0.5
system_template : " "
user_template : " "
allowed_characters : # optional, the characters allowed to act
- user
- ai assistant
begin_character : user # optional, the first character to act
fallback_character : ai assistant # optional, the fallback character when the model fails to predict tipo de user
O tipo user permite que o ser humano escolha o próximo personagem para agir.
scenes :
talking :
flow :
type : user Tipo custom
O tipo custom permite definir uma classe de fluxo personalizada para controlar a ordem da atuação dos caracteres.
scenes :
talking :
flow :
type : custom
path : module_name:CustomFlow
custom_config : value # module_name.py
from typing import Self
from operagents . flow import Flow
from operagents . timeline import Timeline
from operagents . character import Character
from operagents . config import CustomFlowConfig
class CustomFlow ( Flow ):
@ classmethod
def from_config ( cls , config : CustomFlowConfig ) -> Self :
return cls ()
async def begin ( self , timeline : Timeline ) -> Character :
return ""
async def next ( self , timeline : Timeline ) -> Character :
return "" O Director da cena é usado para controlar a próxima cena para jogar. Você pode especificar o tipo e os parâmetros do diretor.
Tipo de model
O tipo model é usado para especificar o modelo para prever a próxima cena a ser reproduzida. Se nenhuma bandeira de acabamento foi encontrada ou nenhum nome de cena encontrado, a cena da Curent continuará jogando.
scenes :
talking :
director :
type : model
backend :
type : openai
model : gpt-3.5-turbo
temperature : 0.5
system_template : " "
user_template : " "
allowed_scenes : # optional, the next scenes allowed to play
- walking
- running
finish_flag : " finish " # optional, the finish flag to end the opera tipo de user
O tipo user permite que o ser humano escolha a próxima cena para jogar.
scenes :
talking :
director :
type : user never digite
O diretor never termina a cena atual. Útil quando há uma única cena e você deseja encerrar a ópera por um Prop .
scenes :
talking :
director :
type : never Tipo custom
O tipo custom permite definir uma classe de diretor personalizado para controlar a próxima cena para jogar.
scenes :
talking :
director :
type : custom
path : module_name:CustomDirector
custom_config : value # module_name.py
from typing import Self
from operagents . scene import Scene
from operagents . director import Director
from operagents . timeline import Timeline
from operagents . config import CustomDirectorConfig
class CustomDirector ( Director ):
@ classmethod
def from_config ( cls , config : CustomDirectorConfig ) -> Self :
return cls ()
async def next_scene ( self , timeline : Timeline ) -> Scene | None :
return None A seção prepare da cena é usada para definir as etapas de preparação antes do início da cena. Você pode fazer algum trabalho de inicialização aqui.
Tipo de preface
Você pode fazer o personagem dizer algo antes do início da cena.
scenes :
talking :
prepare :
- type : preface
character_name : ai assistant
content : |-
Hello, I am John, your AI assistant. How can I help you today? Tipo function
O tipo function chamará a função personalizada antes do início da cena.
scenes :
talking :
prepare :
- type : function
function : module_name:function_name A função personalizada receberá um parâmetro do tipo operagents.timeline.Timeline .
# module_name.py
from operagents . timeline import Timeline
async def function_name ( timeline : Timeline ) -> None :
pass Tipo custom
O tipo custom chamará a classe de preparação personalizada antes do início da cena.
scenes :
talking :
prepare :
- type : custom
path : module_name:CustomPrepare
custom_config : value # module_name.py
from typing import Self
from operagents . timeline import Timeline
from operagents . scene . prepare import ScenePrepare
from operagents . config import CustomScenePrepareConfig
class CustomScenePrepare ( ScenePrepare ):
@ classmethod
def from_config ( cls , config : CustomScenePrepareConfig ) -> Self :
return cls ()
async def prepare ( self , timeline : Timeline ) -> None :
pass Os personagens da cena podem usar adereços para melhorar lá atuando. A seção props é uma lista de adereços, onde cada suporte é um dicionário com o tipo de suporte e a configuração do suporte.
function prop
O suporte function chamará a função personalizada quando o suporte for usado.
scenes :
talking :
characters :
ai assistant :
props :
- type : function
function : module_name:function_name
exception_template : |-
{# some jinja template #} A função personalizada não deve ter argumentos ou um argumento do tipo pydantic.BaseModel .
from pydantic import Field , BaseModel
from datetime import datetime , timezone
async def current_time () -> str :
"""Get the current real world time."""
return datetime . now ( timezone . utc ). astimezone (). isoformat ()
class Args ( BaseModel ):
name : str = Field ( description = "The name" )
async def greet ( args : Args ) -> str :
"""Greet the name."""
return f"Hello, { args . name } !" Observe que o nome e o docstring da função serão usados como o nome e a descrição do suporte. Você também pode fornecer a descrição dos Args pelo Field de Pydantic. O modelo de exceção será usado para renderizar a resposta quando a função levantar um erro.
Prop custom
O suporte custom chamará a classe de suporte personalizada quando o suporte for usado.
scenes :
talking :
characters :
ai assistant :
props :
- type : custom
path : module_name:CustomProp
custom_config : value # module_name.py
from typing import Any , Self
from pydantic import BaseModel
from operagents . prop import Prop
from operagents . config import CustomPropConfig
class CustomProp ( Prop ):
"""The description of the prop"""
params : BaseModel | None
"""The parameters of the prop"""
@ classmethod
def from_config ( cls , config : CustomPropConfig ) -> Self :
return cls ()
async def call ( self , params : BaseModel | None ) -> Any :
return "" Os ganchos permitem executar código personalizado quando ocorrem eventos específicos da linha do tempo. A seção hooks é uma lista de ganchos, onde cada gancho é um dicionário com o tipo de gancho e a configuração do gancho. Por padrão, as operigentes permitem o gancho summary , a menos que você altere a seção hooks .
summary do gancho
O gancho summary chamará os agentes para resumir a sessão quando a sessão terminar. Opcionalmente, você pode especificar os nomes dos agentes a serem resumidos.
hooks :
- type : summary
agent_names :
- Mike
- John gancho custom
O gancho custom invocará a aula de gancho personalizada quando os eventos específicos da linha do tempo encontrarem.
hooks :
- type : custom
path : module_name:CustomHook
custom_config : value # module_name.py
from typing import Self
from operagents . hook import Hook
from operagents . timeline import Timeline
from operagents . config import CustomHookConfig
from operagents . timeline . event import (
TimelineEventEnd ,
TimelineEventStart ,
TimelineEventSessionAct ,
TimelineEventSessionEnd ,
TimelineEventSessionStart ,
)
class CustomHook ( Hook ):
@ classmethod
def from_config ( cls , config : CustomHookConfig ) -> Self :
return cls ()
async def on_timeline_start (
self , timeline : Timeline , event : TimelineEventStart
):
"""Called when the timeline is started."""
pass
async def on_timeline_end (
self , timeline : Timeline , event : TimelineEventEnd
):
"""Called when the timeline is ended."""
pass
async def on_timeline_session_start (
self , timeline : Timeline , event : TimelineEventSessionStart
):
"""Called when a session is started."""
pass
async def on_timeline_session_end (
self , timeline : Timeline , event : TimelineEventSessionEnd
):
"""Called when a session is ended."""
pass
async def on_timeline_session_act (
self , timeline : Timeline , event : TimelineEventSessionAct
):
"""Called when a character acts in a session."""
pass A classe Hook pode contém métodos no formato de on_timeline_<event_type> , onde <event_type> é o tipo do evento da linha do tempo.
Operagents fornece uma ferramenta de linha de comando para executar facilmente a ópera. Você pode executar a ópera com o seguinte comando:
operagents run config.yaml Se você quiser ver os logs de depuração, pode definir a opção --log-level :
operagents run --log-level DEBUG config.yaml Mais comandos e opções podem ser encontrados através da execução operagents --help .
Se você deseja executar a ópera programaticamente, pode usar a função opera.run :
import asyncio
from pathlib import Path
import yaml
from operagents . opera import Opera
from operagents . log import setup_logging
from operagents . config import OperagentsConfig
async def main ():
# if you want to setup the default logging for operagents
setup_logging ( "INFO" )
# load the opera from config file
opera = Opera . from_config (
OperagentsConfig . model_validate (
yaml . safe_load ( Path ( "./config.yaml" ). read_text ( encoding = "utf-8" ))
)
)
finish_state = await opera . run ()
if __name__ == "__main__" :
asyncio . run ( main ()) cd examples/chatbot
env OPENAI_API_KEY=sk-xxx OPENAI_BASE_URL=https://api.openai.com/v1 operagents run --log-level DEBUG config.yamlAberto em codespaces (recipiente de dev):
Ou instale o ambiente de desenvolvimento localmente com:
poetry install && poetry run pre-commit install