//! prompt_composer —— 提示词模板与组合器离线示例。 //! Required features: cargo run --example prompt_composer --features "prompt,llm" //! //! 演示: //! 1. `PromptTemplate::compile` + `render` 变量插值(`{{var}}` 语法) //! 2. 缺失变量返回 `PromptError` //! 3. `PromptTemplateRegistry` 注册 + 按名渲染 //! 4. `PromptComposer` 构造多角色消息序列 //! 5. `validate_messages` 校验消息序列合法性 //! //! 运行:`cargo run --example prompt_composer` use agcore::llm::types::message::{ContentBlock, Message}; use agcore::prompt::{ PromptComposer, PromptTemplate, PromptTemplateRegistry, TemplateContext, validate_messages, }; fn message_text(msg: &Message) -> String { match msg { Message::System { content } | Message::User { content } | Message::Assistant { content } | Message::ToolResult { content, .. } => content .iter() .filter_map(|b| match b { ContentBlock::Text { text } => Some(text.as_str()), _ => None, }) .collect(), Message::UserImage { .. } => "[image]".into(), _ => String::new(), } } fn main() { // 1. PromptTemplate::compile + render —— 直接构造模板 println!("=== PromptTemplate::compile + render ==="); let tpl = PromptTemplate::compile("今日 {{location}} 天气:{{condition}},温度 {{temperature}}") .expect("编译失败"); let mut ctx = TemplateContext::new(); ctx.insert("location", "北京"); ctx.insert("condition", "晴"); ctx.insert("temperature", "25°C"); let rendered = tpl.render(&ctx).expect("渲染失败"); println!("渲染结果: {rendered}"); // 2. 缺失变量 → PromptError println!("\n=== 缺失变量 ==="); match tpl.render(&TemplateContext::new()) { Ok(_) => println!("意外成功"), Err(e) => println!("按预期报错: {e}"), } // 3. PromptTemplateRegistry —— 按名注册 + 渲染(支持 #if 条件) println!("\n=== PromptTemplateRegistry ==="); let mut registry = PromptTemplateRegistry::new(); registry .register("weather", "今日 {{location}}:{{condition}}") .expect("注册失败"); registry .register( "greet", "你好 {{name}}!{{#if formal}} 见到您很荣幸。{{/if}}", ) .expect("注册失败"); let mut ctx = TemplateContext::new(); ctx.insert("name", "Alice"); println!( "greet (formal=false): {}", registry.render("greet", &ctx).unwrap() ); ctx.insert("formal", true); println!( "greet (formal=true): {}", registry.render("greet", &ctx).unwrap() ); // 4. PromptComposer —— 构造多角色消息序列 println!("\n=== PromptComposer ==="); let messages = PromptComposer::new() .system("你是一个天气助手") .user("今天天气怎么样?") .assistant("请告诉我城市名。") .user(rendered) .build(); println!("消息数: {}", messages.len()); for (i, m) in messages.iter().enumerate() { let role = match m { Message::System { .. } => "system", Message::User { .. } | Message::UserImage { .. } => "user", Message::Assistant { .. } => "assistant", Message::ToolResult { .. } => "tool", _ => "unknown", }; println!("[{i}] {role}: {}", message_text(m)); } // 5. validate_messages —— 消息序列合法性校验 println!("\n=== validate_messages ==="); match validate_messages(&messages) { Ok(()) => println!("消息序列合法 ✓"), Err(e) => println!("消息序列非法: {e}"), } let empty: Vec = Vec::new(); match validate_messages(&empty) { Ok(()) => println!("空消息合法"), Err(e) => println!("空消息按预期报错: {e}"), } println!("\n✓ prompt_composer 完成"); }