-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathopenai_graph_agent.rs
More file actions
77 lines (66 loc) · 2.36 KB
/
Copy pathopenai_graph_agent.rs
File metadata and controls
77 lines (66 loc) · 2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! A durable graph whose node drives a real OpenAI-backed agent harness.
//!
//! Wraps an [`AgentHarness`] in an [`Arc`] and captures it in a graph node
//! closure. The graph runs START -> `agent` -> END: the `agent` node calls the
//! harness (which talks to OpenAI), stores the answer in the whole-state graph
//! state, and ends the run. This shows how the durable [`GraphBuilder`]
//! composes with a real model behind a harness.
//!
//! Run with:
//!
//! ```text
//! cargo run --example openai_graph_agent
//! ```
use std::sync::Arc;
use tinyagents::harness::message::Message;
use tinyagents::harness::providers::openai::OpenAiModel;
use tinyagents::harness::runtime::AgentHarness;
use tinyagents::{GraphBuilder, NodeContext, NodeResult, Result};
/// State threaded through the graph: the question to ask and the answer the
/// agent node fills in.
#[derive(Clone, Debug)]
struct ChatState {
question: String,
answer: Option<String>,
}
#[tokio::main]
async fn main() -> Result<()> {
dotenvy::dotenv().ok();
let model = OpenAiModel::from_env()?;
println!("=== OpenAI-backed graph agent ===");
println!("model: {}", model.model());
// Build the harness once and share it into the node via an Arc.
let mut harness: AgentHarness<()> = AgentHarness::new();
harness
.register_model("openai", Arc::new(model))
.set_default_model("openai");
let harness = Arc::new(harness);
let graph = GraphBuilder::<ChatState, ChatState>::overwrite()
.add_node("agent", move |mut state: ChatState, _ctx: NodeContext| {
let harness = harness.clone();
async move {
let run = harness
.invoke_default(&(), vec![Message::user(state.question.clone())])
.await?;
state.answer = run.text();
Ok(NodeResult::Update(state))
}
})
.set_entry("agent")
.set_finish("agent")
.compile()?;
let question = "Name three popular Rust web frameworks, comma-separated.";
println!("question: {question}\n");
let run = graph
.run(ChatState {
question: question.to_string(),
answer: None,
})
.await?;
println!("visited: {:?}", run.visited);
println!(
"answer : {}",
run.state.answer.unwrap_or_else(|| "<none>".to_string())
);
Ok(())
}