🐛 (openai) Fix 2 openai streaming back to back
This commit is contained in:
@ -39,6 +39,7 @@ export const continueBotFlow = async (
|
|||||||
reply: string | undefined,
|
reply: string | undefined,
|
||||||
{ state, version }: Params
|
{ state, version }: Params
|
||||||
): Promise<ChatReply & { newSessionState: SessionState }> => {
|
): Promise<ChatReply & { newSessionState: SessionState }> => {
|
||||||
|
let firstBubbleWasStreamed = false
|
||||||
let newSessionState = { ...state }
|
let newSessionState = { ...state }
|
||||||
|
|
||||||
if (!newSessionState.currentBlock) return startBotFlow({ state, version })
|
if (!newSessionState.currentBlock) return startBotFlow({ state, version })
|
||||||
@ -81,6 +82,7 @@ export const continueBotFlow = async (
|
|||||||
block.type === IntegrationBlockType.OPEN_AI &&
|
block.type === IntegrationBlockType.OPEN_AI &&
|
||||||
block.options.task === 'Create chat completion'
|
block.options.task === 'Create chat completion'
|
||||||
) {
|
) {
|
||||||
|
firstBubbleWasStreamed = true
|
||||||
if (reply) {
|
if (reply) {
|
||||||
const result = await resumeChatCompletion(state, {
|
const result = await resumeChatCompletion(state, {
|
||||||
options: block.options,
|
options: block.options,
|
||||||
@ -125,7 +127,7 @@ export const continueBotFlow = async (
|
|||||||
...group,
|
...group,
|
||||||
blocks: group.blocks.slice(blockIndex + 1),
|
blocks: group.blocks.slice(blockIndex + 1),
|
||||||
},
|
},
|
||||||
{ version, state: newSessionState }
|
{ version, state: newSessionState, firstBubbleWasStreamed }
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
...chatReply,
|
...chatReply,
|
||||||
@ -157,6 +159,7 @@ export const continueBotFlow = async (
|
|||||||
const chatReply = await executeGroup(nextGroup.group, {
|
const chatReply = await executeGroup(nextGroup.group, {
|
||||||
version,
|
version,
|
||||||
state: newSessionState,
|
state: newSessionState,
|
||||||
|
firstBubbleWasStreamed,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -29,11 +29,18 @@ type ContextProps = {
|
|||||||
state: SessionState
|
state: SessionState
|
||||||
currentReply?: ChatReply
|
currentReply?: ChatReply
|
||||||
currentLastBubbleId?: string
|
currentLastBubbleId?: string
|
||||||
|
firstBubbleWasStreamed?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const executeGroup = async (
|
export const executeGroup = async (
|
||||||
group: Group,
|
group: Group,
|
||||||
{ version, state, currentReply, currentLastBubbleId }: ContextProps
|
{
|
||||||
|
version,
|
||||||
|
state,
|
||||||
|
currentReply,
|
||||||
|
currentLastBubbleId,
|
||||||
|
firstBubbleWasStreamed,
|
||||||
|
}: ContextProps
|
||||||
): Promise<ChatReply & { newSessionState: SessionState }> => {
|
): Promise<ChatReply & { newSessionState: SessionState }> => {
|
||||||
const messages: ChatReply['messages'] = currentReply?.messages ?? []
|
const messages: ChatReply['messages'] = currentReply?.messages ?? []
|
||||||
let clientSideActions: ChatReply['clientSideActions'] =
|
let clientSideActions: ChatReply['clientSideActions'] =
|
||||||
@ -44,10 +51,13 @@ export const executeGroup = async (
|
|||||||
|
|
||||||
let newSessionState = state
|
let newSessionState = state
|
||||||
|
|
||||||
|
let index = -1
|
||||||
for (const block of group.blocks) {
|
for (const block of group.blocks) {
|
||||||
|
index++
|
||||||
nextEdgeId = block.outgoingEdgeId
|
nextEdgeId = block.outgoingEdgeId
|
||||||
|
|
||||||
if (isBubbleBlock(block)) {
|
if (isBubbleBlock(block)) {
|
||||||
|
if (firstBubbleWasStreamed && index === 0) continue
|
||||||
messages.push(
|
messages.push(
|
||||||
parseBubbleBlock(block, {
|
parseBubbleBlock(block, {
|
||||||
version,
|
version,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/js",
|
"name": "@typebot.io/js",
|
||||||
"version": "0.2.5",
|
"version": "0.2.6",
|
||||||
"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",
|
||||||
|
@ -3,7 +3,6 @@ import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/enums
|
|||||||
import {
|
import {
|
||||||
createEffect,
|
createEffect,
|
||||||
createSignal,
|
createSignal,
|
||||||
createUniqueId,
|
|
||||||
For,
|
For,
|
||||||
onCleanup,
|
onCleanup,
|
||||||
onMount,
|
onMount,
|
||||||
@ -109,12 +108,11 @@ export const ConversationContainer = (props: Props) => {
|
|||||||
})()
|
})()
|
||||||
})
|
})
|
||||||
|
|
||||||
const streamMessage = (content: string) => {
|
const streamMessage = ({ id, message }: { id: string; message: string }) => {
|
||||||
setIsSending(false)
|
setIsSending(false)
|
||||||
const lastChunk = [...chatChunks()].pop()
|
const lastChunk = [...chatChunks()].pop()
|
||||||
if (!lastChunk) return
|
if (!lastChunk) return
|
||||||
const id = lastChunk.streamingMessageId ?? createUniqueId()
|
if (lastChunk.streamingMessageId !== id)
|
||||||
if (!lastChunk.streamingMessageId)
|
|
||||||
setChatChunks((displayedChunks) => [
|
setChatChunks((displayedChunks) => [
|
||||||
...displayedChunks,
|
...displayedChunks,
|
||||||
{
|
{
|
||||||
@ -122,7 +120,7 @@ export const ConversationContainer = (props: Props) => {
|
|||||||
streamingMessageId: id,
|
streamingMessageId: id,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
setStreamingMessage({ id, content })
|
setStreamingMessage({ id, content: message })
|
||||||
}
|
}
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
@ -216,9 +214,7 @@ export const ConversationContainer = (props: Props) => {
|
|||||||
...displayedChunks,
|
...displayedChunks,
|
||||||
{
|
{
|
||||||
input: data.input,
|
input: data.input,
|
||||||
messages: [...chatChunks()].pop()?.streamingMessageId
|
messages: data.messages,
|
||||||
? data.messages.slice(1)
|
|
||||||
: data.messages,
|
|
||||||
clientSideActions: data.clientSideActions,
|
clientSideActions: data.clientSideActions,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { ClientSideActionContext } from '@/types'
|
import { ClientSideActionContext } from '@/types'
|
||||||
import { guessApiHost } from '@/utils/guessApiHost'
|
import { guessApiHost } from '@/utils/guessApiHost'
|
||||||
import { isNotEmpty } from '@typebot.io/lib/utils'
|
import { isNotEmpty } from '@typebot.io/lib/utils'
|
||||||
|
import { createUniqueId } from 'solid-js'
|
||||||
|
|
||||||
let abortController: AbortController | null = null
|
let abortController: AbortController | null = null
|
||||||
const secondsToWaitBeforeRetries = 3
|
const secondsToWaitBeforeRetries = 3
|
||||||
@ -13,7 +14,9 @@ export const streamChat =
|
|||||||
content?: string | undefined
|
content?: string | undefined
|
||||||
role?: 'system' | 'user' | 'assistant' | undefined
|
role?: 'system' | 'user' | 'assistant' | undefined
|
||||||
}[],
|
}[],
|
||||||
{ onMessageStream }: { onMessageStream?: (message: string) => void }
|
{
|
||||||
|
onMessageStream,
|
||||||
|
}: { onMessageStream?: (props: { id: string; message: string }) => void }
|
||||||
): Promise<{ message?: string; error?: object }> => {
|
): Promise<{ message?: string; error?: object }> => {
|
||||||
try {
|
try {
|
||||||
abortController = new AbortController()
|
abortController = new AbortController()
|
||||||
@ -64,6 +67,8 @@ export const streamChat =
|
|||||||
const reader = res.body.getReader()
|
const reader = res.body.getReader()
|
||||||
const decoder = new TextDecoder()
|
const decoder = new TextDecoder()
|
||||||
|
|
||||||
|
const id = createUniqueId()
|
||||||
|
|
||||||
// eslint-disable-next-line no-constant-condition
|
// eslint-disable-next-line no-constant-condition
|
||||||
while (true) {
|
while (true) {
|
||||||
const { done, value } = await reader.read()
|
const { done, value } = await reader.read()
|
||||||
@ -72,7 +77,7 @@ export const streamChat =
|
|||||||
}
|
}
|
||||||
const chunk = decoder.decode(value)
|
const chunk = decoder.decode(value)
|
||||||
message += chunk
|
message += chunk
|
||||||
if (onMessageStream) onMessageStream(message)
|
if (onMessageStream) onMessageStream({ id, message })
|
||||||
if (abortController === null) {
|
if (abortController === null) {
|
||||||
reader.cancel()
|
reader.cancel()
|
||||||
break
|
break
|
||||||
|
@ -14,7 +14,7 @@ import { injectStartProps } from './injectStartProps'
|
|||||||
type Props = {
|
type Props = {
|
||||||
clientSideAction: NonNullable<ChatReply['clientSideActions']>[0]
|
clientSideAction: NonNullable<ChatReply['clientSideActions']>[0]
|
||||||
context: ClientSideActionContext
|
context: ClientSideActionContext
|
||||||
onMessageStream?: (message: string) => void
|
onMessageStream?: (props: { id: string; message: string }) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const executeClientSideAction = async ({
|
export const executeClientSideAction = async ({
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/nextjs",
|
"name": "@typebot.io/nextjs",
|
||||||
"version": "0.2.5",
|
"version": "0.2.6",
|
||||||
"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",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/react",
|
"name": "@typebot.io/react",
|
||||||
"version": "0.2.5",
|
"version": "0.2.6",
|
||||||
"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",
|
||||||
|
Reference in New Issue
Block a user