From 18e020a563e869208227fa44b1815e28efc95ad8 Mon Sep 17 00:00:00 2001 From: Linus Oleander <220827+oleander@users.noreply.github.com> Date: Wed, 5 Feb 2025 15:28:26 +0100 Subject: [PATCH] Improve AI prompt (#26) * Change max_tokens type from usize to u16 * Bump git-ai version to 0.2.54 in Cargo.lock * Refine context line handling in `PatchDiff` implementation * Refactor `Model` enum with default attributes * Remove pull_request trigger from cd workflow * Update version to 0.2.56 in Cargo files --- .github/workflows/cd.yml | 1 - Cargo.lock | 2 +- Cargo.toml | 2 +- resources/prompt.md | 6 ++++-- src/commit.rs | 2 +- src/hook.rs | 12 +++++++++--- src/model.rs | 10 +++++++--- src/openai.rs | 16 ++++++++++++++++ 8 files changed, 39 insertions(+), 12 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 7c3fbc7..7875d5a 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -4,7 +4,6 @@ on: push: branches: - main - pull_request: workflow_dispatch: concurrency: diff --git a/Cargo.lock b/Cargo.lock index a7074b3..4d44ba1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -651,7 +651,7 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "git-ai" -version = "0.2.53" +version = "0.2.56" dependencies = [ "anyhow", "async-openai", diff --git a/Cargo.toml b/Cargo.toml index f4da61b..61b5325 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git-ai" -version = "0.2.54" +version = "0.2.56" edition = "2021" description = "Git AI: Automates commit messages using ChatGPT. Stage your files, and Git AI generates the messages." license = "MIT" diff --git a/resources/prompt.md b/resources/prompt.md index 6672d21..523b51d 100644 --- a/resources/prompt.md +++ b/resources/prompt.md @@ -1,7 +1,9 @@ You are an AI assistant that generates concise and meaningful git commit messages based on provided diffs. Please adhere to the following guidelines: - Structure: Begin with a clear, present-tense summary. -- Content: Emphasize the changes and their rationale, excluding irrelevant details. +- Content: While you should use the surrounding context to understand the changes, your commit message should ONLY describe the lines marked with + or -. +- Understanding: Use the context (unmarked lines) to understand the purpose and impact of the changes, but do not mention unchanged code in the commit message. +- Changes: Only describe what was actually changed (added, removed, or modified). - Consistency: Maintain uniformity in tense, punctuation, and capitalization. - Accuracy: Ensure the message accurately reflects the changes and their purpose. - Present tense, imperative mood. (e.g., "Add x to y" instead of "Added x to y") @@ -9,7 +11,7 @@ You are an AI assistant that generates concise and meaningful git commit message ## Output: -Your output should be a commit message generated from the input diff and nothing else. +Your output should be a commit message generated from the input diff and nothing else. While you should use the surrounding context to understand the changes, your message should only describe what was actually modified (+ or - lines). ## Input: diff --git a/src/commit.rs b/src/commit.rs index e93df00..865d1fa 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -35,7 +35,7 @@ pub async fn generate(diff: String, max_tokens: usize, model: Model) -> Result { - // TODO: Grouo arguments fn to_patch(&self, max_tokens: usize, model: Model) -> Result { let mut files: HashMap = HashMap::new(); @@ -79,12 +78,19 @@ impl PatchDiff for Diff<'_> { let content = line.content(); let string = content.to_utf8(); + // Include both changes and context, but prefix context lines with "context: " + // This helps the model understand the context while still identifying actual changes + let line_content = match line.origin() { + '+' | '-' => string, + _ => format!("context: {}", string) + }; + match files.get(&diff.path()) { Some(file_acc) => { - files.insert(diff.path(), file_acc.to_owned() + &string); + files.insert(diff.path(), file_acc.to_owned() + &line_content); } None => { - files.insert(diff.path(), string); + files.insert(diff.path(), line_content); } } diff --git a/src/model.rs b/src/model.rs index cff53ea..37cb7c2 100644 --- a/src/model.rs +++ b/src/model.rs @@ -11,6 +11,7 @@ const GPT4: &str = "gpt-4"; const GPT4O: &str = "gpt-4o"; const GPT4_TURBO: &str = "gpt-4-turbo-preview"; const LLAMA3: &str = "llama3"; +const GPT4OMINI: &str = "gpt-4o-mini"; #[derive(Debug, Clone, PartialEq)] pub struct Response { @@ -28,10 +29,11 @@ pub struct Request { #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Serialize, Deserialize, Default)] pub enum Model { GPT4, - #[default] GPT4o, GPT4Turbo, - Llama3 + Llama3, + #[default] + GPT4oMini } impl Model { @@ -79,7 +81,8 @@ impl From<&Model> for &str { Model::GPT4o => GPT4O, Model::GPT4 => GPT4, Model::GPT4Turbo => GPT4_TURBO, - Model::Llama3 => LLAMA3 + Model::Llama3 => LLAMA3, + Model::GPT4oMini => GPT4OMINI } } } @@ -93,6 +96,7 @@ impl FromStr for Model { GPT4 => Ok(Model::GPT4), GPT4_TURBO => Ok(Model::GPT4Turbo), LLAMA3 => Ok(Model::Llama3), + GPT4OMINI => Ok(Model::GPT4oMini), model => bail!("Invalid model: {}", model) } } diff --git a/src/openai.rs b/src/openai.rs index 6720691..2c2c766 100644 --- a/src/openai.rs +++ b/src/openai.rs @@ -7,6 +7,21 @@ use crate::config; use crate::model::Response; use crate::model::Request; +<<<<<<< HEAD +======= +#[derive(Debug, Clone, PartialEq)] +pub struct Response { + pub response: String +} + +#[derive(Debug, Clone, PartialEq)] +pub struct Request { + pub prompt: String, + pub system: String, + pub max_tokens: u16, + pub model: Model +} +>>>>>>> 44782ec (Improve AI prompt (#26)) pub async fn call(request: Request) -> Result { let api_key = config::APP @@ -19,6 +34,7 @@ pub async fn call(request: Request) -> Result { let request = CreateChatCompletionRequestArgs::default() .model(request.model.to_string()) + .max_tokens(request.max_tokens) .messages([ ChatCompletionRequestSystemMessageArgs::default() .content(request.system)