diff options
| author | sigoden <sigoden@gmail.com> | 2023-11-27 14:04:50 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-27 14:04:50 +0800 |
| commit | 35c75506e2fd94e2285d8a3cb66208d518d5f992 (patch) | |
| tree | 97fb643bb5e231022442c1cc617f2daeaa152a66 /src/repl/mod.rs | |
| parent | 5bfe95d31110e75e84626598f033805b0ae4326c (diff) | |
| download | aichat-35c75506e2fd94e2285d8a3cb66208d518d5f992.tar.gz | |
feat: support vision (#249)
* feat: support vision
* clippy
* implement vision
* resolve data url to local file
* add model openai:gpt-4-vision-preview
* use newline to concate embeded text files
* set max_tokens for gpt-4-vision-preview
Diffstat (limited to 'src/repl/mod.rs')
| -rw-r--r-- | src/repl/mod.rs | 46 |
1 files changed, 20 insertions, 26 deletions
diff --git a/src/repl/mod.rs b/src/repl/mod.rs index df4d1c2..b8580c5 100644 --- a/src/repl/mod.rs +++ b/src/repl/mod.rs @@ -7,7 +7,7 @@ use self::highlighter::ReplHighlighter; use self::prompt::ReplPrompt; use crate::client::init_client; -use crate::config::GlobalConfig; +use crate::config::{GlobalConfig, Input}; use crate::render::{render_error, render_stream}; use crate::utils::{create_abort_signal, set_text, AbortSignal}; @@ -20,7 +20,6 @@ use reedline::{ ColumnarMenu, EditMode, Emacs, KeyCode, KeyModifiers, Keybindings, Reedline, ReedlineEvent, ReedlineMenu, ValidationResult, Validator, Vi, }; -use std::io::Read; const MENU_NAME: &str = "completion_menu"; @@ -34,9 +33,9 @@ const REPL_COMMANDS: [(&str, &str); 13] = [ (".session", "Start a context-aware chat session"), (".info session", "Show session info"), (".exit session", "End the current session"), + (".file", "Attach files to the message and then submit it"), (".set", "Modify the configuration parameters"), (".copy", "Copy the last reply to the clipboard"), - (".read", "Read files into the message and submit"), (".exit", "Exit the REPL"), ]; @@ -159,7 +158,7 @@ impl Repl { let old_role = self.config.read().role.as_ref().map(|v| v.name.to_string()); self.config.write().set_role(name)?; - self.ask(text)?; + self.ask(text, vec![])?; match old_role { Some(old_role) => self.config.write().set_role(&old_role)?, None => self.config.write().clear_role()?, @@ -184,29 +183,19 @@ impl Repl { self.copy(config.last_reply()) .with_context(|| "Failed to copy the last output")?; } - ".read" => match args { + ".read" => { + println!(r#"Deprecated. Use '.read' instead."#); + } + ".file" => match args { Some(args) => { let (files, text) = match args.split_once(" -- ") { Some((files, text)) => (files.trim(), text.trim()), None => (args, ""), }; - let files = shell_words::split(files).with_context(|| "Invalid files")?; - let mut texts = vec![]; - if !text.is_empty() { - texts.push(text.to_string()); - } - for file_path in files.into_iter() { - let mut text = String::new(); - let mut file = std::fs::File::open(&file_path) - .with_context(|| format!("Unable to open file '{file_path}'"))?; - file.read_to_string(&mut text) - .with_context(|| format!("Unable to read file '{file_path}'"))?; - texts.push(text); - } - let content = texts.join("\n"); - self.ask(&content)?; + let files = shell_words::split(files).with_context(|| "Invalid args")?; + self.ask(text, files)?; } - None => println!("Usage: .read <files>...[ -- <text>...]"), + None => println!("Usage: .file <files>...[ -- <text>...]"), }, ".exit" => match args { Some("role") => { @@ -233,7 +222,7 @@ impl Repl { _ => unknown_command()?, }, None => { - self.ask(line)?; + self.ask(line, vec![])?; } } @@ -242,13 +231,18 @@ impl Repl { Ok(false) } - fn ask(&self, input: &str) -> Result<()> { - if input.is_empty() { + fn ask(&self, text: &str, files: Vec<String>) -> Result<()> { + if text.is_empty() && files.is_empty() { return Ok(()); } - self.config.read().maybe_print_send_tokens(input); + let input = if files.is_empty() { + Input::from_str(text) + } else { + Input::new(text, files)? + }; + self.config.read().maybe_print_send_tokens(&input); let client = init_client(&self.config)?; - let output = render_stream(input, client.as_ref(), &self.config, self.abort.clone())?; + let output = render_stream(&input, client.as_ref(), &self.config, self.abort.clone())?; self.config.write().save_message(input, &output)?; if self.config.read().auto_copy { let _ = self.copy(&output); |
