Run single tasks

This commit is contained in:
2024-10-30 20:24:12 +01:00
parent f2b9df7611
commit 786a230e78
9 changed files with 500 additions and 248 deletions

View File

@ -8,6 +8,41 @@
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
"""
## Run as Agent
The env. variable `AGENTS_LIST` is used to identify the agents classes/ task handlers.
It must contain he the package name and a variable name in this package divided by `:`.
Then, the variable contains a list of agent classes (subclasses of `ums.agent.agent.BasicAgent`)
For example `AGENTS_LIST=ums.example.example:AGENT_CLASSES`, then in file `./ums/example/example.py` a variable `AGENT_CLASSES` exists.
One line in this file, e.g., is `AGENT_CLASSES = [MyExtractAudioAgent, MyExtractImageAgent]`.
When starting the Docker container of the agent, the classes specified in `AGENTS_LIST` are loaded and if the agent receives a task, the task is sent to the agent classes' `handle` methods.
## Run Single Task
For development it might be cumbersome to always require a running management container and sending messages.
Hence, tasks can be run manually from the terminal (still in the container and using the agent classes), but without having a management.
This also uses the `AGENTS_LIST` env. variable, but the tasks are sent via command line:
There are three ways to send a task (if the agent's Docker container is running):
- `docker compose exec agent_all python -m ums.agent -d`
- Run a dummy task
- Possibly `agent_all` needs to be changed to the service name (see `docker-compose.yml`) of the agent's Docker container
- `cat ./msg.json | docker compose exec -T agent_all python -m ums.agent -i`
- Send the task (json of `AgentMessage`) via STDIN from file `./msg.json` to the agent
- `docker compose exec agent_all python -m ums.agent -f msg.json`
- Get the task from the json file, the files are searched for by full name, in the shared, and the persistent directory.
If the Agent's Docker container is not running, a temporary container can be started.
For the dummy message, the command would be `docker compose run --rm --entrypoint "" agent_all python -m ums.agent -d`.
(Again, change `agent_all` for the service name in `docker-compose.yml`.)
"""
from ums.agent.agent import (
AgentCapability,
BasicAgent,

65
ums/agent/__main__.py Normal file
View File

@ -0,0 +1,65 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
import argparse, sys, os, json
from ums.agent.process import MessageProcessor
from ums.utils import AgentMessage, Riddle, SHARE_PATH, PERSIST_PATH
class _FakeBackgroundTask():
def add_task(self, call, *args):
call(*args)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Agenten Plattform Run Single Task')
parser.add_argument('-f', '--file', help="fetch the message (riddle) from this json file")
parser.add_argument('-d', '--dummy', help="use a dummy message (riddle)", action="store_true")
parser.add_argument('-i', '--stdin', help="get the message (riddle) from STDIN", action="store_true")
args = parser.parse_args()
message = None
if args.dummy:
message = AgentMessage(
id="dummy",
riddle=Riddle(context="Its a dummy.", question="No question!")
)
message.status.extract.required = False
elif args.stdin:
text = ''.join(sys.stdin.readlines())
message = AgentMessage.model_validate_json(text)
elif args.file:
if os.path.isfile(args.file):
f_name = args.file
elif os.path.isfile(os.path.join(SHARE_PATH, args.file)):
f_name = os.path.join(SHARE_PATH, args.file)
elif os.path.isfile(os.path.join(PERSIST_PATH, args.file)):
f_name = os.path.join(PERSIST_PATH, args.file)
else:
print()
print(f"\tFile {args.file} not found!")
print()
f_name = None
if not f_name is None:
message = AgentMessage.model_validate(
json.load(open(f_name, 'r'))
)
if message is None:
parser.print_help()
else:
mp = MessageProcessor(disable_messages=True)
response = mp.new_message(message, _FakeBackgroundTask())
print("\tResponse:")
print(response.model_dump_json(indent=2))

View File

@ -22,8 +22,9 @@ class MessageProcessor():
MANAGEMENT_URL = os.environ.get('MANAGEMENT_URL', 'http://127.0.0.1:80').strip().strip('/')
AGENTS_LIST = os.environ.get('AGENTS_LIST', 'ums.example.example:AGENT_CLASSES').strip()
def __init__(self):
def __init__(self, disable_messages:bool=False):
self.counts = 0
self.disable_messages = disable_messages
module_name, var_name = self.AGENTS_LIST.split(':')
agents_module = importlib.import_module(module_name)
@ -82,14 +83,18 @@ class MessageProcessor():
)
def _send_message(self, message:AgentMessage) -> bool:
r = requests.post(
"{}/message".format(self.MANAGEMENT_URL),
data=message.model_dump_json(),
headers={"accept" : "application/json", "content-type" : "application/json"}
)
if not self.disable_messages:
r = requests.post(
"{}/message".format(self.MANAGEMENT_URL),
data=message.model_dump_json(),
headers={"accept" : "application/json", "content-type" : "application/json"}
)
if r.status_code == 200:
return True
if r.status_code == 200:
return True
else:
logger.warning(f"Error sending message to management! {(r.text, r.headers)}")
return False
else:
logger.warning(f"Error sending message to management! {(r.text, r.headers)}")
return False
print("\tMessages disabled: Requested to send message to management:")
print(message.model_dump_json(indent=2))