From 714aec2275f8df1e517a45e50ecf16bd8ca0e9c3 Mon Sep 17 00:00:00 2001 From: Nathan Marrs <nathanielmarrs@gmail.com> Date: Tue, 31 Oct 2023 13:52:46 -0600 Subject: [PATCH] Auto-generate: Update generation character limits, improve generation history UX (#76849) --- .../GenAI/GenAIDashDescriptionButton.tsx | 4 +++- .../components/GenAI/GenAIDashTitleButton.tsx | 4 +++- .../components/GenAI/GenAIHistory.tsx | 3 +-- .../GenAI/GenAIPanelDescriptionButton.tsx | 6 ++++-- .../GenAI/GenAIPanelTitleButton.tsx | 21 +++++++------------ .../GenAI/MinimalisticPagination.tsx | 1 + .../dashboard/components/GenAI/utils.ts | 15 +++++++++++++ 7 files changed, 34 insertions(+), 20 deletions(-) diff --git a/public/app/features/dashboard/components/GenAI/GenAIDashDescriptionButton.tsx b/public/app/features/dashboard/components/GenAI/GenAIDashDescriptionButton.tsx index b039735c06e..4f9cc429ed0 100644 --- a/public/app/features/dashboard/components/GenAI/GenAIDashDescriptionButton.tsx +++ b/public/app/features/dashboard/components/GenAI/GenAIDashDescriptionButton.tsx @@ -11,6 +11,8 @@ interface GenAIDashDescriptionButtonProps { dashboard: DashboardModel; } +const DASHBOARD_DESCRIPTION_CHAR_LIMIT = 300; + const DESCRIPTION_GENERATION_STANDARD_PROMPT = 'You are an expert in creating Grafana Dashboards.\n' + 'Your goal is to write a descriptive and concise dashboard description.\n' + @@ -19,7 +21,7 @@ const DESCRIPTION_GENERATION_STANDARD_PROMPT = 'If the dashboard has no panels, the description should be "Empty dashboard"\n' + 'There should be no numbers in the description except where they are important.\n' + 'The dashboard description should not have the dashboard title or any quotation marks in it.\n' + - 'The description should be, at most, 140 characters.\n' + + `The description should be, at most, ${DASHBOARD_DESCRIPTION_CHAR_LIMIT} characters.\n` + 'Respond with only the description of the dashboard.'; export const GenAIDashDescriptionButton = ({ onGenerate, dashboard }: GenAIDashDescriptionButtonProps) => { diff --git a/public/app/features/dashboard/components/GenAI/GenAIDashTitleButton.tsx b/public/app/features/dashboard/components/GenAI/GenAIDashTitleButton.tsx index f39e7ce37bd..cebd5cb9478 100644 --- a/public/app/features/dashboard/components/GenAI/GenAIDashTitleButton.tsx +++ b/public/app/features/dashboard/components/GenAI/GenAIDashTitleButton.tsx @@ -11,6 +11,8 @@ interface GenAIDashTitleButtonProps { onGenerate: (description: string) => void; } +const DASH_TITLE_CHAR_LIMIT = 50; + const TITLE_GENERATION_STANDARD_PROMPT = 'You are an expert in creating Grafana Dashboards.\n' + 'Your goal is to write a concise dashboard title.\n' + @@ -19,7 +21,7 @@ const TITLE_GENERATION_STANDARD_PROMPT = 'If the dashboard has no panels, the title should be "Empty dashboard"\n' + 'There should be no numbers in the title.\n' + 'The dashboard title should not have quotation marks in it.\n' + - 'The title should be, at most, 50 characters.\n' + + `The title should be, at most, ${DASH_TITLE_CHAR_LIMIT} characters.\n` + 'Respond with only the title of the dashboard.'; export const GenAIDashTitleButton = ({ onGenerate, dashboard }: GenAIDashTitleButtonProps) => { diff --git a/public/app/features/dashboard/components/GenAI/GenAIHistory.tsx b/public/app/features/dashboard/components/GenAI/GenAIHistory.tsx index 51a2d1072e3..71006a897d0 100644 --- a/public/app/features/dashboard/components/GenAI/GenAIHistory.tsx +++ b/public/app/features/dashboard/components/GenAI/GenAIHistory.tsx @@ -16,12 +16,11 @@ import { VerticalGroup, } from '@grafana/ui'; -import { getFeedbackMessage } from './GenAIPanelTitleButton'; import { GenerationHistoryCarousel } from './GenerationHistoryCarousel'; import { QuickFeedback } from './QuickFeedback'; import { StreamStatus, useOpenAIStream } from './hooks'; import { AutoGenerateItem, EventTrackingSrc, reportAutoGenerateInteraction } from './tracking'; -import { Message, DEFAULT_OAI_MODEL, QuickFeedbackType, sanitizeReply } from './utils'; +import { getFeedbackMessage, Message, DEFAULT_OAI_MODEL, QuickFeedbackType, sanitizeReply } from './utils'; export interface GenAIHistoryProps { history: string[]; diff --git a/public/app/features/dashboard/components/GenAI/GenAIPanelDescriptionButton.tsx b/public/app/features/dashboard/components/GenAI/GenAIPanelDescriptionButton.tsx index 570443e8759..fa42e40c336 100644 --- a/public/app/features/dashboard/components/GenAI/GenAIPanelDescriptionButton.tsx +++ b/public/app/features/dashboard/components/GenAI/GenAIPanelDescriptionButton.tsx @@ -12,6 +12,8 @@ interface GenAIPanelDescriptionButtonProps { panel: PanelModel; } +const PANEL_DESCRIPTION_CHAR_LIMIT = 200; + const DESCRIPTION_GENERATION_STANDARD_PROMPT = 'You are an expert in creating Grafana Panels.\n' + 'You will be given the title and description of the dashboard the panel is in as well as the JSON for the panel.\n' + @@ -19,7 +21,7 @@ const DESCRIPTION_GENERATION_STANDARD_PROMPT = 'The panel description is meant to explain the purpose of the panel, not just its attributes.\n' + 'Do not refer to the panel; simply describe its purpose.\n' + 'There should be no numbers in the description except for thresholds.\n' + - 'The description should be, at most, 140 characters.'; + `The description should be, at most, ${PANEL_DESCRIPTION_CHAR_LIMIT} characters.`; export const GenAIPanelDescriptionButton = ({ onGenerate, panel }: GenAIPanelDescriptionButtonProps) => { const messages = React.useMemo(() => getMessages(panel), [panel]); @@ -48,7 +50,7 @@ function getMessages(panel: PanelModel): Message[] { role: Role.system, }, { - content: `The panel is part of a dashboard with the description: ${dashboard.title}`, + content: `The panel is part of a dashboard with the description: ${dashboard.description}`, role: Role.system, }, { diff --git a/public/app/features/dashboard/components/GenAI/GenAIPanelTitleButton.tsx b/public/app/features/dashboard/components/GenAI/GenAIPanelTitleButton.tsx index 8e58103d826..3cb314623ac 100644 --- a/public/app/features/dashboard/components/GenAI/GenAIPanelTitleButton.tsx +++ b/public/app/features/dashboard/components/GenAI/GenAIPanelTitleButton.tsx @@ -5,17 +5,19 @@ import { PanelModel } from '../../state'; import { GenAIButton } from './GenAIButton'; import { EventTrackingSrc } from './tracking'; -import { Message, QuickFeedbackType, Role } from './utils'; +import { Message, Role } from './utils'; interface GenAIPanelTitleButtonProps { onGenerate: (title: string) => void; panel: PanelModel; } +const PANEL_TITLE_CHAR_LIMIT = 50; + const TITLE_GENERATION_STANDARD_PROMPT = 'You are an expert in creating Grafana Panels.' + - 'Your goal is to write short, descriptive, and concise panel title for a panel.' + - 'The title should be shorter than 50 characters.'; + 'Your goal is to write short, descriptive, and concise panel title.' + + `The title should be shorter than ${PANEL_TITLE_CHAR_LIMIT} characters.`; export const GenAIPanelTitleButton = ({ onGenerate, panel }: GenAIPanelTitleButtonProps) => { const messages = React.useMemo(() => getMessages(panel), [panel]); @@ -44,21 +46,12 @@ function getMessages(panel: PanelModel): Message[] { role: Role.system, }, { - content: `The panel is part of a dashboard with the description: ${dashboard.title}`, + content: `The panel is part of a dashboard with the description: ${dashboard.description}`, role: Role.system, }, { content: `Use this JSON object which defines the panel: ${JSON.stringify(panel.getSaveModel())}`, - role: Role.user, + role: Role.system, }, ]; } - -export const getFeedbackMessage = (previousResponse: string, feedback: string | QuickFeedbackType): Message[] => { - return [ - { - role: Role.system, - content: `Your previous response was: ${previousResponse}. The user has provided the following feedback: ${feedback}. Re-generate your response according to the provided feedback.`, - }, - ]; -}; diff --git a/public/app/features/dashboard/components/GenAI/MinimalisticPagination.tsx b/public/app/features/dashboard/components/GenAI/MinimalisticPagination.tsx index 623532656ee..ce59b2a69de 100644 --- a/public/app/features/dashboard/components/GenAI/MinimalisticPagination.tsx +++ b/public/app/features/dashboard/components/GenAI/MinimalisticPagination.tsx @@ -51,5 +51,6 @@ const getStyles = (theme: GrafanaTheme2) => ({ display: 'flex', flexDirection: 'row', gap: 16, + userSelect: 'none', }), }); diff --git a/public/app/features/dashboard/components/GenAI/utils.ts b/public/app/features/dashboard/components/GenAI/utils.ts index 3d695ba0538..ca5607c4d90 100644 --- a/public/app/features/dashboard/components/GenAI/utils.ts +++ b/public/app/features/dashboard/components/GenAI/utils.ts @@ -65,6 +65,21 @@ export async function isLLMPluginEnabled() { return llms.openai.enabled().then((response) => response.ok); } +/** + * Get the message to be sent to OpenAI to generate a new response. + * @param previousResponse + * @param feedback + * @returns Message[] to be sent to OpenAI to generate a new response + */ +export const getFeedbackMessage = (previousResponse: string, feedback: string | QuickFeedbackType): Message[] => { + return [ + { + role: Role.system, + content: `Your previous response was: ${previousResponse}. The user has provided the following feedback: ${feedback}. Re-generate your response according to the provided feedback.`, + }, + ]; +}; + /** * * @param dashboard Dashboard to generate a title or description for