diff --git a/keipack/stars/__init__.py b/keipack/stars/__init__.py index 04aa7046..a692ff0d 100644 --- a/keipack/stars/__init__.py +++ b/keipack/stars/__init__.py @@ -13,4 +13,3 @@ available_exception_stars = [ # Don't change this, it should automatically generate __all__ __all__ = [command.__name__ for command in [*available_page_stars, *available_exception_stars]] - diff --git a/keipack/stars/api_kei.py b/keipack/stars/api_kei.py index 35ae5cb9..50def3f3 100644 --- a/keipack/stars/api_kei.py +++ b/keipack/stars/api_kei.py @@ -6,7 +6,7 @@ from starlette.responses import * from royalnet.constellation import * from royalnet.utils import * from ..tables import * -from ..utils import Emotion +from ..utils import * class ApiKei(PageStar): @@ -14,25 +14,45 @@ class ApiKei(PageStar): methods = ["POST"] - async def _generate(self, person, form, session) -> Tuple[Emotion, str]: - return Emotion.NEUTRAL, "..." + def __init__(self, config: Dict[str, Any], constellation: "Constellation"): + super().__init__(config, constellation) + self._conversations: Dict[str, Conversation] = {} async def page(self, request: Request) -> JSONResponse: async with self.session_acm() as session: form = await request.form() - person = session.query(self.alchemy.get(KeiPerson)).filter_by(kpid=form["kpid"]).one_or_none() + + kpid = form["kpid"] + convid = form["convid"] + message = form.get("message") + first = form.get("first", False) + + person = await asyncify(session.query(self.alchemy.get(KeiPerson)).filter_by(kpid=kpid).one_or_none) if person is None: - person = self.alchemy.get(KeiPerson)(kpid=form["kpid"]) + person = self.alchemy.get(KeiPerson)(kpid=kpid) session.add(person) - message = self.alchemy.get(KeiMessage)(kei_person=person, message=form["message"]) + message = self.alchemy.get(KeiMessage)(kei_person=person, message=message) session.add(message) await asyncify(session.commit) - try: - emotion, text = await self._generate(person, form, session) - except Exception as e: - print(e) - emotion, text = Emotion.NEUTRAL, "...?" + # Find conversation + while True: + if convid not in self._conversations: + # Create a new conversation + self._conversations[convid] = await ExampleConversation.create() + conv: Conversation = self._conversations[convid] + try: + emotion, text = await conv.next(session=session, person=person, message=message) + except StopAsyncIteration: + del self._conversations[convid] + continue + except Exception as e: + print(e) + emotion, text = Emotion.NEUTRAL, "...?" + else: + break return JSONResponse({ "emotion": str(emotion), "text": text, + }, headers={ + "Access-Control-Allow-Origin": "https://kei.steffo.eu", }) diff --git a/keipack/utils/__init__.py b/keipack/utils/__init__.py index 50fff3ee..55ee2886 100644 --- a/keipack/utils/__init__.py +++ b/keipack/utils/__init__.py @@ -1,5 +1,8 @@ from .emotion import Emotion +from .conversation import Conversation, ExampleConversation __all__ = [ "Emotion", -] \ No newline at end of file + "Conversation", + "ExampleConversation", +] diff --git a/keipack/utils/conversation.py b/keipack/utils/conversation.py new file mode 100644 index 00000000..8e62cf30 --- /dev/null +++ b/keipack/utils/conversation.py @@ -0,0 +1,28 @@ +from .emotion import Emotion + +class Conversation: + def __init__(self): + self.generator = self._generator() + + async def _generator(self): + yield + raise NotImplementedError() + + @classmethod + async def create(cls): + conv = cls() + await conv.generator.asend(None) + return conv + + async def next(self, session, person, message): + reply = await self.generator.asend((session, person, message)) + return reply + + +# noinspection PyTupleAssignmentBalance +class ExampleConversation(Conversation): + async def _generator(self): + session, person, message = yield + session, person, message = yield Emotion.HAPPY, "Ciao!" + session, person, message = yield Emotion.NEUTRAL, "Questa รจ una conversazione di prova." + session, person, message = yield Emotion.X, "X_X" diff --git a/keipack/version.py b/keipack/version.py index 798dabf2..bdf73183 100644 --- a/keipack/version.py +++ b/keipack/version.py @@ -1 +1 @@ -semantic = "0.1" +semantic = "23.12" diff --git a/pyproject.toml b/pyproject.toml index e2c702e9..114995f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ [tool.poetry] name = "keipack" - version = "0.1" + version = "23.12" description = "A mysterious AI assistant" authors = ["Stefano Pigozzi "] license = "AGPL-3.0+" diff --git a/requests/kei.http b/requests/kei.http index db54c30b..4e721eb0 100644 --- a/requests/kei.http +++ b/requests/kei.http @@ -6,15 +6,10 @@ # * 'ptr' and 'ptrp' create a POST request with a simple or parameter-like body; # * 'mptr' and 'fptr' create a POST request to submit a form with a text or file field (multipart/form-data); -POST http://localhost:44445/api/kei -Accept: application/json - -### - POST http://localhost:44445/api/kei Accept: application/json Content-Type: application/x-www-form-urlencoded -first=true +kpid=test&convid=1&first=true&message=lul ### \ No newline at end of file