最近尝试着让两个GPT-3.5扮演各自的角色相互对话,整体的效果还不错,但是遇到了些许困难:
1. 难以让LLM主动打招呼:在调用OpenAI API时,官方文档的指引是同时提供系统提示(system)和用户提示(user),如果仅指定了系统提示就让assistant(也就是GPT)进行对话补全,它就会把系统提示当做上一句话进行回复。比如如果是官方提供的例子“You are a helpful assistant”,那么GPT就会回复“感谢你的赞美”之类的话。总之,这是一个根据对话上文补全回复的接口。
2. 难以停止对话:我在系统提示中指出,如果GPT觉得对话可以结束了请输出“QUIT”,但是尝试了好多次,除了少数几次系统能输出QUIT之外,其他都陷入了“再见”的死循环。GPT-3.5有时候并没有那么聪明。
3. 对话非常拘谨:总之就是GPT相当有礼貌,可能是RLHF阶段进行对齐的时候教训得好。但可能有一些神奇的prompt能让它扮演更有特点的角色,只是可能需要耗费不小的token数,占据了一些剧情铺垫的空间。
上面这些当然也不是什么致命的困难,都有不少的方案可以缓解。对于打招呼的问题,也许有这样一些解决办法:
1.1 可以在系统提示中直接指示GPT下一句就是对某一角色的打招呼文本,不过这部分提示需要根据该角色是否是打招呼的角色进行动态加载。当角色是被动开始聊天的一方,就直接根据原始的系统提示和对方的打招呼进行回复就好。
1.2 对于某一角色,可以准备一些预定义的打招呼文案,在当前角色需要打招呼的时候,用这些打招呼文案替代GPT的补全,进而让对方根据系统提示和打招呼文案进行补全。在这些预定义的文案中还能够设置一些slot,将打招呼对象的名字动态加载进去。
关于停止对话的问题,同样也有不错的办法:
2.1 设置一个告别词库,如果检测到双方完成了告别,就停止对话。
2.2 如果不幸没有触发告别词库,直接按最大对话轮次强行停止对话。
对于对话拘谨的问题,Generative Agents论文也在注脚中提出现在的LLM生成的回复都相当formal,可能得等以后的专用LLM来解决了吧。
顺便提供一份单智能体对话的代码片段,可以设置token数警戒值,一旦上下文超过了这个警戒值就会删除前面的对话内容(但是保留系统提示和第一轮对话),也可以将对话记录保存到文本文件:
gist.github.com