Skip to content

Commit 7e77995

Browse files
committed
frontend/jupyter/llm: fix ai cell generator context selection
1 parent fe4813b commit 7e77995

File tree

12 files changed

+219
-178
lines changed

12 files changed

+219
-178
lines changed

src/packages/frontend/components/raw-prompt.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { CSS } from "@cocalc/frontend/app-framework";
22
import { useBottomScroller } from "@cocalc/frontend/app-framework/use-bottom-scroller";
3-
import { COLORS } from "@cocalc/util/theme";
4-
import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown";
53
import { Paragraph } from "@cocalc/frontend/components";
4+
import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown";
5+
import { COLORS } from "@cocalc/util/theme";
66

77
const STYLE = {
88
border: "1px solid lightgrey",
@@ -21,18 +21,20 @@ interface Props {
2121
input: React.JSX.Element | string;
2222
style?: CSS;
2323
scrollBottom?: boolean;
24+
rawText?: boolean;
2425
}
2526

2627
export function RawPrompt({
2728
input,
2829
style: style0,
2930
scrollBottom = false,
31+
rawText = false,
3032
}: Props) {
3133
const ref = useBottomScroller(scrollBottom, input);
3234
const style = { ...STYLE, ...style0 };
33-
if (typeof input == "string") {
35+
if (typeof input == "string" && !rawText) {
3436
// this looks so much nicer; I realize it doesn't implement scrollBottom.
35-
// But just dropping the input as plain text like below just seems
37+
// But just dropping the input as plain text like below just seems
3638
// utterly broken!
3739
return <StaticMarkdown style={style} value={input} />;
3840
} else {

src/packages/frontend/cspell.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
"language": "en",
44
"enabled": true,
55
"words": [
6+
"ANOVA",
7+
"ARIMA",
68
"autograde",
79
"autograding",
810
"Bioconductor",
11+
"bioinformatics",
912
"CoCalc",
1013
"conat",
1114
"dplyr",
1215
"formatjs",
16+
"geospatial",
1317
"ggplot",
1418
"ipython",
1519
"ipywidgets",
@@ -36,13 +40,15 @@
3640
"sagews",
3741
"scikit",
3842
"simplelocalize",
43+
"sklearn",
3944
"SocketIO",
4045
"statsmodels",
4146
"syncdb",
4247
"syncdoc",
4348
"syncstring",
4449
"synctable",
4550
"synctables",
51+
"tidymodels",
4652
"tidyverse",
4753
"timetravel",
4854
"tolerations",

src/packages/frontend/jupyter/_jupyter.sass

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
.cocalc-jupyter-insert-cell
6969
margin-bottom: 10px
7070
height: 8px
71-
margin-top: 8px
71+
margin-top: 10px
7272
cursor: pointer
7373
text-align: center
7474
&:hover
@@ -111,4 +111,4 @@
111111
// %matplotlib widgets
112112
// from pylab import plot; plot([1,2],[3,4])
113113
cocalc-lumino-adapter
114-
position: relative
114+
position: relative

src/packages/frontend/jupyter/cell-buttonbar.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
RUN_ALL_CELLS_ABOVE_ICON,
3232
RUN_ALL_CELLS_BELOW_ICON,
3333
} from "./consts";
34-
import { LLMCellTool } from "./llm";
34+
import { LLMCellTool } from "./llm/cell-tool";
3535

3636
interface Props {
3737
id: string;
@@ -193,7 +193,14 @@ export const CellButtonBar: React.FC<Props> = React.memo(
193193

194194
function renderCodeBarLLMButtons() {
195195
if (!llmTools || !haveLLMCellTools || is_readonly) return;
196-
return <LLMCellTool id={id} actions={actions} llmTools={llmTools} cellType={isCodeCell ? "code" : "markdown"} />;
196+
return (
197+
<LLMCellTool
198+
id={id}
199+
actions={actions}
200+
llmTools={llmTools}
201+
cellType={isCodeCell ? "code" : "markdown"}
202+
/>
203+
);
197204
}
198205

199206
function renderCodeBarFormatButton() {

src/packages/frontend/jupyter/insert-cell/ai-cell-generator.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { labels } from "@cocalc/frontend/i18n";
4040
import { JupyterActions } from "@cocalc/frontend/jupyter/browser-actions";
4141
import { LLMCellContextSelector } from "@cocalc/frontend/jupyter/llm/cell-context-selector";
4242
import { splitCells } from "@cocalc/frontend/jupyter/llm/split-cells";
43+
import { backtickSequence } from "@cocalc/frontend/markdown/util";
4344
import { LLMCostEstimation } from "@cocalc/frontend/misc/llm-cost-estimation";
4445
import { useProjectContext } from "@cocalc/frontend/project/context";
4546
import { LLMEvent } from "@cocalc/frontend/project/history/types";
@@ -207,16 +208,17 @@ export function AIGenerateCodeCell({
207208
const aboveCount = rangeStart < 0 ? Math.abs(rangeStart) : 0;
208209
const belowCount = rangeEnd > 0 ? rangeEnd : 0;
209210

210-
return getNonemptyCellContents({
211+
const result = getNonemptyCellContents({
211212
actions: frameActions.current,
212213
id,
213-
direction: "around",
214-
cellCount: "all",
215214
cellTypes,
216215
lang,
217216
aboveCount,
218217
belowCount,
218+
includeCurrentCellInAbove: true,
219219
});
220+
221+
return result;
220222
}
221223

222224
function insertCells() {
@@ -454,6 +456,7 @@ export function AIGenerateCodeCell({
454456
onCellTypesChange={setCellTypes}
455457
currentCellId={id}
456458
frameActions={frameActions.current}
459+
mode="insertion"
457460
/>
458461
</>
459462
);
@@ -574,6 +577,7 @@ export function AIGenerateCodeCell({
574577
children: (
575578
<RawPrompt
576579
input={raw}
580+
rawText
577581
style={{ border: "none", padding: "0", margin: "0" }}
578582
/>
579583
),
@@ -729,11 +733,13 @@ function getInput({
729733
contextInfo = `Context: The new cell will be inserted with ${beforeCells} and ${afterCells} the insertion point.\n\n`;
730734

731735
if (contextContent.before) {
732-
contextInfo += `Cells BEFORE insertion point:\n<before>\n${contextContent.before}\n</before>\n\n`;
736+
const beforeDelim = backtickSequence(contextContent.before);
737+
contextInfo += `Cells BEFORE insertion point:\n\n${beforeDelim}\n${contextContent.before}\n${beforeDelim}\n\n`;
733738
}
734739

735740
if (contextContent.after) {
736-
contextInfo += `Cells AFTER insertion point:\n<after>\n${contextContent.after}\n</after>\n\n`;
741+
const afterDelim = backtickSequence(contextContent.after);
742+
contextInfo += `Cells AFTER insertion point:\n\n${afterDelim}\n${contextContent.after}\n${afterDelim}\n\n`;
737743
}
738744
} else {
739745
contextInfo =

src/packages/frontend/jupyter/insert-cell/index.tsx

Lines changed: 74 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ buttons in the hover state (even when tacking mouse moves!),
1212
which is confusing.
1313
*/
1414

15+
// cSpell:ignore aicell
16+
1517
import { Button, Space, Tooltip } from "antd";
1618
import { ReactNode } from "react";
1719

@@ -96,6 +98,65 @@ export function InsertCell({
9698
classNames.push("cocalc-jupyter-insert-cell-below");
9799
}
98100

101+
const isActiveAIGenerator = !hide && showAICellGen === position;
102+
103+
function renderControls() {
104+
return (
105+
<div
106+
className="cocalc-jupyter-insert-cell-controls"
107+
style={
108+
showAICellGen || alwaysShow
109+
? {
110+
visibility: "visible",
111+
opacity: 1,
112+
}
113+
: undefined
114+
}
115+
>
116+
<Space size="large">
117+
<TinyButton
118+
type="code"
119+
title="Insert code cell (click line)"
120+
handleButtonClick={handleButtonClick}
121+
>
122+
<Icon name="code" /> Code
123+
</TinyButton>
124+
<TinyButton
125+
type="markdown"
126+
title="Insert text cell (shift+click line)"
127+
handleButtonClick={handleButtonClick}
128+
>
129+
<Icon name="pen" /> Text
130+
</TinyButton>
131+
<TinyButton
132+
type="paste"
133+
title="Insert clipboard content as cell"
134+
handleButtonClick={handleButtonClick}
135+
>
136+
<Icon name="paste" /> Paste
137+
</TinyButton>
138+
{showGenerateCell && llmTools && (
139+
<TinyButton
140+
type="aicell"
141+
title="Create code based on your description (alt+click line)"
142+
handleButtonClick={handleButtonClick}
143+
>
144+
<Space>
145+
<AIAvatar
146+
backgroundColor={"transparent"}
147+
size={14}
148+
innerStyle={{ color: "default", top: "-2px" }}
149+
/>
150+
Generate...
151+
</Space>
152+
</TinyButton>
153+
)}
154+
</Space>
155+
</div>
156+
);
157+
}
158+
159+
// the AIGenerateCodeCell is only rendered if active – otherwise that dialog is rendered for each cell insertion line
99160
return (
100161
<div
101162
className={classNames.join(" ")}
@@ -105,66 +166,20 @@ export function InsertCell({
105166
}}
106167
onClick={showAICellGen ? undefined : handleBarClick}
107168
>
108-
<AIGenerateCodeCell
109-
setShowAICellGen={setShowAICellGen}
110-
showAICellGen={!hide ? showAICellGen : null}
111-
actions={actions}
112-
frameActions={frameActions}
113-
id={id}
114-
llmTools={llmTools}
115-
>
116-
<div
117-
className="cocalc-jupyter-insert-cell-controls"
118-
style={
119-
showAICellGen || alwaysShow
120-
? {
121-
visibility: "visible",
122-
opacity: 1,
123-
}
124-
: undefined
125-
}
169+
{isActiveAIGenerator ? (
170+
<AIGenerateCodeCell
171+
setShowAICellGen={setShowAICellGen}
172+
showAICellGen={showAICellGen}
173+
actions={actions}
174+
frameActions={frameActions}
175+
id={id}
176+
llmTools={llmTools}
126177
>
127-
<Space size="large">
128-
<TinyButton
129-
type="code"
130-
title="Insert code cell (click line)"
131-
handleButtonClick={handleButtonClick}
132-
>
133-
<Icon name="code" /> Code
134-
</TinyButton>
135-
<TinyButton
136-
type="markdown"
137-
title="Insert text cell (shift+click line)"
138-
handleButtonClick={handleButtonClick}
139-
>
140-
<Icon name="pen" /> Text
141-
</TinyButton>
142-
<TinyButton
143-
type="paste"
144-
title="Insert clipboard content as cell"
145-
handleButtonClick={handleButtonClick}
146-
>
147-
<Icon name="paste" /> Paste
148-
</TinyButton>
149-
{showGenerateCell && llmTools && (
150-
<TinyButton
151-
type="aicell"
152-
title="Create code based on your description (alt+click line)"
153-
handleButtonClick={handleButtonClick}
154-
>
155-
<Space>
156-
<AIAvatar
157-
backgroundColor={"transparent"}
158-
size={14}
159-
innerStyle={{ color: "default", top: "-2px" }}
160-
/>
161-
Generate...
162-
</Space>
163-
</TinyButton>
164-
)}
165-
</Space>
166-
</div>
167-
</AIGenerateCodeCell>
178+
{renderControls()}
179+
</AIGenerateCodeCell>
180+
) : (
181+
renderControls()
182+
)}
168183
</div>
169184
);
170185
}

0 commit comments

Comments
 (0)