使用LLM助力移动应用程序进行语音和自然语言输入

2023年08月10日 由 alex 发表 451 0

介绍


大型语言模型(LLM)是一种能够有效处理自然语言的机器学习系统。目前最先进的LLM是GPT-4,它支持ChatGPT的付费版本。在本文中,你将学习如何使用GPT-4函数调用为应用程序提供高度灵活的语音解释,并与应用程序的图形用户界面(GUI)充分协同。它适用于产品所有者、用户体验设计师和移动开发人员。


2-1


背景


手机(Android和iOS)上的数字助理未能流行起来,原因有很多;其中,它们是有缺陷的,有限的,而且使用起来往往很繁琐。尤其是现在的OpenAI GPT-4,有可能在这方面有所作为,它们有能力更深入地掌握用户的意图,而不是试图粗略地匹配口头表达。


AndroidGoogle Assistant的“应用程序操作”,iOS有SiriKit的意图。这些提供了简单的模板,你可以用它来注册你的应用程序可以处理的语音请求。Google Assistant和Siri已经有了相当大的改进——甚至比你可能意识到的还要多。然而,它们的覆盖范围很大程度上取决于应用程序对它们的支持。不过,你可以通过语音在Spotify上播放你最喜欢的歌曲。然而,这些操作系统提供的服务的自然语言解释,早于LLM(法学硕士)在这一领域所带来的巨大进步,所以是时候迈出下一步了:利用LLM的力量,使语音输入更加可靠和灵活。


虽然我们可以期待操作系统服务(如Siri和Google assistant)将很快调整策略以利用LLM,但我们已经可以使我们的应用程序使用语音而不受这些服务的限制。一旦你采用了本文中的概念,你的应用程序也将准备好利用新的助手。


LLM的选择(GPT, PaLM, LLama2, MPT, Falcon等)确实会对可靠性产生影响,但你将在这里学习的核心原则可以应用于任何LLM。我们将让用户通过在一个表达式中说出他们想要的东西来访问应用程序的全部功能。LLM将自然语言表达式映射到我们应用程序的导航结构和功能上的函数调用中。它不必是像机器人一样说话的句子。LLM的翻译能力允许用户像人类一样说话,使用他们自己的单词或语言;犹豫,犯错,然后改正错误。当用户因为无法理解语音助手的意思而拒绝使用语音助手时,LLM的灵活性可以使交互感觉更加自然和可靠,从而提高用户的采用率。


为什么要在应用中加入语音输入,为什么是现在?


优点:


1. 导航到屏幕并在一个语音表达式中提供所有参数


2. 浅层学习曲线:用户不需要知道数据在应用程序中的位置,也不需要知道如何操作GUI


3. 免提


4. 互补而非不相连(如语音用户界面或VUI):语音和GUI协同工作


5. 视障人士无障碍设施


6. 现在:因为通过LLM,自然语言的解释已经上升到一个新的水平,反应更加可靠


缺点:


1. 说话时的隐私


2. 精度/误解


3. 相对较慢


4. 头脑中的知识vs现实中的知识(我能说什么?):用户不知道系统能理解哪些口头并有答案


可以从语音输入中受益的应用程序包括用于汽车或自行车驾驶辅助的应用程序。一般来说,当用户不能轻松使用他们的手时,例如,当他们在移动中,戴着手套或忙于用手工作时,他们可能不希望通过触摸来精确地导航应用程序。


购物应用也可能受益于这一功能,因为用户可以用自己的语言表达自己的愿望,而不是浏览购物屏幕和设置过滤器。


当应用此方法为视障人士增加可访问性时,你可能需要考虑添加自然语言输出和文本转语音的特性。


你的应用程序


下图显示了一个典型应用程序的导航结构,以你可能熟悉的火车旅行计划程序为例。在顶部,你可以看到触摸导航的默认导航结构。这个结构由导航组件管理。所有导航单击都委托给导航组件,然后由该组件执行导航操作。底部描述了我们如何使用语音输入进入这个结构。


2-2


用户说出他们想要什么,然后语音识别器将语音转换为文本。系统构造一个包含此文本的提示符并将其发送给LLM。LLM用数据响应应用程序,告诉它用哪个参数激活哪个屏幕。这个数据对象被转换成一个深链接,并给出给导航组件。导航组件用正确的参数激活右边的屏幕:在这个例子中,' Outings '屏幕用' Amsterdam '作为参数。请注意,这是一个简化。我们将在下面详细说明。


许多现代应用程序都有一个集中的导航组件。Android有Jetpack Navigation, Flutter有Router, iOS有NavigationStack。集中式导航组件允许深度链接,这是一种允许用户直接导航到移动应用程序中的特定屏幕的技术,而不是通过应用程序的主屏幕或菜单。要使本文中的概念发挥作用,导航组件和集中式深度链接不是必需的,但它使概念的实现更容易。


