-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
123 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod chat; | ||
pub mod complete; | ||
pub mod generate_zsh_completion; | ||
pub mod speak; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
use std::io::Write; | ||
use std::path::PathBuf; | ||
|
||
use clap::Args; | ||
use tokio::fs; | ||
use tokio::io::AsyncBufReadExt; | ||
use tokio::io::AsyncWriteExt; | ||
use tokio::io::BufReader; | ||
use tracing::info; | ||
|
||
use crate::llm; | ||
use crate::llm::ChatEvent; | ||
use crate::llm::ChatListener; | ||
use crate::util::exception::Exception; | ||
|
||
#[derive(Args)] | ||
pub struct Complete { | ||
#[arg(help = "prompt file")] | ||
prompt: PathBuf, | ||
|
||
#[arg(long, help = "conf path")] | ||
conf: PathBuf, | ||
|
||
#[arg(long, help = "model name")] | ||
name: String, | ||
} | ||
|
||
struct Listener; | ||
|
||
impl ChatListener for Listener { | ||
fn on_event(&self, event: ChatEvent) { | ||
match event { | ||
ChatEvent::Delta(data) => { | ||
print!("{data}"); | ||
let _ = std::io::stdout().flush(); | ||
} | ||
ChatEvent::End(usage) => { | ||
println!(); | ||
info!( | ||
"usage, request_tokens={}, response_tokens={}", | ||
usage.request_tokens, usage.response_tokens | ||
); | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl Complete { | ||
pub async fn execute(&self) -> Result<(), Exception> { | ||
let config = llm::load(&self.conf).await?; | ||
let mut model = config.create(&self.name)?; | ||
model.listener(Box::new(Listener)); | ||
|
||
let prompt = fs::OpenOptions::new().read(true).open(&self.prompt).await?; | ||
let reader = BufReader::new(prompt); | ||
let mut lines = reader.lines(); | ||
|
||
let mut files: Vec<PathBuf> = vec![]; | ||
let mut message = String::new(); | ||
let mut on_system_message = false; | ||
loop { | ||
let Some(line) = lines.next_line().await? else { break }; | ||
|
||
if line.is_empty() { | ||
continue; | ||
} | ||
|
||
if line.starts_with("# system") { | ||
if !message.is_empty() { | ||
return Err(Exception::ValidationError("system message must be at first".to_string())); | ||
} | ||
on_system_message = true; | ||
} else if line.starts_with("---") || line.starts_with("# file: ") { | ||
if on_system_message { | ||
info!("system message: {}", message); | ||
model.system_message(message); | ||
message = String::new(); | ||
on_system_message = false; | ||
} | ||
if line.starts_with("# file: ") { | ||
let file = PathBuf::from(line.strip_prefix("# file: ").unwrap().to_string()); | ||
info!("file: {}", file.to_string_lossy()); | ||
files.push(file); | ||
} | ||
} else { | ||
message.push_str(&line); | ||
message.push('\n'); | ||
} | ||
} | ||
|
||
info!("prompt: {}", message); | ||
let files = files.into_iter().map(Some).collect(); | ||
let message = model.chat(message, files).await?; | ||
|
||
let mut prompt = fs::OpenOptions::new().append(true).open(&self.prompt).await?; | ||
prompt.write_all(b"\n---\n\n").await?; | ||
prompt.write_all(message.as_bytes()).await?; | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters