pub enum Probe {
LogprobTokenIds,
AllowedTokenIdsTopK,
CompletionsTopK,
LlamaCppNProbs,
}Expand description
How the target service exposes option-token log probabilities.
Variants§
LogprobTokenIds
vLLM: restrict the distribution to the option tokens and ask for their
exact token ids. This is the same contract fastjev’s own vLLM backend
uses through SamplingParams.
AllowedTokenIdsTopK
vLLM without logprob_token_ids: restrict the distribution and read
the top-k, which must then contain every option token.
CompletionsTopK
OpenAI-compatible completions: read the top-k of the unrestricted next-token distribution.
LlamaCppNProbs
llama.cpp native /completion with n_probs.
Implementations§
Source§impl Probe
impl Probe
Sourcepub fn name(self) -> &'static str
pub fn name(self) -> &'static str
Stable identifier reported by GET /health.
Examples found in repository?
30async fn main() -> Result<()> {
31 let openai_base = std::env::var("JEV_BRIDGE_UPSTREAM_URL")
32 .unwrap_or_else(|_| "http://127.0.0.1:8080/v1".to_string());
33 let native_base = std::env::var("JEV_BRIDGE_NATIVE_URL")
34 .unwrap_or_else(|_| openai_base.trim_end_matches("/v1").to_string());
35 let upstream_model =
36 std::env::var("JEV_BRIDGE_UPSTREAM_MODEL").unwrap_or_else(|_| "local-model".to_string());
37
38 let bridge = Bridge::connect(
39 reqwest::Client::new(),
40 BridgeConfig {
41 openai_base,
42 native_base,
43 upstream_model,
44 upstream_key: std::env::var("JEV_BRIDGE_UPSTREAM_KEY").ok(),
45 served_model: "example-bridge".to_string(),
46 description: "example bridge over a generic inference API".to_string(),
47 release_date: "2026-09-22".to_string(),
48 chat_template_kwargs: json!({"enable_thinking": false}),
49 max_input_tokens: None,
50 local: Default::default(),
51 readout: Default::default(),
52 },
53 )
54 .await
55 .context("connecting to the upstream service failed")?;
56
57 println!("transport: {} via {}", bridge.probe().name(), bridge.probe().endpoint());
58
59 let state = Arc::new(AppState {
60 bridge,
61 api_key: std::env::var("JEV_BRIDGE_API_KEY").ok(),
62 readout_check: None,
63 });
64 let listener = tokio::net::TcpListener::bind(ADDRESS)
65 .await
66 .with_context(|| format!("binding {ADDRESS} failed"))?;
67 println!("listening on http://{ADDRESS}");
68 axum::serve(listener, router(state))
69 .with_graceful_shutdown(async {
70 let _ = tokio::signal::ctrl_c().await;
71 })
72 .await
73 .context("the HTTP server stopped unexpectedly")
74}More examples
30async fn main() -> Result<()> {
31 let openai_base = std::env::var("JEV_BRIDGE_UPSTREAM_URL")
32 .unwrap_or_else(|_| "http://127.0.0.1:8080/v1".to_string());
33 let native_base = std::env::var("JEV_BRIDGE_NATIVE_URL")
34 .unwrap_or_else(|_| openai_base.trim_end_matches("/v1").to_string());
35 let upstream_key = std::env::var("JEV_BRIDGE_UPSTREAM_KEY").ok();
36 let upstream_model =
37 std::env::var("JEV_BRIDGE_UPSTREAM_MODEL").unwrap_or_else(|_| "local-model".to_string());
38
39 let started = Instant::now();
40 let bridge = Bridge::connect(
41 reqwest::Client::new(),
42 BridgeConfig {
43 openai_base,
44 native_base,
45 upstream_model,
46 upstream_key,
47 served_model: "example-bridge".to_string(),
48 description: "example bridge".to_string(),
49 release_date: "2026-09-22".to_string(),
50 chat_template_kwargs: json!({"enable_thinking": false}),
51 max_input_tokens: None,
52 local: Default::default(),
53 readout: Default::default(),
54 },
55 )
56 .await
57 .context("connecting to the upstream service failed")?;
58
59 println!(
60 "connected in {:.2?}: transport={} endpoint={} renders_locally={} tokenizes_locally={}",
61 started.elapsed(),
62 bridge.probe().name(),
63 bridge.probe().endpoint(),
64 bridge.renders_locally(),
65 bridge.tokenizes_locally(),
66 );
67
68 let rows = vec![
69 Row {
70 id: "refund".to_string(),
71 state: json!("I was charged twice and need a refund today."),
72 question: "Which queue should handle this request?".to_string(),
73 options: vec![
74 option("access", "Account access and authentication."),
75 option("billing", "Billing, payments, and refunds."),
76 option("sales", "Pricing and new contracts."),
77 ],
78 },
79 Row {
80 id: "outage".to_string(),
81 state: json!("The API returns 502 for every request since this morning."),
82 question: "Which queue should handle this request?".to_string(),
83 options: vec![
84 option("access", "Account access and authentication."),
85 option("billing", "Billing, payments, and refunds."),
86 option("sales", "Pricing and new contracts."),
87 ],
88 },
89 ];
90
91 let started = Instant::now();
92 // Independent decisions, each carrying its own state: one readout per row.
93 let mut scored = Vec::with_capacity(rows.len());
94 for row in &rows {
95 scored.push(bridge.score_row(row).await?);
96 }
97 println!("scored {} rows in {:.2?}\n", scored.len(), started.elapsed());
98
99 for row in &scored {
100 let winner = row
101 .answer
102 .probabilities
103 .iter()
104 .enumerate()
105 .max_by(|a, b| a.1.partial_cmp(b.1).unwrap())
106 .map(|(index, _)| row.answer.option_ids[index].as_str())
107 .unwrap();
108 println!("{} -> {winner}", row.answer.id);
109 for (id, probability) in row.answer.option_ids.iter().zip(&row.answer.probabilities) {
110 println!(" {id:<8} {probability:.4}");
111 }
112 println!(
113 " input_tokens={} prompt_sha256={}",
114 row.answer.input_tokens,
115 &row.prompt_sha256[..16]
116 );
117 }
118
119 // Probabilities are conditional on the supplied options and uncalibrated.
120 println!("\nThese scores are conditional option probabilities, not calibrated confidence.");
121 Ok(())
122}Sourcepub fn restricts_distribution(self) -> bool
pub fn restricts_distribution(self) -> bool
Whether the request is expected to restrict the distribution to the answer tokens. A probe that claims restriction but returns foreign candidates is rejected rather than silently trusted.
Sourcepub fn supports_batch(self) -> bool
pub fn supports_batch(self) -> bool
Whether this transport can read several prompts in one request.
The OpenAI-shaped transports accept an array prompt, which a
prefix-caching server prefills together. llama.cpp’s native
/completion answers an array with a bare JSON array of response
objects instead of one object, so it stays one prompt per request.
Sourcepub fn endpoint(self) -> &'static str
pub fn endpoint(self) -> &'static str
The path this transport posts to.
Examples found in repository?
30async fn main() -> Result<()> {
31 let openai_base = std::env::var("JEV_BRIDGE_UPSTREAM_URL")
32 .unwrap_or_else(|_| "http://127.0.0.1:8080/v1".to_string());
33 let native_base = std::env::var("JEV_BRIDGE_NATIVE_URL")
34 .unwrap_or_else(|_| openai_base.trim_end_matches("/v1").to_string());
35 let upstream_model =
36 std::env::var("JEV_BRIDGE_UPSTREAM_MODEL").unwrap_or_else(|_| "local-model".to_string());
37
38 let bridge = Bridge::connect(
39 reqwest::Client::new(),
40 BridgeConfig {
41 openai_base,
42 native_base,
43 upstream_model,
44 upstream_key: std::env::var("JEV_BRIDGE_UPSTREAM_KEY").ok(),
45 served_model: "example-bridge".to_string(),
46 description: "example bridge over a generic inference API".to_string(),
47 release_date: "2026-09-22".to_string(),
48 chat_template_kwargs: json!({"enable_thinking": false}),
49 max_input_tokens: None,
50 local: Default::default(),
51 readout: Default::default(),
52 },
53 )
54 .await
55 .context("connecting to the upstream service failed")?;
56
57 println!("transport: {} via {}", bridge.probe().name(), bridge.probe().endpoint());
58
59 let state = Arc::new(AppState {
60 bridge,
61 api_key: std::env::var("JEV_BRIDGE_API_KEY").ok(),
62 readout_check: None,
63 });
64 let listener = tokio::net::TcpListener::bind(ADDRESS)
65 .await
66 .with_context(|| format!("binding {ADDRESS} failed"))?;
67 println!("listening on http://{ADDRESS}");
68 axum::serve(listener, router(state))
69 .with_graceful_shutdown(async {
70 let _ = tokio::signal::ctrl_c().await;
71 })
72 .await
73 .context("the HTTP server stopped unexpectedly")
74}More examples
30async fn main() -> Result<()> {
31 let openai_base = std::env::var("JEV_BRIDGE_UPSTREAM_URL")
32 .unwrap_or_else(|_| "http://127.0.0.1:8080/v1".to_string());
33 let native_base = std::env::var("JEV_BRIDGE_NATIVE_URL")
34 .unwrap_or_else(|_| openai_base.trim_end_matches("/v1").to_string());
35 let upstream_key = std::env::var("JEV_BRIDGE_UPSTREAM_KEY").ok();
36 let upstream_model =
37 std::env::var("JEV_BRIDGE_UPSTREAM_MODEL").unwrap_or_else(|_| "local-model".to_string());
38
39 let started = Instant::now();
40 let bridge = Bridge::connect(
41 reqwest::Client::new(),
42 BridgeConfig {
43 openai_base,
44 native_base,
45 upstream_model,
46 upstream_key,
47 served_model: "example-bridge".to_string(),
48 description: "example bridge".to_string(),
49 release_date: "2026-09-22".to_string(),
50 chat_template_kwargs: json!({"enable_thinking": false}),
51 max_input_tokens: None,
52 local: Default::default(),
53 readout: Default::default(),
54 },
55 )
56 .await
57 .context("connecting to the upstream service failed")?;
58
59 println!(
60 "connected in {:.2?}: transport={} endpoint={} renders_locally={} tokenizes_locally={}",
61 started.elapsed(),
62 bridge.probe().name(),
63 bridge.probe().endpoint(),
64 bridge.renders_locally(),
65 bridge.tokenizes_locally(),
66 );
67
68 let rows = vec![
69 Row {
70 id: "refund".to_string(),
71 state: json!("I was charged twice and need a refund today."),
72 question: "Which queue should handle this request?".to_string(),
73 options: vec![
74 option("access", "Account access and authentication."),
75 option("billing", "Billing, payments, and refunds."),
76 option("sales", "Pricing and new contracts."),
77 ],
78 },
79 Row {
80 id: "outage".to_string(),
81 state: json!("The API returns 502 for every request since this morning."),
82 question: "Which queue should handle this request?".to_string(),
83 options: vec![
84 option("access", "Account access and authentication."),
85 option("billing", "Billing, payments, and refunds."),
86 option("sales", "Pricing and new contracts."),
87 ],
88 },
89 ];
90
91 let started = Instant::now();
92 // Independent decisions, each carrying its own state: one readout per row.
93 let mut scored = Vec::with_capacity(rows.len());
94 for row in &rows {
95 scored.push(bridge.score_row(row).await?);
96 }
97 println!("scored {} rows in {:.2?}\n", scored.len(), started.elapsed());
98
99 for row in &scored {
100 let winner = row
101 .answer
102 .probabilities
103 .iter()
104 .enumerate()
105 .max_by(|a, b| a.1.partial_cmp(b.1).unwrap())
106 .map(|(index, _)| row.answer.option_ids[index].as_str())
107 .unwrap();
108 println!("{} -> {winner}", row.answer.id);
109 for (id, probability) in row.answer.option_ids.iter().zip(&row.answer.probabilities) {
110 println!(" {id:<8} {probability:.4}");
111 }
112 println!(
113 " input_tokens={} prompt_sha256={}",
114 row.answer.input_tokens,
115 &row.prompt_sha256[..16]
116 );
117 }
118
119 // Probabilities are conditional on the supplied options and uncalibrated.
120 println!("\nThese scores are conditional option probabilities, not calibrated confidence.");
121 Ok(())
122}Trait Implementations§
impl Copy for Probe
impl Eq for Probe
impl StructuralPartialEq for Probe
Auto Trait Implementations§
impl Freeze for Probe
impl RefUnwindSafe for Probe
impl Send for Probe
impl Sync for Probe
impl Unpin for Probe
impl UnsafeUnpin for Probe
impl UnwindSafe for Probe
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more