app.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import logging
  2. import os
  3. import re
  4. import requests
  5. from dotenv import load_dotenv
  6. from slack_bolt import App as SlackApp
  7. from slack_bolt.adapter.socket_mode import SocketModeHandler
  8. load_dotenv(".env")
  9. logger = logging.getLogger(__name__)
  10. def remove_mentions(message):
  11. mention_pattern = re.compile(r"<@[^>]+>")
  12. cleaned_message = re.sub(mention_pattern, "", message)
  13. cleaned_message.strip()
  14. return cleaned_message
  15. class SlackBotApp:
  16. def __init__(self) -> None:
  17. logger.info("Slack Bot using Embedchain!")
  18. def add(self, _):
  19. raise ValueError("Add is not implemented yet")
  20. def query(self, query, citations: bool = False):
  21. url = os.environ["EC_APP_URL"] + "/query"
  22. payload = {
  23. "question": query,
  24. "citations": citations,
  25. }
  26. try:
  27. response = requests.request("POST", url, json=payload)
  28. try:
  29. response = response.json()
  30. except Exception:
  31. logger.error(f"Failed to parse response: {response}")
  32. response = {}
  33. return response
  34. except Exception:
  35. logger.exception(f"Failed to query {query}.")
  36. response = "An error occurred. Please try again!"
  37. return response
  38. SLACK_APP_TOKEN = os.environ["SLACK_APP_TOKEN"]
  39. SLACK_BOT_TOKEN = os.environ["SLACK_BOT_TOKEN"]
  40. slack_app = SlackApp(token=SLACK_BOT_TOKEN)
  41. slack_bot = SlackBotApp()
  42. @slack_app.event("message")
  43. def app_message_handler(message, say):
  44. pass
  45. @slack_app.event("app_mention")
  46. def app_mention_handler(body, say, client):
  47. # Get the timestamp of the original message to reply in the thread
  48. if "thread_ts" in body["event"]:
  49. # thread is already created
  50. thread_ts = body["event"]["thread_ts"]
  51. say(
  52. text="🧵 Currently, we don't support answering questions in threads. Could you please send your message in the channel for a swift response? Appreciate your understanding! 🚀", # noqa: E501
  53. thread_ts=thread_ts,
  54. )
  55. return
  56. thread_ts = body["event"]["ts"]
  57. say(
  58. text="🎭 Putting on my thinking cap, brb with an epic response!",
  59. thread_ts=thread_ts,
  60. )
  61. query = body["event"]["text"]
  62. question = remove_mentions(query)
  63. print("Asking question: ", question)
  64. response = slack_bot.query(question, citations=True)
  65. default_answer = "Sorry, I don't know the answer to that question. Please refer to the documentation.\nhttps://nextjs.org/docs" # noqa: E501
  66. answer = response.get("answer", default_answer)
  67. contexts = response.get("contexts", [])
  68. if contexts:
  69. sources = list(set(map(lambda x: x[1]["url"], contexts)))
  70. answer += "\n\n*Sources*:\n"
  71. for i, source in enumerate(sources):
  72. answer += f"- {source}\n"
  73. print("Sending answer: ", answer)
  74. result = say(text=answer, thread_ts=thread_ts)
  75. if result["ok"]:
  76. channel = result["channel"]
  77. timestamp = result["ts"]
  78. client.reactions_add(
  79. channel=channel,
  80. name="open_mouth",
  81. timestamp=timestamp,
  82. )
  83. client.reactions_add(
  84. channel=channel,
  85. name="thumbsup",
  86. timestamp=timestamp,
  87. )
  88. client.reactions_add(
  89. channel=channel,
  90. name="heart",
  91. timestamp=timestamp,
  92. )
  93. client.reactions_add(
  94. channel=channel,
  95. name="thumbsdown",
  96. timestamp=timestamp,
  97. )
  98. def start_bot():
  99. slack_socket_mode_handler = SocketModeHandler(slack_app, SLACK_APP_TOKEN)
  100. slack_socket_mode_handler.start()
  101. if __name__ == "__main__":
  102. start_bot()