Instale la última versión con:
pip install operagents
# or use poetry
poetry add operagents
# or use pdm
pdm add operagents
# or use uv
uv pip install operagentsUn agente es un modelo humano o de lenguaje que puede actuar como caracteres y usar accesorios en las escenas de ópera. El agente puede comunicarse con otros observando y actuando. Cada agente tiene un backend (por ejemplo, usuario, API de OpenAI) para generar la respuesta y la memoria propia para almacenar la información a largo plazo / a corto plazo.
Una escena es parte de la ópera que contiene varios personajes. Cada escena tiene un flujo y un director para controlar todo el proceso de la sesión. La escena también puede tener una sección de preparación para hacer un trabajo de inicialización antes de que comience la escena.
Un personaje es un papel en la escena. Cada personaje tiene un nombre, una descripción y una lista de accesorios. Cuando comience la escena, un agente actuará como el personaje y se comunicará con los demás.
El flujo se utiliza para controlar el orden de la actuación de los personajes en la escena.
El director se usa para decidir si terminar la escena actual y qué escena jugar a continuación.
Un accesorio es una herramienta que los agentes pueden utilizar para mejorar su actuación. Los agentes pueden obtener información externa utilizando accesorios.
La línea de tiempo es el principal componente de tiempo de ejecución de la ópera para administrar el proceso de sesión. Ejecuta la sesión actual y los interruptores entre sesiones. La línea de tiempo también registra la información global de la ópera y puede ser compartida por todos los agentes.
Una sesión indica una sola ejecución de la escena. Contiene un identificador único y su escena correspondiente.
La forma común de usar Operagents es escribir un archivo de configuración y ejecutar la ópera con la herramienta de línea de comandos operagents .
Cree un archivo config.yaml con el siguiente contenido básico:
# yaml-language-server: $schema=https://operagents.yyydl.top/schemas/config.schema.json
agents :
opening_scene : " "
scenes : La primera línea es un comentario que le dice al servidor de idiomas YAML que use el esquema de la URL especificada. Esto habilitará Autocompletación y validación en su editor.
El esquema está relacionado con la versión del marco de los operaciones que está utilizando. La URL está en formato https://operagents.yyydl.top/schemas/config-<version>.schema.json <version>.schema.json, donde <version> es la versión del marco, por ejemplo, 0.0.1 . Si no se especifica ninguna versión, se utilizará la última versión (maestra).
Antes de escribir las configuraciones del agente y la escena, necesitamos aprender sobre la configuración de la plantilla.
Operagents utiliza plantillas para generar la entrada de contexto para el modelo de lenguaje. Una plantilla es una cadena en formato Jinja. Puede usar la sintaxis Jinja2 con variables de contexto proporcionadas para controlar la entrada al modelo de lenguaje.
Una configuración de plantilla puede estar en el siguiente formato:
Plantilla de cadena simple
user_template : |-
{# some jinja template #}plantilla con funciones personalizadas
user_template :
content : |-
{# some jinja template #}
custom_functions :
function_name : module_name:function_name Si desea utilizar funciones personalizadas en la plantilla, debe proporcionar la tecla custom_functions , que es un diccionario de nombres de funciones personalizadas y sus rutas de módulo correspondientes en formato de notación DOT.
La sección de agents es un diccionario de agentes, donde la clave es el nombre del agente y el valor es la configuración del agente.
Los agentes deben actuar como personaje en las escenas y responder a los mensajes de los demás. Entonces, la primera parte de la configuración del agente es la configuración de backend, que se utiliza para comunicarse con el modelo de idioma o el usuario. Puede usar la tecla backend para especificar el tipo de backend y su configuración.
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 #} También puede personalizar el backend proporcionando una ruta de objetos de la clase de backend personalizada que implementa la clase abstracta 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 = "" ) La siguiente parte de la configuración del agente es la plantilla del sistema/usuario utilizada para generar la entrada de contexto para el modelo de idioma. Puede usar la tecla system_template / user_template para especificar la plantilla del sistema / usuario. Aquí hay un ejemplo de la configuración de la plantilla:
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 %} Otra parte de la configuración del agente es el sistema de resumen de la sesión/plantilla de usuario, que se utiliza para generar el resumen de la sesión de la escena. Puede usar la tecla session_summary_system_template / session_summary_user_template para especificar el sistema de resumen de sesión / plantilla de usuario. Aquí hay un ejemplo de la configuración de la plantilla:
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 %} La tecla opening_scene se usa para especificar la escena de inicio de la ópera. El valor es el nombre de la escena de apertura.
opening_scene : " Introduction " La sección scenes es un diccionario de escenas, donde la clave es el nombre de la escena y el valor es la configuración de la escena.
La ópera está compuesta de múltiples escenas, y cada escena tiene varios personajes. Primero debe definir el nombre, la descripción (opcional) y los personajes de la escena.
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 : [] Los personajes de la escena deben definir la tecla agent_name , que es el nombre del agente que actúa como el personaje. La clave description (opcional) se puede usar para describir el carácter en la plantilla de agente. La tecla props (opcional) se puede utilizar para definir los accesorios del carácter, consulte la configuración de PROP para obtener más detalles.
El Flow de la escena está diseñado para controlar el orden de la actuación de los personajes. Puede especificar el tipo y los parámetros del Flow .
tipo order
El tipo order se utiliza para predefinir el orden de la actuación de los caracteres. Los personajes recorrerán la lista de pedidos hasta que termine la escena.
scenes :
talking :
flow :
type : order
order :
- user
- ai assistant tipo model
El tipo model se utiliza para especificar el modelo para predecir el siguiente carácter a actuar. El modelo predecirá el siguiente carácter basado en el contexto actual.
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 user
El tipo user permite a los humanos elegir el siguiente personaje para actuar.
scenes :
talking :
flow :
type : user tipo custom
El tipo custom le permite definir una clase de flujo personalizado para controlar el orden de la actuación de los 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 "" El Director de la escena se usa para controlar la siguiente escena para jugar. Puede especificar el tipo y los parámetros del director.
tipo model
El tipo model se utiliza para especificar el modelo para predecir la siguiente escena a jugar. Si no se encontró una bandera de acabado o no se encuentra el nombre de la escena, la escena curente continuará jugando.
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 user
El tipo user permite a los humanos elegir la siguiente escena para reproducir.
scenes :
talking :
director :
type : user never escriba
El director never termina la escena actual. Útil cuando hay una sola escena y desea terminar la ópera por un Prop .
scenes :
talking :
director :
type : never tipo custom
El tipo custom le permite definir una clase de director personalizado para controlar la siguiente escena para reproducir.
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 La sección prepare de la escena se usa para definir los pasos de preparación antes de que comience la escena. Puede hacer un trabajo de inicialización aquí.
Tipo de preface
Puedes hacer que el personaje diga algo antes de que comience la escena.
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
El tipo function llamará a la función personalizada antes de que comience la escena.
scenes :
talking :
prepare :
- type : function
function : module_name:function_name La función personalizada recibirá un parámetro de tipo operagents.timeline.Timeline .
# module_name.py
from operagents . timeline import Timeline
async def function_name ( timeline : Timeline ) -> None :
pass tipo custom
El tipo custom llamará a la clase de preparación personalizada antes de que comience la escena.
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 Los personajes de la escena pueden usar accesorios para mejorar la actuación. La sección props es una lista de accesorios, donde cada accesorio es un diccionario con el tipo de proporción y la configuración de Prop.
function
El PROP function llamará a la función personalizada cuando se usa el Prop.
scenes :
talking :
characters :
ai assistant :
props :
- type : function
function : module_name:function_name
exception_template : |-
{# some jinja template #} La función personalizada no debe tener argumentos o un argumento de 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 } !" Tenga en cuenta que el nombre y el documento de la función se utilizarán como el nombre y la descripción del PROP. También puede proporcionar la descripción de los args de Pydantic's Field . La plantilla de excepción se utilizará para representar la respuesta cuando la función plantea un error.
accesorio custom
El accesorio custom llamará a la clase de proporción personalizada cuando se use el accesorio.
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 "" Hooks le permite ejecutar código personalizado cuando ocurren eventos de línea de tiempo específicos. La sección hooks es una lista de ganchos, donde cada gancho es un diccionario con el tipo de gancho y la configuración del gancho. Por defecto, los operaciones habilitan el gancho summary a menos que cambie la sección hooks .
summary
El gancho summary llamará a los agentes para resumir la sesión cuando finalice la sesión. Opcionalmente, puede especificar los nombres de los agentes para resumir.
hooks :
- type : summary
agent_names :
- Mike
- John gancho custom
El gancho custom invocará la clase de gancho personalizado cuando se encuentre el evento de línea de tiempo específico.
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 La clase de gancho puede contener métodos en el formato de on_timeline_<event_type> , donde <event_type> es el tipo del evento Timeline.
Operagents proporciona una herramienta de línea de comandos para ejecutar fácilmente la ópera. Puede ejecutar la ópera con el siguiente comando:
operagents run config.yaml Si desea ver los registros de depuración, puede establecer la opción --log-level :
operagents run --log-level DEBUG config.yaml Se pueden encontrar más comandos y opciones ejecutando operagents --help .
Si desea ejecutar la ópera mediante programación, puede usar la función 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.yamlAbra en CodeSpaces (contenedor de dev):
O instalar el entorno de desarrollo localmente con:
poetry install && poetry run pre-commit install