Skip to content

Commit 3fdc6c9

Browse files
scezenassouktim
authored andcommitted
[DERCBOT-1314] Documentation
Adding modifications Typo [DERCBOT-1309] Documentation update + Annotation Model Move Model files + Add Annotation as a subdocument of an Action Update Action and Dialog to support single annotation per action DAO update to allow Annotation insertion in Action subdocument Initiate BotAnnotationEvent as emptyList Business logic + Annotation creation endpoint Model update, refacto and addEvent endpoint logic Update and Delete event endpoint Restore removed byStory endpoint DialogsVerticle + Annotation presence check Improvements Dialog Endpoints to DialogVerticle Update logic to retrieve annotations from /dialogs/search endpoint Modify annotation with PUT endpoint lastUpdateDate logic added Unused import Fix malfunctioning logic + Doc update Add initial event at annotation creation PR Review Rebase + fix canEdit bool Refacto and BotAnnotationUpdateDTO delete Doc update with latest endpoints Annotation on dialogs endpoint + canEdit logic fix namespace & botId check for annotation endpoints annotationId logic removal + doc & endpoint update Fix canEdit logic on updateAnnotation & updateAnnotationEvent [DERCBOT-1329] Support filtering for Annotations + refined Dialogs filters (#1845) * withAnnotations bool * [DERCBOT-1329] Fix annotation filter * Filter by annotation presence, by cumulative state, by cumulative reason * Sort by annotation lastUpdateDate * Filters addition * Filtering by dialog creationDate & sort by ASC/DESC order * FaqSettings files * Single POST endpoint for creation/update of an annotation * pr fix * Revert "FaqSettings files" This reverts commit 21fb259. * rollback on FaqSettings * rollback on FaqSettings V2 --------- Co-authored-by: Mohamed ASSOUKTI <mohamed.assoukti@partnre.com>
1 parent a6ea9c9 commit 3fdc6c9

File tree

34 files changed

+1724
-152
lines changed

34 files changed

+1724
-152
lines changed

bot/admin/server/src/main/kotlin/BotAdminService.kt

Lines changed: 242 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package ai.tock.bot.admin
1818

1919
import ai.tock.bot.admin.FaqAdminService.FAQ_CATEGORY
20+
import ai.tock.bot.admin.annotation.*
2021
import ai.tock.bot.admin.answer.AnswerConfiguration
2122
import ai.tock.bot.admin.answer.AnswerConfigurationType.builtin
2223
import ai.tock.bot.admin.answer.AnswerConfigurationType.script
@@ -46,6 +47,7 @@ import ai.tock.bot.admin.story.dump.*
4647
import ai.tock.bot.admin.user.UserReportDAO
4748
import ai.tock.bot.connector.ConnectorType
4849
import ai.tock.bot.definition.IntentWithoutNamespace
50+
import ai.tock.bot.engine.action.Action
4951
import ai.tock.bot.engine.config.SatisfactionIntent
5052
import ai.tock.bot.engine.dialog.Dialog
5153
import ai.tock.bot.engine.dialog.DialogFlowDAO
@@ -62,6 +64,7 @@ import ai.tock.nlp.front.shared.config.*
6264
import ai.tock.nlp.front.shared.config.ClassifiedSentenceStatus.model
6365
import ai.tock.nlp.front.shared.config.ClassifiedSentenceStatus.validated
6466
import ai.tock.shared.*
67+
import ai.tock.shared.exception.rest.NotFoundException
6568
import ai.tock.shared.security.UserLogin
6669
import ai.tock.shared.security.key.HasSecretKey
6770
import ai.tock.shared.security.key.SecretKey
@@ -70,6 +73,7 @@ import ai.tock.translator.*
7073
import com.github.salomonbrys.kodein.instance
7174
import mu.KotlinLogging
7275
import org.litote.kmongo.Id
76+
import org.litote.kmongo.newId
7377
import org.litote.kmongo.toId
7478
import java.time.Instant
7579
import java.util.*
@@ -149,6 +153,208 @@ object BotAdminService {
149153
}
150154
}
151155

