Skip to content

Commit 319076a

Browse files
committed
more refactor
1 parent 444a8fd commit 319076a

File tree

5 files changed

+71
-53
lines changed

5 files changed

+71
-53
lines changed

packages/slackBotFunction/app/core/config.py

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@
1414
from aws_lambda_powertools.utilities.parameters import get_parameter
1515
from mypy_boto3_dynamodb.service_resource import Table
1616

17+
# we use lru_cache for lots of configs so they are cached
18+
1719

1820
@lru_cache()
1921
def get_logger() -> Logger:
2022
return Logger(service="slackBotFunction")
2123

2224

25+
# set up logger as its used in other functions
2326
logger = get_logger()
2427

2528

@@ -58,6 +61,27 @@ def get_ssm_params() -> Tuple[str, str]:
5861
return bot_token, signing_secret
5962

6063

64+
@lru_cache
65+
def get_bot_token() -> str:
66+
bot_token, _ = get_ssm_params()
67+
return bot_token
68+
69+
70+
@lru_cache
71+
def get_guardrail_config() -> Tuple[str, str, str, str, str]:
72+
# Bedrock configuration from environment
73+
KNOWLEDGEBASE_ID = os.environ["KNOWLEDGEBASE_ID"]
74+
RAG_MODEL_ID = os.environ["RAG_MODEL_ID"]
75+
AWS_REGION = os.environ["AWS_REGION"]
76+
GUARD_RAIL_ID = os.environ["GUARD_RAIL_ID"]
77+
GUARD_VERSION = os.environ["GUARD_RAIL_VERSION"]
78+
79+
logger.info(
80+
"Guardrail configuration loaded", extra={"guardrail_id": GUARD_RAIL_ID, "guardrail_version": GUARD_VERSION}
81+
)
82+
return KNOWLEDGEBASE_ID, RAG_MODEL_ID, AWS_REGION, GUARD_RAIL_ID, GUARD_VERSION
83+
84+
6185
@dataclass
6286
class Constants:
6387
FEEDBACK_PREFIX: str
@@ -98,37 +122,28 @@ class Constants:
98122
)
99123

100124

101-
@lru_cache
102-
def get_bot_token() -> str:
103-
bot_token, _ = get_ssm_params()
104-
return bot_token
125+
@dataclass
126+
class BotMessages:
127+
EMPTY_QUERY: str
128+
ERROR_RESPONSE: str
129+
FEEDBACK_POSITIVE_THANKS: str
130+
FEEDBACK_NEGATIVE_THANKS: str
131+
FEEDBACK_THANKS: str
132+
FEEDBACK_PROMPT: str
133+
FEEDBACK_YES: str
134+
FEEDBACK_NO: str
105135

106136

107137
# Bot response messages
108-
BOT_MESSAGES = {
109-
"empty_query": "Hi there! Please ask me a question and I'll help you find information from our knowledge base.",
110-
"error_response": "Sorry, an error occurred while processing your request. Please try again later.",
111-
"feedback_positive_thanks": "Thank you for your feedback.",
112-
"feedback_negative_thanks": (
138+
bot_messages = BotMessages(
139+
EMPTY_QUERY="Hi there! Please ask me a question and I'll help you find information from our knowledge base.",
140+
ERROR_RESPONSE="Sorry, an error occurred while processing your request. Please try again later.",
141+
FEEDBACK_POSITIVE_THANKS="Thank you for your feedback.",
142+
FEEDBACK_NEGATIVE_THANKS=(
113143
'Please let us know how the answer could be improved. Start your message with "feedback:"'
114144
),
115-
"feedback_thanks": "Thank you for your feedback.",
116-
"feedback_prompt": "Was this helpful?",
117-
"feedback_yes": "Yes",
118-
"feedback_no": "No",
119-
}
120-
121-
122-
@lru_cache
123-
def get_guardrail_config() -> Tuple[str, str, str, str, str]:
124-
# Bedrock configuration from environment
125-
KNOWLEDGEBASE_ID = os.environ["KNOWLEDGEBASE_ID"]
126-
RAG_MODEL_ID = os.environ["RAG_MODEL_ID"]
127-
AWS_REGION = os.environ["AWS_REGION"]
128-
GUARD_RAIL_ID = os.environ["GUARD_RAIL_ID"]
129-
GUARD_VERSION = os.environ["GUARD_RAIL_VERSION"]
130-
131-
logger.info(
132-
"Guardrail configuration loaded", extra={"guardrail_id": GUARD_RAIL_ID, "guardrail_version": GUARD_VERSION}
133-
)
134-
return KNOWLEDGEBASE_ID, RAG_MODEL_ID, AWS_REGION, GUARD_RAIL_ID, GUARD_VERSION
145+
FEEDBACK_THANKS="Thank you for your feedback.",
146+
FEEDBACK_PROMPT="Was this helpful?",
147+
FEEDBACK_YES="Yes",
148+
FEEDBACK_NO="No",
149+
)

packages/slackBotFunction/app/services/slack.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import traceback
22

33
from slack_sdk import WebClient
4-
from app.core.config import get_logger
4+
from app.core.config import bot_messages, get_bot_token, get_logger
55

66

77
logger = get_logger()
@@ -21,3 +21,15 @@ def get_friendly_channel_name(channel_id: str, client: WebClient) -> str:
2121
except Exception:
2222
logger.warning("There was an error getting the friendly channel name", extra={"error": traceback.format_exc()})
2323
return friendly_channel_name
24+
25+
26+
def post_error_message(channel: str, thread_ts: str | None) -> None:
27+
try:
28+
token = get_bot_token()
29+
client = WebClient(token=token)
30+
post_params = {"channel": channel, "text": bot_messages.ERROR_RESPONSE}
31+
if thread_ts: # Only add thread_ts for channel threads, not DMs
32+
post_params["thread_ts"] = thread_ts
33+
client.chat_postMessage(**post_params)
34+
except Exception:
35+
logger.error("Failed to post error message", extra={"error": traceback.format_exc()})

packages/slackBotFunction/app/slack/slack_events.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from botocore.exceptions import ClientError
1212
from slack_sdk import WebClient
1313
from app.core.config import (
14-
BOT_MESSAGES,
14+
bot_messages,
1515
constants,
1616
get_bot_token,
1717
get_logger,
@@ -24,7 +24,7 @@
2424
update_state_information,
2525
)
2626
from app.services.query_reformulator import reformulate_query
27-
from app.services.slack import get_friendly_channel_name
27+
from app.services.slack import get_friendly_channel_name, post_error_message
2828
from app.utils.handler_utils import extract_pull_request_id, is_duplicate_event
2929

3030
logger = get_logger()
@@ -155,20 +155,20 @@ def _create_feedback_blocks(
155155
feedback_value = json.dumps(feedback_data, separators=(",", ":"))
156156
return [
157157
{"type": "section", "text": {"type": "mrkdwn", "text": response_text}},
158-
{"type": "section", "text": {"type": "plain_text", "text": BOT_MESSAGES["feedback_prompt"]}},
158+
{"type": "section", "text": {"type": "plain_text", "text": bot_messages.FEEDBACK_PROMPT}},
159159
{
160160
"type": "actions",
161161
"block_id": "feedback_block",
162162
"elements": [
163163
{
164164
"type": "button",
165-
"text": {"type": "plain_text", "text": BOT_MESSAGES["feedback_yes"]},
165+
"text": {"type": "plain_text", "text": bot_messages.FEEDBACK_YES},
166166
"action_id": "feedback_yes",
167167
"value": feedback_value,
168168
},
169169
{
170170
"type": "button",
171-
"text": {"type": "plain_text", "text": BOT_MESSAGES["feedback_no"]},
171+
"text": {"type": "plain_text", "text": bot_messages.FEEDBACK_NO},
172172
"action_id": "feedback_no",
173173
"value": feedback_value,
174174
},
@@ -210,7 +210,7 @@ def process_async_slack_event(slack_event_data: Dict[str, Any]) -> None:
210210

211211
# handles empty messages
212212
if not user_query:
213-
post_params = {"channel": channel, "text": BOT_MESSAGES["empty_query"]}
213+
post_params = {"channel": channel, "text": bot_messages.EMPTY_QUERY}
214214
if thread_ts: # Only add thread_ts for channel threads, not DMs
215215
post_params["thread_ts"] = thread_ts
216216
client.chat_postMessage(**post_params)
@@ -262,13 +262,7 @@ def process_async_slack_event(slack_event_data: Dict[str, Any]) -> None:
262262
logger.error("Error processing message", extra={"event_id": event_id, "error": traceback.format_exc()})
263263

264264
# Try to notify user of error via Slack
265-
try:
266-
post_params = {"channel": channel, "text": BOT_MESSAGES["error_response"]}
267-
if thread_ts: # Only add thread_ts for channel threads, not DMs
268-
post_params["thread_ts"] = thread_ts
269-
client.chat_postMessage(**post_params)
270-
except Exception:
271-
logger.error("Failed to post error message", extra={"error": traceback.format_exc()})
265+
post_error_message(channel=channel, thread_ts=thread_ts)
272266

273267

274268
def process_pull_request_slack_event(slack_event_data: Dict[str, Any]) -> None:

packages/slackBotFunction/app/slack/slack_handlers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from slack_bolt import Ack, App
1616
from slack_sdk import WebClient
1717
from app.core.config import (
18-
BOT_MESSAGES,
18+
bot_messages,
1919
get_logger,
2020
constants,
2121
)
@@ -183,10 +183,10 @@ def feedback_handler(ack: Ack, body: Dict[str, Any], client: WebClient) -> None:
183183
# Determine feedback type and response message based on action_id
184184
if action_id == "feedback_yes":
185185
feedback_type = "positive"
186-
response_message = BOT_MESSAGES["feedback_positive_thanks"]
186+
response_message = bot_messages.FEEDBACK_POSITIVE_THANKS
187187
elif action_id == "feedback_no":
188188
feedback_type = "negative"
189-
response_message = BOT_MESSAGES["feedback_negative_thanks"]
189+
response_message = bot_messages.FEEDBACK_NEGATIVE_THANKS
190190
else:
191191
logger.error(f"Unknown feedback action: {action_id}")
192192
return
@@ -252,7 +252,7 @@ def _common_message_handler(
252252
try:
253253
params = {
254254
"channel": channel_id,
255-
"text": BOT_MESSAGES["feedback_thanks"],
255+
"text": bot_messages.FEEDBACK_THANKS,
256256
}
257257

258258
if post_to_thread:

packages/slackBotFunction/tests/test_async_processing.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,24 +80,22 @@ def test_process_async_slack_event_empty_query(mock_webclient: Mock, mock_get_pa
8080
)
8181

8282

83-
@patch("slack_sdk.WebClient")
8483
@patch("app.services.dynamo.get_state_information")
8584
@patch("app.services.bedrock.query_bedrock")
8685
@patch("app.services.query_reformulator.reformulate_query")
8786
@patch("app.slack.slack_events.get_conversation_session")
87+
@patch("app.services.slack.post_error_message")
8888
def test_process_async_slack_event_error(
89+
mock_post_error_message: Mock,
8990
mock_get_session: Mock,
9091
mock_reformulate_query: Mock,
9192
mock_query_bedrock: Mock,
9293
mock_get_state_information: Mock,
93-
mock_webclient: Mock,
9494
mock_get_parameter: Mock,
9595
mock_env: Mock,
9696
):
9797
"""Test async event processing with error"""
9898
# set up mocks
99-
mock_client = Mock()
100-
mock_webclient.return_value = mock_client
10199
mock_query_bedrock.side_effect = Exception("Bedrock error")
102100
mock_reformulate_query.return_value = "test question"
103101
mock_get_session.return_value = None # No existing session
@@ -116,9 +114,8 @@ def test_process_async_slack_event_error(
116114
process_async_slack_event(slack_event_data)
117115

118116
# assertions
119-
mock_client.chat_postMessage.assert_called_once_with(
117+
mock_post_error_message.assert_called_once_with(
120118
channel="C789",
121-
text="Sorry, an error occurred while processing your request. Please try again later.",
122119
thread_ts="1234567890.123",
123120
)
124121

0 commit comments

Comments
 (0)