-
Notifications
You must be signed in to change notification settings - Fork 2k
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
[Odysseus] Overhauling framework in line with backend services #78989
Changes from all commits
4989b1a
316e346
b842853
3c845db
3cd4620
45f80d9
d0032c3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,25 +9,52 @@ export type Nudge = { | |
initialMessage: string; | ||
context?: Record< string, unknown >; | ||
}; | ||
|
||
export type MessageRole = 'user' | 'bot'; | ||
|
||
export type MessageType = 'message' | 'action' | 'meta' | 'error'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
export type Message = { | ||
content: string; | ||
role: MessageRole; | ||
type: MessageType; | ||
chatId?: string | null; | ||
}; | ||
Comment on lines
+17
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated type definition |
||
|
||
export type Chat = { | ||
chatId?: string | null; | ||
messages: Message[]; | ||
}; | ||
|
||
interface OdysseusAssistantContextInterface { | ||
currentView: string; | ||
setCurrentView: ( currentView: string ) => void; | ||
addMessage: ( message: Message ) => void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Simplified params to use Message type |
||
chat: Chat; | ||
isLoadingChat: boolean; | ||
lastNudge: Nudge | null; | ||
messages: Message[]; | ||
sectionName: string; | ||
sendNudge: ( nudge: Nudge ) => void; | ||
lastNudge: Nudge | null; | ||
setChat: ( chat: Chat ) => void; | ||
setIsLoadingChat: ( isLoadingChat: boolean ) => void; | ||
setMessages: ( messages: Message[] ) => void; | ||
} | ||
|
||
const defaultCurrentViewContextInterface = { | ||
currentView: '', | ||
setCurrentView: noop, | ||
const defaultContextInterfaceValues = { | ||
addMessage: noop, | ||
chat: { messages: [] }, | ||
isLoadingChat: false, | ||
lastNudge: null, | ||
messages: [], | ||
sectionName: '', | ||
sendNudge: noop, | ||
lastNudge: null, | ||
setChat: noop, | ||
setIsLoadingChat: noop, | ||
setMessages: noop, | ||
}; | ||
|
||
// Create a new context | ||
// Create a default new context | ||
const OdysseusAssistantContext = createContext< OdysseusAssistantContextInterface >( | ||
defaultCurrentViewContextInterface | ||
defaultContextInterfaceValues | ||
); | ||
|
||
// Custom hook to access the OdysseusAssistantContext | ||
|
@@ -41,12 +68,35 @@ const OdysseusAssistantProvider = ( { | |
sectionName: string; | ||
children: ReactNode; | ||
} ) => { | ||
const [ currentView, setCurrentView ] = useState( '' ); | ||
const [ lastNudge, setLastNudge ] = useState< Nudge | null >( null ); | ||
const [ messages, setMessages ] = useState< Message[] >( [] ); | ||
const [ chat, setChat ] = useState< Chat >( { messages: [] } ); | ||
|
||
const addMessage = ( message: Message ) => { | ||
setMessages( ( prevMessages ) => { | ||
const newMessages = [ ...prevMessages, message ]; | ||
setChat( ( prevChat ) => ( { | ||
chatId: message.chatId ?? prevChat.chatId, | ||
messages: newMessages, | ||
} ) ); | ||
return newMessages; | ||
} ); | ||
}; | ||
|
||
return ( | ||
<OdysseusAssistantContext.Provider | ||
value={ { currentView, setCurrentView, sectionName, sendNudge: setLastNudge, lastNudge } } | ||
value={ { | ||
addMessage, | ||
chat, | ||
isLoadingChat: false, | ||
lastNudge, | ||
messages, | ||
sectionName, | ||
sendNudge: setLastNudge, | ||
setChat, | ||
setIsLoadingChat: noop, | ||
setMessages, | ||
} } | ||
> | ||
{ children } | ||
</OdysseusAssistantContext.Provider> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,45 @@ | ||
import { useQuery, useMutation, UseMutationResult } from '@tanstack/react-query'; | ||
import { useMutation, UseMutationResult } from '@tanstack/react-query'; | ||
import wpcom from 'calypso/lib/wp'; | ||
import { Nudge, useOdysseusAssistantContext } from '../context'; | ||
import type { Message } from '../context'; | ||
|
||
function queryValidate( siteId: number | null ) { | ||
const path = `/sites/${ siteId }/odysseus`; | ||
return wpcom.req.get( { path, apiNamespace: 'wpcom/v2' } ); | ||
} | ||
|
||
export type Message = { | ||
content: string; | ||
role: 'user' | 'assistant'; | ||
}; | ||
|
||
// It just checks that the endpoint is working | ||
export const useOddyseusEndpointSanityCheck = ( siteId: number | null ) => { | ||
return useQuery( { | ||
queryKey: [ 'oddyseus-assistant-validation', siteId ], | ||
queryFn: () => queryValidate( siteId ), | ||
staleTime: 5 * 60 * 1000, | ||
enabled: siteId !== null, | ||
} ); | ||
}; | ||
|
||
function postOddyseus( | ||
function odysseusSendMessage( | ||
siteId: number | null, | ||
prompt: string, | ||
messages: Message[], | ||
context: Nudge, | ||
messages: Message[] = [], | ||
sectionName: string | ||
sectionName: string, | ||
chatId?: string | null | ||
) { | ||
const path = `/sites/${ siteId }/odysseus`; | ||
const path = `/odysseus/send_message`; | ||
return wpcom.req.post( { | ||
path, | ||
apiNamespace: 'wpcom/v2', | ||
body: { prompt, context, messages, sectionName }, | ||
body: { messages, context, sectionName, siteId, chatId }, | ||
} ); | ||
} | ||
|
||
export const useOddyseusEndpointPost = ( | ||
// It will post a new message using the current chatId | ||
export const useOddyseusSendMessage = ( | ||
siteId: number | null | ||
): UseMutationResult< | ||
string, | ||
{ chatId: string; message: Message }, | ||
unknown, | ||
{ prompt: string; context: Nudge; messages: Message[] } | ||
{ message: Message; context: Nudge } | ||
> => { | ||
const { sectionName } = useOdysseusAssistantContext(); | ||
const { sectionName, chat, messages, setChat } = useOdysseusAssistantContext(); | ||
|
||
return useMutation( { | ||
mutationFn: ( { | ||
prompt, | ||
context, | ||
messages, | ||
}: { | ||
prompt: string; | ||
context: Nudge; | ||
messages: Message[]; | ||
} ) => postOddyseus( siteId, prompt, context, messages, sectionName ), | ||
mutationFn: ( { message, context }: { message: Message; context: Nudge } ) => { | ||
// If chatId is defined, we only send the message to the current chat | ||
// Otherwise we send previous messages and the new one appended to the end to the server | ||
const messagesToSend = chat?.chatId ? [ message ] : [ ...messages, message ]; | ||
|
||
return odysseusSendMessage( siteId, messagesToSend, context, sectionName, chat.chatId ); | ||
}, | ||
onSuccess: ( data ) => { | ||
setChat( { ...chat, chatId: data.chatId } ); | ||
}, | ||
} ); | ||
}; | ||
|
||
// TODO: We will add lately a clear chat to forget the session |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated this to match the enum declaration on the server
https://github.com/Automattic/ai-services/blob/trunk/odysseus/app/schemas.py#L15-L18