Rasa如何使用通配符实体实现无需预定义实体列表的食谱搜索功能
Rasa 2.6 免枚举食谱实体实现方案
Rasa 本身不原生支持你提到的[*]通配符实体标注语法,但可以通过以下两种方案实现不用逐个罗列食谱实体的需求:
方案1:使用正则实体提取(实现成本最低)
适合查询句式相对固定的场景,不需要修改代码,只要改配置即可:
- 在
config.yml的pipeline中添加RegexEntityExtractor组件:
pipeline: # 保留原有的分词、特征提取等前置组件 - name: RegexEntityExtractor use_word_boundaries: False # 配置意图关联的实体提取规则 intent_regex_filters: - intent_name: cooking_baking # 匹配句式中食谱名称的位置,括号内的内容会被提取为实体 regex_pattern: "show me a recipe for (.+)" entity_name: cookingAndBaking # 取第一个正则捕获组的内容作为实体值 group_index: 1
- NLU训练数据只需要保留足够识别
cooking_baking意图的示例即可,不需要逐个标注所有食谱实体:
- intent: cooking_baking examples: | - show me a recipe for cake - show me a recipe for whatever - find me a recipe for xxx
方案2:自定义实体提取组件(适配灵活句式)
如果你的用户查询句式变化多,正则覆盖不全,可以自己写一个轻量的实体提取组件:
- 新建自定义组件文件
custom_extractors.py,代码如下:
from rasa.nlu.extractors.extractor import EntityExtractor from rasa.shared.nlu.training_data.message import Message from typing import Any, List class RecipeNameExtractor(EntityExtractor): provides = ["entities"] requires = ["intent"] language_list = ["en"] # 中文场景改成"zh"即可 def process(self, message: Message, **kwargs: Any) -> None: # 只处理食谱查询意图 if message.get("intent", {}).get("name") != "cooking_baking": return text = message.text entities = message.get("entities", []) # 可以扩展多个匹配规则适配不同问法 match_rules = [ "show me a recipe for ", "find me a recipe for ", "how to make " ] for prefix in match_rules: if text.lower().startswith(prefix.lower()): recipe_name = text[len(prefix):].strip() entities.append({ "entity": "cookingAndBaking", "value": recipe_name, "start": len(prefix), "end": len(text), "extractor": self.name }) break message.set("entities", entities, add_to_output=True)
- 在
config.yml的pipeline中注册该组件:
pipeline: # 保留原有的前置组件,放在其他NER组件之前即可 - name: custom_extractors.RecipeNameExtractor
- 训练数据只需要标注意图示例,完全不需要标注实体。
注意事项
- 两种方案都可以在Rasa 2.6版本正常运行,不需要升级框架
- 如果需要支持多语言,只要修改对应的匹配规则即可
- 自定义组件的规则可以随时扩展,不需要修改训练数据或者实体列表
内容的提问来源于stack exchange,提问作者goodkid38
相关产品推荐
相关产品推荐

