wesichain_langsmith/lib.rs
1//! # LangSmith Observability for Wesichain
2//!
3//! Enable LangSmith tracing with either callback handlers (core callbacks) or the
4//! graph observer integration.
5//!
6//! ## Callback handler
7//!
8//! ```no_run
9//! use std::collections::BTreeMap;
10//! use std::sync::Arc;
11//!
12//! use futures::StreamExt;
13//! use secrecy::SecretString;
14//! use wesichain_core::{CallbackManager, RunConfig, Runnable, WesichainError};
15//! use wesichain_graph::{ExecutionOptions, GraphBuilder, GraphState, StateSchema, StateUpdate};
16//! use wesichain_langsmith::{LangSmithCallbackHandler, LangSmithConfig};
17//!
18//! #[derive(Clone, Default, Debug, serde::Serialize, serde::Deserialize)]
19//! struct DemoState {
20//! value: usize,
21//! }
22//!
23//! impl StateSchema for DemoState {
24//! type Update = Self;
25//! fn apply(_: &Self, update: Self) -> Self {
26//! update
27//! }
28//! }
29//!
30//! struct IncrNode;
31//!
32//! #[async_trait::async_trait]
33//! impl Runnable<GraphState<DemoState>, StateUpdate<DemoState>> for IncrNode {
34//! async fn invoke(
35//! &self,
36//! input: GraphState<DemoState>,
37//! ) -> Result<StateUpdate<DemoState>, WesichainError> {
38//! Ok(StateUpdate::new(DemoState {
39//! value: input.data.value + 1,
40//! }))
41//! }
42//!
43//! fn stream(
44//! &self,
45//! _input: GraphState<DemoState>,
46//! ) -> futures::stream::BoxStream<'_, Result<wesichain_core::StreamEvent, WesichainError>> {
47//! futures::stream::empty().boxed()
48//! }
49//! }
50//!
51//! #[tokio::main]
52//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
53//! let config = LangSmithConfig::new(SecretString::new("ls-api-key".to_string()), "demo");
54//! let handler = Arc::new(LangSmithCallbackHandler::new(config));
55//! let manager = CallbackManager::new(vec![handler]);
56//!
57//! let options = ExecutionOptions {
58//! run_config: Some(RunConfig {
59//! callbacks: Some(manager),
60//! tags: vec!["example".to_string()],
61//! metadata: BTreeMap::new(),
62//! name_override: Some("demo-graph".to_string()),
63//! }),
64//! ..Default::default()
65//! };
66//!
67//! let graph = GraphBuilder::new()
68//! .add_node("incr", IncrNode)
69//! .set_entry("incr")
70//! .build();
71//! let _ = graph
72//! .invoke_with_options(GraphState::new(DemoState::default()), options)
73//! .await?;
74//! Ok(())
75//! }
76//! ```
77//!
78//! ## Graph observer
79//!
80//! ```rust,no_run
81//! use std::sync::Arc;
82//! use std::time::Duration;
83//!
84//! use secrecy::SecretString;
85//! use wesichain_graph::{ExecutionOptions, ExecutableGraph, GraphState, StateSchema};
86//! use wesichain_langsmith::{LangSmithConfig, LangSmithObserver};
87//!
88//! #[derive(Clone, Default, Debug, serde::Serialize, serde::Deserialize)]
89//! struct DemoState;
90//!
91//! impl StateSchema for DemoState {
92//! type Update = Self;
93//! fn apply(_: &Self, update: Self) -> Self {
94//! update
95//! }
96//! }
97//!
98//! #[tokio::main]
99//! async fn main() {
100//! let config = LangSmithConfig::new(SecretString::new("key".to_string()), "example");
101//! let observer = Arc::new(LangSmithObserver::new(config));
102//! let options = ExecutionOptions {
103//! observer: Some(observer.clone()),
104//! ..Default::default()
105//! };
106//!
107//! let graph: ExecutableGraph<DemoState> = todo!("build with GraphBuilder");
108//! let state = GraphState::new(DemoState::default());
109//! let _ = graph.invoke_with_options(state, options).await;
110//! let _ = observer.flush(Duration::from_secs(5)).await;
111//! }
112//! ```
113mod client;
114mod config;
115mod events;
116mod exporter;
117mod handler;
118mod observer;
119mod run_store;
120mod sampler;
121mod sanitize;
122
123pub use client::{LangSmithClient, LangSmithError};
124pub use config::LangSmithConfig;
125pub use events::{LangSmithInputs, LangSmithOutputs, RunEvent, RunStatus, RunType};
126pub use exporter::{FlushError, FlushStats, LangSmithExporter};
127pub use handler::LangSmithCallbackHandler;
128pub use observer::LangSmithObserver;
129pub use run_store::{RunContextStore, RunMetadata, RunUpdateDecision};
130pub use sampler::{ProbabilitySampler, Sampler};
131pub use sanitize::{ensure_object, sanitize_value, truncate_value};