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({
|
||||
lookups: ['trait'],
|
||||
id: '67e3e41eff551ca5be70559c',
|
||||
weight: 1,
|
||||
});
|
||||
}
|
||||
if (query.name === 'firstname') {
|
||||
return Promise.resolve({
|
||||
lookups: ['trait'],
|
||||
id: '67e3e41eff551ca5be70559d',
|
||||
weight: 1,
|
||||
});
|
||||
}
|
||||
return Promise.resolve(null); // Default response if the entity isn't found
|
||||
@ -444,7 +446,7 @@ describe('BlockService', () => {
|
||||
expect(nlpEntityService.findOne).toHaveBeenCalledWith(
|
||||
{ name: p.entity },
|
||||
undefined,
|
||||
{ _id: 0, lookups: 1 },
|
||||
{ _id: 0, lookups: 1, weight: 1 },
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -464,7 +466,7 @@ describe('BlockService', () => {
|
||||
expect(nlpEntityService.findOne).toHaveBeenCalledWith(
|
||||
{ name: p.entity },
|
||||
undefined,
|
||||
{ _id: 0, lookups: 1 },
|
||||
{ _id: 0, lookups: 1, weight: 1 },
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -348,12 +348,6 @@ export class BlockService extends BaseService<
|
||||
async matchBestNLP(
|
||||
blocks: 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
|
||||
if (blocks?.length === 0 || !blocks) {
|
||||
return undefined;
|
||||
@ -380,18 +374,14 @@ export class BlockService extends BaseService<
|
||||
return await this.entityService.findOne(
|
||||
{ name: entityName },
|
||||
undefined,
|
||||
{ lookups: 1, _id: 0 },
|
||||
{ lookups: 1, weight: 1, _id: 0 },
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
nlpScore += entityLookups.reduce((score, entityLookup) => {
|
||||
if (
|
||||
entityLookup &&
|
||||
entityLookup.lookups[0] &&
|
||||
lookupScores[entityLookup.lookups[0]]
|
||||
) {
|
||||
return score + lookupScores[entityLookup.lookups[0]]; // Add points based on the lookup type
|
||||
if (entityLookup && entityLookup.lookups[0] && entityLookup.weight) {
|
||||
return score + entityLookup.weight; // Add points based on the Nlp entity associated weight
|
||||
}
|
||||
return score; // Return the current score if no match
|
||||
}, 0);
|
||||
|
@ -41,7 +41,7 @@ export default [
|
||||
{
|
||||
group: WEB_CHANNEL_NAMESPACE,
|
||||
label: 'greeting_message',
|
||||
value: 'Welcome! Ready to start a conversation with our chatbot?',
|
||||
value: '',
|
||||
type: SettingType.textarea,
|
||||
translatable: true,
|
||||
},
|
||||
|
@ -139,6 +139,7 @@ describe('BaseNlpHelper', () => {
|
||||
updatedAt: new Date(),
|
||||
builtin: false,
|
||||
lookups: [],
|
||||
weight: 1,
|
||||
},
|
||||
entity2: {
|
||||
id: new ObjectId().toString(),
|
||||
@ -147,6 +148,7 @@ describe('BaseNlpHelper', () => {
|
||||
updatedAt: new Date(),
|
||||
builtin: false,
|
||||
lookups: [],
|
||||
weight: 1,
|
||||
},
|
||||
});
|
||||
jest.spyOn(NlpValue, 'getValueMap').mockReturnValue({
|
||||
@ -207,6 +209,7 @@ describe('BaseNlpHelper', () => {
|
||||
updatedAt: new Date(),
|
||||
builtin: false,
|
||||
lookups: [],
|
||||
weight: 1,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -109,6 +109,7 @@ describe('NlpEntityController', () => {
|
||||
) as NlpEntityFull['values'],
|
||||
lookups: curr.lookups!,
|
||||
builtin: curr.builtin!,
|
||||
weight: curr.weight!,
|
||||
});
|
||||
return acc;
|
||||
},
|
||||
@ -163,6 +164,7 @@ describe('NlpEntityController', () => {
|
||||
name: 'sentiment',
|
||||
lookups: ['trait'],
|
||||
builtin: false,
|
||||
weight: 1,
|
||||
};
|
||||
const result = await nlpEntityController.create(sentimentEntity);
|
||||
expect(result).toEqualPayload(sentimentEntity);
|
||||
@ -214,6 +216,7 @@ describe('NlpEntityController', () => {
|
||||
updatedAt: firstNameEntity!.updatedAt,
|
||||
lookups: firstNameEntity!.lookups,
|
||||
builtin: firstNameEntity!.builtin,
|
||||
weight: firstNameEntity!.weight,
|
||||
};
|
||||
const result = await nlpEntityController.findOne(firstNameEntity!.id, [
|
||||
'values',
|
||||
@ -238,6 +241,7 @@ describe('NlpEntityController', () => {
|
||||
doc: '',
|
||||
lookups: ['trait'],
|
||||
builtin: false,
|
||||
weight: 1,
|
||||
};
|
||||
const result = await nlpEntityController.updateOne(
|
||||
firstNameEntity!.id,
|
||||
|
@ -372,6 +372,7 @@ describe('NlpSampleController', () => {
|
||||
lookups: ['trait'],
|
||||
doc: '',
|
||||
builtin: false,
|
||||
weight: 1,
|
||||
};
|
||||
const priceValueEntity = await nlpEntityService.findOne({
|
||||
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:
|
||||
* 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,
|
||||
IsIn,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
Matches,
|
||||
@ -47,6 +48,14 @@ export class NlpEntityCreateDto {
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
builtin?: boolean;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Nlp entity associated weight for next block triggering',
|
||||
type: Number,
|
||||
})
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
weight?: number;
|
||||
}
|
||||
|
||||
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:
|
||||
* 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 })
|
||||
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
|
||||
* @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:
|
||||
* 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'],
|
||||
doc: '',
|
||||
builtin: false,
|
||||
weight: 1,
|
||||
},
|
||||
{
|
||||
name: 'first_name',
|
||||
lookups: ['keywords'],
|
||||
doc: '',
|
||||
builtin: false,
|
||||
weight: 1,
|
||||
},
|
||||
{
|
||||
name: 'built_in',
|
||||
lookups: ['trait'],
|
||||
doc: '',
|
||||
builtin: true,
|
||||
weight: 1,
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -348,6 +348,7 @@
|
||||
"nlp_lookup_trait": "Trait",
|
||||
"doc": "Documentation",
|
||||
"builtin": "Built-in?",
|
||||
"weight": "Weight",
|
||||
"dataset": "Dataset",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
|
@ -347,6 +347,7 @@
|
||||
"nlp_lookup_trait": "Trait",
|
||||
"synonyms": "Synonymes",
|
||||
"doc": "Documentation",
|
||||
"weight": "Poids",
|
||||
"builtin": "Intégré?",
|
||||
"dataset": "Données",
|
||||
"yes": "Oui",
|
||||
|
@ -165,6 +165,16 @@ const NlpEntity = () => {
|
||||
resizable: false,
|
||||
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,
|
||||
field: "builtin",
|
||||
|
@ -60,6 +60,7 @@ export const NlpEntityVarForm: FC<ComponentFormProps<INlpEntity>> = ({
|
||||
name: data?.name || "",
|
||||
doc: data?.doc || "",
|
||||
lookups: data?.lookups || ["keywords"],
|
||||
weight: data?.weight || 1,
|
||||
},
|
||||
});
|
||||
const validationRules = {
|
||||
@ -82,6 +83,7 @@ export const NlpEntityVarForm: FC<ComponentFormProps<INlpEntity>> = ({
|
||||
reset({
|
||||
name: data.name,
|
||||
doc: data.doc,
|
||||
weight: data.weight,
|
||||
});
|
||||
} else {
|
||||
reset();
|
||||
@ -130,6 +132,14 @@ export const NlpEntityVarForm: FC<ComponentFormProps<INlpEntity>> = ({
|
||||
multiline={true}
|
||||
/>
|
||||
</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>
|
||||
</form>
|
||||
</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:
|
||||
* 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[];
|
||||
doc?: string;
|
||||
builtin?: boolean;
|
||||
weight: number;
|
||||
}
|
||||
|
||||
export enum NlpLookups {
|
||||
|
Loading…
Reference in New Issue
Block a user