nlp.js 无法提取实体

imzjd6km  于 4个月前  发布在  其他
关注(0)|答案(9)|浏览(51)

描述问题

我想从这个包中制作一个聊天机器人,但它无法正确识别实体。我尝试了很多解决方案,但都没有用。如果有人能帮忙解决这个问题,我将非常感激。

重现问题

重现问题的步骤:

  1. 安装node.js。我使用的是v20.0.0
  2. 安装最新版本的node-nlp。我使用的是v4.27.0
  3. 现在你可以运行以下代码:
const { NlpManager } = require("node-nlp");

const manager = new NlpManager({ languages: ["en"], forceNER: true });

manager.addNamedEntityText('hero', 'spiderman', 'en')

manager.addDocument("en", "My name is %name%", "saveName");
manager.addDocument("en", "I will be traveling on %date%", "saveDate");
manager.addDocument("en", "I saw %hero%", "sawHero");

manager.addAnswer("en", "saveName", "Nice talking to you {{name}}");
manager.addAnswer("en", "saveDate", "Have safe journey on {{date}}");
manager.addAnswer("en", "sawHero", "Really you saw {{hero}}!");

(async () => {
  await manager.train();
  manager
    .process("en", "My name is John")
    .then((response) => console.log(response.answer))
    .then(() => manager.process("en", "I will be traveling on 04 June"))
    .then((response) => console.log(response.answer))
    .then(() => manager.process("en", "I saw spiderman"))
    .then((response) => console.log(response.answer));
})();
  1. 上述代码的输出如下:
Nice talking to you {{name}}
Have safe journey on 04 June 
Really you saw spiderman!

预期行为

Nice talking to you John
Have safe journey on 04 June 
Really you saw spiderman!
  1. 如果我删除了manager.addNamedEntityText('hero', 'spiderman', 'en')这一行,那么输出将会是:
Nice talking to you John
Have safe journey on 04 June 
Really you saw {{hero}}!

预期行为

Nice talking to you John
Have safe journey on 04 June 
Really you saw spiderman!

所以主要问题在于,当我不传递namedEntity时,它完全无法识别实体。我不太确定它是如何识别到date的。我想实现类似于date的功能,以便在其他变量的情况下也能识别实体。由于我不了解文本中的实体,所以无法添加命名实体。如果有人有其他解决这个问题的方法,那将是非常有帮助的。

jfewjypa

jfewjypa1#

请尝试以下代码:

nlp.slotManager.addSlot('travel', 'fromCity', true, { en: 'From where you are traveling? {{fromCity}}' });
nlp.addDocument('en', 'I want to travel from @fromCity to @toCity', 'travel')
nlp.addNerRuleOptionTexts('en', 'fromCity', ["Israel", "USA"]);

nlp.addNerRuleOptionTexts('en', 'toCity', ["Israel", "USA"]);

nlp.addAnswer('en', 'greetings.hello', 'Greetings!');
await nlp.train();
const response = await nlp.process('en', 'I want to travel from Israel to USA');
console.log(response.entities[1].utteranceText);


希望这能帮到你 👍
ps:这是因为文档需要为这个项目更好地组织一下!提取槽位等方法在NLP.js的不同版本中有所改变。但这应该适用于您在问题中列出的版本。
4zcjmb1e

4zcjmb1e2#

感谢您的回复@MarketingPip,但在这种情况下,您已经定义了fromCitytoCity的列表。现在NLP只会查找这两个城市,但如果我传递其他内容会怎样?那会起作用吗?

wydwbb8l

wydwbb8l3#

@Jayesh-Patidar,你能发布非工作呼叫的完整响应对象吗?

kx1ctssn

kx1ctssn4#

感谢您的回复@MarketingPip,但在这种情况下,您也定义了fromCitytoCity的列表。现在NLP只会查找这两个城市,但如果我传递其他内容会怎样?那会起作用吗?

非常感谢您!很抱歉我应该再提供一个例子来帮助澄清未定义的被认定实体的情况。

我现在正在使用手机 - 我不能确认,但我认为/回忆起文档中应该有某种符号/方法可以在语料库中填写一个“空槽”。

您必须深入挖掘/或者当我稍后在电脑上时,我会深入研究我的随机代码片段宝箱,看看是否有与我上面提供的最后一个示例类似的其他东西。👆

0mkxixxg

0mkxixxg5#

@Apollon77 Below are the responses for my code
Input: My name is John

