use rstructor::{GrokClient, Instructor, LLMClient};
use serde::{Deserialize, Serialize};
use std::env;
#[derive(Instructor, Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "PascalCase")]
#[llm(description = "Category for a news article")]
enum ArticleCategory {
Politics,
Technology,
Business,
Sports,
Entertainment,
Health,
Science,
Environment,
Education,
Opinion,
Other,
}
#[derive(Instructor, Serialize, Deserialize, Debug)]
#[llm(description = "An entity mentioned in the article")]
struct Entity {
#[llm(description = "Name of the entity")]
name: String,
#[llm(description = "Type of the entity (person, organization, location, etc.)")]
entity_type: String,
#[llm(description = "How important this entity is to the article (1-10 scale)")]
relevance: u8,
}
#[derive(Instructor, Serialize, Deserialize, Debug)]
#[llm(description = "Analysis of a news article")]
struct ArticleAnalysis {
#[llm(
description = "Title of the article",
example = "Tech Stocks Tumble as Inflation Fears Rise"
)]
title: String,
#[llm(
description = "Category the article belongs to. Must be one of: Politics, Technology, Business, Sports, Entertainment, Health, Science, Environment, Education, Opinion, Other."
)]
category: ArticleCategory,
#[llm(
description = "A brief summary of the article (2-3 sentences)",
example = "The article discusses recent market movements in the technology sector. Major tech stocks fell by an average of 3% following concerns about rising inflation."
)]
summary: String,
#[llm(
description = "Overall sentiment of the article (Positive, Negative, or Neutral)",
example = "Negative"
)]
sentiment: String,
#[llm(
description = "Main entities mentioned in the article as objects with 'name' (string), 'entity_type' (person/organization/location), and 'relevance' (1-10) fields"
)]
entities: Vec<Entity>,
#[llm(description = "Important keywords from the article",
example = ["stocks", "technology", "inflation", "market"])]
keywords: Vec<String>,
#[llm(
description = "Assessment of any bias in the reporting",
example = "The article presents a somewhat negative view of tech companies, with limited perspective from industry insiders."
)]
bias_assessment: String,
}
async fn analyze_article(
article_text: &str,
) -> Result<ArticleAnalysis, Box<dyn std::error::Error>> {
let api_key = env::var("XAI_API_KEY").expect("Please set XAI_API_KEY environment variable");
println!("Using Grok for article analysis...");
let client = GrokClient::new(api_key)?.temperature(0.0);
let prompt = format!("Analyze the following news article:\n\n{}", article_text);
let analysis = client.materialize::<ArticleAnalysis>(&prompt).await?;
Ok(analysis)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let article = r#"
TECH GIANT UNVEILS REVOLUTIONARY AI CHIP AMID COMPETITION CONCERNS
Silicon Valley, CA - Tech behemoth NeuraTech announced yesterday the release of their new quantum-
based AI processor, the N-2000, which they claim can perform machine learning tasks at speeds 50
times faster than current market leaders while using 75% less energy.
CEO Jane Rodriguez showcased the processor at their annual developers conference, demonstrating
its capabilities by training a large language model in minutes rather than days. "This represents
a fundamental shift in what's possible with artificial intelligence," Rodriguez told the crowd of
developers and investors.
The announcement comes as regulatory bodies in both the US and EU are scrutinizing the growing
concentration of AI capabilities among a small number of tech companies. Last month, the Federal
Trade Commission opened an inquiry into potential anticompetitive practices in the AI chip market.
Market analysts reacted positively to the news, with NeuraTech's stock price jumping 12% by closing
bell. "The efficiency gains here can't be overstated," said Morgan Stanley analyst Raj Patel. "If
the performance metrics hold up in real-world applications, this could reshape the competitive
landscape."
Competing chip manufacturers SynthLogic and Quantum Semiconductors saw stock declines of 5% and 7%
respectively following the announcement. Representatives from both companies declined to comment.
The N-2000 processor is expected to begin shipping to select enterprise customers in Q3, with wider
availability planned for early next year.
"#;
match analyze_article(article).await {
Ok(analysis) => {
println!("\n===== Article Analysis =====");
println!("Title: {}", analysis.title);
println!("Category: {:?}", analysis.category);
println!("\nSummary: {}", analysis.summary);
println!("\nSentiment: {}", analysis.sentiment);
println!("\nEntities:");
for entity in analysis.entities {
println!(
"• {} ({}): Relevance {}/10",
entity.name, entity.entity_type, entity.relevance
);
}
println!("\nKeywords: {}", analysis.keywords.join(", "));
println!("\nBias Assessment: {}", analysis.bias_assessment);
}
Err(e) => {
eprintln!("Error analyzing article: {}", e);
eprintln!(
"\nNote: This error may occur if the LLM returns entities as strings instead of objects."
);
eprintln!("The retry mechanism attempts to fix this, but complex nested structures");
eprintln!("can be challenging. Try running again or increase retry count.");
}
}
Ok(())
}