mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
Remove is_correction and confidence attributes from kb entry (#222814)
## Summary Closes https://github.com/elastic/kibana/issues/222555 Remove `confidence` and `is_correction` attributes from knowledge base entry since they are no longer used. ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] 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: Søren Louv-Jansen <sorenlouv@gmail.com>
This commit is contained in:
parent
f281a64499
commit
dd1b7a4780
15 changed files with 67 additions and 88 deletions
|
@ -27,10 +27,7 @@ export function useImportKnowledgeBaseEntries() {
|
||||||
ServerError,
|
ServerError,
|
||||||
{
|
{
|
||||||
entries: Array<
|
entries: Array<
|
||||||
Omit<
|
Omit<KnowledgeBaseEntry, '@timestamp' | 'public' | 'labels'> & { title: string }
|
||||||
KnowledgeBaseEntry,
|
|
||||||
'@timestamp' | 'confidence' | 'is_correction' | 'public' | 'labels'
|
|
||||||
> & { title: string }
|
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
>(
|
>(
|
||||||
|
|
|
@ -62,8 +62,6 @@ export function KnowledgeBaseEditManualEntryFlyout({
|
||||||
text: newEntryText,
|
text: newEntryText,
|
||||||
public: isPublic,
|
public: isPublic,
|
||||||
role: KnowledgeBaseEntryRole.UserEntry,
|
role: KnowledgeBaseEntryRole.UserEntry,
|
||||||
confidence: 'high',
|
|
||||||
is_correction: false,
|
|
||||||
labels: {},
|
labels: {},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -206,8 +206,6 @@ describe('KnowledgeBaseTab', () => {
|
||||||
public: false,
|
public: false,
|
||||||
text: 'bar',
|
text: 'bar',
|
||||||
role: 'user_entry',
|
role: 'user_entry',
|
||||||
confidence: 'high',
|
|
||||||
is_correction: false,
|
|
||||||
labels: expect.any(Object),
|
labels: expect.any(Object),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -99,8 +99,6 @@ export interface KnowledgeBaseEntry {
|
||||||
id: string;
|
id: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
text: string;
|
text: string;
|
||||||
confidence: 'low' | 'medium' | 'high';
|
|
||||||
is_correction: boolean;
|
|
||||||
type?: 'user_instruction' | 'contextual';
|
type?: 'user_instruction' | 'contextual';
|
||||||
public: boolean;
|
public: boolean;
|
||||||
labels?: Record<string, string>;
|
labels?: Record<string, string>;
|
||||||
|
@ -108,6 +106,8 @@ export interface KnowledgeBaseEntry {
|
||||||
user?: {
|
user?: {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
confidence?: 'low' | 'medium' | 'high'; // deprecated
|
||||||
|
is_correction?: boolean; // deprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Instruction {
|
export interface Instruction {
|
||||||
|
|
|
@ -20,7 +20,6 @@ export function registerSummarizationFunction({
|
||||||
{
|
{
|
||||||
name: SUMMARIZE_FUNCTION_NAME,
|
name: SUMMARIZE_FUNCTION_NAME,
|
||||||
description: `Use this function to store facts in the knowledge database if the user requests it.
|
description: `Use this function to store facts in the knowledge database if the user requests it.
|
||||||
You can score the learnings with a confidence metric, whether it is a correction on a previous learning.
|
|
||||||
An embedding will be created that you can recall later with a semantic search.
|
An embedding will be created that you can recall later with a semantic search.
|
||||||
When you create this summarisation, make sure you craft it in a way that can be recalled with a semantic
|
When you create this summarisation, make sure you craft it in a way that can be recalled with a semantic
|
||||||
search later, and that it would have answered the user's original request.`,
|
search later, and that it would have answered the user's original request.`,
|
||||||
|
@ -39,34 +38,16 @@ export function registerSummarizationFunction({
|
||||||
description:
|
description:
|
||||||
"A human-readable summary of what you have learned, described in such a way that you can recall it later with semantic search, and that it would have answered the user's original request.",
|
"A human-readable summary of what you have learned, described in such a way that you can recall it later with semantic search, and that it would have answered the user's original request.",
|
||||||
},
|
},
|
||||||
is_correction: {
|
|
||||||
type: 'boolean',
|
|
||||||
description: 'Whether this is a correction for a previous learning.',
|
|
||||||
},
|
|
||||||
confidence: {
|
|
||||||
type: 'string',
|
|
||||||
description: 'How confident you are about this being a correct and useful learning',
|
|
||||||
enum: ['low' as const, 'medium' as const, 'high' as const],
|
|
||||||
},
|
|
||||||
public: {
|
public: {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description:
|
description:
|
||||||
'Whether this information is specific to the user, or generally applicable to any user of the product',
|
'Whether this information is specific to the user, or generally applicable to any user of the product',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: [
|
required: ['title' as const, 'text' as const, 'public' as const],
|
||||||
'title' as const,
|
|
||||||
'text' as const,
|
|
||||||
'is_correction' as const,
|
|
||||||
'confidence' as const,
|
|
||||||
'public' as const,
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
async (
|
async ({ arguments: { title, text, public: isPublic } }, signal) => {
|
||||||
{ arguments: { title, text, is_correction: isCorrection, confidence, public: isPublic } },
|
|
||||||
signal
|
|
||||||
) => {
|
|
||||||
const id = v4();
|
const id = v4();
|
||||||
resources.logger.debug(`Creating new knowledge base entry with id: ${id}`);
|
resources.logger.debug(`Creating new knowledge base entry with id: ${id}`);
|
||||||
|
|
||||||
|
@ -78,8 +59,6 @@ export function registerSummarizationFunction({
|
||||||
text,
|
text,
|
||||||
public: isPublic,
|
public: isPublic,
|
||||||
role: KnowledgeBaseEntryRole.AssistantSummarization,
|
role: KnowledgeBaseEntryRole.AssistantSummarization,
|
||||||
confidence,
|
|
||||||
is_correction: isCorrection,
|
|
||||||
labels: {},
|
labels: {},
|
||||||
},
|
},
|
||||||
// signal,
|
// signal,
|
||||||
|
|
|
@ -167,8 +167,6 @@ const functionSummariseRoute = createObservabilityAIAssistantServerRoute({
|
||||||
body: t.type({
|
body: t.type({
|
||||||
title: t.string,
|
title: t.string,
|
||||||
text: nonEmptyStringRt,
|
text: nonEmptyStringRt,
|
||||||
confidence: t.union([t.literal('low'), t.literal('medium'), t.literal('high')]),
|
|
||||||
is_correction: toBooleanRt,
|
|
||||||
public: toBooleanRt,
|
public: toBooleanRt,
|
||||||
labels: t.record(t.string, t.string),
|
labels: t.record(t.string, t.string),
|
||||||
}),
|
}),
|
||||||
|
@ -181,21 +179,12 @@ const functionSummariseRoute = createObservabilityAIAssistantServerRoute({
|
||||||
handler: async (resources): Promise<void> => {
|
handler: async (resources): Promise<void> => {
|
||||||
const client = await resources.service.getClient({ request: resources.request });
|
const client = await resources.service.getClient({ request: resources.request });
|
||||||
|
|
||||||
const {
|
const { title, text, public: isPublic, labels } = resources.params.body;
|
||||||
title,
|
|
||||||
confidence,
|
|
||||||
is_correction: isCorrection,
|
|
||||||
text,
|
|
||||||
public: isPublic,
|
|
||||||
labels,
|
|
||||||
} = resources.params.body;
|
|
||||||
|
|
||||||
return client.addKnowledgeBaseEntry({
|
return client.addKnowledgeBaseEntry({
|
||||||
entry: {
|
entry: {
|
||||||
title,
|
title,
|
||||||
confidence,
|
|
||||||
id: v4(),
|
id: v4(),
|
||||||
is_correction: isCorrection,
|
|
||||||
text,
|
text,
|
||||||
public: isPublic,
|
public: isPublic,
|
||||||
labels,
|
labels,
|
||||||
|
|
|
@ -215,8 +215,6 @@ const knowledgeBaseEntryRt = t.intersection([
|
||||||
text: nonEmptyStringRt,
|
text: nonEmptyStringRt,
|
||||||
}),
|
}),
|
||||||
t.partial({
|
t.partial({
|
||||||
confidence: t.union([t.literal('low'), t.literal('medium'), t.literal('high')]),
|
|
||||||
is_correction: toBooleanRt,
|
|
||||||
public: toBooleanRt,
|
public: toBooleanRt,
|
||||||
labels: t.record(t.string, t.string),
|
labels: t.record(t.string, t.string),
|
||||||
role: t.union([
|
role: t.union([
|
||||||
|
@ -243,8 +241,6 @@ const saveKnowledgeBaseEntry = createObservabilityAIAssistantServerRoute({
|
||||||
const entry = resources.params.body;
|
const entry = resources.params.body;
|
||||||
return client.addKnowledgeBaseEntry({
|
return client.addKnowledgeBaseEntry({
|
||||||
entry: {
|
entry: {
|
||||||
confidence: 'high',
|
|
||||||
is_correction: false,
|
|
||||||
public: true,
|
public: true,
|
||||||
labels: {},
|
labels: {},
|
||||||
role: KnowledgeBaseEntryRole.UserEntry,
|
role: KnowledgeBaseEntryRole.UserEntry,
|
||||||
|
@ -294,8 +290,6 @@ const importKnowledgeBaseEntries = createObservabilityAIAssistantServerRoute({
|
||||||
}
|
}
|
||||||
|
|
||||||
const entries = resources.params.body.entries.map((entry) => ({
|
const entries = resources.params.body.entries.map((entry) => ({
|
||||||
confidence: 'high' as const,
|
|
||||||
is_correction: false,
|
|
||||||
public: true,
|
public: true,
|
||||||
labels: {},
|
labels: {},
|
||||||
role: KnowledgeBaseEntryRole.UserEntry,
|
role: KnowledgeBaseEntryRole.UserEntry,
|
||||||
|
|
|
@ -785,10 +785,7 @@ export class ObservabilityAIAssistantClient {
|
||||||
addUserInstruction = async ({
|
addUserInstruction = async ({
|
||||||
entry,
|
entry,
|
||||||
}: {
|
}: {
|
||||||
entry: Omit<
|
entry: Omit<KnowledgeBaseEntry, '@timestamp' | 'type' | 'role'>;
|
||||||
KnowledgeBaseEntry,
|
|
||||||
'@timestamp' | 'confidence' | 'is_correction' | 'type' | 'role'
|
|
||||||
>;
|
|
||||||
}): Promise<void> => {
|
}): Promise<void> => {
|
||||||
// for now we want to limit the number of user instructions to 1 per user
|
// for now we want to limit the number of user instructions to 1 per user
|
||||||
// if a user instruction already exists for the user, we get the id and update it
|
// if a user instruction already exists for the user, we get the id and update it
|
||||||
|
@ -815,8 +812,6 @@ export class ObservabilityAIAssistantClient {
|
||||||
user: this.dependencies.user,
|
user: this.dependencies.user,
|
||||||
entry: {
|
entry: {
|
||||||
...entry,
|
...entry,
|
||||||
confidence: 'high',
|
|
||||||
is_correction: false,
|
|
||||||
type: KnowledgeBaseType.UserInstruction,
|
type: KnowledgeBaseType.UserInstruction,
|
||||||
labels: {},
|
labels: {},
|
||||||
role: KnowledgeBaseEntryRole.UserEntry,
|
role: KnowledgeBaseEntryRole.UserEntry,
|
||||||
|
|
|
@ -66,8 +66,9 @@ export function getComponentTemplate(inferenceId: string) {
|
||||||
'ml.tokens': {
|
'ml.tokens': {
|
||||||
type: 'rank_features',
|
type: 'rank_features',
|
||||||
},
|
},
|
||||||
confidence: keyword,
|
confidence: keyword, // deprecated but kept for backwards compatibility
|
||||||
is_correction: {
|
is_correction: {
|
||||||
|
// deprecated but kept for backwards compatibility
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
},
|
},
|
||||||
public: {
|
public: {
|
||||||
|
|
|
@ -47,7 +47,6 @@ export interface RecalledEntry {
|
||||||
title?: string;
|
title?: string;
|
||||||
text: string;
|
text: string;
|
||||||
esScore: number | null;
|
esScore: number | null;
|
||||||
is_correction?: boolean;
|
|
||||||
labels?: Record<string, string>;
|
labels?: Record<string, string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +69,7 @@ export class KnowledgeBaseService {
|
||||||
user?: { name: string };
|
user?: { name: string };
|
||||||
}): Promise<RecalledEntry[]> {
|
}): Promise<RecalledEntry[]> {
|
||||||
const response = await this.dependencies.esClient.asInternalUser.search<
|
const response = await this.dependencies.esClient.asInternalUser.search<
|
||||||
Pick<KnowledgeBaseEntry, 'text' | 'is_correction' | 'labels' | 'title'> & { doc_id?: string }
|
Pick<KnowledgeBaseEntry, 'text' | 'labels' | 'title'> & { doc_id?: string }
|
||||||
>({
|
>({
|
||||||
index: [resourceNames.writeIndexAlias.kb],
|
index: [resourceNames.writeIndexAlias.kb],
|
||||||
query: {
|
query: {
|
||||||
|
@ -96,13 +95,12 @@ export class KnowledgeBaseService {
|
||||||
},
|
},
|
||||||
size: 20,
|
size: 20,
|
||||||
_source: {
|
_source: {
|
||||||
includes: ['text', 'is_correction', 'labels', 'doc_id', 'title'],
|
includes: ['text', 'labels', 'doc_id', 'title'],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.hits.hits.map((hit) => ({
|
return response.hits.hits.map((hit) => ({
|
||||||
text: hit._source?.text!,
|
text: hit._source?.text!,
|
||||||
is_correction: hit._source?.is_correction,
|
|
||||||
labels: hit._source?.labels,
|
labels: hit._source?.labels,
|
||||||
title: hit._source?.title ?? hit._source?.doc_id, // use `doc_id` as fallback title for backwards compatibility
|
title: hit._source?.title ?? hit._source?.doc_id, // use `doc_id` as fallback title for backwards compatibility
|
||||||
esScore: hit._score!,
|
esScore: hit._score!,
|
||||||
|
@ -284,19 +282,7 @@ export class KnowledgeBaseService {
|
||||||
: [{ [String(sortBy)]: { order: sortDirection } }],
|
: [{ [String(sortBy)]: { order: sortDirection } }],
|
||||||
size: 500,
|
size: 500,
|
||||||
_source: {
|
_source: {
|
||||||
includes: [
|
excludes: ['confidence', 'is_correction'], // fields deprecated in https://github.com/elastic/kibana/pull/222814
|
||||||
'title',
|
|
||||||
'doc_id',
|
|
||||||
'text',
|
|
||||||
'is_correction',
|
|
||||||
'labels',
|
|
||||||
'confidence',
|
|
||||||
'public',
|
|
||||||
'@timestamp',
|
|
||||||
'role',
|
|
||||||
'user.name',
|
|
||||||
'type',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,6 @@ async function recallFromSemanticTextConnectors({
|
||||||
const results = response.hits.hits.map((hit) => ({
|
const results = response.hits.hits.map((hit) => ({
|
||||||
text: JSON.stringify(hit._source),
|
text: JSON.stringify(hit._source),
|
||||||
esScore: hit._score!,
|
esScore: hit._score!,
|
||||||
is_correction: false,
|
|
||||||
id: hit._id!,
|
id: hit._id!,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -199,7 +198,6 @@ async function recallFromLegacyConnectors({
|
||||||
const results = response.hits.hits.map((hit) => ({
|
const results = response.hits.hits.map((hit) => ({
|
||||||
text: JSON.stringify(hit._source),
|
text: JSON.stringify(hit._source),
|
||||||
esScore: hit._score!,
|
esScore: hit._score!,
|
||||||
is_correction: false,
|
|
||||||
id: hit._id!,
|
id: hit._id!,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -50,8 +50,6 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon
|
||||||
arguments: JSON.stringify({
|
arguments: JSON.stringify({
|
||||||
title: 'My Title',
|
title: 'My Title',
|
||||||
text: 'Hello world',
|
text: 'Hello world',
|
||||||
is_correction: false,
|
|
||||||
confidence: 'high',
|
|
||||||
public: false,
|
public: false,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,10 +6,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import expect from '@kbn/expect';
|
import expect from '@kbn/expect';
|
||||||
import { type KnowledgeBaseEntry } from '@kbn/observability-ai-assistant-plugin/common';
|
import {
|
||||||
|
type KnowledgeBaseEntry,
|
||||||
|
KnowledgeBaseEntryRole,
|
||||||
|
} from '@kbn/observability-ai-assistant-plugin/common';
|
||||||
import { orderBy, size, toPairs } from 'lodash';
|
import { orderBy, size, toPairs } from 'lodash';
|
||||||
import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context';
|
import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context';
|
||||||
import { clearKnowledgeBase, getKnowledgeBaseEntriesFromEs } from '../utils/knowledge_base';
|
import {
|
||||||
|
clearKnowledgeBase,
|
||||||
|
getKnowledgeBaseEntriesFromEs,
|
||||||
|
addKnowledgeBaseEntryToEs,
|
||||||
|
} from '../utils/knowledge_base';
|
||||||
import {
|
import {
|
||||||
teardownTinyElserModelAndInferenceEndpoint,
|
teardownTinyElserModelAndInferenceEndpoint,
|
||||||
deployTinyElserAndSetupKb,
|
deployTinyElserAndSetupKb,
|
||||||
|
@ -44,6 +51,14 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon
|
||||||
return res.body.entries;
|
return res.body.entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function saveEntry(knowledgeBaseEntry: { title: string; text: string; id: string }) {
|
||||||
|
const { status } = await observabilityAIAssistantAPIClient.editor({
|
||||||
|
endpoint: 'POST /internal/observability_ai_assistant/kb/entries/save',
|
||||||
|
params: { body: knowledgeBaseEntry },
|
||||||
|
});
|
||||||
|
expect(status).to.be(200);
|
||||||
|
}
|
||||||
|
|
||||||
describe('Knowledge base: Basic operations', function () {
|
describe('Knowledge base: Basic operations', function () {
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await deployTinyElserAndSetupKb(getService);
|
await deployTinyElserAndSetupKb(getService);
|
||||||
|
@ -62,11 +77,7 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon
|
||||||
};
|
};
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
const { status } = await observabilityAIAssistantAPIClient.editor({
|
await saveEntry(knowledgeBaseEntry);
|
||||||
endpoint: 'POST /internal/observability_ai_assistant/kb/entries/save',
|
|
||||||
params: { body: knowledgeBaseEntry },
|
|
||||||
});
|
|
||||||
expect(status).to.be(200);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can retrieve the entry', async () => {
|
it('can retrieve the entry', async () => {
|
||||||
|
@ -77,6 +88,33 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon
|
||||||
expect(entry.text).to.equal(knowledgeBaseEntry.text);
|
expect(entry.text).to.equal(knowledgeBaseEntry.text);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not retrieve deprecated properties', async () => {
|
||||||
|
await clearKnowledgeBase(es);
|
||||||
|
await addKnowledgeBaseEntryToEs(es, {
|
||||||
|
confidence: 'high' as const,
|
||||||
|
'@timestamp': new Date().toISOString(),
|
||||||
|
role: KnowledgeBaseEntryRole.UserEntry,
|
||||||
|
is_correction: true,
|
||||||
|
public: false,
|
||||||
|
labels: {},
|
||||||
|
...knowledgeBaseEntry,
|
||||||
|
});
|
||||||
|
|
||||||
|
const hits = await getKnowledgeBaseEntriesFromEs(es);
|
||||||
|
const hitSource = hits[0]._source;
|
||||||
|
expect(hitSource).to.have.property('is_correction');
|
||||||
|
expect(hitSource).to.have.property('confidence');
|
||||||
|
|
||||||
|
const entries = await getEntries();
|
||||||
|
const entry = entries[0];
|
||||||
|
expect(entry).not.to.have.property('confidence');
|
||||||
|
expect(entry).not.to.have.property('is_correction');
|
||||||
|
|
||||||
|
await clearKnowledgeBase(es);
|
||||||
|
|
||||||
|
await saveEntry(knowledgeBaseEntry);
|
||||||
|
});
|
||||||
|
|
||||||
it('generates sparse embeddings', async () => {
|
it('generates sparse embeddings', async () => {
|
||||||
const hits = await getKnowledgeBaseEntriesFromEs(es);
|
const hits = await getKnowledgeBaseEntriesFromEs(es);
|
||||||
const embeddings =
|
const embeddings =
|
||||||
|
|
|
@ -269,6 +269,16 @@ export async function getKnowledgeBaseEntriesFromEs(es: Client) {
|
||||||
return res.hits.hits;
|
return res.hits.hits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function addKnowledgeBaseEntryToEs(es: Client, entry: KnowledgeBaseEntry) {
|
||||||
|
const result = await es.index({
|
||||||
|
index: resourceNames.writeIndexAlias.kb,
|
||||||
|
document: entry,
|
||||||
|
refresh: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
export function getKnowledgeBaseEntriesFromApi({
|
export function getKnowledgeBaseEntriesFromApi({
|
||||||
observabilityAIAssistantAPIClient,
|
observabilityAIAssistantAPIClient,
|
||||||
query = '',
|
query = '',
|
||||||
|
|
|
@ -44,8 +44,6 @@ export default function ApiTest({ getService, getPageObjects }: FtrProviderConte
|
||||||
body: {
|
body: {
|
||||||
title: 'Favourite color',
|
title: 'Favourite color',
|
||||||
text,
|
text,
|
||||||
confidence: 'high',
|
|
||||||
is_correction: false,
|
|
||||||
public: false,
|
public: false,
|
||||||
labels: {},
|
labels: {},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue