mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-04-11 21:39:31 +02:00
Merge pull request #1672 from danswer-ai/add-groups-to-slack-bot-responses
add slack groups to user response list
This commit is contained in:
commit
50f799edf4
@ -37,6 +37,7 @@ from danswer.danswerbot.slack.constants import SLACK_CHANNEL_ID
|
||||
from danswer.danswerbot.slack.models import SlackMessageInfo
|
||||
from danswer.danswerbot.slack.utils import ChannelIdAdapter
|
||||
from danswer.danswerbot.slack.utils import fetch_userids_from_emails
|
||||
from danswer.danswerbot.slack.utils import fetch_userids_from_groups
|
||||
from danswer.danswerbot.slack.utils import respond_in_thread
|
||||
from danswer.danswerbot.slack.utils import slack_usage_report
|
||||
from danswer.danswerbot.slack.utils import SlackRateLimiter
|
||||
@ -262,6 +263,7 @@ def handle_message(
|
||||
|
||||
respond_tag_only = channel_conf.get("respond_tag_only") or False
|
||||
respond_team_member_list = channel_conf.get("respond_team_member_list") or None
|
||||
respond_slack_group_list = channel_conf.get("respond_slack_group_list") or None
|
||||
|
||||
if respond_tag_only and not bypass_filters:
|
||||
logger.info(
|
||||
@ -272,10 +274,15 @@ def handle_message(
|
||||
|
||||
if respond_team_member_list:
|
||||
send_to, _ = fetch_userids_from_emails(respond_team_member_list, client)
|
||||
if respond_slack_group_list:
|
||||
user_ids, _ = fetch_userids_from_groups(respond_slack_group_list, client)
|
||||
send_to = (send_to + user_ids) if send_to else user_ids
|
||||
if send_to:
|
||||
send_to = list(set(send_to)) # remove duplicates
|
||||
|
||||
# If configured to respond to team members only, then cannot be used with a /DanswerBot command
|
||||
# which would just respond to the sender
|
||||
if respond_team_member_list and is_bot_msg:
|
||||
if (respond_team_member_list or respond_slack_group_list) and is_bot_msg:
|
||||
if sender_id:
|
||||
respond_in_thread(
|
||||
client=client,
|
||||
@ -448,7 +455,7 @@ def handle_message(
|
||||
|
||||
# For DM (ephemeral message), we need to create a thread via a normal message so the user can see
|
||||
# the ephemeral message. This also will give the user a notification which ephemeral message does not.
|
||||
if respond_team_member_list:
|
||||
if respond_team_member_list or respond_slack_group_list:
|
||||
respond_in_thread(
|
||||
client=client,
|
||||
channel=channel,
|
||||
@ -593,7 +600,7 @@ def handle_message(
|
||||
|
||||
# For DM (ephemeral message), we need to create a thread via a normal message so the user can see
|
||||
# the ephemeral message. This also will give the user a notification which ephemeral message does not.
|
||||
if respond_team_member_list:
|
||||
if respond_team_member_list or respond_slack_group_list:
|
||||
respond_in_thread(
|
||||
client=client,
|
||||
channel=channel,
|
||||
|
@ -308,6 +308,31 @@ def fetch_userids_from_emails(
|
||||
return user_ids, failed_to_find
|
||||
|
||||
|
||||
def fetch_userids_from_groups(
|
||||
group_names: list[str], client: WebClient
|
||||
) -> tuple[list[str], list[str]]:
|
||||
user_ids: list[str] = []
|
||||
failed_to_find: list[str] = []
|
||||
for group_name in group_names:
|
||||
try:
|
||||
# First, find the group ID from the group name
|
||||
response = client.usergroups_list()
|
||||
groups = {group["name"]: group["id"] for group in response["usergroups"]}
|
||||
group_id = groups.get(group_name)
|
||||
|
||||
if group_id:
|
||||
# Fetch user IDs for the group
|
||||
response = client.usergroups_users_list(usergroup=group_id)
|
||||
user_ids.extend(response["users"])
|
||||
else:
|
||||
failed_to_find.append(group_name)
|
||||
except Exception as e:
|
||||
logger.error(f"Error fetching user IDs for group {group_name}: {str(e)}")
|
||||
failed_to_find.append(group_name)
|
||||
|
||||
return user_ids, failed_to_find
|
||||
|
||||
|
||||
def fetch_groupids_from_names(
|
||||
names: list[str], client: WebClient
|
||||
) -> tuple[list[str], list[str]]:
|
||||
|
@ -1061,6 +1061,7 @@ class ChannelConfig(TypedDict):
|
||||
respond_tag_only: NotRequired[bool] # defaults to False
|
||||
respond_to_bots: NotRequired[bool] # defaults to False
|
||||
respond_team_member_list: NotRequired[list[str]]
|
||||
respond_slack_group_list: NotRequired[list[str]]
|
||||
answer_filters: NotRequired[list[AllowedAnswerFilters]]
|
||||
# If None then no follow up
|
||||
# If empty list, follow up with no tags
|
||||
|
@ -104,6 +104,7 @@ class SlackBotConfigCreationRequest(BaseModel):
|
||||
respond_to_bots: bool = False
|
||||
# If no team members, assume respond in the channel to everyone
|
||||
respond_team_member_list: list[str] = []
|
||||
respond_slack_group_list: list[str] = []
|
||||
answer_filters: list[AllowedAnswerFilters] = []
|
||||
# list of user emails
|
||||
follow_up_tags: list[str] | None = None
|
||||
|
@ -37,6 +37,9 @@ def _form_channel_config(
|
||||
respond_team_member_list = (
|
||||
slack_bot_config_creation_request.respond_team_member_list
|
||||
)
|
||||
respond_slack_group_list = (
|
||||
slack_bot_config_creation_request.respond_slack_group_list
|
||||
)
|
||||
answer_filters = slack_bot_config_creation_request.answer_filters
|
||||
follow_up_tags = slack_bot_config_creation_request.follow_up_tags
|
||||
|
||||
@ -58,7 +61,7 @@ def _form_channel_config(
|
||||
detail=str(e),
|
||||
)
|
||||
|
||||
if respond_tag_only and respond_team_member_list:
|
||||
if respond_tag_only and (respond_team_member_list or respond_slack_group_list):
|
||||
raise ValueError(
|
||||
"Cannot set DanswerBot to only respond to tags only and "
|
||||
"also respond to a predetermined set of users."
|
||||
@ -71,6 +74,8 @@ def _form_channel_config(
|
||||
channel_config["respond_tag_only"] = respond_tag_only
|
||||
if respond_team_member_list:
|
||||
channel_config["respond_team_member_list"] = respond_team_member_list
|
||||
if respond_slack_group_list:
|
||||
channel_config["respond_slack_group_list"] = respond_slack_group_list
|
||||
if answer_filters:
|
||||
channel_config["answer_filters"] = answer_filters
|
||||
if follow_up_tags is not None:
|
||||
|
@ -71,9 +71,13 @@ export const SlackBotCreationForm = ({
|
||||
existingSlackBotConfig?.channel_config?.respond_tag_only || false,
|
||||
respond_to_bots:
|
||||
existingSlackBotConfig?.channel_config?.respond_to_bots || false,
|
||||
respond_team_member_list:
|
||||
respond_member_group_list: (
|
||||
existingSlackBotConfig?.channel_config
|
||||
?.respond_team_member_list || ([] as string[]),
|
||||
?.respond_team_member_list ?? []
|
||||
).concat(
|
||||
existingSlackBotConfig?.channel_config
|
||||
?.respond_slack_group_list ?? []
|
||||
),
|
||||
still_need_help_enabled:
|
||||
existingSlackBotConfig?.channel_config?.follow_up_tags !==
|
||||
undefined,
|
||||
@ -101,7 +105,7 @@ export const SlackBotCreationForm = ({
|
||||
questionmark_prefilter_enabled: Yup.boolean().required(),
|
||||
respond_tag_only: Yup.boolean().required(),
|
||||
respond_to_bots: Yup.boolean().required(),
|
||||
respond_team_member_list: Yup.array().of(Yup.string()).required(),
|
||||
respond_member_group_list: Yup.array().of(Yup.string()).required(),
|
||||
still_need_help_enabled: Yup.boolean().required(),
|
||||
follow_up_tags: Yup.array().of(Yup.string()),
|
||||
document_sets: Yup.array().of(Yup.number()),
|
||||
@ -116,8 +120,13 @@ export const SlackBotCreationForm = ({
|
||||
channel_names: values.channel_names.filter(
|
||||
(channelName) => channelName !== ""
|
||||
),
|
||||
respond_team_member_list: values.respond_team_member_list.filter(
|
||||
(teamMemberEmail) => teamMemberEmail !== ""
|
||||
respond_team_member_list: values.respond_member_group_list.filter(
|
||||
(teamMemberEmail) =>
|
||||
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(teamMemberEmail)
|
||||
),
|
||||
respond_slack_group_list: values.respond_member_group_list.filter(
|
||||
(slackGroupName) =>
|
||||
!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(slackGroupName)
|
||||
),
|
||||
usePersona: usingPersonas,
|
||||
};
|
||||
@ -227,14 +236,14 @@ export const SlackBotCreationForm = ({
|
||||
subtext="If not set, DanswerBot will always ignore messages from Bots"
|
||||
/>
|
||||
<TextArrayField
|
||||
name="respond_team_member_list"
|
||||
label="Team Members Emails"
|
||||
name="respond_member_group_list"
|
||||
label="Team Member Emails Or Slack Group Names"
|
||||
subtext={`If specified, DanswerBot responses will only be
|
||||
visible to members in this list. This is
|
||||
visible to the members or groups in this list. This is
|
||||
useful if you want DanswerBot to operate in an
|
||||
"assistant" mode, where it helps the team members find
|
||||
answers, but let's them build on top of DanswerBot's response / throw
|
||||
out the occasional incorrect answer.`}
|
||||
out the occasional incorrect answer. Group names are case sensitive.`}
|
||||
values={values}
|
||||
/>
|
||||
<Divider />
|
||||
|
@ -14,6 +14,7 @@ interface SlackBotConfigCreationRequest {
|
||||
respond_tag_only: boolean;
|
||||
respond_to_bots: boolean;
|
||||
respond_team_member_list: string[];
|
||||
respond_slack_group_list: string[];
|
||||
follow_up_tags?: string[];
|
||||
usePersona: boolean;
|
||||
response_type: SlackBotResponseType;
|
||||
@ -40,6 +41,7 @@ const buildRequestBodyFromCreationRequest = (
|
||||
respond_tag_only: creationRequest.respond_tag_only,
|
||||
respond_to_bots: creationRequest.respond_to_bots,
|
||||
respond_team_member_list: creationRequest.respond_team_member_list,
|
||||
respond_slack_group_list: creationRequest.respond_slack_group_list,
|
||||
answer_filters: buildFiltersFromCreationRequest(creationRequest),
|
||||
follow_up_tags: creationRequest.follow_up_tags?.filter((tag) => tag !== ""),
|
||||
...(creationRequest.usePersona
|
||||
|
@ -475,6 +475,7 @@ export interface ChannelConfig {
|
||||
respond_tag_only?: boolean;
|
||||
respond_to_bots?: boolean;
|
||||
respond_team_member_list?: string[];
|
||||
respond_slack_group_list?: string[];
|
||||
answer_filters?: AnswerFilterOption[];
|
||||
follow_up_tags?: string[];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user