156+
fun saveAnnotation(
157+
dialogId: String,
158+
actionId: String,
159+
annotationDTO: BotAnnotationDTO,
160+
user: String
161+
): BotAnnotation {
162+
return if (dialogReportDAO.annotationExists(dialogId, actionId)) {
163+
updateAnnotation(dialogId, actionId, annotationDTO, user)
164+
} else {
165+
createAnnotation(dialogId, actionId, annotationDTO, user)
166+
}
167+
}
168+
169+
private fun createAnnotation(
170+
dialogId: String,
171+
actionId: String,
172+
annotationDTO: BotAnnotationDTO,
173+
user: String
174+
): BotAnnotation {
175+
val annotation = BotAnnotation(
176+
state = annotationDTO.state,
177+
reason = annotationDTO.reason,
178+
description = annotationDTO.description,
179+
groundTruth = annotationDTO.groundTruth,
180+
events = mutableListOf(
181+
BotAnnotationEventState(
182+
eventId = newId(),
183+
creationDate = Instant.now(),
184+
lastUpdateDate = Instant.now(),
185+
user = user,
186+
before = null,
187+
after = annotationDTO.state.name
188+
)
189+
),
190+
lastUpdateDate = Instant.now()
191+
)
192+
193+
dialogReportDAO.insertAnnotation(dialogId, actionId, annotation)
194+
return annotation
195+
}
196+
197+
fun addCommentToAnnotation(
198+
dialogId: String,
199+
actionId: String,
200+
eventDTO: BotAnnotationEventDTO,
201+
user: String
202+
): BotAnnotationEvent {
203+
if (eventDTO.type != BotAnnotationEventType.COMMENT) {
204+
throw IllegalArgumentException("Only COMMENT events are allowed")
205+
}
206+
207+
require(!eventDTO.comment.isNullOrBlank()) { "Comment is required and cannot be blank for COMMENT event type" }
208+
209+
val annotation = dialogReportDAO.findAnnotation(dialogId, actionId)
210+
?: throw IllegalStateException("Annotation not found")
211+
212+
val event = BotAnnotationEventComment(
213+
eventId = newId(),
214+
creationDate = Instant.now(),
215+
lastUpdateDate = Instant.now(),
216+
user = user,
217+
comment = eventDTO.comment ?: throw IllegalArgumentException("Comment required")
218+
)
219+
220+
dialogReportDAO.addAnnotationEvent(dialogId, actionId, event)
221+
222+
return event.copy(canEdit = true)
223+
}
224+
225+
fun updateAnnotationEvent(
226+
dialogId: String,
227+
actionId: String,
228+
eventId: String,
229+
eventDTO: BotAnnotationEventDTO,
230+
user: String
231+
): BotAnnotationEvent {
232+
val existingEvent = dialogReportDAO.getAnnotationEvent(dialogId, actionId, eventId)
233+
?: throw IllegalArgumentException("Event not found")
234+
235+
if (existingEvent.type != BotAnnotationEventType.COMMENT) {
236+
throw IllegalArgumentException("Only comment events can be updated")
237+
}
238+
239+
if (eventDTO.type != BotAnnotationEventType.COMMENT) {
240+
throw IllegalArgumentException("Event type must be COMMENT")
241+
}
242+
243+
require(eventDTO.comment != null) { "Comment must be provided" }
244+
245+
val annotation = dialogReportDAO.findAnnotation(dialogId, actionId)
246+
?: throw IllegalStateException("Annotation not found")
247+
248+
val existingCommentEvent = existingEvent as BotAnnotationEventComment
249+
val updatedEvent = existingCommentEvent.copy(
250+
comment = eventDTO.comment!!,
251+
lastUpdateDate = Instant.now()
252+
)
253+
254+
dialogReportDAO.updateAnnotationEvent(dialogId, actionId, eventId, updatedEvent)
255+
256+
return updatedEvent.copy(canEdit = updatedEvent.user == user)
257+
}
258+
259+
fun deleteAnnotationEvent(
260+
dialogId: String,
261+
actionId: String,
262+
eventId: String,
263+
user: String
264+
) {
265+
val existingEvent = dialogReportDAO.getAnnotationEvent(dialogId, actionId, eventId)
266+
?: throw IllegalArgumentException("Event not found")
267+
268+
if (existingEvent.type != BotAnnotationEventType.COMMENT) {
269+
throw IllegalArgumentException("Only comment events can be deleted")
270+
}
271+
272+
dialogReportDAO.deleteAnnotationEvent(dialogId, actionId, eventId)
273+
}
274+
275+
fun updateAnnotation(
276+
dialogId: String,
277+
actionId: String,
278+
annotationDTO: BotAnnotationDTO,
279+
user: String
280+
): BotAnnotation {
281+
val existingAnnotation = dialogReportDAO.findAnnotation(dialogId, actionId)
282+
?: throw IllegalStateException("Annotation not found")
283+
284+
val events = mutableListOf<BotAnnotationEvent>()
285+
286+
if (existingAnnotation.state != annotationDTO.state) {
287+
events.add(
288+
BotAnnotationEventState(
289+
eventId = newId(),
290+
creationDate = Instant.now(),
291+
lastUpdateDate = Instant.now(),
292+
user = user,
293+
before = existingAnnotation.state.name,
294+
after = annotationDTO.state.name
295+
)
296+
)
297+
existingAnnotation.state = annotationDTO.state
298+
}
299+
300+
if (existingAnnotation.reason != annotationDTO.reason) {
301+
events.add(
302+
BotAnnotationEventReason(
303+
eventId = newId(),
304+
creationDate = Instant.now(),
305+
lastUpdateDate = Instant.now(),
306+
user = user,
307+
before = existingAnnotation.reason?.name,
308+
after = annotationDTO.reason?.name
309+
)
310+
)
311+
existingAnnotation.reason = annotationDTO.reason
312+
}
313+
314+
if (existingAnnotation.groundTruth != annotationDTO.groundTruth) {
315+
events.add(
316+
BotAnnotationEventGroundTruth(
317+
eventId = newId(),
318+
creationDate = Instant.now(),
319+
lastUpdateDate = Instant.now(),
320+
user = user,
321+
before = existingAnnotation.groundTruth,
322+
after = annotationDTO.groundTruth
323+
)
324+
)
325+
existingAnnotation.groundTruth = annotationDTO.groundTruth
326+
}
327+
328+
if (existingAnnotation.description != annotationDTO.description) {
329+
events.add(
330+
BotAnnotationEventDescription(
331+
eventId = newId(),
332+
creationDate = Instant.now(),
333+
lastUpdateDate = Instant.now(),
334+
user = user,
335+
before = existingAnnotation.description,
336+
after = annotationDTO.description
337+
)
338+
)
339+
existingAnnotation.description = annotationDTO.description
340+
}
341+
342+
existingAnnotation.lastUpdateDate = Instant.now()
343+
existingAnnotation.events.addAll(events)
344+
345+
dialogReportDAO.insertAnnotation(dialogId, actionId, existingAnnotation)
346+
347+
return existingAnnotation.copy(
348+
events = existingAnnotation.events.map { event ->
349+
if (event is BotAnnotationEventComment) {
350+
event.copy(canEdit = event.user == user)
351+
} else {
352+
event
353+
}
354+
}.toMutableList()
355+
)
356+
}
357+
152358
fun createOrGetIntent(
153359
namespace: String,
154360
intentName: String,
@@ -210,15 +416,47 @@ object BotAdminService {
210416
)
211417
}
212418
)
213-
}
214-
215-
// Add nlp stats
216-
searchResult.copy(
419+
}.copy(
217420
nlpStats = dialogReportDAO.getNlpStats(searchResult.dialogs.map { it.id }, query.namespace)
218421
)
219422
}
220423
}
221424

