From 44b2040b5a50a988f1e8d5dd10d6dcd62407a7d4 Mon Sep 17 00:00:00 2001 From: alyssabull Date: Wed, 7 Feb 2024 22:20:44 -0700 Subject: [PATCH 1/8] Style history --- go.mod | 3 +- go.sum | 2 - src/components/QueryEditor/OpenAIEditor.tsx | 89 +++++++++++++++++--- src/components/QueryEditor/PromptHistory.tsx | 89 ++++++++++++++++++++ 4 files changed, 168 insertions(+), 15 deletions(-) create mode 100644 src/components/QueryEditor/PromptHistory.tsx diff --git a/go.mod b/go.mod index ecb15db1..e84e6210 100644 --- a/go.mod +++ b/go.mod @@ -7,12 +7,10 @@ toolchain go1.21.4 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 - github.com/google/go-cmp v0.6.0 github.com/grafana/grafana-azure-sdk-go v1.10.0 github.com/grafana/grafana-plugin-sdk-go v0.198.0 github.com/json-iterator/go v1.1.12 github.com/stretchr/testify v1.8.4 - github.com/xorcare/pointer v1.2.2 golang.org/x/net v0.20.0 ) @@ -40,6 +38,7 @@ require ( github.com/golang-jwt/jwt/v5 v5.0.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/flatbuffers v23.1.21+incompatible // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.5.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect diff --git a/go.sum b/go.sum index 487d1f8b..ee53fa34 100644 --- a/go.sum +++ b/go.sum @@ -242,8 +242,6 @@ github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3/go.mod h1:1xEUf2abjfP9 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= -github.com/xorcare/pointer v1.2.2 h1:zjD77b5DTehClND4MK+9dDE0DcpFIZisAJ/+yVJvKYA= -github.com/xorcare/pointer v1.2.2/go.mod h1:azsKh7oVwYB7C1o8P284fG8MvtErX/F5/dqXiaj71ak= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= diff --git a/src/components/QueryEditor/OpenAIEditor.tsx b/src/components/QueryEditor/OpenAIEditor.tsx index 51c5db9e..3e70f095 100644 --- a/src/components/QueryEditor/OpenAIEditor.tsx +++ b/src/components/QueryEditor/OpenAIEditor.tsx @@ -11,6 +11,11 @@ import { useStyles2, TextArea, HorizontalGroup, + Field, + Switch, + Tooltip, + CustomScrollbar, + Icon, } from '@grafana/ui'; import { AdxDataSource } from 'datasource'; import React, { ChangeEvent, useEffect, useState } from 'react'; @@ -21,6 +26,7 @@ import { css } from '@emotion/css'; import { useAsync } from 'react-use'; import { getFunctions, getSignatureHelp } from './Suggestions'; +import { PromptHistory } from './PromptHistory'; type Props = QueryEditorProps; @@ -47,9 +53,20 @@ export const OpenAIEditor: React.FC = (props) => { const [generatedQuery, setGeneratedQuery] = useState('//OpenAI generated query'); const [variables] = useState(getTemplateSrv().getVariables()); const [stateSchema, setStateSchema] = useState(cloneDeep(schema)); + const [showQueryHistory, setShowQueryHistory] = useState(false); + const [parsedStoredPrompts, setParsedStoredPrompts] = useState([]); const styles = useStyles2(getStyles); const baselinePrompt = `You are an AI assistant that is fluent in KQL for querying Azure Data Explorer and you only respond with the correct KQL code snippets and no explanations. Generate a query that fulfills the following text.\nText:"""`; + useEffect(() => { + const currentStoredPrompts = localStorage.getItem('storedOpenAIPrompts'); + let allParsedStoredPrompts = []; + if (currentStoredPrompts !== null) { + allParsedStoredPrompts = JSON.parse(currentStoredPrompts); + }; + setParsedStoredPrompts(allParsedStoredPrompts); + }, []) + useAsync(async () => { const enabled = await llms.openai.enabled(); setEnabled(enabled); @@ -71,6 +88,18 @@ export const OpenAIEditor: React.FC = (props) => { } }, [schema, stateSchema]); + const addPromptToLocalStorage = () => { + let allPrompts; + if (parsedStoredPrompts.length > 0) { + allPrompts = [...parsedStoredPrompts, prompt]; + } else { + allPrompts = [prompt]; + }; + const stringifiedPrompts = JSON.stringify(allPrompts); + localStorage.setItem("storedOpenAIPrompts", stringifiedPrompts); + setParsedStoredPrompts(allPrompts); + }; + const generateQuery = () => { reportInteraction('grafana_ds_adx_openai_query_generated'); setWaiting(true); @@ -83,7 +112,6 @@ export const OpenAIEditor: React.FC = (props) => { .generateQueryForOpenAI(`${baselinePrompt}${prompt}"""`) .then((resp) => { setWaiting(false); - setGeneratedQuery(resp); }) .catch((e) => { setWaiting(false); @@ -111,6 +139,10 @@ export const OpenAIEditor: React.FC = (props) => { setGeneratedQuery(m); }, complete: () => { + if (prompt !== "") { + addPromptToLocalStorage(); + setPrompt(''); + }; setWaiting(false); }, error: (e) => { @@ -175,7 +207,14 @@ export const OpenAIEditor: React.FC = (props) => { if (!stateSchema) { return null; - } + }; + + const useStoredPrompt = (prompt: string) => { + setShowQueryHistory(false); + setPrompt(prompt); + onRawQueryChange(prompt); + onRunQuery(); + }; return (
@@ -221,13 +260,37 @@ export const OpenAIEditor: React.FC = (props) => { > {isWaiting && } Generate query + +
+
+ + + +
+ setShowQueryHistory(!showQueryHistory)}> +
+
- + {showQueryHistory ? ( + + + + ) : ( + + )}
@@ -274,9 +337,6 @@ const getStyles = (theme: GrafanaTheme2) => { color: theme.colors.text.link, textDecoration: 'underline', }), - innerMargin: css({ - marginTop: theme.spacing(2), - }), editorSpace: css({ paddingTop: theme.spacing(1), }), @@ -289,5 +349,12 @@ const getStyles = (theme: GrafanaTheme2) => { dividerSpace: css({ marginTop: theme.spacing(4), }), + textArea: css({ + marginTop: theme.spacing(2), + height: '100px' + }), + settingsIcon: css` + color: ${theme.colors.text.secondary}; + `, }; }; diff --git a/src/components/QueryEditor/PromptHistory.tsx b/src/components/QueryEditor/PromptHistory.tsx new file mode 100644 index 00000000..198ffe83 --- /dev/null +++ b/src/components/QueryEditor/PromptHistory.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { Button, Icon, useStyles2 } from "@grafana/ui"; +import { v4 as uuidv4 } from 'uuid'; +import { css } from '@emotion/css'; +import { GrafanaTheme2 } from '@grafana/data'; + +export const PromptHistory = ({ parsedStoredPrompts, useStoredPrompt, setParsedStoredPrompts, setShowQueryHistory }) => { + const NO_STORED_PROMPTS_MESSAGE = "No prompts stored in history. When you write a prompt and click generate query, the prompt will be stored here."; + const styles = useStyles2(getStyles); + + const removePrompt = (prompt: string) => { + const updatedPrompts = parsedStoredPrompts.filter((p) => p !== prompt); + const stringifiedPrompts = JSON.stringify(updatedPrompts); + localStorage.setItem("storedOpenAIPrompts", stringifiedPrompts); + setParsedStoredPrompts(updatedPrompts); + }; + + const useSelectedPrompt = (prompt: string) => { + useStoredPrompt(prompt); + setShowQueryHistory(false); + }; + + const generatePromptCards = ( ) => { + if (parsedStoredPrompts.length > 0) { + return parsedStoredPrompts.map((prompt) => { + return( +
+
+
+
+
{prompt}
+ +
+
+ ) + }) + } else { + return ( +
+
+ +
+
+ {NO_STORED_PROMPTS_MESSAGE} +
+
+ ) + }; + }; + + return( +
+ {generatePromptCards()} +
+ ) +}; + +const getStyles = (theme: GrafanaTheme2) => ({ + wrapper: css({ + marginTop: theme.spacing(2), + background: theme.colors.background.secondary, + display: 'flex', + }), + icon: css({ + background: theme.colors.error.main, + color: theme.colors.error.contrastText, + padding: theme.spacing(1), + }), + message: css({ + fontSize: theme.typography.bodySmall.fontSize, + fontFamily: theme.typography.fontFamilyMonospace, + padding: theme.spacing(1), + }), + }); From 72dd81d26ea18f56ba2fed8ef9fc1d6b32d733f8 Mon Sep 17 00:00:00 2001 From: alyssabull Date: Wed, 7 Feb 2024 22:31:16 -0700 Subject: [PATCH 2/8] Fix scrollbar --- src/components/QueryEditor/OpenAIEditor.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/QueryEditor/OpenAIEditor.tsx b/src/components/QueryEditor/OpenAIEditor.tsx index 3e70f095..6b62a242 100644 --- a/src/components/QueryEditor/OpenAIEditor.tsx +++ b/src/components/QueryEditor/OpenAIEditor.tsx @@ -275,7 +275,7 @@ export const OpenAIEditor: React.FC = (props) => {
{showQueryHistory ? ( - + Date: Wed, 7 Feb 2024 22:32:01 -0700 Subject: [PATCH 3/8] Fix conflict --- go.mod | 3 ++- go.sum | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index e84e6210..ecb15db1 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,12 @@ toolchain go1.21.4 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 + github.com/google/go-cmp v0.6.0 github.com/grafana/grafana-azure-sdk-go v1.10.0 github.com/grafana/grafana-plugin-sdk-go v0.198.0 github.com/json-iterator/go v1.1.12 github.com/stretchr/testify v1.8.4 + github.com/xorcare/pointer v1.2.2 golang.org/x/net v0.20.0 ) @@ -38,7 +40,6 @@ require ( github.com/golang-jwt/jwt/v5 v5.0.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/flatbuffers v23.1.21+incompatible // indirect - github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.5.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect diff --git a/go.sum b/go.sum index ee53fa34..487d1f8b 100644 --- a/go.sum +++ b/go.sum @@ -242,6 +242,8 @@ github.com/unknwon/log v0.0.0-20150304194804-e617c87089d3/go.mod h1:1xEUf2abjfP9 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= +github.com/xorcare/pointer v1.2.2 h1:zjD77b5DTehClND4MK+9dDE0DcpFIZisAJ/+yVJvKYA= +github.com/xorcare/pointer v1.2.2/go.mod h1:azsKh7oVwYB7C1o8P284fG8MvtErX/F5/dqXiaj71ak= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= From da5f06e0bdc4d45f41ea5d9936a4a9b6ce2006a3 Mon Sep 17 00:00:00 2001 From: alyssabull Date: Wed, 7 Feb 2024 22:35:58 -0700 Subject: [PATCH 4/8] Update spellcheck --- cspell.config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cspell.config.json b/cspell.config.json index 33aff112..6ba75ba6 100644 --- a/cspell.config.json +++ b/cspell.config.json @@ -162,6 +162,6 @@ "Ymin", "llms", "proxying", - "" + "uuidv" ] } From 4afac322c7d16c7aafdbbcfa7ef4e6e1de85399c Mon Sep 17 00:00:00 2001 From: Alyssa Bull <58453566+alyssabull@users.noreply.github.com> Date: Thu, 8 Feb 2024 08:00:05 -0700 Subject: [PATCH 5/8] Update src/components/QueryEditor/OpenAIEditor.tsx Co-authored-by: Adam Yeats <16296989+adamyeats@users.noreply.github.com> --- src/components/QueryEditor/OpenAIEditor.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/QueryEditor/OpenAIEditor.tsx b/src/components/QueryEditor/OpenAIEditor.tsx index 6b62a242..8d9be81d 100644 --- a/src/components/QueryEditor/OpenAIEditor.tsx +++ b/src/components/QueryEditor/OpenAIEditor.tsx @@ -60,10 +60,7 @@ export const OpenAIEditor: React.FC = (props) => { useEffect(() => { const currentStoredPrompts = localStorage.getItem('storedOpenAIPrompts'); - let allParsedStoredPrompts = []; - if (currentStoredPrompts !== null) { - allParsedStoredPrompts = JSON.parse(currentStoredPrompts); - }; + const allParsedStoredPrompts = currentStoredPrompts !== null ? JSON.parse(currentStoredPrompts) : [] setParsedStoredPrompts(allParsedStoredPrompts); }, []) From 759d18ade9c83475223ea8e8beabe3a8ffdaa369 Mon Sep 17 00:00:00 2001 From: Alyssa Bull <58453566+alyssabull@users.noreply.github.com> Date: Thu, 8 Feb 2024 08:00:17 -0700 Subject: [PATCH 6/8] Update src/components/QueryEditor/OpenAIEditor.tsx Co-authored-by: Adam Yeats <16296989+adamyeats@users.noreply.github.com> --- src/components/QueryEditor/OpenAIEditor.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/QueryEditor/OpenAIEditor.tsx b/src/components/QueryEditor/OpenAIEditor.tsx index 8d9be81d..0e62163b 100644 --- a/src/components/QueryEditor/OpenAIEditor.tsx +++ b/src/components/QueryEditor/OpenAIEditor.tsx @@ -86,12 +86,7 @@ export const OpenAIEditor: React.FC = (props) => { }, [schema, stateSchema]); const addPromptToLocalStorage = () => { - let allPrompts; - if (parsedStoredPrompts.length > 0) { - allPrompts = [...parsedStoredPrompts, prompt]; - } else { - allPrompts = [prompt]; - }; + const allPrompts = parsedStoredPrompts.length > 0 ? [...parsedStoredPrompts, prompt] : [prompt]; const stringifiedPrompts = JSON.stringify(allPrompts); localStorage.setItem("storedOpenAIPrompts", stringifiedPrompts); setParsedStoredPrompts(allPrompts); From 2321e7bc891da70611e14a3ad774f9fc140a5c3b Mon Sep 17 00:00:00 2001 From: Alyssa Bull <58453566+alyssabull@users.noreply.github.com> Date: Thu, 8 Feb 2024 08:00:31 -0700 Subject: [PATCH 7/8] Update src/components/QueryEditor/PromptHistory.tsx Co-authored-by: Adam Yeats <16296989+adamyeats@users.noreply.github.com> --- src/components/QueryEditor/PromptHistory.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/QueryEditor/PromptHistory.tsx b/src/components/QueryEditor/PromptHistory.tsx index 198ffe83..6dfc7096 100644 --- a/src/components/QueryEditor/PromptHistory.tsx +++ b/src/components/QueryEditor/PromptHistory.tsx @@ -22,8 +22,7 @@ export const PromptHistory = ({ parsedStoredPrompts, useStoredPrompt, setParsedS const generatePromptCards = ( ) => { if (parsedStoredPrompts.length > 0) { - return parsedStoredPrompts.map((prompt) => { - return( + return parsedStoredPrompts.map((prompt) => (
) - }) + ) } else { return (
From e501b740724cb6775d448fe383308a525e74fa2f Mon Sep 17 00:00:00 2001 From: alyssabull Date: Thu, 8 Feb 2024 08:06:05 -0700 Subject: [PATCH 8/8] Fix typo --- src/components/QueryEditor/OpenAIEditor.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/QueryEditor/OpenAIEditor.tsx b/src/components/QueryEditor/OpenAIEditor.tsx index 0e62163b..63141437 100644 --- a/src/components/QueryEditor/OpenAIEditor.tsx +++ b/src/components/QueryEditor/OpenAIEditor.tsx @@ -86,10 +86,9 @@ export const OpenAIEditor: React.FC = (props) => { }, [schema, stateSchema]); const addPromptToLocalStorage = () => { - const allPrompts = parsedStoredPrompts.length > 0 ? [...parsedStoredPrompts, prompt] : [prompt]; + const allPrompts = parsedStoredPrompts.length > 0 ? [...parsedStoredPrompts, prompt] : [prompt]; const stringifiedPrompts = JSON.stringify(allPrompts); localStorage.setItem("storedOpenAIPrompts", stringifiedPrompts); - setParsedStoredPrompts(allPrompts); }; const generateQuery = () => {