feat: implement api/show endpoint
This commit is contained in:
@@ -162,6 +162,7 @@ When the model decides to call a tool, the response `message.tool_calls` field w
|
|||||||
| `chat(request)` | Chat conversation (streaming) |
|
| `chat(request)` | Chat conversation (streaming) |
|
||||||
| `pull(request)` | Pull/download a model (streaming) |
|
| `pull(request)` | Pull/download a model (streaming) |
|
||||||
| `delete(request)` | Delete a model from the server |
|
| `delete(request)` | Delete a model from the server |
|
||||||
|
| `show_model(request)` | Show information about a model |
|
||||||
| `embed(request)` | Generate vector embeddings |
|
| `embed(request)` | Generate vector embeddings |
|
||||||
|
|
||||||
**`OllamaClient::builder(server_address)`** -- `.connection_timeout(Duration)`, `.build()`
|
**`OllamaClient::builder(server_address)`** -- `.connection_timeout(Duration)`, `.build()`
|
||||||
@@ -185,6 +186,8 @@ let client = OllamaClient::builder("http://localhost:11434")
|
|||||||
|
|
||||||
**`EmbedRequest::builder(model)`** -- `.input()`, `.inputs()`, `.truncate()`, `.dimensions()`, `.keep_alive()`, `.options()`
|
**`EmbedRequest::builder(model)`** -- `.input()`, `.inputs()`, `.truncate()`, `.dimensions()`, `.keep_alive()`, `.options()`
|
||||||
|
|
||||||
|
**`ShowModelRequest::new(model)`** -- `.verbose()`
|
||||||
|
|
||||||
### Generation Options
|
### Generation Options
|
||||||
|
|
||||||
Configure sampling parameters via `Options::builder()`:
|
Configure sampling parameters via `Options::builder()`:
|
||||||
@@ -212,6 +215,7 @@ The `examples/` directory contains runnable programs:
|
|||||||
| `tool_call` | Function calling / tool use |
|
| `tool_call` | Function calling / tool use |
|
||||||
| `pull` | Download a model |
|
| `pull` | Download a model |
|
||||||
| `delete` | Delete a model |
|
| `delete` | Delete a model |
|
||||||
|
| `show_model` | Show model information |
|
||||||
| `embed` | Generate text embeddings |
|
| `embed` | Generate text embeddings |
|
||||||
| `tags` | List available models |
|
| `tags` | List available models |
|
||||||
| `ps` | List running models |
|
| `ps` | List running models |
|
||||||
|
|||||||
22
examples/show_model.rs
Normal file
22
examples/show_model.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
use ollama_rs::OllamaClient;
|
||||||
|
use ollama_rs::types::show::ShowModelRequest;
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let client = OllamaClient::default();
|
||||||
|
let model = "qwen3:8b";
|
||||||
|
|
||||||
|
println!("Requesting info for model: {}", model);
|
||||||
|
let request = ShowModelRequest::new(model.to_string());
|
||||||
|
let response = client.show_model(request).await?;
|
||||||
|
|
||||||
|
println!("Model Info:");
|
||||||
|
println!(" License: {}", response.license.as_deref().unwrap_or("N/A").lines().next().unwrap_or("")); // First line only
|
||||||
|
println!(" Modelfile: {} bytes", response.modelfile.as_ref().map(|s| s.len()).unwrap_or(0));
|
||||||
|
println!(" Parameters: {}", response.parameters.as_ref().map(|s| s.len()).unwrap_or(0));
|
||||||
|
println!(" Template: {:?}", response.template.is_some());
|
||||||
|
println!(" Details: {:?}", response.details);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
38
src/lib.rs
38
src/lib.rs
@@ -98,6 +98,7 @@ use crate::{
|
|||||||
generate::{GenerateRequest, GenerateResponse},
|
generate::{GenerateRequest, GenerateResponse},
|
||||||
ps::PsResponse,
|
ps::PsResponse,
|
||||||
pull::{PullRequest, PullResponse},
|
pull::{PullRequest, PullResponse},
|
||||||
|
show::{ShowModelRequest, ShowModelResponse},
|
||||||
tags::TagsResponse,
|
tags::TagsResponse,
|
||||||
version::VersionResponse,
|
version::VersionResponse,
|
||||||
},
|
},
|
||||||
@@ -456,6 +457,43 @@ impl OllamaClient {
|
|||||||
let request_address = format!("{}/api/pull", self.server_address);
|
let request_address = format!("{}/api/pull", self.server_address);
|
||||||
self.stream_response(request_address, request)
|
self.stream_response(request_address, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shows information about a model.
|
||||||
|
///
|
||||||
|
/// Calls `POST /api/show`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns [`OllamaError::NetworkError`] if the server is unreachable or returns
|
||||||
|
/// a non-success status code.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// # use ollama_rs::OllamaClient;
|
||||||
|
/// # use ollama_rs::types::show::ShowModelRequest;
|
||||||
|
/// # async fn run() -> ollama_rs::error::OllamaResult<()> {
|
||||||
|
/// let client = OllamaClient::default();
|
||||||
|
/// let request = ShowModelRequest::new("llama3".to_string());
|
||||||
|
///
|
||||||
|
/// let response = client.show_model(request).await?;
|
||||||
|
/// println!("Model info: {:?}", response);
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub async fn show_model(&self, request: ShowModelRequest) -> OllamaResult<ShowModelResponse> {
|
||||||
|
let request_address = format!("{}/api/show", self.server_address);
|
||||||
|
info!("Show model: {}", request.name);
|
||||||
|
Ok(self
|
||||||
|
.client
|
||||||
|
.post(request_address)
|
||||||
|
.json(&request)
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.error_for_status()?
|
||||||
|
.json()
|
||||||
|
.await?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A builder for constructing an [`OllamaClient`] with custom configuration.
|
/// A builder for constructing an [`OllamaClient`] with custom configuration.
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Detailed metadata about a model, returned by the tags and ps endpoints.
|
/// Detailed metadata about a model, returned by the tags, ps, and show endpoints.
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct ModelDetails {
|
pub struct ModelDetails {
|
||||||
/// The model file format (e.g., `"gguf"`).
|
/// The model file format (e.g., `"gguf"`).
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
//! | [`embed`] | `POST /api/embed` | Generate vector embeddings |
|
//! | [`embed`] | `POST /api/embed` | Generate vector embeddings |
|
||||||
//! | [`generate`] | `POST /api/generate` | Single-prompt text generation |
|
//! | [`generate`] | `POST /api/generate` | Single-prompt text generation |
|
||||||
//! | [`pull`] | `POST /api/pull` | Download models from the registry |
|
//! | [`pull`] | `POST /api/pull` | Download models from the registry |
|
||||||
|
//! | [`show`] | `POST /api/show` | Show model details |
|
||||||
//! | [`tags`] | `GET /api/tags` | List available models |
|
//! | [`tags`] | `GET /api/tags` | List available models |
|
||||||
//! | [`ps`] | `GET /api/ps` | List currently loaded/running models |
|
//! | [`ps`] | `GET /api/ps` | List currently loaded/running models |
|
||||||
//! | [`version`] | `GET /api/version` | Query the server version |
|
//! | [`version`] | `GET /api/version` | Query the server version |
|
||||||
@@ -24,5 +25,6 @@ pub mod embed;
|
|||||||
pub mod generate;
|
pub mod generate;
|
||||||
pub mod ps;
|
pub mod ps;
|
||||||
pub mod pull;
|
pub mod pull;
|
||||||
|
pub mod show;
|
||||||
pub mod tags;
|
pub mod tags;
|
||||||
pub mod version;
|
pub mod version;
|
||||||
|
|||||||
101
src/types/show.rs
Normal file
101
src/types/show.rs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
//! Types for the show model information endpoint (`POST /api/show`).
|
||||||
|
//!
|
||||||
|
//! Use [`ShowModelRequest`] to construct a request and pass it to
|
||||||
|
//! [`OllamaClient::show_model`](crate::OllamaClient::show_model).
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::common::ModelDetails;
|
||||||
|
|
||||||
|
/// A request to the show model endpoint (`POST /api/show`).
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct ShowModelRequest {
|
||||||
|
/// The name of the model to retrieve information for.
|
||||||
|
pub name: String,
|
||||||
|
/// Whether to return full model details (e.g. system prompt, template).
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub verbose: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShowModelRequest {
|
||||||
|
/// Creates a new request for the given model name.
|
||||||
|
pub fn new(name: String) -> Self {
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
verbose: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enables verbose output, returning full model details.
|
||||||
|
pub fn verbose(mut self) -> Self {
|
||||||
|
self.verbose = Some(true);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A response from the show model endpoint.
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct ShowModelResponse {
|
||||||
|
/// The license of the model.
|
||||||
|
pub license: Option<String>,
|
||||||
|
/// The modelfile content.
|
||||||
|
pub modelfile: Option<String>,
|
||||||
|
/// The model parameters (e.g., stop tokens, temperature defaults).
|
||||||
|
pub parameters: Option<String>,
|
||||||
|
/// The prompt template.
|
||||||
|
pub template: Option<String>,
|
||||||
|
/// The system prompt.
|
||||||
|
pub system: Option<String>,
|
||||||
|
/// Detailed model metadata.
|
||||||
|
pub details: Option<ModelDetails>,
|
||||||
|
/// Additional model information.
|
||||||
|
pub model_info: Option<serde_json::Map<String, serde_json::Value>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn request_new_serialized() {
|
||||||
|
let request = ShowModelRequest::new("llama3".to_string());
|
||||||
|
let json = serde_json::to_value(&request).unwrap();
|
||||||
|
assert_eq!(json, json!({"name": "llama3"}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn request_verbose_serialized() {
|
||||||
|
let request = ShowModelRequest::new("llama3".to_string()).verbose();
|
||||||
|
let json = serde_json::to_value(&request).unwrap();
|
||||||
|
assert_eq!(json, json!({"name": "llama3", "verbose": true}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn response_deserialization() {
|
||||||
|
let json = json!({
|
||||||
|
"license": "MIT",
|
||||||
|
"modelfile": "FROM llama3",
|
||||||
|
"parameters": "temperature 0.7",
|
||||||
|
"template": "Please answer:",
|
||||||
|
"system": "You are helpful",
|
||||||
|
"details": {
|
||||||
|
"format": "gguf",
|
||||||
|
"family": "llama",
|
||||||
|
"families": ["llama"],
|
||||||
|
"parameter_size": "8B",
|
||||||
|
"quantization_level": "Q4_0"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let response: ShowModelResponse = serde_json::from_value(json).unwrap();
|
||||||
|
assert_eq!(response.license, Some("MIT".to_string()));
|
||||||
|
assert_eq!(response.modelfile, Some("FROM llama3".to_string()));
|
||||||
|
assert_eq!(response.parameters, Some("temperature 0.7".to_string()));
|
||||||
|
assert_eq!(response.template, Some("Please answer:".to_string()));
|
||||||
|
assert_eq!(response.system, Some("You are helpful".to_string()));
|
||||||
|
|
||||||
|
let details = response.details.unwrap();
|
||||||
|
assert_eq!(details.format, "gguf");
|
||||||
|
assert_eq!(details.family, "llama");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user