mirror of
				https://github.com/grafana/grafana.git
				synced 2025-02-25 18:55:37 -06:00 
			
		
		
		
	Auto-generate: Update generation character limits, improve generation history UX (#76849)
This commit is contained in:
		@@ -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) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -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) => {
 | 
			
		||||
 
 | 
			
		||||
@@ -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[];
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -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.`,
 | 
			
		||||
    },
 | 
			
		||||
  ];
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -51,5 +51,6 @@ const getStyles = (theme: GrafanaTheme2) => ({
 | 
			
		||||
    display: 'flex',
 | 
			
		||||
    flexDirection: 'row',
 | 
			
		||||
    gap: 16,
 | 
			
		||||
    userSelect: 'none',
 | 
			
		||||
  }),
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user