关键词触发是最基础的机器人功能——用户发"菜单"返回菜单,发"客服"转人工。单个关键词好办,关键词一多问题就来了——匹配效率下降、一个消息命中多个词、触发结果不稳定。本文讲关键词触发的三个关键点:匹配算法、优先级冲突、动作编排。

一、匹配算法选型

关键词规模决定算法。几十个关键词,直接遍历列表逐个判断包含关系就够了,简单可靠。上千个关键词,遍历就有性能问题——每条消息都要跑上千次字符串比较,消息量一上来CPU吃不住。这时候要用Trie树或AC自动机,一次扫描消息文本就能命中所有关键词。

还有一层是模糊匹配。用户输入往往不规范——该发"菜单"发成"菜单呢""菜单位置",严格相等匹配就漏了。用包含匹配(关键词是消息的子串即命中)能覆盖大部分情况。同义词也要处理——"客服""人工""找个人"指同一件事,做同义词归并成同一个触发词。关键词匹配和消息接收的接口在 Eyun 开发文档 中有对应说明。

二、优先级与冲突解决

一条消息可能命中多个关键词。用户发"客服电话多少",同时命中"客服"和"电话"。两个关键词对应两个不同的动作,先执行哪个必须定规则,否则触发结果随机,用户体验不稳定。

优先级规则按这个顺序定:精确匹配优先于包含匹配,长关键词优先于短关键词,专属关键词优先于通用关键词。规则定完要落成配置,不能靠代码里的书写顺序决定,书写顺序一改行为就变。触发条件和动作配置的接口在 Eyun 开发文档 中有对应能力。

三、命中动作编排

关键词命中后执行动作——回复固定文本、转人工、调业务接口。动作可以是多个串联,比如先回复"正在为你转接"再触发转人工。

动作要有超时和失败处理。调外部接口的动作可能超时,超时后要有降级回复,不能用户发了消息机器人没反应。动作执行结果要记录,方便排查为什么这次触发没生效。

关键词触发方案对照

关键词规模

匹配算法

复杂度

适用场景

几十个

遍历包含

简单

基础功能

上千个

Trie/AC自动机

中等

高频消息

含同义词

归并+包含

中等

用户口语化

关键词触发与优先级实现

class KeywordTrigger:
    def __init__(self):
        self.keywords = []                   # [(关键词, 动作, 优先级)]
        self.synonyms = {}                   # 同义词映射

    def normalize(self, text):
        # 同义词归并:统一成标准词
        for alias, std in self.synonyms.items():
            if alias in text:
                text = text.replace(alias, std)
        return text

    def match(self, text):
        # 匹配:收集所有命中词
        text = self.normalize(text)
        hits = []
        for kw, action, priority in self.keywords:
            if kw in text:                   # 包含匹配
                hits.append((len(kw), priority, kw, action))
        if not hits:
            return None
        # 优先级:长词优先,再按配置优先级
        hits.sort(key=lambda x: (-x[0], -x[1]))
        return hits[0]                       # 取最高优先级

    def trigger(self, msg):
        result = self.match(msg.content)
        if not result:
            return None                      # 无命中正常处理
        _, _, kw, action = result
        return self.execute(action, msg)

    def execute(self, action, msg):
        # 动作编排:可串联多个动作
        for act in action["steps"]:
            try:
                if act["type"] == "reply":
                    send_wechat(msg.wxid, act["content"])
                elif act["type"] == "transfer":
                    self.to_human(msg)
                elif act["type"] == "api":
                    self.call_business_api(msg, act["params"])
            except TimeoutError:
                send_wechat(msg.wxid, "处理超时,请稍后重试")
                return "timeout"             # 超时降级
            except Exception as e:
                self.log_action_error(msg, act, e)
                return "error"
        return "ok"

    def register(self, keyword, action, priority=0):
        # 注册关键词和动作
        self.keywords.append((keyword, action, priority))

落地建议

匹配算法按规模选——几十个关键词遍历够用,上千个必须上Trie或AC自动机。模糊匹配要处理——包含匹配覆盖口语化输入,同义词归并避免漏触发。优先级要定规则——精确优先、长词优先,规则落配置不靠书写顺序。动作要能降级——外部接口超时给降级回复,不能用户发消息没反应。微信侧的消息接收和发送由 Eyun 这类个人微信API平台 提供,匹配算法和动作编排在自建服务实现,接口字段以平台开发文档为准。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