编者按:一直有客户问我们国产大模型的能力如何,我们院首席工程专家Eric上周从我们这个帮助企业实际落地应用的角度出发做了一个评测,我们分享出来。当然并不是跑分的那种,如果你要看SuperCLUE等跑分的话到处都是。
随着国产模型的百花齐放,选择基于哪种模型进行开发变得愈发重要。在文生文模型领域,国内有一些知名模型,如百度的文心一言、讯飞的星火、抖音的豆包(基于云雀模型)、智谱的智谱清言(基于ChatGLM),甚至蓝厂(Vivo)也发布了蓝心小V(基于BlueLM)。
最近我尝试了一下蓝厂的大模型应用,发现效果还不错。本文将通过简单的ReAct+COT提示词测试,验证在ReAct COT应用场景下,哪些模型表现较好。
为何测试ReAct+COT场景?
文生文模型主要提供基本的COT(常识、逻辑、推理)能力,结合用户输入的提示词回答问题。然而,预训练模型本身无法回答训练结束后的新知识。若用户需要模型根据私有知识或实时网络信息回答问题,而模型提供商未主动整合网络搜索,大模型无法胜任。一些应用场景需要模型不仅提供基本常识,还需要结合私有知识或与私有服务对接,实现复杂的场景。
文生文模型通常用于传统客服机器人等场景,但大模型赋予我们更大的灵活性,无需强制限制用户输入。大模型可根据用户输入信息自动提取、摘要,并以更人性化的方式输出。这些都是预训练模型提供的基本能力,类似于高中生具备基本逻辑和语言表达能力,但若需要回答未学过的知识,需要先给予相关提示词上下文,就像给学生扔一本书让其学习后再回答问题。
然而,提示词上下文的长度并非无限制,通常为4K、8K、16K、32K等。随着长度增加,大模型会迅速遗忘前面的内容。因此,无法一次性将所有新知识直接放入上下文。为了解决这个问题,可以采用动态加载,根据用户输入检索本地向量库的知识,将这些知识作为参考上下文传递给大模型。这样,大模型始终能获取最相关的私有知识,减少对上下文的消耗,提高回答准确性。
加载私有知识到上下文的挑战
但是,什么时候将私有知识加载到上下文呢?用户每次输入都先查询一遍向量库?这不是一个好的方案,因为token消耗太高了。大模型的响应速度、硬件资源消耗和提示词token与完成token长度都成正相关,这些都是宝贵的资源,尤其是在显卡受到制裁,价格波动成倍增长的情况下。即使使用公有云大模型,对应的就是token消耗的暴增。
解决方案是依据大模型基本的COT(常识、逻辑、推理)能力,对提示词进行特殊构造。要求大模型在需要从外部系统拉取外部知识时,返回特定结构的消息,触发本地程序查询私有知识并加入到上下文。
这种生成特定结构JSON的方式有两种。
一种是模型提供商针对模型进行微调,需要调用外部系统时自动返回特定结构的消息,如OpenAI的function calling。这当然很好,也是性能比较好、比较节约token的方式。
参考:
Function calling and other API updates (openai.com)
但是,针对开源模型,目前原生支持类似function calling功能的并不多。已知智谱的ChatGLM3明确提到原生支持工具调用。
参考:
ChatGLM3/tools_using_demo/README.md at main · THUDM/ChatGLM3 (github.com)
然而,对于没有这种原生支持function calling的模型怎么办呢,可以采用ReAct方式。通过针对提示词特殊构造,引导大模型基于基本COT能力和提示词上下中的必要思维提示步骤,输出所需的JSON。实验证明,这种方式可以显著增强回答的准确性,透过其中的Action步骤,还可以整合外部调用,动态丰富上下文信息。
详细了解ReAct的方式可参考
参考:
ReAct: Synergizing Reasoning and Acting in Language Models (react-lm.github.io)
说了那么多,我们现在明白为何要测试大模型的COT+ReAct能力了吧。
构造ReAct提示词
system:你是公司内部的智能客服助手,正在解答用户提出的问题。
尽量调用本地工具回答用户提出的问题,确保对话通顺流畅。
本地工具定义清单如下:
```json
[
{
"name": "track",
"description": "追踪指定股票的实时价格",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"description": "需要追踪的股票代码,默认空"
}
},
"required": ['symbol']
}
},
{
"name": "text-to-speech",
"description": "将文本转换为语音",
"parameters": {
"type": "object",
"properties": {
"text": {
"description": "需要转换成语音的文本"
},
"voice": {
"description": "要使用的语音类型(男声、女声等),默认男声"
},
"speed": {
"description": "语音的速度(快、中等、慢等),默认快"
}
},
"required": ['text']
}
}
]
```
请按照以下思考过程回答员工问题:
1. 用户问题:用户提问内容。
2. 分析调用:分析上下文,确定待调用的本地工具名称和顺序。
3. 检查参数:严格参考上下文待调用本地工具说明,分析上下文,检查待调用本地工具必填参数是否存在部分缺失。若无缺失,跳过步骤4和步骤5,直接执行步骤6。
4. 收集参数:如待调用本地工具部分必填参数存在缺失,输出如下JSON以收集必填参数。
```json
{
"action": "收集参数",
"action_input": "请输入缺失的必填参数,此处为回复给用户的提示"
}
```
5. 观察参数:观察收集到的参数值,检查待调用本地工具的全部必填参数是否还有缺失。重复"收集参数"/"观察参数"直至待调用本地工具的全部必填参数已输入。
6. 思考:根据上下文,考虑如何进行下一步操作。
7. 操作:按照如下格式输出JSON以调用本地工具操作,注意输入参数值的格式和有效性,必要时先进行转换和验证。
```json
{
"action": "有效的本地工具名称",
"action_input": {
"本地工具输入参数名1": "本地工具输入参数值1(如缺失,默认‘’)",
"本地工具输入参数名2": "本地工具输入参数值2(如缺失,默认‘’)",
"本地工具输入参数名...": "本地工具输入参数值...(如缺失,默认‘’)"
}
}
```
8. 观察:观察操作结果。重复"思考"/"操作"/"观察"直至问题解决。
9. 思考:考虑如何回复用户。
10. 最终答案:输出如下JSON以回复用户,有效"action"值:"最终答案""收集参数","text-to-speech","track"。
```json
{
"action": "最终答案",
"action_input": "回复用户的最终答案"
}
```
user:查询讯飞的股价
如果你使用过Langchain,可能会发现这很像structured_chat这种agent使用的提示词。确实,上述提示词是基于Langchain的智慧结晶改动而来。只是增加分析调用,检查参数,收集参数,观察参数这些额外步骤。
为何要这么设计呢?主要是为了解决多参数收集的问题。如果不这样设计,一方面可能会产生虚幻的概率较高的问题,另一方面在收集参数的过程中回复会显得生硬。
回归正题,下面我们将挑选几个模型进行测试验证,透过官方提供的App进行测试。
模型测试和结论
讯飞星火
抖音豆包
智谱清言
蓝厂小V
结论: 对于上述提示词,讯飞表现最好,充分理解思维提示,严格按照要求输出。最出乎意料的是智谱表现最差,虚幻太严重,没有理解上下文,而蓝厂新发布的小V虽然没有完整输出,但核心的JSON输出是正确的。豆包也有正确输出,但存在虚幻问题没有得到有效控制。
这些测试是基于官方发布的App进行的,实际底层模型性能可能有所差异,但仍可作为一个参考选择依据,同时大模型们跑得都挺快,所以仅代表目前能力的一管之见。