NLP(七十六)使用大模型完成填字游戏

本文将介绍如何使用大模型来完成汉字填字游戏。

这一次,我们将利用大模型来做一件酷酷的事情,那就是用它来完成汉字填字游戏(word puzzle)。

填字游戏

填字游戏一般在国外较受欢迎。填字游戏一般给出一个矩形的表格。这个表格被分割为若干个大小相同的方格,方格的颜色有白色与黑色两种。白色的方格组成一些交叉的行与列,行列的长度不等。玩家根据题目所提供的有关信息,将答案填入这些行与列之中,每个白色方格中只能填入一个字。

笔者在公交上打开澎湃新闻App,里面有"澎湃填字"游戏,本次游戏的界面如下:

澎湃填字游戏

游戏中的题目如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1. 李清照的词《一剪梅·红藕香残玉簟秋》中“一种相思,两处闲愁”的上一句,7
2. 印度洋的一个岛国,首都科伦坡,4
3. 一种伞形装备,用于从飞机上空头人员或物质等,3
4. 苏轼的词《念奴娇·赤壁怀古》中“浪淘尽,千古风流人物”的上一句,4
5. 一种可以用作宠物饲养的可爱鸭子,即Call duck,3
6. 中国最早的出版社之一,1912年1月1日成立于上海,4
7. 横跨欧亚两洲的一个国家,首都是安卡拉,3
8. 中国的一个知名音乐节,今日因在南阳成“音乐劫”引发关注,5
9. 中国最大的内陆咸水湖,也是世界上海拔最高的湖泊之一,3
10. 中国古代四大发明之一,蔡伦是其发明者,3

一、曾让牛顿痴迷的中世纪炼金术中,“神圣三元素”包括硫磺、盐和哪种物质?,2
二、“迪士尼公主”大家庭中,唯一设定没有皇室血统或身份的公主形象是谁?,3
三、一种充满复杂通道的建筑物,很难找到正确的通行道路,3
四、汉代蔡邕用柯亭竹所制的著名笛子,后泛指美笛,3
五、成语,喜欢做某事,并在其中获得乐趣,4
六、上海的一所知名财经类高校,校训是“厚德博学,经济匡时”,4
七、清朝洋务运动中成立的近代军事工业生产机构,也是近代中国最大的军火工厂,5
八、李煜的词《浪淘沙》中“天上人间”的上一句,7
九、今日“巴以冲突”再起,其中“巴”是指那个国家,4
十、学术上用来表示特殊意义的专门用语,2

其中,阿拉伯数字开头的是竖排,汉字数字开头的代表横排,最后的数字代表答案的字数。

既然大模型的能力很好很强大,那么,我们为什么不尝试用LLM来完成填字游戏呢?

Let's go!

程序

首先先介绍下笔者的解决思路。

  1. 需要调用搜索引擎。一是因为题目中包含最近的时事新闻,二是因为ChatGPT对于汉语,尤其是诗词的理解能力较弱,三是因为有了搜索引擎,才使回复更好更完善,并给出答案解释,类似与perplexity.ai
  2. 写一个合适的prompt,包含搜索引擎的结果作为背景知识
  3. 限定回答的字数,这个采用openai中的模型调用参数max_tokens来实现
  4. 回答时先解决竖排,再解决横排。当知道竖排结果时,可以对横排结果的答案进行限制,这边采用openai中模型调用参数logit_bias来实现

实现的Python程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# -*- coding: utf-8 -*-
# @place: Pudong, Shanghai
# @file: chinese_word_puzzle.py
# @time: 2023/10/10 23:24
import os
import openai
import tiktoken
from langchain.tools import Tool
from langchain.utilities import GoogleSearchAPIWrapper

os.environ["GOOGLE_CSE_ID"] = "xxx"
os.environ["GOOGLE_API_KEY"] = "xxx"


class ChnWordPuzzle(object):
def __init__(self, model_name, query, answer_number, special_rules):
self.model_name = model_name
self.query = query
self.answer_number = answer_number
self.special_rule = special_rules

def get_google_search_result(self):
search = GoogleSearchAPIWrapper()

# return first five search results
def top5_results(query):
return search.results(query, 5)

tool = Tool(
name="Google Search",
description="Search Google for recent results.",
func=top5_results,
)
result = tool.run(self.query)
return result

def make_prompt(self):
prefix_prompt = "请根据搜索引擎的结果,回答下面的问题。搜索结果如下:\n"

search_prompt = ""
try:
for record in self.get_google_search_result():
search_prompt += f"标题:{record['title']},内容:{record['snippet']}\n"
except Exception:
pass

suffix_prompt = f"问题:{self.query}。请用{self.answer_number}个汉字进行回答。"

prompt = prefix_prompt + search_prompt + suffix_prompt
return prompt

def solve(self):
openai.api_key = "sk-xxx"

prompt = self.make_prompt()
print(prompt)
logit_bias_dict = {}
enc = tiktoken.encoding_for_model(self.model_name)
for no, char in self.special_rule.items():
for token_id in enc.encode(char):
logit_bias_dict[token_id] = 10
print(logit_bias_dict)

response = openai.ChatCompletion.create(
model=self.model_name,
messages=[
{"role": "user", "content": prompt}
],
max_tokens=self.answer_number + 3,
temperature=0,
logit_bias=logit_bias_dict
)

