kibana/x-pack/solutions/search/plugins/search_playground/common/prompt.ts
Rodney Norris 575e80bccc
[Search][Playground] View Saved Playground (#223062)
## Summary

This PR implements the frontend for opening a Saved Playground. As a
part of that there are several refactors to the current playground that
warrant regression testing.

### Testing

To test the saved playground view the search mode feature flag should be
enabled, either with a config override or via console:
```
POST kbn:/internal/kibana/settings/searchPlayground:searchModeEnabled
{"value": true} 
```

Then you will need to manually save a playground:

```
curl -X "PUT" "http://localhost:5601/internal/search_playground/playgrounds" \
     -H 'elastic-api-version: 1' \
     -H 'kbn-xsrf: dev' \
     -H 'x-elastic-internal-origin: Kibana' \
     -H 'Content-Type: application/json; charset=utf-8' \
     -u 'elastic_serverless:<PASSWORD>' \
     -d $'{
  "elasticsearchQueryJSON": "{\\"retriever\\":{\\"standard\\":{\\"query\\":{\\"semantic\\":{\\"field\\":\\"text\\",\\"query\\":\\"{query}\\"}}}},\\"highlight\\":{\\"fields\\":{\\"text\\":{\\"type\\":\\"semantic\\",\\"number_of_fragments\\":2,\\"order\\":\\"score\\"}}}}",
  "indices": [
    "search-test"
  ],
  "name": "Test playground",
  "queryFields": {
    "search-test": [
      "text"
    ]
  }
}'
```

*Note this creates a saved playground in the Default space, and
playgrounds are space aware so it will only be available in the default
space. If you want to create a playground in another space you will need
to update this URL to include the space.

This assumes you have a `search-test` index created using the
semantic_text onboarding workflow mapping.

Then you can open the saved playground page at:
`/app/search_playground/p/<ID_RETURNED_FROM_CURL>`

## Screenshots
Chat

![image](https://github.com/user-attachments/assets/700958ed-e0e4-4276-b670-4bd4b70b3df9)

Chat - Query

![image](https://github.com/user-attachments/assets/4f2cb9f1-f1fe-47bd-b53d-4e59a4713689)

Search - Query

![image](https://github.com/user-attachments/assets/be96dcd9-2395-4117-a7d9-1080a0e1895b)

### Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
2025-06-18 21:58:57 +02:00

106 lines
2.8 KiB
TypeScript

/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
const OpenAIPrompt = (systemInstructions: string, question?: boolean) => {
return `
Instructions:
${systemInstructions}
Context:
{context}
${question ? 'follow up question: {question}' : ''}
`;
};
const MistralPrompt = (systemInstructions: string, question?: boolean) => {
return `
<s>[INST]${systemInstructions}[/INST] </s>
[INST]
Context:
{context}
[/INST]
${question ? '[INST]follow up question: {question}[/INST]' : ''}
`;
};
// https://docs.anthropic.com/claude/docs/use-xml-tags
const AnthropicPrompt = (systemInstructions: string, question?: boolean) => {
return `
<instructions>${systemInstructions}</instructions>
<context>
{context}
</context>
${question ? '<input>{question}</input>' : ''}
`;
};
const GeminiPrompt = (systemInstructions: string, question?: boolean) => {
return `
Instructions:
${systemInstructions}
Context:
{context}
${question ? 'follow up question: {question}' : ''}
`;
};
interface PromptTemplateOptions {
citations?: boolean;
context?: boolean;
type?: 'openai' | 'mistral' | 'anthropic' | 'gemini';
}
export const Prompt = (instructions: string, options: PromptTemplateOptions): string => {
const systemInstructions = `
- ${instructions}
${
options.context
? '- Answer questions truthfully and factually using only the context presented.'
: ''
}
- If you don't know the answer, just say that you don't know, don't make up an answer.
${
options.citations
? '- You must always cite the document where the answer was extracted using inline academic citation style [], using the position.'
: ''
}
- Use markdown format for code examples.
- You are correct, factual, precise, and reliable.
`;
return {
openai: OpenAIPrompt,
mistral: MistralPrompt,
anthropic: AnthropicPrompt,
gemini: GeminiPrompt,
}[options.type || 'openai'](systemInstructions, false);
};
interface QuestionRewritePromptOptions {
type: 'openai' | 'mistral' | 'anthropic' | 'gemini';
}
export const QuestionRewritePrompt = (options: QuestionRewritePromptOptions): string => {
const systemInstructions = `Given the following conversation context and a follow up question, rephrase the follow up question to be a standalone question. Rewrite the question in the question language. Keep the answer to a single sentence. Do not use quotes.`;
return {
openai: OpenAIPrompt,
mistral: MistralPrompt,
anthropic: AnthropicPrompt,
gemini: GeminiPrompt,
}[options.type || 'openai'](systemInstructions, true);
};
export const DEFAULT_LLM_PROMPT = 'You are an assistant for question-answering tasks.';