mirror of
https://github.com/hexastack/hexabot
synced 2025-06-26 18:27:28 +00:00
feat: add weight to nlp entity schema and readapt
This commit is contained in:
parent
95e07c84bc
commit
67ce8ebbfc
@ -83,12 +83,14 @@ const mockNlpEntityService = {
|
|||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
lookups: ['trait'],
|
lookups: ['trait'],
|
||||||
id: '67e3e41eff551ca5be70559c',
|
id: '67e3e41eff551ca5be70559c',
|
||||||
|
weight: 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (query.name === 'firstname') {
|
if (query.name === 'firstname') {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
lookups: ['trait'],
|
lookups: ['trait'],
|
||||||
id: '67e3e41eff551ca5be70559d',
|
id: '67e3e41eff551ca5be70559d',
|
||||||
|
weight: 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return Promise.resolve(null); // Default response if the entity isn't found
|
return Promise.resolve(null); // Default response if the entity isn't found
|
||||||
@ -444,7 +446,7 @@ describe('BlockService', () => {
|
|||||||
expect(nlpEntityService.findOne).toHaveBeenCalledWith(
|
expect(nlpEntityService.findOne).toHaveBeenCalledWith(
|
||||||
{ name: p.entity },
|
{ name: p.entity },
|
||||||
undefined,
|
undefined,
|
||||||
{ _id: 0, lookups: 1 },
|
{ _id: 0, lookups: 1, weight: 1 },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -464,7 +466,7 @@ describe('BlockService', () => {
|
|||||||
expect(nlpEntityService.findOne).toHaveBeenCalledWith(
|
expect(nlpEntityService.findOne).toHaveBeenCalledWith(
|
||||||
{ name: p.entity },
|
{ name: p.entity },
|
||||||
undefined,
|
undefined,
|
||||||
{ _id: 0, lookups: 1 },
|
{ _id: 0, lookups: 1, weight: 1 },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -348,12 +348,6 @@ export class BlockService extends BaseService<
|
|||||||
async matchBestNLP(
|
async matchBestNLP(
|
||||||
blocks: Block[] | BlockFull[] | undefined,
|
blocks: Block[] | BlockFull[] | undefined,
|
||||||
): Promise<Block | BlockFull | undefined> {
|
): Promise<Block | BlockFull | undefined> {
|
||||||
// @TODO make lookup scores configurable in hexabot settings
|
|
||||||
const lookupScores: { [key: string]: number } = {
|
|
||||||
trait: 2,
|
|
||||||
keywords: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// No blocks to check against
|
// No blocks to check against
|
||||||
if (blocks?.length === 0 || !blocks) {
|
if (blocks?.length === 0 || !blocks) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -380,18 +374,14 @@ export class BlockService extends BaseService<
|
|||||||
return await this.entityService.findOne(
|
return await this.entityService.findOne(
|
||||||
{ name: entityName },
|
{ name: entityName },
|
||||||
undefined,
|
undefined,
|
||||||
{ lookups: 1, _id: 0 },
|
{ lookups: 1, weight: 1, _id: 0 },
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
nlpScore += entityLookups.reduce((score, entityLookup) => {
|
nlpScore += entityLookups.reduce((score, entityLookup) => {
|
||||||
if (
|
if (entityLookup && entityLookup.lookups[0] && entityLookup.weight) {
|
||||||
entityLookup &&
|
return score + entityLookup.weight; // Add points based on the Nlp entity associated weight
|
||||||
entityLookup.lookups[0] &&
|
|
||||||
lookupScores[entityLookup.lookups[0]]
|
|
||||||
) {
|
|
||||||
return score + lookupScores[entityLookup.lookups[0]]; // Add points based on the lookup type
|
|
||||||
}
|
}
|
||||||
return score; // Return the current score if no match
|
return score; // Return the current score if no match
|
||||||
}, 0);
|
}, 0);
|
||||||
|
@ -41,7 +41,7 @@ export default [
|
|||||||
{
|
{
|
||||||
group: WEB_CHANNEL_NAMESPACE,
|
group: WEB_CHANNEL_NAMESPACE,
|
||||||
label: 'greeting_message',
|
label: 'greeting_message',
|
||||||
value: 'Welcome! Ready to start a conversation with our chatbot?',
|
value: '',
|
||||||
type: SettingType.textarea,
|
type: SettingType.textarea,
|
||||||
translatable: true,
|
translatable: true,
|
||||||
},
|
},
|
||||||
|
@ -139,6 +139,7 @@ describe('BaseNlpHelper', () => {
|
|||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
builtin: false,
|
builtin: false,
|
||||||
lookups: [],
|
lookups: [],
|
||||||
|
weight: 1,
|
||||||
},
|
},
|
||||||
entity2: {
|
entity2: {
|
||||||
id: new ObjectId().toString(),
|
id: new ObjectId().toString(),
|
||||||
@ -147,6 +148,7 @@ describe('BaseNlpHelper', () => {
|
|||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
builtin: false,
|
builtin: false,
|
||||||
lookups: [],
|
lookups: [],
|
||||||
|
weight: 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
jest.spyOn(NlpValue, 'getValueMap').mockReturnValue({
|
jest.spyOn(NlpValue, 'getValueMap').mockReturnValue({
|
||||||
@ -207,6 +209,7 @@ describe('BaseNlpHelper', () => {
|
|||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
builtin: false,
|
builtin: false,
|
||||||
lookups: [],
|
lookups: [],
|
||||||
|
weight: 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -109,6 +109,7 @@ describe('NlpEntityController', () => {
|
|||||||
) as NlpEntityFull['values'],
|
) as NlpEntityFull['values'],
|
||||||
lookups: curr.lookups!,
|
lookups: curr.lookups!,
|
||||||
builtin: curr.builtin!,
|
builtin: curr.builtin!,
|
||||||
|
weight: curr.weight!,
|
||||||
});
|
});
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
@ -163,6 +164,7 @@ describe('NlpEntityController', () => {
|
|||||||
name: 'sentiment',
|
name: 'sentiment',
|
||||||
lookups: ['trait'],
|
lookups: ['trait'],
|
||||||
builtin: false,
|
builtin: false,
|
||||||
|
weight: 1,
|
||||||
};
|
};
|
||||||
const result = await nlpEntityController.create(sentimentEntity);
|
const result = await nlpEntityController.create(sentimentEntity);
|
||||||
expect(result).toEqualPayload(sentimentEntity);
|
expect(result).toEqualPayload(sentimentEntity);
|
||||||
@ -214,6 +216,7 @@ describe('NlpEntityController', () => {
|
|||||||
updatedAt: firstNameEntity!.updatedAt,
|
updatedAt: firstNameEntity!.updatedAt,
|
||||||
lookups: firstNameEntity!.lookups,
|
lookups: firstNameEntity!.lookups,
|
||||||
builtin: firstNameEntity!.builtin,
|
builtin: firstNameEntity!.builtin,
|
||||||
|
weight: firstNameEntity!.weight,
|
||||||
};
|
};
|
||||||
const result = await nlpEntityController.findOne(firstNameEntity!.id, [
|
const result = await nlpEntityController.findOne(firstNameEntity!.id, [
|
||||||
'values',
|
'values',
|
||||||
@ -238,6 +241,7 @@ describe('NlpEntityController', () => {
|
|||||||
doc: '',
|
doc: '',
|
||||||
lookups: ['trait'],
|
lookups: ['trait'],
|
||||||
builtin: false,
|
builtin: false,
|
||||||
|
weight: 1,
|
||||||
};
|
};
|
||||||
const result = await nlpEntityController.updateOne(
|
const result = await nlpEntityController.updateOne(
|
||||||
firstNameEntity!.id,
|
firstNameEntity!.id,
|
||||||
|
@ -372,6 +372,7 @@ describe('NlpSampleController', () => {
|
|||||||
lookups: ['trait'],
|
lookups: ['trait'],
|
||||||
doc: '',
|
doc: '',
|
||||||
builtin: false,
|
builtin: false,
|
||||||
|
weight: 1,
|
||||||
};
|
};
|
||||||
const priceValueEntity = await nlpEntityService.findOne({
|
const priceValueEntity = await nlpEntityService.findOne({
|
||||||
name: 'intent',
|
name: 'intent',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2024 Hexastack. All rights reserved.
|
* Copyright © 2025 Hexastack. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||||
@ -12,6 +12,7 @@ import {
|
|||||||
IsBoolean,
|
IsBoolean,
|
||||||
IsIn,
|
IsIn,
|
||||||
IsNotEmpty,
|
IsNotEmpty,
|
||||||
|
IsNumber,
|
||||||
IsOptional,
|
IsOptional,
|
||||||
IsString,
|
IsString,
|
||||||
Matches,
|
Matches,
|
||||||
@ -47,6 +48,14 @@ export class NlpEntityCreateDto {
|
|||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
builtin?: boolean;
|
builtin?: boolean;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: 'Nlp entity associated weight for next block triggering',
|
||||||
|
type: Number,
|
||||||
|
})
|
||||||
|
@IsNumber()
|
||||||
|
@IsOptional()
|
||||||
|
weight?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NlpEntityDto = DtoConfig<{
|
export type NlpEntityDto = DtoConfig<{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2024 Hexastack. All rights reserved.
|
* Copyright © 2025 Hexastack. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||||
@ -58,6 +58,12 @@ export class NlpEntityStub extends BaseSchema {
|
|||||||
@Prop({ type: Boolean, default: false })
|
@Prop({ type: Boolean, default: false })
|
||||||
builtin: boolean;
|
builtin: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity's weight used to determine the next block to trigger in the conversational flow.
|
||||||
|
*/
|
||||||
|
@Prop({ type: Number, default: 1, unique: false })
|
||||||
|
weight: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a map object for entities
|
* Returns a map object for entities
|
||||||
* @param entities - Array of entities
|
* @param entities - Array of entities
|
||||||
|
5
api/src/utils/test/fixtures/nlpentity.ts
vendored
5
api/src/utils/test/fixtures/nlpentity.ts
vendored
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2024 Hexastack. All rights reserved.
|
* Copyright © 2025 Hexastack. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||||
@ -17,18 +17,21 @@ export const nlpEntityFixtures: NlpEntityCreateDto[] = [
|
|||||||
lookups: ['trait'],
|
lookups: ['trait'],
|
||||||
doc: '',
|
doc: '',
|
||||||
builtin: false,
|
builtin: false,
|
||||||
|
weight: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'first_name',
|
name: 'first_name',
|
||||||
lookups: ['keywords'],
|
lookups: ['keywords'],
|
||||||
doc: '',
|
doc: '',
|
||||||
builtin: false,
|
builtin: false,
|
||||||
|
weight: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'built_in',
|
name: 'built_in',
|
||||||
lookups: ['trait'],
|
lookups: ['trait'],
|
||||||
doc: '',
|
doc: '',
|
||||||
builtin: true,
|
builtin: true,
|
||||||
|
weight: 1,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -348,6 +348,7 @@
|
|||||||
"nlp_lookup_trait": "Trait",
|
"nlp_lookup_trait": "Trait",
|
||||||
"doc": "Documentation",
|
"doc": "Documentation",
|
||||||
"builtin": "Built-in?",
|
"builtin": "Built-in?",
|
||||||
|
"weight": "Weight",
|
||||||
"dataset": "Dataset",
|
"dataset": "Dataset",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
|
@ -347,6 +347,7 @@
|
|||||||
"nlp_lookup_trait": "Trait",
|
"nlp_lookup_trait": "Trait",
|
||||||
"synonyms": "Synonymes",
|
"synonyms": "Synonymes",
|
||||||
"doc": "Documentation",
|
"doc": "Documentation",
|
||||||
|
"weight": "Poids",
|
||||||
"builtin": "Intégré?",
|
"builtin": "Intégré?",
|
||||||
"dataset": "Données",
|
"dataset": "Données",
|
||||||
"yes": "Oui",
|
"yes": "Oui",
|
||||||
|
@ -165,6 +165,16 @@ const NlpEntity = () => {
|
|||||||
resizable: false,
|
resizable: false,
|
||||||
renderHeader,
|
renderHeader,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
maxWidth: 210,
|
||||||
|
field: "weight",
|
||||||
|
headerName: t("label.weight"),
|
||||||
|
renderCell: (val) => <Chip label={val.value} variant="title" />,
|
||||||
|
sortable: true,
|
||||||
|
disableColumnMenu: true,
|
||||||
|
resizable: false,
|
||||||
|
renderHeader,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
maxWidth: 90,
|
maxWidth: 90,
|
||||||
field: "builtin",
|
field: "builtin",
|
||||||
|
@ -60,6 +60,7 @@ export const NlpEntityVarForm: FC<ComponentFormProps<INlpEntity>> = ({
|
|||||||
name: data?.name || "",
|
name: data?.name || "",
|
||||||
doc: data?.doc || "",
|
doc: data?.doc || "",
|
||||||
lookups: data?.lookups || ["keywords"],
|
lookups: data?.lookups || ["keywords"],
|
||||||
|
weight: data?.weight || 1,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const validationRules = {
|
const validationRules = {
|
||||||
@ -82,6 +83,7 @@ export const NlpEntityVarForm: FC<ComponentFormProps<INlpEntity>> = ({
|
|||||||
reset({
|
reset({
|
||||||
name: data.name,
|
name: data.name,
|
||||||
doc: data.doc,
|
doc: data.doc,
|
||||||
|
weight: data.weight,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
reset();
|
reset();
|
||||||
@ -130,6 +132,14 @@ export const NlpEntityVarForm: FC<ComponentFormProps<INlpEntity>> = ({
|
|||||||
multiline={true}
|
multiline={true}
|
||||||
/>
|
/>
|
||||||
</ContentItem>
|
</ContentItem>
|
||||||
|
<ContentItem>
|
||||||
|
<Input
|
||||||
|
label={t("label.weight")}
|
||||||
|
{...register("weight", { valueAsNumber: true })}
|
||||||
|
type="number"
|
||||||
|
inputProps={{ min: 1, step: 1 }} // Restricts input to positive integers only
|
||||||
|
/>
|
||||||
|
</ContentItem>
|
||||||
</ContentContainer>
|
</ContentContainer>
|
||||||
</form>
|
</form>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright © 2024 Hexastack. All rights reserved.
|
* Copyright © 2025 Hexastack. All rights reserved.
|
||||||
*
|
*
|
||||||
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
|
||||||
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
|
||||||
@ -19,6 +19,7 @@ export interface INlpEntityAttributes {
|
|||||||
lookups: Lookup[];
|
lookups: Lookup[];
|
||||||
doc?: string;
|
doc?: string;
|
||||||
builtin?: boolean;
|
builtin?: boolean;
|
||||||
|
weight: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NlpLookups {
|
export enum NlpLookups {
|
||||||
|
Loading…
Reference in New Issue
Block a user