2
0

Stream bubble content if placed right after Op…

Closes #617
This commit is contained in:
Baptiste Arnaud
2023-07-19 11:20:44 +02:00
parent 6c540657a6
commit 3952ae2755
14 changed files with 231 additions and 34 deletions

View File

@@ -5145,6 +5145,9 @@
},
"additionalProperties": false
}
},
"displayStream": {
"type": "boolean"
}
},
"required": [

View File

@@ -1,12 +1,12 @@
import { ExecuteIntegrationResponse } from '@/features/chat/types'
import prisma from '@/lib/prisma'
import { SessionState } from '@typebot.io/schemas'
import { Block, BubbleBlockType, SessionState } from '@typebot.io/schemas'
import {
ChatCompletionOpenAIOptions,
OpenAICredentials,
chatCompletionMessageRoles,
} from '@typebot.io/schemas/features/blocks/integrations/openai'
import { isEmpty } from '@typebot.io/lib'
import { byId, isEmpty } from '@typebot.io/lib'
import { decrypt, isCredentialsV2 } from '@typebot.io/lib/api/encryption'
import { updateVariables } from '@/features/variables/updateVariables'
import { parseVariableNumber } from '@/features/variables/parseVariableNumber'
@@ -20,7 +20,12 @@ export const createChatCompletionOpenAI = async (
{
outgoingEdgeId,
options,
}: { outgoingEdgeId?: string; options: ChatCompletionOpenAIOptions }
blockId,
}: {
outgoingEdgeId?: string
options: ChatCompletionOpenAIOptions
blockId: string
}
): Promise<ExecuteIntegrationResponse> => {
let newSessionState = state
const noCredentialsError = {
@@ -60,7 +65,14 @@ export const createChatCompletionOpenAI = async (
isPlaneteScale() &&
isCredentialsV2(credentials) &&
newSessionState.isStreamEnabled
)
) {
const assistantMessageVariableName = state.typebot.variables.find(
(variable) =>
options.responseMapping.find(
(m) => m.valueToExtract === 'Message content'
)?.variableId === variable.id
)?.name
return {
clientSideActions: [
{
@@ -69,12 +81,17 @@ export const createChatCompletionOpenAI = async (
content?: string
role: (typeof chatCompletionMessageRoles)[number]
}[],
displayStream: isNextBubbleMessageWithAssistantMessage(
state.typebot
)(blockId, assistantMessageVariableName),
},
},
],
outgoingEdgeId,
newSessionState,
}
}
const { response, logs } = await executeChatCompletionOpenAIRequest({
apiKey,
messages,
@@ -98,3 +115,40 @@ export const createChatCompletionOpenAI = async (
logs,
})(messageContent, totalTokens)
}
const isNextBubbleMessageWithAssistantMessage =
(typebot: SessionState['typebot']) =>
(blockId: string, assistantVariableName?: string): boolean => {
if (!assistantVariableName) return false
const nextBlock = getNextBlock(typebot)(blockId)
if (!nextBlock) return false
return (
nextBlock.type === BubbleBlockType.TEXT &&
nextBlock.content.richText?.length > 0 &&
nextBlock.content.richText?.at(0)?.children.at(0).text ===
`{{${assistantVariableName}}}`
)
}
const getNextBlock =
(typebot: SessionState['typebot']) =>
(blockId: string): Block | undefined => {
const group = typebot.groups.find((group) =>
group.blocks.find(byId(blockId))
)
if (!group) return
const blockIndex = group.blocks.findIndex(byId(blockId))
const nextBlockInGroup = group.blocks.at(blockIndex + 1)
if (nextBlockInGroup) return nextBlockInGroup
const outgoingEdgeId = group.blocks.at(blockIndex)?.outgoingEdgeId
if (!outgoingEdgeId) return
const outgoingEdge = typebot.edges.find(byId(outgoingEdgeId))
if (!outgoingEdge) return
const connectedGroup = typebot.groups.find(byId(outgoingEdge?.to.groupId))
if (!connectedGroup) return
return outgoingEdge.to.blockId
? connectedGroup.blocks.find(
(block) => block.id === outgoingEdge.to.blockId
)
: connectedGroup?.blocks.at(0)
}

View File

@@ -12,6 +12,7 @@ export const executeOpenAIBlock = async (
return createChatCompletionOpenAI(state, {
options: block.options,
outgoingEdgeId: block.outgoingEdgeId,
blockId: block.id,
})
case 'Create image':
case undefined: