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, ConversationalExtension,
EngineManager, EngineManager,
ToolManager, ToolManager,
ChatCompletionMessage,
} from '@janhq/core' } from '@janhq/core'
import { extractInferenceParams, extractModelLoadParams } from '@janhq/core' import { extractInferenceParams, extractModelLoadParams } from '@janhq/core'
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai' import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai'
@ -21,7 +20,6 @@ import {
fileUploadAtom, fileUploadAtom,
} from '@/containers/Providers/Jotai' } from '@/containers/Providers/Jotai'
import { Stack } from '@/utils/Stack'
import { compressImage, getBase64 } from '@/utils/base64' import { compressImage, getBase64 } from '@/utils/base64'
import { MessageRequestBuilder } from '@/utils/messageRequestBuilder' import { MessageRequestBuilder } from '@/utils/messageRequestBuilder'
@ -86,33 +84,6 @@ export default function useSendChatMessage() {
selectedModelRef.current = selectedModel selectedModelRef.current = selectedModel
}, [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) => { const resendChatMessage = async (currentMessage: ThreadMessage) => {
// Delete last response before regenerating // Delete last response before regenerating
const newConvoData = currentMessages const newConvoData = currentMessages
@ -247,7 +218,6 @@ export default function useSendChatMessage() {
(assistant) => assistant.tools ?? [] (assistant) => assistant.tools ?? []
) ?? [] ) ?? []
) )
request.messages = normalizeMessages(request.messages ?? [])
// Request for inference // Request for inference
EngineManager.instance() EngineManager.instance()

View File

@ -15,6 +15,8 @@ import { ulid } from 'ulidx'
import { FileType } from '@/containers/Providers/Jotai' import { FileType } from '@/containers/Providers/Jotai'
import { Stack } from '@/utils/Stack'
export class MessageRequestBuilder { export class MessageRequestBuilder {
msgId: string msgId: string
type: MessageRequestType type: MessageRequestType
@ -36,7 +38,7 @@ export class MessageRequestBuilder {
.filter((e) => e.status !== MessageStatus.Error) .filter((e) => e.status !== MessageStatus.Error)
.map<ChatCompletionMessage>((msg) => ({ .map<ChatCompletionMessage>((msg) => ({
role: msg.role, role: msg.role,
content: msg.content[0]?.text.value ?? '', content: msg.content[0]?.text.value ?? '.',
})) }))
} }
@ -130,12 +132,39 @@ export class MessageRequestBuilder {
return this 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 { build(): MessageRequest {
return { return {
id: this.msgId, id: this.msgId,
type: this.type, type: this.type,
threadId: this.thread.id, threadId: this.thread.id,
messages: this.messages, messages: this.normalizeMessages(this.messages),
model: this.model, model: this.model,
thread: this.thread, thread: this.thread,
} }