Skip to content

Commit

Permalink
release v0.1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
EluvK committed Mar 10, 2023
1 parent d358fc3 commit fc8f5a2
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
os: macos-latest
- target: x86_64-apple-darwin
os: macos-latest
- target: x86_64-pc-windows-gnu
os: windows-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/target
/test
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "qbot"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
authors = ["[email protected]"]

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Options:

目前支持:

- [x] 单条消息回复群聊里的 @ 问题
- [x] 单条消息回复群聊里的 @ 问题, 连续上下文记录
- [x] 私聊消息,连续上下文记录
- [x] # 机器人指令,更换prompt内容、清理上下文记录等。

Expand Down
2 changes: 1 addition & 1 deletion src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::role::BotRole;

pub(super) static COMMAND_HELP_INFO: &str = r#"
- `#role { name }` to set role
- assistant | taler | storyteller | default
- assistant | taler | storyteller | foodcritic | default
- `#clean` to clean chat history
- `#reset` to reset everything
- `#help` for this menu
Expand Down
53 changes: 44 additions & 9 deletions src/cqbot/bot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use tokio_tungstenite::{connect_async, tungstenite::Message, MaybeTlsStream, Web
use crate::{
cqbot::msg::{MessageType, RecvMsg, SendMsg},
gpt::{GPTPostMessage, GPTRecvMessage},
private_manager::PrivateManager,
private_manager::{GroupManager, PrivateManager},
};

pub struct Bot {
Expand All @@ -14,6 +14,7 @@ pub struct Bot {
api_key: String,
web_socket_stream: Box<WebSocketStream<MaybeTlsStream<TcpStream>>>,
private_manager: PrivateManager,
group_manager: GroupManager,
}

static OPENAIAPIURL: &str = "https://api.openai.com/v1/chat/completions";
Expand All @@ -27,6 +28,7 @@ impl Bot {
api_key,
web_socket_stream: Box::new(wss),
private_manager: PrivateManager::new(),
group_manager: GroupManager::new(),
}
}

Expand Down Expand Up @@ -72,15 +74,48 @@ impl Bot {
}

async fn handler_group_message(&mut self, message: RecvMsg) -> SendMsg {
let post_message = GPTPostMessage::new_basic_message(message.message().clone());
let return_message = match self.post_gpt_request(post_message).await {
Ok(gpt_recv_msg) => {
let msg = gpt_recv_msg.get_return_msg().unwrap();
msg.into_contnet()
let group_id = message.group_id();
let user_id = message.user_id();
let gpm = self
.group_manager
.pre_handle_private_message(group_id, user_id, message.message().clone());

match gpm {
Ok(_) => {
// legal request
let post_message = GPTPostMessage::new_with_history(
self.group_manager.get_histories(group_id, user_id).unwrap().clone(),
);
let return_message = match self.post_gpt_request(post_message).await {
Ok(gpt_recv_msg) => {
let msg = gpt_recv_msg.get_return_msg().unwrap();
self.group_manager.push_history(group_id, user_id, msg.clone());
msg.into_contnet()
}
Err(e) => {
// todo might need to noted user to reset || clean
self.group_manager.pop_history(group_id, user_id);
e.to_string()
}
};
self.group_manager.after_handle_private_message(group_id, user_id);
SendMsg::new_group_reply_msg_at(group_id, user_id, return_message)
}
Err(e) => e.to_string(),
};
SendMsg::new_group_reply_msg(message.group_id(), message.message_id(), return_message)
Err(e) => {
self.group_manager.after_handle_private_message(group_id, user_id);
SendMsg::new_group_reply_msg_at(group_id, user_id, e.to_string())
}
}

// let post_message = GPTPostMessage::new_basic_message(message.message().clone());
// let return_message = match self.post_gpt_request(post_message).await {
// Ok(gpt_recv_msg) => {
// let msg = gpt_recv_msg.get_return_msg().unwrap();
// msg.into_contnet()
// }
// Err(e) => e.to_string(),
// };
// SendMsg::new_group_reply_msg(message.group_id(), message.message_id(), return_message)
}
async fn handler_private_message(&mut self, message: RecvMsg) -> SendMsg {
let user_id = message.user_id();
Expand Down
16 changes: 14 additions & 2 deletions src/cqbot/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,27 @@ impl SendMsg {
}
}

pub fn new_group_reply_msg(group_id: u64, message_id: i64, message: String) -> Self {
pub fn new_group_reply_msg_at(group_id: u64, user_id: u64, message: String) -> Self {
SendMsg {
action: SendMsgAction::SendGroupMsg,
params: SendMsgParams {
user_id: None,
group_id: Some(group_id),
message: format!("[CQ:reply,id={}]{}", message_id, message),
message: format!("[CQ:at,qq={}]{}", user_id, message),
},
}
}

// pub fn new_group_reply_msg(group_id: u64, message_id: i64, message: String) -> Self {
// SendMsg {
// action: SendMsgAction::SendGroupMsg,
// params: SendMsgParams {
// user_id: None,
// group_id: Some(group_id),
// message: format!("[CQ:reply,id={}]{}", message_id, message),
// },
// }
// }
}

#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -125,6 +136,7 @@ impl RecvMsg {
pub fn user_id(&self) -> u64 {
self.user_id
}
#[allow(dead_code)]
pub fn message_id(&self) -> i64 {
self.message_id
}
Expand Down
1 change: 1 addition & 0 deletions src/gpt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl Default for GPTPostMessage {
}

impl GPTPostMessage {
#[allow(dead_code)]
pub fn new_basic_message(message: String) -> Self {
GPTPostMessage {
messages: vec![
Expand Down
47 changes: 46 additions & 1 deletion src/private_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ impl ChatContext {

fn set_role(&mut self, role: &BotRole) {
self.histories.clear();
self.histories.push(role.system_infomation())
self.role = role.clone();
role.system_infomation()
.iter()
.for_each(|m| self.histories.push(m.clone()));
}
}

Expand Down Expand Up @@ -121,6 +124,48 @@ impl PrivateManager {
}
}

pub struct GroupManager {
contexts: HashMap<u64, PrivateManager>,
}

impl GroupManager {
pub fn new() -> Self {
Self {
contexts: HashMap::new(),
}
}

pub fn pre_handle_private_message(
&mut self,
group_id: u64,
user_id: u64,
message: String,
) -> Result<(), PrivateManagerError> {
self.contexts.entry(group_id).or_insert_with(|| PrivateManager::new());
let group_private_manager = self.contexts.get_mut(&group_id).unwrap();
group_private_manager.pre_handle_private_message(user_id, message)
}

pub fn get_histories(&mut self, group_id: u64, user_id: u64) -> Option<&Vec<GPTMessages>> {
self.contexts.get_mut(&group_id).unwrap().get_histories(user_id)
}

pub fn push_history(&mut self, group_id: u64, user_id: u64, msg: GPTMessages) {
self.contexts.get_mut(&group_id).unwrap().push_history(user_id, msg)
}

pub fn pop_history(&mut self, group_id: u64, user_id: u64) {
self.contexts.get_mut(&group_id).unwrap().pop_history(user_id)
}

pub fn after_handle_private_message(&mut self, group_id: u64, user_id: u64) {
self.contexts
.get_mut(&group_id)
.unwrap()
.after_handle_private_message(user_id)
}
}

mod error {
use thiserror::Error;

Expand Down
16 changes: 12 additions & 4 deletions src/role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub enum BotRole {
Assistant,
Taler,
StoryTeller,
FoodCritic,
}

impl BotRole {
Expand All @@ -18,6 +19,7 @@ impl BotRole {
"assistant" | "Assistant" | "default" | "Default" => Self::Assistant,
"taler" => Self::Taler,
"storyteller" => Self::StoryTeller,
"foodcritic" => Self::FoodCritic,
_ => Self::Assistant,
}
}
Expand All @@ -29,13 +31,19 @@ impl BotRole {
}
BotRole::Taler => "I am now a fairy tale writer, I will help you write stories.",
BotRole::StoryTeller => "I am now a story teller, I will help you wirte stories.",
BotRole::FoodCritic => "好的,请告诉我店名和食物名称。",
}
}
pub fn system_infomation(&self) -> GPTMessages {
pub fn system_infomation(&self) -> Vec<GPTMessages> {
match self {
BotRole::Assistant => GPTMessages::new_system_message(ASSISTANT_SYSTEM_INFO.into()),
BotRole::Taler => GPTMessages::new_system_message(TALER_SYSTEM_INFO.into()),
BotRole::StoryTeller => GPTMessages::new_system_message(STORYTELLER_SYSTEM_INFO.into()),
BotRole::Assistant => vec![GPTMessages::new_system_message(ASSISTANT_SYSTEM_INFO.into())],
BotRole::Taler => vec![GPTMessages::new_system_message(TALER_SYSTEM_INFO.into())],
BotRole::StoryTeller => vec![GPTMessages::new_system_message(STORYTELLER_SYSTEM_INFO.into())],
BotRole::FoodCritic => vec![
GPTMessages::new_system_message("你是美食评论员,帮助编写美食的评论文章。".into()),
GPTMessages::new_user_message("接下来我会给你店名和食物的名称,生存一篇300字的评论,且注意评论食物的句子要简单但语气夸张,不要用重复的话,每行不超过30个字,换行要换两次,在每行的最前面加上几个不一样的emoji。".into()),
GPTMessages::new_assist_message("好的,请告诉我店名和食物名称。".into()),
],
}
}
}

0 comments on commit fc8f5a2

Please sign in to comment.