feat: Reply suggestion and summary generation using OpenAI (#7029)

Add `reply_suggestions` and `summary_generation` options for OpenAI integration

Fixes: https://linear.app/chatwoot/issue/CW-1595/frontend-for-generating-conversation-summary

Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
This commit is contained in:
Muhsin Keloth
2023-05-10 17:50:37 +05:30
committed by GitHub
parent 55e5fa2205
commit 86384bf876
10 changed files with 169 additions and 68 deletions

View File

@@ -1,45 +1,70 @@
<template>
<div v-if="isAIIntegrationEnabled" class="position-relative">
<woot-button
v-tooltip.top-end="$t('INTEGRATION_SETTINGS.OPEN_AI.TITLE')"
icon="wand"
color-scheme="secondary"
variant="smooth"
size="small"
@click="toggleDropdown"
/>
<div
v-if="showDropdown"
v-on-clickaway="closeDropdown"
class="dropdown-pane dropdown-pane--open ai-modal"
>
<h4 class="sub-block-title margin-top-1">
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.TITLE') }}
</h4>
<p>
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.SUBTITLE') }}
</p>
<label>
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.TONE.TITLE') }}
</label>
<div class="tone__item">
<select v-model="activeTone" class="status--filter small">
<option v-for="tone in tones" :key="tone.key" :value="tone.key">
{{ tone.value }}
</option>
</select>
</div>
<div class="modal-footer flex-container align-right">
<woot-button variant="clear" size="small" @click="closeDropdown">
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.BUTTONS.CANCEL') }}
</woot-button>
<woot-button
:is-loading="isGenerating"
size="small"
@click="processText"
>
{{ buttonText }}
</woot-button>
<div v-if="!message">
<woot-button
v-if="isPrivateNote"
v-tooltip.top-end="$t('INTEGRATION_SETTINGS.OPEN_AI.SUMMARY_TITLE')"
icon="book-pulse"
color-scheme="secondary"
variant="smooth"
size="small"
:is-loading="uiFlags.summarize"
@click="processEvent('summarize')"
/>
<woot-button
v-else
v-tooltip.top-end="$t('INTEGRATION_SETTINGS.OPEN_AI.REPLY_TITLE')"
icon="wand"
color-scheme="secondary"
variant="smooth"
size="small"
:is-loading="uiFlags.reply_suggestion"
@click="processEvent('reply_suggestion')"
/>
</div>
<div v-else>
<woot-button
v-tooltip.top-end="$t('INTEGRATION_SETTINGS.OPEN_AI.TITLE')"
icon="text-grammar-wand"
color-scheme="secondary"
variant="smooth"
size="small"
@click="toggleDropdown"
/>
<div
v-if="showDropdown"
v-on-clickaway="closeDropdown"
class="dropdown-pane dropdown-pane--open ai-modal"
>
<h4 class="sub-block-title margin-top-1">
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.TITLE') }}
</h4>
<p>
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.SUBTITLE') }}
</p>
<label>
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.TONE.TITLE') }}
</label>
<div class="tone__item">
<select v-model="activeTone" class="status--filter small">
<option v-for="tone in tones" :key="tone.key" :value="tone.key">
{{ tone.value }}
</option>
</select>
</div>
<div class="modal-footer flex-container align-right">
<woot-button variant="clear" size="small" @click="closeDropdown">
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.BUTTONS.CANCEL') }}
</woot-button>
<woot-button
:is-loading="uiFlags.rephrase"
size="small"
@click="processEvent('rephrase')"
>
{{ buttonText }}
</woot-button>
</div>
</div>
</div>
</div>
@@ -61,10 +86,18 @@ export default {
type: String,
default: '',
},
isPrivateNote: {
type: Boolean,
default: false,
},
},
data() {
return {
isGenerating: false,
uiFlags: {
rephrase: false,
reply_suggestion: false,
summarize: false,
},
showDropdown: false,
activeTone: 'professional',
tones: [
@@ -94,7 +127,7 @@ export default {
).hooks[0].id;
},
buttonText() {
return this.isGenerating
return this.uiFlags.isRephrasing
? this.$t('INTEGRATION_SETTINGS.OPEN_AI.BUTTONS.GENERATING')
: this.$t('INTEGRATION_SETTINGS.OPEN_AI.BUTTONS.GENERATE');
},
@@ -111,14 +144,15 @@ export default {
closeDropdown() {
this.showDropdown = false;
},
async processText() {
this.isGenerating = true;
async processEvent(type = 'rephrase') {
this.uiFlags[type] = true;
try {
const result = await OpenAPI.processEvent({
hookId: this.hookId,
type: 'rephrase',
type,
content: this.message,
tone: this.activeTone,
conversationId: this.conversationId,
});
const {
data: { message: generatedMessage },
@@ -128,7 +162,7 @@ export default {
} catch (error) {
this.showAlert(this.$t('INTEGRATION_SETTINGS.OPEN_AI.GENERATE_ERROR'));
} finally {
this.isGenerating = false;
this.uiFlags[type] = false;
}
},
},