Allow for prompt caching to work by using baibot_conversation_start_time_utc instead of baibot_now_utc

This patch introduces a new `baibot_conversation_start_time_utc`
variable which indicates the time the conversation got started.

Using `baibot_now_utc` is still possible, but given that the current
time is a moving target, its use is in conflict with prompt caching.

Because the new `baibot_conversation_start_time_utc` prompt variable
is a more reasonable default, we're now using it in all sample configs.
This commit is contained in:
Slavi Pantaleev
2024-10-03 11:48:14 +03:00
parent db9422740c
commit 85e66406dc
25 changed files with 159 additions and 25 deletions

View File

@@ -77,11 +77,14 @@ Prompts may contain the following **placeholder variables** which will be replac
|---------------------------|-------------|---------|
| `{{ baibot_name }}` | Name of the bot as configured in the `user.name` field in the [Static configuration](./README.md#static-configuration) | `Baibot` |
| `{{ baibot_model_id }}` | Text-Generation model ID as configured in the [🤖 agent](../agents.md)'s configuration | `gpt-4o` |
| `{{ baibot_now_utc }}` | Current date and time in UTC | `2024-09-20 (Friday), 14:26:42 UTC` |
| `{{ baibot_now_utc }}` | Current date and time in UTC (⚠️ usage may break prompt caching - see below) | `2024-09-20 (Friday), 14:26:42 UTC` |
| `{{ baibot_conversation_start_time_utc }}` | The date and time in UTC that the conversation started | `2024-09-20 (Friday), 14:26:42 UTC` |
💡 `{{ baibot_now_utc }}` changes as time goes on, which prevents [prompt caching](https://platform.openai.com/docs/guides/prompt-caching) from working. It's better to use `{{ baibot_conversation_start_time_utc }}` in prompts, as its value doesn't change yet still orients the bot to the current date/time.
Here's a prompt that combines some of the above variables:
> You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
> You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
### 🌡️ Temperature Override

View File

@@ -2,7 +2,7 @@ base_url: https://api.anthropic.com/v1
api_key: YOUR_API_KEY_HERE
text_generation:
model_id: claude-3-5-sonnet-20240620
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
temperature: 1.0
max_response_tokens: 8192
max_context_tokens: 204800

View File

@@ -2,7 +2,7 @@ base_url: https://api.groq.com/openai/v1
api_key: YOUR_API_KEY_HERE
text_generation:
model_id: llama3-70b-8192
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
temperature: 1.0
max_response_tokens: 4096
max_context_tokens: 131072

View File

@@ -2,7 +2,7 @@ base_url: http://my-localai-self-hosted-service:8080/v1
api_key: YOUR_API_KEY_HERE
text_generation:
model_id: gpt-4
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
temperature: 1.0
max_response_tokens: 4096
max_context_tokens: 128000

View File

@@ -2,7 +2,7 @@ base_url: https://api.mistral.ai/v1
api_key: YOUR_API_KEY_HERE
text_generation:
model_id: mistral-large-latest
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
temperature: 1.0
max_response_tokens: 4096
max_context_tokens: 128000

View File

@@ -2,7 +2,7 @@ base_url: http://my-ollama-self-hosted-service:11434/v1
api_key: YOUR_API_KEY_HERE
text_generation:
model_id: gemma2:2b
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
temperature: 1.0
max_response_tokens: 4096
max_context_tokens: 128000

View File

@@ -2,7 +2,7 @@ base_url: ''
api_key: YOUR_API_KEY_HERE
text_generation:
model_id: some-model
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
temperature: 1.0
max_response_tokens: 4096
max_context_tokens: 128000

View File

@@ -2,7 +2,7 @@ base_url: https://api.openai.com/v1
api_key: YOUR_API_KEY_HERE
text_generation:
model_id: gpt-4o
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
temperature: 1.0
max_response_tokens: 16384
max_context_tokens: 128000

View File

@@ -2,7 +2,7 @@ base_url: https://openrouter.ai/api/v1
api_key: YOUR_API_KEY_HERE
text_generation:
model_id: mattshumer/reflection-70b:free
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
temperature: 1.0
max_response_tokens: 2048
max_context_tokens: 8192

View File

@@ -2,7 +2,7 @@ base_url: https://api.together.xyz/v1
api_key: YOUR_API_KEY_HERE
text_generation:
model_id: meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
temperature: 1.0
max_response_tokens: 2048
max_context_tokens: 8192

View File

@@ -73,7 +73,7 @@ agents:
# api_key: ""
# text_generation:
# model_id: gpt-4o
# prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
# prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
# temperature: 1.0
# max_response_tokens: 16384
# max_context_tokens: 128000
@@ -97,7 +97,7 @@ agents:
# api_key: null
# text_generation:
# model_id: gpt-4
# prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
# prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
# temperature: 1.0
# max_response_tokens: 16384
# max_context_tokens: 128000
@@ -122,7 +122,7 @@ agents:
# api_key: null
# text_generation:
# model_id: "gemma2:2b"
# prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
# prompt: "You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
# temperature: 1.0
# max_response_tokens: 4096
# max_context_tokens: 128000

View File

@@ -21,5 +21,5 @@ pub use provider::{AgentProvider, AgentProviderInfo, ControllerTrait};
pub use purpose::AgentPurpose;
pub(super) fn default_prompt() -> &'static str {
"You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time now is: {{ baibot_now_utc }}."
"You are a brief, but helpful bot called {{ baibot_name }} powered by the {{ baibot_model_id }} model. The date/time of this conversation's start is: {{ baibot_conversation_start_time_utc }}."
}

View File

@@ -72,6 +72,7 @@ impl ControllerTrait for Controller {
let messages = vec![LLMMessage {
author: LLMAuthor::User,
message_text: "Hello!".to_string(),
timestamp: chrono::Utc::now(),
}];
let conversation = LLMConversation { messages };
@@ -108,6 +109,7 @@ impl ControllerTrait for Controller {
Some(LLMMessage {
author: LLMAuthor::Prompt,
message_text: prompt_text,
timestamp: chrono::Utc::now(),
})
};

View File

@@ -7,17 +7,33 @@ pub struct TextGenerationPromptVariables {
impl Default for TextGenerationPromptVariables {
fn default() -> Self {
Self::new("unnamed", "unknown-model", Utc::now())
let now = Utc::now();
Self::new("unnamed", "unknown-model", now, Some(now))
}
}
impl TextGenerationPromptVariables {
pub fn new(bot_name: &str, model_id: &str, utc_time: DateTime<Utc>) -> Self {
pub fn new(
bot_name: &str,
model_id: &str,
now_time: DateTime<Utc>,
conversation_start_time: Option<DateTime<Utc>>,
) -> Self {
let mut map = HashMap::new();
map.insert("baibot_name".to_string(), bot_name.to_string());
map.insert("baibot_model_id".to_string(), model_id.to_string());
map.insert("baibot_now_utc".to_string(), format_utc_time(utc_time));
map.insert("baibot_now_utc".to_string(), format_utc_time(now_time));
let baibot_conversation_start_time_utc = match conversation_start_time {
Some(conversation_start_time) => format_utc_time(conversation_start_time),
None => "unknown".to_string(),
};
map.insert(
"baibot_conversation_start_time_utc".to_string(),
baibot_conversation_start_time_utc,
);
Self { map }
}
@@ -52,7 +68,18 @@ mod tests {
.with_nanosecond(250000000)
.unwrap();
let variables = TextGenerationPromptVariables::new("baibot", "gpt-4o", now_utc);
let conversation_start_time_utc = Utc
.with_ymd_and_hms(2024, 9, 19, 18, 34, 15)
.unwrap()
.with_nanosecond(250000000)
.unwrap();
let variables = TextGenerationPromptVariables::new(
"baibot",
"gpt-4o",
now_utc,
Some(conversation_start_time_utc),
);
assert_eq!(
variables.map.get("baibot_name"),
@@ -66,9 +93,13 @@ mod tests {
variables.map.get("baibot_now_utc"),
Some(&format_utc_time(now_utc))
);
assert_eq!(
variables.map.get("baibot_conversation_start_time_utc"),
Some(&format_utc_time(conversation_start_time_utc))
);
let prompt = "Hello, I'm {{ baibot_name }} using {{ baibot_model_id }}. The date/time now is {{ baibot_now_utc }}.";
let expected = "Hello, I'm baibot using gpt-4o. The date/time now is 2024-09-20 (Friday), 18:34:15 UTC.";
let prompt = "Hello, I'm {{ baibot_name }} using {{ baibot_model_id }}. The date/time now is {{ baibot_now_utc }} and this conversation started at {{ baibot_conversation_start_time_utc }}.";
let expected = "Hello, I'm baibot using gpt-4o. The date/time now is 2024-09-20 (Friday), 18:34:15 UTC and this conversation started at 2024-09-19 (Thursday), 18:34:15 UTC.";
assert_eq!(variables.format(prompt), expected);
}

View File

@@ -63,6 +63,7 @@ impl ControllerTrait for Controller {
let messages = vec![LLMMessage {
author: LLMAuthor::User,
message_text: "Hello!".to_string(),
timestamp: chrono::Utc::now(),
}];
let conversation = LLMConversation { messages };
@@ -99,6 +100,7 @@ impl ControllerTrait for Controller {
Some(LLMMessage {
author: LLMAuthor::Prompt,
message_text: prompt_text,
timestamp: chrono::Utc::now(),
})
};

View File

@@ -61,6 +61,7 @@ impl ControllerTrait for Controller {
let messages = vec![LLMMessage {
author: LLMAuthor::User,
message_text: "Hello!".to_string(),
timestamp: chrono::Utc::now(),
}];
let conversation = LLMConversation { messages };
@@ -97,6 +98,7 @@ impl ControllerTrait for Controller {
Some(LLMMessage {
author: LLMAuthor::Prompt,
message_text: prompt_text,
timestamp: chrono::Utc::now(),
})
};

View File

@@ -492,6 +492,7 @@ async fn handle_stage_text_generation(
.text_generation_model_id()
.unwrap_or("unknown-model".to_owned()),
chrono::Utc::now(),
conversation.start_time(),
);
let params = TextGenerationParams {

View File

@@ -46,6 +46,8 @@ mod tests {
#[test]
fn test_build_prompt() {
let timestamp = chrono::Utc::now();
let test_cases = vec![
// Simple case
TestCase {
@@ -59,6 +61,7 @@ mod tests {
messages: vec![Message {
author: Author::User,
message_text: "Must be blue".to_owned(),
timestamp,
}],
expected_prompt: "Generate a picture of a dog\nOther criteria:\n- Must be blue",
},
@@ -68,14 +71,17 @@ mod tests {
messages: vec![Message {
author: Author::User,
message_text: "Must be blue".to_owned(),
timestamp,
},
Message {
author: Author::Assistant,
message_text: "Whatever".to_owned(),
timestamp,
},
Message {
author: Author::User,
message_text: "Must be 3-legged.\nMust be flying.".to_owned(),
timestamp,
}],
expected_prompt: "Generate a picture of an elephant\nOther criteria:\n- Must be blue\n- Must be 3-legged.. Must be flying.",
},
@@ -85,18 +91,22 @@ mod tests {
messages: vec![Message {
author: Author::User,
message_text: "Must be blue".to_owned(),
timestamp,
},
Message {
author: Author::Assistant,
message_text: "Whatever".to_owned(),
timestamp,
},
Message {
author: Author::User,
message_text: "Again".to_owned(),
timestamp,
},
Message {
author: Author::User,
message_text: "again".to_owned(),
timestamp,
}],
expected_prompt: "Generate a picture of a grizzly bear\nOther criteria:\n- Must be blue",
},

View File

@@ -1,3 +1,5 @@
use chrono::{DateTime, Utc};
#[derive(Debug, Clone, PartialEq)]
pub enum Author {
Prompt,
@@ -9,6 +11,7 @@ pub enum Author {
pub struct Message {
pub author: Author,
pub message_text: String,
pub timestamp: DateTime<Utc>,
}
#[derive(Debug)]
@@ -52,39 +55,59 @@ impl Conversation {
messages: new_messages,
}
}
pub fn start_time(&self) -> Option<DateTime<Utc>> {
self.messages.first().map(|message| message.timestamp)
}
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::{TimeZone, Utc};
#[test]
fn combine_consecutive_messages() {
let timestamp_1 = Utc.with_ymd_and_hms(2024, 9, 20, 18, 34, 15).unwrap();
let timestamp_2 = Utc.with_ymd_and_hms(2024, 9, 21, 18, 34, 15).unwrap();
let timestamp_3 = Utc.with_ymd_and_hms(2024, 9, 22, 18, 34, 15).unwrap();
let conversation = Conversation {
messages: vec![
// User's turn
Message {
author: Author::User,
message_text: "Hello".to_string(),
timestamp: timestamp_1,
},
Message {
author: Author::User,
message_text: "How are you?".to_string(),
timestamp: timestamp_2,
},
Message {
author: Author::User,
message_text: "I'm OK, btw.".to_string(),
timestamp: timestamp_3,
},
// Assistant's turn
Message {
author: Author::Assistant,
message_text: "Hi there!".to_string(),
timestamp: timestamp_2,
},
Message {
author: Author::Assistant,
message_text: "I'm doing well, thank you.".to_string(),
timestamp: timestamp_3,
},
// User's turn
Message {
author: Author::User,
message_text: "That's great!".to_string(),
timestamp: timestamp_3,
},
],
};
@@ -97,12 +120,17 @@ mod tests {
conversation.messages[0].message_text,
"Hello\nHow are you?\nI'm OK, btw."
);
assert_eq!(conversation.messages[0].timestamp, timestamp_1);
assert_eq!(conversation.messages[1].author, Author::Assistant);
assert_eq!(
conversation.messages[1].message_text,
"Hi there!\nI'm doing well, thank you."
);
assert_eq!(conversation.messages[1].timestamp, timestamp_2);
assert_eq!(conversation.messages[2].author, Author::User);
assert_eq!(conversation.messages[2].message_text, "That's great!");
assert_eq!(conversation.messages[2].timestamp, timestamp_3);
}
}

View File

@@ -15,6 +15,7 @@ fn test_messages_by_the_bot_are_identified_correctly() {
message_type: super::super::matrix::MatrixMessageType::Text,
message_text: "Hello!".to_owned(),
mentioned_users: vec![],
timestamp: chrono::Utc::now(),
};
let llm_message = convert_matrix_message_to_llm_message(&matrix_message, &bot_user_id).unwrap();
@@ -39,6 +40,7 @@ fn test_notice_messages_by_bot_with_speech_to_text_prefix_are_cleaned_up_and_con
message_type: super::super::matrix::MatrixMessageType::Notice,
message_text,
mentioned_users: vec![],
timestamp: chrono::Utc::now(),
};
let llm_message = convert_matrix_message_to_llm_message(&matrix_message, &bot_user_id).unwrap();
@@ -62,6 +64,7 @@ fn test_notice_error_messages_by_bot_are_ignored() {
message_type: super::super::matrix::MatrixMessageType::Notice,
message_text,
mentioned_users: vec![],
timestamp: chrono::Utc::now(),
};
let llm_message = convert_matrix_message_to_llm_message(&matrix_message, &bot_user_id);
@@ -86,6 +89,7 @@ fn test_other_notice_messages_by_the_bot_are_ignored() {
message_type: super::super::matrix::MatrixMessageType::Notice,
message_text: message_text.to_owned(),
mentioned_users: vec![],
timestamp: chrono::Utc::now(),
};
let llm_message = convert_matrix_message_to_llm_message(&matrix_message, &bot_user_id);

View File

@@ -86,6 +86,7 @@ pub mod test {
let message = super::Message {
author: super::Author::User,
message_text: "Hello there!".to_owned(),
timestamp: chrono::Utc::now(),
};
let tokens = super::calculate_token_size_for_message(&bpe, model, &message);
@@ -104,6 +105,7 @@ pub mod test {
let prompt = super::Message {
author: super::Author::Prompt,
message_text: "You are a bot!".to_owned(),
timestamp: chrono::Utc::now(),
};
let prompt_length = 10;
@@ -117,6 +119,7 @@ pub mod test {
let first = super::Message {
author: super::Author::User,
message_text: "Hello there!".to_owned(),
timestamp: chrono::Utc::now(),
};
let first_length = 8;
@@ -130,6 +133,7 @@ pub mod test {
let second = super::Message {
author: super::Author::Assistant,
message_text: "Hello!".to_owned(),
timestamp: chrono::Utc::now(),
};
let second_length = 7;
@@ -144,6 +148,7 @@ pub mod test {
author: super::Author::User,
message_text: "This is the 3rd message in this conversation. It shall be preserved."
.to_owned(),
timestamp: chrono::Utc::now(),
};
let third_length = 21;
@@ -157,6 +162,7 @@ pub mod test {
let forth = super::Message {
author: super::Author::Assistant,
message_text: "This is yet another message that shall be preserved.".to_owned(),
timestamp: chrono::Utc::now(),
};
let forth_length = 15;
@@ -201,6 +207,7 @@ pub mod test {
let prompt = super::Message {
author: super::Author::User,
message_text: "あなたはボットです。".to_owned(),
timestamp: chrono::Utc::now(),
};
let prompt_length = 14;
@@ -214,6 +221,7 @@ pub mod test {
let first = super::Message {
author: super::Author::User,
message_text: "こんにちは!".to_owned(),
timestamp: chrono::Utc::now(),
};
let first_length = 7;
@@ -227,6 +235,7 @@ pub mod test {
let second = super::Message {
author: super::Author::Assistant,
message_text: "こんにちは。今日は元気ですか。".to_owned(),
timestamp: chrono::Utc::now(),
};
let second_length = 15;
@@ -240,6 +249,7 @@ pub mod test {
let third = super::Message {
author: super::Author::User,
message_text: "これは第3のメッセージなので、保存されます。".to_owned(),
timestamp: chrono::Utc::now(),
};
let third_length = 22;
@@ -253,6 +263,7 @@ pub mod test {
let forth = super::Message {
author: super::Author::Assistant,
message_text: "これはもう一つの保存されますメッセージです。".to_owned(),
timestamp: chrono::Utc::now(),
};
let forth_length = 21;

View File

@@ -17,19 +17,30 @@ pub fn convert_matrix_message_to_llm_message(
fn convert_bot_message(matrix_message: &MatrixMessage) -> Option<Message> {
match matrix_message.message_type {
MatrixMessageType::Text => convert_bot_text_message(&matrix_message.message_text),
MatrixMessageType::Notice => convert_bot_notice_message(&matrix_message.message_text),
MatrixMessageType::Text => {
convert_bot_text_message(&matrix_message.message_text, &matrix_message.timestamp)
}
MatrixMessageType::Notice => {
convert_bot_notice_message(&matrix_message.message_text, &matrix_message.timestamp)
}
}
}
fn convert_bot_text_message(text: &str) -> Option<Message> {
fn convert_bot_text_message(
text: &str,
timestamp: &chrono::DateTime<chrono::Utc>,
) -> Option<Message> {
Some(Message {
author: Author::Assistant,
message_text: text.to_owned(),
timestamp: timestamp.to_owned(),
})
}
fn convert_bot_notice_message(text: &str) -> Option<Message> {
fn convert_bot_notice_message(
text: &str,
timestamp: &chrono::DateTime<chrono::Utc>,
) -> Option<Message> {
// 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.
@@ -42,6 +53,7 @@ fn convert_bot_notice_message(text: &str) -> Option<Message> {
return Some(Message {
author: Author::User,
message_text: text.to_owned(),
timestamp: timestamp.to_owned(),
});
}
@@ -52,5 +64,6 @@ fn convert_user_message(matrix_message: &MatrixMessage) -> Option<Message> {
Some(Message {
author: Author::User,
message_text: matrix_message.message_text.clone(),
timestamp: matrix_message.timestamp.to_owned(),
})
}

View File

@@ -1,3 +1,4 @@
use chrono::{DateTime, Utc};
use regex::Regex;
use mxlink::matrix_sdk::ruma::OwnedUserId;
@@ -8,6 +9,7 @@ pub struct MatrixMessage {
pub message_type: MatrixMessageType,
pub message_text: String,
pub mentioned_users: Vec<OwnedUserId>,
pub timestamp: DateTime<Utc>,
}
#[derive(Clone)]

View File

@@ -234,6 +234,13 @@ pub fn convert_matrix_native_event_to_matrix_message(
text
};
let timestamp = chrono::DateTime::<chrono::Utc>::from(
matrix_native_event
.origin_server_ts()
.to_system_time()
.unwrap_or_else(std::time::SystemTime::now),
);
let mentioned_users = room_message
.mentions
.map(|m| m.user_ids.iter().map(|u| u.to_owned()).collect())
@@ -248,6 +255,7 @@ pub fn convert_matrix_native_event_to_matrix_message(
},
message_text: text,
mentioned_users,
timestamp,
})
}

View File

@@ -1,3 +1,5 @@
use chrono::{TimeZone, Utc};
use mxlink::matrix_sdk::ruma::OwnedUserId;
use crate::conversation::matrix::{
@@ -11,11 +13,14 @@ fn is_message_from_allowed_sender() {
let allowed_user_id = OwnedUserId::try_from("@user.someone:example.com").unwrap();
let unallowed_user_id = OwnedUserId::try_from("@another:example.com").unwrap();
let timestamp = Utc.with_ymd_and_hms(2024, 9, 20, 18, 34, 15).unwrap();
let bot_message = MatrixMessage {
sender_id: bot_user_id.to_owned(),
message_type: MatrixMessageType::Text,
message_text: "Hello!".to_owned(),
mentioned_users: vec![],
timestamp,
};
let allowed_user_message = MatrixMessage {
@@ -23,6 +28,7 @@ fn is_message_from_allowed_sender() {
message_type: MatrixMessageType::Text,
message_text: "Hello!".to_owned(),
mentioned_users: vec![],
timestamp,
};
let unallowed_user_message = MatrixMessage {
@@ -30,6 +36,7 @@ fn is_message_from_allowed_sender() {
message_type: MatrixMessageType::Text,
message_text: "Hello!".to_owned(),
mentioned_users: vec![],
timestamp,
};
let parsed_regex = match mxidwc::parse_pattern("@user.*:example.com") {
@@ -77,11 +84,14 @@ async fn process_matrix_messages() {
let allowed_user_id = OwnedUserId::try_from("@user.someone:example.com").unwrap();
let unallowed_user_id = OwnedUserId::try_from("@another:example.com").unwrap();
let timestamp = Utc.with_ymd_and_hms(2024, 9, 20, 18, 34, 15).unwrap();
let allowed_user_message = MatrixMessage {
sender_id: allowed_user_id.to_owned(),
message_type: MatrixMessageType::Text,
message_text: "Hello from the user!".to_owned(),
mentioned_users: vec![],
timestamp,
};
let allowed_user_message_with_prefix = MatrixMessage {
@@ -89,6 +99,7 @@ async fn process_matrix_messages() {
message_type: MatrixMessageType::Text,
message_text: "!bai Hello from the user!".to_owned(),
mentioned_users: vec![],
timestamp,
};
let allowed_user_message_with_prefix_no_space = MatrixMessage {
@@ -96,6 +107,7 @@ async fn process_matrix_messages() {
message_type: MatrixMessageType::Text,
message_text: "!baiHello from the user!".to_owned(),
mentioned_users: vec![],
timestamp,
};
let allowed_user_message_with_prefix_full_width_space = MatrixMessage {
@@ -103,6 +115,7 @@ async fn process_matrix_messages() {
message_type: MatrixMessageType::Text,
message_text: "!bai Hello from the user!".to_owned(),
mentioned_users: vec![],
timestamp,
};
let bot_message = MatrixMessage {
@@ -110,6 +123,7 @@ async fn process_matrix_messages() {
message_type: MatrixMessageType::Text,
message_text: "Hello from the bot!".to_owned(),
mentioned_users: vec![],
timestamp,
};
let allowed_user_message_with_bot_mention = MatrixMessage {
@@ -117,6 +131,7 @@ async fn process_matrix_messages() {
message_type: MatrixMessageType::Text,
message_text: "@baibot: Hello from the user!".to_owned(),
mentioned_users: vec![bot_user_id.to_owned()],
timestamp,
};
// The message text is the same as above - it mentions the bot, but the actually-mentioned user is another user.
@@ -125,6 +140,7 @@ async fn process_matrix_messages() {
message_type: MatrixMessageType::Text,
message_text: allowed_user_message_with_bot_mention.message_text.clone(),
mentioned_users: vec![allowed_user_id.to_owned()],
timestamp,
};
let unallowed_user_message = MatrixMessage {
@@ -132,6 +148,7 @@ async fn process_matrix_messages() {
message_type: MatrixMessageType::Text,
message_text: "Hello from an unallowed user!".to_owned(),
mentioned_users: vec![],
timestamp,
};
let parsed_regex = match mxidwc::parse_pattern("@user.*:example.com") {