Accept Messages
This commit is contained in:
parent
4199b1c347
commit
5e0945f9ae
@ -1,9 +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
|
|
41
ums/__main__.py
Normal file
41
ums/__main__.py
Normal file
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
from ums.utils import AgentMessage, RiddleData, RiddleDataType, RiddleSolution, ManagementRequest
|
||||||
|
|
||||||
|
ex = AgentMessage(
|
||||||
|
id="ex1",
|
||||||
|
riddle={
|
||||||
|
"context":"Example 1",
|
||||||
|
"question":"Get the name of the person."
|
||||||
|
},
|
||||||
|
data=[
|
||||||
|
RiddleData(
|
||||||
|
type=RiddleDataType.TEXT,
|
||||||
|
file_plain="./cv.txt"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
ex.status.extract.required = False
|
||||||
|
|
||||||
|
ex.solution = RiddleSolution(
|
||||||
|
solution="Otto",
|
||||||
|
explanation="Written in line 6 after 'Name:'"
|
||||||
|
)
|
||||||
|
|
||||||
|
mr = ManagementRequest("localhost")
|
||||||
|
|
||||||
|
print( mr.send_message(ex) )
|
||||||
|
|
||||||
|
print( mr.get_status(20))
|
||||||
|
|
@ -15,44 +15,9 @@ from datetime import datetime
|
|||||||
from threading import Lock
|
from threading import Lock
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
|
||||||
from pydantic import validate_call, BaseModel
|
from pydantic import validate_call
|
||||||
|
|
||||||
from ums.utils import PERSIST_PATH, AgentMessage
|
from ums.utils import PERSIST_PATH, AgentMessage, MessageDbRow
|
||||||
|
|
||||||
class RowObject(BaseModel):
|
|
||||||
"""
|
|
||||||
Object representing a database row.
|
|
||||||
"""
|
|
||||||
|
|
||||||
count : int
|
|
||||||
"""
|
|
||||||
The count (primary key) of the item.
|
|
||||||
"""
|
|
||||||
|
|
||||||
sender : str
|
|
||||||
"""
|
|
||||||
The sender of the message.
|
|
||||||
"""
|
|
||||||
|
|
||||||
recipient : str
|
|
||||||
"""
|
|
||||||
The recipient of the message
|
|
||||||
"""
|
|
||||||
|
|
||||||
time : int
|
|
||||||
"""
|
|
||||||
The time (unix timestamp) the message was received/ sent.
|
|
||||||
"""
|
|
||||||
|
|
||||||
message : AgentMessage
|
|
||||||
"""
|
|
||||||
The message received/ sent.
|
|
||||||
"""
|
|
||||||
|
|
||||||
processed : bool
|
|
||||||
"""
|
|
||||||
Did the management process the message, i.e., did the tasks necessary for this message (mostly only relevant for received messages).
|
|
||||||
"""
|
|
||||||
|
|
||||||
class DB():
|
class DB():
|
||||||
|
|
||||||
@ -117,7 +82,7 @@ class DB():
|
|||||||
finally:
|
finally:
|
||||||
self.db_lock.release()
|
self.db_lock.release()
|
||||||
|
|
||||||
def __iter__(self) -> Generator[RowObject, None, None]:
|
def __iter__(self) -> Generator[MessageDbRow, None, None]:
|
||||||
yield from self.iterate()
|
yield from self.iterate()
|
||||||
|
|
||||||
@validate_call
|
@validate_call
|
||||||
@ -126,7 +91,7 @@ class DB():
|
|||||||
processed:bool|None=None,
|
processed:bool|None=None,
|
||||||
time_after:int|None=None, time_before:int|None=None,
|
time_after:int|None=None, time_before:int|None=None,
|
||||||
limit:int=20, offset:int=0, _count_only:bool=False
|
limit:int=20, offset:int=0, _count_only:bool=False
|
||||||
) -> Generator[RowObject|int, None, None]:
|
) -> Generator[MessageDbRow|int, None, None]:
|
||||||
|
|
||||||
where = []
|
where = []
|
||||||
params = {
|
params = {
|
||||||
@ -177,8 +142,8 @@ class DB():
|
|||||||
kwargs['_count_only'] = True
|
kwargs['_count_only'] = True
|
||||||
return next(self.iterate(**kwargs))
|
return next(self.iterate(**kwargs))
|
||||||
|
|
||||||
def _create_row_object(self, row:sqlite3.Row) -> RowObject:
|
def _create_row_object(self, row:sqlite3.Row) -> MessageDbRow:
|
||||||
return RowObject(
|
return MessageDbRow(
|
||||||
count=row['count'],
|
count=row['count'],
|
||||||
sender=row['sender'],
|
sender=row['sender'],
|
||||||
recipient=row['recipient'],
|
recipient=row['recipient'],
|
||||||
@ -187,7 +152,7 @@ class DB():
|
|||||||
processed=row['processed']
|
processed=row['processed']
|
||||||
)
|
)
|
||||||
|
|
||||||
def by_count(self, count:int) -> RowObject|None:
|
def by_count(self, count:int) -> MessageDbRow|None:
|
||||||
with self.db:
|
with self.db:
|
||||||
try:
|
try:
|
||||||
return self._create_row_object(
|
return self._create_row_object(
|
||||||
|
@ -12,16 +12,17 @@ import os
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request, BackgroundTasks, HTTPException
|
||||||
from fastapi.responses import HTMLResponse
|
from fastapi.responses import HTMLResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
from jinja2.runtime import Undefined as JinjaUndefined
|
from jinja2.runtime import Undefined as JinjaUndefined
|
||||||
|
|
||||||
from ums.management.interface import Interface
|
from ums.management.interface import Interface
|
||||||
from ums.management.db import DB
|
from ums.management.db import DB, MessageDbRow
|
||||||
|
from ums.management.process import MessageProcessor
|
||||||
|
|
||||||
from ums.utils import AgentMessage, RiddleData, RiddleDataType, RiddleSolution, TEMPLATE_PATH
|
from ums.utils import AgentMessage, AgentResponse, TEMPLATE_PATH
|
||||||
|
|
||||||
class WebMain():
|
class WebMain():
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ class WebMain():
|
|||||||
self._init_templates()
|
self._init_templates()
|
||||||
|
|
||||||
self.db = DB()
|
self.db = DB()
|
||||||
|
self.msg_process = MessageProcessor(self.db)
|
||||||
|
|
||||||
self._add_routes()
|
self._add_routes()
|
||||||
self._add_routers()
|
self._add_routers()
|
||||||
@ -75,33 +77,25 @@ class WebMain():
|
|||||||
'index.html',
|
'index.html',
|
||||||
{"request" : request}
|
{"request" : request}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@self.app.post("/message", summary="Send a message to the management")
|
||||||
|
def message(request: Request, message:AgentMessage, background_tasks: BackgroundTasks) -> AgentResponse:
|
||||||
|
|
||||||
|
receiver = request.headers['host']
|
||||||
|
if ':' in receiver:
|
||||||
|
receiver = receiver[:receiver.rindex(':')]
|
||||||
|
|
||||||
|
sender = request.headers['x-forwarded-for']
|
||||||
|
|
||||||
|
return self.msg_process.new_message(sender, receiver, message, background_tasks)
|
||||||
|
|
||||||
@self.app.get("/test", summary="Test")
|
@self.app.get("/status", summary="Get status of a message")
|
||||||
def huhu(request: Request) -> AgentMessage:
|
def status(count:int) -> MessageDbRow:
|
||||||
ex = AgentMessage(
|
msg = self.db.by_count(count)
|
||||||
id="ex1",
|
if msg is None:
|
||||||
riddle={
|
raise HTTPException(status_code=404, detail="Message not found")
|
||||||
"context":"Example 1",
|
|
||||||
"question":"Get the name of the person."
|
return msg
|
||||||
},
|
|
||||||
data=[
|
|
||||||
RiddleData(
|
|
||||||
type=RiddleDataType.TEXT,
|
|
||||||
file_plain="./cv.txt"
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
ex.status.extract.required = False
|
|
||||||
|
|
||||||
ex.solution = RiddleSolution(
|
|
||||||
solution="Otto",
|
|
||||||
explanation="Written in line 6 after 'Name:'"
|
|
||||||
)
|
|
||||||
|
|
||||||
ins_count = self.db.add_message('from', 'to', ex)
|
|
||||||
self.db.set_processed(ins_count)
|
|
||||||
|
|
||||||
return ex
|
|
||||||
|
|
||||||
if __name__ == "ums.management.main" and os.environ.get('SERVE', 'false') == 'true':
|
if __name__ == "ums.management.main" and os.environ.get('SERVE', 'false') == 'true':
|
||||||
main = WebMain()
|
main = WebMain()
|
||||||
|
44
ums/management/process.py
Normal file
44
ums/management/process.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# 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 fastapi import BackgroundTasks
|
||||||
|
|
||||||
|
from ums.management.db import DB
|
||||||
|
|
||||||
|
from ums.utils import AgentMessage, AgentResponse
|
||||||
|
|
||||||
|
class MessageProcessor():
|
||||||
|
|
||||||
|
def __init__(self, db:DB):
|
||||||
|
self.db = db
|
||||||
|
|
||||||
|
def new_message(self,
|
||||||
|
sender:str, receiver:str, message:AgentMessage,
|
||||||
|
background_tasks: BackgroundTasks
|
||||||
|
) -> AgentResponse:
|
||||||
|
|
||||||
|
try:
|
||||||
|
db_count = self.db.add_message(sender, receiver, message)
|
||||||
|
background_tasks.add_task(self._process_message, db_count)
|
||||||
|
|
||||||
|
return AgentResponse(
|
||||||
|
count=db_count,
|
||||||
|
msg="Added message to queue"
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
return AgentResponse(
|
||||||
|
count=-1,
|
||||||
|
error=True,
|
||||||
|
error_msg=str(e)
|
||||||
|
)
|
||||||
|
|
||||||
|
def _process_message(self, count:int):
|
||||||
|
# TODO !!!
|
||||||
|
self.db.set_processed(count=count, processed=True)
|
@ -15,7 +15,11 @@ from ums.utils.types import (
|
|||||||
RiddleSolution,
|
RiddleSolution,
|
||||||
RiddleData,
|
RiddleData,
|
||||||
RiddleDataType,
|
RiddleDataType,
|
||||||
RiddleStatus
|
RiddleStatus,
|
||||||
|
AgentResponse,
|
||||||
|
MessageDbRow
|
||||||
)
|
)
|
||||||
|
|
||||||
from ums.utils.const import *
|
from ums.utils.const import *
|
||||||
|
|
||||||
|
from ums.utils.request import ManagementRequest
|
45
ums/utils/request.py
Normal file
45
ums/utils/request.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# 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 requests
|
||||||
|
|
||||||
|
from ums.utils.types import AgentMessage, AgentResponse, MessageDbRow
|
||||||
|
|
||||||
|
class RequestException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ManagementRequest():
|
||||||
|
|
||||||
|
def __init__(self, hostname:str, port:int=80):
|
||||||
|
self.url = "http://{hostname}:{port}".format(hostname=hostname, port=port)
|
||||||
|
|
||||||
|
def get_status(self, count:int) -> MessageDbRow:
|
||||||
|
r = requests.get(
|
||||||
|
"{}/status".format(self.url),
|
||||||
|
params={"count": count}
|
||||||
|
)
|
||||||
|
|
||||||
|
if r.status_code == 200:
|
||||||
|
return MessageDbRow.model_validate_json(r.text)
|
||||||
|
else:
|
||||||
|
raise RequestException(str(r.text)+str(r.headers))
|
||||||
|
|
||||||
|
|
||||||
|
def send_message(self, message:AgentMessage) -> AgentResponse:
|
||||||
|
r = requests.post(
|
||||||
|
"{}/message".format(self.url),
|
||||||
|
data=message.model_dump_json(),
|
||||||
|
headers={"accept" : "application/json", "content-type" : "application/json"}
|
||||||
|
)
|
||||||
|
|
||||||
|
if r.status_code == 200:
|
||||||
|
return AgentResponse.model_validate_json(r.text)
|
||||||
|
else:
|
||||||
|
return AgentResponse(count=-1, error=True, error_msg=str(r.text)+str(r.headers))
|
@ -289,4 +289,64 @@ class AgentMessage(RiddleInformation):
|
|||||||
status: RiddleStatus = RiddleStatus()
|
status: RiddleStatus = RiddleStatus()
|
||||||
"""
|
"""
|
||||||
The status of the riddle.
|
The status of the riddle.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class AgentResponse(RiddleInformation):
|
||||||
|
"""
|
||||||
|
Returned by the management when receiving an `AgentMessage`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
count : int
|
||||||
|
"""
|
||||||
|
The count of the message (overall numeric id).
|
||||||
|
"""
|
||||||
|
|
||||||
|
msg: str|None = None
|
||||||
|
"""
|
||||||
|
An additional message.
|
||||||
|
"""
|
||||||
|
|
||||||
|
error: bool = False
|
||||||
|
"""
|
||||||
|
If an error occurred.
|
||||||
|
"""
|
||||||
|
|
||||||
|
error_msg: str|None = None
|
||||||
|
"""
|
||||||
|
Error message (if `error` )
|
||||||
|
"""
|
||||||
|
|
||||||
|
class MessageDbRow(BaseModel):
|
||||||
|
"""
|
||||||
|
Object representing a database row.
|
||||||
|
"""
|
||||||
|
|
||||||
|
count : int
|
||||||
|
"""
|
||||||
|
The count (primary key) of the item.
|
||||||
|
"""
|
||||||
|
|
||||||
|
sender : str
|
||||||
|
"""
|
||||||
|
The sender of the message.
|
||||||
|
"""
|
||||||
|
|
||||||
|
recipient : str
|
||||||
|
"""
|
||||||
|
The recipient of the message
|
||||||
|
"""
|
||||||
|
|
||||||
|
time : int
|
||||||
|
"""
|
||||||
|
The time (unix timestamp) the message was received/ sent.
|
||||||
|
"""
|
||||||
|
|
||||||
|
message : AgentMessage
|
||||||
|
"""
|
||||||
|
The message received/ sent.
|
||||||
|
"""
|
||||||
|
|
||||||
|
processed : bool
|
||||||
|
"""
|
||||||
|
Did the management process the message, i.e., did the tasks necessary for this message (mostly only relevant for received messages).
|
||||||
"""
|
"""
|
Loading…
x
Reference in New Issue
Block a user