Skip to content

Commit

Permalink
feat(context): use as context the content of the files matched by the…
Browse files Browse the repository at this point in the history
… given glob pattern
  • Loading branch information
efugier committed Jan 3, 2024
1 parent 13f6814 commit c09ac3f
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 56 deletions.
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "smartcat"
version = "0.4.0"
version = "0.5.0"
authors = ["Emilien Fugier <[email protected]>"]
description = '''
Putting a brain behind `cat`.
Expand All @@ -17,11 +17,12 @@ readme="README.md"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
toml = "0"
log = "0"
clap = { version = "4", features = ["derive"] }
ureq = { version="2", features = ["json"] }
glob = "0"
log = "0"
serde = { version = "1", features = ["derive"] }
toml = "0"
ureq = { version="2", features = ["json"] }

[dev-dependencies]
tempfile = "3"
Expand Down
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,27 +64,26 @@ Arguments:
[CONFIG_PROMPT] which prompt in the config to fetch [default: default]
Options:
-i, --input <INPUT>
skip reading from stdin and use that value instead
-p, --custom-prompt <CUSTOM_PROMPT>
custom prompt to append before the input
-e, --extend-conversation
whether to extend the previous conversation or start a new one
-r, --repeat-input
whether to repeat the input before the output, useful to extend instead of replacing
-p, --custom-prompt <CUSTOM_PROMPT>
custom prompt to append before the input
-c, --context <CONTEXT>
glob pattern to given the matched files' content as context
-s, --system-message <SYSTEM_MESSAGE>
system "config" message to send after the prompt and before the first user message
-c, --context <CONTEXT>
context string (will be file content if it resolves to an existing file's path) to
include after the system message and before first user message
-a, --after-input <AFTER_INPUT>
suffix to add after the input and the custom prompt
-f, --file <FILE>
skip reading from the input and read this file instead
-i, --input <INPUT>
skip reading from input and use that value instead
-t, --temparature <TEMPARATURE>
-t, --temperature <TEMPERATURE>
temperature between 0 and 2, higher means answer further from the average
--api <API>
overrides which api to hit [possible values: openai, mistral]
overrides which api to hit [possible values: openai, mistral, another-api-for-tests]
-m, --model <MODEL>
overrides which model (of the api) to use
-h, --help
Expand All @@ -101,11 +100,16 @@ The key to make this work seamlessly is a good default prompt that tells the mod

## A few examples to get started 🐈‍⬛

Ask anything without leaving the confort of your terminal, use the `-i` flag so that it doesn't wait for piped input.
Ask anything without leaving the confort of your terminal! Use the `-i` flag so that it doesn't wait for piped input.

```
sc -i "write an overview of this prject's usage" -c "src/**/*.rs"
```
> _This project is a smart version of the Unix cat command. It takes text and a prompt, then outputs text according to specifications. The output is clean and ready for further processing by other programs, making it useful for precise text control in toolchains or workflow automation._
```
sc -i "sed command to remove trailaing whitespaces at the end of all non-markdown files?"
> sed -i '' 's/[ \t]*$//' *.* !(*.md)
sed -i '' 's/[ \t]*$//' *.* !(*.md)
```

continue the last conversation use `-e`
Expand Down
55 changes: 27 additions & 28 deletions src/cutsom_prompt.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use glob::glob;
use log::debug;
use std::fs;

Expand Down Expand Up @@ -44,9 +45,22 @@ pub fn customize_prompt(
}
};
maybe_insert_message(system_message, None);
// context can be a file
let context = context.map(|ctx| fs::read_to_string(&ctx).unwrap_or(ctx));
maybe_insert_message(context, Some("context:\n".to_string()));

// insert matched file's content as context in a system message
let context = context.and_then(|glob_pattern| {
let files_content = glob(&glob_pattern)
.expect("Failed to read glob pattern")
.filter_map(Result::ok)
.filter_map(|path| {
fs::read_to_string(&path)
.ok()
.map(|content| format!("{}:\n```\n{}\n```\n", path.display(), content))
})
.collect::<String>();

(!files_content.is_empty()).then_some(files_content)
});
maybe_insert_message(context, Some("files content for context:\n\n".to_owned()));

// if prompt customization was provided, add it in a new message
if let Some(command_text) = custom_prompt {
Expand Down Expand Up @@ -251,30 +265,11 @@ mod tests {

assert_eq!(
customized.messages[0].content,
format!("context:\n{}", context_content)
);
assert_eq!(customized.messages[0].role, "system");
}

#[test]
fn test_customize_prompt_with_context_string() {
let prompt = Prompt::empty();
let context_content = "hello there";

let customized = customize_prompt(
prompt,
&None,
&None,
&None,
&None,
None,
Some(context_content.to_string()),
None,
);

assert_eq!(
customized.messages[0].content,
format!("context:\n{}", context_content)
format!(
"files content for context:\n\n{}:\n```\n{}\n```\n",
context_file.path().display(),
context_content
)
);
assert_eq!(customized.messages[0].role, "system");
}
Expand Down Expand Up @@ -370,7 +365,11 @@ mod tests {
assert_eq!(customized.messages[0].role, "system");
assert_eq!(
customized.messages[1].content,
format!("context:\n{}", context_content)
format!(
"files content for context:\n\n{}:\n```\n{}\n```\n",
context_file.path().display(),
context_content
)
);
assert_eq!(customized.messages[1].role, "system");
assert!(
Expand Down
25 changes: 12 additions & 13 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,33 @@ mod config;
long_about = None
)]
struct Cli {
/// whether to extend the previous conversation or start a new one
#[arg(short, long)]
extend_conversation: bool,
/// which prompt in the config to fetch
#[arg(default_value_t = String::from("default"))]
/// which prompt in the config to fetch
config_prompt: String,
/// whether to repeat the input before the output, useful to extend instead of replacing
/// skip reading from stdin and use that value instead
#[arg(short, long)]
repeat_input: bool,
input: Option<String>,
/// custom prompt to append before the input
#[arg(short = 'p', long)]
custom_prompt: Option<String>,
/// system "config" message to send after the prompt and before the first user message
/// whether to extend the previous conversation or start a new one
#[arg(short, long)]
system_message: Option<String>,
/// context string (will be file content if it resolves to an existing file's path) to
/// include after the system message and before first user message
extend_conversation: bool,
/// whether to repeat the input before the output, useful to extend instead of replacing
#[arg(short, long)]
repeat_input: bool,
/// glob pattern to given the matched files' content as context
#[arg(short, long)]
context: Option<String>,
/// system "config" message to send after the prompt and before the first user message
#[arg(short, long)]
system_message: Option<String>,
/// suffix to add after the input and the custom prompt
#[arg(short, long)]
after_input: Option<String>,
/// skip reading from the input and read this file instead
#[arg(short, long)]
file: Option<String>,
/// skip reading from input and use that value instead
#[arg(short, long)]
input: Option<String>,
/// temperature between 0 and 2, higher means answer further from the average
#[arg(short, long)]
temperature: Option<f32>,
Expand Down

0 comments on commit c09ac3f

Please sign in to comment.