{ locale: 'en',
  utterance: 'My name is John',
  settings: undefined,
  languageGuessed: false,
  localeIso2: 'en',
  language: 'English',
  nluAnswer: { classifications: [
            { intent: 'saveName', score: 1
            },
            { intent: 'sawHero', score: 0
            },
            { intent: 'saveDate', score: 0
            }
        ],
     entities: undefined,
     explanation: undefined
    },
  classifications: [
        { intent: 'saveName', score: 1
        },
        { intent: 'sawHero', score: 0
        },
        { intent: 'saveDate', score: 0
        }
    ],
  intent: 'saveName',
  score: 1,
  domain: 'default',
  sourceEntities: [],
  entities: [],
  answers: [
        { answer: 'Nice talking to you {{name}}', opts: undefined
        }
    ],
  answer: 'Nice talking to you {{name}}',
  actions: [],
  sentiment: { score: 0.375,
     numWords: 4,
     numHits: 1,
     average: 0.09375,
     type: 'senticon',
     locale: 'en',
     vote: 'positive'
    }
}

Input: I will be traveling on 04 June

{ locale: 'en',
  utterance: 'I will be traveling on 04 June',
  settings: undefined,
  languageGuessed: false,
  localeIso2: 'en',
  language: 'English',
  nluAnswer: { classifications: [
            { intent: 'saveDate', score: 0.9927472726951043
            },
            { intent: 'sawHero', score: 0.007252727304895593
            }
        ],
     entities: undefined,
     explanation: undefined
    },
  classifications: [
        { intent: 'saveDate', score: 0.9927472726951043
        },
        { intent: 'sawHero', score: 0.007252727304895593
        }
    ],
  intent: 'saveDate',
  score: 0.9927472726951043,
  domain: 'default',
  sourceEntities: [
        { start: 23,
       end: 24,
       resolution: { value: '4'
            },
       text: '04',
       typeName: 'number',
       entity: 'number'
        },
        { start: 23,
       end: 29,
       resolution: { values: [
                    { timex: 'XXXX-06-04', type: 'date', value: '2023-06-04'
                    },
                    { timex: 'XXXX-06-04', type: 'date', value: '2024-06-04'
                    }
                ]
            },
       text: '04 june',
       typeName: 'datetimeV2.date',
       entity: 'date'
        }
    ],
  entities: [
        { start: 23,
       end: 24,
       len: 2,
       accuracy: 0.95,
       sourceText: '04',
       utteranceText: '04',
       entity: 'number',
       rawEntity: 'number',
       resolution: { strValue: '4', value: 4, subtype: 'integer'
            }
        },
        { start: 23,
       end: 29,
       len: 7,
       accuracy: 0.95,
       sourceText: '04 June',
       utteranceText: '04 June',
       entity: 'date',
       rawEntity: 'datetimeV2.date',
       resolution: { type: 'interval',
          timex: 'XXXX-06-04',
          strPastValue: '2023-06-04',
          pastDate: Sun Jun 04 2023 05: 30: 00 GMT+0530 (India Standard Time),
          strFutureValue: '2024-06-04',
          futureDate: Tue Jun 04 2024 05: 30: 00 GMT+0530 (India Standard Time)
            }
        }
    ],
  answers: [
        { answer: 'Have safe journey on 04 June', opts: undefined
        }
    ],
  answer: 'Have safe journey on 04 June',
  actions: [],
  sentiment: { score: 0.813,
     numWords: 7,
     numHits: 3,
     average: 0.11614285714285713,
     type: 'senticon',
     locale: 'en',
     vote: 'positive'
    }
}

Input: I saw spiderman

{ locale: 'en',
  utterance: 'I saw spiderman',
  settings: undefined,
  languageGuessed: false,
  localeIso2: 'en',
  language: 'English',
  explanation: [
        { token: '', stem: '##exact', weight: 1
        }
    ],
  classifications: [
        { intent: 'sawHero', score: 1
        },
        { intent: 'saveName', score: 0
        },
        { intent: 'saveDate', score: 0
        }
    ],
  intent: 'sawHero',
  score: 1,
  domain: 'default',
  optionalUtterance: 'I saw %hero%',
  sourceEntities: [],
  entities: [
        { start: 6,
       end: 14,
       len: 9,
       levenshtein: 0,
       accuracy: 1,
       entity: 'hero',
       type: 'enum',
       option: 'spiderman',
       sourceText: 'spiderman',
       utteranceText: 'spiderman'
        }
    ],
  answers: [
        { answer: 'Really you saw spiderman!', opts: undefined
        }
    ],
  answer: 'Really you saw spiderman!',
  actions: [],
  sentiment: { score: 0.375,
     numWords: 3,
     numHits: 1,
     average: 0.125,
     type: 'senticon',
     locale: 'en',
     vote: 'positive'
    }
}

You can clearly see when I passed input as My name is John then it is not able to extract entities. I want to extract the name John from then text and return it in response in place of {{name}} .
Thank you

