diff --git a/.gitignore b/.gitignore
index bdac0ef..1c8f9a2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,14 @@
+.DS_Store
+__pycache__
+# data of containers
/data/
+!/data/share/example/*.txt
-.DS_Store
\ No newline at end of file
+# ignore local venv
+/bin/
+/lib/
+/include/
+/pyvenv.cfg
+# ignore ums source
+/ums/
\ No newline at end of file
diff --git a/agent-extract/Dockerfile b/Dockerfile
similarity index 100%
rename from agent-extract/Dockerfile
rename to Dockerfile
diff --git a/Example.md b/Example.md
new file mode 100644
index 0000000..2bda8d2
--- /dev/null
+++ b/Example.md
@@ -0,0 +1,3 @@
+# Beispiel: Rätsel & Agent
+
+TODO
\ No newline at end of file
diff --git a/Implement.md b/Implement.md
new file mode 100644
index 0000000..ef677b0
--- /dev/null
+++ b/Implement.md
@@ -0,0 +1,3 @@
+# Implementierung
+
+TODO
\ No newline at end of file
diff --git a/Readme.md b/Readme.md
index ca23c59..6b2655c 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,4 +1,51 @@
-# Template für ein Agentensystem
+# Template für das Agentensystem
+
+## Einstieg
+0. Rechner vorbereiten
+ 1. Docker Desktop installieren
+ 2. Editor (IDE) installieren (freie Auswahl, Beispiele für )
+1. Repository einrichten
+ 1. Template laden `git clone -o UHH https://git.chai.uni-hamburg.de/UMS-Agenten/Agenten-Plattform.git`
+ 2. *Eigenes* Repository hinzufügen `git remote add UMS https://git.uni-muenster.de/example/my-group.git`
+ 3. In *eigenes* Repository pushen `git push UMS master`
+ 4. Später dann auch immer `git push UMS ...`, `git pull UMS ...`
+ 5. Updates vom Template `git pull UHH master` (Achtung: Merge-Konflikt)
+2. Lokale Umgebung (kann übersprungen werden, mach aber das Entwickeln netter; nur für VS Code)
+ - Python-Paket `src`: Eigene Implementierung
+ - Python-Paket `ums`: Agenten-Plattform ([Quelle](https://git.chai.uni-hamburg.de/UMS-Agenten/Agenten-Plattform/src/branch/master/ums))
+ - VS Code kann leider kein Autocomplete/ IntelliSense im Docker Container anbieten, daher müssen die Quellen auch auf dem Host verfügbar sein.
+ - VS Code erkennt das Verzeichnis `./src/` als Paket `src`
+ - Wir brauchen zusätzlich ein paar Abhängigkeiten und `ums`
+ 1. Virtuelles Env. erstellen `python3 -m venv .`
+ 2. Virtuelles Env. aktivieren `source ./bin/activate`
+ 3. Pakete installieren `pip install requests fastapi pdoc` (evtl. später weitere, damit diese auch IntelliSense unterstützen)
+ 4. In VS Code (in einer Python-Datei unten rechts) das Virtuelle Env. auswählen (`./bin/...`)
+ 5. Verzeichnis `ums` aus dem Docker Container extrahieren:
+ ```bash
+ docker create --name "management" "git.chai.uni-hamburg.de/ums-agenten/management:arm64" # oder :amd64
+ docker cp "management:/ums-agenten/plattform/ums/" ./ums/
+ docker rm "management"
+ ```
+ - Virtuelles Env. und das Verzeichnis `./ums` werden von git ignoriert (siehe `./.gitignore`)
+3. Agenten und Management starten
+ - Die Konfiguration des Managements und er verschiedenen Agenten erfolgt über die Datei `docker-compose.yml`
+ - Es ist sehr sinnvoll die Datei einmal durchzugehen und die Kommentare dort anzusehen.
+ 1. Für jeden Container/ Service die Images prüfen und anpassen (`:arm64` or `:amd64`, siehe [↓](#docker-images))
+ 2. `docker compose up` startet alle Container wie in der `docker-compose.yml` angegeben
+ - Anschließend hängt das Terminal an der Ausgabe der verschiedenen Container
+ - Fehler erscheinen dort im Terminal oder/ und in `./data/persist-*/ums.log`
+ 3. Das Management kann über erreicht werden, es bietet:
+ - Dokumentation:
+ - Übersicht der Nachrichten zwischen Agenten und Management:
+ - Senden von Nachrichten/ Erstellen von Rätseln:
+ - Web API: (siehe auch )
+4. Im Ordner `src` ist ein sehr einfaches Agentensystem implementiert [→ Beispiel: Rätsel & Agent](./Example.md)
+5. Die Implementierung kann auf dem Beispiel aufbauen [→ Implementierung](./Implement.md)
+
+> **Generell gilt:**
+> Die Images sind größtenteils neu.
+> Auch das Management und Agenten-Framework wurde neu entworfen, d.h., es können (und werden) noch ein paar Käfer irgendwo lauern.
+> Bugs also bitte melden und bei Problemen mit dem System nachfragen (magnus.bender@uni-hamburg.de).
## Docker Images
Es gibt unter viele verschiedene Docker Images.
@@ -24,18 +71,6 @@ Folgende Images sind verfügbar:
- Dieses Repository bildet einen einfachen und beispielhaften Agenten ab und soll als Basis dienen.
-> **Generell gilt:**
-> Die Images sind größtenteils neu.
-> Auch das Management und Agenten-Framework wurde neu entworfen, d.h., es können (und werden) noch ein paar Käfer irgendwo lauern.
-> Bugs also bitte melden und bei Problemen mit dem System nachfragen (magnus.bender@uni-hamburg.de).
-
Es wird im Laufe der Zeit sicherlich Updates der verschiedenen Images geben.
Aus diesem Grund gibt bei den Tags Suffixe wie z.B. `2024-10-04` mit dem Datum des Build eines Images.
Somit bleiben auch alte Versionen erreichbar, auch wenn am Ende die aktuelle Version ohne Suffix genutzt werden soll.
-
-## Struktur einen Agenten
-> Dieses Repository ist so konzipiert, dass es geclont werden kann und dann zu einem Angenten *umgebaut* wird.
-
-...
-
-TODO
\ No newline at end of file
diff --git a/agent-extract/src/agent.py b/agent-extract/src/agent.py
deleted file mode 100644
index b8f1c20..0000000
--- a/agent-extract/src/agent.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# 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
-
-from ums.agent import ExtractAudioAgent, ExtractImageAgent
-
-from ums.utils.types import RiddleData
-
-"""
- Examples for simple agents.
-
- Each agent is represented by its own class. The handling of tasks is done by `handle()` in each agent.
-
- Finally `AGENT_CLASSES` contains the classes of the agents in a list. Via environmental variables this list is specified to the ums.agent system.
-"""
-
-class MyExtractAudioAgent(ExtractAudioAgent):
-
- def handle(self, data: RiddleData) -> RiddleData:
- print("Audio Process:", data.file_plain)
- return data
-
-class MyExtractImageAgent(ExtractImageAgent):
-
- def handle(self, data: RiddleData) -> RiddleData:
- print("Image Process:", data.file_plain)
- return data
-
-AGENT_CLASSES = [
- MyExtractAudioAgent, MyExtractImageAgent
-]
\ No newline at end of file
diff --git a/agent-solve/Dockerfile b/agent-solve/Dockerfile
deleted file mode 100644
index adc6384..0000000
--- a/agent-solve/Dockerfile
+++ /dev/null
@@ -1,15 +0,0 @@
-ARG IMAGE_FROM
-FROM $IMAGE_FROM
-
-# become root
-USER root
-
-# do somthing as root, e.g. install packages, set up things ...
-# RUN ...
-
-# copy the source of the agent in this repo
-COPY --chown=user:user ./src/ /ums-agenten/project/src/
-# fix permissions
-RUN chown -R user:user /ums-agenten
-# switch back to user
-USER user
\ No newline at end of file
diff --git a/agent-solve/src/agent.py b/agent-solve/src/agent.py
deleted file mode 100644
index 281a8d8..0000000
--- a/agent-solve/src/agent.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# 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
-
-from typing import Callable
-from ums.agent import ExtractTextAgent, SolveAgent, GatekeeperAgent
-
-from ums.utils.types import AgentMessage, Riddle, RiddleData, RiddleSolution, RiddleStatus
-
-"""
- Examples for simple agents.
-
- Each agent is represented by its own class. The handling of tasks is done by `handle()` in each agent.
-
- Finally `AGENT_CLASSES` contains the classes of the agents in a list. Via environmental variables this list is specified to the ums.agent system.
-"""
-
-class MyExtractTextAgent(ExtractTextAgent):
-
- def before_response(self, response: AgentMessage, send_it: Callable[[], None]) -> bool:
- print("The response will be:", response)
- return True
-
- def handle(self, data: RiddleData) -> RiddleData:
- print("Text Process:", data.file_plain)
- return data
-
-
-class MySolveAgent(SolveAgent):
-
- def handle(self, riddle: Riddle, data: RiddleData) -> RiddleSolution:
-
- if self.message().id == "test":
- status = RiddleStatus()
- status.extract.required = False
- self.sub_riddle(riddle=Riddle(context="Haha", question="Blubber"), status=status)
-
- return RiddleSolution(solution="Huii", explanation="Blubb")
-
-
-class MyGatekeeperAgent(GatekeeperAgent):
-
- def handle(self, solution: RiddleSolution, riddle: Riddle) -> RiddleSolution:
- solution.accepted = True
- solution.review = "Ok"
-
- return solution
-
-AGENT_CLASSES = [
- MyExtractTextAgent,
- MySolveAgent,
- MyGatekeeperAgent
-]
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index 8dda606..6c33628 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,5 +1,8 @@
services:
+
+ # first the management
+
management:
# select the correct one base on platform this is running on
image: git.chai.uni-hamburg.de/ums-agenten/management:arm64
@@ -11,12 +14,16 @@ services:
environment:
# limit number of trials for solving a riddle
- SOLUTION_MAX_TRIALS=5
+ # limit to prevent messages in never ending cycles
+ - MESSAGE_MAX_CONTACTS=100
# how to access management (the host name is the name of the service in this file)
- MANAGEMENT_URL=http://management
# *register* the agents to the management
- - AGENTS_PROCESS=http://agent_extract_1:8000,http://agent_extract_2:8000
+ - AGENTS_PROCESS=http://agent_extract:8000
- AGENTS_SOLVE=http://agent_solve:8000
- AGENTS_GATEKEEPER=http://agent_gatekeeper:8000
+ # divide multiple agents of same type by comma
+ #- AGENTS_PROCESS=http://agent_extract_1:8000,http://agent_extract_2:8000
volumes:
# all data is bind-mounted from ./data on the host into the containers
# the folder *share* is shared with all agents, it can be used to pass the data via files
@@ -24,10 +31,12 @@ services:
# the folder *persist* is different for each container and is used to store data permanently
- ./data/persist-management/:/ums-agenten/persist/
- agent_solve:
+ # afterwards the agents
+
+ agent_extract:
# this allow to do installs etc. in the docker image (a new image will be built on top of the provided one)
build:
- context: ./agent-solve
+ context: .
dockerfile: Dockerfile
args:
# select the correct one base on platform this is running on
@@ -39,28 +48,20 @@ services:
- 8081:8000
environment:
# python package:variable_name of the list of agents implemeted here
- - AGENTS_LIST=src.agent:AGENT_CLASSES
+ - AGENTS_LIST=src.extract.agent:AGENT_CLASSES
# tell the agent where the management is accessible
- MANAGEMENT_URL=http://management
volumes:
- ./data/share/:/ums-agenten/share/
- - ./data/persist-solve/:/ums-agenten/persist/
+ - ./data/persist-extract/:/ums-agenten/persist/
# this is for development (s.t. the changes in ./src/ are directly applied)
- - ./agent-solve/src/:/ums-agenten/project/src/:ro
+ - ./src/:/ums-agenten/project/src/:ro
# for development: will detect file changes and reload server with new source
entrypoint: bash -c "SERVE=true uvicorn ums.agent.main:app --host 0.0.0.0 --port 8000 --reload --reload-dir /ums-agenten/project/src/"
- networks:
- # this is a trick: we add multiple host names to the same container
- # later, each agent will get its own container, but for testing, by this
- # one container can become *all* agents
- default:
- aliases:
- - agent_extract_2
- - agent_gatekeeper
- agent_extract_1:
+ agent_solve:
build:
- context: ./agent-extract
+ context: .
dockerfile: Dockerfile
args:
- IMAGE_FROM=git.chai.uni-hamburg.de/ums-agenten/base-agent:cpu-arm64
@@ -69,9 +70,30 @@ services:
ports:
- 8082:8000
environment:
- - AGENTS_LIST=src.agent:AGENT_CLASSES
+ - AGENTS_LIST=src.solve.agent:AGENT_CLASSES
- MANAGEMENT_URL=http://management
volumes:
- ./data/share/:/ums-agenten/share/
- - ./data/persist-extract/:/ums-agenten/persist/
- - ./agent-extract/src/:/ums-agenten/project/src/:ro
\ No newline at end of file
+ - ./data/persist-solve/:/ums-agenten/persist/
+ - ./src/:/ums-agenten/project/src/:ro
+ entrypoint: bash -c "SERVE=true uvicorn ums.agent.main:app --host 0.0.0.0 --port 8000 --reload --reload-dir /ums-agenten/project/src/"
+
+ agent_gatekeeper:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ args:
+ - IMAGE_FROM=git.chai.uni-hamburg.de/ums-agenten/base-agent:cpu-arm64
+ #- IMAGE_FROM=git.chai.uni-hamburg.de/ums-agenten/base-agent:cpu-amd64
+ #- IMAGE_FROM=git.chai.uni-hamburg.de/ums-agenten/base-agent:gpu-amd64
+ ports:
+ - 8083:8000
+ environment:
+ - AGENTS_LIST=src.validate.agent:AGENT_CLASSES
+ - MANAGEMENT_URL=http://management
+ volumes:
+ - ./data/share/:/ums-agenten/share/
+ - ./data/persist-validate/:/ums-agenten/persist/
+ - ./src/:/ums-agenten/project/src/:ro
+ entrypoint: bash -c "SERVE=true uvicorn ums.agent.main:app --host 0.0.0.0 --port 8000 --reload --reload-dir /ums-agenten/project/src/"
+
\ No newline at end of file
diff --git a/agent-extract/src/__init__.py b/src/extract/__init__.py
similarity index 100%
rename from agent-extract/src/__init__.py
rename to src/extract/__init__.py
diff --git a/src/extract/agent.py b/src/extract/agent.py
new file mode 100644
index 0000000..3c36ba2
--- /dev/null
+++ b/src/extract/agent.py
@@ -0,0 +1,41 @@
+# 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
+
+from typing import Callable
+
+from ums.agent import ExtractAudioAgent, ExtractImageAgent, ExtractTextAgent
+from ums.utils.types import RiddleData, AgentMessage
+
+
+class SimpleExtractAudioAgent(ExtractAudioAgent):
+
+ def handle(self, data: RiddleData) -> RiddleData:
+ print("Audio Process:", data.file_plain)
+ return data
+
+class SimpleExtractImageAgent(ExtractImageAgent):
+
+ def handle(self, data: RiddleData) -> RiddleData:
+ print("Image Process:", data.file_plain)
+ return data
+
+class SimpleExtractTextAgent(ExtractTextAgent):
+
+ def before_response(self, response: AgentMessage, send_it: Callable[[], None]) -> bool:
+ print("The response will be:", response)
+ return True
+
+ def handle(self, data: RiddleData) -> RiddleData:
+ print("Text Process:", data.file_plain)
+ return data
+
+AGENT_CLASSES = [
+ SimpleExtractAudioAgent, SimpleExtractImageAgent, SimpleExtractTextAgent
+]
\ No newline at end of file
diff --git a/agent-solve/src/__init__.py b/src/solve/__init__.py
similarity index 100%
rename from agent-solve/src/__init__.py
rename to src/solve/__init__.py
diff --git a/src/solve/agent.py b/src/solve/agent.py
new file mode 100644
index 0000000..716e1b9
--- /dev/null
+++ b/src/solve/agent.py
@@ -0,0 +1,30 @@
+# 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
+
+
+from ums.agent import SolveAgent
+
+from ums.utils.types import Riddle, RiddleData, RiddleSolution, RiddleStatus
+
+class SimpleSolveAgent(SolveAgent):
+
+ def handle(self, riddle: Riddle, data: RiddleData) -> RiddleSolution:
+
+ if self.message().id == "test":
+ status = RiddleStatus()
+ status.extract.required = False
+ self.sub_riddle(riddle=Riddle(context="Haha", question="Blubber"), status=status)
+
+ return RiddleSolution(solution="Huii", explanation="Blubb")
+
+
+AGENT_CLASSES = [
+ SimpleSolveAgent
+]
\ No newline at end of file
diff --git a/src/validate/__init__.py b/src/validate/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/validate/agent.py b/src/validate/agent.py
new file mode 100644
index 0000000..781878d
--- /dev/null
+++ b/src/validate/agent.py
@@ -0,0 +1,27 @@
+# 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
+
+
+from ums.agent import GatekeeperAgent
+
+from ums.utils.types import Riddle, RiddleSolution
+
+
+class SimpleSolveAgent(GatekeeperAgent):
+
+ def handle(self, solution: RiddleSolution, riddle: Riddle) -> RiddleSolution:
+ solution.accepted = True
+ solution.review = "Ok"
+
+ return solution
+
+AGENT_CLASSES = [
+ SimpleSolveAgent
+]
\ No newline at end of file