use thiserror::Error;
#[derive(Debug, Error)]
pub enum CommandRTaskError {
#[error("query must not be empty")]
EmptyQuery,
#[error("tool list must not be empty")]
NoTools,
#[error("document entry at index {0} has empty {1}")]
EmptyDocument(usize, &'static str),
}
pub const START_OF_TURN: &str = "<|START_OF_TURN_TOKEN|>";
pub const END_OF_TURN: &str = "<|END_OF_TURN_TOKEN|>";
pub const USER_TOKEN: &str = "<|USER_TOKEN|>";
pub const CHATBOT_TOKEN: &str = "<|CHATBOT_TOKEN|>";
pub const SYSTEM_TOKEN: &str = "<|SYSTEM_TOKEN|>";
pub fn format_chat_prompt(
system: Option<&str>,
user_message: &str,
) -> Result<String, CommandRTaskError> {
if user_message.trim().is_empty() {
return Err(CommandRTaskError::EmptyQuery);
}
let mut buf = String::new();
if let Some(sys) = system {
buf.push_str(START_OF_TURN);
buf.push_str(SYSTEM_TOKEN);
buf.push_str(sys);
buf.push_str(END_OF_TURN);
buf.push('\n');
}
buf.push_str(START_OF_TURN);
buf.push_str(USER_TOKEN);
buf.push_str(user_message);
buf.push_str(END_OF_TURN);
buf.push('\n');
buf.push_str(START_OF_TURN);
buf.push_str(CHATBOT_TOKEN);
Ok(buf)
}
#[derive(Debug, Clone)]
pub struct RagDocument<'a> {
pub title: &'a str,
pub content: &'a str,
}
pub fn format_rag_prompt(
system_preamble: Option<&str>,
documents: &[RagDocument<'_>],
query: &str,
) -> Result<String, CommandRTaskError> {
if query.trim().is_empty() {
return Err(CommandRTaskError::EmptyQuery);
}
for (idx, doc) in documents.iter().enumerate() {
if doc.title.trim().is_empty() {
return Err(CommandRTaskError::EmptyDocument(idx, "title"));
}
if doc.content.trim().is_empty() {
return Err(CommandRTaskError::EmptyDocument(idx, "content"));
}
}
let mut buf = String::new();
buf.push_str(START_OF_TURN);
buf.push_str(SYSTEM_TOKEN);
if let Some(preamble) = system_preamble {
buf.push_str(preamble);
buf.push('\n');
}
if documents.is_empty() {
buf.push_str("No supporting documents were retrieved. Answer based on your knowledge.");
} else {
buf.push_str(
"Use the documents below to answer the user's question. \
Cite the relevant document title(s) in your response.\n\n",
);
for (idx, doc) in documents.iter().enumerate() {
buf.push_str(&format!("Document [{}] (Title: {})\n", idx + 1, doc.title));
buf.push_str(doc.content);
buf.push_str("\n\n");
}
}
buf.push_str(END_OF_TURN);
buf.push('\n');
buf.push_str(START_OF_TURN);
buf.push_str(USER_TOKEN);
buf.push_str(query);
buf.push_str(END_OF_TURN);
buf.push('\n');
buf.push_str(START_OF_TURN);
buf.push_str(CHATBOT_TOKEN);
Ok(buf)
}
pub fn format_tool_use_prompt(tools: &[&str], query: &str) -> Result<String, CommandRTaskError> {
if tools.is_empty() {
return Err(CommandRTaskError::NoTools);
}
if query.trim().is_empty() {
return Err(CommandRTaskError::EmptyQuery);
}
let mut buf = String::new();
buf.push_str(START_OF_TURN);
buf.push_str(SYSTEM_TOKEN);
buf.push_str(
"You have access to the following tools. \
When appropriate, call a tool by emitting a JSON object \
with \"tool\" and \"parameters\" keys.\n\n",
);
buf.push_str("Available tools:\n");
for (idx, tool) in tools.iter().enumerate() {
buf.push_str(&format!(" {}. {}\n", idx + 1, tool));
}
buf.push_str(END_OF_TURN);
buf.push('\n');
buf.push_str(START_OF_TURN);
buf.push_str(USER_TOKEN);
buf.push_str(query);
buf.push_str(END_OF_TURN);
buf.push('\n');
buf.push_str(START_OF_TURN);
buf.push_str(CHATBOT_TOKEN);
Ok(buf)
}
pub fn apply_logit_scale(logits: &[f32], scale: f32) -> Vec<f32> {
logits.iter().map(|&x| x * scale).collect()
}
pub fn greedy_token(logits: &[f32]) -> Option<u32> {
logits
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal))
.map(|(idx, _)| idx as u32)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_command_r_config_default() {
use crate::command_r::CommandRConfig;
let cfg = CommandRConfig::default();
assert_eq!(cfg.vocab_size, 256000);
assert!(cfg.validate().is_ok());
}
#[test]
fn test_command_r_config_base() {
use crate::command_r::CommandRConfig;
let cfg = CommandRConfig::command_r();
assert_eq!(cfg.hidden_size, 8192);
assert_eq!(cfg.num_hidden_layers, 40);
assert_eq!(cfg.num_attention_heads, 64);
assert_eq!(cfg.num_key_value_heads, 64);
assert!(cfg.validate().is_ok());
}
#[test]
fn test_command_r_config_plus() {
use crate::command_r::CommandRConfig;
let cfg = CommandRConfig::command_r_plus();
assert_eq!(cfg.hidden_size, 12288);
assert_eq!(cfg.num_hidden_layers, 64);
assert_eq!(cfg.num_attention_heads, 96);
assert_eq!(cfg.num_key_value_heads, 96);
assert_eq!(cfg.intermediate_size, 33792);
assert!(cfg.validate().is_ok());
}
#[test]
fn test_command_r_layer_norm_basic() {
let x = vec![1.0_f32, 2.0, 3.0, 4.0];
let weight = vec![1.0_f32; 4];
let bias = vec![0.0_f32; 4];
let eps = 1e-5_f64;
let n = x.len() as f32;
let mean = x.iter().sum::<f32>() / n; let var = x.iter().map(|v| (v - mean).powi(2)).sum::<f32>() / n;
let std = (var + eps as f32).sqrt();
let expected: Vec<f32> = x
.iter()
.zip(weight.iter())
.zip(bias.iter())
.map(|((xi, wi), bi)| (xi - mean) / std * wi + bi)
.collect();
assert!((expected[0] - (-1.3416_f32)).abs() < 1e-3);
assert!((expected[3] - 1.3416_f32).abs() < 1e-3);
}
#[test]
fn test_command_r_layer_norm_zero_mean() {
let x = vec![1.0_f32, 3.0, 5.0, 7.0];
let n = x.len() as f32;
let mean = x.iter().sum::<f32>() / n;
let var = x.iter().map(|v| (v - mean).powi(2)).sum::<f32>() / n;
let std = (var + 1e-5_f32).sqrt();
let normed: Vec<f32> = x.iter().map(|xi| (xi - mean) / std).collect();
let normed_mean: f32 = normed.iter().sum::<f32>() / n;
assert!(
normed_mean.abs() < 1e-4,
"mean should be ~0, got {}",
normed_mean
);
}
#[test]
fn test_command_r_layernorm_vs_rmsnorm_differ() {
let x = vec![2.0_f32, 4.0, 6.0];
let n = x.len() as f32;
let eps = 1e-5_f32;
let mean_ln = x.iter().sum::<f32>() / n;
let var_ln = x.iter().map(|v| (v - mean_ln).powi(2)).sum::<f32>() / n;
let ln_out0 = (x[0] - mean_ln) / (var_ln + eps).sqrt();
let rms = (x.iter().map(|v| v * v).sum::<f32>() / n + eps).sqrt();
let rms_out0 = x[0] / rms;
assert!((ln_out0 - rms_out0).abs() > 1e-3);
}
#[test]
fn test_command_r_rope_standard() {
let dim = 8usize;
let base = 10000.0_f32;
let inv_freqs: Vec<f32> =
(0..dim / 2).map(|i| 1.0 / base.powf(2.0 * i as f32 / dim as f32)).collect();
assert!((inv_freqs[0] - 1.0_f32).abs() < 1e-6);
for i in 1..inv_freqs.len() {
assert!(inv_freqs[i] < inv_freqs[i - 1]);
}
}
#[test]
fn test_command_r_attention_gqa() {
use crate::command_r::config::CommandRConfig;
let cfg = CommandRConfig {
num_attention_heads: 32,
num_key_value_heads: 8,
hidden_size: 4096,
..CommandRConfig::command_r()
};
assert_eq!(cfg.num_query_groups(), 4);
assert!(cfg.is_gqa());
}
#[test]
fn test_command_r_gqa_head_ratio() {
use crate::command_r::config::CommandRConfig;
let cfg = CommandRConfig {
num_attention_heads: 56,
num_key_value_heads: 8,
hidden_size: 7168,
..CommandRConfig::command_r()
};
assert_eq!(cfg.num_query_groups(), 7);
}
#[test]
fn test_command_r_non_gqa_base() {
use crate::command_r::config::CommandRConfig;
let cfg = CommandRConfig::command_r();
assert!(!cfg.is_gqa());
assert_eq!(cfg.num_query_groups(), 1);
}
#[test]
fn test_command_r_mlp_swiglu() {
let x = 1.0_f32;
let sigmoid_x = 1.0 / (1.0 + (-x).exp());
let silu_x = x * sigmoid_x;
assert!((silu_x - 0.7311_f32).abs() < 1e-4);
let gate = vec![1.0_f32, -1.0, 0.5];
let up = vec![2.0_f32, 2.0, 2.0];
let swiglu: Vec<f32> = gate
.iter()
.zip(up.iter())
.map(|(&g, &u)| {
let s = 1.0 / (1.0 + (-g).exp());
g * s * u
})
.collect();
assert!(swiglu[0] > 0.0); assert!(swiglu[1] < 0.0); }
#[test]
fn test_command_r_logit_scale() {
let raw = vec![10.0_f32, 5.0, 0.0, -5.0];
let scaled = apply_logit_scale(&raw, 0.0625);
assert!((scaled[0] - 0.625_f32).abs() < 1e-6);
assert!((scaled[1] - 0.3125_f32).abs() < 1e-6);
assert!((scaled[2] - 0.0_f32).abs() < 1e-6);
assert!((scaled[3] - (-0.3125_f32)).abs() < 1e-6);
}
#[test]
fn test_command_r_model_forward() {
let logits = vec![0.1_f32, 0.9, 0.3, 0.7];
let token = greedy_token(&logits);
assert_eq!(token, Some(1u32)); }
#[test]
fn test_command_r_generate() {
let steps: Vec<Vec<f32>> = vec![
vec![0.1, 0.9, 0.2], vec![0.8, 0.1, 0.3], vec![0.2, 0.3, 0.7], ];
let generated: Vec<u32> = steps.iter().filter_map(|logits| greedy_token(logits)).collect();
assert_eq!(generated, vec![1u32, 0, 2]);
}
#[test]
fn test_command_r_rag_prompt_no_docs() {
let prompt = format_rag_prompt(None, &[], "What is the capital of France?")
.expect("should succeed with no docs");
assert!(prompt.contains(START_OF_TURN));
assert!(prompt.contains(SYSTEM_TOKEN));
assert!(prompt.contains("No supporting documents"));
assert!(prompt.contains("What is the capital of France?"));
assert!(prompt.ends_with(CHATBOT_TOKEN));
}
#[test]
fn test_command_r_rag_prompt_with_docs() {
let docs = vec![
RagDocument {
title: "Paris Guide",
content: "Paris is the capital of France.",
},
RagDocument {
title: "Europe Facts",
content: "France is a country in Western Europe.",
},
];
let prompt = format_rag_prompt(None, &docs, "What is the capital of France?")
.expect("should succeed");
assert!(prompt.contains("Paris Guide"));
assert!(prompt.contains("Europe Facts"));
assert!(prompt.contains("Document [1]"));
assert!(prompt.contains("Document [2]"));
assert!(prompt.ends_with(CHATBOT_TOKEN));
}
#[test]
fn test_command_r_tool_use_prompt() {
let tools = &[
"search(query: str) -> List[str]",
"calculator(expr: str) -> float",
];
let prompt = format_tool_use_prompt(tools, "What is 2 + 2?").expect("should succeed");
assert!(prompt.contains("search(query: str)"));
assert!(prompt.contains("calculator(expr: str)"));
assert!(prompt.contains("What is 2 + 2?"));
assert!(prompt.ends_with(CHATBOT_TOKEN));
}
#[test]
fn test_command_r_tool_use_prompt_empty_tools() {
let err = format_tool_use_prompt(&[], "hello");
assert!(matches!(err, Err(CommandRTaskError::NoTools)));
}
#[test]
fn test_command_r_chat_format() {
let prompt =
format_chat_prompt(Some("You are helpful."), "Hello!").expect("should succeed");
assert!(prompt.contains(SYSTEM_TOKEN));
assert!(prompt.contains("You are helpful."));
assert!(prompt.contains(USER_TOKEN));
assert!(prompt.contains("Hello!"));
assert!(prompt.ends_with(CHATBOT_TOKEN));
}
#[test]
fn test_command_r_chat_format_no_system() {
let prompt =
format_chat_prompt(None, "Hello!").expect("should succeed without system prompt");
assert!(!prompt.contains(SYSTEM_TOKEN));
assert!(prompt.contains(USER_TOKEN));
assert!(prompt.ends_with(CHATBOT_TOKEN));
}
#[test]
fn test_command_r_chat_format_empty_query() {
let err = format_chat_prompt(None, " ");
assert!(matches!(err, Err(CommandRTaskError::EmptyQuery)));
}
#[test]
fn test_command_r_error_display() {
let e1 = CommandRTaskError::EmptyQuery;
assert!(e1.to_string().contains("empty"));
let e2 = CommandRTaskError::NoTools;
assert!(e2.to_string().contains("empty"));
let e3 = CommandRTaskError::EmptyDocument(2, "title");
assert!(e3.to_string().contains("2"));
assert!(e3.to_string().contains("title"));
}
}