ollama_rs/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3use url::Url;
4
5#[cfg(feature = "macros")]
6pub use ollama_rs_macros::function;
7
8#[cfg(feature = "macros")]
9pub mod re_exports {
10 pub use schemars;
11 pub use serde;
12}
13
14pub mod coordinator;
15pub mod error;
16pub mod generation;
17#[cfg_attr(docsrs, doc(cfg(feature = "headers")))]
18#[cfg(feature = "headers")]
19pub mod headers;
20pub mod history;
21pub mod models;
22
23/// A trait to try to convert some type into a [`Url`].
24///
25/// This trait is "sealed", such that only types within ollama-rs can
26/// implement it.
27///
28/// # Examples
29///
30/// ```
31/// use url::Url;
32/// use ollama_rs::IntoUrl;
33///
34/// let url: Url = "http://example.com".into_url().unwrap();
35/// ```
36pub trait IntoUrl: IntoUrlSealed {}
37
38impl IntoUrl for Url {}
39impl IntoUrl for String {}
40impl IntoUrl for &str {}
41impl IntoUrl for &String {}
42
43pub trait IntoUrlSealed {
44 fn into_url(self) -> Result<Url, url::ParseError>;
45
46 fn as_str(&self) -> &str;
47}
48
49impl IntoUrlSealed for Url {
50 fn into_url(self) -> Result<Url, url::ParseError> {
51 Ok(self)
52 }
53
54 fn as_str(&self) -> &str {
55 self.as_str()
56 }
57}
58
59impl IntoUrlSealed for &str {
60 fn into_url(self) -> Result<Url, url::ParseError> {
61 Url::parse(self)?.into_url()
62 }
63
64 fn as_str(&self) -> &str {
65 self
66 }
67}
68
69impl IntoUrlSealed for &String {
70 fn into_url(self) -> Result<Url, url::ParseError> {
71 (&**self).into_url()
72 }
73
74 fn as_str(&self) -> &str {
75 self.as_ref()
76 }
77}
78
79impl IntoUrlSealed for String {
80 fn into_url(self) -> Result<Url, url::ParseError> {
81 (&*self).into_url()
82 }
83
84 fn as_str(&self) -> &str {
85 self.as_ref()
86 }
87}
88
89#[derive(Debug, Clone)]
90pub struct Ollama {
91 pub(crate) url: Url,
92 pub(crate) reqwest_client: reqwest::Client,
93 #[cfg(feature = "headers")]
94 pub(crate) request_headers: reqwest::header::HeaderMap,
95}
96
97/// The main struct representing an Ollama client.
98///
99/// This struct is used to interact with the Ollama service.
100///
101/// # Fields
102///
103/// * `url` - The base URL of the Ollama service.
104/// * `reqwest_client` - The HTTP client used for requests.
105/// * `request_headers` - Optional headers for requests (enabled with the `headers` feature).
106impl Ollama {
107 /// Creates a new `Ollama` instance with the specified host and port.
108 ///
109 /// # Arguments
110 ///
111 /// * `host` - The host of the Ollama service.
112 /// * `port` - The port of the Ollama service.
113 ///
114 /// # Returns
115 ///
116 /// A new `Ollama` instance.
117 ///
118 /// # Panics
119 ///
120 /// Panics if the host is not a valid URL or if the URL cannot have a port.
121 pub fn new(host: impl IntoUrl, port: u16) -> Self {
122 let mut url: Url = host.into_url().unwrap();
123 url.set_port(Some(port)).unwrap();
124
125 Self::from_url(url)
126 }
127
128 /// Creates a new `Ollama` instance with the specified host, port, and `reqwest` client.
129 ///
130 /// # Arguments
131 ///
132 /// * `host` - The host of the Ollama service.
133 /// * `port` - The port of the Ollama service.
134 /// * `reqwest_client` - The `reqwest` client instance.
135 ///
136 /// # Returns
137 ///
138 /// A new `Ollama` instance with the specified `reqwest` client.
139 ///
140 /// # Panics
141 ///
142 /// Panics if the host is not a valid URL or if the URL cannot have a port.
143 pub fn new_with_client(host: impl IntoUrl, port: u16, reqwest_client: reqwest::Client) -> Self {
144 let mut url: Url = host.into_url().unwrap();
145 url.set_port(Some(port)).unwrap();
146
147 Self {
148 url,
149 reqwest_client,
150 #[cfg(feature = "headers")]
151 request_headers: reqwest::header::HeaderMap::new(),
152 }
153 }
154
155 /// Attempts to create a new `Ollama` instance from a URL.
156 ///
157 /// # Arguments
158 ///
159 /// * `url` - The URL of the Ollama service.
160 ///
161 /// # Returns
162 ///
163 /// A `Result` containing the new `Ollama` instance or a `url::ParseError`.
164 #[inline]
165 pub fn try_new(url: impl IntoUrl) -> Result<Self, url::ParseError> {
166 Ok(Self::from_url(url.into_url()?))
167 }
168
169 /// Create new instance from a [`Url`].
170 #[inline]
171 pub fn from_url(url: Url) -> Self {
172 Self {
173 url,
174 ..Default::default()
175 }
176 }
177
178 /// Returns the URI of the Ollama service as a `String`.
179 ///
180 /// # Panics
181 ///
182 /// Panics if the URL does not have a host.
183 #[inline]
184 pub fn uri(&self) -> String {
185 self.url.host().unwrap().to_string()
186 }
187
188 /// Returns a reference to the URL of the Ollama service.
189 pub fn url(&self) -> &Url {
190 &self.url
191 }
192
193 /// Returns the URL of the Ollama service as a `&str`.
194 ///
195 /// Syntax in pseudo-BNF:
196 ///
197 /// ```bnf
198 /// url = scheme ":" [ hierarchical | non-hierarchical ] [ "?" query ]? [ "#" fragment ]?
199 /// non-hierarchical = non-hierarchical-path
200 /// non-hierarchical-path = /* Does not start with "/" */
201 /// hierarchical = authority? hierarchical-path
202 /// authority = "//" userinfo? host [ ":" port ]?
203 /// userinfo = username [ ":" password ]? "@"
204 /// hierarchical-path = [ "/" path-segment ]+
205 /// ```
206 #[inline]
207 pub fn url_str(&self) -> &str {
208 self.url.as_str()
209 }
210}
211
212impl From<Url> for Ollama {
213 fn from(url: Url) -> Self {
214 Self::from_url(url)
215 }
216}
217
218impl Default for Ollama {
219 /// Returns a default Ollama instance with the host set to `http://127.0.0.1:11434`.
220 fn default() -> Self {
221 Self {
222 url: Url::parse("http://127.0.0.1:11434").unwrap(),
223 reqwest_client: reqwest::Client::new(),
224 #[cfg(feature = "headers")]
225 request_headers: reqwest::header::HeaderMap::new(),
226 }
227 }
228}