return response['choices'][0]['message']['content']


if __name__ == '__main__':
my_query = "李清照的词《一剪梅·红藕香残玉簟秋》中“一种相思,两处闲愁”的上一句"
my_answer_number = 7
my_model_name = "gpt-3.5-turbo"
# my_model_name = "gpt-4"
my_special_rules = {}
chn_word_puzzle = ChnWordPuzzle(my_model_name, my_query, my_answer_number, my_special_rules)
print(chn_word_puzzle.solve()[:my_answer_number])

在实际运行程序时,将Google search的API key和OpenAI的key替换成自己的。

我们来看一下,第一个问题的prompt和答案。

1
2
3
4
5
6
7
8
9
请根据搜索引擎的结果,回答下面的问题。搜索结果如下:
标题:李清照,花自飘零水自流,《一剪梅·红藕香残玉簟秋》,表达思念_独 ...,内容:May 3, 2019 ... 李清照的词能够唤起很多人们对情感的追索,对于情感的一种追忆。从李清照的词中人们能够找到很多现实生活中情感的寄托。这首词的意思就是:“粉红色的 ...
标题:一剪梅·红藕香残玉簟秋_百度百科,内容:一剪梅·红藕香残玉簟秋》是宋代女词人李清照的词作。此词作于词人与丈夫赵明诚离别之后,先写清秋时节与爱人别后,独上兰舟以排遣愁怀,西楼望月恨雁来无书, ...
标题:一剪梅·红藕香残玉簟秋原文、翻译及赏析、拼音版_李清照_古诗文网,内容:轻解罗裳,独上兰舟。云中谁寄锦书来?雁字回时,月满西楼。花自飘零水自流。一种相思,两处闲愁。此情无计可消除,才下眉头,却上 ... 词的上阕首句 ...
标题:一剪梅•红藕香残玉簟秋,李清照玉簟秋赏析,一种相思两处闲愁- 知乎,内容:Mar 5, 2020 ... 这首词牌名“一剪梅”分为上下两阕(que,四声),阕字义是“停止”的意思,用在词里面,一般指“一段”的意思,这首词牌名是分为两段的,第一段称为上阕,第二 ...
标题:"花自飘零水自流。一种相思,两处闲愁。"全诗赏析_古诗文网,内容:原文. 李清照《一剪梅·红藕香残玉簟秋》. 红藕香残玉簟秋。轻解罗裳,独上兰舟。云中谁寄锦书来?雁字回时,月满西楼。 花自飘零水自流。一种相思,两处闲愁。此 ...
问题:李清照的词《一剪梅·红藕香残玉簟秋》中“一种相思,两处闲愁”的上一句。请用7个汉字进行回答。
{}
花自飘零水自流

回答正确!Perfect!

实验

我们使用gpt-3.5-turbo模型,对前10个问题进行测试,答案如下:

1
2
3
4
5
6
7
8
9
10
1. 花自飘零水自流
2. 斯里兰卡
3. 投物伞
4. 大江东去
5. 柯尔鸭
6. 中华书局
7. 土耳其
8. 迷笛音乐节
9. 青海湖
10. 蔡伦

其中,第10个回答明确有错,我们调用GPT-4模型,可得到正确答案:造纸术。

在得到竖排答案后,我们在回答横排问题时,可以用竖排的答案对回复进行约束,比如在回答横排第二个问题“迪士尼公主”大家庭中,唯一设定没有皇室血统或身份的公主形象是谁?时,我们知道第一、第三个字分别为花、兰,那么答案应该为花X兰。于是,我们将my_special_rules = {"一": "花", "三": "兰"},可对答案进行约束。

横排答案如下:

1
2
3
4
5
6
7
8
9
10
一. 水银
二. 花木兰
三. 迷宫
四. 柯亭笛
五. 乐在其中
六. 上海财大
七. 江南制造局
八. 流水落花春去也
九. 巴勒斯坦
十. 术语

总结

在上述的解决方案中,竖排的第3个回答投物伞有误,这是Google Search和大模型回复共同导致的错误。正确答案为降落伞,作为人可以轻松地回答出来,而大模型+搜索引擎竟然不行!

竖排的第10个回答,gpt-3.5-turbo模型错误,而GPT-4模型回答正确。

同时,横排的第一个问题在Google Search没有搜索结果,靠logit_bias约束答案中有“水”字生成的答案为水银,答案正确。

最后,横排的第六个问题,答案为上海财大,但如果logit_bias的值设为5,答案为上海财经,由于竖排的答案已知最后一个为大字,所以可调整logit_bias的值。

在上述的种种调试下,使用gpt-3.5-turbo模型,回答正确共18个,正确率90%。

综上,

  1. 尽管有Google Search的加持,但大模型还是会回答错误。
  2. Google Search存在搜索无结果,因此需要容错。
  3. logit_bias的值有一定的概率会生成错误答案。

因此,上述的解决方案还不十分靠谱,期待下次优化~

欢迎关注我的公众号NLP奇幻之旅,原创技术文章第一时间推送。

欢迎关注我的知识星球“自然语言处理奇幻之旅”,笔者正在努力构建自己的技术社区。


NLP(七十六)使用大模型完成填字游戏
https://percent4.github.io/NLP(七十六)使用大模型完成填字游戏/
作者
Jclian91
发布于
2024年1月10日
许可协议