1use candid::{CandidType, Principal};
3use serde::{Deserialize, Serialize};
4use std::fmt;
5
6const LLM_CANISTER: &str = "w36hm-eqaaa-aaaal-qr76a-cai";
8
9#[derive(CandidType, Serialize, Deserialize, Debug)]
10struct Request {
11 model: String,
12 messages: Vec<ChatMessage>,
13}
14
15#[derive(CandidType, Serialize, Deserialize, Debug)]
17pub enum Role {
18 #[serde(rename = "system")]
19 System,
20 #[serde(rename = "user")]
21 User,
22}
23
24#[derive(CandidType, Serialize, Deserialize, Debug)]
26pub struct ChatMessage {
27 pub role: Role,
28 pub content: String,
29}
30
31#[derive(Debug)]
33pub enum Model {
34 Llama3_1_8B,
35}
36
37impl fmt::Display for Model {
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 let text = match self {
40 Model::Llama3_1_8B => "llama3.1:8b",
41 };
42 write!(f, "{}", text)
43 }
44}
45
46pub async fn prompt<P: ToString>(model: Model, prompt_str: P) -> String {
58 let llm_canister = Principal::from_text(LLM_CANISTER).expect("invalid canister id");
59
60 let res: (String,) = ic_cdk::call(
61 llm_canister,
62 "v0_chat",
63 (Request {
64 model: model.to_string(),
65 messages: vec![ChatMessage {
66 role: Role::User,
67 content: prompt_str.to_string(),
68 }],
69 },),
70 )
71 .await
72 .unwrap();
73 res.0
74}
75
76pub async fn chat(model: Model, messages: Vec<ChatMessage>) -> String {
101 let llm_canister = Principal::from_text(LLM_CANISTER).expect("invalid canister id");
102
103 let res: (String,) = ic_cdk::call(
104 llm_canister,
105 "v0_chat",
106 (Request {
107 model: model.to_string(),
108 messages,
109 },),
110 )
111 .await
112 .unwrap();
113 res.0
114}