diff --git a/Cargo.lock b/Cargo.lock index d3a2440977403ce50f21281e27300b98cfaf2a1e..739479882ca76db85ce3442919348c5a7932db6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18391,9 +18391,9 @@ dependencies = [ [[package]] name = "zed_llm_client" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91b8b05f1028157205026e525869eb860fa89bec87ea60b445efc91d05df31f" +checksum = "ad17428120f5ca776dc5195e2411a282f5150a26d5536671f8943c622c31274f" dependencies = [ "anyhow", "serde", diff --git a/Cargo.toml b/Cargo.toml index edfe44483ff5a556fbf920c1030cff8e88df6cab..05fee5fb3926ed3e376353dcab3b090371967fa7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -605,7 +605,7 @@ wasmtime-wasi = "29" which = "6.0.0" wit-component = "0.221" workspace-hack = "0.1.0" -zed_llm_client = "0.6.0" +zed_llm_client = "0.6.1" zstd = "0.11" metal = "0.29" diff --git a/crates/agent/src/active_thread.rs b/crates/agent/src/active_thread.rs index 5dddbd23ad85c89c3801e01f2dbde2c8a8b4fd5f..6899e26fe550901587a010e2b1730e170103854f 100644 --- a/crates/agent/src/active_thread.rs +++ b/crates/agent/src/active_thread.rs @@ -1212,6 +1212,8 @@ impl ActiveThread { } let request = language_model::LanguageModelRequest { + thread_id: None, + prompt_id: None, messages: vec![LanguageModelRequestMessage { role: language_model::Role::User, content: vec![content.into()], @@ -1277,6 +1279,7 @@ impl ActiveThread { } self.thread.update(cx, |thread, cx| { + thread.advance_prompt_id(); thread.send_to_model(model.model, RequestKind::Chat, cx) }); cx.notify(); diff --git a/crates/agent/src/buffer_codegen.rs b/crates/agent/src/buffer_codegen.rs index 3cd9306fa778f152aa2749ec8113fcb4bb69d231..bd8bf29758d26164ce52f7cbd0edf1e6d6308f4e 100644 --- a/crates/agent/src/buffer_codegen.rs +++ b/crates/agent/src/buffer_codegen.rs @@ -425,6 +425,8 @@ impl CodegenAlternative { request_message.content.push(prompt.into()); Ok(LanguageModelRequest { + thread_id: None, + prompt_id: None, tools: Vec::new(), stop: Vec::new(), temperature: None, diff --git a/crates/agent/src/message_editor.rs b/crates/agent/src/message_editor.rs index 73ca95888d1fba5a29af69b67fafcbc1d67c7e69..d64c95b9b99301da0ed900510d3dc4b0dff819d5 100644 --- a/crates/agent/src/message_editor.rs +++ b/crates/agent/src/message_editor.rs @@ -330,6 +330,7 @@ impl MessageEditor { // Send to model after summaries are done thread .update(cx, |thread, cx| { + thread.advance_prompt_id(); thread.send_to_model(model, request_kind, cx); }) .log_err(); @@ -1013,6 +1014,8 @@ impl MessageEditor { } let request = language_model::LanguageModelRequest { + thread_id: None, + prompt_id: None, messages: vec![LanguageModelRequestMessage { role: language_model::Role::User, content: vec![content.into()], diff --git a/crates/agent/src/terminal_inline_assistant.rs b/crates/agent/src/terminal_inline_assistant.rs index de3c96fc155ffc114bf46c7b0e836ce05b2dc6f2..95099e542c896e8897e7171c62ab8cbf8832e6cf 100644 --- a/crates/agent/src/terminal_inline_assistant.rs +++ b/crates/agent/src/terminal_inline_assistant.rs @@ -261,6 +261,8 @@ impl TerminalInlineAssistant { request_message.content.push(prompt.into()); Ok(LanguageModelRequest { + thread_id: None, + prompt_id: None, messages: vec![request_message], tools: Vec::new(), stop: Vec::new(), diff --git a/crates/agent/src/thread.rs b/crates/agent/src/thread.rs index ea9db9d9f5a9e71a0402b780f38d291cf4a3b1cb..a7044b01004eb38120dda397ea774762ec35f104 100644 --- a/crates/agent/src/thread.rs +++ b/crates/agent/src/thread.rs @@ -70,6 +70,24 @@ impl From<&str> for ThreadId { } } +/// The ID of the user prompt that initiated a request. +/// +/// This equates to the user physically submitting a message to the model (e.g., by pressing the Enter key). +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)] +pub struct PromptId(Arc); + +impl PromptId { + pub fn new() -> Self { + Self(Uuid::new_v4().to_string().into()) + } +} + +impl std::fmt::Display for PromptId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize)] pub struct MessageId(pub(crate) usize); @@ -274,6 +292,7 @@ pub struct Thread { detailed_summary_state: DetailedSummaryState, messages: Vec, next_message_id: MessageId, + last_prompt_id: PromptId, context: BTreeMap, context_by_message: HashMap>, project_context: SharedProjectContext, @@ -320,6 +339,7 @@ impl Thread { detailed_summary_state: DetailedSummaryState::NotGenerated, messages: Vec::new(), next_message_id: MessageId(0), + last_prompt_id: PromptId::new(), context: BTreeMap::default(), context_by_message: HashMap::default(), project_context: system_prompt, @@ -393,6 +413,7 @@ impl Thread { }) .collect(), next_message_id, + last_prompt_id: PromptId::new(), context: BTreeMap::default(), context_by_message: HashMap::default(), project_context, @@ -432,6 +453,10 @@ impl Thread { self.updated_at = Utc::now(); } + pub fn advance_prompt_id(&mut self) { + self.last_prompt_id = PromptId::new(); + } + pub fn summary(&self) -> Option { self.summary.clone() } @@ -942,6 +967,8 @@ impl Thread { cx: &mut Context, ) -> LanguageModelRequest { let mut request = LanguageModelRequest { + thread_id: Some(self.id.to_string()), + prompt_id: Some(self.last_prompt_id.to_string()), messages: vec![], tools: Vec::new(), stop: Vec::new(), @@ -1083,6 +1110,7 @@ impl Thread { cx: &mut Context, ) { let pending_completion_id = post_inc(&mut self.completion_count); + let prompt_id = self.last_prompt_id.clone(); let task = cx.spawn(async move |thread, cx| { let stream_completion_future = model.stream_completion_with_usage(request, &cx); let initial_token_usage = @@ -1273,6 +1301,7 @@ impl Thread { telemetry::event!( "Assistant Thread Completion", thread_id = thread.id().to_string(), + prompt_id = prompt_id, model = model.telemetry_id(), model_provider = model.provider_id().to_string(), input_tokens = usage.input_tokens, diff --git a/crates/assistant/src/inline_assistant.rs b/crates/assistant/src/inline_assistant.rs index d5914292dec0975665b1a1c8cc64ce4ec046185c..b7ba199d839e0f93e48907957e0d8e71f7e2d94f 100644 --- a/crates/assistant/src/inline_assistant.rs +++ b/crates/assistant/src/inline_assistant.rs @@ -2978,6 +2978,8 @@ impl CodegenAlternative { }); Ok(LanguageModelRequest { + thread_id: None, + prompt_id: None, messages, tools: Vec::new(), stop: Vec::new(), diff --git a/crates/assistant/src/terminal_inline_assistant.rs b/crates/assistant/src/terminal_inline_assistant.rs index 90e59cf376821aa8dbfa0db07301cc04e2b30110..db50193d2ea8d8b240a4721964a5edf4d44bbec1 100644 --- a/crates/assistant/src/terminal_inline_assistant.rs +++ b/crates/assistant/src/terminal_inline_assistant.rs @@ -292,6 +292,8 @@ impl TerminalInlineAssistant { }); Ok(LanguageModelRequest { + thread_id: None, + prompt_id: None, messages, tools: Vec::new(), stop: Vec::new(), diff --git a/crates/assistant_context_editor/src/context.rs b/crates/assistant_context_editor/src/context.rs index b68b140d3088e0b5ae1ca20f0840ca7091df61a9..097cdb6ad50f4f729d0be173e2934a4032299706 100644 --- a/crates/assistant_context_editor/src/context.rs +++ b/crates/assistant_context_editor/src/context.rs @@ -2555,6 +2555,8 @@ impl AssistantContext { } let mut completion_request = LanguageModelRequest { + thread_id: None, + prompt_id: None, messages: Vec::new(), tools: Vec::new(), stop: Vec::new(), diff --git a/crates/eval/src/example.rs b/crates/eval/src/example.rs index 6210b6b434c8644441ab5460a92f6b5046e6ec50..04681c43ff815ae5e226efd5a5105e38d500e9e1 100644 --- a/crates/eval/src/example.rs +++ b/crates/eval/src/example.rs @@ -499,6 +499,8 @@ impl Example { )?; let request = LanguageModelRequest { + thread_id: None, + prompt_id: None, messages: vec![LanguageModelRequestMessage { role: Role::User, content: vec![MessageContent::Text(prompt)], diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index a2a776a29ce0c62abb7a1639b39f66f4dbcc5ee5..f30f116c47d891f516efe6c831dc9f1cc05681f5 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -1739,6 +1739,8 @@ impl GitPanel { const PROMPT: &str = include_str!("commit_message_prompt.txt"); let request = LanguageModelRequest { + thread_id: None, + prompt_id: None, messages: vec![LanguageModelRequestMessage { role: Role::User, content: vec![content.into()], diff --git a/crates/language_model/src/request.rs b/crates/language_model/src/request.rs index 696e3644f6b3999f96428b51c51bea109408bdeb..754b1671bb0593fd77a1d602f7bbeaba8daacadb 100644 --- a/crates/language_model/src/request.rs +++ b/crates/language_model/src/request.rs @@ -238,6 +238,8 @@ pub struct LanguageModelRequestTool { #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)] pub struct LanguageModelRequest { + pub thread_id: Option, + pub prompt_id: Option, pub messages: Vec, pub tools: Vec, pub stop: Vec, diff --git a/crates/language_models/src/provider/cloud.rs b/crates/language_models/src/provider/cloud.rs index 25a048537be2017abf04f457d9dedea897206246..525125354b741d2a91c4efe85923f1ebd9d6f18c 100644 --- a/crates/language_models/src/provider/cloud.rs +++ b/crates/language_models/src/provider/cloud.rs @@ -719,7 +719,7 @@ impl LanguageModel for CloudLanguageModel { fn stream_completion_with_usage( &self, - request: LanguageModelRequest, + mut request: LanguageModelRequest, _cx: &AsyncApp, ) -> BoxFuture< 'static, @@ -728,6 +728,8 @@ impl LanguageModel for CloudLanguageModel { Option, )>, > { + let thread_id = request.prompt_id.take(); + let prompt_id = request.prompt_id.take(); match &self.model { CloudModel::Anthropic(model) => { let request = into_anthropic( @@ -744,6 +746,8 @@ impl LanguageModel for CloudLanguageModel { client.clone(), llm_api_token, CompletionBody { + thread_id, + prompt_id, provider: zed_llm_client::LanguageModelProvider::Anthropic, model: request.model.clone(), provider_request: serde_json::to_value(&request)?, @@ -788,6 +792,8 @@ impl LanguageModel for CloudLanguageModel { client.clone(), llm_api_token, CompletionBody { + thread_id, + prompt_id, provider: zed_llm_client::LanguageModelProvider::OpenAi, model: request.model.clone(), provider_request: serde_json::to_value(&request)?, @@ -816,6 +822,8 @@ impl LanguageModel for CloudLanguageModel { client.clone(), llm_api_token, CompletionBody { + thread_id, + prompt_id, provider: zed_llm_client::LanguageModelProvider::Google, model: request.model.clone(), provider_request: serde_json::to_value(&request)?, diff --git a/crates/prompt_library/src/prompt_library.rs b/crates/prompt_library/src/prompt_library.rs index 5ed987f955cbe7229f3b1fab9757ec08457da4a0..a0e9fbc9a360a47ea04bc9df36c0696aa943deb1 100644 --- a/crates/prompt_library/src/prompt_library.rs +++ b/crates/prompt_library/src/prompt_library.rs @@ -924,6 +924,8 @@ impl PromptLibrary { .update(|_, cx| { model.count_tokens( LanguageModelRequest { + thread_id: None, + prompt_id: None, messages: vec![LanguageModelRequestMessage { role: Role::System, content: vec![body.to_string().into()], diff --git a/crates/semantic_index/src/summary_index.rs b/crates/semantic_index/src/summary_index.rs index 397b5f07d52cf262802e6d36d3fd8b844545c506..f1b829f9b5a36ad7f9dfd0b817eed3172ded30c3 100644 --- a/crates/semantic_index/src/summary_index.rs +++ b/crates/semantic_index/src/summary_index.rs @@ -557,6 +557,8 @@ impl SummaryIndex { ); let request = LanguageModelRequest { + thread_id: None, + prompt_id: None, messages: vec![LanguageModelRequestMessage { role: Role::User, content: vec![prompt.into()],