Compare commits
2 Commits
inline-ass
...
zeta2-navi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a2c92aa4a | ||
|
|
94cdcf9457 |
@@ -1397,6 +1397,13 @@
|
||||
"end": "settings_editor::FocusLastNavEntry"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Zeta2Inspector > Editor",
|
||||
"bindings": {
|
||||
"ctrl-h": "dev::Zeta2InspectorPrevious",
|
||||
"ctrl-l": "dev::Zeta2InspectorNext"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Zeta2Feedback > Editor",
|
||||
"bindings": {
|
||||
|
||||
@@ -12,8 +12,9 @@ use edit_prediction_context::{
|
||||
EditPredictionExcerptOptions, EditPredictionScoreOptions, SyntaxIndex, SyntaxIndexState,
|
||||
};
|
||||
use feature_flags::{FeatureFlag, FeatureFlagAppExt as _};
|
||||
use futures::AsyncReadExt as _;
|
||||
use futures::channel::{mpsc, oneshot};
|
||||
use futures::future::{BoxFuture, Shared};
|
||||
use futures::{AsyncReadExt as _, FutureExt};
|
||||
use gpui::http_client::{AsyncBody, Method};
|
||||
use gpui::{
|
||||
App, Entity, EntityId, Global, SemanticVersion, SharedString, Subscription, Task, WeakEntity,
|
||||
@@ -89,7 +90,7 @@ pub struct Zeta {
|
||||
projects: HashMap<EntityId, ZetaProject>,
|
||||
options: ZetaOptions,
|
||||
update_required: bool,
|
||||
debug_tx: Option<mpsc::UnboundedSender<PredictionDebugInfo>>,
|
||||
observe_tx: Option<mpsc::UnboundedSender<ObservedPredictionRequest>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -101,13 +102,15 @@ pub struct ZetaOptions {
|
||||
pub file_indexing_parallelism: usize,
|
||||
}
|
||||
|
||||
pub struct PredictionDebugInfo {
|
||||
pub request: predict_edits_v3::PredictEditsRequest,
|
||||
#[derive(Clone)]
|
||||
pub struct ObservedPredictionRequest {
|
||||
pub full_request: predict_edits_v3::PredictEditsRequest,
|
||||
pub retrieval_time: TimeDelta,
|
||||
pub buffer: WeakEntity<Buffer>,
|
||||
pub position: language::Anchor,
|
||||
pub local_prompt: Result<String, String>,
|
||||
pub response_rx: oneshot::Receiver<Result<predict_edits_v3::PredictEditsResponse, String>>,
|
||||
pub response:
|
||||
Shared<BoxFuture<'static, Result<predict_edits_v3::PredictEditsResponse, String>>>,
|
||||
}
|
||||
|
||||
pub type RequestDebugInfo = predict_edits_v3::DebugInfo;
|
||||
@@ -224,14 +227,14 @@ impl Zeta {
|
||||
},
|
||||
),
|
||||
update_required: false,
|
||||
debug_tx: None,
|
||||
observe_tx: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debug_info(&mut self) -> mpsc::UnboundedReceiver<PredictionDebugInfo> {
|
||||
let (debug_watch_tx, debug_watch_rx) = mpsc::unbounded();
|
||||
self.debug_tx = Some(debug_watch_tx);
|
||||
debug_watch_rx
|
||||
pub fn observe_requests(&mut self) -> mpsc::UnboundedReceiver<ObservedPredictionRequest> {
|
||||
let (tx, rx) = mpsc::unbounded();
|
||||
self.observe_tx = Some(tx);
|
||||
rx
|
||||
}
|
||||
|
||||
pub fn options(&self) -> &ZetaOptions {
|
||||
@@ -518,7 +521,7 @@ impl Zeta {
|
||||
.worktrees(cx)
|
||||
.map(|worktree| worktree.read(cx).snapshot())
|
||||
.collect::<Vec<_>>();
|
||||
let debug_tx = self.debug_tx.clone();
|
||||
let observe_tx = self.observe_tx.clone();
|
||||
|
||||
let events = project_state
|
||||
.map(|state| {
|
||||
@@ -616,28 +619,35 @@ impl Zeta {
|
||||
diagnostic_groups,
|
||||
diagnostic_groups_truncated,
|
||||
None,
|
||||
debug_tx.is_some(),
|
||||
observe_tx.is_some(),
|
||||
&worktree_snapshots,
|
||||
index_state.as_deref(),
|
||||
Some(options.max_prompt_bytes),
|
||||
options.prompt_format,
|
||||
);
|
||||
|
||||
let debug_response_tx = if let Some(debug_tx) = &debug_tx {
|
||||
let observe_response_tx = if let Some(observe_tx) = &observe_tx {
|
||||
let (response_tx, response_rx) = oneshot::channel();
|
||||
|
||||
let local_prompt = PlannedPrompt::populate(&request)
|
||||
.and_then(|p| p.to_prompt_string().map(|p| p.0))
|
||||
.map_err(|err| err.to_string());
|
||||
|
||||
debug_tx
|
||||
.unbounded_send(PredictionDebugInfo {
|
||||
request: request.clone(),
|
||||
observe_tx
|
||||
.unbounded_send(ObservedPredictionRequest {
|
||||
full_request: request.clone(),
|
||||
retrieval_time,
|
||||
buffer: buffer.downgrade(),
|
||||
local_prompt,
|
||||
position,
|
||||
response_rx,
|
||||
response: async move {
|
||||
let resp = response_rx
|
||||
.await
|
||||
.map_err(|_: oneshot::Canceled| "Canceled".to_string());
|
||||
Ok(resp??)
|
||||
}
|
||||
.boxed()
|
||||
.shared(),
|
||||
})
|
||||
.ok();
|
||||
Some(response_tx)
|
||||
@@ -646,8 +656,8 @@ impl Zeta {
|
||||
};
|
||||
|
||||
if cfg!(debug_assertions) && std::env::var("ZED_ZETA2_SKIP_REQUEST").is_ok() {
|
||||
if let Some(debug_response_tx) = debug_response_tx {
|
||||
debug_response_tx
|
||||
if let Some(observe_response_tx) = observe_response_tx {
|
||||
observe_response_tx
|
||||
.send(Err("Request skipped".to_string()))
|
||||
.ok();
|
||||
}
|
||||
@@ -657,7 +667,7 @@ impl Zeta {
|
||||
let response =
|
||||
Self::send_prediction_request(client, llm_token, app_version, request).await;
|
||||
|
||||
if let Some(debug_response_tx) = debug_response_tx {
|
||||
if let Some(debug_response_tx) = observe_response_tx {
|
||||
debug_response_tx
|
||||
.send(
|
||||
response
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
use std::{cmp::Reverse, path::PathBuf, str::FromStr, sync::Arc, time::Duration};
|
||||
use std::{
|
||||
cmp::Reverse, collections::hash_map::Entry, fmt::Debug, ops::Add as _, path::PathBuf,
|
||||
str::FromStr, sync::Arc, time::Duration,
|
||||
};
|
||||
|
||||
use chrono::TimeDelta;
|
||||
use client::{Client, UserStore};
|
||||
use cloud_llm_client::predict_edits_v3::{
|
||||
self, DeclarationScoreComponents, PredictEditsRequest, PredictEditsResponse, PromptFormat,
|
||||
self, DeclarationScoreComponents, PredictEditsResponse, PromptFormat,
|
||||
};
|
||||
use collections::HashMap;
|
||||
use collections::{HashMap, HashSet};
|
||||
use editor::{Editor, EditorEvent, EditorMode, ExcerptRange, MultiBuffer};
|
||||
use feature_flags::FeatureFlagAppExt as _;
|
||||
use futures::{FutureExt, StreamExt as _, channel::oneshot, future::Shared};
|
||||
use futures::{FutureExt, StreamExt as _, future::Shared};
|
||||
use gpui::{
|
||||
CursorStyle, Empty, Entity, EventEmitter, FocusHandle, Focusable, Subscription, Task,
|
||||
WeakEntity, actions, prelude::*,
|
||||
@@ -20,7 +22,7 @@ use ui::{ButtonLike, ContextMenu, ContextMenuEntry, DropdownMenu, KeyBinding, pr
|
||||
use ui_input::SingleLineInput;
|
||||
use util::{ResultExt, paths::PathStyle, rel_path::RelPath};
|
||||
use workspace::{Item, SplitDirection, Workspace};
|
||||
use zeta2::{PredictionDebugInfo, Zeta, Zeta2FeatureFlag, ZetaOptions};
|
||||
use zeta2::{ObservedPredictionRequest, Zeta, Zeta2FeatureFlag, ZetaOptions};
|
||||
|
||||
use edit_prediction_context::{EditPredictionContextOptions, EditPredictionExcerptOptions};
|
||||
|
||||
@@ -33,6 +35,10 @@ actions!(
|
||||
Zeta2RatePredictionPositive,
|
||||
/// Rate prediction as negative.
|
||||
Zeta2RatePredictionNegative,
|
||||
/// Go to the previous request in the zeta2 inspector
|
||||
Zeta2InspectorPrevious,
|
||||
/// Go to the next request in the zeta2 inspector
|
||||
Zeta2InspectorNext,
|
||||
]
|
||||
);
|
||||
|
||||
@@ -64,7 +70,8 @@ pub fn init(cx: &mut App) {
|
||||
pub struct Zeta2Inspector {
|
||||
focus_handle: FocusHandle,
|
||||
project: Entity<Project>,
|
||||
last_prediction: Option<LastPrediction>,
|
||||
requests: Vec<InspectorObservedPredictionRequest>,
|
||||
current: Option<CurrentRequest>,
|
||||
max_excerpt_bytes_input: Entity<SingleLineInput>,
|
||||
min_excerpt_bytes_input: Entity<SingleLineInput>,
|
||||
cursor_context_ratio_input: Entity<SingleLineInput>,
|
||||
@@ -77,21 +84,24 @@ pub struct Zeta2Inspector {
|
||||
_receive_task: Task<()>,
|
||||
}
|
||||
|
||||
struct InspectorObservedPredictionRequest {
|
||||
observed_request: ObservedPredictionRequest,
|
||||
project_snapshot: Shared<Task<Arc<TelemetrySnapshot>>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum ActiveView {
|
||||
Context,
|
||||
Inference,
|
||||
}
|
||||
|
||||
struct LastPrediction {
|
||||
struct CurrentRequest {
|
||||
index: usize,
|
||||
context_editor: Entity<Editor>,
|
||||
prompt_editor: Entity<Editor>,
|
||||
retrieval_time: TimeDelta,
|
||||
buffer: WeakEntity<Buffer>,
|
||||
position: language::Anchor,
|
||||
state: LastPredictionState,
|
||||
request: PredictEditsRequest,
|
||||
project_snapshot: Shared<Task<Arc<TelemetrySnapshot>>>,
|
||||
state: CurrentPredictionState,
|
||||
_task: Option<Task<()>>,
|
||||
}
|
||||
|
||||
@@ -101,7 +111,7 @@ enum Feedback {
|
||||
Negative,
|
||||
}
|
||||
|
||||
enum LastPredictionState {
|
||||
enum CurrentPredictionState {
|
||||
Requested,
|
||||
Success {
|
||||
model_response_editor: Entity<Editor>,
|
||||
@@ -123,12 +133,21 @@ impl Zeta2Inspector {
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let zeta = Zeta::global(client, user_store, cx);
|
||||
let mut request_rx = zeta.update(cx, |zeta, _cx| zeta.debug_info());
|
||||
let mut request_rx = zeta.update(cx, |zeta, _cx| zeta.observe_requests());
|
||||
|
||||
let receive_task = cx.spawn_in(window, async move |this, cx| {
|
||||
while let Some(prediction) = request_rx.next().await {
|
||||
while let Some(request) = request_rx.next().await {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
this.update_last_prediction(prediction, window, cx)
|
||||
let project_snapshot_task = TelemetrySnapshot::new(&this.project, cx);
|
||||
this.requests.push(InspectorObservedPredictionRequest {
|
||||
observed_request: request,
|
||||
project_snapshot: cx
|
||||
.foreground_executor()
|
||||
.spawn(async move { Arc::new(project_snapshot_task.await) })
|
||||
.shared(),
|
||||
});
|
||||
|
||||
this.set_current_predition(this.requests.len() - 1, window, cx)
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
@@ -137,7 +156,8 @@ impl Zeta2Inspector {
|
||||
let mut this = Self {
|
||||
focus_handle: cx.focus_handle(),
|
||||
project: project.clone(),
|
||||
last_prediction: None,
|
||||
requests: Vec::new(),
|
||||
current: None,
|
||||
active_view: ActiveView::Inference,
|
||||
max_excerpt_bytes_input: Self::number_input("Max Excerpt Bytes", window, cx),
|
||||
min_excerpt_bytes_input: Self::number_input("Min Excerpt Bytes", window, cx),
|
||||
@@ -196,7 +216,7 @@ impl Zeta2Inspector {
|
||||
|
||||
const THROTTLE_TIME: Duration = Duration::from_millis(100);
|
||||
|
||||
if let Some(prediction) = self.last_prediction.as_mut() {
|
||||
if let Some(prediction) = self.current.as_mut() {
|
||||
if let Some(buffer) = prediction.buffer.upgrade() {
|
||||
let position = prediction.position;
|
||||
let zeta = self.zeta.clone();
|
||||
@@ -212,9 +232,9 @@ impl Zeta2Inspector {
|
||||
task.await.log_err();
|
||||
}
|
||||
}));
|
||||
prediction.state = LastPredictionState::Requested;
|
||||
prediction.state = CurrentPredictionState::Requested;
|
||||
} else {
|
||||
self.last_prediction.take();
|
||||
self.current.take();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,12 +307,7 @@ impl Zeta2Inspector {
|
||||
input
|
||||
}
|
||||
|
||||
fn update_last_prediction(
|
||||
&mut self,
|
||||
prediction: zeta2::PredictionDebugInfo,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
fn set_current_predition(&mut self, index: usize, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let project = self.project.read(cx);
|
||||
let path_style = project.path_style(cx);
|
||||
let Some(worktree_id) = project
|
||||
@@ -301,7 +316,7 @@ impl Zeta2Inspector {
|
||||
.map(|worktree| worktree.read(cx).id())
|
||||
else {
|
||||
log::error!("Open a worktree to use edit prediction debug view");
|
||||
self.last_prediction.take();
|
||||
self.current.take();
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -309,20 +324,42 @@ impl Zeta2Inspector {
|
||||
let language_registry = self.project.read(cx).languages().clone();
|
||||
async move |this, cx| {
|
||||
let mut languages = HashMap::default();
|
||||
for ext in prediction
|
||||
.request
|
||||
.referenced_declarations
|
||||
.iter()
|
||||
.filter_map(|snippet| snippet.path.extension())
|
||||
.chain(prediction.request.excerpt_path.extension())
|
||||
{
|
||||
if !languages.contains_key(ext) {
|
||||
|
||||
let file_extensions = this
|
||||
.read_with(cx, |this, _| {
|
||||
let mut file_extensions = HashSet::default();
|
||||
let request = &this.requests[index];
|
||||
|
||||
for ext in request
|
||||
.observed_request
|
||||
.full_request
|
||||
.referenced_declarations
|
||||
.iter()
|
||||
.filter_map(|snippet| snippet.path.extension())
|
||||
.chain(
|
||||
request
|
||||
.observed_request
|
||||
.full_request
|
||||
.excerpt_path
|
||||
.extension(),
|
||||
)
|
||||
{
|
||||
if !file_extensions.contains(ext) {
|
||||
file_extensions.insert(ext.to_owned());
|
||||
}
|
||||
}
|
||||
file_extensions
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
for ext in file_extensions {
|
||||
if let Entry::Vacant(entry) = languages.entry(ext) {
|
||||
// Most snippets are gonna be the same language,
|
||||
// so we think it's fine to do this sequentially for now
|
||||
languages.insert(
|
||||
ext.to_owned(),
|
||||
let ext_str = entry.key().to_string_lossy().to_string();
|
||||
entry.insert(
|
||||
language_registry
|
||||
.language_for_name_or_extension(&ext.to_string_lossy())
|
||||
.language_for_name_or_extension(&ext_str)
|
||||
.await
|
||||
.ok(),
|
||||
);
|
||||
@@ -335,6 +372,11 @@ impl Zeta2Inspector {
|
||||
.log_err();
|
||||
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
let InspectorObservedPredictionRequest {
|
||||
observed_request: request,
|
||||
..
|
||||
} = &this.requests[index];
|
||||
|
||||
let context_editor = cx.new(|cx| {
|
||||
let mut excerpt_score_components = HashMap::default();
|
||||
|
||||
@@ -348,9 +390,9 @@ impl Zeta2Inspector {
|
||||
|
||||
let excerpt_buffer = cx.new(|cx| {
|
||||
let mut buffer =
|
||||
Buffer::local(prediction.request.excerpt.clone(), cx);
|
||||
if let Some(language) = prediction
|
||||
.request
|
||||
Buffer::local(request.full_request.excerpt.clone(), cx);
|
||||
if let Some(language) = request
|
||||
.full_request
|
||||
.excerpt_path
|
||||
.extension()
|
||||
.and_then(|ext| languages.get(ext))
|
||||
@@ -358,6 +400,14 @@ impl Zeta2Inspector {
|
||||
buffer.set_language(language.clone(), cx);
|
||||
}
|
||||
buffer.file_updated(excerpt_file, cx);
|
||||
#[cfg(debug_assertions)]
|
||||
buffer.debug(
|
||||
&language::Point::new(
|
||||
request.full_request.cursor_point.line.0,
|
||||
request.full_request.cursor_point.column,
|
||||
),
|
||||
CursorMarker,
|
||||
);
|
||||
buffer
|
||||
});
|
||||
|
||||
@@ -368,7 +418,7 @@ impl Zeta2Inspector {
|
||||
);
|
||||
|
||||
let mut declarations =
|
||||
prediction.request.referenced_declarations.clone();
|
||||
request.full_request.referenced_declarations.clone();
|
||||
declarations.sort_unstable_by_key(|declaration| {
|
||||
Reverse(OrderedFloat(declaration.declaration_score))
|
||||
});
|
||||
@@ -419,24 +469,23 @@ impl Zeta2Inspector {
|
||||
editor
|
||||
});
|
||||
|
||||
let PredictionDebugInfo {
|
||||
response_rx,
|
||||
let ObservedPredictionRequest {
|
||||
response,
|
||||
position,
|
||||
buffer,
|
||||
retrieval_time,
|
||||
local_prompt,
|
||||
..
|
||||
} = prediction;
|
||||
} = request;
|
||||
|
||||
let response_task = response.clone();
|
||||
let task = cx.spawn_in(window, {
|
||||
let markdown_language = markdown_language.clone();
|
||||
async move |this, cx| {
|
||||
let response = response_rx.await;
|
||||
|
||||
let response = response_task.await;
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
if let Some(prediction) = this.last_prediction.as_mut() {
|
||||
if let Some(prediction) = this.current.as_mut() {
|
||||
prediction.state = match response {
|
||||
Ok(Ok(response)) => {
|
||||
Ok(response) => {
|
||||
if let Some(debug_info) = &response.debug_info {
|
||||
prediction.prompt_editor.update(
|
||||
cx,
|
||||
@@ -488,8 +537,8 @@ impl Zeta2Inspector {
|
||||
|this, editor, ev, window, cx| match ev {
|
||||
EditorEvent::BufferEdited => {
|
||||
if let Some(last_prediction) =
|
||||
this.last_prediction.as_mut()
|
||||
&& let LastPredictionState::Success {
|
||||
this.current.as_mut()
|
||||
&& let CurrentPredictionState::Success {
|
||||
feedback: feedback_state,
|
||||
..
|
||||
} = &mut last_prediction.state
|
||||
@@ -511,7 +560,7 @@ impl Zeta2Inspector {
|
||||
)
|
||||
.detach();
|
||||
|
||||
LastPredictionState::Success {
|
||||
CurrentPredictionState::Success {
|
||||
model_response_editor: cx.new(|cx| {
|
||||
let buffer = cx.new(|cx| {
|
||||
let mut buffer = Buffer::local(
|
||||
@@ -548,12 +597,7 @@ impl Zeta2Inspector {
|
||||
response,
|
||||
}
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
LastPredictionState::Failed { message: err }
|
||||
}
|
||||
Err(oneshot::Canceled) => LastPredictionState::Failed {
|
||||
message: "Canceled".to_string(),
|
||||
},
|
||||
Err(err) => CurrentPredictionState::Failed { message: err },
|
||||
};
|
||||
}
|
||||
})
|
||||
@@ -561,14 +605,15 @@ impl Zeta2Inspector {
|
||||
}
|
||||
});
|
||||
|
||||
let project_snapshot_task = TelemetrySnapshot::new(&this.project, cx);
|
||||
|
||||
this.last_prediction = Some(LastPrediction {
|
||||
this.current = Some(CurrentRequest {
|
||||
index,
|
||||
context_editor,
|
||||
prompt_editor: cx.new(|cx| {
|
||||
let buffer = cx.new(|cx| {
|
||||
let mut buffer =
|
||||
Buffer::local(local_prompt.unwrap_or_else(|err| err), cx);
|
||||
let mut buffer = Buffer::local(
|
||||
local_prompt.as_ref().unwrap_or_else(|err| err),
|
||||
cx,
|
||||
);
|
||||
buffer.set_language(markdown_language.clone(), cx);
|
||||
buffer
|
||||
});
|
||||
@@ -581,15 +626,9 @@ impl Zeta2Inspector {
|
||||
editor.set_show_scrollbars(false, cx);
|
||||
editor
|
||||
}),
|
||||
retrieval_time,
|
||||
buffer,
|
||||
position,
|
||||
state: LastPredictionState::Requested,
|
||||
project_snapshot: cx
|
||||
.foreground_executor()
|
||||
.spawn(async move { Arc::new(project_snapshot_task.await) })
|
||||
.shared(),
|
||||
request: prediction.request,
|
||||
buffer: buffer.clone(),
|
||||
position: *position,
|
||||
state: CurrentPredictionState::Requested,
|
||||
_task: Some(task),
|
||||
});
|
||||
cx.notify();
|
||||
@@ -599,6 +638,41 @@ impl Zeta2Inspector {
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_prev(
|
||||
&mut self,
|
||||
_action: &Zeta2InspectorPrevious,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.set_current_predition(
|
||||
self.current
|
||||
.as_ref()
|
||||
.map(|c| c.index)
|
||||
.unwrap_or_default()
|
||||
.saturating_sub(1),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_next(
|
||||
&mut self,
|
||||
_action: &Zeta2InspectorPrevious,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
self.set_current_predition(
|
||||
self.current
|
||||
.as_ref()
|
||||
.map(|c| c.index)
|
||||
.unwrap_or_default()
|
||||
.add(1)
|
||||
.min(self.requests.len() - 1),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_rate_positive(
|
||||
&mut self,
|
||||
_action: &Zeta2RatePredictionPositive,
|
||||
@@ -618,23 +692,25 @@ impl Zeta2Inspector {
|
||||
}
|
||||
|
||||
fn handle_rate(&mut self, kind: Feedback, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let Some(last_prediction) = self.last_prediction.as_mut() else {
|
||||
let Some(last_prediction) = self.current.as_mut() else {
|
||||
return;
|
||||
};
|
||||
if !last_prediction.request.can_collect_data {
|
||||
let request = &self.requests[last_prediction.index];
|
||||
if !request.observed_request.full_request.can_collect_data {
|
||||
return;
|
||||
}
|
||||
|
||||
let project_snapshot_task = last_prediction.project_snapshot.clone();
|
||||
let project_snapshot_task = request.project_snapshot.clone();
|
||||
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let project_snapshot = project_snapshot_task.await;
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
let Some(last_prediction) = this.last_prediction.as_mut() else {
|
||||
let Some(last_prediction) = this.current.as_mut() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let LastPredictionState::Success {
|
||||
// todo! move to Self::requests?
|
||||
let CurrentPredictionState::Success {
|
||||
feedback: feedback_state,
|
||||
feedback_editor,
|
||||
model_response_editor,
|
||||
@@ -670,12 +746,14 @@ impl Zeta2Inspector {
|
||||
Feedback::Negative => "negative",
|
||||
};
|
||||
|
||||
let request = &this.requests[last_prediction.index];
|
||||
|
||||
telemetry::event!(
|
||||
"Zeta2 Prediction Rated",
|
||||
id = response.request_id,
|
||||
kind = kind,
|
||||
text = text,
|
||||
request = last_prediction.request,
|
||||
request = request.observed_request.full_request,
|
||||
response = response,
|
||||
project_snapshot = project_snapshot,
|
||||
);
|
||||
@@ -686,8 +764,8 @@ impl Zeta2Inspector {
|
||||
}
|
||||
|
||||
fn focus_feedback(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if let Some(last_prediction) = self.last_prediction.as_mut() {
|
||||
if let LastPredictionState::Success {
|
||||
if let Some(last_prediction) = self.current.as_mut() {
|
||||
if let CurrentPredictionState::Success {
|
||||
feedback_editor, ..
|
||||
} = &mut last_prediction.state
|
||||
{
|
||||
@@ -780,7 +858,7 @@ impl Zeta2Inspector {
|
||||
}
|
||||
|
||||
fn render_tabs(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
|
||||
if self.last_prediction.is_none() {
|
||||
if self.current.is_none() {
|
||||
return None;
|
||||
};
|
||||
|
||||
@@ -816,19 +894,19 @@ impl Zeta2Inspector {
|
||||
}
|
||||
|
||||
fn render_stats(&self) -> Option<Div> {
|
||||
let Some(prediction) = self.last_prediction.as_ref() else {
|
||||
let Some(current) = self.current.as_ref() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let (prompt_planning_time, inference_time, parsing_time) =
|
||||
if let LastPredictionState::Success {
|
||||
if let CurrentPredictionState::Success {
|
||||
response:
|
||||
PredictEditsResponse {
|
||||
debug_info: Some(debug_info),
|
||||
..
|
||||
},
|
||||
..
|
||||
} = &prediction.state
|
||||
} = ¤t.state
|
||||
{
|
||||
(
|
||||
Some(debug_info.prompt_planning_time),
|
||||
@@ -847,7 +925,7 @@ impl Zeta2Inspector {
|
||||
.child(Headline::new("Stats").size(HeadlineSize::Small))
|
||||
.child(Self::render_duration(
|
||||
"Context retrieval",
|
||||
Some(prediction.retrieval_time),
|
||||
Some(self.requests[current.index].observed_request.retrieval_time),
|
||||
))
|
||||
.child(Self::render_duration(
|
||||
"Prompt planning",
|
||||
@@ -878,10 +956,10 @@ impl Zeta2Inspector {
|
||||
return Self::render_message("`zeta2` feature flag is not enabled");
|
||||
}
|
||||
|
||||
match self.last_prediction.as_ref() {
|
||||
match self.current.as_ref() {
|
||||
None => Self::render_message("No prediction"),
|
||||
Some(prediction) => self
|
||||
.render_last_prediction(prediction, window, cx)
|
||||
.render_current_prediction(prediction, window, cx)
|
||||
.into_any(),
|
||||
}
|
||||
}
|
||||
@@ -895,14 +973,14 @@ impl Zeta2Inspector {
|
||||
.into_any()
|
||||
}
|
||||
|
||||
fn render_last_prediction(
|
||||
fn render_current_prediction(
|
||||
&self,
|
||||
prediction: &LastPrediction,
|
||||
current: &CurrentRequest,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Div {
|
||||
match &self.active_view {
|
||||
ActiveView::Context => div().size_full().child(prediction.context_editor.clone()),
|
||||
ActiveView::Context => div().size_full().child(current.context_editor.clone()),
|
||||
ActiveView::Inference => h_flex()
|
||||
.items_start()
|
||||
.w_full()
|
||||
@@ -920,17 +998,21 @@ impl Zeta2Inspector {
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.child(ui::Headline::new("Prompt").size(ui::HeadlineSize::XSmall))
|
||||
.child(match prediction.state {
|
||||
LastPredictionState::Requested
|
||||
| LastPredictionState::Failed { .. } => ui::Chip::new("Local")
|
||||
.bg_color(cx.theme().status().warning_background)
|
||||
.label_color(Color::Success),
|
||||
LastPredictionState::Success { .. } => ui::Chip::new("Cloud")
|
||||
.bg_color(cx.theme().status().success_background)
|
||||
.label_color(Color::Success),
|
||||
.child(match current.state {
|
||||
CurrentPredictionState::Requested
|
||||
| CurrentPredictionState::Failed { .. } => {
|
||||
ui::Chip::new("Local")
|
||||
.bg_color(cx.theme().status().warning_background)
|
||||
.label_color(Color::Success)
|
||||
}
|
||||
CurrentPredictionState::Success { .. } => {
|
||||
ui::Chip::new("Cloud")
|
||||
.bg_color(cx.theme().status().success_background)
|
||||
.label_color(Color::Success)
|
||||
}
|
||||
}),
|
||||
)
|
||||
.child(prediction.prompt_editor.clone()),
|
||||
.child(current.prompt_editor.clone()),
|
||||
)
|
||||
.child(ui::vertical_divider())
|
||||
.child(
|
||||
@@ -947,16 +1029,16 @@ impl Zeta2Inspector {
|
||||
ui::Headline::new("Model Response")
|
||||
.size(ui::HeadlineSize::XSmall),
|
||||
)
|
||||
.child(match &prediction.state {
|
||||
LastPredictionState::Success {
|
||||
.child(match ¤t.state {
|
||||
CurrentPredictionState::Success {
|
||||
model_response_editor,
|
||||
..
|
||||
} => model_response_editor.clone().into_any_element(),
|
||||
LastPredictionState::Requested => v_flex()
|
||||
CurrentPredictionState::Requested => v_flex()
|
||||
.gap_2()
|
||||
.child(Label::new("Loading...").buffer_font(cx))
|
||||
.into_any_element(),
|
||||
LastPredictionState::Failed { message } => v_flex()
|
||||
CurrentPredictionState::Failed { message } => v_flex()
|
||||
.gap_2()
|
||||
.max_w_96()
|
||||
.child(Label::new(message.clone()).buffer_font(cx))
|
||||
@@ -965,12 +1047,15 @@ impl Zeta2Inspector {
|
||||
)
|
||||
.child(ui::divider())
|
||||
.child(
|
||||
if prediction.request.can_collect_data
|
||||
&& let LastPredictionState::Success {
|
||||
if self.requests[current.index]
|
||||
.observed_request
|
||||
.full_request
|
||||
.can_collect_data
|
||||
&& let CurrentPredictionState::Success {
|
||||
feedback_editor,
|
||||
feedback: feedback_state,
|
||||
..
|
||||
} = &prediction.state
|
||||
} = ¤t.state
|
||||
{
|
||||
v_flex()
|
||||
.key_context("Zeta2Feedback")
|
||||
@@ -1063,7 +1148,11 @@ impl EventEmitter<()> for Zeta2Inspector {}
|
||||
impl Render for Zeta2Inspector {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.track_focus(&self.focus_handle)
|
||||
.key_context("Zeta2Inspector")
|
||||
.size_full()
|
||||
.on_action(cx.listener(Self::handle_prev))
|
||||
.on_action(cx.listener(Self::handle_next))
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.child(
|
||||
h_flex()
|
||||
@@ -1131,6 +1220,16 @@ impl language::File for ExcerptMetadataFile {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
struct CursorMarker;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
impl Debug for CursorMarker {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Cursor")
|
||||
}
|
||||
}
|
||||
|
||||
struct ZetaContextAddon {
|
||||
excerpt_score_components: HashMap<editor::ExcerptId, DeclarationScoreComponents>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user