mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 11:00:55 +03:00
Fix merge conflicts
This commit is contained in:
@@ -6,6 +6,11 @@ export enum chatType {
|
||||
INTERNAL = 'INTERNAL',
|
||||
EXTERNAL = 'EXTERNAL'
|
||||
}
|
||||
|
||||
export enum ChatMessageRatingType {
|
||||
THUMBS_UP = 'THUMBS_UP',
|
||||
THUMBS_DOWN = 'THUMBS_DOWN'
|
||||
}
|
||||
/**
|
||||
* Databases
|
||||
*/
|
||||
@@ -39,6 +44,16 @@ export interface IChatMessage {
|
||||
createdDate: Date
|
||||
}
|
||||
|
||||
export interface IChatMessageFeedback {
|
||||
id: string
|
||||
content?: string
|
||||
chatflowid: string
|
||||
chatId: string
|
||||
messageId: string
|
||||
rating: ChatMessageRatingType
|
||||
createdDate: Date
|
||||
}
|
||||
|
||||
export interface ITool {
|
||||
id: string
|
||||
name: string
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/* eslint-disable */
|
||||
import { Entity, Column, CreateDateColumn, PrimaryGeneratedColumn, Index, Unique } from 'typeorm'
|
||||
import { IChatMessageFeedback, ChatMessageRatingType } from '../../Interface'
|
||||
|
||||
@Entity()
|
||||
@Unique(['messageId'])
|
||||
export class ChatMessageFeedback implements IChatMessageFeedback {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string
|
||||
|
||||
@Index()
|
||||
@Column()
|
||||
chatflowid: string
|
||||
|
||||
@Index()
|
||||
@Column()
|
||||
chatId: string
|
||||
|
||||
@Column()
|
||||
messageId: string
|
||||
|
||||
@Column({ nullable: true })
|
||||
rating: ChatMessageRatingType
|
||||
|
||||
@Column({ nullable: true, type: 'text' })
|
||||
content?: string
|
||||
|
||||
@CreateDateColumn()
|
||||
createdDate: Date
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ChatFlow } from './ChatFlow'
|
||||
import { ChatMessage } from './ChatMessage'
|
||||
import { ChatMessageFeedback } from './ChatMessageFeedback'
|
||||
import { Credential } from './Credential'
|
||||
import { Tool } from './Tool'
|
||||
import { Assistant } from './Assistant'
|
||||
@@ -8,6 +9,7 @@ import { Variable } from './Variable'
|
||||
export const entities = {
|
||||
ChatFlow,
|
||||
ChatMessage,
|
||||
ChatMessageFeedback,
|
||||
Credential,
|
||||
Tool,
|
||||
Assistant,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddFeedback1707213626553 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS \`chat_message_feedback\` (
|
||||
\`id\` varchar(36) NOT NULL,
|
||||
\`chatflowid\` varchar(255) NOT NULL,
|
||||
\`content\` text,
|
||||
\`chatId\` varchar(255) NOT NULL,
|
||||
\`messageId\` varchar(255) NOT NULL,
|
||||
\`rating\` varchar(255) NOT NULL,
|
||||
\`createdDate\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (\`id\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE chat_message_feedback`)
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { AddFileAnnotationsToChatMessage1700271021237 } from './1700271021237-Ad
|
||||
import { AddFileUploadsToChatMessage1701788586491 } from './1701788586491-AddFileUploadsToChatMessage'
|
||||
import { AddVariableEntity1699325775451 } from './1702200925471-AddVariableEntity'
|
||||
import { AddSpeechToText1706364937060 } from './1706364937060-AddSpeechToText'
|
||||
import { AddFeedback1707213626553 } from './1707213626553-AddFeedback'
|
||||
|
||||
export const mysqlMigrations = [
|
||||
Init1693840429259,
|
||||
@@ -29,5 +30,6 @@ export const mysqlMigrations = [
|
||||
AddFileAnnotationsToChatMessage1700271021237,
|
||||
AddFileUploadsToChatMessage1701788586491,
|
||||
AddVariableEntity1699325775451,
|
||||
AddSpeechToText1706364937060
|
||||
AddSpeechToText1706364937060,
|
||||
AddFeedback1707213626553
|
||||
]
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddFeedback1707213601923 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS chat_message_feedback (
|
||||
id uuid NOT NULL DEFAULT uuid_generate_v4(),
|
||||
"chatflowid" varchar NOT NULL,
|
||||
"content" text,
|
||||
"chatId" varchar NOT NULL,
|
||||
"messageId" varchar NOT NULL,
|
||||
"rating" varchar NOT NULL,
|
||||
"createdDate" timestamp NOT NULL DEFAULT now(),
|
||||
CONSTRAINT "PK_98419043dd704f54-9830ab78f8" PRIMARY KEY (id)
|
||||
);`
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE chat_message_feedback`)
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { AddFileAnnotationsToChatMessage1700271021237 } from './1700271021237-Ad
|
||||
import { AddFileUploadsToChatMessage1701788586491 } from './1701788586491-AddFileUploadsToChatMessage'
|
||||
import { AddVariableEntity1699325775451 } from './1702200925471-AddVariableEntity'
|
||||
import { AddSpeechToText1706364937060 } from './1706364937060-AddSpeechToText'
|
||||
import { AddFeedback1707213601923 } from './1707213601923-AddFeedback'
|
||||
|
||||
export const postgresMigrations = [
|
||||
Init1693891895163,
|
||||
@@ -29,5 +30,6 @@ export const postgresMigrations = [
|
||||
AddFileAnnotationsToChatMessage1700271021237,
|
||||
AddFileUploadsToChatMessage1701788586491,
|
||||
AddVariableEntity1699325775451,
|
||||
AddSpeechToText1706364937060
|
||||
AddSpeechToText1706364937060,
|
||||
AddFeedback1707213601923
|
||||
]
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class AddFeedback1707213619308 implements MigrationInterface {
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE IF NOT EXISTS "chat_message_feedback" ("id" varchar PRIMARY KEY NOT NULL, "chatflowid" varchar NOT NULL, "chatId" varchar NOT NULL, "messageId" varchar NOT NULL, "rating" varchar NOT NULL, "content" text, "createdDate" datetime NOT NULL DEFAULT (datetime('now')));`
|
||||
)
|
||||
await queryRunner.query(`CREATE INDEX IF NOT EXISTS "IDX_e574527322272fd838f4f0f3d3" ON "chat_message_feedback" ("chatflowid") ;`)
|
||||
await queryRunner.query(`CREATE INDEX IF NOT EXISTS "IDX_e574527322272fd838f4f0f3d3" ON "chat_message_feedback" ("chatId") ;`)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP TABLE IF EXISTS "chat_message_feedback";`)
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import { AddFileAnnotationsToChatMessage1700271021237 } from './1700271021237-Ad
|
||||
import { AddFileUploadsToChatMessage1701788586491 } from './1701788586491-AddFileUploadsToChatMessage'
|
||||
import { AddVariableEntity1699325775451 } from './1702200925471-AddVariableEntity'
|
||||
import { AddSpeechToText1706364937060 } from './1706364937060-AddSpeechToText'
|
||||
import { AddFeedback1707213619308 } from './1707213619308-AddFeedback'
|
||||
|
||||
export const sqliteMigrations = [
|
||||
Init1693835579790,
|
||||
@@ -29,5 +30,6 @@ export const sqliteMigrations = [
|
||||
AddFileAnnotationsToChatMessage1700271021237,
|
||||
AddFileUploadsToChatMessage1701788586491,
|
||||
AddVariableEntity1699325775451,
|
||||
AddSpeechToText1706364937060
|
||||
AddSpeechToText1706364937060,
|
||||
AddFeedback1707213619308
|
||||
]
|
||||
|
||||
@@ -11,7 +11,7 @@ import logger from './utils/logger'
|
||||
import { expressRequestLogger } from './utils/logger'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import OpenAI from 'openai'
|
||||
import { FindOptionsWhere, MoreThanOrEqual, LessThanOrEqual } from 'typeorm'
|
||||
import { FindOptionsWhere, MoreThanOrEqual, LessThanOrEqual, Between } from 'typeorm'
|
||||
import {
|
||||
IChatFlow,
|
||||
IncomingInput,
|
||||
@@ -21,8 +21,10 @@ import {
|
||||
ICredentialReturnResponse,
|
||||
chatType,
|
||||
IChatMessage,
|
||||
IChatMessageFeedback,
|
||||
IDepthQueue,
|
||||
INodeDirectedGraph,
|
||||
ChatMessageRatingType,
|
||||
IUploadFileSizeAndTypes
|
||||
} from './Interface'
|
||||
import {
|
||||
@@ -57,6 +59,7 @@ import { getDataSource } from './DataSource'
|
||||
import { NodesPool } from './NodesPool'
|
||||
import { ChatFlow } from './database/entities/ChatFlow'
|
||||
import { ChatMessage } from './database/entities/ChatMessage'
|
||||
import { ChatMessageFeedback } from './database/entities/ChatMessageFeedback'
|
||||
import { Credential } from './database/entities/Credential'
|
||||
import { Tool } from './database/entities/Tool'
|
||||
import { Assistant } from './database/entities/Assistant'
|
||||
@@ -184,6 +187,7 @@ export class App {
|
||||
'/api/v1/chatflows-streaming',
|
||||
'/api/v1/chatflows-uploads',
|
||||
'/api/v1/openai-assistants-file',
|
||||
'/api/v1/feedback',
|
||||
'/api/v1/get-upload-file',
|
||||
'/api/v1/ip'
|
||||
]
|
||||
@@ -556,6 +560,7 @@ export class App {
|
||||
const messageId = req.query?.messageId as string | undefined
|
||||
const startDate = req.query?.startDate as string | undefined
|
||||
const endDate = req.query?.endDate as string | undefined
|
||||
const feedback = req.query?.feedback as boolean | undefined
|
||||
let chatTypeFilter = req.query?.chatType as chatType | undefined
|
||||
|
||||
if (chatTypeFilter) {
|
||||
@@ -582,7 +587,8 @@ export class App {
|
||||
sessionId,
|
||||
startDate,
|
||||
endDate,
|
||||
messageId
|
||||
messageId,
|
||||
feedback
|
||||
)
|
||||
return res.json(chatmessages)
|
||||
})
|
||||
@@ -640,6 +646,10 @@ export class App {
|
||||
if (sessionId) deleteOptions.sessionId = sessionId
|
||||
if (chatType) deleteOptions.chatType = chatType
|
||||
|
||||
// remove all related feedback records
|
||||
const feedbackDeleteOptions: FindOptionsWhere<ChatMessageFeedback> = { chatId }
|
||||
await this.AppDataSource.getRepository(ChatMessageFeedback).delete(feedbackDeleteOptions)
|
||||
|
||||
// Delete all uploads corresponding to this chatflow/chatId
|
||||
if (chatId) {
|
||||
try {
|
||||
@@ -654,6 +664,68 @@ export class App {
|
||||
return res.json(results)
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// Chat Message Feedback
|
||||
// ----------------------------------------
|
||||
|
||||
// Get all chatmessage feedback from chatflowid
|
||||
this.app.get('/api/v1/feedback/:id', async (req: Request, res: Response) => {
|
||||
const chatflowid = req.params.id
|
||||
const chatId = req.query?.chatId as string | undefined
|
||||
const sortOrder = req.query?.order as string | undefined
|
||||
const startDate = req.query?.startDate as string | undefined
|
||||
const endDate = req.query?.endDate as string | undefined
|
||||
|
||||
const feedback = await this.getChatMessageFeedback(chatflowid, chatId, sortOrder, startDate, endDate)
|
||||
|
||||
return res.json(feedback)
|
||||
})
|
||||
|
||||
// Add chatmessage feedback for chatflowid
|
||||
this.app.post('/api/v1/feedback/:id', async (req: Request, res: Response) => {
|
||||
const body = req.body
|
||||
const results = await this.addChatMessageFeedback(body)
|
||||
return res.json(results)
|
||||
})
|
||||
|
||||
// Update chatmessage feedback for id
|
||||
this.app.put('/api/v1/feedback/:id', async (req: Request, res: Response) => {
|
||||
const id = req.params.id
|
||||
const body = req.body
|
||||
await this.updateChatMessageFeedback(id, body)
|
||||
return res.json({ status: 'OK' })
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// stats
|
||||
// ----------------------------------------
|
||||
//
|
||||
// get stats for showing in chatflow
|
||||
this.app.get('/api/v1/stats/:id', async (req: Request, res: Response) => {
|
||||
const chatflowid = req.params.id
|
||||
const chatTypeFilter = chatType.EXTERNAL
|
||||
|
||||
const totalMessages = await this.AppDataSource.getRepository(ChatMessage).count({
|
||||
where: {
|
||||
chatflowid,
|
||||
chatType: chatTypeFilter
|
||||
}
|
||||
})
|
||||
|
||||
const chatMessageFeedbackRepo = this.AppDataSource.getRepository(ChatMessageFeedback)
|
||||
|
||||
const totalFeedback = await chatMessageFeedbackRepo.count({ where: { chatflowid } })
|
||||
const positiveFeedback = await chatMessageFeedbackRepo.countBy({ chatflowid, rating: ChatMessageRatingType.THUMBS_UP })
|
||||
|
||||
const results = {
|
||||
totalMessages,
|
||||
totalFeedback,
|
||||
positiveFeedback
|
||||
}
|
||||
|
||||
res.json(results)
|
||||
})
|
||||
|
||||
// ----------------------------------------
|
||||
// Credentials
|
||||
// ----------------------------------------
|
||||
@@ -1622,6 +1694,7 @@ export class App {
|
||||
* @param {string} sessionId
|
||||
* @param {string} startDate
|
||||
* @param {string} endDate
|
||||
* @param {boolean} feedback
|
||||
*/
|
||||
async getChatMessage(
|
||||
chatflowid: string,
|
||||
@@ -1632,7 +1705,8 @@ export class App {
|
||||
sessionId?: string,
|
||||
startDate?: string,
|
||||
endDate?: string,
|
||||
messageId?: string
|
||||
messageId?: string,
|
||||
feedback?: boolean
|
||||
): Promise<ChatMessage[]> {
|
||||
const setDateToStartOrEndOfDay = (dateTimeStr: string, setHours: 'start' | 'end') => {
|
||||
const date = new Date(dateTimeStr)
|
||||
@@ -1649,6 +1723,40 @@ export class App {
|
||||
let toDate
|
||||
if (endDate) toDate = setDateToStartOrEndOfDay(endDate, 'end')
|
||||
|
||||
if (feedback) {
|
||||
const query = this.AppDataSource.getRepository(ChatMessage).createQueryBuilder('chat_message')
|
||||
|
||||
// do the join with chat message feedback based on messageId for each chat message in the chatflow
|
||||
query
|
||||
.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 (chatType) {
|
||||
query.andWhere('chat_message.chatType = :chatType', { chatType })
|
||||
}
|
||||
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
|
||||
query.andWhere('chat_message.createdDate BETWEEN :fromDate AND :toDate', {
|
||||
fromDate: fromDate ?? new Date().setMonth(new Date().getMonth() - 1),
|
||||
toDate: toDate ?? new Date()
|
||||
})
|
||||
// sort
|
||||
query.orderBy('chat_message.createdDate', sortOrder === 'DESC' ? 'DESC' : 'ASC')
|
||||
|
||||
const messages = await query.getMany()
|
||||
return messages
|
||||
}
|
||||
|
||||
return await this.AppDataSource.getRepository(ChatMessage).find({
|
||||
where: {
|
||||
chatflowid,
|
||||
@@ -1678,6 +1786,62 @@ export class App {
|
||||
return await this.AppDataSource.getRepository(ChatMessage).save(chatmessage)
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that get chat messages.
|
||||
* @param {string} chatflowid
|
||||
* @param {string} sortOrder
|
||||
* @param {string} chatId
|
||||
* @param {string} startDate
|
||||
* @param {string} endDate
|
||||
*/
|
||||
async getChatMessageFeedback(
|
||||
chatflowid: string,
|
||||
chatId?: string,
|
||||
sortOrder: string = 'ASC',
|
||||
startDate?: string,
|
||||
endDate?: string
|
||||
): Promise<ChatMessageFeedback[]> {
|
||||
let fromDate
|
||||
if (startDate) fromDate = new Date(startDate)
|
||||
|
||||
let toDate
|
||||
if (endDate) toDate = new Date(endDate)
|
||||
return await this.AppDataSource.getRepository(ChatMessageFeedback).find({
|
||||
where: {
|
||||
chatflowid,
|
||||
chatId,
|
||||
createdDate: toDate && fromDate ? Between(fromDate, toDate) : undefined
|
||||
},
|
||||
order: {
|
||||
createdDate: sortOrder === 'DESC' ? 'DESC' : 'ASC'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that add chat message feedback.
|
||||
* @param {Partial<IChatMessageFeedback>} chatMessageFeedback
|
||||
*/
|
||||
async addChatMessageFeedback(chatMessageFeedback: Partial<IChatMessageFeedback>): Promise<ChatMessageFeedback> {
|
||||
const newChatMessageFeedback = new ChatMessageFeedback()
|
||||
Object.assign(newChatMessageFeedback, chatMessageFeedback)
|
||||
|
||||
const feedback = this.AppDataSource.getRepository(ChatMessageFeedback).create(newChatMessageFeedback)
|
||||
return await this.AppDataSource.getRepository(ChatMessageFeedback).save(feedback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that updates chat message feedback.
|
||||
* @param {string} id
|
||||
* @param {Partial<IChatMessageFeedback>} chatMessageFeedback
|
||||
*/
|
||||
async updateChatMessageFeedback(id: string, chatMessageFeedback: Partial<IChatMessageFeedback>) {
|
||||
const newChatMessageFeedback = new ChatMessageFeedback()
|
||||
Object.assign(newChatMessageFeedback, chatMessageFeedback)
|
||||
|
||||
await this.AppDataSource.getRepository(ChatMessageFeedback).update({ id }, chatMessageFeedback)
|
||||
}
|
||||
|
||||
async upsertVector(req: Request, res: Response, isInternal: boolean = false) {
|
||||
try {
|
||||
const chatflowid = req.params.id
|
||||
|
||||
Reference in New Issue
Block a user