ui7jx7zq

ui7jx7zq6#

@Jayesh-Patidar - 这里有你需要的完整工作示例。

import { containerBootstrap } from "https://cdn.skypack.dev/@nlpjs/core@4.26.1";
import { Nlp } from "https://cdn.skypack.dev/@nlpjs/nlp@4.26.1";
import { LangEn } from "https://cdn.skypack.dev/@nlpjs/lang-en-min@4.26.1";

(async () => {
  const container = await containerBootstrap();
  container.use(Nlp);
  container.use(LangEn);
  const nlp = container.get('nlp');
  nlp.settings.autoSave = false;
  nlp.addLanguage('en');
  nlp.slotManager.addSlot('travel', 'fromCity', true);
  nlp.addDocument('en', 'I want to travel from %fromCity% to @toCity', 'travel')

  
    nlp.addNerBetweenLastCondition('en', 'fromCity', 'from', 'to');
  nlp.addNerAfterLastCondition('en', 'fromCity', 'from');
  nlp.addNerBetweenLastCondition('en', 'toCity', 'to', 'from');
  nlp.addNerAfterLastCondition('en', 'toCity', 'to');
 
  nlp.slotManager.addSlot('travel', 'fromCity', true);
  nlp.slotManager.addSlot('travel', 'toCity', true);
  
  
  await nlp.train();
  const response = await nlp.process('en', 'I want to travel from here to you go bro!');
  console.log(response.entities[0].utteranceText); // Outputs: here
   console.log(response.entities[1].utteranceText); // Outputs: you go bro!
})();

希望这对你有帮助。
Ps:你可以使用正则表达式匹配提取插槽。但是匹配任何内容,例如 (.*) -会让库表现得有些奇怪。

s1ag04yj

s1ag04yj7#

感谢您的回复。很抱歉回复晚了。

我尝试了您的解决方案,但这次它运行正常,提取了fromCitytoCity实体。但是现在假设我们已经为这个意图找到了答案,其中包含这些实体,那么它就不会在答案中加载实体。

const { Nlp } = require('@nlpjs/nlp');
const { LangEn } = require('@nlpjs/lang-en-min');

(async () => {
	const container = await containerBootstrap();
	container.use(Nlp);
	container.use(LangEn);
	const nlp = container.get('nlp');
	nlp.settings.autoSave = false;
	nlp.addLanguage('en');
	nlp.slotManager.addSlot('travel', 'fromCity', true);
	nlp.addDocument('en', 'I want to travel from %fromCity% to @toCity', 'travel');

	nlp.addNerBetweenLastCondition('en', 'fromCity', 'from', 'to');
	nlp.addNerAfterLastCondition('en', 'fromCity', 'from');
	nlp.addNerBetweenLastCondition('en', 'toCity', 'to', 'from');
	nlp.addNerAfterLastCondition('en', 'toCity', 'to');

	nlp.slotManager.addSlot('travel', 'fromCity', true);
	nlp.slotManager.addSlot('travel', 'toCity', true);

	nlp.addAnswer('en', 'travel', 'Happy journey {{fromCity}} to {{toCity}}');

	await nlp.train();
	const response = await nlp.process('en', 'I want to travel from here to you go bro!');
	console.log(response.entities[0].utteranceText); // Outputs: here
	console.log(response.entities[1].utteranceText); // Outputs: you go bro!
	console.log(response.answer); // Happy journey {{fromCity}} to {{toCity}}
})();

之前添加答案的语法对于命名实体来说是正常的。

您能在这里帮助我吗?

hfsqlsce

hfsqlsce8#

出于某种原因,我似乎无法在我这边实现这个功能。尽管我会尝试使用正则表达式匹配等方法进行替换(虽然这不太方便),但这可能只是一个临时解决方案,直到你从这个仓库的维护者那里得到答案。例如:@axa-group

/// Create a for loop with all your entities. 

let entities = response.entities
let replacedText = response.answer

for (let item in entities){
// Regex for example {{.*}}
  replacedText = replacedText.replace(regex_for_your_entities, "entity"); // Happy journey {{fromCity}} to {{toCity}}
}

根据你的需求和适当的正则表达式调整这段代码!
我很想帮助你更多,但请记住我不是这个项目的贡献者或维护者。希望我们能从他们那里得到更多的输入。
也许在这里加个标签/提及会有帮助 - @jesus-seijas-sp
祝你好运,周末愉快,@Jayesh-Patidar。 ✌️

6bc51xsx

6bc51xsx9#

感谢你的帮助 @MarketingPip。在等待他人回复的同时,我会尝试你提供的解决方案。

相关问题