425+
fun searchWithCommentRights(query: DialogsSearchQuery, userLogin: String): DialogReportQueryResult {
426+
val result = search(query)
427+
return result.copy(
428+
dialogs = result.dialogs.map { dialog ->
429+
processAnnotationsForUser(dialog, userLogin)
430+
}
431+
)
432+
}
433+
434+
fun getDialogWithCommentRights(id: Id<Dialog>, userLogin: String): DialogReport? {
435+
return dialogReportDAO.getDialog(id)?.let { dialog ->
436+
processAnnotationsForUser(dialog, userLogin)
437+
}
438+
}
439+
440+
private fun processAnnotationsForUser(dialog: DialogReport, userLogin: String): DialogReport {
441+
return dialog.copy(
442+
actions = dialog.actions.map { action ->
443+
action.copy(
444+
annotation = action.annotation?.let { annotation ->
445+
annotation.copy(
446+
events = annotation.events.map { event ->
447+
if (event is BotAnnotationEventComment) {
448+
event.copy(canEdit = event.user == userLogin)
449+
} else {
450+
event
451+
}
452+
}.toMutableList()
453+
)
454+
}
455+
)
456+
}
457+
)
458+
}
459+
222460
fun getIntentsInDialogs(namespace: String,nlpModel : String) : Set<String>{
223461
return dialogReportDAO.intents(namespace,nlpModel)
224462
}

0 commit comments

Comments
 (0)