Skip to content

Commit 56efb02

Browse files
committed
feat!: Implement Prefix-First prompt structure for Gemini
- 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.
1 parent 98a6383 commit 56efb02

File tree

3 files changed

+125
-26
lines changed

3 files changed

+125
-26
lines changed

README.md

+9-10
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
- [Claude](#claude)
2222
- [Codestral](#codestral)
2323
- [Gemini](#gemini)
24-
- [Experimental Configuration](#experimental-configuration)
2524
- [OpenAI-compatible](#openai-compatible)
2625
- [OpenAI-FIM-compatible](#openai-fim-compatible)
2726
- [Commands](#commands)
@@ -581,7 +580,13 @@ default_config = {
581580
-- see the documentation in each provider in the following part.
582581
},
583582
-- see the documentation in the `Prompt` section
584-
default_template = {
583+
default_system = {
584+
template = '...',
585+
prompt = '...',
586+
guidelines = '...',
587+
n_completion_template = '...',
588+
},
589+
default_system_prefix_first = {
585590
template = '...',
586591
prompt = '...',
587592
guidelines = '...',
@@ -593,6 +598,8 @@ default_config = {
593598
},
594599
default_few_shots = { '...' },
595600
default_chat_input = { '...' },
601+
default_few_shots_prefix_first = { '...' },
602+
default_chat_input_prefix_first = { '...' },
596603
-- Config options for `Minuet change_preset` command
597604
presets = {}
598605
}
@@ -814,14 +821,6 @@ provider_options = {
814821

815822
</details>
816823

817-
### Experimental Configuration
818-
819-
Gemini appears to perform better with an alternative input structure, unlike
820-
other chat-based LLMs. This observation is currently experimental and requires
821-
further validation. For details on the experimental prompt setup currently in
822-
use by the maintainer, please refer to the [prompt
823-
documentation](./prompt.md#an-experimental-configuration-setup-for-gemini).
824-
825824
## OpenAI-compatible
826825

827826
Use any providers compatible with OpenAI's chat completion API.

lua/minuet/config.lua

+36-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
local default_prompt = [[
1+
local default_prompt_prefix_first = [[
22
You are the backend of an AI-powered code completion engine. Your task is to
33
provide code suggestions based on the user's input. The user's code will be
44
enclosed in markers:
55
66
- `<contextAfterCursor>`: Code context after the cursor
77
- `<cursorPosition>`: Current cursor location
88
- `<contextBeforeCursor>`: Code context before the cursor
9+
]]
10+
11+
local default_prompt = default_prompt_prefix_first
12+
.. [[
913
1014
Note that the user's code will be prompted in reverse order: first the code
1115
after the cursor, then the code before the cursor.
@@ -57,6 +61,21 @@ def fibonacci(n):
5761
},
5862
}
5963

64+
local default_few_shots_prefix_first = {
65+
{
66+
role = 'user',
67+
content = [[
68+
# language: python
69+
<contextBeforeCursor>
70+
def fibonacci(n):
71+
<cursorPosition>
72+
<contextAfterCursor>
73+
74+
fib(5)]],
75+
},
76+
default_few_shots[2],
77+
}
78+
6079
local n_completion_template = '8. Provide at most %d completion items.'
6180

6281
-- use {{{ and }}} to wrap placeholders, which will be further processesed in other function
@@ -120,6 +139,10 @@ local default_chat_input = {
120139
end,
121140
}
122141

142+
local default_chat_input_prefix_first = vim.deepcopy(default_chat_input)
143+
default_chat_input_prefix_first.template =
144+
'{{{language}}}\n{{{tab}}}\n<contextBeforeCursor>\n{{{context_before_cursor}}}<cursorPosition>\n<contextAfterCursor>\n{{{context_after_cursor}}}'
145+
123146
local M = {
124147
-- Enable or disable auto-completion. Note that you still need to add
125148
-- Minuet to your cmp/blink sources. This option controls whether cmp/blink
@@ -231,9 +254,18 @@ M.default_system = {
231254
n_completion_template = n_completion_template,
232255
}
233256

257+
M.default_system_prefix_first = {
258+
template = default_system_template,
259+
prompt = default_prompt_prefix_first,
260+
guidelines = default_guidelines,
261+
n_completion_template = n_completion_template,
262+
}
263+
234264
M.default_chat_input = default_chat_input
265+
M.default_chat_input_prefix_first = default_chat_input_prefix_first
235266

236267
M.default_few_shots = default_few_shots
268+
M.default_few_shots_prefix_first = default_few_shots_prefix_first
237269

238270
M.default_fim_template = {
239271
prompt = default_fim_prompt,
@@ -293,9 +325,9 @@ M.provider_options = {
293325
gemini = {
294326
model = 'gemini-2.0-flash',
295327
api_key = 'GEMINI_API_KEY',
296-
system = M.default_system,
297-
chat_input = M.default_chat_input,
298-
few_shots = M.default_few_shots,
328+
system = M.default_system_prefix_first,
329+
chat_input = M.default_chat_input_prefix_first,
330+
few_shots = M.default_few_shots_prefix_first,
299331
stream = true,
300332
optional = {},
301333
},

prompt.md

+80-12
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
- [Default Template](#default-template)
44
- [Default Prompt](#default-prompt)
55
- [Default Guidelines](#default-guidelines)
6-
- [Default `n_completions` template](#default--n-completions--template)
6+
- [Default `n_completions` template](#default-n_completions-template)
77
- [Default Few Shots Examples](#default-few-shots-examples)
88
- [Default Chat Input Example](#default-chat-input-example)
99
- [Customization](#customization)
10-
- [An Experimental Configuration Setup for Gemini](#an-experimental-configuration-setup-for-gemini)
10+
- [A Practical Example](#a-practical-example)
1111

1212
# FIM LLM Prompt Structure
1313

@@ -42,12 +42,46 @@ tokens within the prompt function.
4242

4343
# Chat LLM Prompt Structure
4444

45+
We utilize two distinct strategies when constructing prompts:
46+
47+
1. **Prefix First Style**: This involves including the code preceding the
48+
cursor initially, followed by the code succeeding the cursor. This approach
49+
is used only for the **Gemini** provider.
50+
51+
2. **Suffix First Style**: This method involves including the code following
52+
the cursor initially, and then the code preceding the cursor. It is employed
53+
for **other** providers such as OpenAI, OpenAI-Compatible, and Claude.
54+
55+
To access the **Suffix First Style** default prompt, use:
56+
57+
1. `require('minuet.config').default_system`
58+
1. `require('minuet.config').default_few_shots`
59+
1. `require('minuet.config').default_chat_input`
60+
61+
To access the **Prefix First Style** default prompt, use:
62+
63+
1. `require('minuet.config').default_system_prefix_first`
64+
1. `require('minuet.config').default_few_shots_prefix_first`
65+
1. `require('minuet.config').default_chat_input_prefix_first`
66+
4567
## Default Template
4668

4769
`{{{prompt}}}\n{{{guidelines}}}\n{{{n_completion_template}}}`
4870

4971
## Default Prompt
5072

73+
**Prefix First Style**:
74+
75+
You are the backend of an AI-powered code completion engine. Your task is to
76+
provide code suggestions based on the user's input. The user's code will be
77+
enclosed in markers:
78+
79+
- `<contextAfterCursor>`: Code context after the cursor
80+
- `<cursorPosition>`: Current cursor location
81+
- `<contextBeforeCursor>`: Code context before the cursor
82+
83+
**Suffix First Style**:
84+
5185
You are the backend of an AI-powered code completion engine. Your task is to
5286
provide code suggestions based on the user's input. The user's code will be
5387
enclosed in markers:
@@ -81,6 +115,7 @@ Guidelines:
81115
## Default Few Shots Examples
82116

83117
```lua
118+
-- suffix first style
84119
local default_few_shots = {
85120
{
86121
role = 'user',
@@ -114,6 +149,22 @@ def fibonacci(n):
114149
]],
115150
},
116151
}
152+
153+
-- prefix first style
154+
local default_few_shots_prefix_first = {
155+
{
156+
role = 'user',
157+
content = [[
158+
# language: python
159+
<contextBeforeCursor>
160+
def fibonacci(n):
161+
<cursorPosition>
162+
<contextAfterCursor>
163+
164+
fib(5)]],
165+
},
166+
default_few_shots[2],
167+
}
117168
```
118169

119170
## Default Chat Input Example
@@ -122,7 +173,27 @@ The chat input represents the final prompt delivered to the LLM for completion.
122173
Its template follows a structured format similar to the system prompt and can
123174
be customized as follows:
124175

125-
`{{{language}}}\n{{{tab}}}\n<contextAfterCursor>\n{{{context_after_cursor}}}\n<contextBeforeCursor>\n{{{context_before_cursor}}}<cursorPosition>`
176+
**Suffix First Style**:
177+
178+
```
179+
{{{language}}}
180+
{{{tab}}}
181+
<contextAfterCursor>
182+
{{{context_after_cursor}}}
183+
<contextBeforeCursor>
184+
{{{context_before_cursor}}}<cursorPosition>
185+
```
186+
187+
**Prefix First Style**:
188+
189+
```
190+
{{{language}}}
191+
{{{tab}}}
192+
<contextBeforeCursor>
193+
{{{context_before_cursor}}}<cursorPosition>
194+
<contextAfterCursor>
195+
{{{context_after_cursor}}}
196+
```
126197

127198
Components:
128199

@@ -207,17 +278,13 @@ require('minuet').setup {
207278
There's no need to replicate unchanged fields. The system will automatically
208279
merge modified fields with default values using the `tbl_deep_extend` function.
209280

210-
## An Experimental Configuration Setup for Gemini
211-
212-
Some observations suggest that Gemini might perform better with a `Prefix-Suffix`
213-
structured input format, specifically `Before-Cursor -> Cursor-Pos -> After-Cursor`.
214-
215-
This contrasts with other chat-based LLMs, which may yield better results with
216-
the inverse structure: `After-Cursor -> Before-Cursor -> Cursor-Pos`.
281+
## A Practical Example
217282

218-
This finding remains experimental and requires further validation.
283+
Here, we present a practical example for configuring the prompt for Gemini,
284+
aiming to reuse existing components of the default prompt wherever possible.
219285

220-
Below is the current configuration used by the maintainer for Gemini:
286+
Please note that you should not copy-paste this into your configuration, as it
287+
represents the **default setting** applied to Gemini.
221288

222289
```lua
223290
local gemini_prompt = [[
@@ -251,6 +318,7 @@ local gemini_chat_input_template =
251318
gemini_few_shots[2] = require('minuet.config').default_few_shots[2]
252319

253320
require('minuet').setup {
321+
provider = 'gemini',
254322
provider_options = {
255323
gemini = {
256324
system = {

0 commit comments

Comments
 (0)