Merge pull request #4199 from janhq/fix/4165-refactor-message-builder-to-avoid-sending-empty-messages

fix: 4165 - Refactor message builder to avoid sending empty messages
This commit is contained in:
Louis 2024-12-03 16:27:53 +07:00 committed by GitHub
commit 7f62e84096
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 31 additions and 32 deletions

View File

@ -10,7 +10,6 @@ import {
ConversationalExtension,
EngineManager,
ToolManager,
ChatCompletionMessage,
} from '@janhq/core'
import { extractInferenceParams, extractModelLoadParams } from '@janhq/core'
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai'
@ -21,7 +20,6 @@ import {
fileUploadAtom,
} from '@/containers/Providers/Jotai'
import { Stack } from '@/utils/Stack'
import { compressImage, getBase64 } from '@/utils/base64'
import { MessageRequestBuilder } from '@/utils/messageRequestBuilder'
@ -86,33 +84,6 @@ export default function useSendChatMessage() {
selectedModelRef.current = selectedModel
}, [selectedModel])
const normalizeMessages = (
messages: ChatCompletionMessage[]
): ChatCompletionMessage[] => {
const stack = new Stack<ChatCompletionMessage>()
for (const message of messages) {
if (stack.isEmpty()) {
stack.push(message)
continue
}
const topMessage = stack.peek()
if (message.role === topMessage.role) {
// add an empty message
stack.push({
role:
topMessage.role === ChatCompletionRole.User
? ChatCompletionRole.Assistant
: ChatCompletionRole.User,
content: '.', // some model requires not empty message
})
}
stack.push(message)
}
return stack.reverseOutput()
}
const resendChatMessage = async (currentMessage: ThreadMessage) => {
// Delete last response before regenerating
const newConvoData = currentMessages
@ -247,7 +218,6 @@ export default function useSendChatMessage() {
(assistant) => assistant.tools ?? []
) ?? []
)
request.messages = normalizeMessages(request.messages ?? [])
// Request for inference
EngineManager.instance()

View File

@ -15,6 +15,8 @@ import { ulid } from 'ulidx'
import { FileType } from '@/containers/Providers/Jotai'
import { Stack } from '@/utils/Stack'
export class MessageRequestBuilder {
msgId: string
type: MessageRequestType
@ -36,7 +38,7 @@ export class MessageRequestBuilder {
.filter((e) => e.status !== MessageStatus.Error)
.map<ChatCompletionMessage>((msg) => ({
role: msg.role,
content: msg.content[0]?.text.value ?? '',
content: msg.content[0]?.text.value ?? '.',
}))
}
@ -130,12 +132,39 @@ export class MessageRequestBuilder {
return this
}
normalizeMessages = (
messages: ChatCompletionMessage[]
): ChatCompletionMessage[] => {
const stack = new Stack<ChatCompletionMessage>()
for (const message of messages) {
if (stack.isEmpty()) {
stack.push(message)
continue
}
const topMessage = stack.peek()
if (message.role === topMessage.role) {
// add an empty message
stack.push({
role:
topMessage.role === ChatCompletionRole.User
? ChatCompletionRole.Assistant
: ChatCompletionRole.User,
content: '.', // some model requires not empty message
})
}
stack.push(message)
}
return stack.reverseOutput()
}
build(): MessageRequest {
return {
id: this.msgId,
type: this.type,
threadId: this.thread.id,
messages: this.messages,
messages: this.normalizeMessages(this.messages),
model: this.model,
thread: this.thread,
}