use std::sync::Arc;
use crate::language_model::LanguageModel;
use crate::language_model_message::{LanguageModelPrompt, LanguageModelPromptMessage};
use crate::result::GenerateContent;
use crate::types::{TokenUsage, Usage};
pub type ChildModel = Arc<dyn LanguageModel>;
#[must_use]
pub fn add_usage(a: Usage, b: &Usage) -> Usage {
Usage {
input_tokens: add_token_usage(a.input_tokens, &b.input_tokens),
output_tokens: add_token_usage(a.output_tokens, &b.output_tokens),
raw: None,
}
}
fn add_token_usage(a: TokenUsage, b: &TokenUsage) -> TokenUsage {
TokenUsage {
total: opt_add(a.total, b.total),
no_cache: opt_add(a.no_cache, b.no_cache),
cache_read: opt_add(a.cache_read, b.cache_read),
cache_write: opt_add(a.cache_write, b.cache_write),
text: opt_add(a.text, b.text),
reasoning: opt_add(a.reasoning, b.reasoning),
}
}
fn opt_add(a: Option<u32>, b: Option<u32>) -> Option<u32> {
match (a, b) {
(None, None) => None,
(Some(x), None) => Some(x),
(None, Some(y)) => Some(y),
(Some(x), Some(y)) => Some(x + y),
}
}
#[must_use]
pub fn extract_text(content: &[GenerateContent]) -> String {
let mut out = String::new();
for c in content {
if let GenerateContent::Text { text, .. } = c {
out.push_str(text);
}
}
out
}
#[must_use]
pub fn build_aggregator_prompt(
prompt: &LanguageModelPrompt,
instructions: Option<&str>,
references: &[(String, String)],
) -> LanguageModelPrompt {
let mut out: LanguageModelPrompt = prompt.to_vec();
if references.is_empty() {
return out;
}
let instruction = instructions.unwrap_or(
"You are an aggregation assistant. Synthesize the reference model \
responses below into a single high-quality answer. Resolve conflicts \
by preferring the most accurate reasoning; do not mention the \
reference models unless asked.",
);
let mut body = String::new();
body.push_str(instruction);
body.push_str("\n\n# Reference model responses\n");
for (model_id, text) in references {
body.push_str("\n## ");
body.push_str(model_id);
body.push('\n');
body.push_str(text);
body.push('\n');
}
out.push(LanguageModelPromptMessage {
role: crate::message::Role::User,
content: vec![crate::content::ContentPart::text(body)],
provider_options: None,
});
out
}