branch: externals/minuet commit 64240457eb4868af8ae614c304a5691f1f6fc43d Author: milanglacier <d...@milanglacier.com> Commit: GitHub <nore...@github.com>
feat!: Implement Prefix-First prompt structure for Gemini (#36) - Add a new "Prefix-First" prompt structure for chat LLMs. - Modified the Gemini provider's default prompt strategy to use this new structure. - Other providers will continue to use their previous default prompt configurations. --- README.md | 15 +++-------- minuet.el | 35 +++++++++++++++++++++----- prompt.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 100 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index a69c966b95..3180051fe5 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ - [Claude](#claude) - [Codestral](#codestral) - [Gemini](#gemini) - - [Experimental Configuration](#experimental-configuration) - [OpenAI-compatible](#openai-compatible) - [OpenAI-FIM-Compatible](#openai-fim-compatible) - [Troubleshooting](#troubleshooting) @@ -476,12 +475,12 @@ The following config is the default. :api-key "GEMINI_API_KEY" :system (:template minuet-default-system-template - :prompt minuet-default-prompt + :prompt minuet-default-prompt-prefix-first :guidelines minuet-default-guidelines :n-completions-template minuet-default-n-completion-template) - :fewshots minuet-default-fewshots + :fewshots minuet-default-fewshots-prefix-first :chat-input - (:template minuet-default-chat-input-template + (:template minuet-default-chat-input-template-prefix-first :language-and-tab minuet--default-chat-input-language-and-tab-function :context-before-cursor minuet--default-chat-input-before-cursor-function :context-after-cursor minuet--default-chat-input-after-cursor-function) @@ -512,14 +511,6 @@ settings following the example: </details> -### Experimental Configuration - -Gemini appears to perform better with an alternative input structure, unlike -other chat-based LLMs. This observation is currently experimental and requires -further validation. For details on the experimental prompt setup currently in -use by the maintainer, please refer to the -[prompt documentation](./prompt.md#an-experimental-configuration-setup-for-gemini). - ## OpenAI-compatible Use any providers compatible with OpenAI's chat completion API. diff --git a/minuet.el b/minuet.el index 844e691f7f..97066cfb08 100644 --- a/minuet.el +++ b/minuet.el @@ -164,7 +164,7 @@ guarantee the exact number of completion items specified, as this parameter serves only as a prompt guideline. The default is `3`." :type 'integer) -(defvar minuet-default-prompt +(defvar minuet-default-prompt-prefix-first "You are the backend of an AI-powered code completion engine. Your task is to provide code suggestions based on the user's input. The user's code will be enclosed in markers: @@ -172,11 +172,15 @@ enclosed in markers: - `<contextAfterCursor>`: Code context after the cursor - `<cursorPosition>`: Current cursor location - `<contextBeforeCursor>`: Code context before the cursor +" + "The default prefix style prompt for minuet completion.") +(defvar minuet-default-prompt + (concat minuet-default-prompt-prefix-first + " Note that the user's code will be prompted in reverse order: first the code after the cursor, then the code before the cursor. -" - "The default prompt for minuet completion.") +") "The default prefix-first style prompt for minuet completion.") (defvar minuet-default-guidelines "Guidelines: @@ -207,6 +211,14 @@ after the cursor, then the code before the cursor. {{{:context-before-cursor}}}<cursorPosition>" "The default template for minuet chat input.") +(defvar minuet-default-chat-input-template-prefix-first + "{{{:language-and-tab}}} +<contextBeforeCursor> +{{{:context-before-cursor}}}<cursorPosition> +<contextAfterCursor> +{{{:context-after-cursor}}}" + "The default prefix-first style template for minuet chat input.") + (defvar minuet-default-fewshots `((:role "user" :content "# language: python @@ -234,6 +246,17 @@ def fibonacci(n): <endCompletion> "))) +(defvar minuet-default-fewshots-prefix-first + `((:role "user" + :content "# language: python +<contextBeforeCursor> +def fibonacci(n): + <cursorPosition> +<contextAfterCursor> + +fib(5)") + ,(cadr minuet-default-fewshots))) + (defvar minuet-claude-options `(:model "claude-3-5-haiku-20241022" :max_tokens 512 @@ -311,12 +334,12 @@ def fibonacci(n): :api-key "GEMINI_API_KEY" :system (:template minuet-default-system-template - :prompt minuet-default-prompt + :prompt minuet-default-prompt-prefix-first :guidelines minuet-default-guidelines :n-completions-template minuet-default-n-completion-template) - :fewshots minuet-default-fewshots + :fewshots minuet-default-fewshots-prefix-first :chat-input - (:template minuet-default-chat-input-template + (:template minuet-default-chat-input-template-prefix-first :language-and-tab minuet--default-chat-input-language-and-tab-function :context-before-cursor minuet--default-chat-input-before-cursor-function :context-after-cursor minuet--default-chat-input-after-cursor-function) diff --git a/prompt.md b/prompt.md index 12740910c9..3f2d2d5499 100644 --- a/prompt.md +++ b/prompt.md @@ -7,7 +7,7 @@ - [Default Few Shots Examples](#default-few-shots-examples) - [Default Chat Input Example](#default-chat-input-example) - [Customization](#customization) - - [An Experimental Configuration Setup for Gemini](#an-experimental-configuration-setup-for-gemini) + - [A Practical Example](#a-practical-example) # FIM LLM Prompt Structure @@ -36,12 +36,41 @@ incorporate the necessary special tokens within the prompt function. # Chat LLM Prompt Structure +We utilize two distinct strategies when constructing prompts: + +1. **Prefix First Style**: This involves including the code preceding the cursor + initially, followed by the code succeeding the cursor. This approach is used + only for the **Gemini** provider. + +2. **Suffix First Style**: This method involves including the code following the + cursor initially, and then the code preceding the cursor. It is employed for + **other** providers such as OpenAI, OpenAI-Compatible, and Claude. + +The counterpart variables are: + +1. `minuet-default-prompt` and `minuet-default-prompt-prefix-first`. +2. `minuet-default-fewshots` and `minuet-default-fewshots-prefix-first`. +3. `minuet-default-chat-input-template` and + `minuet-default-chat-input-template-prefix-first`. + ## Default Template `{{{:prompt}}}\n{{{:guidelines}}}\n{{{:n_completion_template}}}` ## Default Prompt +**Prefix First Style**: + +You are the backend of an AI-powered code completion engine. Your task is to +provide code suggestions based on the user's input. The user's code will be +enclosed in markers: + +- `<contextAfterCursor>`: Code context after the cursor +- `<cursorPosition>`: Current cursor location +- `<contextBeforeCursor>`: Code context before the cursor + +**Suffix First Style**: + You are the backend of an AI-powered code completion engine. Your task is to provide code suggestions based on the user's input. The user's code will be enclosed in markers: @@ -77,16 +106,19 @@ Guidelines: ## Default Few Shots Examples ```lisp -`((:role "user" - :content "# language: python + +;; suffix-first style +(defvar minuet-default-fewshots + `((:role "user" + :content "# language: python <contextAfterCursor> fib(5) <contextBeforeCursor> def fibonacci(n): <cursorPosition>") - (:role "assistant" - :content " ''' + (:role "assistant" + :content " ''' Recursive Fibonacci implementation ''' if n < 2: @@ -101,7 +133,18 @@ def fibonacci(n): a, b = b, a + b return a <endCompletion> -")) +"))) + +(defvar minuet-default-fewshots-prefix-first + `((:role "user" + :content "# language: python +<contextBeforeCursor> +def fibonacci(n): + <cursorPosition> +<contextAfterCursor> + +fib(5)") + ,(cadr minuet-default-fewshots))) ``` ## Default Chat Input Example @@ -111,12 +154,24 @@ The chat input represents the final prompt delivered to the LLM for completion. The chat input template follows a structure similar to the system prompt and can be customized using the following format: +**Suffix First Style**: + ``` {{{:language-and-tab}}} <contextAfterCursor> -{{{:context-after-cursor}}} +{{{:context_after_cursor}}} <contextBeforeCursor> -{{{:context-before-cursor}}}<cursorPosition> +{{{:context_before_cursor}}}<cursorPosition> +``` + +**Prefix First Style**: + +``` +{{{:language-and-tab}}} +<contextBeforeCursor> +{{{:context_before_cursor}}}<cursorPosition> +<contextAfterCursor> +{{{:context_after_cursor}}} ``` Components: @@ -203,18 +258,13 @@ function fibonacci(n) { (plist-put minuet-openai-options :fewshots #'my-minuet-few-shots) ``` -## An Experimental Configuration Setup for Gemini - -Some observations suggest that Gemini might perform better with a -`Prefix-Suffix` structured input format, specifically -`Before-Cursor -> Cursor-Pos -> After-Cursor`. - -This contrasts with other chat-based LLMs, which may yield better results with -the inverse structure: `After-Cursor -> Before-Cursor -> Cursor-Pos`. +## A Practical Example -This finding remains experimental and requires further validation. +Here, we present a practical example for configuring the prompt for Gemini, +aiming to reuse existing components of the default prompt wherever possible. -Below is the current configuration used by the maintainer for Gemini: +Please note that you should not copy-paste this into your configuration, as it +represents the **default setting** applied to Gemini. ```lisp (use-package minuet