深度链接涉及创建一个唯一的(URI)路径,指向应用程序中的特定内容或特定部分。此外,该路径可以包含控制深度链接所指向的屏幕上GUI元素状态的参数。


调用应用程序的函数


我们告诉LLM通过提示工程技术将自然语言表达式映射到导航函数调用。基本上,提示符是这样的:“给定以下带参数的函数模板,将以下自然语言问题映射到这些函数模板之一并返回它”。


大多数LLM都能做到这一点。LangChain通过Zero Shot ReAct代理有效地利用了它,要调用的函数称为Tools。OpenAI 对其 GPT-3.5 和 GPT-4 模型进行了微调,其中包含非常擅长于此的特殊版本(当前为 gpt-3.5-turbo-0613 和 gpt-4-0613),并且他们为此制作了特定的API条目。在本文中,我们将采用OpenAI符号,但这些概念可以应用于任何LLM,例如使用前面提到的ReAct机制。此外,LangChain有一个特定的代理类型(AgentType.OPENAI_FUNCTIONS),它在底层将Tools转换为OpenAI函数模板。对于LLama2,你将能够使用与OpenAI相同语法的llama-api。


LLM的函数调用工作原理如下:


1. 将函数模板的JSON模式以及用户的自然语言表达式作为用户消息插入到提示符中。


2. LLM试图将用户的自然语言表达式映射到这些模板之一


3. LLM返回生成JSON对象,以便你的代码可以进行函数调用


在本文中,函数定义是(移动)应用程序的图形用户界面(GUI)的直接映射,其中每个函数对应于屏幕,每个参数对应于屏幕上的GUI元素。发送到LLM的自然语言表达式返回一个JSON对象,其中包含一个函数名及其参数,你可以使用这些参数导航到正确的屏幕,并触发视图模型中的正确函数,从而获取正确的数据,并根据参数设置屏幕上相关GUI元素的值。


如下图所示:


2-3


它显示了添加到LLM提示符中的函数模板的剥离版本。


无参数屏幕


应用程序中的一些屏幕没有任何参数,或者至少没有LLM需要知道的参数。为了减少令牌的使用和混乱,我们可以将许多这些屏幕触发器组合在一个函数中,并使用一个参数:要打开的屏幕


{
    "name": "show_screen",
    "description": "Determine which screen the user wants to see",
    "parameters": {
        "type": "object",
        "properties": {
            "screen_to_show": {
                "description": "type of screen to show. Either 
                    'account': 'all personal data of the user', 
                    'settings': 'if the user wants to change the settings of 
                                the app'",
                "enum": [
                    "account",
                    "settings"
                ],
                "type": "string"
            }
        },
        "required": [
            "screen_to_show"
        ]
    }
},


触发函数是否需要参数的标准是用户是否有选择;屏幕上是否有某种形式的搜索或导航,即是否有任何搜索(类似)字段或选项卡可供选择。


如果没有,那么LLM就不需要知道它,屏幕触发可以添加到应用程序的通用屏幕触发功能中。


及时指导和修复:


在提示符的系统消息中,你提供了通用的转向信息。在我们的例子中,对于LLM来说,知道现在的日期和时间是很重要的,例如,如果你想计划明天的旅行。另一件重要的事情是控制它的臆断。通常我们宁愿让LLM过于自信,也不愿让它的不确定性打扰用户。对于我们的示例应用程序,一个好的系统消息是:


