use anyhow::Result;
use jsonxf::pretty_print;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fs;
use tyrell::{ClaudeRequest, ContentType, Model, Role, Tool, ToolBuilder, ToolChoice};
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct EarningsCallAnalysis {
company_name: String,
ticker: String,
call_date: String,
fiscal_period: String,
reported_eps: f64,
estimated_eps: f64,
reported_revenue: f64,
estimated_revenue: f64,
yoy_revenue_growth: f64,
net_income: f64,
kpis: Vec<KPI>,
key_quotes: Vec<String>,
guidance: Option<Guidance>,
announcements: Vec<String>,
sentiment: CallSentiment,
risk_factors: Vec<String>,
qa_summary: Vec<QAItem>,
}
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct KPI {
name: String,
value: String,
previous_value: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct Guidance {
next_quarter_revenue: Option<(f64, f64)>,
next_quarter_eps: Option<(f64, f64)>,
full_year_revenue: Option<(f64, f64)>,
full_year_eps: Option<(f64, f64)>,
}
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct CallSentiment {
overall_score: f64,
performance_sentiment: String,
outlook_sentiment: String,
}
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct QAItem {
question: String,
response_summary: String,
}
impl ToolBuilder for EarningsCallAnalysis {
fn name() -> &'static str {
"analyze_earnings_call"
}
fn description() -> Option<&'static str> {
Some("Extract information from a quarterly earnings call")
}
}
#[tokio::main]
async fn main() -> Result<()> {
let tool = Tool::new::<EarningsCallAnalysis>();
let earnings_call_transcript =
fs::read_to_string("examples/boeing_2024q2_earnings_transcript.txt")?;
let chat = ClaudeRequest::builder()
.model(Model::Haiku3)
.add_message(
Role::Assistant,
vec![ContentType::Text {
text: "You are an expert financial analyst.".to_string(),
}],
)
.add_message(
Role::User,
vec![ContentType::Text {
text: format!(
"Analyze the this quarterly earnings call:\n\n{}",
earnings_call_transcript
),
}],
)
.max_tokens(200)
.tools(vec![tool])
.tool_choice(ToolChoice::Specific {
name: "analyze_earnings_call".to_string(),
disable_parallel_tool_use: Some(false),
})
.build()
.unwrap();
let response = chat.call().await.unwrap();
let response = pretty_print(&response).unwrap();
println!("{}", response);
Ok(())
}