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 accept_any_model: false,
52 scoring: Default::default(),
53 confidence: Default::default(),
54 readout: Default::default(),
55 },
56 )
57 .await
58 .context("connecting to the upstream service failed")?;
59
60 println!("transport: {} via {}", bridge.probe().name(), bridge.probe().endpoint());
61
62 let state = Arc::new(AppState {
63 bridge,
64 api_key: std::env::var("JEV_BRIDGE_API_KEY").ok(),
65 readout_check: None,
66 });
67 let listener = tokio::net::TcpListener::bind(ADDRESS)
68 .await
69 .with_context(|| format!("binding {ADDRESS} failed"))?;
70 println!("listening on http://{ADDRESS}");
71 axum::serve(listener, router(state))
72 .with_graceful_shutdown(async {
73 let _ = tokio::signal::ctrl_c().await;
74 })
75 .await
76 .context("the HTTP server stopped unexpectedly")
77}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 accept_any_model: false,
54 scoring: Default::default(),
55 confidence: Default::default(),
56 readout: Default::default(),
57 },
58 )
59 .await
60 .context("connecting to the upstream service failed")?;
61
62 println!(
63 "connected in {:.2?}: transport={} endpoint={} renders_locally={} tokenizes_locally={}",
64 started.elapsed(),
65 bridge.probe().name(),
66 bridge.probe().endpoint(),
67 bridge.renders_locally(),
68 bridge.tokenizes_locally(),
69 );
70
71 let rows = vec![
72 Row {
73 id: "refund".to_string(),
74 state: json!("I was charged twice and need a refund today."),
75 question: "Which queue should handle this request?".to_string(),
76 options: vec![
77 option("access", "Account access and authentication."),
78 option("billing", "Billing, payments, and refunds."),
79 option("sales", "Pricing and new contracts."),
80 ],
81 },
82 Row {
83 id: "outage".to_string(),
84 state: json!("The API returns 502 for every request since this morning."),
85 question: "Which queue should handle this request?".to_string(),
86 options: vec![
87 option("access", "Account access and authentication."),
88 option("billing", "Billing, payments, and refunds."),
89 option("sales", "Pricing and new contracts."),
90 ],
91 },
92 ];
93
94 let started = Instant::now();
95 // Independent decisions, each carrying its own state: one readout per row.
96 let mut scored = Vec::with_capacity(rows.len());
97 for row in &rows {
98 scored.push(bridge.score_row(row).await?);
99 }
100 println!("scored {} rows in {:.2?}\n", scored.len(), started.elapsed());
101
102 for row in &scored {
103 let winner = row
104 .answer
105 .probabilities
106 .iter()
107 .enumerate()
108 .max_by(|a, b| a.1.partial_cmp(b.1).unwrap())
109 .map(|(index, _)| row.answer.option_ids[index].as_str())
110 .unwrap();
111 println!("{} -> {winner}", row.answer.id);
112 for (id, probability) in row.answer.option_ids.iter().zip(&row.answer.probabilities) {
113 println!(" {id:<8} {probability:.4}");
114 }
115 println!(
116 " input_tokens={} prompt_sha256={}",
117 row.answer.input_tokens,
118 &row.prompt_sha256[..16]
119 );
120 }
121
122 // Probabilities are conditional on the supplied options and uncalibrated.
123 println!("\nThese scores are conditional option probabilities, not calibrated confidence.");
124 Ok(())
125}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 accept_any_model: false,
52 scoring: Default::default(),
53 confidence: Default::default(),
54 readout: Default::default(),
55 },
56 )
57 .await
58 .context("connecting to the upstream service failed")?;
59
60 println!("transport: {} via {}", bridge.probe().name(), bridge.probe().endpoint());
61
62 let state = Arc::new(AppState {
63 bridge,
64 api_key: std::env::var("JEV_BRIDGE_API_KEY").ok(),
65 readout_check: None,
66 });
67 let listener = tokio::net::TcpListener::bind(ADDRESS)
68 .await
69 .with_context(|| format!("binding {ADDRESS} failed"))?;
70 println!("listening on http://{ADDRESS}");
71 axum::serve(listener, router(state))
72 .with_graceful_shutdown(async {
73 let _ = tokio::signal::ctrl_c().await;
74 })
75 .await
76 .context("the HTTP server stopped unexpectedly")
77}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 accept_any_model: false,
54 scoring: Default::default(),
55 confidence: Default::default(),
56 readout: Default::default(),
57 },
58 )
59 .await
60 .context("connecting to the upstream service failed")?;
61
62 println!(
63 "connected in {:.2?}: transport={} endpoint={} renders_locally={} tokenizes_locally={}",
64 started.elapsed(),
65 bridge.probe().name(),
66 bridge.probe().endpoint(),
67 bridge.renders_locally(),
68 bridge.tokenizes_locally(),
69 );
70
71 let rows = vec![
72 Row {
73 id: "refund".to_string(),
74 state: json!("I was charged twice and need a refund today."),
75 question: "Which queue should handle this request?".to_string(),
76 options: vec![
77 option("access", "Account access and authentication."),
78 option("billing", "Billing, payments, and refunds."),
79 option("sales", "Pricing and new contracts."),
80 ],
81 },
82 Row {
83 id: "outage".to_string(),
84 state: json!("The API returns 502 for every request since this morning."),
85 question: "Which queue should handle this request?".to_string(),
86 options: vec![
87 option("access", "Account access and authentication."),
88 option("billing", "Billing, payments, and refunds."),
89 option("sales", "Pricing and new contracts."),
90 ],
91 },
92 ];
93
94 let started = Instant::now();
95 // Independent decisions, each carrying its own state: one readout per row.
96 let mut scored = Vec::with_capacity(rows.len());
97 for row in &rows {
98 scored.push(bridge.score_row(row).await?);
99 }
100 println!("scored {} rows in {:.2?}\n", scored.len(), started.elapsed());
101
102 for row in &scored {
103 let winner = row
104 .answer
105 .probabilities
106 .iter()
107 .enumerate()
108 .max_by(|a, b| a.1.partial_cmp(b.1).unwrap())
109 .map(|(index, _)| row.answer.option_ids[index].as_str())
110 .unwrap();
111 println!("{} -> {winner}", row.answer.id);
112 for (id, probability) in row.answer.option_ids.iter().zip(&row.answer.probabilities) {
113 println!(" {id:<8} {probability:.4}");
114 }
115 println!(
116 " input_tokens={} prompt_sha256={}",
117 row.answer.input_tokens,
118 &row.prompt_sha256[..16]
119 );
120 }
121
122 // Probabilities are conditional on the supplied options and uncalibrated.
123 println!("\nThese scores are conditional option probabilities, not calibrated confidence.");
124 Ok(())
125}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