zai_rs/knowledge/
update.rs1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use validator::Validate;
5
6use super::create::{BackgroundColor, EmbeddingId, KnowledgeIcon};
7use crate::client::http::HttpClient;
8
9#[derive(Debug, Clone, Default, Serialize, Deserialize, Validate)]
11pub struct UpdateKnowledgeBody {
12 #[serde(skip_serializing_if = "Option::is_none")]
14 pub embedding_id: Option<EmbeddingId>,
15 #[serde(skip_serializing_if = "Option::is_none")]
17 #[validate(length(min = 1))]
18 pub name: Option<String>,
19 #[serde(skip_serializing_if = "Option::is_none")]
21 pub description: Option<String>,
22 #[serde(skip_serializing_if = "Option::is_none")]
24 pub background: Option<BackgroundColor>,
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pub icon: Option<KnowledgeIcon>,
28 #[serde(skip_serializing_if = "Option::is_none")]
30 pub callback_url: Option<String>,
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub callback_header: Option<HashMap<String, String>>,
34}
35
36impl UpdateKnowledgeBody {
37 fn is_empty(&self) -> bool {
39 self.embedding_id.is_none()
40 && self.name.is_none()
41 && self.description.is_none()
42 && self.background.is_none()
43 && self.icon.is_none()
44 && self.callback_url.is_none()
45 && self.callback_header.is_none()
46 }
47}
48
49pub struct KnowledgeUpdateRequest {
51 pub key: String,
53 url: String,
54 body: UpdateKnowledgeBody,
55}
56
57impl KnowledgeUpdateRequest {
58 pub fn new(key: String, id: impl AsRef<str>) -> Self {
60 let url = format!(
61 "https://open.bigmodel.cn/api/llm-application/open/knowledge/{}",
62 id.as_ref()
63 );
64 Self {
65 key,
66 url,
67 body: UpdateKnowledgeBody::default(),
68 }
69 }
70
71 pub fn with_embedding_id(mut self, id: EmbeddingId) -> Self {
73 self.body.embedding_id = Some(id);
74 self
75 }
76 pub fn with_name(mut self, name: impl Into<String>) -> Self {
77 self.body.name = Some(name.into());
78 self
79 }
80 pub fn with_description(mut self, desc: impl Into<String>) -> Self {
81 self.body.description = Some(desc.into());
82 self
83 }
84 pub fn with_background(mut self, bg: BackgroundColor) -> Self {
85 self.body.background = Some(bg);
86 self
87 }
88 pub fn with_icon(mut self, icon: KnowledgeIcon) -> Self {
89 self.body.icon = Some(icon);
90 self
91 }
92 pub fn with_callback_url(mut self, url: impl Into<String>) -> Self {
93 self.body.callback_url = Some(url.into());
94 self
95 }
96 pub fn with_callback_header(mut self, headers: HashMap<String, String>) -> Self {
97 self.body.callback_header = Some(headers);
98 self
99 }
100
101 pub async fn send(&self) -> anyhow::Result<KnowledgeUpdateResponse> {
103 if self.body.is_empty() {
104 return Err(anyhow::anyhow!(
105 "update body is empty; set at least one field"
106 ));
107 }
108 self.body.validate()?;
109 let resp = self.put().await?;
110 let parsed = resp.json::<KnowledgeUpdateResponse>().await?;
111 Ok(parsed)
112 }
113
114 pub fn put(
116 &self,
117 ) -> impl std::future::Future<Output = anyhow::Result<reqwest::Response>> + Send {
118 let url = self.url.clone();
119 let key = self.key.clone();
120 let body = self.body.clone();
121 async move {
122 let body_str = serde_json::to_string(&body)?;
123 let resp = reqwest::Client::new()
124 .put(url)
125 .bearer_auth(key)
126 .header("Content-Type", "application/json")
127 .body(body_str)
128 .send()
129 .await?;
130 let status = resp.status();
131 if status.is_success() {
132 return Ok(resp);
133 }
134 let text = resp.text().await.unwrap_or_default();
136 #[derive(serde::Deserialize)]
137 struct ErrEnv {
138 error: ErrObj,
139 }
140 #[derive(serde::Deserialize)]
141 struct ErrObj {
142 code: serde_json::Value,
143 message: String,
144 }
145 if let Ok(parsed) = serde_json::from_str::<ErrEnv>(&text) {
146 return Err(anyhow::anyhow!(
147 "HTTP {} {} | code={} | message={}",
148 status.as_u16(),
149 status.canonical_reason().unwrap_or(""),
150 parsed.error.code,
151 parsed.error.message
152 ));
153 }
154 Err(anyhow::anyhow!(
155 "HTTP {} {} | body={}",
156 status.as_u16(),
157 status.canonical_reason().unwrap_or(""),
158 text
159 ))
160 }
161 }
162}
163
164impl HttpClient for KnowledgeUpdateRequest {
165 type Body = UpdateKnowledgeBody;
166 type ApiUrl = String;
167 type ApiKey = String;
168
169 fn api_url(&self) -> &Self::ApiUrl {
170 &self.url
171 }
172 fn api_key(&self) -> &Self::ApiKey {
173 &self.key
174 }
175 fn body(&self) -> &Self::Body {
176 &self.body
177 }
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
182pub struct KnowledgeUpdateResponse {
183 #[serde(skip_serializing_if = "Option::is_none")]
184 pub code: Option<i64>,
185 #[serde(skip_serializing_if = "Option::is_none")]
186 pub message: Option<String>,
187 #[serde(skip_serializing_if = "Option::is_none")]
188 pub timestamp: Option<u64>,
189}