summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorsigoden <sigoden@gmail.com>2023-03-02 20:11:17 +0800
committersigoden <sigoden@gmail.com>2023-03-02 20:11:17 +0800
commita80399df364a7e81af95afe451a27f60b34be9a7 (patch)
tree3d939660622e23e65b698185cae55f8abaead30d /src
parentdfebab910debf8375f1b628c0e0494399e21cecb (diff)
downloadaichat-a80399df364a7e81af95afe451a27f60b34be9a7.tar.gz
feat: repl supports history
Diffstat (limited to 'src')
-rw-r--r--src/main.rs22
1 files changed, 19 insertions, 3 deletions
diff --git a/src/main.rs b/src/main.rs
index b88a209..156add8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -15,13 +15,14 @@ use futures_util::StreamExt;
use inquire::{Confirm, Text};
use reedline::{
default_emacs_keybindings, ColumnarMenu, DefaultCompleter, DefaultPrompt, DefaultPromptSegment,
- Emacs, KeyCode, KeyModifiers, Reedline, ReedlineEvent, ReedlineMenu, Signal,
+ Emacs, FileBackedHistory, KeyCode, KeyModifiers, Reedline, ReedlineEvent, ReedlineMenu, Signal,
};
use reqwest::{Client, Proxy};
use serde_json::{json, Value};
use tokio::runtime::Runtime;
const API_URL: &str = "https://api.openai.com/v1/chat/completions";
+const MODEL: &str = "gpt-3.5-turbo";
const HELP: &str = r###".exit Exit the REPL.
.help Print this help message.
.role Specify the role that the AI will play.
@@ -39,6 +40,11 @@ fn start() -> Result<()> {
let matches = Command::new(env!("CARGO_CRATE_NAME"))
.version(env!("CARGO_PKG_VERSION"))
.author(env!("CARGO_PKG_AUTHORS"))
+ .about(concat!(
+ env!("CARGO_PKG_DESCRIPTION"),
+ " - ",
+ env!("CARGO_PKG_REPOSITORY")
+ ))
.arg(
Arg::new("role")
.short('r')
@@ -148,9 +154,14 @@ fn run_repl(runtime: Runtime, client: Client, config: Config, role: Option<Strin
ReedlineEvent::MenuNext,
]),
);
+ let history = Box::new(
+ FileBackedHistory::with_file(1000, get_history_path()?)
+ .map_err(|err| anyhow!("Failed to setup history file, {err}"))?,
+ );
let edit_mode = Box::new(Emacs::new(keybindings));
let mut line_editor = Reedline::create()
.with_completer(completer)
+ .with_history(history)
.with_menu(ReedlineMenu::EngineCompleter(completion_menu))
.with_edit_mode(edit_mode);
let prompt = DefaultPrompt::new(DefaultPromptSegment::Empty, DefaultPromptSegment::Empty);
@@ -241,7 +252,7 @@ async fn acquire(client: &Client, config: &Config, content: &str) -> Result<Stri
return Ok(content.to_string());
}
let body = json!({
- "model": "gpt-3.5-turbo",
+ "model": MODEL,
"messages": [{"role": "user", "content": content}]
});
@@ -267,7 +278,7 @@ async fn acquire_stream(
content: &str,
) -> Result<EventStream<impl Stream<Item = reqwest::Result<bytes::Bytes>>>> {
let body = json!({
- "model": "gpt-3.5-turbo",
+ "model": MODEL,
"messages": [{"role": "user", "content": content}],
"stream": true,
});
@@ -293,3 +304,8 @@ fn get_config_path() -> Result<PathBuf> {
let config_dir = dirs::home_dir().ok_or_else(|| anyhow!("No home dir"))?;
Ok(config_dir.join(format!(".{}.toml", env!("CARGO_CRATE_NAME"))))
}
+
+fn get_history_path() -> Result<PathBuf> {
+ let config_dir = dirs::home_dir().ok_or_else(|| anyhow!("No home dir"))?;
+ Ok(config_dir.join(format!(".{}_history", env!("CARGO_CRATE_NAME"))))
+}