zai_rs/knowledge/
create.rs

1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use validator::Validate;
3
4use crate::client::http::HttpClient;
5
6/// Embedding model id enum mapped to integer ids
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum EmbeddingId {
9    /// 3: Embedding-2
10    Embedding2,
11    /// 11: Embedding-3-new
12    Embedding3New,
13}
14
15impl EmbeddingId {
16    pub fn as_i64(&self) -> i64 {
17        match self {
18            EmbeddingId::Embedding2 => 3,
19            EmbeddingId::Embedding3New => 11,
20        }
21    }
22}
23
24impl Serialize for EmbeddingId {
25    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
26        serializer.serialize_i64(self.as_i64())
27    }
28}
29
30impl<'de> Deserialize<'de> for EmbeddingId {
31    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
32        let v = i64::deserialize(deserializer)?;
33        match v {
34            3 => Ok(EmbeddingId::Embedding2),
35            11 => Ok(EmbeddingId::Embedding3New),
36            other => Err(serde::de::Error::custom(format!(
37                "unsupported embedding_id: {} (expected 3 or 11)",
38                other
39            ))),
40        }
41    }
42}
43
44/// Background color enum
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46#[serde(rename_all = "lowercase")]
47pub enum BackgroundColor {
48    Blue,
49    Red,
50    Orange,
51    Purple,
52    Sky,
53    Green,
54    Yellow,
55}
56
57/// Knowledge icon enum
58#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
59#[serde(rename_all = "lowercase")]
60pub enum KnowledgeIcon {
61    Question,
62    Book,
63    Seal,
64    Wrench,
65    Tag,
66    Horn,
67    House,
68}
69
70/// Request body for creating a knowledge base
71#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
72pub struct CreateKnowledgeBody {
73    /// Embedding model id (3 or 11)
74    pub embedding_id: EmbeddingId,
75    /// Knowledge base name
76    #[validate(length(min = 1))]
77    pub name: String,
78    /// Knowledge base description (optional)
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub description: Option<String>,
81    /// Background color (optional; default blue on server)
82    #[serde(skip_serializing_if = "Option::is_none")]
83    pub background: Option<BackgroundColor>,
84    /// Icon name (optional; default question on server)
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub icon: Option<KnowledgeIcon>,
87}
88
89/// Create knowledge request (POST /llm-application/open/knowledge)
90pub struct CreateKnowledgeRequest {
91    /// Bearer key
92    pub key: String,
93    url: String,
94    body: CreateKnowledgeBody,
95}
96
97impl CreateKnowledgeRequest {
98    /// Build a create request with required fields
99    pub fn new(key: String, embedding_id: EmbeddingId, name: impl Into<String>) -> Self {
100        let url = "https://open.bigmodel.cn/api/llm-application/open/knowledge".to_string();
101        let body = CreateKnowledgeBody {
102            embedding_id,
103            name: name.into(),
104            description: None,
105            background: None,
106            icon: None,
107        };
108        Self { key, url, body }
109    }
110
111    /// Optional fields setters
112    pub fn with_description(mut self, desc: impl Into<String>) -> Self {
113        self.body.description = Some(desc.into());
114        self
115    }
116    pub fn with_background(mut self, bg: BackgroundColor) -> Self {
117        self.body.background = Some(bg);
118        self
119    }
120    pub fn with_icon(mut self, icon: KnowledgeIcon) -> Self {
121        self.body.icon = Some(icon);
122        self
123    }
124
125    /// Validate and send, returning typed response
126    pub async fn send(&self) -> anyhow::Result<CreateKnowledgeResponse> {
127        self.body.validate()?;
128        let resp: reqwest::Response = self.post().await?;
129        let parsed = resp.json::<CreateKnowledgeResponse>().await?;
130        Ok(parsed)
131    }
132}
133
134impl HttpClient for CreateKnowledgeRequest {
135    type Body = CreateKnowledgeBody;
136    type ApiUrl = String;
137    type ApiKey = String;
138
139    fn api_url(&self) -> &Self::ApiUrl {
140        &self.url
141    }
142    fn api_key(&self) -> &Self::ApiKey {
143        &self.key
144    }
145    fn body(&self) -> &Self::Body {
146        &self.body
147    }
148}
149
150/// Response of knowledge creation
151#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
152pub struct CreateKnowledgeResponseData {
153    /// Newly created id
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub id: Option<String>,
156}
157
158#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
159pub struct CreateKnowledgeResponse {
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub data: Option<CreateKnowledgeResponseData>,
162    #[serde(skip_serializing_if = "Option::is_none")]
163    pub code: Option<i64>,
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub message: Option<String>,
166    #[serde(skip_serializing_if = "Option::is_none")]
167    pub timestamp: Option<u64>,
168}