Files
Flowise/packages/server/src/utils/getChatMessage.ts
T
Henry Heng 7924fbce0d Feature/agentflow v2 (#4298)
* agent flow v2

* chat message background

* conditon agent flow

* add sticky note

* update human input dynamic prompt

* add HTTP node

* add default tool icon

* fix export duplicate agentflow v2

* add agentflow v2 marketplaces

* refractor memoization, add iteration nodes

* add agentflow v2 templates

* add agentflow generator

* add migration scripts for mysql, mariadb, posrgres and fix date filters for executions

* update agentflow chat history config

* fix get all flows error after deletion and rename

* add previous nodes from parent node

* update generator prompt

* update run time state when using iteration nodes

* prevent looping connection, prevent duplication of start node, add executeflow node, add nodes agentflow, chat history variable

* update embed

* convert form input to string

* bump openai version

* add react rewards

* add prompt generator to prediction queue

* add array schema to overrideconfig

* UI touchup

* update embedded chat version

* fix node info dialog

* update start node and loop default iteration

* update UI fixes for agentflow v2

* fix async drop down

* add export import to agentflowsv2, executions, fix UI bugs

* add default empty object to flowlisttable

* add ability to share trace link publicly, allow MCP tool use for Agent and Assistant

* add runtime message length to variable, display conditions on UI

* fix array validation

* add ability to add knowledge from vector store and embeddings for agent

* add agent tool require human input

* add ephemeral memory to start node

* update agent flow node to show vs and embeddings icons

* feat: add import chat data functionality for AgentFlowV2

* feat: set chatMessage.executionId to null if not found in import JSON file or database

* fix: MariaDB execution migration script to utf8mb4_unicode_520_ci

---------

Co-authored-by: Ong Chung Yau <33013947+chungyau97@users.noreply.github.com>
Co-authored-by: chungyau97 <chungyau97@gmail.com>
2025-05-10 10:21:26 +08:00

133 lines
4.6 KiB
TypeScript

import { MoreThanOrEqual, LessThanOrEqual, Between, In } from 'typeorm'
import { ChatMessageRatingType, ChatType } from '../Interface'
import { ChatMessage } from '../database/entities/ChatMessage'
import { ChatMessageFeedback } from '../database/entities/ChatMessageFeedback'
import { getRunningExpressApp } from '../utils/getRunningExpressApp'
import { aMonthAgo } from '.'
/**
* Method that get chat messages.
* @param {string} chatflowid
* @param {ChatType[]} chatTypes
* @param {string} sortOrder
* @param {string} chatId
* @param {string} memoryType
* @param {string} sessionId
* @param {string} startDate
* @param {string} endDate
* @param {boolean} feedback
* @param {ChatMessageRatingType[]} feedbackTypes
*/
interface GetChatMessageParams {
chatflowid: string
chatTypes?: ChatType[]
sortOrder?: string
chatId?: string
memoryType?: string
sessionId?: string
startDate?: string
endDate?: string
messageId?: string
feedback?: boolean
feedbackTypes?: ChatMessageRatingType[]
}
export const utilGetChatMessage = async ({
chatflowid,
chatTypes,
sortOrder = 'ASC',
chatId,
memoryType,
sessionId,
startDate,
endDate,
messageId,
feedback,
feedbackTypes
}: GetChatMessageParams): Promise<ChatMessage[]> => {
const appServer = getRunningExpressApp()
if (feedback) {
const query = await appServer.AppDataSource.getRepository(ChatMessage).createQueryBuilder('chat_message')
// do the join with chat message feedback based on messageId for each chat message in the chatflow
query
.leftJoinAndSelect('chat_message.execution', 'execution')
.leftJoinAndMapOne('chat_message.feedback', ChatMessageFeedback, 'feedback', 'feedback.messageId = chat_message.id')
.where('chat_message.chatflowid = :chatflowid', { chatflowid })
// based on which parameters are available add `andWhere` clauses to the query
if (chatTypes && chatTypes.length > 0) {
query.andWhere('chat_message.chatType IN (:...chatTypes)', { chatTypes })
}
if (chatId) {
query.andWhere('chat_message.chatId = :chatId', { chatId })
}
if (memoryType) {
query.andWhere('chat_message.memoryType = :memoryType', { memoryType })
}
if (sessionId) {
query.andWhere('chat_message.sessionId = :sessionId', { sessionId })
}
// set date range
if (startDate) {
query.andWhere('chat_message.createdDate >= :startDateTime', { startDateTime: startDate ? new Date(startDate) : aMonthAgo() })
}
if (endDate) {
query.andWhere('chat_message.createdDate <= :endDateTime', { endDateTime: endDate ? new Date(endDate) : new Date() })
}
// sort
query.orderBy('chat_message.createdDate', sortOrder === 'DESC' ? 'DESC' : 'ASC')
const messages = (await query.getMany()) as Array<ChatMessage & { feedback: ChatMessageFeedback }>
if (feedbackTypes && feedbackTypes.length > 0) {
// just applying a filter to the messages array will only return the messages that have feedback,
// but we also want the message before the feedback message which is the user message.
const indicesToKeep = new Set()
messages.forEach((message, index) => {
if (message.role === 'apiMessage' && message.feedback && feedbackTypes.includes(message.feedback.rating)) {
if (index > 0) indicesToKeep.add(index - 1)
indicesToKeep.add(index)
}
})
return messages.filter((_, index) => indicesToKeep.has(index))
}
return messages
}
let createdDateQuery
if (startDate || endDate) {
if (startDate && endDate) {
createdDateQuery = Between(new Date(startDate), new Date(endDate))
} else if (startDate) {
createdDateQuery = MoreThanOrEqual(new Date(startDate))
} else if (endDate) {
createdDateQuery = LessThanOrEqual(new Date(endDate))
}
}
return await appServer.AppDataSource.getRepository(ChatMessage).find({
where: {
chatflowid,
chatType: chatTypes?.length ? In(chatTypes) : undefined,
chatId,
memoryType: memoryType ?? undefined,
sessionId: sessionId ?? undefined,
createdDate: createdDateQuery,
id: messageId ?? undefined
},
relations: {
execution: true
},
order: {
createdDate: sortOrder === 'DESC' ? 'DESC' : 'ASC'
}
})
}