Move report_assistant_event
into language_model
crate (#25508)
This PR moves the `report_assistant_event` function from the `language_models` crate to the `language_model` crate. This allows us to drop some dependencies on `language_models`. Release Notes: - N/A
This commit is contained in:
parent
e06666759a
commit
e5b97a5e48
15 changed files with 28 additions and 34 deletions
|
@ -19,6 +19,7 @@ test-support = []
|
|||
anthropic = { workspace = true, features = ["schemars"] }
|
||||
anyhow.workspace = true
|
||||
base64.workspace = true
|
||||
client.workspace = true
|
||||
collections.workspace = true
|
||||
futures.workspace = true
|
||||
google_ai = { workspace = true, features = ["schemars"] }
|
||||
|
@ -34,6 +35,7 @@ serde.workspace = true
|
|||
serde_json.workspace = true
|
||||
smol.workspace = true
|
||||
strum.workspace = true
|
||||
telemetry_events.workspace = true
|
||||
thiserror.workspace = true
|
||||
ui.workspace = true
|
||||
util.workspace = true
|
||||
|
|
|
@ -3,6 +3,7 @@ mod rate_limiter;
|
|||
mod registry;
|
||||
mod request;
|
||||
mod role;
|
||||
mod telemetry;
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub mod fake_provider;
|
||||
|
@ -11,12 +12,7 @@ use anyhow::Result;
|
|||
use futures::FutureExt;
|
||||
use futures::{future::BoxFuture, stream::BoxStream, StreamExt, TryStreamExt as _};
|
||||
use gpui::{AnyElement, AnyView, App, AsyncApp, SharedString, Task, Window};
|
||||
pub use model::*;
|
||||
use proto::Plan;
|
||||
pub use rate_limiter::*;
|
||||
pub use registry::*;
|
||||
pub use request::*;
|
||||
pub use role::*;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
@ -24,6 +20,13 @@ use std::{future::Future, sync::Arc};
|
|||
use thiserror::Error;
|
||||
use ui::IconName;
|
||||
|
||||
pub use crate::model::*;
|
||||
pub use crate::rate_limiter::*;
|
||||
pub use crate::registry::*;
|
||||
pub use crate::request::*;
|
||||
pub use crate::role::*;
|
||||
pub use crate::telemetry::*;
|
||||
|
||||
pub const ZED_CLOUD_PROVIDER_ID: &str = "zed.dev";
|
||||
|
||||
pub fn init(cx: &mut App) {
|
||||
|
|
90
crates/language_model/src/telemetry.rs
Normal file
90
crates/language_model/src/telemetry.rs
Normal file
|
@ -0,0 +1,90 @@
|
|||
use anthropic::{AnthropicError, ANTHROPIC_API_URL};
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use client::telemetry::Telemetry;
|
||||
use gpui::BackgroundExecutor;
|
||||
use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest};
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase};
|
||||
use util::ResultExt;
|
||||
|
||||
pub const ANTHROPIC_PROVIDER_ID: &str = "anthropic";
|
||||
|
||||
pub fn report_assistant_event(
|
||||
event: AssistantEvent,
|
||||
telemetry: Option<Arc<Telemetry>>,
|
||||
client: Arc<dyn HttpClient>,
|
||||
model_api_key: Option<String>,
|
||||
executor: &BackgroundExecutor,
|
||||
) {
|
||||
if let Some(telemetry) = telemetry.as_ref() {
|
||||
telemetry.report_assistant_event(event.clone());
|
||||
if telemetry.metrics_enabled() && event.model_provider == ANTHROPIC_PROVIDER_ID {
|
||||
executor
|
||||
.spawn(async move {
|
||||
report_anthropic_event(event, client, model_api_key)
|
||||
.await
|
||||
.log_err();
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn report_anthropic_event(
|
||||
event: AssistantEvent,
|
||||
client: Arc<dyn HttpClient>,
|
||||
model_api_key: Option<String>,
|
||||
) -> Result<(), AnthropicError> {
|
||||
let api_key = match model_api_key {
|
||||
Some(key) => key,
|
||||
None => {
|
||||
return Err(AnthropicError::Other(anyhow!(
|
||||
"Anthropic API key is not set"
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
let uri = format!("{ANTHROPIC_API_URL}/v1/log/zed");
|
||||
let request_builder = HttpRequest::builder()
|
||||
.method(Method::POST)
|
||||
.uri(uri)
|
||||
.header("X-Api-Key", api_key)
|
||||
.header("Content-Type", "application/json");
|
||||
let serialized_event: serde_json::Value = serde_json::json!({
|
||||
"completion_type": match event.kind {
|
||||
AssistantKind::Inline => "natural_language_completion_in_editor",
|
||||
AssistantKind::InlineTerminal => "natural_language_completion_in_terminal",
|
||||
AssistantKind::Panel => "conversation_message",
|
||||
},
|
||||
"event": match event.phase {
|
||||
AssistantPhase::Response => "response",
|
||||
AssistantPhase::Invoked => "invoke",
|
||||
AssistantPhase::Accepted => "accept",
|
||||
AssistantPhase::Rejected => "reject",
|
||||
},
|
||||
"metadata": {
|
||||
"language_name": event.language_name,
|
||||
"message_id": event.message_id,
|
||||
"platform": env::consts::OS,
|
||||
}
|
||||
});
|
||||
|
||||
let request = request_builder
|
||||
.body(AsyncBody::from(serialized_event.to_string()))
|
||||
.context("failed to construct request body")?;
|
||||
|
||||
let response = client
|
||||
.send(request)
|
||||
.await
|
||||
.context("failed to send request to Anthropic")?;
|
||||
|
||||
if response.status().is_success() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
return Err(AnthropicError::Other(anyhow!(
|
||||
"Failed to log: {}",
|
||||
response.status(),
|
||||
)));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue