1 line
54 KiB
JSON
1 line
54 KiB
JSON
{"repo": "acscoder/deepseek-api-client", "files": {"src/lib.rs": {"30e7850643c0e51e7dd399eff71d20f672ad130e": {"t": 1785745835.2830276, "n": 17702, "h": "0dfd27d32152de28", "c": "use optional_default::OptionalDefault;\nuse reqwest;\nuse serde::{Deserialize, Serialize};\nuse std::collections::HashMap;\nuse std::fmt::format;\nuse std::future::Future;\nuse std::pin::Pin;\nuse std::{boxed::Box, rc::Rc};\n\nuse anyhow::{anyhow, Result};\nuse serde_json::{json, Value};\npub static CHAT_COMPLETION_API_URL: &str = \"https://api.deepseek.com/chat/completions\";\npub static DEEPSEEK_MODEL_CHAT: &str = \"deepseek-chat\";\npub static DEEPSEEK_MODEL_CODER: &str = \"deepseek-coder\";\n\n#[derive(Serialize, Deserialize, Clone, Debug)]\npub struct Message {\n pub role: String,\n pub content: String,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct FunctionalCallObject {\n r#type: String,\n function: FunctionalCallObjectSingle,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct FunctionalCallObjectSingle {\n name: String,\n description: String,\n parameters: Value,\n}\nimpl FunctionalCallObject {\n fn new(fname: &str, fdesc: &str, parameters: Value) -> Self {\n Self {\n r#type: \"function\".to_owned(),\n function: FunctionalCallObjectSingle {\n name: fname.to_owned(),\n description: fdesc.to_owned(),\n parameters,\n },\n }\n }\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct LogprobsObject {\n token: String,\n logprob: f32,\n #[optional(default = None)]\n bytes: Option<Vec<i32>>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct TopLogprobsObject {\n token: String,\n logprob: f32,\n #[optional(default = None)]\n bytes: Option<Vec<i32>>,\n top_logprobs: Vec<LogprobsObject>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct LogprobsContent {\n #[optional(default = None)]\n content: Option<Vec<TopLogprobsObject>>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Clone, Debug)]\npub struct ChoiceObjectMessage {\n #[optional(default = \"assistant\".to_owned())]\n pub role: String,\n pub content: Option<String>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChoiceObject {\n #[optional(default = None)]\n finish_reason: Option<String>,\n index: i32,\n #[optional(default = None)]\n logprobs: Option<LogprobsContent>,\n message: ChoiceObjectMessage,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\nstruct Usage {\n completion_tokens: i32,\n prompt_tokens: i32,\n total_tokens: i32,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\nstruct ResponseFormatType {\n r#type: String,\n}\n#[derive(Serialize, OptionalDefault, Debug)]\npub struct RequestChat {\n messages: Vec<Message>,\n model: String,\n #[optional(default = 0.0)]\n frequency_penalty: f32,\n #[optional(default = 2048)]\n max_tokens: usize,\n #[optional(default = 0.0)]\n presence_penalty: f32,\n #[optional(default = ResponseFormatType{r#type: \"text\".to_owned()} )]\n response_format: ResponseFormatType,\n #[optional(default = None)]\n stop: Option<String>,\n #[optional(default = false)]\n stream: bool,\n #[optional(default = None)]\n stream_options: Option<String>,\n #[optional(default = 1.0)]\n temperature: f32,\n #[optional(default = 1.0)]\n top_p: f32,\n #[optional(default = None)]\n tools: Option<Vec<FunctionalCallObject>>,\n #[optional(default = \"none\".to_owned())]\n tool_choice: String,\n #[optional(default = false)]\n logprobs: bool,\n #[optional(default = None)]\n top_logprobs: Option<i32>,\n}\n\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChatResponses {\n id: String,\n object: String,\n created: i64,\n model: String,\n system_fingerprint: String,\n choices: Vec<ChoiceObject>,\n #[optional(default = None)]\n usage: Option<Usage>,\n}\n\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChatResponsesStream {\n id: String,\n object: String,\n created: i64,\n model: String,\n system_fingerprint: String,\n choices: Vec<ChoiceObjectChunk>,\n #[optional(default = None)]\n usage: Option<Usage>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChoiceObjectChunk {\n #[optional(default = None)]\n finish_reason: Option<String>,\n index: i32,\n #[optional(default = None)]\n logprobs: Option<LogprobsContent>,\n delta: Value,\n}\npub fn chat_DeepSeek_LLM_stream(\n mut params: RequestChat,\n api_key: &str,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let api_key_rc = Rc::new(api_key.to_owned());\n let c = move |messages: Vec<Message>| -> Pin<Box<dyn Future<Output = Result<reqwest::Response,reqwest::Error> >>> {\n params.messages = messages;\n let params_json = serde_json::to_string(¶ms).unwrap();\n let client = reqwest::Client::new();\n let api_key = api_key_rc.clone();\n let req = client.post(CHAT_COMPLETION_API_URL)\n .header(\"Content-Type\", \"application/json\")\n .header(\"Authorization\", format!(\"Bearer {}\", api_key.to_string()))\n .body(params_json)\n .send();\n Box::pin(req) \n };\n Box::new(c)\n}\npub fn chat_deepSeek_LLM_synchornous(\n mut params: RequestChat,\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let api_key_rc = Rc::new(api_key.to_owned());\n let c = move |messages: Vec<Message>| -> Result<ChatResponses> {\n params.messages = messages;\n let params_json = serde_json::to_string(¶ms).unwrap();\n let api_key = api_key_rc.clone();\n let client = reqwest::blocking::Client::new();\n let req = client\n .post(CHAT_COMPLETION_API_URL)\n .header(\"Content-Type\", \"application/json\")\n .header(\"Authorization\", format!(\"Bearer {}\", api_key.to_string()))\n .body(params_json)\n .send();\n\n if let Ok(req) = req {\n let s = req.text().unwrap();\n let data = serde_json::from_str(&s);\n if let Ok(data) = data {\n return Ok(data);\n }\n return Err(anyhow!(\"Parse error {:?}\", data));\n }\n Err(anyhow!(\"Can't connect to API\"))\n };\n Box::new(c)\n}\n\npub fn chat_DeepSeek_LLM(\n mut params: RequestChat,\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let api_key_rc = Rc::new(api_key.to_owned());\n let f = move |messages: Vec<Message>| -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>> {\n params.messages = messages;\n let is_stream = params.stream;\n let params_json = serde_json::to_string(¶ms).unwrap();\n\n let api_key = api_key_rc.clone();\n let c = async move {\n let client = reqwest::Client::new();\n let req = curl_post_request(\n &client,\n CHAT_COMPLETION_API_URL,\n params_json,\n api_key.to_string().as_str(),\n );\n if let Ok(req) = req {\n let res = client.execute(req);\n\n if let Ok(r) = res.await {\n let s = r.text().await;\n\n if let Ok(s) = s {\n if is_stream {\n let data = string_to_ChatResponses(&s);\n Ok(data)\n } else {\n let data = serde_json::from_str(&s);\n if data.is_ok() {\n let d: ChatResponses = data.unwrap();\n Ok(d)\n } else {\n Err(anyhow!(\"Parse error {:?}\", data))\n }\n }\n } else {\n Err(anyhow!(\"Result response {:?}\", s))\n }\n } else {\n Err(anyhow!(\"Can't connect to API\"))\n }\n } else {\n Err(anyhow!(\"Request {:?}\", req))\n }\n };\n Box::pin(c)\n };\n Box::new(f)\n}\npub fn get_response_text(d: &ChatResponses, ind: usize) -> Option<String> {\n let response_index = d.choices.get(ind);\n if let Some(response_index) = response_index {\n response_index.message.content.clone()\n } else {\n None\n }\n}\npub fn string_to_ChatResponses(s: &str) -> ChatResponses {\n let st = s.split(\"\\n\\n\");\n let fold_init: ChatResponses = ChatResponses!( id: \"\".to_owned(),\n object: \"\".to_owned(),\n created: 0,\n model: \"\".to_owned(),\n system_fingerprint: \"\".to_owned(),\n choices: vec![]);\n\n let data: ChatResponses = st.filter_map(|item|{\n let sj = item.strip_prefix(\"data: \").unwrap_or(\"\"); \n let dt = serde_json::from_str::<ChatResponsesStream>(sj).ok();\n dt\n }).fold(fold_init,|mut acc,item|{\n if acc.choices.is_empty(){\n acc.id = item.id;\n acc.object = item.object;\n acc.created = item.created;\n acc.model = item.model;\n acc.system_fingerprint = item.system_fingerprint;\n let choice = item.choices.get(0).unwrap().delta.as_object().unwrap().get(\"content\").unwrap().as_str().unwrap_or(\"\").to_owned();\n acc.choices = vec![ChoiceObject!(finish_reason: None,index: item.choices.get(0).unwrap().index,logprobs: None,message: ChoiceObjectMessage!(content: Some(choice) ))];\n }else{\n let choice = item.choices.get(0).unwrap().delta.as_object().unwrap().get(\"content\").unwrap().as_str().unwrap_or(\"\").to_owned();\n let acc_choices = acc.choices[0].message.content.clone().unwrap();\n acc.choices[0].message.content = Some(acc_choices+&choice);\n } \n acc\n });\n\n data\n}\nfn curl_post_request(\n client: &reqwest::Client,\n url: &str,\n params: String,\n api_key: &str,\n) -> Result<reqwest::Request, reqwest::Error> {\n let req = client\n .post(url)\n .header(\"Content-Type\", \"application/json\")\n .header(\"Authorization\", format!(\"Bearer {}\", api_key))\n .body(params)\n .build();\n req\n}\n\npub fn chat_completion(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CHAT.to_owned(),\n messages: vec![]\n };\n chat_DeepSeek_LLM(params, api_key)\n}\npub fn code_completion(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n stream:true,\n messages: vec![]\n };\n chat_DeepSeek_LLM(params, api_key)\n}\npub fn llm_function_call(\n api_key: &str,\n tools: Vec<FunctionalCallObject>,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n messages: vec![],\n tools:Some(tools)\n };\n chat_DeepSeek_LLM(params, api_key)\n}\npub fn chat_completion_stream(\n api_key: &str,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CHAT.to_owned(),\n stream:true,\n messages: vec![]\n };\n chat_DeepSeek_LLM_stream(params, api_key)\n}\npub fn code_completion_stream(\n api_key: &str,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n stream:true,\n messages: vec![]\n };\n chat_DeepSeek_LLM_stream(params, api_key)\n}\npub fn llm_function_call_stream(\n api_key: &str,\n tools: Vec<FunctionalCallObject>,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n stream:true,\n messages: vec![],\n tools:Some(tools)\n };\n chat_DeepSeek_LLM_stream(params, api_key)\n}\npub fn chat_completion_sync(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CHAT.to_owned(),\n messages: vec![]\n };\n chat_deepSeek_LLM_synchornous(params, api_key)\n}\npub fn code_completion_sync(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n messages: vec![]\n };\n chat_deepSeek_LLM_synchornous(params, api_key)\n}\npub fn llm_function_call_sync(\n api_key: &str,\n tools: Vec<FunctionalCallObject>,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n messages: vec![],\n tools:Some(tools)\n };\n chat_deepSeek_LLM_synchornous(params, api_key)\n}\n#[cfg(test)]\nmod tests {\n use super::*;\n use futures_util::StreamExt;\n use tokio::runtime::Runtime;\n // replace by your API key\n pub static DEEPSEEK_API_KEY: &str = \"sk-.......................\";\n #[test]\n fn synchornous_completion_test() {\n \n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"Write Hello world in rust\".to_owned(),\n },\n ];\n let mut llm = chat_completion_sync(DEEPSEEK_API_KEY);\n let res = llm(messages);\n let res_text = get_response_text(&res.unwrap(), 0);\n dbg!(res_text);\n }\n #[test]\n fn stream_completion_test() {\n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"Write Hello world in rust\".to_owned(),\n },\n ];\n\n let mut llm = chat_completion_stream(DEEPSEEK_API_KEY);\n let rt = Runtime::new().unwrap();\n\n let dt = llm(messages);\n let _ = rt.block_on(async {\n let res = dt.await.unwrap();\n let mut stream = res.bytes_stream();\n while let Some(item) = stream.next().await {\n let item = item.unwrap();\n let s = match std::str::from_utf8(&item) {\n Ok(v) => v,\n Err(e) => panic!(\"Invalid UTF-8 sequence: {}\", e),\n };\n let data = string_to_ChatResponses(s);\n let res = get_response_text(&data, 0).unwrap_or(\"\".to_owned());\n println!(\"{}\", res);\n }\n });\n }\n #[test]\n fn chat_completion_test() {\n let rt = Runtime::new().unwrap();\n let mut codeLLM = code_completion(DEEPSEEK_API_KEY);\n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"Write Hello world in rust\".to_owned(),\n },\n ];\n let res = codeLLM(messages);\n let r = rt.block_on(async { get_response_text(&res.await.unwrap(), 0) });\n dbg!(&r);\n assert!(r.is_some());\n }\n #[test]\n fn function_call_test() {\n let rt = Runtime::new().unwrap();\n\n let tparam1 = json!({\n \"type\": \"object\",\n \"required\": [\"location\"],\n \"properties\": {\n \"location\": {\n \"type\": \"string\",\n \"description\": \"The city and state, e.g. San Francisco, CA\"\n }\n }\n });\n\n let t1 = FunctionalCallObject::new(\n \"get_weather\",\n \"Get weather of an location, the user shoud supply a location first\",\n tparam1,\n );\n\n let tools = vec![t1];\n let mut codeLLM = llm_function_call(DEEPSEEK_API_KEY, tools);\n\n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant,your should reply in json format\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"How's the weather in Hangzhou?\".to_owned(),\n },\n ];\n let res = codeLLM(messages);\n let r = rt.block_on(async {\n let d = res.await.unwrap();\n dbg!(&d);\n get_response_text(&d, 0)\n });\n dbg!(&r);\n assert!(r.is_some());\n }\n}\n"}, "6273eb05ade5006d6be1096852886ff90fd8e441": {"t": 1785757034.6735232, "n": 17702, "h": "0dfd27d32152de28", "c": "use optional_default::OptionalDefault;\nuse reqwest;\nuse serde::{Deserialize, Serialize};\nuse std::collections::HashMap;\nuse std::fmt::format;\nuse std::future::Future;\nuse std::pin::Pin;\nuse std::{boxed::Box, rc::Rc};\n\nuse anyhow::{anyhow, Result};\nuse serde_json::{json, Value};\npub static CHAT_COMPLETION_API_URL: &str = \"https://api.deepseek.com/chat/completions\";\npub static DEEPSEEK_MODEL_CHAT: &str = \"deepseek-chat\";\npub static DEEPSEEK_MODEL_CODER: &str = \"deepseek-coder\";\n\n#[derive(Serialize, Deserialize, Clone, Debug)]\npub struct Message {\n pub role: String,\n pub content: String,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct FunctionalCallObject {\n r#type: String,\n function: FunctionalCallObjectSingle,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct FunctionalCallObjectSingle {\n name: String,\n description: String,\n parameters: Value,\n}\nimpl FunctionalCallObject {\n fn new(fname: &str, fdesc: &str, parameters: Value) -> Self {\n Self {\n r#type: \"function\".to_owned(),\n function: FunctionalCallObjectSingle {\n name: fname.to_owned(),\n description: fdesc.to_owned(),\n parameters,\n },\n }\n }\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct LogprobsObject {\n token: String,\n logprob: f32,\n #[optional(default = None)]\n bytes: Option<Vec<i32>>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct TopLogprobsObject {\n token: String,\n logprob: f32,\n #[optional(default = None)]\n bytes: Option<Vec<i32>>,\n top_logprobs: Vec<LogprobsObject>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct LogprobsContent {\n #[optional(default = None)]\n content: Option<Vec<TopLogprobsObject>>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Clone, Debug)]\npub struct ChoiceObjectMessage {\n #[optional(default = \"assistant\".to_owned())]\n pub role: String,\n pub content: Option<String>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChoiceObject {\n #[optional(default = None)]\n finish_reason: Option<String>,\n index: i32,\n #[optional(default = None)]\n logprobs: Option<LogprobsContent>,\n message: ChoiceObjectMessage,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\nstruct Usage {\n completion_tokens: i32,\n prompt_tokens: i32,\n total_tokens: i32,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\nstruct ResponseFormatType {\n r#type: String,\n}\n#[derive(Serialize, OptionalDefault, Debug)]\npub struct RequestChat {\n messages: Vec<Message>,\n model: String,\n #[optional(default = 0.0)]\n frequency_penalty: f32,\n #[optional(default = 2048)]\n max_tokens: usize,\n #[optional(default = 0.0)]\n presence_penalty: f32,\n #[optional(default = ResponseFormatType{r#type: \"text\".to_owned()} )]\n response_format: ResponseFormatType,\n #[optional(default = None)]\n stop: Option<String>,\n #[optional(default = false)]\n stream: bool,\n #[optional(default = None)]\n stream_options: Option<String>,\n #[optional(default = 1.0)]\n temperature: f32,\n #[optional(default = 1.0)]\n top_p: f32,\n #[optional(default = None)]\n tools: Option<Vec<FunctionalCallObject>>,\n #[optional(default = \"none\".to_owned())]\n tool_choice: String,\n #[optional(default = false)]\n logprobs: bool,\n #[optional(default = None)]\n top_logprobs: Option<i32>,\n}\n\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChatResponses {\n id: String,\n object: String,\n created: i64,\n model: String,\n system_fingerprint: String,\n choices: Vec<ChoiceObject>,\n #[optional(default = None)]\n usage: Option<Usage>,\n}\n\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChatResponsesStream {\n id: String,\n object: String,\n created: i64,\n model: String,\n system_fingerprint: String,\n choices: Vec<ChoiceObjectChunk>,\n #[optional(default = None)]\n usage: Option<Usage>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChoiceObjectChunk {\n #[optional(default = None)]\n finish_reason: Option<String>,\n index: i32,\n #[optional(default = None)]\n logprobs: Option<LogprobsContent>,\n delta: Value,\n}\npub fn chat_DeepSeek_LLM_stream(\n mut params: RequestChat,\n api_key: &str,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let api_key_rc = Rc::new(api_key.to_owned());\n let c = move |messages: Vec<Message>| -> Pin<Box<dyn Future<Output = Result<reqwest::Response,reqwest::Error> >>> {\n params.messages = messages;\n let params_json = serde_json::to_string(¶ms).unwrap();\n let client = reqwest::Client::new();\n let api_key = api_key_rc.clone();\n let req = client.post(CHAT_COMPLETION_API_URL)\n .header(\"Content-Type\", \"application/json\")\n .header(\"Authorization\", format!(\"Bearer {}\", api_key.to_string()))\n .body(params_json)\n .send();\n Box::pin(req) \n };\n Box::new(c)\n}\npub fn chat_deepSeek_LLM_synchornous(\n mut params: RequestChat,\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let api_key_rc = Rc::new(api_key.to_owned());\n let c = move |messages: Vec<Message>| -> Result<ChatResponses> {\n params.messages = messages;\n let params_json = serde_json::to_string(¶ms).unwrap();\n let api_key = api_key_rc.clone();\n let client = reqwest::blocking::Client::new();\n let req = client\n .post(CHAT_COMPLETION_API_URL)\n .header(\"Content-Type\", \"application/json\")\n .header(\"Authorization\", format!(\"Bearer {}\", api_key.to_string()))\n .body(params_json)\n .send();\n\n if let Ok(req) = req {\n let s = req.text().unwrap();\n let data = serde_json::from_str(&s);\n if let Ok(data) = data {\n return Ok(data);\n }\n return Err(anyhow!(\"Parse error {:?}\", data));\n }\n Err(anyhow!(\"Can't connect to API\"))\n };\n Box::new(c)\n}\n\npub fn chat_DeepSeek_LLM(\n mut params: RequestChat,\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let api_key_rc = Rc::new(api_key.to_owned());\n let f = move |messages: Vec<Message>| -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>> {\n params.messages = messages;\n let is_stream = params.stream;\n let params_json = serde_json::to_string(¶ms).unwrap();\n\n let api_key = api_key_rc.clone();\n let c = async move {\n let client = reqwest::Client::new();\n let req = curl_post_request(\n &client,\n CHAT_COMPLETION_API_URL,\n params_json,\n api_key.to_string().as_str(),\n );\n if let Ok(req) = req {\n let res = client.execute(req);\n\n if let Ok(r) = res.await {\n let s = r.text().await;\n\n if let Ok(s) = s {\n if is_stream {\n let data = string_to_ChatResponses(&s);\n Ok(data)\n } else {\n let data = serde_json::from_str(&s);\n if data.is_ok() {\n let d: ChatResponses = data.unwrap();\n Ok(d)\n } else {\n Err(anyhow!(\"Parse error {:?}\", data))\n }\n }\n } else {\n Err(anyhow!(\"Result response {:?}\", s))\n }\n } else {\n Err(anyhow!(\"Can't connect to API\"))\n }\n } else {\n Err(anyhow!(\"Request {:?}\", req))\n }\n };\n Box::pin(c)\n };\n Box::new(f)\n}\npub fn get_response_text(d: &ChatResponses, ind: usize) -> Option<String> {\n let response_index = d.choices.get(ind);\n if let Some(response_index) = response_index {\n response_index.message.content.clone()\n } else {\n None\n }\n}\npub fn string_to_ChatResponses(s: &str) -> ChatResponses {\n let st = s.split(\"\\n\\n\");\n let fold_init: ChatResponses = ChatResponses!( id: \"\".to_owned(),\n object: \"\".to_owned(),\n created: 0,\n model: \"\".to_owned(),\n system_fingerprint: \"\".to_owned(),\n choices: vec![]);\n\n let data: ChatResponses = st.filter_map(|item|{\n let sj = item.strip_prefix(\"data: \").unwrap_or(\"\"); \n let dt = serde_json::from_str::<ChatResponsesStream>(sj).ok();\n dt\n }).fold(fold_init,|mut acc,item|{\n if acc.choices.is_empty(){\n acc.id = item.id;\n acc.object = item.object;\n acc.created = item.created;\n acc.model = item.model;\n acc.system_fingerprint = item.system_fingerprint;\n let choice = item.choices.get(0).unwrap().delta.as_object().unwrap().get(\"content\").unwrap().as_str().unwrap_or(\"\").to_owned();\n acc.choices = vec![ChoiceObject!(finish_reason: None,index: item.choices.get(0).unwrap().index,logprobs: None,message: ChoiceObjectMessage!(content: Some(choice) ))];\n }else{\n let choice = item.choices.get(0).unwrap().delta.as_object().unwrap().get(\"content\").unwrap().as_str().unwrap_or(\"\").to_owned();\n let acc_choices = acc.choices[0].message.content.clone().unwrap();\n acc.choices[0].message.content = Some(acc_choices+&choice);\n } \n acc\n });\n\n data\n}\nfn curl_post_request(\n client: &reqwest::Client,\n url: &str,\n params: String,\n api_key: &str,\n) -> Result<reqwest::Request, reqwest::Error> {\n let req = client\n .post(url)\n .header(\"Content-Type\", \"application/json\")\n .header(\"Authorization\", format!(\"Bearer {}\", api_key))\n .body(params)\n .build();\n req\n}\n\npub fn chat_completion(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CHAT.to_owned(),\n messages: vec![]\n };\n chat_DeepSeek_LLM(params, api_key)\n}\npub fn code_completion(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n stream:true,\n messages: vec![]\n };\n chat_DeepSeek_LLM(params, api_key)\n}\npub fn llm_function_call(\n api_key: &str,\n tools: Vec<FunctionalCallObject>,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n messages: vec![],\n tools:Some(tools)\n };\n chat_DeepSeek_LLM(params, api_key)\n}\npub fn chat_completion_stream(\n api_key: &str,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CHAT.to_owned(),\n stream:true,\n messages: vec![]\n };\n chat_DeepSeek_LLM_stream(params, api_key)\n}\npub fn code_completion_stream(\n api_key: &str,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n stream:true,\n messages: vec![]\n };\n chat_DeepSeek_LLM_stream(params, api_key)\n}\npub fn llm_function_call_stream(\n api_key: &str,\n tools: Vec<FunctionalCallObject>,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n stream:true,\n messages: vec![],\n tools:Some(tools)\n };\n chat_DeepSeek_LLM_stream(params, api_key)\n}\npub fn chat_completion_sync(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CHAT.to_owned(),\n messages: vec![]\n };\n chat_deepSeek_LLM_synchornous(params, api_key)\n}\npub fn code_completion_sync(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n messages: vec![]\n };\n chat_deepSeek_LLM_synchornous(params, api_key)\n}\npub fn llm_function_call_sync(\n api_key: &str,\n tools: Vec<FunctionalCallObject>,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n messages: vec![],\n tools:Some(tools)\n };\n chat_deepSeek_LLM_synchornous(params, api_key)\n}\n#[cfg(test)]\nmod tests {\n use super::*;\n use futures_util::StreamExt;\n use tokio::runtime::Runtime;\n // replace by your API key\n pub static DEEPSEEK_API_KEY: &str = \"sk-.......................\";\n #[test]\n fn synchornous_completion_test() {\n \n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"Write Hello world in rust\".to_owned(),\n },\n ];\n let mut llm = chat_completion_sync(DEEPSEEK_API_KEY);\n let res = llm(messages);\n let res_text = get_response_text(&res.unwrap(), 0);\n dbg!(res_text);\n }\n #[test]\n fn stream_completion_test() {\n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"Write Hello world in rust\".to_owned(),\n },\n ];\n\n let mut llm = chat_completion_stream(DEEPSEEK_API_KEY);\n let rt = Runtime::new().unwrap();\n\n let dt = llm(messages);\n let _ = rt.block_on(async {\n let res = dt.await.unwrap();\n let mut stream = res.bytes_stream();\n while let Some(item) = stream.next().await {\n let item = item.unwrap();\n let s = match std::str::from_utf8(&item) {\n Ok(v) => v,\n Err(e) => panic!(\"Invalid UTF-8 sequence: {}\", e),\n };\n let data = string_to_ChatResponses(s);\n let res = get_response_text(&data, 0).unwrap_or(\"\".to_owned());\n println!(\"{}\", res);\n }\n });\n }\n #[test]\n fn chat_completion_test() {\n let rt = Runtime::new().unwrap();\n let mut codeLLM = code_completion(DEEPSEEK_API_KEY);\n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"Write Hello world in rust\".to_owned(),\n },\n ];\n let res = codeLLM(messages);\n let r = rt.block_on(async { get_response_text(&res.await.unwrap(), 0) });\n dbg!(&r);\n assert!(r.is_some());\n }\n #[test]\n fn function_call_test() {\n let rt = Runtime::new().unwrap();\n\n let tparam1 = json!({\n \"type\": \"object\",\n \"required\": [\"location\"],\n \"properties\": {\n \"location\": {\n \"type\": \"string\",\n \"description\": \"The city and state, e.g. San Francisco, CA\"\n }\n }\n });\n\n let t1 = FunctionalCallObject::new(\n \"get_weather\",\n \"Get weather of an location, the user shoud supply a location first\",\n tparam1,\n );\n\n let tools = vec![t1];\n let mut codeLLM = llm_function_call(DEEPSEEK_API_KEY, tools);\n\n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant,your should reply in json format\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"How's the weather in Hangzhou?\".to_owned(),\n },\n ];\n let res = codeLLM(messages);\n let r = rt.block_on(async {\n let d = res.await.unwrap();\n dbg!(&d);\n get_response_text(&d, 0)\n });\n dbg!(&r);\n assert!(r.is_some());\n }\n}\n"}, "ab09b597fe2f1b984959ef2e74fee719833cc64c": {"t": 1785757036.2981322, "n": 17698, "h": "64c3cc54ee944e36", "c": "use optional_default::OptionalDefault;\nuse reqwest;\nuse serde::{Deserialize, Serialize};\nuse std::collections::HashMap;\nuse std::fmt::format;\nuse std::future::Future;\nuse std::pin::Pin;\nuse std::{boxed::Box, rc::Rc};\n\nuse anyhow::{anyhow, Result};\nuse serde_json::{json, Value};\npub static CHAT_COMPLETION_API_URL: &str = \"https://api.deepseek.com/chat/completions\";\npub static DEEPSEEK_MODEL_CHAT: &str = \"deepseek-chat\";\npub static DEEPSEEK_MODEL_CODER: &str = \"deepseek-coder\";\n\n#[derive(Serialize, Deserialize, Clone, Debug)]\npub struct Message {\n pub role: String,\n pub content: String,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct FunctionalCallObject {\n r#type: String,\n function: FunctionalCallObjectSingle,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct FunctionalCallObjectSingle {\n name: String,\n description: String,\n parameters: Value,\n}\nimpl FunctionalCallObject {\n fn new(fname: &str, fdesc: &str, parameters: Value) -> Self {\n Self {\n r#type: \"function\".to_owned(),\n function: FunctionalCallObjectSingle {\n name: fname.to_owned(),\n description: fdesc.to_owned(),\n parameters,\n },\n }\n }\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct LogprobsObject {\n token: String,\n logprob: f32,\n #[optional(default = None)]\n bytes: Option<Vec<i32>>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct TopLogprobsObject {\n token: String,\n logprob: f32,\n #[optional(default = None)]\n bytes: Option<Vec<i32>>,\n top_logprobs: Vec<LogprobsObject>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct LogprobsContent {\n #[optional(default = None)]\n content: Option<Vec<TopLogprobsObject>>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Clone, Debug)]\npub struct ChoiceObjectMessage {\n #[optional(default = \"assistant\".to_owned())]\n pub role: String,\n pub content: Option<String>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChoiceObject {\n #[optional(default = None)]\n finish_reason: Option<String>,\n index: i32,\n #[optional(default = None)]\n logprobs: Option<LogprobsContent>,\n message: ChoiceObjectMessage,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\nstruct Usage {\n completion_tokens: i32,\n prompt_tokens: i32,\n total_tokens: i32,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\nstruct ResponseFormatType {\n r#type: String,\n}\n#[derive(Serialize, OptionalDefault, Debug)]\npub struct RequestChat {\n messages: Vec<Message>,\n model: String,\n #[optional(default = 0.0)]\n frequency_penalty: f32,\n #[optional(default = 2048)]\n max_tokens: usize,\n #[optional(default = 0.0)]\n presence_penalty: f32,\n #[optional(default = ResponseFormatType{r#type: \"text\".to_owned()} )]\n response_format: ResponseFormatType,\n #[optional(default = None)]\n stop: Option<String>,\n #[optional(default = false)]\n stream: bool,\n #[optional(default = None)]\n stream_options: Option<String>,\n #[optional(default = 1.0)]\n temperature: f32,\n #[optional(default = 1.0)]\n top_p: f32,\n #[optional(default = None)]\n tools: Option<Vec<FunctionalCallObject>>,\n #[optional(default = \"none\".to_owned())]\n tool_choice: String,\n #[optional(default = false)]\n logprobs: bool,\n #[optional(default = None)]\n top_logprobs: Option<i32>,\n}\n\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChatResponses {\n id: String,\n object: String,\n created: i64,\n model: String,\n system_fingerprint: String,\n choices: Vec<ChoiceObject>,\n #[optional(default = None)]\n usage: Option<Usage>,\n}\n\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChatResponsesStream {\n id: String,\n object: String,\n created: i64,\n model: String,\n system_fingerprint: String,\n choices: Vec<ChoiceObjectChunk>,\n #[optional(default = None)]\n usage: Option<Usage>,\n}\n#[derive(Serialize, Deserialize, OptionalDefault, Debug)]\npub struct ChoiceObjectChunk {\n #[optional(default = None)]\n finish_reason: Option<String>,\n index: i32,\n #[optional(default = None)]\n logprobs: Option<LogprobsContent>,\n delta: Value,\n}\npub fn chat_DeepSeek_LLM_stream(\n mut params: RequestChat,\n api_key: &str,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let api_key_rc = Rc::new(api_key.to_owned());\n let c = move |messages: Vec<Message>| -> Pin<Box<dyn Future<Output = Result<reqwest::Response,reqwest::Error> >>> {\n params.messages = messages;\n let params_json = serde_json::to_string(¶ms).unwrap();\n let client = reqwest::Client::new();\n let api_key = api_key_rc.clone();\n let req = client.post(CHAT_COMPLETION_API_URL)\n .header(\"Content-Type\", \"application/json\")\n .header(\"Authorization\", format!(\"Bearer {}\", api_key.to_string()))\n .body(params_json)\n .send();\n Box::pin(req) \n };\n Box::new(c)\n}\npub fn chat_deepSeek_LLM_synchornous(\n mut params: RequestChat,\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let api_key_rc = Rc::new(api_key.to_owned());\n let c = move |messages: Vec<Message>| -> Result<ChatResponses> {\n params.messages = messages;\n let params_json = serde_json::to_string(¶ms).unwrap();\n let api_key = api_key_rc.clone();\n let client = reqwest::blocking::Client::new();\n let req = client\n .post(CHAT_COMPLETION_API_URL)\n .header(\"Content-Type\", \"application/json\")\n .header(\"Authorization\", format!(\"Bearer {}\", api_key.to_string()))\n .body(params_json)\n .send();\n\n if let Ok(req) = req {\n let s = req.text().unwrap();\n let data = serde_json::from_str(&s);\n if let Ok(data) = data {\n return Ok(data);\n }\n return Err(anyhow!(\"Parse error {:?}\", data));\n }\n Err(anyhow!(\"Can't connect to API\"))\n };\n Box::new(c)\n}\n\npub fn chat_DeepSeek_LLM(\n mut params: RequestChat,\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let api_key_rc = Rc::new(api_key.to_owned());\n let f = move |messages: Vec<Message>| -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>> {\n params.messages = messages;\n let is_stream = params.stream;\n let params_json = serde_json::to_string(¶ms).unwrap();\n\n let api_key = api_key_rc.clone();\n let c = async move {\n let client = reqwest::Client::new();\n let req = curl_post_request(\n &client,\n CHAT_COMPLETION_API_URL,\n params_json,\n api_key.to_string().as_str(),\n );\n if let Ok(req) = req {\n let res = client.execute(req);\n\n if let Ok(r) = res.await {\n let s = r.text().await;\n\n if let Ok(s) = s {\n if is_stream {\n let data = string_to_ChatResponses(&s);\n Ok(data)\n } else {\n let data = serde_json::from_str(&s);\n if data.is_ok() {\n let d: ChatResponses = data.unwrap();\n Ok(d)\n } else {\n Err(anyhow!(\"Parse error {:?}\", data))\n }\n }\n } else {\n Err(anyhow!(\"Result response {:?}\", s))\n }\n } else {\n Err(anyhow!(\"Can't connect to API\"))\n }\n } else {\n Err(anyhow!(\"Request {:?}\", req))\n }\n };\n Box::pin(c)\n };\n Box::new(f)\n}\npub fn get_response_text(d: &ChatResponses, ind: usize) -> Option<String> {\n let response_index = d.choices.get(ind);\n if let Some(response_index) = response_index {\n response_index.message.content.clone()\n } else {\n None\n }\n}\nfn string_to_ChatResponses(s: &str) -> ChatResponses {\n let st = s.split(\"\\n\\n\");\n let fold_init: ChatResponses = ChatResponses!( id: \"\".to_owned(),\n object: \"\".to_owned(),\n created: 0,\n model: \"\".to_owned(),\n system_fingerprint: \"\".to_owned(),\n choices: vec![]);\n\n let data: ChatResponses = st.filter_map(|item|{\n let sj = item.strip_prefix(\"data: \").unwrap_or(\"\"); \n let dt = serde_json::from_str::<ChatResponsesStream>(sj).ok();\n dt\n }).fold(fold_init,|mut acc,item|{\n if acc.choices.is_empty(){\n acc.id = item.id;\n acc.object = item.object;\n acc.created = item.created;\n acc.model = item.model;\n acc.system_fingerprint = item.system_fingerprint;\n let choice = item.choices.get(0).unwrap().delta.as_object().unwrap().get(\"content\").unwrap().as_str().unwrap_or(\"\").to_owned();\n acc.choices = vec![ChoiceObject!(finish_reason: None,index: item.choices.get(0).unwrap().index,logprobs: None,message: ChoiceObjectMessage!(content: Some(choice) ))];\n }else{\n let choice = item.choices.get(0).unwrap().delta.as_object().unwrap().get(\"content\").unwrap().as_str().unwrap_or(\"\").to_owned();\n let acc_choices = acc.choices[0].message.content.clone().unwrap();\n acc.choices[0].message.content = Some(acc_choices+&choice);\n } \n acc\n });\n\n data\n}\nfn curl_post_request(\n client: &reqwest::Client,\n url: &str,\n params: String,\n api_key: &str,\n) -> Result<reqwest::Request, reqwest::Error> {\n let req = client\n .post(url)\n .header(\"Content-Type\", \"application/json\")\n .header(\"Authorization\", format!(\"Bearer {}\", api_key))\n .body(params)\n .build();\n req\n}\n\npub fn chat_completion(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CHAT.to_owned(),\n messages: vec![]\n };\n chat_DeepSeek_LLM(params, api_key)\n}\npub fn code_completion(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n stream:true,\n messages: vec![]\n };\n chat_DeepSeek_LLM(params, api_key)\n}\npub fn llm_function_call(\n api_key: &str,\n tools: Vec<FunctionalCallObject>,\n) -> Box<dyn FnMut(Vec<Message>) -> Pin<Box<dyn Future<Output = Result<ChatResponses>>>>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n messages: vec![],\n tools:Some(tools)\n };\n chat_DeepSeek_LLM(params, api_key)\n}\npub fn chat_completion_stream(\n api_key: &str,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CHAT.to_owned(),\n stream:true,\n messages: vec![]\n };\n chat_DeepSeek_LLM_stream(params, api_key)\n}\npub fn code_completion_stream(\n api_key: &str,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n stream:true,\n messages: vec![]\n };\n chat_DeepSeek_LLM_stream(params, api_key)\n}\npub fn llm_function_call_stream(\n api_key: &str,\n tools: Vec<FunctionalCallObject>,\n) -> Box<\n dyn FnMut(\n Vec<Message>,\n ) -> Pin<Box<dyn Future<Output = Result<reqwest::Response, reqwest::Error>>>>,\n> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n stream:true,\n messages: vec![],\n tools:Some(tools)\n };\n chat_DeepSeek_LLM_stream(params, api_key)\n}\npub fn chat_completion_sync(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CHAT.to_owned(),\n messages: vec![]\n };\n chat_deepSeek_LLM_synchornous(params, api_key)\n}\npub fn code_completion_sync(\n api_key: &str,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n messages: vec![]\n };\n chat_deepSeek_LLM_synchornous(params, api_key)\n}\npub fn llm_function_call_sync(\n api_key: &str,\n tools: Vec<FunctionalCallObject>,\n) -> Box<dyn FnMut(Vec<Message>) -> Result<ChatResponses>> {\n let params = RequestChat! {\n model: DEEPSEEK_MODEL_CODER.to_owned(),\n messages: vec![],\n tools:Some(tools)\n };\n chat_deepSeek_LLM_synchornous(params, api_key)\n}\n#[cfg(test)]\nmod tests {\n use super::*;\n use futures_util::StreamExt;\n use tokio::runtime::Runtime;\n // replace by your API key\n pub static DEEPSEEK_API_KEY: &str = \"sk-.......................\";\n #[test]\n fn synchornous_completion_test() {\n \n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"Write Hello world in rust\".to_owned(),\n },\n ];\n let mut llm = chat_completion_sync(DEEPSEEK_API_KEY);\n let res = llm(messages);\n let res_text = get_response_text(&res.unwrap(), 0);\n dbg!(res_text);\n }\n #[test]\n fn stream_completion_test() {\n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"Write Hello world in rust\".to_owned(),\n },\n ];\n\n let mut llm = chat_completion_stream(DEEPSEEK_API_KEY);\n let rt = Runtime::new().unwrap();\n\n let dt = llm(messages);\n let _ = rt.block_on(async {\n let res = dt.await.unwrap();\n let mut stream = res.bytes_stream();\n while let Some(item) = stream.next().await {\n let item = item.unwrap();\n let s = match std::str::from_utf8(&item) {\n Ok(v) => v,\n Err(e) => panic!(\"Invalid UTF-8 sequence: {}\", e),\n };\n let data = string_to_ChatResponses(s);\n let res = get_response_text(&data, 0).unwrap_or(\"\".to_owned());\n println!(\"{}\", res);\n }\n });\n }\n #[test]\n fn chat_completion_test() {\n let rt = Runtime::new().unwrap();\n let mut codeLLM = code_completion(DEEPSEEK_API_KEY);\n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"Write Hello world in rust\".to_owned(),\n },\n ];\n let res = codeLLM(messages);\n let r = rt.block_on(async { get_response_text(&res.await.unwrap(), 0) });\n dbg!(&r);\n assert!(r.is_some());\n }\n #[test]\n fn function_call_test() {\n let rt = Runtime::new().unwrap();\n\n let tparam1 = json!({\n \"type\": \"object\",\n \"required\": [\"location\"],\n \"properties\": {\n \"location\": {\n \"type\": \"string\",\n \"description\": \"The city and state, e.g. San Francisco, CA\"\n }\n }\n });\n\n let t1 = FunctionalCallObject::new(\n \"get_weather\",\n \"Get weather of an location, the user shoud supply a location first\",\n tparam1,\n );\n\n let tools = vec![t1];\n let mut codeLLM = llm_function_call(DEEPSEEK_API_KEY, tools);\n\n let messages = vec![\n Message {\n role: \"system\".to_owned(),\n content: \"You are a helpful assistant,your should reply in json format\".to_owned(),\n },\n Message {\n role: \"user\".to_owned(),\n content: \"How's the weather in Hangzhou?\".to_owned(),\n },\n ];\n let res = codeLLM(messages);\n let r = rt.block_on(async {\n let d = res.await.unwrap();\n dbg!(&d);\n get_response_text(&d, 0)\n });\n dbg!(&r);\n assert!(r.is_some());\n }\n}\n"}}}} |