Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds plugin for OpenAI's Generative Artificial Intelligence platform #3159

Merged
merged 7 commits into from
Mar 24, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
],
},
)
11 changes: 6 additions & 5 deletions src/dispatch/plugins/bases/__init__.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
15 changes: 15 additions & 0 deletions src/dispatch/plugins/bases/artificial_intelligence.py
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
"""
from dispatch.plugins.base import Plugin


class ArtificialIntelligencePlugin(Plugin):
type = "artificial-intelligence"

def ask(self, items, **kwargs):
raise NotImplementedError
1 change: 1 addition & 0 deletions src/dispatch/plugins/dispatch_openai/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from ._version import __version__ # noqa
1 change: 1 addition & 0 deletions src/dispatch/plugins/dispatch_openai/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "0.1.0"
35 changes: 35 additions & 0 deletions src/dispatch/plugins/dispatch_openai/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from pydantic import Field, SecretStr, HttpUrl
from typing import List, TypeVar

from dispatch.config import BaseConfigurationModel

Stop = TypeVar("Stop", str, List)


class OpenAIConfiguration(BaseConfigurationModel):
"""OpenAI configuration description."""

api_url: HttpUrl = Field(
"https://api.openai.com/v1/engines/text-davinci-002/completions",
title="API URL",
description="OpenAI's API URL.",
)
api_key: SecretStr = Field(title="API Key", description="Your secret OpenAI API key.")
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.",
)
55 changes: 55 additions & 0 deletions src/dispatch/plugins/dispatch_openai/plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
.. 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 <[email protected]>
"""
import json
import logging
import requests

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 _generate_headers(self):
return {"Content-Type": "application/json", "Authorization": f"Bearer {self.api_key}"}

def ask(self, prompt):
payload = {
"prompt": prompt,
"max_tokens": self.max_tokens,
"n": self.n,
"stop": self.stop,
"temperature": self.temperature,
}
headers = self._generate_headers()
response = requests.post(self.base_url, headers=headers, data=json.dumps(payload))

if response.status_code == 200:
return response.json()["choices"]
else:
error_message = f"Error {response.status_code}: {response.text}"
logger.error(error_message)
raise Exception(error_message)