Skip to content

Commit

Permalink
ReplyTo: extract
Browse files Browse the repository at this point in the history
  • Loading branch information
enricoros committed May 9, 2024
1 parent 1acaed1 commit d929438
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 24 deletions.
20 changes: 6 additions & 14 deletions src/apps/chat/AppChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { PreferencesTab, useOptimaLayout, usePluggableOptimaLayout } from '~/com
import { ScrollToBottom } from '~/common/scroll-to-bottom/ScrollToBottom';
import { ScrollToBottomButton } from '~/common/scroll-to-bottom/ScrollToBottomButton';
import { addSnackbar, removeSnackbar } from '~/common/components/useSnackbarsStore';
import { createDMessage, DConversationId, DMessage, getConversation, getConversationSystemPurposeId, useConversation } from '~/common/state/store-chats';
import { createDMessage, DConversationId, DMessage, DMessageMetadata, getConversation, getConversationSystemPurposeId, useConversation } from '~/common/state/store-chats';
import { themeBgAppChatComposer } from '~/common/app.theme';
import { useFolderStore } from '~/common/state/store-folders';
import { useIsMobile } from '~/common/components/useMatchMedia';
Expand All @@ -39,7 +39,7 @@ import { ChatBeamWrapper } from './components/ChatBeamWrapper';
import { ChatDrawerMemo } from './components/ChatDrawer';
import { ChatMessageList } from './components/ChatMessageList';
import { ChatPageMenuItems } from './components/ChatPageMenuItems';
import { Composer, ComposerActionMetadata } from './components/composer/Composer';
import { Composer } from './components/composer/Composer';
import { usePanesManager } from './components/panes/usePanesManager';

import { _handleExecute } from './editors/_handleExecute';
Expand Down Expand Up @@ -210,7 +210,7 @@ export function AppChat() {
return outcome === true;
}, [openModelsSetup, openPreferencesTab]);

const handleComposerAction = React.useCallback((conversationId: DConversationId, chatModeId: ChatModeId, multiPartMessage: ComposerOutputMultiPart, metadata: ComposerActionMetadata): boolean => {
const handleComposerAction = React.useCallback((conversationId: DConversationId, chatModeId: ChatModeId, multiPartMessage: ComposerOutputMultiPart, metadata?: DMessageMetadata): boolean => {
// validate inputs
if (multiPartMessage.length !== 1 || multiPartMessage[0].type !== 'text-block') {
addSnackbar({
Expand All @@ -236,19 +236,11 @@ export function AppChat() {
const history = getConversation(_cId)?.messages;
if (!history) continue;

const newHistory = [
...history,
createDMessage('user', userText),
];

// FIXME: HACK - this is a temporary solution to pass the metadata to the execution
// Only works with OpenAI right now - shall be passed as higher level metadata, so that
// each LLM vendor can encode this the way they like
if (metadata.inReplyTo)
newHistory.push(createDMessage('system', `The user is referring to this in particular:\n${metadata.inReplyTo}`));
const newUserMessage = createDMessage('user', userText);
if (metadata) newUserMessage.metadata = metadata;

// fire/forget
void handleExecuteAndOutcome(chatModeId, _cId, newHistory);
void handleExecuteAndOutcome(chatModeId, _cId, [...history, newUserMessage]);
enqueuedAny = true;
}
return enqueuedAny;
Expand Down
13 changes: 3 additions & 10 deletions src/apps/chat/components/composer/Composer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { ConversationsManager } from '~/common/chats/ConversationsManager';
import { PreferencesTab, useOptimaLayout } from '~/common/layout/optima/useOptimaLayout';
import { SpeechResult, useSpeechRecognition } from '~/common/components/useSpeechRecognition';
import { animationEnterBelow } from '~/common/util/animUtils';
import { conversationTitle, DConversationId, getConversation, useChatStore } from '~/common/state/store-chats';
import { conversationTitle, DConversationId, DMessageMetadata, getConversation, useChatStore } from '~/common/state/store-chats';
import { countModelTokens } from '~/common/util/token-counter';
import { isMacUser } from '~/common/util/pwaUtils';
import { launchAppCall } from '~/common/app.routes';
Expand Down Expand Up @@ -90,11 +90,6 @@ const dropppedCardDraggingSx: SxProps = {
} as const;


export interface ComposerActionMetadata {
inReplyTo: string | null;
}


/**
* A React component for composing messages, with attachments and different modes.
*/
Expand All @@ -106,7 +101,7 @@ export function Composer(props: {
capabilityHasT2I: boolean;
isMulticast: boolean | null;
isDeveloperMode: boolean;
onAction: (conversationId: DConversationId, chatModeId: ChatModeId, multiPartMessage: ComposerOutputMultiPart, metadata: ComposerActionMetadata) => boolean;
onAction: (conversationId: DConversationId, chatModeId: ChatModeId, multiPartMessage: ComposerOutputMultiPart, metadata?: DMessageMetadata) => boolean;
onTextImagine: (conversationId: DConversationId, text: string) => void;
setIsMulticast: (on: boolean) => void;
sx?: SxProps;
Expand Down Expand Up @@ -217,9 +212,7 @@ export function Composer(props: {
return false;

// metadata
const metadata: ComposerActionMetadata = {
inReplyTo: replyToGenerateText || null,
};
const metadata = replyToGenerateText ? { inReplyToText: replyToGenerateText } : undefined;

// send the message
const enqueued = onAction(conversationId, _chatModeId, multiPartMessage, metadata);
Expand Down
5 changes: 5 additions & 0 deletions src/apps/chat/editors/_handleExecute.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getChatLLMId } from '~/modules/llms/store-llms';
import { updateHistoryForReplyTo } from '~/modules/aifn/replyto/replyTo';

import { ConversationsManager } from '~/common/chats/ConversationsManager';
import { createDMessage, DConversationId, DMessage, getConversationSystemPurposeId } from '~/common/state/store-chats';
Expand Down Expand Up @@ -30,6 +31,10 @@ export async function _handleExecute(chatModeId: ChatModeId, conversationId: DCo
const cHandler = ConversationsManager.getHandler(conversationId);
cHandler.inlineUpdatePurposeInHistory(history, chatLLMId || undefined);

// FIXME: shouldn't do this for all the code paths. The advantage for having it here (vs Composer output only) is re-executing history
// TODO: move this to the server side after transferring metadata?
updateHistoryForReplyTo(history);

// Handle unconfigured
if (!chatLLMId || !chatModeId) {
// set the history (e.g. the updated system prompt and the user prompt) at least, see #523
Expand Down
22 changes: 22 additions & 0 deletions src/modules/aifn/replyto/replyTo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { createDMessage, DMessage } from '~/common/state/store-chats';


const replyToSystemPrompt = `The user is referring to this in particular:
{{ReplyToText}}`;

/**
* Adds a system message to the history, explaining the context of the reply
*
* FIXME: HACK - this is a temporary solution to pass the metadata to the execution
*
* Only works with OpenAI and a couple more right now. Fix it by making it vendor-agnostic
*/
export function updateHistoryForReplyTo(history: DMessage[]) {
if (history?.length < 1)
return;

const lastMessage = history[history.length - 1];

if (lastMessage.role === 'user' && lastMessage.metadata?.inReplyToText)
history.push(createDMessage('system', replyToSystemPrompt.replace('{{ReplyToText}}', lastMessage.metadata.inReplyToText)));
}

0 comments on commit d929438

Please sign in to comment.