From adacdced8ac24e605de5f1ce8e0f860160a0ba98 Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Wed, 22 Jan 2025 13:23:04 +0000 Subject: [PATCH] feat(perplexity): add perplexity app with send chat prompt action --- .../src/apps/perplexity/actions/index.js | 3 + .../actions/send-chat-prompt/index.js | 185 ++++++++++++++++++ .../src/apps/perplexity/assets/favicon.svg | 1 + .../backend/src/apps/perplexity/auth/index.js | 34 ++++ .../apps/perplexity/auth/is-still-verified.js | 5 + .../perplexity/auth/verify-credentials.js | 5 + .../apps/perplexity/common/add-auth-header.js | 9 + packages/backend/src/apps/perplexity/index.js | 18 ++ .../src/models/__snapshots__/app.test.js.snap | 1 + packages/docs/pages/.vitepress/config.js | 9 + .../docs/pages/apps/perplexity/actions.md | 12 ++ .../docs/pages/apps/perplexity/connection.md | 8 + packages/docs/pages/guide/available-apps.md | 1 + .../docs/pages/public/favicons/perplexity.svg | 1 + 14 files changed, 292 insertions(+) create mode 100644 packages/backend/src/apps/perplexity/actions/index.js create mode 100644 packages/backend/src/apps/perplexity/actions/send-chat-prompt/index.js create mode 100644 packages/backend/src/apps/perplexity/assets/favicon.svg create mode 100644 packages/backend/src/apps/perplexity/auth/index.js create mode 100644 packages/backend/src/apps/perplexity/auth/is-still-verified.js create mode 100644 packages/backend/src/apps/perplexity/auth/verify-credentials.js create mode 100644 packages/backend/src/apps/perplexity/common/add-auth-header.js create mode 100644 packages/backend/src/apps/perplexity/index.js create mode 100644 packages/docs/pages/apps/perplexity/actions.md create mode 100644 packages/docs/pages/apps/perplexity/connection.md create mode 100644 packages/docs/pages/public/favicons/perplexity.svg diff --git a/packages/backend/src/apps/perplexity/actions/index.js b/packages/backend/src/apps/perplexity/actions/index.js new file mode 100644 index 00000000..c95d62f1 --- /dev/null +++ b/packages/backend/src/apps/perplexity/actions/index.js @@ -0,0 +1,3 @@ +import sendChatPrompt from './send-chat-prompt/index.js'; + +export default [sendChatPrompt]; diff --git a/packages/backend/src/apps/perplexity/actions/send-chat-prompt/index.js b/packages/backend/src/apps/perplexity/actions/send-chat-prompt/index.js new file mode 100644 index 00000000..bde28cf1 --- /dev/null +++ b/packages/backend/src/apps/perplexity/actions/send-chat-prompt/index.js @@ -0,0 +1,185 @@ +import defineAction from '../../../../helpers/define-action.js'; + +const castFloatOrUndefined = (value) => { + return value === '' ? undefined : parseFloat(value); +}; + +export default defineAction({ + name: 'Send chat prompt', + key: 'sendChatPrompt', + description: `Generates a model's response for the given chat conversation.`, + arguments: [ + { + label: 'Model', + key: 'model', + type: 'dropdown', + required: true, + variables: true, + options: [ + { + label: 'Sonar Pro', + value: 'sonar-pro', + }, + { + label: 'Sonar', + value: 'sonar', + }, + ], + }, + { + label: 'Messages', + key: 'messages', + type: 'dynamic', + required: true, + description: 'Add or remove messages as needed', + value: [{ role: 'system', body: '' }], + fields: [ + { + label: 'Role', + key: 'role', + type: 'dropdown', + required: true, + description: + 'The role of the speaker in this turn of conversation. After the (optional) system message, user and assistant roles should alternate with user then assistant, ending in user.', + options: [ + { + label: 'System', + value: 'system', + }, + { + label: 'Assistant', + value: 'assistant', + }, + { + label: 'User', + value: 'user', + }, + ], + }, + { + label: 'Content', + key: 'content', + type: 'string', + required: true, + variables: true, + description: + 'The contents of the message in this turn of conversation.', + }, + ], + }, + { + label: 'Temperature', + key: 'temperature', + type: 'string', + required: false, + variables: true, + description: + 'The amount of randomness in the response, valued between 0 inclusive and 2 exclusive. Higher values are more random, and lower values are more deterministic.', + }, + { + label: 'Maximum tokens', + key: 'maxTokens', + type: 'string', + required: false, + variables: true, + description: + 'The maximum number of tokens to generate in the completion.', + }, + { + label: 'Top P', + key: 'topP', + type: 'string', + required: false, + variables: true, + description: + 'The nucleus sampling threshold, valued between 0 and 1 inclusive. For each subsequent token, the model considers the results of the tokens with top_p probability mass. We recommend either altering top_k or top_p, but not both.', + }, + { + label: 'Top K', + key: 'topK', + type: 'string', + required: false, + variables: true, + description: + 'The number of tokens to keep for highest top-k filtering, specified as an integer between 0 and 2048 inclusive. If set to 0, top-k filtering is disabled. We recommend either altering top_k or top_p, but not both.', + }, + { + label: 'Frequency Penalty', + key: 'frequencyPenalty', + type: 'string', + required: false, + variables: true, + description: `A multiplicative penalty greater than 0. Values greater than 1.0 penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. A value of 1.0 means no penalty. Incompatible with presence_penalty.`, + }, + { + label: 'Presence Penalty', + key: 'presencePenalty', + type: 'string', + required: false, + variables: true, + description: `A value between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. Incompatible with frequency_penalty.`, + }, + { + label: 'Return images', + key: 'returnImages', + type: 'dropdown', + required: false, + variables: true, + value: false, + options: [ + { + label: 'Yes', + value: true, + }, + { + label: 'No', + value: false, + }, + ], + }, + { + label: 'Return related questions', + key: 'returnRelatedQuestions', + type: 'dropdown', + required: false, + variables: true, + value: false, + options: [ + { + label: 'Yes', + value: true, + }, + { + label: 'No', + value: false, + }, + ], + }, + ], + + async run($) { + const payload = { + model: $.step.parameters.model, + temperature: castFloatOrUndefined($.step.parameters.temperature), + max_tokens: castFloatOrUndefined($.step.parameters.maxTokens), + top_p: castFloatOrUndefined($.step.parameters.topP), + top_k: castFloatOrUndefined($.step.parameters.topK), + frequency_penalty: castFloatOrUndefined( + $.step.parameters.frequencyPenalty + ), + presence_penalty: castFloatOrUndefined($.step.parameters.presencePenalty), + messages: $.step.parameters.messages.map((message) => ({ + role: message.role, + content: message.content, + })), + return_images: $.step.parameters.returnImages, + return_related_questions: $.step.parameters.returnRelatedQuestons, + }; + + const { data } = await $.http.post('/chat/completions', payload); + + $.setActionItem({ + raw: data, + }); + }, +}); diff --git a/packages/backend/src/apps/perplexity/assets/favicon.svg b/packages/backend/src/apps/perplexity/assets/favicon.svg new file mode 100644 index 00000000..b27ffc98 --- /dev/null +++ b/packages/backend/src/apps/perplexity/assets/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/backend/src/apps/perplexity/auth/index.js b/packages/backend/src/apps/perplexity/auth/index.js new file mode 100644 index 00000000..67b870bf --- /dev/null +++ b/packages/backend/src/apps/perplexity/auth/index.js @@ -0,0 +1,34 @@ +import verifyCredentials from './verify-credentials.js'; +import isStillVerified from './is-still-verified.js'; + +export default { + fields: [ + { + key: 'screenName', + label: 'Screen Name', + type: 'string', + required: true, + readOnly: false, + value: null, + placeholder: null, + description: + 'Screen name of your connection to be used on Automatisch UI.', + clickToCopy: false, + }, + { + key: 'apiKey', + label: 'API Key', + type: 'string', + required: true, + readOnly: false, + value: null, + placeholder: null, + description: 'Perplexity API key of your account.', + docUrl: 'https://automatisch.io/docs/perplexity#api-key', + clickToCopy: false, + }, + ], + + verifyCredentials, + isStillVerified, +}; diff --git a/packages/backend/src/apps/perplexity/auth/is-still-verified.js b/packages/backend/src/apps/perplexity/auth/is-still-verified.js new file mode 100644 index 00000000..3f853952 --- /dev/null +++ b/packages/backend/src/apps/perplexity/auth/is-still-verified.js @@ -0,0 +1,5 @@ +const isStillVerified = async () => { + return true; +}; + +export default isStillVerified; diff --git a/packages/backend/src/apps/perplexity/auth/verify-credentials.js b/packages/backend/src/apps/perplexity/auth/verify-credentials.js new file mode 100644 index 00000000..07e4f027 --- /dev/null +++ b/packages/backend/src/apps/perplexity/auth/verify-credentials.js @@ -0,0 +1,5 @@ +const verifyCredentials = async () => { + return true; +}; + +export default verifyCredentials; diff --git a/packages/backend/src/apps/perplexity/common/add-auth-header.js b/packages/backend/src/apps/perplexity/common/add-auth-header.js new file mode 100644 index 00000000..f9f5acba --- /dev/null +++ b/packages/backend/src/apps/perplexity/common/add-auth-header.js @@ -0,0 +1,9 @@ +const addAuthHeader = ($, requestConfig) => { + if ($.auth.data?.apiKey) { + requestConfig.headers.Authorization = `Bearer ${$.auth.data.apiKey}`; + } + + return requestConfig; +}; + +export default addAuthHeader; diff --git a/packages/backend/src/apps/perplexity/index.js b/packages/backend/src/apps/perplexity/index.js new file mode 100644 index 00000000..ed401025 --- /dev/null +++ b/packages/backend/src/apps/perplexity/index.js @@ -0,0 +1,18 @@ +import defineApp from '../../helpers/define-app.js'; +import addAuthHeader from './common/add-auth-header.js'; +import auth from './auth/index.js'; +import actions from './actions/index.js'; + +export default defineApp({ + name: 'Perplexity', + key: 'perplexity', + baseUrl: 'https://perplexity.ai', + apiBaseUrl: 'https://api.perplexity.ai', + iconUrl: '{BASE_URL}/apps/perplexity/assets/favicon.svg', + authDocUrl: '{DOCS_URL}/apps/perplexity/connection', + primaryColor: '#091717', + supportsConnections: true, + beforeRequest: [addAuthHeader], + auth, + actions, +}); diff --git a/packages/backend/src/models/__snapshots__/app.test.js.snap b/packages/backend/src/models/__snapshots__/app.test.js.snap index 38324be3..d7901334 100644 --- a/packages/backend/src/models/__snapshots__/app.test.js.snap +++ b/packages/backend/src/models/__snapshots__/app.test.js.snap @@ -41,6 +41,7 @@ exports[`App model > list should have list of applications keys 1`] = ` "ntfy", "odoo", "openai", + "perplexity", "pipedrive", "placetel", "postgresql", diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 0fd2511b..da8bcdff 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -350,6 +350,15 @@ export default defineConfig({ { text: 'Connection', link: '/apps/openai/connection' }, ], }, + { + text: 'Perplexity', + collapsible: true, + collapsed: true, + items: [ + { text: 'Actions', link: '/apps/perplexity/actions' }, + { text: 'Connection', link: '/apps/perplexity/connection' }, + ], + }, { text: 'Pipedrive', collapsible: true, diff --git a/packages/docs/pages/apps/perplexity/actions.md b/packages/docs/pages/apps/perplexity/actions.md new file mode 100644 index 00000000..114be044 --- /dev/null +++ b/packages/docs/pages/apps/perplexity/actions.md @@ -0,0 +1,12 @@ +--- +favicon: /favicons/perplexity.svg +items: + - name: Send chat prompt + desc: Generates a model's response for the given chat conversation. +--- + + + + diff --git a/packages/docs/pages/apps/perplexity/connection.md b/packages/docs/pages/apps/perplexity/connection.md new file mode 100644 index 00000000..5962f51f --- /dev/null +++ b/packages/docs/pages/apps/perplexity/connection.md @@ -0,0 +1,8 @@ +# Perplexity + +1. Go to [API page](https://www.perplexity.ai/settings/api) on Perplexity. +2. Generate a new API key. +3. Paste the key into the `API Key` field in Automatisch. +4. Write any screen name to be displayed in Automatisch. +5. Click `Save`. +6. Start using Perplexity integration with Automatisch! diff --git a/packages/docs/pages/guide/available-apps.md b/packages/docs/pages/guide/available-apps.md index 4be6447b..53eb6ae6 100644 --- a/packages/docs/pages/guide/available-apps.md +++ b/packages/docs/pages/guide/available-apps.md @@ -35,6 +35,7 @@ The following integrations are currently supported by Automatisch. - [Ntfy](/apps/ntfy/actions) - [Odoo](/apps/odoo/actions) - [OpenAI](/apps/openai/actions) +- [Perplexity](/apps/perplexity/actions) - [Pipedrive](/apps/pipedrive/triggers) - [Placetel](/apps/placetel/triggers) - [PostgreSQL](/apps/postgresql/actions) diff --git a/packages/docs/pages/public/favicons/perplexity.svg b/packages/docs/pages/public/favicons/perplexity.svg new file mode 100644 index 00000000..b27ffc98 --- /dev/null +++ b/packages/docs/pages/public/favicons/perplexity.svg @@ -0,0 +1 @@ + \ No newline at end of file