Skip to content

Commit 5c3f1f3

Browse files
committed
Improve LLM prompting
1 parent f1ebff1 commit 5c3f1f3

File tree

2 files changed

+56
-46
lines changed

2 files changed

+56
-46
lines changed

src/Llm.svelte

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -66,29 +66,39 @@
6666
let responsePromise = $state();
6767
let modelName = $state("Gemini");
6868
let template =
69-
$state(`You modify a spreadsheet by executing JavaScript code. You output JavaScript code to run in Markdown blocks. You are a broadly knowledgeable, technical expert.
69+
$state(`You modify a spreadsheet by executing Markdown JavaScript code blocks. You should always output JavaScript that will be executed, and you should always refer to the \\\`llmToolFunctions\\\` object within that code. You NEVER use the tool calling API or function calling API. You are a knowledgeable, technical expert.
7070
71-
First you plan. Then, you operate in a loop of think, query/action, PAUSE, result (sent by the user). You loop until the plan is complete, or until the user gives new instructions. Only the first message contains a plan, steps of the loop do not. If the user gives new instructions, make a new plan.
72-
73-
74-
You can run the following functions:
71+
- First, you plan
72+
- Then you revise the plan to combine as many steps as possible
73+
- Ask follow up questions only about the plan; any later questions should be answered by queries
74+
- Then, you operate in a loop:
75+
- First you think
76+
- Then you do as many queries or actions as you can do in one step
77+
- Then you PAUSE
78+
- Then the results of the queries or actions are returned by the user
79+
- Loop until the plan is complete, or until the user gives new instructions
80+
- Only the first message contains a plan, steps of the loop do not
81+
- If the user gives new instructions, make a new plan
82+
83+
84+
You can run the following JavaScript functions in code blocks:
7585
- \${Object.entries(llmToolFunctions).map(([name, f]) => {
7686
const args = f.toString().replaceAll("\\n", " ").replaceAll(/ */g, " ").match(/\\([^)]*\\)/)?.[0] ?? "";
7787
return \`llmToolFunctions.\${name}\${args} \${f.description ?? ""}\`;
7888
}).join("\\n- ")}
7989
8090
81-
Formulas begin with an equals sign (\\\`=\\\`), and can contain:
82-
- Numbers such as \\\`123\\\` and \\\`-3.21\\\`
83-
- Strings such as \\\`"asdf"\\\` and \\\`"multi\\\\nline"\\\`
84-
- Singleton references in R1C1 notation such as \\\`R10C3\\\` (zero-indexed) and \\\`RC0\\\` for absolute references, \\\`R[-1]c[2]\\\` for relative references, and \\\`RC\\\` for self-references
85-
- Row and column indices are zero-indexed
86-
- Negative absolute references start from the end of a row or column, such as \\\`R-1C-1\\\` to select the cell in the bottom right corner of the sheet, and \\\`R1C0:R1C-1\\\` to select all of row 1
87-
- Ranges such as \\\`R[-3]C:R[-1]C\\\`
91+
Spreadsheet formulas begin with an equals sign (\\\`=\\\`), and can contain:
92+
- Numbers like \\\`123\\\` and \\\`-3.21\\\`
93+
- Strings like \\\`"asdf"\\\` and \\\`"multi\\\\nline"\\\`
94+
- Singleton references in R1C1 notation like \\\`R10C3\\\` (zero-indexed) and \\\`RC0\\\` for absolute references, \\\`R[-1]c[2]\\\` for relative references, and \\\`RC\\\` for self-references
95+
- CRITICAL: Row and column indices are zero-indexed, so R0C0 is the top, left cell
96+
- Negative absolute references start from the end of a row or column, like \\\`R-1C-1\\\` to select the cell in the bottom right corner of the sheet, and \\\`R1C0:R1C-1\\\` to select all of row 1
97+
- Ranges like \\\`R[-3]C:R[-1]C\\\`
8898
- References and ranges across sheets like \\\`S1!R1C1\\\` and \\\`S[1]!R2C2:R2C-1\\\` and \\\`S-1R2C3\\\` (the exclamation point is optional)
8999
- Sheet indices are zero-indexed
90-
- Function calls (case insensitive) containing expressions as arguments such as \\\`sum(RC0:RC[-1])\\\`, \\\`sLiDeR(0, 10, 1)\\\`, and \\\`DOLLARS(PRODUCT(1 * 2 + 3, 4, 3, R[-1]C))\\\`
91-
- Optionally parenthesized binary operations combining any of the expressions above using standard JavaScript arithmetic operations such as \\\`(RC[-2] + RC[-3]) * 100\\\` and \\\`1 + -2 + 3 ** 5\\\`
100+
- Function calls (case insensitive) containing expressions as arguments like \\\`sum(RC0:RC[-1])\\\`, \\\`sLiDeR(0, 10, 1)\\\`, and \\\`DOLLARS(PRODUCT(1 * 2 + 3, 4, 3, R[-1]C))\\\`
101+
- Optionally parenthesized binary operations combining any of the expressions above using standard JavaScript arithmetic operations like \\\`(RC[-2] + RC[-3]) * 100\\\` and \\\`1 + -2 + 3 ** 5\\\`
92102
93103
Formula function definitions have access to a \\\`this\\\` object with:
94104
- this.row and this.col - readonly
@@ -105,52 +115,46 @@ User:
105115
Find the receipt items that contain seafood and make them red.
106116
107117
Model:
108-
Plan: First, I should learn about the current sheets through a query. Then, I should find the items with seafood using another query. Then, I should check if there is already a formula to make items red. If not, I should add one. Finally, I should modify the formulas for the seafood item cells to wrap them in calls to the new red formula.
118+
Plan:
119+
- I should learn about the current sheets through a query.
120+
- I should find the items with seafood using another query.
121+
- I should check if there is already a formula to make items red.
122+
- If not, I should add one.
123+
- I should modify the formulas for the seafood item cells to wrap them in calls to the new red formula.
109124
110125
Thought: I should learn more about the current sheets using a query.
111126
112127
\\\`\\\`\\\`javascript
128+
// Query the current sheets
113129
const sheets = llmToolFunctions.getSheets();
114130
llmToolFunctions.query("Sheets", sheets);
131+
// Query the first rows of each sheet to learn about the columns
115132
let firstRows = {};
116133
sheets.forEach((sheet, sheetIndex) => {
117134
firstRows[sheet.name] = new Array(sheet.cols).fill().map(
118-
(_, i) => llmToolFunctions.getCellFormula(sheetIndex, 0, i)
135+
(_, i) => llmToolFunctions.getCell(sheetIndex, 0, i).formula
119136
)
120137
});
121138
llmToolFunctions.query("First rows", firstRows);
122139
\\\`\\\`\\\`
123140
124-
PAUSE
125-
126141
User:
127142
Sheets: [{"name": "Sheet 1", "rows": 10, "cols": 3}, {"name": "Receipt", "rows": 6, "cols": 2}]
128143
First rows: {"Sheet 1": [null, null, null], "Receipt": ["=BOLD(\\\\"Item\\\\")", "=BOLD(\\\\"Cost\\\\")"]}
129144
130145
Model:
131146
Thought: I should find the cells that might contain seafood. I now know that I can identify them by the "Item" column.
147+
Thought: I can also query the formulas at the same time to check and see if there is already a formula to make items red.
132148
133149
\\\`\\\`\\\`javascript
134150
llmToolFunctions.query("Items", new Array(6).fill().map(
135-
(_, i) => llmToolFunctions.getCellFormula(1, i, 0)
151+
(_, i) => llmToolFunctions.getCell(1, i, 0).formula
136152
));
137-
\\\`\\\`\\\`
138-
139-
PAUSE
140-
141-
User:
142-
Items: ["=BOLD(\\\\"Items\\\\")", "shrimp", "chicken", "vegetables", "scallops", "cups"]
143-
144-
Model:
145-
Thought: Now that I know which rows contain seafood, I should check to see if there is already a formula to make items red.
146-
147-
\\\`\\\`\\\`javascript
148153
llmToolFunctions.query("Formulas", llmToolFunctions.getFormulaFunctionsList());
149154
\\\`\\\`\\\`
150155
151-
PAUSE
152-
153156
User:
157+
Items: ["=BOLD(\\\\"Items\\\\")", "shrimp", "chicken", "vegetables", "scallops", "cups"]
154158
Formulas: [ "abs", "acos", ..., "average", "rand", "slider", "bold", "center", "dollars", "sparkbars", "checkbox" ]
155159
156160
Model:
@@ -163,10 +167,11 @@ functions.red = function (s) {
163167
return s;
164168
}
165169
\\\`);
166-
llmToolFunctions.setCellFormula(1, 1, 0, \\\`=RED(\\\${llmToolFunctions.getCellFormula(1, 1, 0)})\\\`)
167-
llmToolFunctions.setCellFormula(1, 4, 0, \\\`=RED(\\\${llmToolFunctions.getCellFormula(1, 4, 0)})\\\`)
170+
llmToolFunctions.setCellFormula(1, 1, 0, \\\`=RED(\\\${llmToolFunctions.getCell(1, 1, 0).formula})\\\`)
171+
llmToolFunctions.setCellFormula(1, 4, 0, \\\`=RED(\\\${llmToolFunctions.getCell(1, 4, 0).formula})\\\`)
168172
\\\`\\\`\\\`
169173
`);
174+
170175
let conversation = $state([
171176
{ role: "system", text: "" },
172177
{ role: "user", text: "" },
@@ -198,7 +203,10 @@ llmToolFunctions.setCellFormula(1, 4, 0, \\\`=RED(\\\${llmToolFunctions.getCellF
198203
.request(conversationSlice)
199204
.then((parts) =>
200205
parts.map((part) => {
201-
if (part.startsWith("```") && part.endsWith("```")) {
206+
if (
207+
part.match(/^````*( *javascript *)?\n/) &&
208+
part.endsWith("\n```")
209+
) {
202210
return {
203211
role: "model",
204212
code: part
@@ -218,15 +226,16 @@ llmToolFunctions.setCellFormula(1, 4, 0, \\\`=RED(\\\${llmToolFunctions.getCellF
218226
});
219227
}
220228
221-
function execute(llmCode, i) {
229+
function execute(llmCode, codeIndex) {
222230
llmToolFunctions.globals = globals;
223231
224232
llmToolFunctions.query = (name, value) => {
225233
let userResponse;
234+
let i = codeIndex;
226235
for (
227-
userResponse = conversation[i + 1];
228-
userResponse != null && userResponse.role != "user";
229-
i++
236+
userResponse = conversation[++i];
237+
i < conversation.length && userResponse.role != "user";
238+
userResponse = conversation[++i]
230239
) {}
231240
if (userResponse.text.length && !userResponse.text.endsWith("\n")) {
232241
userResponse.text += "\n";

src/llm.svelte.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ llmToolFunctions.addFunction = function (code) {
2525
llmToolFunctions.addFunction.description =
2626
"set functions.formula_name to a new JavaScript function in code to add a formula function";
2727

28-
llmToolFunctions.getCellValue = function (sheetIndex, row, col) {
29-
return this.globals.sheets[sheetIndex]?.cells[row]?.[col]?.get();
30-
};
31-
32-
llmToolFunctions.getCellFormula = function (sheetIndex, row, col) {
33-
return this.globals.sheets[sheetIndex]?.cells[row]?.[col]?.formula ?? "";
28+
llmToolFunctions.getCell = function (sheetIndex, row, col) {
29+
const cell = this.globals.sheets[sheetIndex]?.cells[row]?.[col];
30+
return {
31+
value: cell?.get(),
32+
formula: cell?.formula ?? "",
33+
};
3434
};
35+
llmToolFunctions.getCell.description =
36+
"returns a cell object with a value and formula fields";
3537

3638
llmToolFunctions.setCellFormula = function (sheetIndex, row, col, formula) {
3739
this.globals.sheets[sheetIndex].cells[row][col].formula = formula;
@@ -73,7 +75,6 @@ llmModels.Gemini = {
7375
body: JSON.stringify({
7476
generation_config: {
7577
temperature: 0.3,
76-
stop_sequences: ["PAUSE"],
7778
},
7879
system_instruction: {
7980
parts: conversation

0 commit comments

Comments
 (0)