Skip to content

Commit

Permalink
refactor: refactor message reply in CreateMessageReplyUseCase as Chai…
Browse files Browse the repository at this point in the history
…n of Responsibility
  • Loading branch information
ttpss930141011 committed Oct 9, 2023
1 parent e8ba594 commit 5f0fe78
Show file tree
Hide file tree
Showing 29 changed files with 440 additions and 154 deletions.
Binary file modified .coverage
Binary file not shown.
4 changes: 2 additions & 2 deletions src/app/flask_postgresql/api/event_handlers/event_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
from src.interactor.dtos.event_dto import EventInputDto
from src.interactor.dtos.window_dtos import CreateWindowInputDto, GetWindowInputDto
from src.interactor.interfaces.logger.logger import LoggerInterface
from src.interactor.use_cases.create_window import CreateWindowUseCase
from src.interactor.use_cases.get_window import GetWindowUseCase
from src.interactor.use_cases.window.create_window import CreateWindowUseCase
from src.interactor.use_cases.window.get_window import GetWindowUseCase


class EventHandler(EventHandlerInterface):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from src.app.flask_postgresql.api.event_handlers.event_handler import EventHandler
from src.app.flask_postgresql.presenters.message_reply_presenter import EventPresenter
from src.interactor.dtos.event_dto import EventInputDto
from src.interactor.use_cases.create_text_message_reply import CreateTextMessageReplyUseCase
from src.interactor.use_cases.message.create_message_reply import CreateMessageReplyUseCase


class TextEventHandler(EventHandler):
Expand All @@ -15,7 +15,7 @@ def __init__(self, logger, agent_repository):

