langchain_rust/agent/
agent.rs1use std::{pin::Pin, sync::Arc};
2
3use async_trait::async_trait;
4use futures::Stream;
5
6use crate::{
7 language_models::TokenUsage,
8 prompt::PromptArgs,
9 schemas::agent::{AgentAction, AgentEvent, AgentFinish},
10 tools::Tool,
11};
12
13use super::AgentError;
14
15#[derive(Debug)]
17#[non_exhaustive]
18pub enum PlanEvent {
19 Text(String),
21 Usage(TokenUsage),
24 Done(AgentEvent),
26}
27
28pub type PlanEventStream<'a> =
30 Pin<Box<dyn Stream<Item = Result<PlanEvent, AgentError>> + Send + 'a>>;
31
32pub(crate) fn box_plan_events<'a, S>(stream: S) -> PlanEventStream<'a>
34where
35 S: Stream<Item = Result<PlanEvent, AgentError>> + Send + 'a,
36{
37 Box::pin(stream)
38}
39
40#[async_trait]
41pub trait Agent: Send + Sync {
42 async fn plan(
43 &self,
44 intermediate_steps: &[(AgentAction, String)],
45 inputs: PromptArgs,
46 ) -> Result<AgentEvent, AgentError>;
47
48 fn get_tools(&self) -> Vec<Arc<dyn Tool>>;
49
50 async fn plan_with_usage(
55 &self,
56 intermediate_steps: &[(AgentAction, String)],
57 inputs: PromptArgs,
58 ) -> Result<(AgentEvent, Option<TokenUsage>), AgentError> {
59 Ok((self.plan(intermediate_steps, inputs).await?, None))
60 }
61
62 fn plan_stream<'a>(
70 &'a self,
71 intermediate_steps: &'a [(AgentAction, String)],
72 inputs: PromptArgs,
73 ) -> PlanEventStream<'a> {
74 box_plan_events(async_stream::try_stream! {
75 let (event, usage) = self.plan_with_usage(intermediate_steps, inputs).await?;
76 if let AgentEvent::Finish(AgentFinish { output }) = &event {
77 if !output.is_empty() {
78 yield PlanEvent::Text(output.clone());
79 }
80 }
81 if let Some(usage) = usage {
82 yield PlanEvent::Usage(usage);
83 }
84 yield PlanEvent::Done(event);
85 })
86 }
87}