diff --git a/setup.py b/setup.py index 97c22cff2d40..76eaf08551ce 100644 --- a/setup.py +++ b/setup.py @@ -402,12 +402,14 @@ def run(self): entry_points={ "console_scripts": ["dispatch = dispatch.cli:entrypoint"], "dispatch.plugins": [ + "dispatch_atlassian_confluence = dispatch.plugins.dispatch_atlassian_confluence.plugin:ConfluencePagePlugin", + "dispatch_atlassian_confluence_document = dispatch.plugins.dispatch_atlassian_confluence.docs.plugin:ConfluencePageDocPlugin", "dispatch_basic_auth = dispatch.plugins.dispatch_core.plugin:BasicAuthProviderPlugin", "dispatch_contact = dispatch.plugins.dispatch_core.plugin:DispatchContactPlugin", "dispatch_document_resolver = dispatch.plugins.dispatch_core.plugin:DispatchDocumentResolverPlugin", + "dispatch_header_auth = dispatch.plugins.dispatch_core.plugin:HeaderAuthProviderPlugin", "dispatch_participant_resolver = dispatch.plugins.dispatch_core.plugin:DispatchParticipantResolverPlugin", "dispatch_pkce_auth = dispatch.plugins.dispatch_core.plugin:PKCEAuthProviderPlugin", - "dispatch_header_auth = dispatch.plugins.dispatch_core.plugin:HeaderAuthProviderPlugin", "dispatch_ticket = dispatch.plugins.dispatch_core.plugin:DispatchTicketPlugin", "duo_auth_mfa = dispatch.plugins.dispatch_duo.plugin:DuoMfaPlugin", "generic_workflow = dispatch.plugins.generic_workflow.plugin:GenericWorkflowPlugin", @@ -419,13 +421,12 @@ def run(self): "google_gmail_email = dispatch.plugins.dispatch_google.gmail.plugin:GoogleGmailEmailPlugin", "google_groups_participants = dispatch.plugins.dispatch_google.groups.plugin:GoogleGroupParticipantGroupPlugin", "jira_ticket = dispatch.plugins.dispatch_jira.plugin:JiraTicketPlugin", + "openai_artificial_intelligence = dispatch.plugins.dispatch_openai.plugin:OpenAIPlugin", "opsgenie_oncall = dispatch.plugins.dispatch_opsgenie.plugin:OpsGenieOncallPlugin", "pagerduty_oncall = dispatch.plugins.dispatch_pagerduty.plugin:PagerDutyOncallPlugin", "slack_contact = dispatch.plugins.dispatch_slack.plugin:SlackContactPlugin", "slack_conversation = dispatch.plugins.dispatch_slack.plugin:SlackConversationPlugin", "zoom_conference = dispatch.plugins.dispatch_zoom.plugin:ZoomConferencePlugin", - "dispatch_atlassian_confluence = dispatch.plugins.dispatch_atlassian_confluence.plugin:ConfluencePagePlugin", - "dispatch_atlassian_confluence_document = dispatch.plugins.dispatch_atlassian_confluence.docs.plugin:ConfluencePageDocPlugin", ], }, ) diff --git a/src/dispatch/plugins/bases/__init__.py b/src/dispatch/plugins/bases/__init__.py index 9c304dcab19e..495e2a92f12d 100644 --- a/src/dispatch/plugins/bases/__init__.py +++ b/src/dispatch/plugins/bases/__init__.py @@ -1,3 +1,5 @@ +from .artificial_intelligence import ArtificialIntelligencePlugin # noqa +from .auth_mfa import MultiFactorAuthenticationPlugin # noqa from .auth_provider import AuthenticationProviderPlugin # noqa from .conference import ConferencePlugin # noqa from .contact import ContactPlugin # noqa @@ -6,17 +8,16 @@ from .document import DocumentPlugin # noqa from .document_resolver import DocumentResolverPlugin # noqa from .email import EmailPlugin # noqa -from .auth_mfa import MultiFactorAuthenticationPlugin # noqa +from .monitor import MonitorPlugin # noqa from .oncall import OncallPlugin # noqa from .participant import ParticipantPlugin # noqa from .participant_group import ParticipantGroupPlugin # noqa +from .signal_consumer import SignalConsumerPlugin # noqa +from .signal_enrichment import SignalEnrichmentPlugin # noqa +from .source import SourcePlugin # noqa from .storage import StoragePlugin # noqa from .tag import TagPlugin # noqa from .task import TaskPlugin # noqa from .term import TermPlugin # noqa from .ticket import TicketPlugin # noqa from .workflow import WorkflowPlugin # noqa -from .monitor import MonitorPlugin # noqa -from .source import SourcePlugin # noqa -from .signal_consumer import SignalConsumerPlugin # noqa -from .signal_enrichment import SignalEnrichmentPlugin # noqa diff --git a/src/dispatch/plugins/bases/artificial_intelligence.py b/src/dispatch/plugins/bases/artificial_intelligence.py new file mode 100644 index 000000000000..51096e4f7d99 --- /dev/null +++ b/src/dispatch/plugins/bases/artificial_intelligence.py @@ -0,0 +1,15 @@ +""" +.. module: dispatch.plugins.bases.artificial_intelligence + :platform: Unix + :copyright: (c) 2019 by Netflix Inc., see AUTHORS for more + :license: Apache, see LICENSE for more details. +.. moduleauthor:: Marc Vilanova +""" +from dispatch.plugins.base import Plugin + + +class ArtificialIntelligencePlugin(Plugin): + type = "artificial-intelligence" + + def ask(self, items, **kwargs): + raise NotImplementedError diff --git a/src/dispatch/plugins/dispatch_openai/__init__.py b/src/dispatch/plugins/dispatch_openai/__init__.py new file mode 100644 index 000000000000..ad5cc752c07b --- /dev/null +++ b/src/dispatch/plugins/dispatch_openai/__init__.py @@ -0,0 +1 @@ +from ._version import __version__ # noqa diff --git a/src/dispatch/plugins/dispatch_openai/_version.py b/src/dispatch/plugins/dispatch_openai/_version.py new file mode 100644 index 000000000000..3dc1f76bc69e --- /dev/null +++ b/src/dispatch/plugins/dispatch_openai/_version.py @@ -0,0 +1 @@ +__version__ = "0.1.0" diff --git a/src/dispatch/plugins/dispatch_openai/config.py b/src/dispatch/plugins/dispatch_openai/config.py new file mode 100644 index 000000000000..bba63cf71335 --- /dev/null +++ b/src/dispatch/plugins/dispatch_openai/config.py @@ -0,0 +1,31 @@ +from pydantic import Field, SecretStr +from typing import List, TypeVar + +from dispatch.config import BaseConfigurationModel + +Stop = TypeVar("Stop", str, List) + + +class OpenAIConfiguration(BaseConfigurationModel): + """OpenAI configuration description.""" + + api_key: SecretStr = Field(title="API Key", description="Your secret OpenAI API key.") + model: str = Field("text-davinci-003", title="Model", description="") + max_tokens: int = Field( + 50, + title="Max Tokens", + description="The maximum number of tokens to generate in the completion.", + ) + temperature: float = Field( + 1, title="Temperature", description="What sampling temperature to use, between 0 and 2." + ) + n: int = Field( + 1, + title="Number of completions (n)", + description="How many completions to generate for each prompt.", + ) + stop: Stop = Field( + None, + title="Stop", + description="Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.", + ) diff --git a/src/dispatch/plugins/dispatch_openai/plugin.py b/src/dispatch/plugins/dispatch_openai/plugin.py new file mode 100644 index 000000000000..6ad75ea02747 --- /dev/null +++ b/src/dispatch/plugins/dispatch_openai/plugin.py @@ -0,0 +1,53 @@ +""" +.. module: dispatch.plugins.openai.plugin + :platform: Unix + :copyright: (c) 2019 by Netflix Inc., see AUTHORS for more + :license: Apache, see LICENSE for more details. +.. moduleauthor:: Marc Vilanova +""" +import logging + +import openai +from openai import util + +from dispatch.decorators import apply, counter, timer +from dispatch.plugins import dispatch_openai as openai_plugin +from dispatch.plugins.bases import ArtificialIntelligencePlugin +from dispatch.plugins.dispatch_openai.config import ( + OpenAIConfiguration, +) + +logger = logging.getLogger(__name__) + + +@apply(counter, exclude=["__init__"]) +@apply(timer, exclude=["__init__"]) +class OpenAIPlugin(ArtificialIntelligencePlugin): + title = "OpenAI Plugin - Generative Artificial Intelligence" + slug = "openai-artificial-intelligence" + description = "Uses OpenAI's platform to allow users to ask questions in natural language." + version = openai_plugin.__version__ + + author = "Netflix" + author_url = "https://github.com/netflix/dispatch.git" + + def __init__(self): + self.configuration_schema = OpenAIConfiguration + + def ask(self, prompt: str) -> dict: + openai.api_key = self.api_key + + try: + response = openai.Completion.create( + max_tokens=self.max_tokens, + model=self.model, + n=self.n, + prompt=prompt, + stop=self.stop, + temperature=self.temperature, + ) + except Exception as e: + logger.error(e) + raise + + return util.convert_to_dict(response)