mirror of
https://github.com/sigoden/aichat
synced 2024-11-16 06:15:26 +00:00
feat: add .info role
and .info session
(#183)
This commit is contained in:
parent
42339fac42
commit
e86ad7dc16
22
README.md
22
README.md
@ -140,12 +140,14 @@ The Chat REPL supports:
|
||||
```
|
||||
〉.help
|
||||
.help Print this help message
|
||||
.info Print system-wide information
|
||||
.info Print system info
|
||||
.edit Multi-line editing (CTRL+S to finish)
|
||||
.model Switch LLM model
|
||||
.role Use role
|
||||
.info role Show role info
|
||||
.exit role Leave current role
|
||||
.session Start a context-aware chat session
|
||||
.info session Show session info
|
||||
.exit session End the current session
|
||||
.set Modify the configuration parameters
|
||||
.copy Copy the last reply to the clipboard
|
||||
@ -156,7 +158,7 @@ Press Ctrl+C to abort readline, Ctrl+D to exit the REPL
|
||||
|
||||
```
|
||||
|
||||
### `.info` - view current configuration information
|
||||
### `.info` - view information
|
||||
|
||||
```
|
||||
〉.info
|
||||
@ -210,19 +212,16 @@ Select a role:
|
||||
|
||||
```
|
||||
〉.role emoji
|
||||
name: emoji
|
||||
prompt: I want you to translate the sentences I write into emojis. I will write the sentence, and you will express it with emojis. I just want you to express it with emojis. I don't want you to reply with anything but emoji. When I need to tell you something in English, I will do it by wrapping it in curly brackets like {like this}.
|
||||
temperature: null
|
||||
```
|
||||
|
||||
AI takes the role we specified:
|
||||
Send message with role:
|
||||
|
||||
```
|
||||
emoji〉hello
|
||||
👋
|
||||
```
|
||||
|
||||
Clear current selected role:
|
||||
Leave current role:
|
||||
|
||||
```
|
||||
emoji〉.exit role
|
||||
@ -231,6 +230,15 @@ emoji〉.exit role
|
||||
Hello there! How can I assist you today?
|
||||
```
|
||||
|
||||
Show role info:
|
||||
|
||||
```
|
||||
emoji〉.info role
|
||||
name: emoji
|
||||
prompt: I want you to translate the sentences I write into emojis. I will write the sentence, and you will express it with emojis. I just want you to express it with emojis. I don't want you to reply with anything but emoji. When I need to tell you something in English, I will do it by wrapping it in curly brackets like {like this}.
|
||||
temperature: null
|
||||
```
|
||||
|
||||
## `.session` - context-aware conversation
|
||||
|
||||
By default, aichat behaves in a one-off request/response manner.
|
||||
|
@ -148,12 +148,16 @@ impl Config {
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn get_role(&self, name: &str) -> Option<Role> {
|
||||
self.roles.iter().find(|v| v.match_name(name)).map(|v| {
|
||||
let mut role = v.clone();
|
||||
role.complete_prompt_args(name);
|
||||
role
|
||||
})
|
||||
pub fn retrieve_role(&self, name: &str) -> Result<Role> {
|
||||
self.roles
|
||||
.iter()
|
||||
.find(|v| v.match_name(name))
|
||||
.map(|v| {
|
||||
let mut role = v.clone();
|
||||
role.complete_prompt_args(name);
|
||||
role
|
||||
})
|
||||
.ok_or_else(|| anyhow!("Unknown role `{name}`"))
|
||||
}
|
||||
|
||||
pub fn config_dir() -> Result<PathBuf> {
|
||||
@ -235,20 +239,14 @@ impl Config {
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
pub fn set_role(&mut self, name: &str) -> Result<String> {
|
||||
match self.get_role(name) {
|
||||
Some(role) => {
|
||||
if let Some(session) = self.session.as_mut() {
|
||||
session.update_role(Some(role.clone()))?;
|
||||
}
|
||||
let output = serde_yaml::to_string(&role)
|
||||
.unwrap_or_else(|_| "Unable to echo role details".into());
|
||||
self.temperature = role.temperature;
|
||||
self.role = Some(role);
|
||||
Ok(output)
|
||||
}
|
||||
None => bail!("Unknown role `{name}`"),
|
||||
pub fn set_role(&mut self, name: &str) -> Result<()> {
|
||||
let role = self.retrieve_role(name)?;
|
||||
if let Some(session) = self.session.as_mut() {
|
||||
session.update_role(Some(role.clone()))?;
|
||||
}
|
||||
self.temperature = role.temperature;
|
||||
self.role = Some(role);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn clear_role(&mut self) -> Result<()> {
|
||||
|
@ -1,6 +1,8 @@
|
||||
use super::message::{num_tokens_from_messages, Message, MessageRole};
|
||||
use super::role::Role;
|
||||
|
||||
use crate::render::MarkdownRender;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs::{self, read_to_string};
|
||||
@ -52,13 +54,46 @@ impl Session {
|
||||
Ok(session)
|
||||
}
|
||||
|
||||
pub fn info(&self) -> Result<String> {
|
||||
pub fn export(&self) -> Result<String> {
|
||||
self.guard_save()?;
|
||||
let output = serde_yaml::to_string(&self)
|
||||
.with_context(|| format!("Unable to show info about session {}", &self.name))?;
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
pub fn render(&self, render: &mut MarkdownRender) -> Result<String> {
|
||||
let temperature = self
|
||||
.temperature
|
||||
.map_or_else(|| String::from("-"), |v| v.to_string());
|
||||
let items = vec![
|
||||
("path", self.path.clone().unwrap_or_else(|| "-".into())),
|
||||
("model", self.model.clone()),
|
||||
("tokens", self.tokens.to_string()),
|
||||
("temperature", temperature),
|
||||
];
|
||||
let mut lines = vec![];
|
||||
for (name, value) in items {
|
||||
lines.push(format!("{name:<20}{value}"));
|
||||
}
|
||||
lines.push("".into());
|
||||
for message in &self.messages {
|
||||
match message.role {
|
||||
MessageRole::System => {
|
||||
continue;
|
||||
}
|
||||
MessageRole::Assistant => {
|
||||
lines.push(render.render(&message.content));
|
||||
lines.push("".into());
|
||||
}
|
||||
MessageRole::User => {
|
||||
lines.push(format!("{}){}", self.name, message.content));
|
||||
}
|
||||
}
|
||||
}
|
||||
let output = lines.join("\n");
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
pub fn update_role(&mut self, role: Option<Role>) -> Result<()> {
|
||||
self.guard_empty()?;
|
||||
self.temperature = role.as_ref().and_then(|v| v.temperature);
|
||||
|
@ -69,7 +69,7 @@ fn main() -> Result<()> {
|
||||
}
|
||||
if cli.info {
|
||||
let info = if let Some(session) = &config.read().session {
|
||||
session.info()?
|
||||
session.export()?
|
||||
} else if let Some(role) = &config.read().role {
|
||||
role.info()?
|
||||
} else {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::client::init_client;
|
||||
use crate::config::SharedConfig;
|
||||
use crate::print_now;
|
||||
use crate::render::render_stream;
|
||||
use crate::render::{render_stream, MarkdownRender};
|
||||
use std::fs;
|
||||
use std::io::Read;
|
||||
|
||||
@ -15,7 +15,9 @@ use std::cell::RefCell;
|
||||
|
||||
pub enum ReplCmd {
|
||||
Submit(String),
|
||||
ViewInfo,
|
||||
Info,
|
||||
RoleInfo,
|
||||
SessionInfo,
|
||||
SetModel(String),
|
||||
SetRole(String),
|
||||
ExitRole,
|
||||
@ -66,7 +68,7 @@ impl ReplCmdHandler {
|
||||
let _ = self.copy(&buffer);
|
||||
}
|
||||
}
|
||||
ReplCmd::ViewInfo => {
|
||||
ReplCmd::Info => {
|
||||
let output = self.config.read().info()?;
|
||||
print_now!("{}\n\n", output.trim_end());
|
||||
}
|
||||
@ -75,8 +77,15 @@ impl ReplCmdHandler {
|
||||
print_now!("\n");
|
||||
}
|
||||
ReplCmd::SetRole(name) => {
|
||||
let output = self.config.write().set_role(&name)?;
|
||||
print_now!("{}\n\n", output.trim_end());
|
||||
self.config.write().set_role(&name)?;
|
||||
print_now!("\n");
|
||||
}
|
||||
ReplCmd::RoleInfo => {
|
||||
if let Some(role) = &self.config.read().role {
|
||||
print_now!("{}\n\n", role.info()?);
|
||||
} else {
|
||||
bail!("No role")
|
||||
}
|
||||
}
|
||||
ReplCmd::ExitRole => {
|
||||
self.config.write().clear_role()?;
|
||||
@ -86,6 +95,15 @@ impl ReplCmdHandler {
|
||||
self.config.write().start_session(&name)?;
|
||||
print_now!("\n");
|
||||
}
|
||||
ReplCmd::SessionInfo => {
|
||||
if let Some(session) = &self.config.read().session {
|
||||
let render_options = self.config.read().get_render_options();
|
||||
let mut markdown_render = MarkdownRender::init(render_options)?;
|
||||
print_now!("{}\n\n", session.render(&mut markdown_render)?);
|
||||
} else {
|
||||
bail!("No session")
|
||||
}
|
||||
}
|
||||
ReplCmd::ExitSession => {
|
||||
self.config.write().end_session()?;
|
||||
print_now!("\n");
|
||||
|
@ -18,14 +18,16 @@ use lazy_static::lazy_static;
|
||||
use reedline::Signal;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub const REPL_COMMANDS: [(&str, &str); 12] = [
|
||||
pub const REPL_COMMANDS: [(&str, &str); 14] = [
|
||||
(".help", "Print this help message"),
|
||||
(".info", "Print system-wide information"),
|
||||
(".info", "Print system info"),
|
||||
(".edit", "Multi-line editing (CTRL+S to finish)"),
|
||||
(".model", "Switch LLM model"),
|
||||
(".role", "Use role"),
|
||||
(".info role", "Show role info"),
|
||||
(".exit role", "Leave current role"),
|
||||
(".session", "Start a context-aware chat session"),
|
||||
(".info session", "Show session info"),
|
||||
(".exit session", "End the current session"),
|
||||
(".set", "Modify the configuration parameters"),
|
||||
(".copy", "Copy the last reply to the clipboard"),
|
||||
@ -66,7 +68,7 @@ impl Repl {
|
||||
}
|
||||
Err(err) => {
|
||||
let err = format!("{err:?}");
|
||||
print_now!("{}\n\n", err.trim());
|
||||
print_now!("Error: {}\n\n", err.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,9 +97,14 @@ impl Repl {
|
||||
".help" => {
|
||||
dump_repl_help();
|
||||
}
|
||||
".info" => {
|
||||
handler.handle(ReplCmd::ViewInfo)?;
|
||||
}
|
||||
".info" => match args {
|
||||
Some("role") => handler.handle(ReplCmd::RoleInfo)?,
|
||||
Some("session") => handler.handle(ReplCmd::SessionInfo)?,
|
||||
Some(_) => unknown_command(),
|
||||
None => {
|
||||
handler.handle(ReplCmd::Info)?;
|
||||
}
|
||||
},
|
||||
".edit" => {
|
||||
if let Some(text) = args {
|
||||
handler.handle(ReplCmd::Submit(text.to_string()))?;
|
||||
@ -128,7 +135,7 @@ impl Repl {
|
||||
".exit" => match args {
|
||||
Some("role") => handler.handle(ReplCmd::ExitRole)?,
|
||||
Some("session") => handler.handle(ReplCmd::ExitSession)?,
|
||||
Some(_) => dump_unknown_command(),
|
||||
Some(_) => unknown_command(),
|
||||
None => {
|
||||
return Ok(true);
|
||||
}
|
||||
@ -141,9 +148,9 @@ impl Repl {
|
||||
Some("session") => {
|
||||
print_now!("Deprecated. Use '.exit session' instead.\n\n");
|
||||
}
|
||||
_ => dump_unknown_command(),
|
||||
_ => unknown_command(),
|
||||
},
|
||||
_ => dump_unknown_command(),
|
||||
_ => unknown_command(),
|
||||
},
|
||||
None => {
|
||||
handler.handle(ReplCmd::Submit(line.to_string()))?;
|
||||
@ -154,8 +161,8 @@ impl Repl {
|
||||
}
|
||||
}
|
||||
|
||||
fn dump_unknown_command() {
|
||||
print_now!("Unknown command. Type \".help\" for more information.\n\n");
|
||||
fn unknown_command() {
|
||||
print_now!("Unknown command. Try `.help`.\n\n");
|
||||
}
|
||||
|
||||
fn dump_repl_help() {
|
||||
|
Loading…
Reference in New Issue
Block a user