sim_lib_openai_server/runtime/
runners.rs1use std::{fmt, sync::Arc};
2
3use sim_kernel::{Cx, Error, Result};
4use sim_lib_agent_runner_core::{ModelCard, ModelRequest, ModelResponse, ModelRunner};
5
6#[derive(Clone, Default)]
8pub struct OpenAiRunnerRegistry {
9 entries: Vec<OpenAiRunnerEntry>,
10}
11
12#[derive(Clone)]
13struct OpenAiRunnerEntry {
14 model: String,
15 runner: Arc<dyn ModelRunner>,
16}
17
18impl fmt::Debug for OpenAiRunnerRegistry {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 f.debug_struct("OpenAiRunnerRegistry")
21 .field(
22 "models",
23 &self
24 .entries
25 .iter()
26 .map(|entry| entry.model.as_str())
27 .collect::<Vec<_>>(),
28 )
29 .finish()
30 }
31}
32
33impl OpenAiRunnerRegistry {
34 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn with_runner(mut self, model: impl Into<String>, runner: Arc<dyn ModelRunner>) -> Self {
41 self.register(model, runner);
42 self
43 }
44
45 pub fn register(&mut self, model: impl Into<String>, runner: Arc<dyn ModelRunner>) {
47 self.entries.push(OpenAiRunnerEntry {
48 model: model.into(),
49 runner,
50 });
51 }
52
53 fn entry_for(&self, model: &str) -> Option<&OpenAiRunnerEntry> {
54 self.entries.iter().find(|entry| entry.model == model)
55 }
56
57 fn card_for_entry(entry: &OpenAiRunnerEntry) -> ModelCard {
58 let mut card = entry.runner.card();
59 if card.model != entry.model {
60 card.extra.push((
61 sim_kernel::Expr::Symbol(sim_kernel::Symbol::new("runner-model")),
62 sim_kernel::Expr::String(card.model.clone()),
63 ));
64 card.model = entry.model.clone();
65 }
66 card
67 }
68
69 pub fn cards(&self) -> Vec<ModelCard> {
75 self.entries.iter().map(Self::card_for_entry).collect()
76 }
77
78 pub fn card_for(&self, model: &str) -> Option<ModelCard> {
80 self.entry_for(model).map(Self::card_for_entry)
81 }
82
83 pub fn infer(&self, cx: &mut Cx, model: &str, request: ModelRequest) -> Result<ModelResponse> {
87 let runner = self
88 .entry_for(model)
89 .map(|entry| entry.runner.clone())
90 .ok_or_else(|| Error::Eval(format!("model_not_found: {model}")))?;
91 runner.infer(cx, request)
92 }
93
94 pub fn is_empty(&self) -> bool {
96 self.entries.is_empty()
97 }
98}