-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
re-organisate chat files, continue last conversation if settings are …
…equal
- Loading branch information
Showing
16 changed files
with
247 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 3 additions & 2 deletions
5
lumni/src/apps/builtin/llm/prompt/src/chat/conversation/cache.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 10 additions & 71 deletions
81
lumni/src/apps/builtin/llm/prompt/src/chat/conversation/mod.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,16 @@ | ||
use serde::{Deserialize, Serialize}; | ||
|
||
mod cache; | ||
mod model; | ||
|
||
mod instruction; | ||
mod prepare; | ||
pub use cache::ConversationCache; | ||
pub use model::{ModelIdentifier, ModelSpec}; | ||
|
||
use super::PromptRole; | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] | ||
pub struct ModelServerName(pub String); | ||
|
||
impl ModelServerName { | ||
pub fn from_str<T: AsRef<str>>(s: T) -> Self { | ||
ModelServerName(s.as_ref().to_string()) | ||
} | ||
|
||
pub fn to_string(&self) -> String { | ||
self.0.clone() | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] | ||
pub struct ConversationId(pub i64); | ||
use db::{ConversationId, MessageId}; | ||
pub use instruction::PromptInstruction; | ||
pub use prepare::NewConversation; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] | ||
pub struct MessageId(pub i64); | ||
pub use super::db; | ||
use super::{ChatCompletionOptions, ChatMessage, PromptRole}; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] | ||
pub struct AttachmentId(pub i64); | ||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)] | ||
pub struct Conversation { | ||
#[derive(Debug, Clone)] | ||
pub struct ParentConversation { | ||
pub id: ConversationId, | ||
pub name: String, | ||
pub info: serde_json::Value, | ||
pub model_identifier: ModelIdentifier, | ||
pub parent_conversation_id: Option<ConversationId>, | ||
pub fork_message_id: Option<MessageId>, // New field | ||
pub completion_options: Option<serde_json::Value>, | ||
pub created_at: i64, | ||
pub updated_at: i64, | ||
pub is_deleted: bool, | ||
} | ||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)] | ||
pub struct Message { | ||
pub id: MessageId, | ||
pub conversation_id: ConversationId, | ||
pub role: PromptRole, | ||
pub message_type: String, | ||
pub content: String, | ||
pub has_attachments: bool, | ||
pub token_length: Option<i64>, | ||
pub previous_message_id: Option<MessageId>, | ||
pub created_at: i64, | ||
pub is_deleted: bool, | ||
} | ||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)] | ||
pub enum AttachmentData { | ||
Uri(String), | ||
Data(Vec<u8>), | ||
} | ||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)] | ||
pub struct Attachment { | ||
pub attachment_id: AttachmentId, | ||
pub message_id: MessageId, | ||
pub conversation_id: ConversationId, | ||
pub data: AttachmentData, // file_uri or file_data | ||
pub file_type: String, | ||
pub metadata: Option<serde_json::Value>, | ||
pub created_at: i64, | ||
pub is_deleted: bool, | ||
pub fork_message_id: MessageId, | ||
} |
114 changes: 114 additions & 0 deletions
114
lumni/src/apps/builtin/llm/prompt/src/chat/conversation/prepare.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
use lumni::api::error::ApplicationError; | ||
|
||
use super::db::{ConversationReader, Message, ModelServerName, ModelSpec}; | ||
use super::{ParentConversation, PromptRole}; | ||
pub use crate::external as lumni; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct NewConversation { | ||
pub server: ModelServerName, | ||
pub model: Option<ModelSpec>, | ||
pub options: Option<serde_json::Value>, | ||
pub system_prompt: Option<String>, // system_prompt ignored if parent is provided | ||
pub initial_messages: Option<Vec<Message>>, // initial_messages ignored if parent is provided | ||
pub parent: Option<ParentConversation>, // forked conversation | ||
} | ||
|
||
impl NewConversation { | ||
pub fn new( | ||
new_server: ModelServerName, | ||
new_model: ModelSpec, | ||
conversation_reader: Option<&ConversationReader<'_>>, | ||
) -> Result<NewConversation, ApplicationError> { | ||
if let Some(reader) = conversation_reader { | ||
// fork from an existing conversation | ||
let current_conversation_id = reader.get_conversation_id(); | ||
let mut current_completion_options = | ||
reader.get_completion_options()?; | ||
|
||
current_completion_options["model_server"] = | ||
serde_json::to_value(new_server.clone())?; | ||
|
||
if let Some(last_message_id) = reader.get_last_message_id()? { | ||
Ok(NewConversation { | ||
server: new_server, | ||
model: Some(new_model), | ||
options: Some(current_completion_options), | ||
system_prompt: None, // ignored when forking | ||
initial_messages: None, // ignored when forking | ||
parent: Some(ParentConversation { | ||
id: current_conversation_id, | ||
fork_message_id: last_message_id, | ||
}), | ||
}) | ||
} else { | ||
// start a new conversation, as there is no last message is there is nothing to fork from. | ||
// Both system_prompt and assistant_name are set to None, because if no messages exist, these were also None in the (empty) parent conversation | ||
Ok(NewConversation { | ||
server: new_server, | ||
model: Some(new_model), | ||
options: Some(current_completion_options), | ||
system_prompt: None, | ||
initial_messages: None, | ||
parent: None, | ||
}) | ||
} | ||
} else { | ||
// start a new conversation | ||
let completion_options = serde_json::json!({ | ||
"model_server": new_server, | ||
}); | ||
Ok(NewConversation { | ||
server: new_server, | ||
model: Some(new_model), | ||
options: Some(completion_options), | ||
system_prompt: None, | ||
initial_messages: None, | ||
parent: None, | ||
}) | ||
} | ||
} | ||
|
||
pub fn is_equal( | ||
&self, | ||
reader: &ConversationReader, | ||
) -> Result<bool, ApplicationError> { | ||
// check if conversation settings are equal to the conversation stored in the database | ||
|
||
// Compare model | ||
let last_model = reader.get_model_spec()?; | ||
if self.model.as_ref() != Some(&last_model) { | ||
return Ok(false); | ||
} | ||
|
||
// Compare completion options (which includes server name and assistant) | ||
let last_options = reader.get_completion_options()?; | ||
let new_options = match &self.options { | ||
Some(opts) => opts.clone(), | ||
None => serde_json::json!({}), | ||
}; | ||
if last_options != new_options { | ||
return Ok(false); | ||
} | ||
|
||
// Compare system prompt. If the system prompt is not set in the new conversation, we check by first system prompt in the initial messages | ||
let last_system_prompt = reader.get_system_prompt()?; | ||
let new_system_prompt = match &self.system_prompt { | ||
Some(prompt) => Some(prompt.as_str()), | ||
None => self.initial_messages.as_ref().and_then(|messages| { | ||
messages.first().and_then(|msg| { | ||
if msg.role == PromptRole::System { | ||
Some(msg.content.as_str()) | ||
} else { | ||
None | ||
} | ||
}) | ||
}), | ||
}; | ||
if last_system_prompt.as_deref() != new_system_prompt { | ||
return Ok(false); | ||
} | ||
// Conversation settings are equal | ||
Ok(true) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.