2
0

🚸 (openai) Improve streaming bubble sequence and visual

This commit is contained in:
Baptiste Arnaud
2023-10-09 11:30:51 +02:00
parent 8eb9f2568b
commit 49826d1303
10 changed files with 69 additions and 25 deletions

View File

@ -72,19 +72,23 @@ export const createChatCompletionOpenAI = async (
options.advancedSettings?.temperature options.advancedSettings?.temperature
) )
const assistantMessageVariableName = typebot.variables.find(
(variable) =>
options.responseMapping.find(
(m) => m.valueToExtract === 'Message content'
)?.variableId === variable.id
)?.name
if ( if (
isPlaneteScale() && isPlaneteScale() &&
isCredentialsV2(credentials) && isCredentialsV2(credentials) &&
newSessionState.isStreamEnabled && newSessionState.isStreamEnabled &&
!newSessionState.whatsApp !newSessionState.whatsApp &&
isNextBubbleMessageWithAssistantMessage(typebot)(
blockId,
assistantMessageVariableName
)
) { ) {
const assistantMessageVariableName = typebot.variables.find(
(variable) =>
options.responseMapping.find(
(m) => m.valueToExtract === 'Message content'
)?.variableId === variable.id
)?.name
return { return {
clientSideActions: [ clientSideActions: [
{ {
@ -93,10 +97,6 @@ export const createChatCompletionOpenAI = async (
content?: string content?: string
role: (typeof chatCompletionMessageRoles)[number] role: (typeof chatCompletionMessageRoles)[number]
}[], }[],
displayStream: isNextBubbleMessageWithAssistantMessage(typebot)(
blockId,
assistantMessageVariableName
),
}, },
expectsDedicatedReply: true, expectsDedicatedReply: true,
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/js", "name": "@typebot.io/js",
"version": "0.2.3", "version": "0.2.4",
"description": "Javascript library to display typebots on your website", "description": "Javascript library to display typebots on your website",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",

View File

@ -117,7 +117,9 @@ export const ChatChunk = (props: Props) => {
<div <div
class="flex flex-col flex-1 gap-2" class="flex flex-col flex-1 gap-2"
style={{ style={{
width: isMobile() ? 'calc(100% - 32px)' : 'calc(100% - 48px)', 'max-width': isMobile()
? 'calc(100% - 32px)'
: 'calc(100% - 48px)',
'margin-right': props.theme.chat.guestAvatar?.isEnabled 'margin-right': props.theme.chat.guestAvatar?.isEnabled
? isMobile() ? isMobile()
? '32px' ? '32px'

View File

@ -297,8 +297,9 @@ export const ConversationContainer = (props: Props) => {
context={props.context} context={props.context}
hideAvatar={ hideAvatar={
!chatChunk.input && !chatChunk.input &&
!chatChunk.streamingMessageId && ((chatChunks()[index() + 1]?.messages ?? 0).length > 0 ||
index() < chatChunks().length - 1 chatChunks()[index() + 1]?.streamingMessageId !== undefined ||
isSending())
} }
hasError={hasError() && index() === chatChunks().length - 1} hasError={hasError() && index() === chatChunks().length - 1}
onNewBubbleDisplayed={handleNewBubbleDisplayed} onNewBubbleDisplayed={handleNewBubbleDisplayed}

View File

@ -28,7 +28,7 @@ export const StreamingBubble = (props: Props) => {
return ( return (
<div class="flex flex-col animate-fade-in"> <div class="flex flex-col animate-fade-in">
<div class="flex w-full items-center"> <div class="flex w-full items-center">
<div class="flex relative items-start typebot-host-bubble w-full"> <div class="flex relative items-start typebot-host-bubble max-w-full">
<div <div
class="flex items-center absolute px-4 py-2 bubble-typing " class="flex items-center absolute px-4 py-2 bubble-typing "
style={{ style={{

View File

@ -39,7 +39,52 @@ export const PlateElement = (props: Props) => (
</For> </For>
</a> </a>
</Match> </Match>
<Match when={props.element.type !== 'a'}> <Match when={props.element.type === 'ol'}>
<ol>
<For each={props.element.children as TDescendant[]}>
{(child) => (
<PlateElement
element={child}
isUniqueChild={
(props.element.children as TDescendant[])?.length === 1
}
inElement={true}
/>
)}
</For>
</ol>
</Match>
<Match when={props.element.type === 'ul'}>
<ul>
<For each={props.element.children as TDescendant[]}>
{(child) => (
<PlateElement
element={child}
isUniqueChild={
(props.element.children as TDescendant[])?.length === 1
}
inElement={true}
/>
)}
</For>
</ul>
</Match>
<Match when={props.element.type === 'li'}>
<li>
<For each={props.element.children as TDescendant[]}>
{(child) => (
<PlateElement
element={child}
isUniqueChild={
(props.element.children as TDescendant[])?.length === 1
}
inElement={true}
/>
)}
</For>
</li>
</Match>
<Match when={true}>
<ElementRoot <ElementRoot
element={props.element as TElement} element={props.element as TElement}
inElement={props.inElement ?? false} inElement={props.inElement ?? false}

View File

@ -51,10 +51,7 @@ export const executeClientSideAction = async ({
const { error, message } = await streamChat(context)( const { error, message } = await streamChat(context)(
clientSideAction.streamOpenAiChatCompletion.messages, clientSideAction.streamOpenAiChatCompletion.messages,
{ {
onMessageStream: clientSideAction.streamOpenAiChatCompletion onMessageStream,
.displayStream
? onMessageStream
: undefined,
} }
) )
if (error) if (error)

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/nextjs", "name": "@typebot.io/nextjs",
"version": "0.2.3", "version": "0.2.4",
"description": "Convenient library to display typebots on your Next.js website", "description": "Convenient library to display typebots on your Next.js website",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/react", "name": "@typebot.io/react",
"version": "0.2.3", "version": "0.2.4",
"description": "Convenient library to display typebots on your React app", "description": "Convenient library to display typebots on your React app",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",

View File

@ -218,7 +218,6 @@ const clientSideActionSchema = z
messages: z.array( messages: z.array(
chatCompletionMessageSchema.pick({ content: true, role: true }) chatCompletionMessageSchema.pick({ content: true, role: true })
), ),
displayStream: z.boolean().optional(),
}), }),
}) })
) )