Skip to main content

frink_api/
lora.rs

1//! Wire shapes for `GET /lora-adapters`, `POST /lora-adapters` and the
2//! per-request `lora` field, llama.cpp's spellings.
3//!
4//! The list `GET` returns is `server_task_result_get_lora::to_json`
5//! (`tools/server/server-task.cpp:1608-1626`) minus the aLoRA fields,
6//! which frink refuses to load. `POST` takes the same `[{id, scale}]`
7//! array `parse_lora_request` reads (`server-common.cpp:131-142`) and
8//! answers `{"success": true}` (`server-task.cpp:1632-1634`). The
9//! per-request `lora` field on a completion is that array again, and
10//! it means what `construct_lora_list` makes it mean
11//! (`server-context.cpp:1721-1732`): every adapter named gets its
12//! scale, every adapter NOT named gets `0` for that request.
13
14use serde::{Deserialize, Serialize};
15
16/// One loaded adapter, as `GET /lora-adapters` lists it.
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18pub struct LoraAdapterInfo {
19    /// Its index in the load order: what `POST` and the per-request
20    /// `lora` field address it by.
21    pub id: usize,
22    pub path: String,
23    /// The scale currently applied to every request that does not
24    /// override it.
25    pub scale: f32,
26    /// `adapter.lora.task_name` from the file, or empty.
27    pub task_name: String,
28    /// `adapter.lora.prompt_prefix` from the file, or empty.
29    pub prompt_prefix: String,
30}
31
32/// One entry of the `[{id, scale}]` array `POST /lora-adapters` and a
33/// request's `lora` field carry.
34///
35/// `scale` defaults to `0` when absent, as `json_value(entry, "scale",
36/// 0.0f)` reads it upstream; an entry without an `id` is refused here
37/// where upstream reads `-1` and silently matches nothing.
38#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
39pub struct LoraScaleRequest {
40    pub id: usize,
41    #[serde(default)]
42    pub scale: f32,
43}
44
45/// The answer to `POST /lora-adapters`.
46#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
47pub struct LoraApplyResponse {
48    pub success: bool,
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn a_scale_request_without_a_scale_reads_zero() {
57        let r: LoraScaleRequest = serde_json::from_str(r#"{"id": 1}"#).unwrap();
58        assert_eq!(r, LoraScaleRequest { id: 1, scale: 0.0 });
59        assert!(serde_json::from_str::<LoraScaleRequest>(r#"{"scale": 1.0}"#).is_err());
60    }
61}