Skip to content

Commit

Permalink
feat(openai): add OpenAI / ChatGPT Connector (#383)
Browse files Browse the repository at this point in the history
  • Loading branch information
chillleader authored Mar 27, 2023
1 parent efccb6b commit 02f4ca7
Show file tree
Hide file tree
Showing 4 changed files with 386 additions and 0 deletions.
5 changes: 5 additions & 0 deletions connectors/openai/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under one or more contributor license agreements and licensed to you under a proprietary license.
You may not use this file except in compliance with the proprietary license.
The proprietary license can be either the Camunda Platform Self-Managed Free Edition license (available on Camunda’s website) or the Camunda Platform Self-Managed Enterprise Edition license (a copy you obtain when you contact Camunda).
The Camunda Platform Self-Managed Free Edition comes for free but only allows for usage of the software (file) in non-production environments.
If you want to use the software (file) in production, you need to purchase the Camunda Platform Self-Managed Enterprise Edition.
24 changes: 24 additions & 0 deletions connectors/openai/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# OpenAI Connector

The **OpenAI Connector** allows you to use [ChatGPT](https://platform.openai.com/docs/guides/chat/chat-completions-beta)
or [Moderation API](https://platform.openai.com/docs/guides/moderation/moderation) in your Camunda 8 processes.

This Connector reuses the base implementation of [HTTP JSON Connector](../http-json) by providing a compatible element template.

## What can I use it for?

Large language models like GPT-3 or GPT-4 can create and edit content, or respond to user prompt in an interactive manner.
Please refer to the [example API use-cases](https://platform.openai.com/examples) provided by OpenAI.

![process example](../openai/img/process_example.png)

## Model selection

Refer to the [Models](https://platform.openai.com/docs/models/models) section of OpenAI documentation.
Selection of models is user-specific and depends on your account privileges. Therefore, some models (e.g. GPT-4 at the time of writing)
may appear as non-existing when you attempt to use them, although they are defined in the element template.

## Moderation

It is recommended to use the Moderation API to sanitize both inputs and outputs of the language model.
This way you will be able to prevent violation of OpenAI policies and displaying the potentially unsafe content in your system.
357 changes: 357 additions & 0 deletions connectors/openai/element-templates/openai-connector.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,357 @@
{
"$schema": "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json",
"name": "OpenAI Connector",
"id": "io.camunda.connectors.OpenAI.v1",
"description": "Interact with ChatGPT or Moderation API",
"icon": {
"contents": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjU2cHgiIGhlaWdodD0iMjYwcHgiIHZpZXdCb3g9IjAgMCAyNTYgMjYwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4KICAgIDx0aXRsZT5PcGVuQUk8L3RpdGxlPgogICAgPGc+CiAgICAgICAgPHBhdGggZD0iTTIzOS4xODM5MTQsMTA2LjIwMjc4MyBDMjQ1LjA1NDMwNCw4OC41MjQyMDk2IDI0My4wMjIyOCw2OS4xNzMzODA1IDIzMy42MDc1OTksNTMuMDk5ODg2NCBDMjE5LjQ1MTY3OCwyOC40NTg4MDIxIDE5MC45OTk3MDMsMTUuNzgzNjEyOSAxNjMuMjEzMDA3LDIxLjczOTUwNSBDMTQ3LjU1NDA3Nyw0LjMyMTQ1ODgzIDEyMy43OTQ5MDksLTMuNDIzOTg1NTQgMTAwLjg3OTAxLDEuNDE4NzM4OTggQzc3Ljk2MzExMDUsNi4yNjE0NjM0OSA1OS4zNjkwMDkzLDIyLjk1NzI1MzYgNTIuMDk1OTYyMSw0NS4yMjE0MjE5IEMzMy44NDM2NDk0LDQ4Ljk2NDQ4NjcgMTguMDkwMTcyMSw2MC4zOTI3NDkgOC44NjY3MjUxMyw3Ni41ODE4MDMzIEMtNS40NDM0OTEsMTAxLjE4Mjk2MiAtMi4xOTU0NDQzMSwxMzIuMjE1MjU1IDE2Ljg5ODY2NjIsMTUzLjMyMDA5NCBDMTEuMDA2MDg2NSwxNzAuOTkwNjU2IDEzLjAxOTcyODMsMTkwLjM0Mzk5MSAyMi40MjM4MjMxLDIwNi40MjI5OTEgQzM2LjU5NzU1NTMsMjMxLjA3MjM0NCA2NS4wNjgwMzQyLDI0My43NDY1NjYgOTIuODY5NTczOCwyMzcuNzgzMzcyIEMxMDUuMjM1NjM5LDI1MS43MDgyNDkgMTIzLjAwMTExMywyNTkuNjMwOTQyIDE0MS42MjM5NjgsMjU5LjUyNjkyIEMxNzAuMTA1MzU5LDI1OS41NTIxNjkgMTk1LjMzNzYxMSwyNDEuMTY1NzE4IDIwNC4wMzc3NzcsMjE0LjA0NTY2MSBDMjIyLjI4NzM0LDIxMC4yOTYzNTYgMjM4LjAzODQ4OSwxOTguODY5NzgzIDI0Ny4yNjcwMTQsMTgyLjY4NTI4IEMyNjEuNDA0NDUzLDE1OC4xMjc1MTUgMjU4LjE0MjQ5NCwxMjcuMjYyNzc1IDIzOS4xODM5MTQsMTA2LjIwMjc4MyBMMjM5LjE4MzkxNCwxMDYuMjAyNzgzIFogTTE0MS42MjM5NjgsMjQyLjU0MTIwNyBDMTMwLjI1NTY4MiwyNDIuNTU5MTc3IDExOS4yNDM4NzYsMjM4LjU3NDY0MiAxMTAuNTE5MzgxLDIzMS4yODYxOTcgTDExMi4wNTQxNDYsMjMwLjQxNjQ5NiBMMTYzLjcyNDU5NSwyMDAuNTkwODgxIEMxNjYuMzQwNjQ4LDE5OS4wNTY0NDQgMTY3Ljk1NDMyMSwxOTYuMjU2ODE4IDE2Ny45NzA3ODEsMTkzLjIyNDAwNSBMMTY3Ljk3MDc4MSwxMjAuMzczNzg4IEwxODkuODE1NjE0LDEzMy4wMTAwMjYgQzE5MC4wMzQxMzIsMTMzLjEyMTQyMyAxOTAuMTg2MjM1LDEzMy4zMzA1NjQgMTkwLjIyNDg4NSwxMzMuNTcyNzc0IEwxOTAuMjI0ODg1LDE5My45NDAyMjkgQzE5MC4xNjg2MDMsMjIwLjc1ODQyNyAxNjguNDQyMTY2LDI0Mi40ODQ4NjQgMTQxLjYyMzk2OCwyNDIuNTQxMjA3IFogTTM3LjE1NzU3NDksMTk3LjkzMDYyIEMzMS40NTY0OTgsMTg4LjA4NjM1OSAyOS40MDk0ODE4LDE3Ni41NDY5ODQgMzEuMzc2NjIzNywxNjUuMzQyNDI2IEwzMi45MTEzODk1LDE2Ni4yNjMyODUgTDg0LjYzMjk5NzMsMTk2LjA4ODkwMSBDODcuMjM4OTM0OSwxOTcuNjE4MjA3IDkwLjQ2ODI3MTcsMTk3LjYxODIwNyA5My4wNzQyMDkzLDE5Ni4wODg5MDEgTDE1Ni4yNTU0MDIsMTU5LjY2Mzc5MyBMMTU2LjI1NTQwMiwxODQuODg1MTExIEMxNTYuMjQzNTU3LDE4NS4xNDk3NzEgMTU2LjExMTcyNSwxODUuMzk0NjAyIDE1NS44OTcyOSwxODUuNTUwMTc2IEwxMDMuNTYxNzc2LDIxNS43MzM5MDMgQzgwLjMwNTQ5NTMsMjI5LjEzMTYzMiA1MC41OTI0OTU0LDIyMS4xNjU0MzUgMzcuMTU3NTc0OSwxOTcuOTMwNjIgWiBNMjMuNTQ5MzE4MSw4NS4zODExMjczIEMyOS4yODk5ODYxLDc1LjQ3MzMwOTcgMzguMzUxMTkxMSw2Ny45MTYyNjQ4IDQ5LjEyODc0ODIsNjQuMDQ3ODgyNSBMNDkuMTI4NzQ4MiwxMjUuNDM4NTE1IEM0OS4wODkxNDkyLDEyOC40NTk0MjUgNTAuNjk2NTM4NiwxMzEuMjYyNTU2IDUzLjMyMzc3NDgsMTMyLjc1NDIzMiBMMTE2LjE5ODAxNCwxNjkuMDI1ODY0IEw5NC4zNTMxODA4LDE4MS42NjIxMDIgQzk0LjExMzIzMjUsMTgxLjc4OTQzNCA5My44MjU3NDYxLDE4MS43ODk0MzQgOTMuNTg1Nzk3OSwxODEuNjYyMTAyIEw0MS4zNTI2MDE1LDE1MS41Mjk1MzQgQzE4LjE0MTk0MjYsMTM4LjA3NjA5OCAxMC4xODE3NjgxLDEwOC4zODU1NjIgMjMuNTQ5MzE4MSw4NS4xMjUzMzMgTDIzLjU0OTMxODEsODUuMzgxMTI3MyBaIE0yMDMuMDE0NiwxMjcuMDc1NTk4IEwxMzkuOTM1NzI1LDkwLjQ0NTg1NDUgTDE2MS43Mjk0LDc3Ljg2MDc3NDggQzE2MS45NjkzNDgsNzcuNzMzNDQzNCAxNjIuMjU2ODM0LDc3LjczMzQ0MzQgMTYyLjQ5Njc4Myw3Ny44NjA3NzQ4IEwyMTQuNzI5OTc5LDEwOC4wNDQ1MDIgQzIzMS4wMzIzMjksMTE3LjQ1MTc0NyAyNDAuNDM3Mjk0LDEzNS40MjYxMDkgMjM4Ljg3MTUwNCwxNTQuMTgyNzM5IEMyMzcuMzA1NzE0LDE3Mi45MzkzNjggMjI1LjA1MDcxOSwxODkuMTA1NTcyIDIwNy40MTQyNjIsMTk1LjY3OTYzIEwyMDcuNDE0MjYyLDEzNC4yODg5OTggQzIwNy4zMjI1MjEsMTMxLjI3Njg2NyAyMDUuNjUwNjk3LDEyOC41MzU4NTMgMjAzLjAxNDYsMTI3LjA3NTU5OCBaIE0yMjQuNzU3MTE2LDk0LjM4NTA4NjcgTDIyMy4yMjIzNSw5My40NjQyMjcyIEwxNzEuNjAzMDYsNjMuMzgyODE3MyBDMTY4Ljk4MTI5Myw2MS44NDQzNzUxIDE2NS43MzI0NTYsNjEuODQ0Mzc1MSAxNjMuMTEwNjg5LDYzLjM4MjgxNzMgTDk5Ljk4MDY1NTQsOTkuODA3OTI1OSBMOTkuOTgwNjU1NCw3NC41ODY2MDc3IEM5OS45NTMzMDA0LDc0LjMyNTQwODggMTAwLjA3MTA5NSw3NC4wNzAxODY5IDEwMC4yODc2MDksNzMuOTIxNTQyNiBMMTUyLjUyMDgwNSw0My43ODg5NzM4IEMxNjguODYzMDk4LDM0LjM3NDM1MTggMTg5LjE3NDI1NiwzNS4yNTI5MDQzIDIwNC42NDI1NzksNDYuMDQzNDg0MSBDMjIwLjExMDkwMyw1Ni44MzQwNjM4IDIyNy45NDkyNjksNzUuNTkyMzk1OSAyMjQuNzU3MTE2LDk0LjE4MDQ1MTMgTDIyNC43NTcxMTYsOTQuMzg1MDg2NyBaIE04OC4wNjA2NDA5LDEzOS4wOTc5MzEgTDY2LjIxNTgwNzYsMTI2LjUxMjg1MSBDNjUuOTk1MDM5OSwxMjYuMzc5MDkxIDY1Ljg0NTA5NjUsMTI2LjE1NDE3NiA2NS44MDY1MzY3LDEyNS44OTg5NDUgTDY1LjgwNjUzNjcsNjUuNjg0OTY2IEM2NS44MzE0NDk1LDQ2LjgyODUzNjcgNzYuNzUwMDYwNSwyOS42ODQ2MDMyIDkzLjgyNzA4NTIsMjEuNjg4MzA1NSBDMTEwLjkwNDExLDEzLjY5MjAwNzkgMTMxLjA2MzgzMywxNi4yODM1NDYyIDE0NS41NjMyLDI4LjMzODk5OCBMMTQ0LjAyODQzNCwyOS4yMDg2OTg2IEw5Mi4zNTc5ODUyLDU5LjAzNDMxNDIgQzg5Ljc0MTkzMjcsNjAuNTY4NzUxMyA4OC4xMjgyNTk3LDYzLjM2ODM3NjcgODguMTExNzk5OCw2Ni40MDExOTAxIEw4OC4wNjA2NDA5LDEzOS4wOTc5MzEgWiBNOTkuOTI5NDk2NSwxMTMuNTE4NSBMMTI4LjA2Njg3LDk3LjMwMTE0MTcgTDE1Ni4yNTU0MDIsMTEzLjUxODUgTDE1Ni4yNTU0MDIsMTQ1Ljk1MzIxOCBMMTI4LjE2OTE4NywxNjIuMTcwNTc3IEw5OS45ODA2NTU0LDE0NS45NTMyMTggTDk5LjkyOTQ5NjUsMTEzLjUxODUgWiIgZmlsbD0iIzAwMDAwMCI+PC9wYXRoPgogICAgPC9nPgo8L3N2Zz4K"
},
"documentationRef": "https://docs.camunda.io/docs/components/connectors/out-of-the-box-connectors/openai/",
"category": {
"id": "connectors",
"name": "Connectors"
},
"appliesTo": [
"bpmn:Task"
],
"elementType": {
"value": "bpmn:ServiceTask"
},
"groups": [
{
"id": "authentication",
"label": "Authentication"
},
{
"id": "input",
"label": "Payload"
},
{
"id": "input",
"label": "Payload"
},
{
"id": "output",
"label": "Response Mapping"
},
{
"id": "errors",
"label": "Error Handling"
}
],
"properties": [
{
"type": "Hidden",
"value": "io.camunda:http-json:1",
"binding": {
"type": "zeebe:taskDefinition:type"
}
},
{
"id": "authenticationType",
"value": "bearer",
"type": "Hidden",
"binding": {
"type": "zeebe:input",
"name": "authentication.type"
}
},
{
"label": "OpenAI API Key",
"group": "authentication",
"feel": "optional",
"description": "Your OpenAI API key",
"type": "String",
"binding": {
"type": "zeebe:input",
"name": "authentication.token"
},
"constraints": {
"notEmpty": true
}
},
{
"label": "Organization",
"group": "authentication",
"description": "For members of multiple organizations. Details in the <a href=\"https://platform.openai.com/docs/api-reference/requesting-organization\" target=\"_blank\">OpenAI documentation</a>",
"type": "String",
"feel": "optional",
"binding": {
"type": "zeebe:input",
"name": "internal_organization"
},
"optional": true
},
{
"group": "authentication",
"type": "Hidden",
"value": "=if is defined(internal_organization) and internal_organization != null then {\"Content-Type\":\"application/json\", \"OpenAI-Organization\":internal_organization} else {\"Content-Type\":\"application/json\"}",
"binding": {
"type": "zeebe:input",
"name": "headers"
}
},
{
"label": "Operation",
"group": "input",
"description": "OpenAI API operation",
"type": "Dropdown",
"id": "operation",
"value": "chat",
"choices": [
{
"name": "Chat",
"value": "chat"
},
{
"name": " Moderation",
"value": "moderation"
}
],
"binding": {
"type": "zeebe:input",
"name": "operation"
}
},
{
"id": "method",
"group": "endpoint",
"type": "Hidden",
"value": "post",
"binding": {
"type": "zeebe:input",
"name": "method"
}
},
{
"group": "endpoint",
"type": "Hidden",
"value": "https://api.openai.com/v1/chat/completions",
"binding": {
"type": "zeebe:input",
"name": "url"
},
"condition": {
"property": "operation",
"equals": "chat"
}
},
{
"group": "endpoint",
"type": "Hidden",
"value": "https://api.openai.com/v1/moderations",
"binding": {
"type": "zeebe:input",
"name": "url"
},
"condition": {
"property": "operation",
"equals": "moderation"
}
},
{
"label": "Evaluation input",
"description": "Provide the text to analyze as static value or variable",
"group": "input",
"type": "Text",
"feel": "optional",
"binding": {
"type": "zeebe:input",
"name": "internal_textToAnalyze"
},
"condition": {
"property": "operation",
"equals": "moderation"
},
"constraints": {
"notEmpty": true
}
},
{
"label": "Model",
"description": "Select the model",
"group": "input",
"type": "Dropdown",
"value": "gpt-3.5-turbo",
"choices": [
{
"name": "GPT-3.5-turbo",
"value": "gpt-3.5-turbo"
},
{
"name": "GPT-4",
"value": "gpt-4"
}
],
"binding": {
"type": "zeebe:input",
"name": "internal_model"
},
"condition": {
"property": "operation",
"equals": "chat"
}
},
{
"label": "System message",
"description": "Optional initial instructions for the model",
"group": "input",
"type": "Text",
"optional": true,
"feel": "optional",
"binding": {
"type": "zeebe:input",
"name": "internal_systemMessage"
},
"condition": {
"property": "operation",
"equals": "chat"
}
},
{
"label": "Chat history",
"description": "Optional chat history, or examples of the desired model behavior",
"feel": "required",
"optional": true,
"type": "String",
"group": "input",
"binding": {
"type": "zeebe:input",
"name": "internal_chatHistory"
},
"condition": {
"property": "operation",
"equals": "chat"
}
},
{
"label": "Prompt",
"description": "Input to be evaluated",
"group": "input",
"type": "Text",
"feel": "optional",
"binding": {
"type": "zeebe:input",
"name": "internal_prompt"
},
"condition": {
"property": "operation",
"equals": "chat"
},
"constraints": {
"notEmpty": true
}
},
{
"label": "Choices to generate",
"description": "Amount of alternative responses the model will generate",
"group": "input",
"type": "String",
"feel": "optional",
"optional": false,
"value": "1",
"binding": {
"type": "zeebe:input",
"name": "internal_choices"
},
"condition": {
"property": "operation",
"equals": "chat"
},
"constraints": {
"notEmpty": true,
"pattern": {
"value": "^[1-9]\\d*$",
"message": "Must be a positive integer number"
}
}
},
{
"type": "Hidden",
"binding": {
"type": "zeebe:input",
"name": "internal_messages"
},
"condition": {
"property": "operation",
"equals": "chat"
},
"value": "=append(concatenate(if is defined(internal_systemMessage) then [{\"role\": \"system\", \"content\": internal_systemMessage}] else [], if is defined(internal_chatHistory) then internal_chatHistory else []), {\"role\": \"user\", \"content\": internal_prompt})"
},
{
"type": "Hidden",
"value": "={\"model\": internal_model, \"messages\": internal_messages, \"n\": number(internal_choices)}",
"binding": {
"type": "zeebe:input",
"name": "body"
},
"condition": {
"property": "operation",
"equals": "chat"
}
},
{
"type": "Hidden",
"value": "={\"input\": internal_textToAnalyze}",
"binding": {
"type": "zeebe:input",
"name": "body"
},
"condition": {
"property": "operation",
"equals": "moderation"
}
},
{
"label": "Result Variable",
"description": "Name of variable to store the response in. Details in the <a href=\"https://docs.camunda.io/docs/components/connectors/use-connectors/#result-variable\" target=\"_blank\">documentation</a>",
"group": "output",
"type": "String",
"binding": {
"type": "zeebe:taskHeader",
"key": "resultVariable"
}
},
{
"label": "Result Expression",
"description": "Expression to map the response into process variables. Details in the <a href=\"https://docs.camunda.io/docs/components/connectors/use-connectors/#result-expression\" target=\"_blank\">documentation</a>",
"group": "output",
"type": "Text",
"feel": "required",
"binding": {
"type": "zeebe:taskHeader",
"key": "resultExpression"
}
},
{
"label": "Connection Timeout",
"description": "Sets the timeout in seconds to establish a connection or 0 for an infinite timeout",
"group": "errors",
"type": "String",
"value": "30",
"binding": {
"type": "zeebe:input",
"name": "connectionTimeoutInSeconds"
},
"optional": true,
"constraints": {
"notEmpty": false,
"pattern": {
"value": "^([0-9]*$)|(secrets.*$)",
"message": "Must be timeout in seconds (default value is 20 seconds)"
}
}
},
{
"label": "Error Expression",
"description": "Expression to handle errors. Details in the <a href=\"https://docs.camunda.io/docs/components/connectors/use-connectors/#bpmn-errors\" target=\"_blank\">documentation</a>",
"group": "errors",
"type": "Text",
"feel": "required",
"binding": {
"type": "zeebe:taskHeader",
"key": "errorExpression"
}
}
]
}
Binary file added connectors/openai/img/process_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 02f4ca7

Please sign in to comment.