use std::sync::Arc;
use langchain_rust::{
agent::{AgentExecutor, OpenAiToolAgentBuilder},
chain::Chain,
llm::{openai::OpenAI, OpenAIConfig},
prompt_args,
tools::{FunctionTool, Tool},
};
use serde::Deserialize;
use serde_json::json;
#[derive(Deserialize)]
struct AddInput {
a: f64,
b: f64,
}
#[tokio::main]
async fn main() {
let adder = FunctionTool::new(
"adder",
"Adds two numbers together",
json!({
"type": "object",
"properties": {
"a": { "type": "number", "description": "First number" },
"b": { "type": "number", "description": "Second number" }
},
"required": ["a", "b"]
}),
|input: AddInput| async move {
println!(" [adder] {} + {}", input.a, input.b);
Ok::<_, String>(format!(
"The sum of {} and {} is {}",
input.a,
input.b,
input.a + input.b
))
},
);
let word_count = FunctionTool::text(
"word_count",
"Counts the words in a text",
|text: String| async move {
println!(" [word_count] {text:?}");
Ok::<_, String>(text.split_whitespace().count())
},
);
println!(
"direct call: {}",
adder.call(r#"{"a": 2, "b": 3}"#).await.unwrap()
);
let llm = match std::env::var("TOOLS_OLLAMA_MODEL") {
Ok(model) => OpenAI::default()
.with_config(
OpenAIConfig::default()
.with_api_base("http://localhost:11434/v1")
.with_api_key("ollama"),
)
.with_model(model),
Err(_) => OpenAI::default(),
};
let tools: Vec<Arc<dyn Tool>> = vec![Arc::new(adder), Arc::new(word_count)];
let agent = OpenAiToolAgentBuilder::new()
.tools(&tools)
.build(llm)
.unwrap();
let executor = AgentExecutor::from_agent(agent).with_max_iterations(5);
let answer = executor
.invoke(prompt_args! {
"input" => "How many words are in 'the quick brown fox jumps', and what is that number plus 1234.5? Use the tools.",
})
.await
.unwrap();
println!("agent: {answer}");
}