Skip to main content

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}