mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
# Backport This will backport the following commits from `main` to `8.x`: - [[Obs AI Assistant] unskip kb user instructions test in serverless (#205519)](https://github.com/elastic/kibana/pull/205519) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Sandra G","email":"neptunian@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-01-04T21:32:32Z","message":"[Obs AI Assistant] unskip kb user instructions test in serverless (#205519)\n\n## Summary\r\nResolves https://github.com/elastic/kibana/issues/192886\r\n\r\n- Unskips `knowledge_base_user_instructions.spec.ts` in serverless\r\n - stays skipped in mki due to proxy usage issue\r\n - Duplicates new changes from non serverless\r\n- Removes `skipInMKI` tags for:\r\n`knowledge_base_setup.spec.ts`\r\n`knowledge_base.spec.ts `\r\n`knowledge_base_status.spec.ts`\r\n\r\n\r\nIf https://github.com/elastic/kibana/issues/192718 is merged before\r\nthis, I will move `knowledge_base_user_instructions.spec.ts` to\r\ndeployment agnostic. Otherwise It can be done in that PR or another.","sha":"b17b10eea1aa465a4291ce716dba473eb9195cb1","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","backport:prev-minor","Team:Obs AI Assistant"],"title":"[Obs AI Assistant] unskip kb user instructions test in serverless","number":205519,"url":"https://github.com/elastic/kibana/pull/205519","mergeCommit":{"message":"[Obs AI Assistant] unskip kb user instructions test in serverless (#205519)\n\n## Summary\r\nResolves https://github.com/elastic/kibana/issues/192886\r\n\r\n- Unskips `knowledge_base_user_instructions.spec.ts` in serverless\r\n - stays skipped in mki due to proxy usage issue\r\n - Duplicates new changes from non serverless\r\n- Removes `skipInMKI` tags for:\r\n`knowledge_base_setup.spec.ts`\r\n`knowledge_base.spec.ts `\r\n`knowledge_base_status.spec.ts`\r\n\r\n\r\nIf https://github.com/elastic/kibana/issues/192718 is merged before\r\nthis, I will move `knowledge_base_user_instructions.spec.ts` to\r\ndeployment agnostic. Otherwise It can be done in that PR or another.","sha":"b17b10eea1aa465a4291ce716dba473eb9195cb1"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/205519","number":205519,"mergeCommit":{"message":"[Obs AI Assistant] unskip kb user instructions test in serverless (#205519)\n\n## Summary\r\nResolves https://github.com/elastic/kibana/issues/192886\r\n\r\n- Unskips `knowledge_base_user_instructions.spec.ts` in serverless\r\n - stays skipped in mki due to proxy usage issue\r\n - Duplicates new changes from non serverless\r\n- Removes `skipInMKI` tags for:\r\n`knowledge_base_setup.spec.ts`\r\n`knowledge_base.spec.ts `\r\n`knowledge_base_status.spec.ts`\r\n\r\n\r\nIf https://github.com/elastic/kibana/issues/192718 is merged before\r\nthis, I will move `knowledge_base_user_instructions.spec.ts` to\r\ndeployment agnostic. Otherwise It can be done in that PR or another.","sha":"b17b10eea1aa465a4291ce716dba473eb9195cb1"}}]}] BACKPORT--> Co-authored-by: Sandra G <neptunian@users.noreply.github.com>
This commit is contained in:
parent
2c7c1c7c6d
commit
38812745a3
4 changed files with 118 additions and 65 deletions
|
@ -22,8 +22,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient');
|
||||
|
||||
describe('Knowledge base', function () {
|
||||
// TODO: https://github.com/elastic/kibana/issues/192886 kb/setup error
|
||||
this.tags(['skipMKI']);
|
||||
before(async () => {
|
||||
await createKnowledgeBaseModel(ml);
|
||||
|
||||
|
|
|
@ -23,9 +23,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient');
|
||||
|
||||
describe('/internal/observability_ai_assistant/kb/setup', function () {
|
||||
// TODO: https://github.com/elastic/kibana/issues/192886 kb/setup error
|
||||
this.tags(['skipMKI']);
|
||||
|
||||
before(async () => {
|
||||
await deleteKnowledgeBaseModel(ml).catch(() => {});
|
||||
await deleteInferenceEndpoint({ es }).catch(() => {});
|
||||
|
|
|
@ -24,8 +24,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const observabilityAIAssistantAPIClient = getService('observabilityAIAssistantAPIClient');
|
||||
|
||||
describe('/internal/observability_ai_assistant/kb/status', function () {
|
||||
this.tags(['skipMKI']);
|
||||
|
||||
before(async () => {
|
||||
await createKnowledgeBaseModel(ml);
|
||||
await observabilityAIAssistantAPIClient
|
||||
|
|
|
@ -9,12 +9,14 @@ import expect from '@kbn/expect';
|
|||
import { sortBy } from 'lodash';
|
||||
import { Message, MessageRole } from '@kbn/observability-ai-assistant-plugin/common';
|
||||
import { CONTEXT_FUNCTION_NAME } from '@kbn/observability-ai-assistant-plugin/server/functions/context';
|
||||
import { Instruction } from '@kbn/observability-ai-assistant-plugin/common/types';
|
||||
import {
|
||||
clearConversations,
|
||||
clearKnowledgeBase,
|
||||
createKnowledgeBaseModel,
|
||||
deleteInferenceEndpoint,
|
||||
deleteKnowledgeBaseModel,
|
||||
TINY_ELSER,
|
||||
} from '@kbn/test-suites-xpack/observability_ai_assistant_api_integration/tests/knowledge_base/helpers';
|
||||
import { getConversationCreatedEvent } from '@kbn/test-suites-xpack/observability_ai_assistant_api_integration/tests/conversations/helpers';
|
||||
import {
|
||||
|
@ -33,8 +35,10 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
const log = getService('log');
|
||||
const svlUserManager = getService('svlUserManager');
|
||||
const svlCommonApi = getService('svlCommonApi');
|
||||
const retry = getService('retry');
|
||||
|
||||
describe.skip('Knowledge base user instructions', function () {
|
||||
describe('Knowledge base user instructions', function () {
|
||||
// TODO: https://github.com/elastic/kibana/issues/192751
|
||||
this.tags(['skipMKI']);
|
||||
let editorRoleAuthc: RoleCredentials;
|
||||
let internalReqHeader: InternalRequestHeader;
|
||||
|
@ -45,8 +49,13 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
await createKnowledgeBaseModel(ml);
|
||||
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsEditor({
|
||||
.slsAdmin({
|
||||
endpoint: 'POST /internal/observability_ai_assistant/kb/setup',
|
||||
params: {
|
||||
query: {
|
||||
model_id: TINY_ELSER.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
});
|
||||
|
@ -64,10 +73,22 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
await clearKnowledgeBase(es);
|
||||
|
||||
const promises = [
|
||||
{ username: 'editor', isPublic: true },
|
||||
{ username: 'editor', isPublic: false },
|
||||
{ username: 'john', isPublic: true },
|
||||
{ username: 'john', isPublic: false },
|
||||
{
|
||||
username: 'editor' as const,
|
||||
isPublic: true,
|
||||
},
|
||||
{
|
||||
username: 'editor' as const,
|
||||
isPublic: false,
|
||||
},
|
||||
{
|
||||
username: 'secondary_editor' as const,
|
||||
isPublic: true,
|
||||
},
|
||||
{
|
||||
username: 'secondary_editor' as const,
|
||||
isPublic: false,
|
||||
},
|
||||
].map(async ({ username, isPublic }) => {
|
||||
const visibility = isPublic ? 'Public' : 'Private';
|
||||
const user = username === 'editor' ? 'slsEditor' : 'slsAdmin';
|
||||
|
@ -88,61 +109,69 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it('"editor" can retrieve their own private instructions and the public instruction', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions',
|
||||
await retry.try(async () => {
|
||||
const res = await observabilityAIAssistantAPIClient.slsEditor({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions',
|
||||
});
|
||||
|
||||
const instructions = res.body.userInstructions;
|
||||
// TODO: gets 4 in serverless, bufferFlush event?
|
||||
expect(instructions).to.have.length(3);
|
||||
|
||||
const sortById = (data: Array<Instruction & { public?: boolean }>) => sortBy(data, 'id');
|
||||
expect(sortById(instructions)).to.eql(
|
||||
sortById([
|
||||
{
|
||||
id: 'private-doc-from-editor',
|
||||
public: false,
|
||||
text: 'Private user instruction from "editor"',
|
||||
},
|
||||
{
|
||||
id: 'public-doc-from-editor',
|
||||
public: true,
|
||||
text: 'Public user instruction from "editor"',
|
||||
},
|
||||
{
|
||||
id: 'public-doc-from-secondary_editor',
|
||||
public: true,
|
||||
text: 'Public user instruction from "secondary_editor"',
|
||||
},
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
const instructions = res.body.userInstructions;
|
||||
|
||||
const sortByDocId = (data: any) => sortBy(data, 'doc_id');
|
||||
expect(sortByDocId(instructions)).to.eql(
|
||||
sortByDocId([
|
||||
{
|
||||
doc_id: 'private-doc-from-editor',
|
||||
public: false,
|
||||
text: 'Private user instruction from "editor"',
|
||||
},
|
||||
{
|
||||
doc_id: 'public-doc-from-editor',
|
||||
public: true,
|
||||
text: 'Public user instruction from "editor"',
|
||||
},
|
||||
{
|
||||
doc_id: 'public-doc-from-john',
|
||||
public: true,
|
||||
text: 'Public user instruction from "john"',
|
||||
},
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
it('"john" can retrieve their own private instructions and the public instruction', async () => {
|
||||
const res = await observabilityAIAssistantAPIClient.slsAdmin({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions',
|
||||
it('"secondaryEditor" can retrieve their own private instructions and the public instruction', async () => {
|
||||
await retry.try(async () => {
|
||||
const res = await observabilityAIAssistantAPIClient.slsAdmin({
|
||||
endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions',
|
||||
});
|
||||
|
||||
const instructions = res.body.userInstructions;
|
||||
expect(instructions).to.have.length(3);
|
||||
|
||||
const sortById = (data: Array<Instruction & { public?: boolean }>) => sortBy(data, 'id');
|
||||
|
||||
expect(sortById(instructions)).to.eql(
|
||||
sortById([
|
||||
{
|
||||
id: 'public-doc-from-editor',
|
||||
public: true,
|
||||
text: 'Public user instruction from "editor"',
|
||||
},
|
||||
{
|
||||
id: 'public-doc-from-secondary_editor',
|
||||
public: true,
|
||||
text: 'Public user instruction from "secondary_editor"',
|
||||
},
|
||||
{
|
||||
id: 'private-doc-from-secondary_editor',
|
||||
public: false,
|
||||
text: 'Private user instruction from "secondary_editor"',
|
||||
},
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
const instructions = res.body.userInstructions;
|
||||
|
||||
const sortByDocId = (data: any) => sortBy(data, 'doc_id');
|
||||
expect(sortByDocId(instructions)).to.eql(
|
||||
sortByDocId([
|
||||
{
|
||||
doc_id: 'public-doc-from-editor',
|
||||
public: true,
|
||||
text: 'Public user instruction from "editor"',
|
||||
},
|
||||
{
|
||||
doc_id: 'public-doc-from-john',
|
||||
public: true,
|
||||
text: 'Public user instruction from "john"',
|
||||
},
|
||||
{
|
||||
doc_id: 'private-doc-from-john',
|
||||
public: false,
|
||||
text: 'Private user instruction from "john"',
|
||||
},
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -186,7 +215,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
|
||||
expect(instructions).to.eql([
|
||||
{
|
||||
doc_id: 'doc-to-update',
|
||||
id: 'doc-to-update',
|
||||
text: 'Updated text',
|
||||
public: false,
|
||||
},
|
||||
|
@ -330,6 +359,37 @@ export default function ApiTest({ getService }: FtrProviderContext) {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Instructions can be saved and cleared again', () => {
|
||||
async function updateInstruction(text: string) {
|
||||
await observabilityAIAssistantAPIClient
|
||||
.slsEditor({
|
||||
endpoint: 'PUT /internal/observability_ai_assistant/kb/user_instructions',
|
||||
params: {
|
||||
body: {
|
||||
id: 'my-instruction-that-will-be-cleared',
|
||||
text,
|
||||
public: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const res = await observabilityAIAssistantAPIClient
|
||||
.slsEditor({ endpoint: 'GET /internal/observability_ai_assistant/kb/user_instructions' })
|
||||
.expect(200);
|
||||
|
||||
return res.body.userInstructions[0].text;
|
||||
}
|
||||
|
||||
it('can clear the instruction', async () => {
|
||||
const res1 = await updateInstruction('This is a user instruction that will be cleared');
|
||||
expect(res1).to.be('This is a user instruction that will be cleared');
|
||||
|
||||
const res2 = await updateInstruction('');
|
||||
expect(res2).to.be('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('security roles and access privileges', () => {
|
||||
describe('should deny access for users without the ai_assistant privilege', () => {
|
||||
it('PUT /internal/observability_ai_assistant/kb/user_instructions', async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue