feat: adapt workflow for ppt & minimap (#7464)

This commit is contained in:
darkskygit
2024-07-10 10:13:17 +00:00
parent 22187f964a
commit 0739e10683
10 changed files with 227 additions and 27 deletions

View File

@@ -149,15 +149,18 @@ export class CopilotClient {
}
// Text or image to text
chatTextStream({
sessionId,
messageId,
}: {
sessionId: string;
messageId?: string;
}) {
chatTextStream(
{
sessionId,
messageId,
}: {
sessionId: string;
messageId?: string;
},
endpoint = 'stream'
) {
const url = new URL(
`${this.backendUrl}/api/copilot/chat/${sessionId}/stream`
`${this.backendUrl}/api/copilot/chat/${sessionId}/${endpoint}`
);
if (messageId) url.searchParams.set('messageId', messageId);
return new EventSource(url.toString());

View File

@@ -28,20 +28,20 @@ export const promptKeys = [
'Write outline',
'Change tone to',
'Brainstorm ideas about this',
'Brainstorm mindmap',
'Expand mind map',
'Improve writing for it',
'Improve grammar for it',
'Fix spelling for it',
'Find action items from it',
'Check code error',
'Create a presentation',
'Create headings',
'Make it real',
'Make it real with text',
'Make it longer',
'Make it shorter',
'Continue writing',
'workflow:presentation',
'workflow:brainstorm',
] as const;
export type PromptKey = (typeof promptKeys)[number];

View File

@@ -22,6 +22,8 @@ export type TextToTextOptions = {
stream?: boolean;
signal?: AbortSignal;
retry?: boolean;
workflow?: boolean;
postfix?: (text: string) => string;
};
export type ToImageOptions = TextToTextOptions & {
@@ -111,6 +113,8 @@ export function textToText({
signal,
timeout = TIMEOUT,
retry = false,
workflow = false,
postfix,
}: TextToTextOptions) {
let _sessionId: string;
let _messageId: string | undefined;
@@ -139,10 +143,13 @@ export function textToText({
_messageId = message.messageId;
}
const eventSource = client.chatTextStream({
sessionId: _sessionId,
messageId: _messageId,
});
const eventSource = client.chatTextStream(
{
sessionId: _sessionId,
messageId: _messageId,
},
workflow ? 'workflow' : undefined
);
AIProvider.LAST_ACTION_SESSIONID = _sessionId;
if (signal) {
@@ -154,12 +161,25 @@ export function textToText({
eventSource.close();
};
}
for await (const event of toTextStream(eventSource, {
timeout,
signal,
})) {
if (event.type === 'message') {
yield event.data;
if (postfix) {
const messages: string[] = [];
for await (const event of toTextStream(eventSource, {
timeout,
signal,
})) {
if (event.type === 'message') {
messages.push(event.data);
}
}
yield postfix(messages.join(''));
} else {
for await (const event of toTextStream(eventSource, {
timeout,
signal,
})) {
if (event.type === 'message') {
yield event.data;
}
}
}
},

View File

@@ -8,6 +8,7 @@ import { Trans } from '@affine/i18n';
import { UnauthorizedError } from '@blocksuite/blocks';
import { assertExists } from '@blocksuite/global/utils';
import { getCurrentStore } from '@toeverything/infra';
import { z } from 'zod';
import type { PromptKey } from './prompt';
import {
@@ -233,7 +234,8 @@ function setupAIProvider() {
return textToText({
...options,
content: options.input,
promptName: 'Brainstorm mindmap',
promptName: 'workflow:brainstorm',
workflow: true,
});
});
@@ -289,10 +291,48 @@ Could you make a new website based on these notes and send back just the html fi
});
AIProvider.provide('createSlides', options => {
const SlideSchema = z.object({
page: z.number(),
type: z.enum(['name', 'title', 'content']),
content: z.string(),
});
type Slide = z.infer<typeof SlideSchema>;
const parseJson = (json: string) => {
try {
return SlideSchema.parse(JSON.parse(json));
} catch {
return null;
}
};
// TODO(@darkskygit): move this to backend's workflow after workflow support custom code action
const postfix = (text: string): string => {
const slides = text
.split('\n')
.map(parseJson)
.filter((v): v is Slide => !!v);
return slides
.map(slide => {
if (slide.type === 'name') {
return `- ${slide.content}`;
} else if (slide.type === 'title') {
return ` - ${slide.content}`;
} else if (slide.content.includes('\n')) {
return slide.content
.split('\n')
.map(c => ` - ${c}`)
.join('\n');
} else {
return ` - ${slide.content}`;
}
})
.join('\n');
};
return textToText({
...options,
content: options.input,
promptName: 'Create a presentation',
promptName: 'workflow:presentation',
workflow: true,
postfix,
});
});