1use anyhow::{anyhow, Result};
2use schemars::JsonSchema;
3use serde::Deserialize;
4use serde::Serialize;
5use std::ffi::OsStr;
6use std::path::Path;
7
8use allms::{
9 files::{AnthropicFile, LLMFiles},
10 llm::{
11 tools::{
12 AnthropicCodeExecutionConfig, AnthropicFileSearchConfig, AnthropicWebSearchConfig,
13 LLMTools,
14 },
15 AnthropicModels,
16 },
17 Completions,
18};
19
20#[derive(Deserialize, Serialize, JsonSchema, Debug, Clone)]
22struct AINewsArticles {
23 pub articles: Vec<AINewsArticle>,
24}
25
26#[derive(Deserialize, Serialize, JsonSchema, Debug, Clone)]
27struct AINewsArticle {
28 pub title: String,
29 pub url: String,
30 pub description: String,
31}
32
33#[derive(Deserialize, Serialize, Debug, Clone, JsonSchema)]
35pub struct CodeInterpreterResponse {
36 pub problem: String,
37 pub code: String,
38 pub solution: String,
39}
40
41#[derive(Deserialize, Serialize, Debug, Clone, JsonSchema)]
43pub struct ConcertInfo {
44 dates: Vec<String>,
45 band: String,
46 genre: String,
47 venue: String,
48 city: String,
49 country: String,
50 ticket_price: String,
51}
52
53const BANDS_GENRES: &[(&str, &str)] = &[
54 ("Metallica", "Metal"),
55 ("The Beatles", "Rock"),
56 ("Daft Punk", "Electronic"),
57 ("Miles Davis", "Jazz"),
58 ("Johnny Cash", "Country"),
59];
60
61#[tokio::main]
62async fn main() -> Result<()> {
63 env_logger::init();
64
65 let anthropic_api_key: String =
66 std::env::var("ANTHROPIC_API_KEY").expect("ANTHROPIC_API_KEY not set");
67
68 let web_search_tool = LLMTools::AnthropicWebSearch(AnthropicWebSearchConfig::new());
70 let anthropic_responses = Completions::new(
71 AnthropicModels::ClaudeOpus4_7,
72 &anthropic_api_key,
73 None,
74 None,
75 )
76 .add_tool(web_search_tool);
77
78 match anthropic_responses
79 .get_answer::<AINewsArticles>("Find up to 5 most recent news items about Artificial Intelligence, Generative AI, and Large Language Models.
80 For each news item, provide the title, url, and a short description.")
81 .await
82 {
83 Ok(response) => println!("AI news articles:\n{:#?}", response),
84 Err(e) => eprintln!("Error: {:?}", e),
85 }
86
87 let code_interpreter_tool =
90 LLMTools::AnthropicCodeExecution(AnthropicCodeExecutionConfig::new());
91 let anthropic_responses = Completions::new(
92 AnthropicModels::ClaudeOpus4_7,
93 &anthropic_api_key,
94 None,
95 None,
96 )
97 .add_tool(code_interpreter_tool);
98
99 match anthropic_responses
100 .get_answer::<CodeInterpreterResponse>(
101 "Calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]",
102 )
103 .await
104 {
105 Ok(response) => println!("Code interpreter response:\n{:#?}", response),
106 Err(e) => eprintln!("Error: {:?}", e),
107 }
108
109 let path = Path::new("metallica.pdf");
113 let bytes = std::fs::read(path)?;
114 let file_name = path
115 .file_name()
116 .and_then(OsStr::to_str)
117 .map(|s| s.to_string())
118 .ok_or_else(|| anyhow!("Failed to extract file name"))?;
119
120 let anthropic_file = AnthropicFile::new(None, &anthropic_api_key)
121 .upload(&file_name, bytes)
122 .await?;
123
124 let file_search_tool = LLMTools::AnthropicFileSearch(AnthropicFileSearchConfig::new(
126 anthropic_file.id.clone().unwrap_or_default(),
127 ));
128
129 let anthropic_responses = Completions::new(
130 AnthropicModels::ClaudeSonnet4_6,
131 &anthropic_api_key,
132 None,
133 None,
134 )
135 .set_context("bands_genres", &BANDS_GENRES)?
136 .add_tool(file_search_tool);
137
138 match anthropic_responses
139 .get_answer::<ConcertInfo>("Extract the information requested in the response type from the attached concert information.
140 The response should include the genre of the music the 'band' represents.
141 The mapping of bands to genres was provided in 'bands_genres' list.")
142 .await
143 {
144 Ok(response) => println!("Concert Info:\n{:#?}", response),
145 Err(e) => eprintln!("Error: {:?}", e),
146 }
147
148 anthropic_file.delete().await?;
150
151 Ok(())
152}