(conversation: ChatMessage[], api: WebAPI, signal?: AbortSignal)
| 9 | |
| 10 | export class TitleGenerator { |
| 11 | async generateForConversation(conversation: ChatMessage[], api: WebAPI, signal?: AbortSignal) { |
| 12 | // Generate a prompt using stripped chat content. |
| 13 | const messages = conversation |
| 14 | .filter(m => m.role == ChatRole.User || (m.role == ChatRole.Assistant && m.content)) |
| 15 | .map(m => `${m.role.toString()}: ${stripContent(m.content)}`); |
| 16 | const promptText = `\ |
| 17 | Name the conversation based on following chat records: |
| 18 | |
| 19 | --- |
| 20 | ${messages.join('\n\n')} |
| 21 | --- |
| 22 | |
| 23 | Provide a concise name, within 15 characters and without quotation marks. |
| 24 | The name should be in the same language used by the conversation. |
| 25 | |
| 26 | The conversation is named: |
| 27 | `; |
| 28 | |
| 29 | let title = ''; |
| 30 | if (api instanceof ChatCompletionAPI) { |
| 31 | const message = {role: ChatRole.User, content: promptText}; |
| 32 | await api.sendConversation([message], { |
| 33 | signal, |
| 34 | onMessageDelta(delta) { title += delta.content ?? ''; } |
| 35 | }); |
| 36 | } else if (api instanceof ChatConversationAPI && |
| 37 | !(api.constructor as ChatConversationAPIType).badSummarizer) { |
| 38 | // Spawn a new conversation to ask for title generation, |
| 39 | const newapi = api.clone() as ChatConversationAPI; |
| 40 | await newapi.sendMessage(promptText, { |
| 41 | signal, |
| 42 | onMessageDelta(delta) { title += delta.content ?? ''; } |
| 43 | }); |
| 44 | // Clear the temporary conversation. |
| 45 | if ((api.constructor as ChatConversationAPIType).canRemoveFromServer) |
| 46 | await newapi.removeFromServer(); |
| 47 | } else { |
| 48 | // Return the first words of last message. |
| 49 | title = getFirstSentence(conversation[conversation.length - 1].content); |
| 50 | // Do a fake await since this method is supposed to be async, returning |
| 51 | // too early might trigger some bugs. |
| 52 | await new Promise(resolve => setImmediate(resolve)); |
| 53 | } |
| 54 | return title.trim(); |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | export default new TitleGenerator(); |
no test coverage detected