use harmony_response::{
chat::{Conversation, Message, Role, SystemContent, ReasoningEffort},
encoding::RenderConversationConfig,
load_harmony_encoding, HarmonyEncodingName,
};
fn main() -> anyhow::Result<()> {
println!("๐บ Harmony Response Format - Channel Management Example");
println!("=======================================================");
println!("\nโ๏ธ Step 1: Setting up channel configuration");
let system_content = SystemContent::new()
.with_model_identity("Channel Management Demo Assistant")
.with_reasoning_effort(ReasoningEffort::High)
.with_required_channels(["analysis", "commentary", "final"])
.with_browser_tool()
.with_conversation_start_date("2024-01-15");
println!("โ Configured system with required channels: analysis, commentary, final");
println!("โ Set reasoning effort to HIGH for detailed analysis");
println!("\n๐ฌ Step 2: Creating multi-channel conversation");
let conversation = Conversation::from_messages([
Message::from_role_and_content(Role::System, system_content),
Message::from_role_and_content(
Role::User,
"I'm trying to decide between two job offers. One pays more but has longer hours, \
the other has better work-life balance but lower salary. How should I approach this decision?"
),
Message::from_role_and_content(
Role::Assistant,
"This is a complex decision involving multiple factors: compensation, work-life balance, \
career growth potential, personal values, and life circumstances. I need to provide a \
structured approach that helps them evaluate both options objectively."
).with_channel("analysis"),
Message::from_role_and_content(
Role::Assistant,
"I should consider both quantitative factors (salary difference, hours) and qualitative \
factors (job satisfaction, stress levels, career development). A decision framework \
would be most helpful here."
).with_channel("analysis"),
Message::from_role_and_content(
Role::Assistant,
"The user is facing a classic trade-off dilemma. Rather than telling them what to choose, \
I should provide a systematic approach they can use to make the decision themselves, \
taking into account their personal priorities and circumstances."
).with_channel("commentary"),
Message::from_role_and_content(
Role::Assistant,
"I'll structure my response to include: a decision framework, key questions to consider, \
and a practical evaluation method. This empowers them to make an informed choice."
).with_channel("commentary"),
Message::from_role_and_content(
Role::Assistant,
"This is a great question that many people face! Here's a structured approach to help you make this decision:\n\n\
**1. Quantify the Trade-offs**\n\
- Calculate the actual hourly rate for both jobs (salary รท total hours worked)\n\
- Consider the long-term financial impact over 2-5 years\n\
- Factor in benefits, bonuses, and growth potential\n\n\
**2. Assess Personal Priorities**\n\
- How important is work-life balance to you right now?\n\
- Do you have family commitments or personal goals requiring time?\n\
- What are your career aspirations in the next 5 years?\n\n\
**3. Evaluate the Roles**\n\
- Which role offers better learning opportunities?\n\
- What are the company cultures like?\n\
- Which position aligns better with your long-term goals?\n\n\
**4. Create a Decision Matrix**\n\
Score each job (1-10) on factors important to you: salary, hours, growth, culture, etc. \
Weight each factor by importance to you personally.\n\n\
Remember, there's no universally 'right' choice - only what's right for your current situation and goals."
).with_channel("final"),
Message::from_role_and_content(
Role::User,
"That's helpful! Can you also help me think about how to negotiate with either company?"
),
Message::from_role_and_content(
Role::Assistant,
"Now they're asking about negotiation strategies. This requires understanding leverage, \
timing, and what's typically negotiable. I should provide practical, actionable advice \
while being realistic about what's possible in different scenarios."
).with_channel("analysis"),
Message::from_role_and_content(
Role::Assistant,
"Absolutely! Here are key negotiation strategies:\n\n\
**Timing is Everything**\n\
- Wait for a written offer before negotiating\n\
- Negotiate after acceptance but before starting\n\n\
**What You Can Negotiate**\n\
- Salary (most obvious)\n\
- Start date (gives you time)\n\
- Remote work options\n\
- Professional development budget\n\
- Additional vacation days\n\
- Flexible hours\n\n\
**How to Approach It**\n\
- Express enthusiasm first: 'I'm excited about this opportunity...'\n\
- Be specific: 'Based on my research and experience...'\n\
- Provide rationale: market rates, unique skills, competing offers\n\
- Be prepared to compromise\n\n\
Having two offers gives you significant leverage - use it wisely!"
).with_channel("final"),
]);
println!("โ Created conversation with {} messages across multiple channels", conversation.messages.len());
let mut channel_counts = std::collections::HashMap::new();
for message in &conversation.messages {
if let Some(channel) = &message.channel {
*channel_counts.entry(channel.clone()).or_insert(0) += 1;
} else {
*channel_counts.entry("none".to_string()).or_insert(0) += 1;
}
}
println!(" Channel distribution:");
for (channel, count) in &channel_counts {
println!(" - {}: {} messages", channel, count);
}
println!("\n๐จ Step 3: Testing different rendering configurations");
match load_harmony_encoding(HarmonyEncodingName::HarmonyGptOss) {
Ok(encoding) => {
println!("โ
Successfully loaded encoding");
let config_keep_all = RenderConversationConfig { auto_drop_analysis: false };
let tokens_with_all = encoding.render_conversation(&conversation, Some(&config_keep_all))?;
println!("โ Rendered with all channels: {} tokens", tokens_with_all.len());
let config_drop_analysis = RenderConversationConfig { auto_drop_analysis: true };
let tokens_dropped = encoding.render_conversation(&conversation, Some(&config_drop_analysis))?;
println!("โ Rendered with analysis dropping: {} tokens", tokens_dropped.len());
let token_reduction = tokens_with_all.len() - tokens_dropped.len();
if token_reduction > 0 {
println!("๐ Analysis dropping saved {} tokens ({:.1}% reduction)",
token_reduction,
(token_reduction as f64 / tokens_with_all.len() as f64) * 100.0
);
} else {
println!("๐ No analysis dropping occurred (no final messages found)");
}
let completion_tokens = encoding
.render_conversation_for_completion(&conversation, Role::Assistant, Some(&config_drop_analysis))?;
println!("โ Rendered for completion: {} tokens", completion_tokens.len());
let training_tokens = encoding
.render_conversation_for_training(&conversation, Some(&config_drop_analysis))?;
println!("โ Rendered for training: {} tokens", training_tokens.len());
println!("\n๐ Step 4: Analyzing conversation structure");
let mut message_flow = Vec::new();
for (i, message) in conversation.messages.iter().enumerate() {
let channel = message.channel.as_deref().unwrap_or("none");
let role = message.author.role.as_str();
message_flow.push(format!("{}. {} ({})", i + 1, role, channel));
}
println!("Message flow:");
for flow_item in message_flow {
println!(" {}", flow_item);
}
println!("\n๐ Channel management example completed successfully!");
}
Err(e) => {
println!("โ ๏ธ Encoding load failed (expected without network access)");
println!(" Error: {}", e);
println!(" Channel structure created successfully!");
println!("\n๐ Channel analysis (without encoding):");
for (channel, count) in &channel_counts {
println!(" - {} channel: {} messages", channel, count);
}
let analysis_messages = conversation.messages.iter()
.filter(|msg| msg.channel.as_deref() == Some("analysis"))
.count();
let final_messages = conversation.messages.iter()
.filter(|msg| msg.channel.as_deref() == Some("final"))
.count();
if analysis_messages > 0 && final_messages > 0 {
println!(" Analysis dropping would remove {} analysis messages", analysis_messages);
}
}
}
Ok(())
}