diff --git a/README.md b/README.md index c4c146e..3fd8b00 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,9 @@ Inspired by [ChatGPT-in-Slack](https://github.com/seratch/ChatGPT-in-Slack/tree/ Before getting started, make sure you have a development workspace where you have permissions to install apps. If you don’t have one setup, go ahead and [create one](https://slack.com/create). ## Installation +#### Prerequisites +* To use the OpenAI and Anthropic models, you must have an account with sufficient credits. + #### Create a Slack App 1. Open [https://api.slack.com/apps/new](https://api.slack.com/apps/new) and choose "From an app manifest" 2. Choose the workspace you want to install the application to @@ -29,7 +32,7 @@ Before you can run the app, you'll need to store some environment variables. 2. Click ***Basic Information** from the left hand menu and follow the steps in the App-Level Tokens section to create an app-level token with the `connections:write` scope. Copy this token. You will store this in your environment as `SLACK_APP_TOKEN`. ```zsh -# Replace with your app token, bot token, and the token for whichever API(s) you plan on using +# Run these commands in the terminal. Replace with your app token, bot token, and the token for whichever API(s) you plan on using export SLACK_BOT_TOKEN= export SLACK_APP_TOKEN= export OPENAI_API_KEY= diff --git a/ai/__init__.py b/ai/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ai/ai_utils/handle_response.py b/ai/ai_utils/handle_response.py index 8662235..9d2ef72 100644 --- a/ai/ai_utils/handle_response.py +++ b/ai/ai_utils/handle_response.py @@ -5,11 +5,13 @@ from state_store.get_user_state import get_user_state from typing import Optional, List from ..providers import _get_provider + """ This file defines the `get_provider_response` function which retrieves the user's selected API provider and model, sets the model, and generates a response. """ + def get_provider_response(user_id: str, prompt: str, context: Optional[List] = None, system_content=DEFAULT_SYSTEM_CONTENT): try: formatted_context = "\n".join([f"{msg['user']}: {msg['text']}" for msg in context]) diff --git a/ai/providers/__init__.py b/ai/providers/__init__.py index ca10756..a01dba6 100644 --- a/ai/providers/__init__.py +++ b/ai/providers/__init__.py @@ -5,6 +5,8 @@ The `_get_provider()` function returns an instance of the appropriate API provider based on the given provider name. New providers must be added below. """ + + def _get_provider(provider_name: str): if provider_name.lower() == "openai": return OpenAI_API() diff --git a/ai/providers/anthropic.py b/ai/providers/anthropic.py index 011464c..6fbb284 100644 --- a/ai/providers/anthropic.py +++ b/ai/providers/anthropic.py @@ -18,6 +18,7 @@ class AnthropicAPI(BaseAPIProvider): def __init__(self): self.api_key = os.environ.get("ANTHROPIC_API_KEY") + self.client = anthropic.Anthropic(api_key=self.api_key) def set_model(self, model_name: str): if model_name not in self.MODELS.keys(): @@ -32,8 +33,7 @@ def get_models(self) -> dict: def generate_response(self, prompt: str, system_content: str) -> str: try: - client = anthropic.Anthropic(api_key=self.api_key) - response = client.messages.create( + response = self.client.messages.create( model=self.current_model, system=system_content, messages=[{"role": "user", "content": [{"type": "text", "text": prompt}]}], diff --git a/ai/providers/openai.py b/ai/providers/openai.py index 20cba83..8f21221 100644 --- a/ai/providers/openai.py +++ b/ai/providers/openai.py @@ -15,6 +15,7 @@ class OpenAI_API(BaseAPIProvider): def __init__(self): self.api_key = os.environ.get("OPENAI_API_KEY") + self.client = openai.OpenAI(api_key=self.api_key) def set_model(self, model_name: str): if model_name not in self.MODELS.keys(): @@ -29,8 +30,7 @@ def get_models(self) -> dict: def generate_response(self, prompt: str, system_content: str) -> str: try: - client = openai.OpenAI(api_key=self.api_key) - response = client.chat.completions.create( + response = self.client.chat.completions.create( model=self.current_model, n=1, messages=[{"role": "system", "content": system_content}, {"role": "user", "content": prompt}], diff --git a/listeners/commands/ask_command.py b/listeners/commands/ask_command.py index 7e61445..fb912cd 100644 --- a/listeners/commands/ask_command.py +++ b/listeners/commands/ask_command.py @@ -2,6 +2,9 @@ from logging import Logger from ai.ai_utils.handle_response import get_provider_response +# Callback for handling the 'ask-bolty' command. It acknowledges the command, retrieves the user's ID and prompt, +# checks if the prompt is empty, and responds with either an error message or the provider's response. + def ask_callback(ack: Ack, command, say: Say, logger: Logger, context: BoltContext): try: diff --git a/listeners/events/app_home_opened.py b/listeners/events/app_home_opened.py index a55c55f..8ff4f31 100644 --- a/listeners/events/app_home_opened.py +++ b/listeners/events/app_home_opened.py @@ -1,11 +1,14 @@ from logging import Logger from ai.ai_utils.get_available_providers import get_available_providers -from slack_bolt import BoltContext from slack_sdk import WebClient from state_store.get_user_state import get_user_state +# Callback for handling the 'app_home_opened' event. It checks if the event is for the 'home' tab, +# generates a list of model options for a dropdown menu, retrieves the user's state to set the initial option, +# and publishes a view to the user's home tab in Slack. -def app_home_opened_callback(event: dict, logger: Logger, client: WebClient, context: BoltContext): + +def app_home_opened_callback(event: dict, logger: Logger, client: WebClient): if event["tab"] != "home": return