Skip to content

Commit

Permalink
Add describe command to provide descriptions of commands and their …
Browse files Browse the repository at this point in the history
…options (#43)

Add describe command to commands module
  • Loading branch information
ykdy3951 committed Mar 22, 2024
1 parent c4d18bc commit 854dbfd
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 0 deletions.
101 changes: 101 additions & 0 deletions src/commands/describe/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use clap::Parser;
use llm_chain::{
chains::conversation::Chain,
executor,
options::{ModelRef, OptionsBuilder},
parameters, prompt,
prompt::{ChatMessageCollection, Conversation},
step::Step,
};
use llm_chain_openai::chatgpt::Model;
use spinners::{Spinner, Spinners};
use std::env;

#[derive(Debug, Parser)]
#[clap(name = "describe", about = "Describe a command from the LLM model")]
pub struct Describe {
// The command to search
#[clap(help = "The command to describe")]
qeury: String,
}

pub fn few_shot_template(list: Vec<(String, String)>) -> ChatMessageCollection<String> {
let mut ret_prompt = Conversation::new();

for (user, assistant) in &list {
ret_prompt = ret_prompt
.with_user(user.to_string())
.with_assistant(assistant.to_string());
}

ret_prompt
}

pub async fn handle_describe(describe: Describe) -> Result<(), Box<dyn std::error::Error>> {
if env::var("OPENAI_API_KEY").is_err() {
println!("Please set your OpenAI API key using the `set key` command.");
return Ok(());
}

let mut spinner = Spinner::new(
Spinners::Dots9,
"Searching description for the command...".into(),
);

let model = ModelRef::from_model_name(Model::Gpt35Turbo.to_string());

let mut option_builder = OptionsBuilder::new();
option_builder.add_option(llm_chain::options::Opt::Model(model));
let options = option_builder.build();

let exec = executor!(chatgpt, options)?;

let few_shot_examples: Vec<(String, String)> = vec![
(
"sudo apt-get".to_string(),
"• sudo is used to run a command with elevated rights, typically as the superuser.\n
• apt-get is the package management command-line tool on Ubuntu and Debian-based systems.\n\t• It is used to interact with the package repositories and install, upgrade, or remove software packages.\n\t• It requires administrative privileges to perform system-wide package operations.".to_string()
),
(
"hello world".to_string(),
"The command \"hello world\" is not a valid shell command.".to_string()
),
(
"docker build -t myapp:latest --path".to_string(),
"• docker build is used to build a Docker image from a Dockerfile.\n\t• -t myapp:latest specifies the name and tag for the resulting image.\n\t\t• myapp is the name of the image.\n\t\t• latest is the tag for the image.\n\t• --path specifies the path to the build context, which is the directory that contains the Dockerfile and any additional files needed for the build.".to_string()
),
];

let mut conversation = Conversation::new()
.with_system(
"I want you to act as genertaing a description for the command. You should provide a brief explanation of the command and its arguments.".to_string()
);

let few_shot_prompt = few_shot_template(few_shot_examples);

conversation.append(few_shot_prompt);

let conversation =
conversation.with_system("Explain the command and its arguments step by step.".to_string());

let mut chain = Chain::new_with_message_collection(&conversation);

let step = Step::for_prompt_template(prompt!(
user: "{{query}}"
));
let parameters = parameters!().with("query", describe.qeury.clone());
let res = chain.send_message(step, &parameters, &exec).await?;
let res = res.to_immediate().await?.as_content().to_chat().to_string();
let res = res.split("Assistant: ").collect::<Vec<&str>>()[1]
.to_string()
.trim()
.to_string();

spinner.stop_and_persist(
"✔",
"Finished searching for the command. Here's the description:".to_string(),
);

println!("{}", res);
Ok(())
}
3 changes: 3 additions & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod describe;
mod history;
mod search;
mod set;
Expand All @@ -9,12 +10,14 @@ pub enum Commands {
Search(search::Search),
Set(set::Set),
History(history::History),
Describe(describe::Describe),
}

pub async fn handle_command(command: Commands) -> Result<(), Box<dyn std::error::Error>> {
match command {
Commands::Search(search) => search::handle_search(search).await,
Commands::Set(set) => set::handle_set(set).await,
Commands::History(history) => history::handle_history(history).await,
Commands::Describe(describe) => describe::handle_describe(describe).await,
}
}

0 comments on commit 854dbfd

Please sign in to comment.