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

741 fix backend chat history message types #803

Merged
merged 90 commits into from
Feb 6, 2024

Conversation

pmarsh-scottlogic
Copy link
Contributor

@pmarsh-scottlogic pmarsh-scottlogic commented Jan 30, 2024

This PR is the result of a change request in #800 . It was deemed a large enough change to warrant a second PR. This branch came of the branch for the first PR. This PR should be merged after #800.

Description

Tightens up the types for the backend's chat message history. No functional change.

Notes

  • Renames ChatHistoryMessage to ChatMessage
  • Introduces individual types for each of the CHAT_MESSAGE_TYPEs (enum). These specify which CHAT_MESSAGE_TYPEs need completions and which need info messages, and lets us be more specific about our completion types.
  • ChatMessage is now a union of the above types, and all of them live in their own new file, chatMessage.ts

Checklist

Have you done the following?

  • Linked the relevant Issue
  • Added tests
  • Ensured the workflow steps are passing

chatMessageType,
infoMessage,
}
} as ChatMessage
Copy link
Contributor Author

@pmarsh-scottlogic pmarsh-scottlogic Feb 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method allows invalidly typed chatMessages to be added to the history. Does it need to be fixed? Is it problematic if, because of client error, a message has superfluous properties?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, good question. We might consider two improvements then:

  • Create a type representing ChatMessages that originate from an API call (i.e. from the UI)
  • Validate these messages on arrival, by checking their content conforms to our expected shape(s) and types.

Either or both of these could be done in a separate issue if you prefer, though you migth want to get them done now rather than kicking them down the road.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding extra types seems not useful if types don't exist at runtime. We'd need to add explicit checks that would work even when the project is compiled to js, non?

Copy link
Contributor Author

@pmarsh-scottlogic pmarsh-scottlogic Feb 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I've done my best shot at this, which may well could have been a separate PR's worth of work, so let me know if you want me to cherry pick commits across for ease of review.

  • I've completely revamped the models/chatMessage.ts file which defines the chat message types. All the chat message types which will (in the history) store the message in the infoMessage property are grouped together as CHAT_MESSAGE_TYPE_AS_INFO. This comes from an array of string literals. This same array is used to check that the message type in the request isn't bogus.
  • I realised that we were exclusively adding the messages as info messages in handleAddToChatHistory. So really we should only accept chat message types that only store stuff in the infoMessage property. So I renamed handleAddToChatHistory along with the associated bits and bobs to handleAddToChatHistoryAsInfo
  • While I was doing that I accidentally bumped into this bug and solved it before realising there was already a ticket for it. I added an extra unit test to catch future instances for good measure.

this is a type-safe as I can get it, but it's kinda ugly and the names are confusing, so I'm happy to try another approach / take suggestions.

Copy link
Member

@chriswilty chriswilty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will continue the review tomorrow. I'm probably better off looking at all the changes, instead of just the latest.

'INFO',
] as const;

type CHAT_MESSAGE_TYPE_AS_INFO = (typeof chatMessageTypesAsInfo)[number];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the "as info" suffix to me? I can't see what you're trying to convey.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. So as I was saying on teams, we have to things to distinguish.

  • "INFO" which is a specific type of chat message which should be rendered in a certain way on the front end. This is distinct from, but the same kind of thing as "LEVEL_INFO" and "LEVEL_RESET" etc.
  • chatMessages which store the the message in the infoMessage property. I was assigning these the type chatMessageAsInfo.

This was weird and the names were confusing. So what I've done is

  • Rename "INFO" to "GENERIC_INFO".
  • Rename chatMessageAsInfo to chatInfoMessage.

And I've renamed the bits and bobs surrounding those too. The goal is to distinguish the two things. So now we have the idea of a chat info message, which is any message that appears in chat to give info, but doesn't get fed into the bot as a completion. Then we have the specific types that those messages can take, one of which is "GENERIC_INFO", and these types determine how they are rendered on the front end.

I think this is a satisfying resolution. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep I think this will work fine, and you'll likely be revisiting anyway when you look at consolidating network requests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"GENERIC_INFO"

Naming things is hard! How about "INFO_BUBBLE" or something like that? EVENT_INFO, INFORMATIVE, STATUS_UPDATE? Or just leave it as is cos you'll be revisiting this code anyway 😆

backend/src/utils/chat.ts Outdated Show resolved Hide resolved
Copy link
Member

@chriswilty chriswilty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All looks sane to me. Couple of questions / random thoughts, but essentially ready to approve once you're happy with it.

backend/src/models/chatMessage.ts Outdated Show resolved Hide resolved
chatMessageType: CHAT_MESSAGE_TYPE.USER,
infoMessage: message,
})
? chatHistoryWithNewUserMessages
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've lost track of this PR a touch! Looks like you're keeping the transformed message now even if it was blocked, so I'm assuming that's a deliberate change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, it was not so deliberate. I want the new messages in the history, but I do not want the completion there. I shall change that now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So now we need a version of type ChatUserTransformedMessage which doesn't include a completion. I was in two minds about whether I should just make the completion optional, or to make a whole new type that doesn't have the completion. I went with the former for lightweightness, but very happy to try the latter.

backend/src/controller/chatController.ts Outdated Show resolved Hide resolved
function handleAddInfoToChatHistory(
req: OpenAiAddInfoToChatHistoryRequest,
res: Response
) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I think about this separate API call, the weirder it seems. In theory it allows us to inject an arbitrary message into the chat, of any chat message type. Ok we can't add a completion, but we could add a "BOT" message with an infoMessage property. Will the ChatGPT call simply ignore that message, as it has no completion property?

Anyhow, nothing to do here, just blurting out my thoughts as they form 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, not any more! They can only inject one that makes sense with the new checks I've added.
namely

if (... && 
  chatInfoMessageType.includes(chatMessageType) &&
  ...
) {
  // do the stuff
}

frontend/src/models/chat.ts Show resolved Hide resolved
Copy link
Member

@chriswilty chriswilty left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that looks nice 👌

},
createAs === 'completion'
? {
completion: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is indentation squiffy here? One too many indents?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just Prettier doing its thing. Looks better in the ide

image

@pmarsh-scottlogic pmarsh-scottlogic merged commit 8c4e2c9 into dev Feb 6, 2024
2 checks passed
@pmarsh-scottlogic pmarsh-scottlogic deleted the 741-fix-chat-message-types branch February 6, 2024 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Transformed messages not showing correctly
2 participants