"messages": [
        {
            "role": "system",
            "content": "The current date and time is 2023-07-13T08:21:16+02:00.
                       Be very presumptive when guessing the values of 
                       function parameters."
        },


函数参数描述可能需要相当多的调优。一个例子是计划火车旅行时的trip_date_time。合理的参数说明为:


"trip_date_time": {
      "description": "Requested DateTime for the departure or arrival of the 
                      trip in 'YYYY-MM-DDTHH:MM:SS+02:00' format.
                      The user will use a time in a 12 hour system, make an 
                      intelligent guess about what the user is most likely to 
                      mean in terms of a 24 hour system, e.g. not planning 
                      for the past.",
                      "type": "string"
                  },


因此,如果现在是15:00,用户说他们想在8点离开,他们的意思是20:00,除非他们特别提到一天中的时间。上述说明对GPT-4相当有效。但在某些极端情况下,它仍然失败。然后,我们可以在函数模板中添加额外的参数,以便在我们自己的代码中进行进一步的修复。例如,我们可以加上:


"explicit_day_part_reference": {
          "description": "Always prefer None! None if the request refers to 
                        the current day, otherwise the part of the day the 
                        request refers to."
          "enum": ["none", "morning", "afternoon", "evening", "night"], 
                           }


在你的应用中,你可能会发现需要进行后期处理以提高成功率的参数。


系统要求澄清


有时,用户的请求缺乏继续执行的信息。可能没有适合处理用户请求的函数。在这种情况下,LLM将以自然语言响应,你可以向用户展示,例如通过敬酒的方式。


还有一种情况是,LLM确实识别出要调用的潜在函数,但缺乏填充所有必需函数参数的信息。在这种情况下,如果可能的话,考虑使参数成为可选的。但是,如果这是不可能的,LLM可以用用户的语言,用自然语言发送请求,以获取缺失的参数。


语音识别


语音识别是app从语音到参数化导航动作转变的关键环节,当翻译质量高的时候,糟糕的语音识别很可能是最薄弱的环节。手机有内置语音识别,质量合理,但基于LLM的语音识别,如Whisper, Google Chirp/USM, Meta MMS或DeepGram往往会带来更好的结果,特别是当你可以根据你的用例调整它们时。


体系结构


最好将函数定义存储在服务器上,但它们也可以由应用程序管理并随每个请求一起发送。两者都有各自的优点和缺点。让它们随每个请求一起发送更灵活,功能和屏幕的对齐可能更容易维护。然而,函数模板不仅包含函数名和参数,还包含它们的描述,我们可能希望比应用商店中的更新流更快地更新它们。这些描述或多或少依赖于LLM,并为有效的内容精心设计。你很可能希望将LLM换成更好或更便宜的LLM,甚至在某些时候动态地交换LLM。如果你的应用是在iOS和Android平台上运行,那么将功能模板放在服务器上也有好处。如果你在语音识别和自然语言处理中都使用OpenAI服务,那么流程的技术大图如下:


2-4


用户说出他们的请求,它被记录到m4a缓冲区/文件(或mp3,如果你喜欢),它被发送到你的服务器,它转发给Whisper。Whisper用转录进行响应,你的服务器将其与系统消息和功能模板组合成LLM的提示符。你的服务器接收回原始函数调用JSON,然后将其处理为应用程序的函数调用JSON对象。


从函数调用到深链接


为了说明如何将函数调用转换为深链接,我们从初始示例中获取函数调用响应:


"function_call": {
                    "name": "outings",
                    "arguments": "{\n  \"area\": \"Amsterdam\"\n}"
                }


在不同的平台上,完全不同的处理方式,随着时间的推移,许多不同的导航机制已经被使用,并且通常仍然在使用。最新版本的平台可以采用以下深度链接:


在Android上:


navController.navigate("outings/?area=Amsterdam")


关于Flutter:


Navigator.pushNamed(
      context,
      '/outings',
      arguments: ScreenArguments(
        area: 'Amsterdam',
      ),
    );


在iOS上,事情没有那么标准化,但使用NavigationStack:


NavigationStack(path: $router.path) {
            ...
}


然后发出:


router.path.append("outing?area=Amsterdam")


应用程序的自由文本字段


有两种自由文本输入模式:语音和打字。我们主要讨论了语音,但是用于输入的文本字段也是一个选项。自然语言通常相当冗长,因此可能难以与GUI交互竞争。然而,GPT-4往往非常擅长从缩写中猜测参数,因此即使是非常短的缩写输入也经常可以被正确解释。


在提示符中使用带参数的函数通常会大大缩小LLM的解释范围。因此,它需要的很少,如果你指示它是假定的,甚至更少。这是一种新的现象,为移动交互带来了希望。


未来


你可以期待这个深层链接结构来处理应用程序中的功能,使其成为手机操作系统(Android或iOS)的一个组成部分。手机上的全球助手将处理语音请求,应用程序可以向操作系统公开它们的功能,因此它们可以以深度链接的方式被触发。这与ChatGPT提供插件的方式相似。显然,现在已经可以通过Android上的AndroidManifest和App Actions中的intent,以及通过SiriKit intent在iOS上使用。你对它们的控制是有限的,用户必须像机器人一样说话才能可靠地激活它们。毫无疑问,随着时间的推移,当LLM支持的助手接管时,这种情况将得到改善。


VR和AR (XR)为语音识别提供了巨大的机会,因为用户的手经常从事其他活动。


可能用不了多久,任何人都可以运行自己的高质量LLM。在接下来的一年里,成本将会下降,速度将会迅速提高。很快,LoRA llm将可以在智能手机上使用,因此推理可以在手机上进行,从而降低成本和速度。同时,越来越多的竞争将会到来,既有像Llama2这样的开源,也有像PaLM这样的闭源。


最后,模式的协同作用可以被进一步推动,而不是提供对整个应用程序GUI的随机访问。LLM结合多个资源的能力,保证了更好的帮助出现。


结论


在本文中,你学习了如何将函数调用应用于语音启用应用程序。使用提供的Gist作为出发点,你可以在Postman或命令行中进行实验,以了解函数调用有多强大。




文章来源:https://towardsdatascience.com/speech-and-natural-language-input-for-your-mobile-app-using-llms-e79e23d3c5fd
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
热门职位
Maluuba
20000~40000/月
Cisco
25000~30000/月 深圳市
PilotAILabs
30000~60000/年 深圳市
写评论取消
回复取消