Skip to main content

genai/client/
model_spec.rs

1use crate::{ModelIden, ModelName, ServiceTarget};
2
3/// Specifies how to identify and resolve a model for API calls.
4///
5/// `ModelSpec` provides three levels of control over model resolution:
6///
7/// - [`ModelSpec::Name`]: Just a model name string. The adapter kind is inferred
8///   from the name, and auth/endpoint are resolved via the client's configured resolvers.
9///
10/// - [`ModelSpec::Iden`]: An explicit [`ModelIden`] with adapter kind specified.
11///   Skips adapter inference but still resolves auth/endpoint via config.
12///
13/// - [`ModelSpec::Target`]: A complete [`ServiceTarget`] with endpoint, auth, and model.
14///   Used directly, only runs the service target resolver.
15///
16/// # Examples
17///
18/// ```rust
19/// use genai::adapter::AdapterKind;
20/// use genai::resolver::{AuthData, Endpoint};
21/// use genai::{ModelIden, ModelSpec, ServiceTarget};
22///
23/// // Using a string name (full inference)
24/// let spec: ModelSpec = "gpt-4".into();
25///
26/// // Using an explicit ModelIden (skip adapter inference)
27/// let spec: ModelSpec = ModelIden::new(AdapterKind::OpenAI, "gpt-4").into();
28///
29/// // Using a complete ServiceTarget (bypass all resolution)
30/// let target = ServiceTarget {
31///     endpoint: Endpoint::from_static("https://custom.api/v1/"),
32///     auth: AuthData::from_env("CUSTOM_API_KEY"),
33///     model: ModelIden::new(AdapterKind::OpenAI, "custom-model"),
34/// };
35/// let spec: ModelSpec = target.into();
36/// ```
37#[derive(Debug, Clone)]
38pub enum ModelSpec {
39	/// Model name - without or without model namespace
40	Name(ModelName),
41
42	/// Explicit [`ModelIden`] - skips adapter inference, still resolves auth/endpoint.
43	Iden(ModelIden),
44
45	/// Complete [`ServiceTarget`] - used directly, bypasses model mapping and auth resolution
46	Target(ServiceTarget),
47}
48
49// region:    --- Constructors
50
51impl ModelSpec {
52	/// Creates a `ModelSpec::Name` from a string.
53	pub fn from_name(name: impl Into<ModelName>) -> Self {
54		ModelSpec::Name(name.into())
55	}
56
57	/// Creates a `ModelSpec::Name` from a static str.
58	pub fn from_static_name(name: &'static str) -> Self {
59		let name = ModelName::from_static(name);
60		ModelSpec::Name(name)
61	}
62
63	/// Creates a `ModelSpec::Iden` from a ModelIden
64	pub fn from_iden(model_iden: impl Into<ModelIden>) -> Self {
65		let model_iden = model_iden.into();
66		Self::Iden(model_iden)
67	}
68
69	/// Creates a `ModelSpec::Target` from a complete service target.
70	pub fn from_target(target: ServiceTarget) -> Self {
71		ModelSpec::Target(target)
72	}
73}
74
75// endregion: --- Constructors
76
77// region:    --- From Implementations
78
79impl From<&str> for ModelSpec {
80	fn from(name: &str) -> Self {
81		ModelSpec::Name(name.into())
82	}
83}
84
85impl From<&&str> for ModelSpec {
86	fn from(name: &&str) -> Self {
87		ModelSpec::Name((*name).into())
88	}
89}
90
91impl From<String> for ModelSpec {
92	fn from(name: String) -> Self {
93		ModelSpec::Name(name.into())
94	}
95}
96
97impl From<&String> for ModelSpec {
98	fn from(name: &String) -> Self {
99		ModelSpec::Name(name.into())
100	}
101}
102
103impl From<ModelName> for ModelSpec {
104	fn from(model: ModelName) -> Self {
105		ModelSpec::Name(model)
106	}
107}
108
109impl From<&ModelName> for ModelSpec {
110	fn from(model: &ModelName) -> Self {
111		ModelSpec::Name(model.clone())
112	}
113}
114
115impl From<ModelIden> for ModelSpec {
116	fn from(model: ModelIden) -> Self {
117		ModelSpec::Iden(model)
118	}
119}
120
121impl From<&ModelIden> for ModelSpec {
122	fn from(model: &ModelIden) -> Self {
123		ModelSpec::Iden(model.clone())
124	}
125}
126
127impl From<ServiceTarget> for ModelSpec {
128	fn from(target: ServiceTarget) -> Self {
129		ModelSpec::Target(target)
130	}
131}
132
133// endregion: --- From Implementations