Files
baibot-withmcp/src/conversation/llm/utils.rs

125 lines
4.8 KiB
Rust
Raw Normal View History

use mxlink::matrix_sdk::ruma::OwnedUserId;
use super::entity::{Author, FileDetails, ImageDetails, Message, MessageContent};
use crate::conversation::matrix::{MatrixMessage, MatrixMessageContent};
2024-09-12 13:44:06 +03:00
use crate::utils::text_to_speech as text_to_speech_utils;
pub fn convert_matrix_message_to_llm_message(
matrix_message: &MatrixMessage,
bot_user_id: &OwnedUserId,
2024-09-12 13:44:06 +03:00
) -> Option<Message> {
if matrix_message.sender_id == bot_user_id.as_str() {
2024-09-12 13:44:06 +03:00
return convert_bot_message(matrix_message);
}
convert_user_message(matrix_message)
}
fn convert_bot_message(matrix_message: &MatrixMessage) -> Option<Message> {
match &matrix_message.content {
MatrixMessageContent::Text(text) => convert_bot_text_message(
text,
&matrix_message.timestamp,
matrix_message.sender_id.clone(),
),
MatrixMessageContent::Notice(text) => {
convert_bot_notice_message(text, &matrix_message.timestamp)
}
2025-05-10 11:47:50 +03:00
MatrixMessageContent::Image(image_content, mime_type, media_bytes) => Some(Message {
author: Author::Assistant,
sender_id: Some(matrix_message.sender_id.clone()),
2025-05-10 11:47:50 +03:00
content: MessageContent::Image(ImageDetails::new(
image_content.clone(),
mime_type.clone(),
media_bytes.clone(),
)),
timestamp: matrix_message.timestamp.to_owned(),
}),
MatrixMessageContent::File(file_content, mime_type, media_bytes) => Some(Message {
author: Author::Assistant,
sender_id: Some(matrix_message.sender_id.clone()),
content: MessageContent::File(FileDetails::new(
file_content.clone(),
mime_type.clone(),
media_bytes.clone(),
)),
timestamp: matrix_message.timestamp.to_owned(),
}),
2024-09-12 13:44:06 +03:00
}
}
fn convert_bot_text_message(
text: &str,
timestamp: &chrono::DateTime<chrono::Utc>,
sender_id: OwnedUserId,
) -> Option<Message> {
2024-09-12 13:44:06 +03:00
Some(Message {
author: Author::Assistant,
sender_id: Some(sender_id),
content: MessageContent::Text(text.to_owned()),
timestamp: timestamp.to_owned(),
2024-09-12 13:44:06 +03:00
})
}
fn convert_bot_notice_message(
text: &str,
timestamp: &chrono::DateTime<chrono::Utc>,
) -> Option<Message> {
2024-09-12 13:44:06 +03:00
// Notice messages sent by the bot are usually transcriptions of previous messages sent by the user.
// Such transcriptions are prefixed with an emoji and blockquoted.
// If we find a notice that doesn't match this pattern, we skip it.
Do not send blockquote-formatted transcription when replying without a thread This actually fixes 2 issues. Fixes https://github.com/etkecc/baibot/issues/14 Fixes https://github.com/etkecc/baibot/issues/17 When people enable transcribe-only mode and the bot replies outside of a thread, messages will no longer look like this: `> 🦻 Transcribed text`. Instead, they will: - look like this: `Transcribed text` - get an emoji reaction (🦻) sent by the bot itself, to indicate that the message is a transcription --------------------------------------- As https://github.com/etkecc/baibot/issues/14 discusses, the `> 🦻` prefixing of messages also served the purpose of indicating to the bot that this is not its own message, but rather something it "heard" from a user. Given that out-of-thread replies no longer include this, they could be mistaken for bot messages. Because transcribed messages are posted as notice messages, we can easily tell them apart from regular text-generated messages by the bot itself, so we can (and do) treat them differently. Thankfully, the bot does not yet support building a text-generation conversation from arbitrary messages (something discussed in https://github.com/etkecc/baibot/issues/15), so these out-of-thread replies having the wrong owner are not an issue for now. If we do land support for this, we'll probably need to make the bot inspect such notice messages posted by it, inspect their reactons and attribute them properly (🦻 -> user message).
2024-09-30 17:18:44 +03:00
//
// It should be noted that transcriptions are sometimes posted as regular notice (or even text) messages which do not include
Do not send blockquote-formatted transcription when replying without a thread This actually fixes 2 issues. Fixes https://github.com/etkecc/baibot/issues/14 Fixes https://github.com/etkecc/baibot/issues/17 When people enable transcribe-only mode and the bot replies outside of a thread, messages will no longer look like this: `> 🦻 Transcribed text`. Instead, they will: - look like this: `Transcribed text` - get an emoji reaction (🦻) sent by the bot itself, to indicate that the message is a transcription --------------------------------------- As https://github.com/etkecc/baibot/issues/14 discusses, the `> 🦻` prefixing of messages also served the purpose of indicating to the bot that this is not its own message, but rather something it "heard" from a user. Given that out-of-thread replies no longer include this, they could be mistaken for bot messages. Because transcribed messages are posted as notice messages, we can easily tell them apart from regular text-generated messages by the bot itself, so we can (and do) treat them differently. Thankfully, the bot does not yet support building a text-generation conversation from arbitrary messages (something discussed in https://github.com/etkecc/baibot/issues/15), so these out-of-thread replies having the wrong owner are not an issue for now. If we do land support for this, we'll probably need to make the bot inspect such notice messages posted by it, inspect their reactons and attribute them properly (🦻 -> user message).
2024-09-30 17:18:44 +03:00
// the `> 🦻` formatting. This function will not handle these properly.
2024-09-12 13:44:06 +03:00
if let Some(text) = text_to_speech_utils::parse_transcribed_message_text(text) {
// This is a transcription message. We remove the prefix and consider it as a message sent by the user.
// sender_id is None because the original speaker is unknown.
2024-09-12 13:44:06 +03:00
return Some(Message {
author: Author::User,
sender_id: None,
content: MessageContent::Text(text.to_owned()),
timestamp: timestamp.to_owned(),
2024-09-12 13:44:06 +03:00
});
}
None
}
fn convert_user_message(matrix_message: &MatrixMessage) -> Option<Message> {
match &matrix_message.content {
2025-05-10 11:47:50 +03:00
MatrixMessageContent::Text(text) => Some(Message {
author: Author::User,
sender_id: Some(matrix_message.sender_id.clone()),
2025-05-10 11:47:50 +03:00
content: MessageContent::Text(text.clone()),
timestamp: matrix_message.timestamp.to_owned(),
}),
MatrixMessageContent::Notice(text) => Some(Message {
author: Author::User,
sender_id: Some(matrix_message.sender_id.clone()),
2025-05-10 11:47:50 +03:00
content: MessageContent::Text(text.clone()),
timestamp: matrix_message.timestamp.to_owned(),
}),
MatrixMessageContent::Image(image_content, mime_type, media_bytes) => Some(Message {
author: Author::User,
sender_id: Some(matrix_message.sender_id.clone()),
2025-05-10 11:47:50 +03:00
content: MessageContent::Image(ImageDetails::new(
image_content.clone(),
mime_type.clone(),
media_bytes.clone(),
)),
timestamp: matrix_message.timestamp.to_owned(),
}),
MatrixMessageContent::File(file_content, mime_type, media_bytes) => Some(Message {
author: Author::User,
sender_id: Some(matrix_message.sender_id.clone()),
content: MessageContent::File(FileDetails::new(
file_content.clone(),
mime_type.clone(),
media_bytes.clone(),
)),
timestamp: matrix_message.timestamp.to_owned(),
}),
}
2024-09-12 13:44:06 +03:00
}