Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Follow-up Prompts #3280

Merged
merged 47 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
adf051b
Add migrations - add follow up prompts column to chatflow and chat me…
0xi4o Sep 27, 2024
0cde2d0
Add configuration tab for follow-up prompts
0xi4o Sep 27, 2024
e597de7
Add follow up prompts functionality
0xi4o Sep 27, 2024
75b9f0a
Pin zod version in components - this was causing a type error with st…
0xi4o Sep 27, 2024
15faddc
Generate follow up prompts if enabled and return it in stream, respon…
0xi4o Sep 27, 2024
5f6f3ea
Show follow up prompts after getting response
0xi4o Sep 27, 2024
7cc2df4
Add google gen ai for generating follow up prompts and fix issues
0xi4o Sep 30, 2024
592d344
Add config for google gen ai and update model options
0xi4o Sep 30, 2024
72778f7
Update follow-up prompts ui and styles
0xi4o Sep 30, 2024
34c73fe
Release/2.1.0 (#3204)
HenryHengZJ Sep 17, 2024
3118de6
Chore/update flowise embed version to 2.0.0 (#3205)
HenryHengZJ Sep 17, 2024
11b85bb
Bugfix/CodeInterpreter E2B Credential (#3206)
HenryHengZJ Sep 17, 2024
24d164b
Release/2.1.0 (#3207)
HenryHengZJ Sep 17, 2024
14f4589
Bugfix/Add artifacts migration script to other database types (#3210)
HenryHengZJ Sep 17, 2024
1e28a71
Release/2.1.1 (#3213)
HenryHengZJ Sep 18, 2024
c538ee9
Bugfix/Add header to allow sse on nginx (#3214)
HenryHengZJ Sep 18, 2024
ca287c9
Bugfix/remove invalid markdown (#3219)
HenryHengZJ Sep 19, 2024
a01df37
Correct "as" casing (#3216)
dillfrescott Sep 19, 2024
2cb7352
chore: update unstructured API url and doc reference (#3224)
cragwolfe Sep 20, 2024
79031bf
Feature/add ability to specify dynamic metadata to jsonlines (#3238)
HenryHengZJ Sep 23, 2024
d64e8c0
Bugfix/Buffer Memory for Anthropic (#3242)
HenryHengZJ Sep 24, 2024
1ae4a1c
Added env vars to ui and api URL (#3141)
patrickreinan Sep 24, 2024
bd542e5
Added 1-click deployment link for Alibaba Cloud. (#3251)
yehanyh Sep 25, 2024
d2577e5
Chore/Groq Llama3.2 (#3255)
HenryHengZJ Sep 25, 2024
a80ba4b
Bugfix/Prevent streaming of chatflow tool and chain tool (#3257)
HenryHengZJ Sep 25, 2024
7f82587
Bugfix/Enable Custom Tool Optional Input Schema (#3258)
HenryHengZJ Sep 26, 2024
a264b12
Bugfix/Searxng tool not working (#3263)
HenryHengZJ Sep 26, 2024
2a64343
LunaryAI automatic Thread and User tracking (#3233)
vincelwt Sep 26, 2024
e4e7de5
feat: enable autofocus to the `new chatflow title` to improve usabili…
rhumbertgz Sep 26, 2024
3723a76
feat: save a new Chatflow when the `ENTER` key is pressed (#3261)
rhumbertgz Sep 26, 2024
1e2d480
feat: save Chatflow title when the `ENTER` key is pressed or discard …
rhumbertgz Sep 26, 2024
81a4095
feat: enable autofocus to the `edit chatflow title` field to improve …
rhumbertgz Sep 26, 2024
6e45410
feat: add search keyboard shortcut based on the current platform (#3267)
rhumbertgz Sep 26, 2024
4470608
feat: highlight valid/invalid connection between nodes (#3266)
rhumbertgz Sep 26, 2024
a565da5
Bugfix/add fixes for search of view header (#3271)
HenryHengZJ Sep 26, 2024
788f807
fix: warning when passing a boolean to border property of a Card (#3275)
rhumbertgz Sep 27, 2024
8e30669
feat: add shortcut text hint to the search field (#3269)
rhumbertgz Sep 27, 2024
78f55df
fix: warning when a non-boolean values was used to set `checked` prop…
rhumbertgz Sep 27, 2024
4c138dc
Bugfix/Throw error to prevent SSE from retrying (#3281)
HenryHengZJ Sep 28, 2024
4c672a4
Pin zod version in components - this was causing a type error with st…
0xi4o Sep 27, 2024
9f36932
Fix conflicts in pnpm lock
0xi4o Sep 30, 2024
8c9d2a9
Fix conflicts
0xi4o Sep 30, 2024
a3f9783
Merge branch 'main' into feature/follow-up-prompts
HenryHengZJ Sep 30, 2024
90aadd9
fix ui changes for follow up prompts
HenryHengZJ Oct 2, 2024
3e1d1bb
Fix button disable state in follow-up prompts configuration
0xi4o Oct 3, 2024
596c7ff
Fix follow-up prompts not showing up for agent flows
0xi4o Oct 3, 2024
73a8994
Show follow up prompts if last message is apiMessage and follow up pr…
0xi4o Oct 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
"weaviate-ts-client": "^1.1.0",
"winston": "^3.9.0",
"ws": "^8.9.0",
"zod": "^3.22.4",
"zod": "3.22.4",
"zod-to-json-schema": "^3.21.4"
},
"devDependencies": {
Expand Down
22 changes: 22 additions & 0 deletions packages/components/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,3 +419,25 @@ export interface IServerSideEventStreamer {
streamAbortEvent(chatId: string): void
streamEndEvent(chatId: string): void
}

export enum FollowUpPromptProvider {
ANTHROPIC = 'chatAnthropic',
AZURE_OPENAI = 'azureChatOpenAI',
GOOGLE_GENAI = 'chatGoogleGenerativeAI',
MISTRALAI = 'chatMistralAI',
OPENAI = 'chatOpenAI'
}

export type FollowUpPromptProviderConfig = {
[key in FollowUpPromptProvider]: {
credentialId: string
modelName: string
prompt: string
temperature: string
}
}

export type FollowUpPromptConfig = {
status: boolean
selectedProvider: FollowUpPromptProvider
} & FollowUpPromptProviderConfig
113 changes: 113 additions & 0 deletions packages/components/src/followUpPrompts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { FollowUpPromptConfig, FollowUpPromptProvider, ICommonObject } from './Interface'
import { getCredentialData } from './utils'
import { ChatAnthropic } from '@langchain/anthropic'
import { ChatGoogleGenerativeAI } from '@langchain/google-genai'
import { ChatMistralAI } from '@langchain/mistralai'
import { ChatOpenAI } from '@langchain/openai'
import { z } from 'zod'
import { PromptTemplate } from '@langchain/core/prompts'
import { StructuredOutputParser } from '@langchain/core/output_parsers'

const FollowUpPromptType = z
.object({
questions: z.array(z.string())
})
.describe('Generate Follow Up Prompts')

export const generateFollowUpPrompts = async (
followUpPromptsConfig: FollowUpPromptConfig,
apiMessageContent: string,
options: ICommonObject
) => {
if (followUpPromptsConfig) {
const providerConfig = followUpPromptsConfig[followUpPromptsConfig.selectedProvider]
const credentialId = providerConfig.credentialId as string
const credentialData = await getCredentialData(credentialId ?? '', options)
const followUpPromptsPrompt = providerConfig.prompt.replace('{history}', apiMessageContent)

switch (followUpPromptsConfig.selectedProvider) {
case FollowUpPromptProvider.ANTHROPIC: {
const llm = new ChatAnthropic({
apiKey: credentialData.anthropicApiKey,
model: providerConfig.modelName,
temperature: parseFloat(`${providerConfig.temperature}`)
})
const structuredLLM = llm.withStructuredOutput(FollowUpPromptType)
const structuredResponse = await structuredLLM.invoke(followUpPromptsPrompt)
return structuredResponse
}
case FollowUpPromptProvider.AZURE_OPENAI: {
const azureOpenAIApiKey = credentialData['azureOpenAIApiKey']
const azureOpenAIApiInstanceName = credentialData['azureOpenAIApiInstanceName']
const azureOpenAIApiDeploymentName = credentialData['azureOpenAIApiDeploymentName']
const azureOpenAIApiVersion = credentialData['azureOpenAIApiVersion']

const llm = new ChatOpenAI({
azureOpenAIApiKey,
azureOpenAIApiInstanceName,
azureOpenAIApiDeploymentName,
azureOpenAIApiVersion,
model: providerConfig.modelName,
temperature: parseFloat(`${providerConfig.temperature}`)
})
// use structured output parser because withStructuredOutput is not working
const parser = StructuredOutputParser.fromZodSchema(FollowUpPromptType)
const formatInstructions = parser.getFormatInstructions()
const prompt = PromptTemplate.fromTemplate(`
${providerConfig.prompt}

{format_instructions}
`)
const chain = prompt.pipe(llm).pipe(parser)
const structuredResponse = await chain.invoke({
history: apiMessageContent,
format_instructions: formatInstructions
})
return structuredResponse
}
case FollowUpPromptProvider.GOOGLE_GENAI: {
const llm = new ChatGoogleGenerativeAI({
apiKey: credentialData.googleGenerativeAPIKey,
model: providerConfig.modelName,
temperature: parseFloat(`${providerConfig.temperature}`)
})
// use structured output parser because withStructuredOutput is not working
const parser = StructuredOutputParser.fromZodSchema(FollowUpPromptType)
const formatInstructions = parser.getFormatInstructions()
const prompt = PromptTemplate.fromTemplate(`
${providerConfig.prompt}

{format_instructions}
`)
const chain = prompt.pipe(llm).pipe(parser)
const structuredResponse = await chain.invoke({
history: apiMessageContent,
format_instructions: formatInstructions
})
return structuredResponse
}
case FollowUpPromptProvider.MISTRALAI: {
const model = new ChatMistralAI({
apiKey: credentialData.mistralAIAPIKey,
model: providerConfig.modelName,
temperature: parseFloat(`${providerConfig.temperature}`)
})
const structuredLLM = model.withStructuredOutput(FollowUpPromptType)
const structuredResponse = await structuredLLM.invoke(followUpPromptsPrompt)
return structuredResponse
}
case FollowUpPromptProvider.OPENAI: {
const model = new ChatOpenAI({
apiKey: credentialData.openAIApiKey,
model: providerConfig.modelName,
temperature: parseFloat(`${providerConfig.temperature}`)
})
const structuredLLM = model.withStructuredOutput(FollowUpPromptType)
const structuredResponse = await structuredLLM.invoke(followUpPromptsPrompt)
return structuredResponse
}
}
} else {
return undefined
}
}
1 change: 1 addition & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from './utils'
export * from './speechToText'
export * from './storageUtils'
export * from './handler'
export * from './followUpPrompts'
1 change: 1 addition & 0 deletions packages/server/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export interface IChatMessage {
createdDate: Date
leadEmail?: string
action?: string | null
followUpPrompts?: string
}

export interface IChatMessageFeedback {
Expand Down
3 changes: 3 additions & 0 deletions packages/server/src/database/entities/ChatFlow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export class ChatFlow implements IChatFlow {
@Column({ nullable: true, type: 'text' })
speechToText?: string

@Column({ nullable: true, type: 'text' })
followUpPrompts?: string

@Column({ nullable: true, type: 'text' })
category?: string

Expand Down
3 changes: 3 additions & 0 deletions packages/server/src/database/entities/ChatMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,7 @@ export class ChatMessage implements IChatMessage {

@Column({ nullable: true, type: 'text' })
leadEmail?: string

@Column({ nullable: true, type: 'text' })
followUpPrompts?: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { MigrationInterface, QueryRunner } from 'typeorm'

export class AddFollowUpPrompts1726666318346 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
const columnExistsInChatflow = await queryRunner.hasColumn('chat_flow', 'followUpPrompts')
if (!columnExistsInChatflow) queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`followUpPrompts\` TEXT;`)
const columnExistsInChatMessage = await queryRunner.hasColumn('chat_flow', 'followUpPrompts')
if (!columnExistsInChatMessage) queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`followUpPrompts\` TEXT;`)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE \`chat_flow\` DROP COLUMN \`followUpPrompts\`;`)
}
}
4 changes: 3 additions & 1 deletion packages/server/src/database/migrations/mariadb/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { AddActionToChatMessage1721078251523 } from './1721078251523-AddActionTo
import { LongTextColumn1722301395521 } from './1722301395521-LongTextColumn'
import { AddCustomTemplate1725629836652 } from './1725629836652-AddCustomTemplate'
import { AddArtifactsToChatMessage1726156258465 } from './1726156258465-AddArtifactsToChatMessage'
import { AddFollowUpPrompts1726666318346 } from './1726666318346-AddFollowUpPrompts'

export const mariadbMigrations = [
Init1693840429259,
Expand Down Expand Up @@ -53,5 +54,6 @@ export const mariadbMigrations = [
AddActionToChatMessage1721078251523,
LongTextColumn1722301395521,
AddCustomTemplate1725629836652,
AddArtifactsToChatMessage1726156258465
AddArtifactsToChatMessage1726156258465,
AddFollowUpPrompts1726666318346
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from 'typeorm'

export class AddFollowUpPrompts1726666302024 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
const columnExistsInChatflow = await queryRunner.hasColumn('chat_flow', 'followUpPrompts')
if (!columnExistsInChatflow) queryRunner.query(`ALTER TABLE \`chat_flow\` ADD COLUMN \`followUpPrompts\` TEXT;`)
const columnExistsInChatMessage = await queryRunner.hasColumn('chat_message', 'followUpPrompts')
if (!columnExistsInChatMessage) queryRunner.query(`ALTER TABLE \`chat_message\` ADD COLUMN \`followUpPrompts\` TEXT;`)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE \`chat_flow\` DROP COLUMN \`followUpPrompts\`;`)
await queryRunner.query(`ALTER TABLE \`chat_message\` DROP COLUMN \`followUpPrompts\`;`)
}
}
4 changes: 3 additions & 1 deletion packages/server/src/database/migrations/mysql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { AddActionToChatMessage1721078251523 } from './1721078251523-AddActionTo
import { LongTextColumn1722301395521 } from './1722301395521-LongTextColumn'
import { AddCustomTemplate1725629836652 } from './1725629836652-AddCustomTemplate'
import { AddArtifactsToChatMessage1726156258465 } from './1726156258465-AddArtifactsToChatMessage'
import { AddFollowUpPrompts1726666302024 } from './1726666302024-AddFollowUpPrompts'

export const mysqlMigrations = [
Init1693840429259,
Expand Down Expand Up @@ -55,5 +56,6 @@ export const mysqlMigrations = [
AddActionToChatMessage1721078251523,
LongTextColumn1722301395521,
AddCustomTemplate1725629836652,
AddArtifactsToChatMessage1726156258465
AddArtifactsToChatMessage1726156258465,
AddFollowUpPrompts1726666302024
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from 'typeorm'

export class AddFollowUpPrompts1726666309552 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "chat_flow" ADD COLUMN IF NOT EXISTS "followUpPrompts" TEXT;`)
await queryRunner.query(`ALTER TABLE "chat_message" ADD COLUMN IF NOT EXISTS "followUpPrompts" TEXT;`)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "chat_flow" DROP COLUMN "followUpPrompts";`)
await queryRunner.query(`ALTER TABLE "chat_message" DROP COLUMN "followUpPrompts";`)
}
}
4 changes: 3 additions & 1 deletion packages/server/src/database/migrations/postgres/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { AddApiKey1720230151480 } from './1720230151480-AddApiKey'
import { AddActionToChatMessage1721078251523 } from './1721078251523-AddActionToChatMessage'
import { AddCustomTemplate1725629836652 } from './1725629836652-AddCustomTemplate'
import { AddArtifactsToChatMessage1726156258465 } from './1726156258465-AddArtifactsToChatMessage'
import { AddFollowUpPrompts1726666309552 } from './1726666309552-AddFollowUpPrompts'

export const postgresMigrations = [
Init1693891895163,
Expand Down Expand Up @@ -55,5 +56,6 @@ export const postgresMigrations = [
AddApiKey1720230151480,
AddActionToChatMessage1721078251523,
AddCustomTemplate1725629836652,
AddArtifactsToChatMessage1726156258465
AddArtifactsToChatMessage1726156258465,
AddFollowUpPrompts1726666309552
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from 'typeorm'

export class AddFollowUpPrompts1726666294213 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "chat_flow" ADD COLUMN "followUpPrompts" TEXT;`)
await queryRunner.query(`ALTER TABLE "chat_message" ADD COLUMN "followUpPrompts" TEXT;`)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "chat_flow" DROP COLUMN "followUpPrompts";`)
await queryRunner.query(`ALTER TABLE "chat_message" DROP COLUMN "followUpPrompts";`)
}
}
4 changes: 3 additions & 1 deletion packages/server/src/database/migrations/sqlite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { AddApiKey1720230151480 } from './1720230151480-AddApiKey'
import { AddActionToChatMessage1721078251523 } from './1721078251523-AddActionToChatMessage'
import { AddArtifactsToChatMessage1726156258465 } from './1726156258465-AddArtifactsToChatMessage'
import { AddCustomTemplate1725629836652 } from './1725629836652-AddCustomTemplate'
import { AddFollowUpPrompts1726666294213 } from './1726666294213-AddFollowUpPrompts'

export const sqliteMigrations = [
Init1693835579790,
Expand Down Expand Up @@ -53,5 +54,6 @@ export const sqliteMigrations = [
AddApiKey1720230151480,
AddActionToChatMessage1721078251523,
AddArtifactsToChatMessage1726156258465,
AddCustomTemplate1725629836652
AddCustomTemplate1725629836652,
AddFollowUpPrompts1726666294213
]
3 changes: 3 additions & 0 deletions packages/server/src/utils/SSEStreamer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ export class SSEStreamer implements IServerSideEventStreamer {
if (apiResponse.memoryType) {
metadataJson['memoryType'] = apiResponse.memoryType
}
if (apiResponse.followUpPrompts) {
metadataJson['followUpPrompts'] = JSON.parse(apiResponse.followUpPrompts)
}
if (Object.keys(metadataJson).length > 0) {
this.streamCustomEvent(chatId, 'metadata', metadataJson)
}
Expand Down
14 changes: 14 additions & 0 deletions packages/server/src/utils/buildChatflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
addArrayFilesToStorage,
mapMimeTypeToInputField,
mapExtToInputField,
generateFollowUpPrompts,
IServerSideEventStreamer
} from 'flowise-components'
import { StatusCodes } from 'http-status-codes'
Expand Down Expand Up @@ -452,6 +453,18 @@ export const utilBuildChatflow = async (req: Request, isInternal: boolean = fals
if (result?.usedTools) apiMessage.usedTools = JSON.stringify(result.usedTools)
if (result?.fileAnnotations) apiMessage.fileAnnotations = JSON.stringify(result.fileAnnotations)
if (result?.artifacts) apiMessage.artifacts = JSON.stringify(result.artifacts)
if (chatflow.followUpPrompts) {
const followUpPromptsConfig = JSON.parse(chatflow.followUpPrompts)
const followUpPrompts = await generateFollowUpPrompts(followUpPromptsConfig, apiMessage.content, {
chatId,
chatflowid,
appDataSource: appServer.AppDataSource,
databaseEntities
})
if (followUpPrompts?.questions) {
apiMessage.followUpPrompts = JSON.stringify(followUpPrompts.questions)
}
}

const chatMessage = await utilAddChatMessage(apiMessage)

Expand All @@ -470,6 +483,7 @@ export const utilBuildChatflow = async (req: Request, isInternal: boolean = fals
result.question = incomingInput.question
result.chatId = chatId
result.chatMessageId = chatMessage?.id
result.followUpPrompts = JSON.stringify(apiMessage.followUpPrompts)
result.isStreamValid = isStreamValid

if (sessionId) result.sessionId = sessionId
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/assets/images/anthropic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/ui/src/assets/images/azure_openai.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/ui/src/assets/images/mistralai.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading