diff --git a/nonebot/__init__.py b/nonebot/__init__.py index e6aba0de..c2afd951 100644 --- a/nonebot/__init__.py +++ b/nonebot/__init__.py @@ -106,7 +106,8 @@ from .plugin import (load_plugin, load_plugins, load_builtin_plugins, get_loaded_plugins) from .message import message_preprocessor, Message, MessageSegment from .command import on_command, CommandSession, CommandGroup -from .natural_language import on_natural_language, NLPSession, NLPResult +from .natural_language import (on_natural_language, NLPSession, NLPResult, + IntentCommand) from .notice_request import (on_notice, NoticeSession, on_request, RequestSession) @@ -117,6 +118,6 @@ __all__ = [ 'get_loaded_plugins', 'message_preprocessor', 'Message', 'MessageSegment', 'on_command', 'CommandSession', 'CommandGroup', - 'on_natural_language', 'NLPSession', 'NLPResult', + 'on_natural_language', 'NLPSession', 'NLPResult', 'IntentCommand', 'on_notice', 'NoticeSession', 'on_request', 'RequestSession', ] diff --git a/nonebot/natural_language.py b/nonebot/natural_language.py index a93ef61e..726c28c6 100644 --- a/nonebot/natural_language.py +++ b/nonebot/natural_language.py @@ -72,10 +72,30 @@ class NLPSession(BaseSession): class NLPResult(NamedTuple): + """ + Deprecated. + Use class IntentCommand instead. + """ confidence: float cmd_name: Union[str, CommandName_T] cmd_args: Optional[CommandArgs_T] = None + def to_intent_command(self): + return IntentCommand(confidence=self.confidence, + name=self.cmd_name, + args=self.cmd_args, + current_arg=None) + + +class IntentCommand(NamedTuple): + """ + To represent a command that we think the user may be intended to call. + """ + confidence: float + name: Union[str, CommandName_T] + args: Optional[CommandArgs_T] = None + current_arg: Optional[str] = None + async def handle_natural_language(bot: NoneBot, ctx: Context_T) -> bool: """ @@ -135,24 +155,34 @@ async def handle_natural_language(bot: NoneBot, ctx: Context_T) -> bool: futures.append(asyncio.ensure_future(p.func(session))) if futures: - # wait for possible results, and sort them by confidence - results = [] + # wait for intent commands, and sort them by confidence + intent_commands = [] for fut in futures: try: - results.append(await fut) + res = await fut + if isinstance(res, NLPResult): + intent_commands.append(res.to_intent_command()) + elif isinstance(res, IntentCommand): + intent_commands.append(res) except Exception as e: logger.error('An exception occurred while running ' 'some natural language processor:') logger.exception(e) - results = sorted(filter(lambda r: r, results), - key=lambda r: r.confidence, reverse=True) - logger.debug(f'NLP results: {results}') - if results and results[0].confidence >= 60.0: - # choose the result with highest confidence - logger.debug(f'NLP result with highest confidence: {results[0]}') - return await call_command(bot, ctx, results[0].cmd_name, - args=results[0].cmd_args, - check_perm=False) + + intent_commands.sort(key=lambda ic: ic.confidence, reverse=True) + logger.debug(f'Intent commands: {intent_commands}') + + if intent_commands and intent_commands[0].confidence >= 60.0: + # choose the intent command with highest confidence + chosen_cmd = intent_commands[0] + logger.debug( + f'Intent command with highest confidence: {chosen_cmd}') + return await call_command( + bot, ctx, chosen_cmd.name, + args=chosen_cmd.args, + current_arg=chosen_cmd.current_arg, + check_perm=False + ) else: - logger.debug('No NLP result having enough confidence') + logger.debug('No intent command has enough confidence') return False