1pub use genai;
2
3pub trait LLMSafe {}
4
5impl<T: LLMSafe> LLMSafe for Vec<T> {}
6impl<T: LLMSafe> LLMSafe for Option<T> {}
7impl<T: LLMSafe> LLMSafe for Box<T> {}
8impl<T: LLMSafe> LLMSafe for &T {}
9impl<T: LLMSafe> LLMSafe for [T] {}
10impl<T: LLMSafe, const N: usize> LLMSafe for [T; N] {}
11use std::collections::HashMap;
12impl<K: LLMSafe, V: LLMSafe> LLMSafe for HashMap<K, V> {}
13
14pub use synapto_derive::LLMSafe;
15
16#[derive(
17 Clone,
18 Copy,
19 Debug,
20 serde::Serialize,
21 serde::Deserialize,
22 schemars::JsonSchema,
23 PartialEq,
24 Eq,
25 Default,
26)]
27pub enum ReasoningEffort {
28 #[default]
29 None,
30 Minimal,
31 Low,
32 Medium,
33 High,
34}
35
36#[derive(
37 Clone, Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema, PartialEq, Eq,
38)]
39pub struct ModelConfig {
40 pub model: String,
41 #[serde(default)]
42 pub thinking_level: ReasoningEffort,
43}
44
45#[derive(Debug, Default, Clone)]
46pub struct RawLlmOptions {
47 pub reasoning_effort: Option<genai::chat::ReasoningEffort>,
48 pub tools: Option<Vec<genai::chat::Tool>>,
49 pub resolved_tools: Option<Vec<(genai::chat::ToolCall, String)>>,
50 pub output_schema: Option<schemars::Schema>,
51 pub messages: Option<Vec<genai::chat::ChatMessage>>,
52}
53
54#[async_trait::async_trait]
56pub trait LlmExecutor: Send + Sync + 'static {
57 async fn execute_raw(
58 &self,
59 model: &str,
60 system_prompt: &str,
61 prompt: &str,
62 options: RawLlmOptions,
63 ) -> Result<genai::chat::ChatResponse, String>;
64}
65
66#[async_trait::async_trait]
67impl<T: LlmExecutor + ?Sized> LlmExecutor for std::sync::Arc<T> {
68 async fn execute_raw(
69 &self,
70 model: &str,
71 system_prompt: &str,
72 prompt: &str,
73 options: RawLlmOptions,
74 ) -> Result<genai::chat::ChatResponse, String> {
75 (**self)
76 .execute_raw(model, system_prompt, prompt, options)
77 .await
78 }
79}