def execute(self):
presenter = EventPresenter()
use_case = CreateTextMessageReplyUseCase(
use_case = CreateMessageReplyUseCase(
presenter=presenter,
repository=self.agent_repository,
logger=self.logger,
Expand Down
10 changes: 6 additions & 4 deletions src/app/flask_postgresql/api/response.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
from typing import List

from linebot.v3.messaging import (
ApiClient,
Configuration,
MessagingApi,
ReplyMessageRequest,
TextMessage,
)
from linebot.v3.messaging.api_response import ApiResponse
from linebot.v3.messaging.models.message import Message


def create_response(configuration: Configuration, reply_token: str, *results) -> ApiResponse:
messages = [TextMessage(text=result) for result in results]

def create_response(
configuration: Configuration, reply_token: str, messages: List[Message]
) -> ApiResponse:
with ApiClient(configuration) as api_client:
line_bot_api = MessagingApi(api_client)

Expand Down
5 changes: 4 additions & 1 deletion src/app/flask_postgresql/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Config(object):
CHANNEL_ACCESS_TOKEN = os.getenv("CHANNEL_ACCESS_TOKEN", "")
PORT = int(os.getenv("PORT", 5000))
SERPAPI_API_KEY = os.getenv("SERPAPI_API_KEY", "")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "your_openai_api_key")
CHATBOT_DESCRIPTION = os.getenv("CHATBOT_DESCRIPTION", "")
CHATBOT_LANGUAGE = os.getenv("CHATBOT_LANGUAGE", "")
MEMORY_KEY = "chat_history"
Expand All @@ -53,6 +53,9 @@ def __init__(self):
if self.CHATBOT_LANGUAGE is None:
print("Specify CHATBOT_LANGUAGE as environment variable.")
sys.exit(1)
if self.OPENAI_API_KEY is None:
print("Specify OPENAI_API_KEY as environment variable.")
sys.exit(1)

def __setitem__(self, key, item):
self.__dict__[key] = item
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
""" Module for the EventPresenter
"""

from typing import List

from linebot.v3.messaging.models.message import Message

from src.interactor.dtos.event_dto import EventOutputDto
from src.interactor.interfaces.presenters.message_reply_presenter import EventPresenterInterface


class EventPresenter(EventPresenterInterface):
"""Class for the EventPresenter"""

def present(self, output_dto: EventOutputDto) -> str:
def present(self, output_dto: EventOutputDto) -> List[Message]:
"""
Present the output DTO.
Expand Down
12 changes: 12 additions & 0 deletions src/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ def fixture_window():
}


@pytest.fixture
def fixture_window_with_muting():
"""Fixture with Window example"""
return {
"window_id": "abc1234567890",
"is_muting": True,
"system_message": "Hello World",
"agent_language": "en",
"temperature": 20.0,
}


@pytest.fixture
def fixture_message():
"""Fixture with Message example"""
Expand Down
6 changes: 4 additions & 2 deletions src/interactor/dtos/event_dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@


from dataclasses import asdict, dataclass
from typing import Dict
from typing import Dict, List

from linebot.v3.messaging.models.message import Message


@dataclass
Expand All @@ -24,7 +26,7 @@ class EventOutputDto:

window: Dict
user_input: str
response: str
response: List[Message]

def to_dict(self):
"""Convert data into dictionary"""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
""" Module for the MessageReplyPresenterInterface
"""


from abc import ABC, abstractmethod
from typing import Dict
from typing import List

from linebot.v3.messaging.models.message import Message

from src.interactor.dtos.event_dto import EventOutputDto

Expand All @@ -12,5 +13,5 @@ class EventPresenterInterface(ABC):
"""Class for the Interface of the WindowPresenter"""

@abstractmethod
def present(self, output_dto: EventOutputDto) -> Dict:
def present(self, output_dto: EventOutputDto) -> List[Message]:
"""Present the Window"""
110 changes: 0 additions & 110 deletions src/interactor/use_cases/create_text_message_reply_test.py

This file was deleted.

21 changes: 21 additions & 0 deletions src/interactor/use_cases/message/cor/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from typing import List

from linebot.v3.messaging.models.message import Message

from src.interactor.dtos.event_dto import EventInputDto
from src.interactor.interfaces.repositories.agent_executor_repository import (
AgentExecutorRepositoryInterface,
)
from src.interactor.use_cases.message.cor.addition_handler import AdditionHandler
from src.interactor.use_cases.message.cor.default_handler import DefaultHandler
from src.interactor.use_cases.message.cor.muting_handler import MutingHandler


class ReplyMessagesCOR:
def __init__(self):
self._chain = MutingHandler(AdditionHandler(DefaultHandler()))

def handle(self, input_dto: EventInputDto, repository: AgentExecutorRepositoryInterface):
response: List[Message] = []
self._chain.handle(input_dto, repository, response)
return response
24 changes: 24 additions & 0 deletions src/interactor/use_cases/message/cor/addition_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from typing import List

from linebot.v3.messaging.models import TextMessage
from linebot.v3.messaging.models.message import Message

from src.interactor.dtos.event_dto import EventInputDto
from src.interactor.interfaces.repositories.agent_executor_repository import (
AgentExecutorRepositoryInterface,
)
from src.interactor.use_cases.message.cor.handler_base import Handler


class AdditionHandler(Handler):
def handle(
self,
input_dto: EventInputDto,
repository: AgentExecutorRepositoryInterface,
response: List[Message],
):
response.append(TextMessage(text="test handler"))
if self._successor is not None:
return self._successor.handle(input_dto, repository, response)
else:
response.append(TextMessage(text="靜悄悄的,什麼都沒有發生。"))
29 changes: 29 additions & 0 deletions src/interactor/use_cases/message/cor/default_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from typing import List

from langchain.agents import AgentExecutor
from linebot.v3.messaging.models import TextMessage
from linebot.v3.messaging.models.message import Message

from src.interactor.dtos.event_dto import EventInputDto
from src.interactor.interfaces.repositories.agent_executor_repository import (
AgentExecutorRepositoryInterface,
)
from src.interactor.use_cases.message.cor.handler_base import Handler


class DefaultHandler(Handler):
def handle(
self,
input_dto: EventInputDto,
repository: AgentExecutorRepositoryInterface,
response: List[Message],
):
try:
agent_executor = self._get_agent_executor(input_dto, repository)
result = agent_executor.run(input=input_dto.user_input)
response.append(TextMessage(text=result))
except Exception as e:
print(e)
response.append(TextMessage(text="出現錯誤啦!請稍後再試。"))
finally:
return response
47 changes: 47 additions & 0 deletions src/interactor/use_cases/message/cor/handler_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from abc import ABC, abstractmethod
from typing import List, Type

from langchain.agents import AgentExecutor
from linebot.v3.messaging.models.message import Message

from src.interactor.dtos.event_dto import EventInputDto
from src.interactor.interfaces.repositories.agent_executor_repository import (
AgentExecutorRepositoryInterface,
)


class Handler(ABC):
def __init__(self, successor: Type["Handler"] = None):
self._successor = successor

def _get_agent_executor(
self,
input_dto: EventInputDto,
repository: AgentExecutorRepositoryInterface,
) -> AgentExecutor:
"""
Retrieves the agent executor associated with the current window.
:param None: This function does not take any parameters.
:return: None
"""

window_id = input_dto.window.get("window_id")

agent_executor = repository.get(
window_id=window_id,
)
if agent_executor is None:
agent_executor = repository.create(
window_id=window_id,
)
return agent_executor

@abstractmethod
def handle(
self,
input_dto: EventInputDto,
repository: AgentExecutorRepositoryInterface,
response: List[Message],
) -> List[Message]:
pass
Loading

0 comments on commit 5f0fe78

Please sign in to comment.