Skip to main content

netget/llm/
event_instructions.rs

1//! Event-specific instructions and configuration
2//!
3//! This module provides simple default instructions for each EventType,
4//! with the ability to override them at server configuration time.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9/// Event-specific instructions
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct EventInstructions {
12    /// Mandatory instructions string
13    pub instructions: String,
14
15    /// Optional examples for the event
16    #[serde(default)]
17    pub examples: Vec<Example>,
18}
19
20/// An example for an event
21#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct Example {
23    /// Input example
24    pub input: String,
25
26    /// Expected output
27    pub output: String,
28
29    /// Optional description
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub description: Option<String>,
32}
33
34/// Server instruction configuration
35#[derive(Debug, Clone, Default)]
36pub struct ServerInstructionConfig {
37    /// Global instructions that apply to all events
38    pub global_instructions: Option<String>,
39
40    /// Event-specific instruction overrides
41    pub event_overrides: HashMap<String, EventInstructions>,
42
43    /// Existing scripting configuration (preserved)
44    pub scripts: HashMap<String, crate::scripting::types::ScriptConfig>,
45}
46
47impl ServerInstructionConfig {
48    /// Create a new empty configuration
49    pub fn new() -> Self {
50        Self::default()
51    }
52
53    /// Set global instructions
54    pub fn with_global_instructions(mut self, instructions: String) -> Self {
55        self.global_instructions = Some(instructions);
56        self
57    }
58
59    /// Add an event-specific override
60    pub fn with_event_override(
61        mut self,
62        event_type: String,
63        instructions: EventInstructions,
64    ) -> Self {
65        self.event_overrides.insert(event_type, instructions);
66        self
67    }
68
69    /// Get instructions for a specific event type
70    pub fn get_instructions_for_event(&self, event_type: &str) -> Option<&EventInstructions> {
71        self.event_overrides.get(event_type)
72    }
73
74    /// Check if a script handles this event type (priority over instructions)
75    pub fn has_script_for_event(&self, event_type: &str) -> bool {
76        self.scripts
77            .iter()
78            .any(|(_, config)| config.handles_context(event_type))
79    }
80}
81
82/// Result of instruction resolution
83#[derive(Debug, Clone)]
84pub enum InstructionSource {
85    /// Using a script
86    Script(String),
87    /// Using event override instructions
88    EventOverride(EventInstructions),
89    /// Using default instructions
90    Default(EventInstructions),
91    /// Using global instructions only
92    GlobalOnly(String),
93    /// No instructions found
94    None,
95}
96
97impl EventInstructions {
98    /// Create new event instructions with just text
99    pub fn new(instructions: impl Into<String>) -> Self {
100        Self {
101            instructions: instructions.into(),
102            examples: Vec::new(),
103        }
104    }
105
106    /// Add an example
107    pub fn with_example(mut self, input: impl Into<String>, output: impl Into<String>) -> Self {
108        self.examples.push(Example {
109            input: input.into(),
110            output: output.into(),
111            description: None,
112        });
113        self
114    }
115
116    /// Add an example with description
117    pub fn with_described_example(
118        mut self,
119        input: impl Into<String>,
120        output: impl Into<String>,
121        description: impl Into<String>,
122    ) -> Self {
123        self.examples.push(Example {
124            input: input.into(),
125            output: output.into(),
126            description: Some(description.into()),
127        });
128        self
129    }
130}