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 #[serde(rename = "assistant")]
23 Assistant,
24}
25
26#[derive(CandidType, Serialize, Deserialize, Debug)]
28pub struct ChatMessage {
29 pub role: Role,
30 pub content: String,
31}
32
33#[derive(Debug)]
35pub enum Model {
36 Llama3_1_8B,
37}
38
39impl fmt::Display for Model {
40 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41 let text = match self {
42 Model::Llama3_1_8B => "llama3.1:8b",
43 };
44 write!(f, "{}", text)
45 }
46}
47
48pub async fn prompt<P: ToString>(model: Model, prompt_str: P) -> String {
60 let llm_canister = Principal::from_text(LLM_CANISTER).expect("invalid canister id");
61
62 let res: (String,) = ic_cdk::call(
63 llm_canister,
64 "v0_chat",
65 (Request {
66 model: model.to_string(),
67 messages: vec![ChatMessage {
68 role: Role::User,
69 content: prompt_str.to_string(),
70 }],
71 },),
72 )
73 .await
74 .unwrap();
75 res.0
76}
77
78pub async fn chat(model: Model, messages: Vec<ChatMessage>) -> String {
103 let llm_canister = Principal::from_text(LLM_CANISTER).expect("invalid canister id");
104
105 let res: (String,) = ic_cdk::call(
106 llm_canister,
107 "v0_chat",
108 (Request {
109 model: model.to_string(),
110 messages,
111 },),
112 )
113 .await
114 .unwrap();
115 res.0
116}