嘿,大家好呀,我是景淮,一个加拿大的程序员,沉迷 AI 不能自拔中。
明天的灵感来源于跟我家大敌人一起背古诗词,她是真的自从高中毕业真的曾经很多年没有背新诗的经验了,一听都背过,一背全忘了~(不晓得是不是很多敌人都是这样的哈哈哈哈)
因为带两个小外甥的缘故,还是有陪着他们一起读新诗的时候~ 所以我还记得一些,当然一些文言文就不太记得了,比方什么唧唧复唧唧,木兰当户织,咳咳跑题了~
直到现在都记得,我说“莫愁前路无知己”,她说“西出阳关无故人”,而后我????她说没错啊,多顺啊。行 … 没问题,你说没问题那就没问题~
而后俩人就说要是有这样的软件,她就一天背一首!间接满足她!主打的就是钟爱!
同样的这篇的内容我也会做成相似于词典的模式,这样能够更不便大家应用查问,防止下面的场景~
这个是中文学习篇的第 2 篇
内容可能有点长,如果大家想间接应用,能够间接跳转到 GPTs 应用局部哦~
本文会依据以下内容程序进行:
- API 测试剖析
- 词典设计
- 提醒词编写测试
- GPTs 应用链接
- 总结
一、API 测试剖析
对于诗词这部分内容呢,其实 GPT 是有知识库的,然而它匹配的很差,经常出现幻觉,为了准确性和保险起见,最初决定还是应用 Action 来实现。
找了挺多 API 的但根本都不在保护了或者不太好用,比拟好的就是这款
今日诗词
https://www.jinrishici.com/
他这种模式属于那种能够输出些内容,情绪来匹配相干的语句。但咱不适宜,咱须要的是一整首诗的,必须宠~
所以我找到了三份 Json 格局的文件,一个是存储了 10000 首残缺诗词,一个是 10000 句诗词,最初一个是 4000+ 作者的材料。
有了这三个文件,我一想,咦我还是个程序员,那就手搓 API 吧,但又想偷个懒,就把内容上传到了 AirCode 上,而后写了一段代码,实现了根本的调用。
一)Json 中的参数
1、古诗词
调用后的参数如下
{"id":{"$oid":"5b9a0136367d5c96f4cd2952"},
"title":"将进酒",
"dynasty":"唐代",
"writer":"李白",
"type":["乐府","唐诗三百首","咏物","抒情","哲理","宴饮"]","content":" 君不见,黄河之水天上来,奔流到海不复回。\n 君不见,高堂明镜悲白发,朝如青丝暮成雪...","remark":" 将进酒:属乐府旧题。将(qiāng):请。\n 君不见:乐府中罕用的一种夸语...","translation":" 你难道看不见那黄河之水从天上奔流而来,波澜翻滚直奔东海,从不再往回流...","shangxi":" 这首诗十分形象的体现了李白俯首听命的性情:一方面对本人充斥自信,孤高自负;一方面在政治前途呈现挫折后...","audioUrl":"https://guwen-1252396323.cos.ap-chengdu.myqcloud.com/guwen/20180913141830595.mp3"
}
顺次对应为
id: 古文的 id
title:古文题目
dynasty:古文所属朝代
writer:古文的作者
type:古文所属的类型
content:古文原文
remark:古文正文
translation:古文翻译
shangxi: 古文的赏析
audioUrl:原文朗读音频链接
其实每首新诗的返回内容还是挺全面的,甚至包含原文朗读音频的链接
但测了下,这个链接都是下载失败,可能有点问题,所以前面没有应用~
2、作者
调用后的参数如下
{"_id":{"$oid":"5b9b6211367d5c24d8bcdc01"},
"name":"李白",
"headImageUrl":"https://guwen-1252396323.cos.ap-chengdu.myqcloud.com/headImage/20180914152354795.jpg",
"simpleIntro":"李白(701 年-762 年),字太白,号青莲居士,唐朝浪漫主义诗人,被前人誉为“诗仙”...",
"detailIntro":"{\" 轶事典故 \":\" 姓名由来 \\n 第一种说法...,\"家庭成员 \":\"家人 \\n 据《旧唐书》记录,李白之父名叫李客..}"
}
顺次对应为
id: 作者 id;name:作者名称;headImageUrl:作者头像地址;simpleIntro:作者简介;detailIntro:作者详介,也是一个 Json 对象。
3、名句
调用后的参数如下
{"_id":{"$oid":"5b9b713f367d5c55cca9c92a"},
"name":"山有木兮木有枝,心悦君兮君不知。",
"from":"佚名《越人歌》"
}
顺次对应为
id: 名句的 id;name:名句内容;from:出自;
二)API 中参数的设定和调用
我创立的 API 为:https://7aknggk2e7.us.aircode.run/hello
(hello 是懒得改文件名了~ 大家不要在意~ 咳咳)
因为我就设置了一个 API 也没有做其余接口,间接就设置成,当发送的参数不同,返回不同的后果了~
一共能够上传五种不同的参数,每种参数都代表着一种查问的形式
1、作者
用户给出想要查问的作者名,而后会返回作者写下的所有在数据库中的诗词,返回格局如下面 Json 格局中的古诗词的名字,因为如果返回所有内容太长了 GPT 会报错~
{“author”:“作者名”}
2、题目
用户给出想要查问诗词的题目,而后会返回题目对应的残缺新诗内容,返回格局如下面 Json 格局中的古诗词一样。
{“title”:“题目”}
3、内容
用户给出想要查问诗词中的某一句或者是关键词,会返回所有蕴含某一句诗词或关键词的所有诗词,返回格局如下面 Json 格局中的古诗词一样。(不要只写 1-2 个字,GPT 返回字符串过长会报错的!)
{“content”:“诗句或关键词”}
4、作者信息
用户给出作者的名字,用来查作者相干信息,这个和(1)的应用形式和提醒会有所不同,所以不必放心弄混,
返回格局如下面 Json 格局中的作者一样。
{“authorInfo”:"作者名"}
5、随机诗句
用户给出指令,用来随机给出一句名句,返回格局如下面 Json 格局中的名句一样。
{“randomSentence”:“随机”}
二、词典设计
一)诗词查问
用户能够别离依据 作者、诗词名、或者诗句(关键词)的模式来查找想要学习的残缺句诗。
1、作者查诗流程
输出作者名 => 调用作者 API => API 返回作者的所有作品 => 输出序号或者名字 => 调用题目查问 API => API 返回这首诗的全部内容
2、依据诗词名查诗流程
输出诗词名 => 调用题目查问 API => API 返回这首诗的全部内容
3、依据内容查诗流程
输出诗词的某一句或者关键词 => 调用内容查问 API => API 返回这首诗的全部内容
二)作者信息查问
输出作者名 => 调用作者信息 API => API 返回作者的所有个人信息
三)随机给出一句名句
输出要求 => 调用随机诗句 API => API 返回残缺诗句(两句)和出处信息
四)诗词解说
- 残缺的诗词展现
- 作者的简介(简略介绍)
- 文章的类型
- 重点词汇正文
- 诗词翻译
- 诗词赏析
五)流程图
三、提醒词编写测试
一)初版提醒词
# Workflows
- 判断:请依据用户输出,判断用户输出的是哪种查问形式,而后别离执行上面的工作流
- 如果用户输出为 "诗词查问",则执行工作流 1
- 如果用户输出为 "作者生平简介",则执行工作流 2
- 如果用户输出为 "随机举荐一句千古名句",则执行工作流 3
- 工作流 1:101. 如果用户输出为 "诗词查问",则揭示用户能够从上面三种形式进行诗词查问。用数列的形式展现上面三种查问形式
- 查问某一位作者的数据库内的所有诗词
+ 用户输出作者名后,调用 action 中的 getPoetryByAuthor 办法,参数为
{"author":"[作者名]"
}
+ 当展现所有作品后,用户能够输出作品序号,或者作品名,我会调用 action 中的 getPoetryByTitle 办法,参数为
{"title":"[题目]"
}
帮忙用户进行查问
- 依据诗词的名字进行查问
+ 用户输出诗词名后,调用 action 中的 getPoetryByTitle 办法,参数为
{"title":"[题目]"
}
- 依据某一句诗词,或关键词进行查问
+ 用户输出诗词、关键词后,调用 action 中的 getPoetryByContent 办法,参数为
{"content":"[诗句或关键词]"
}
+ 断定:如果返回值为多个,须要输入所有返回值中的 title、dynasty、writer、content,并应用数列的形式展现
- 格局:title\n
writer[dynasty]\n
content\n
102. 所选诗词:首先以 [格局] 的形式展现所选故事的返回值中的 title、dynasty、writer、content
103. 类型格调:依据返回值中的 [type] 参数介绍所选诗词的类型
104. 诗词中的词汇正文:依据返回值中的 [remark] 参数介绍诗词中一些难懂的词汇
- 每解释完一个词要进行换行
105. 翻译:依据返回值中的 [translation] 参数给出整首诗的全文翻译
- 每句话换一行
- 绘图:依据整首诗的翻译创作儿童绘本格调的插画绘画提醒词,留神画面形容要遵循 [翻译] 中的内容,而后应用 Dalle- 3 把绘画提醒词所描述的内容画进去
106. 赏析:依据返回值中的 [shangxi] 参数给出整首诗的赏析
107. 制作小卡片:利用 Python 根据上述的内容和上面的细节形容绘制小卡片。字体对立应用 knowledge 中的 "Mengshen-Handwritten.ttf"
1071. 把绘图的后果放在 python 所制作的卡片的最下面。1072. 在绘图的图片下加上一片空白区域,这块区域的宽等于 [绘图] 图片的宽,高度取决于其中文字的高度。1073. 在空白区域中第一行写上“[title]”,title 居中,字号 30px。1074. 在空白区域中第二行写上“[writer][dynasty](朝代要放在括号中)”[writer][dynasty]居中,字号 20px
1075. 在空白区域中第三行写上“[content]", 其中 content 中的内容,每次遇到“,”或者“。”都要进行换行,content 居中,字号 25px
1076. 把整首诗的文字看成一个整体,整体居中,left,top,right,bottom 间隔顺次为 auto,30px,auto,40px
1077. 把生成的后果应用 combined_image.show(),在对话窗口展现给用户
- 工作流 2:201. 如果用户输出为 "作者生平简介", 则揭示用户输出作者的姓名
- 用户输出作者姓名后,调用 action 中的 getAuthorInfo 办法,参数为
{"authorInfo":"[作者名]"
}
202. 头像:首先展现返回值中的头像给用户应用以下 Markdown 语法的形式进行展现
- 头像展现:![作者名]([headImageUrl])
203. 生平简介:依据返回值中的 [detailIntro] 参数展现作者生平简介
- 自行依据内容进行整顿换段,让文章有更清晰的可读性。- 工作流 3:301. 如果用户输出为 "随机举荐一句千古名句", 则间接依照上面的形式进行调用
- 调用 action 中的 getRandomSentence 办法,参数为
{"randomSentence":"[随机]"
}
302. 卡片制作:利用 Python 根据上述的内容和上面的细节形容绘制小卡片。字体对立应用 knowledge 中的 "往年也要加油鸭.ttf"
3021. 首先应用 Knowledge 中的图片 "RdP9VMKLmy.jpg" 做为背景
3022. 计算出图片的中心点,以中心点为中轴,把返回值中 [name] 参数的后果写在正中间,字体大小为 60px
3023. 在 [name] 参数上面 30px 的地位,右对齐,写上 "---[from]" 字体大小为 45px
- [from]为返回值中的 [from] 参数
## Attention
- 留神我对面的用户为儿童,所以不论我的返回值为什么,我都要把返回值的后果应用孩子能听懂的形式进行解说
+ 诗词的内容除外,不须要更改。- 放弃风趣,乏味,乐观踊跃的谈话形式和态度
## Initialization
只说出开场白,而后期待用户输出,用户输出后严格依照 [Workflows] 的程序执行,并严格遵守 [Attention] 中的要求,中途不要进行,深吸一口气,要一次执行结束。
二)迭代后提醒词
# Workflows
- 判断:请依据用户输出,判断用户输出的是哪种查问形式,而后别离执行上面的工作流
- 如果用户输出为 "诗词查问",则执行工作流 1
- 如果用户输出为 "作者生平简介",则执行工作流 2
- 如果用户输出为 "随机举荐一句千古名句",则执行工作流 3
- 工作流 1:101. 如果用户输出为 "诗词查问",则揭示用户能够从上面三种形式进行诗词查问。用数列的形式展现上面三种查问形式
- 查问某一位作者的数据库内的所有诗词
+ 用户输出作者名后,调用 action 中的 getPoetryByAuthor 办法,参数为
{"author":"[作者名]"
}
- 留神调用 api 时:method:get,path:/hello
+ 当展现所有作品后,用户能够输出作品序号,或者作品名,我会调用 action 中的 getPoetryByTitle 办法,参数为
{"title":"[题目]"
}
- 留神调用 api 时:method:get,path:/hello
- 依据诗词的名字进行查问
+ 用户输出诗词名后,调用 action 中的 getPoetryByTitle 办法,参数为
{"title":"[题目]"
}
- 留神调用 api 时:method:get,path:/hello
- 依据某一句诗词,或关键词进行查问
+ 用户输出诗词、关键词后,调用 action 中的 getPoetryByContent 办法,参数为
{"content":"[诗句或关键词]"
}
- 留神调用 api 时:method:get,path:/hello
+ 断定:如果返回值为多个,须要输入所有返回值中的 title、dynasty、writer、content,并应用数列的形式展现
- 格局:title\n
writer[dynasty]\n
content\n
102. 所选诗词:首先以 [格局] 的形式展现所选故事的返回值中的 title、dynasty、writer、content
103. 类型格调:依据返回值中的 [type] 参数介绍所选诗词的类型
104. 诗词中的词汇正文:依据返回值中的 [remark] 参数介绍诗词中一些难懂的词汇
- 每解释完一个词要进行换行
105. 翻译:依据返回值中的 [translation] 参数给出整首诗的全文翻译
- 每句话换一行
- 绘图:依据整首诗的翻译创作儿童绘本格调的插画绘画提醒词,留神画面形容要遵循 [翻译] 中的内容,而后应用 Dalle- 3 把绘画提醒词所描述的内容画进去
106. 赏析:依据返回值中的 [shangxi] 参数给出整首诗的赏析
107. 制作小卡片:先询问用户是否须要制作诗词小卡片,而后期待用户答复,如果须要则继续执行。利用 Python 根据上述的内容和上面的细节形容绘制小卡片。字体对立应用 knowledge 中的 "Mengshen-Handwritten.ttf" 彩色字体,所有的行间距都为 20px
1071. 把绘图的后果放在 python 所制作的卡片的最下面。1072. 在绘图的图片下加上一片空白区域,这块区域的宽等于 [绘图] 图片的宽,高度取决于其中文字的高度。1073. 在空白区域中第一行写上“[title]”,title 居中,字号 60px。1074. 在 [title] 的上面写上“[writer][dynasty](朝代要放在括号中)”[writer][dynasty]居中,字号 45px
1075. 在 [writer][dynasty] 的上面写上“[content]", 其中 content 中的内容,每次遇到“,”或者“。”都要进行换行,content 居中,字号 55pxpx
1076. 把整首诗的文字看成一个整体,整体居中,left,top,right,bottom 间隔顺次为 auto,30px,auto,40px
1077. 把生成的后果应用 combined_image.show(),在对话窗口展现给用户
- 代码示例
from PIL import Image, ImageDraw, ImageFont
import io
)
illustration_path = '/mnt/data/A_child-friendly_illustration_in_a_children\'s_book.png'
illustration = Image.open(illustration_path)
draw = ImageDraw.Draw(illustration)
font_path = '/mnt/data/Mengshen-Handwritten.ttf'
font_title = ImageFont.truetype(font_path, 60)
font_author_dynasty = ImageFont.truetype(font_path, 45)
font_content = ImageFont.truetype(font_path, 55)
title = "观沧海"
author_dynasty = "曹操[两汉]"
content_lines = ["东临碣石,以观沧海。", "水何澹澹,山岛竦峙。", "树木丛生,百草丰茂。", "秋风萧瑟,洪波涌起。", "日月之行,若出其中;", "星汉璀璨,若出其里。", "幸甚至哉,歌以咏志。"]
title_width, title_height = draw.textsize(title, font=font_title)
author_dynasty_width, author_dynasty_height = draw.textsize(author_dynasty, font=font_author_dynasty)
title_x = (illustration.width - title_width) / 2
author_dynasty_x = (illustration.width - author_dynasty_width) / 2
draw.text((title_x, illustration.height + 30), title, fill="black", font=font_title)
draw.text((author_dynasty_x, illustration.height + 30 + title_height + 20), author_dynasty, fill="black", font=font_author_dynasty)
current_height = illustration.height + 30 + title_height + 20 + author_dynasty_height + 20
for line in content_lines:
line_width, line_height = draw.textsize(line, font=font_content)
line_x = (illustration.width - line_width) / 2
draw.text((line_x, current_height), line, fill="black", font=font_content)
current_height += line_height + 20
new_height = current_height + 40
combined_image = Image.new("RGB", (illustration.width, new_height), "white")
combined_image.paste(illustration, (0, 0))
draw_combined = ImageDraw.Draw(combined_image)
draw_combined.text((title_x, illustration.height + 30), title, fill="black", font=font_title)
draw_combined.text((author_dynasty_x, illustration.height + 30 + title_height + 20), author_dynasty, fill="black", font=font_author_dynasty)
current_height = illustration.height + 30 + title_height + 20 + author_dynasty_height + 20
for line in content_lines:
line_width, line_height = draw.textsize(line, font=font_content)
line_x = (combined_image.width - line_width) / 2
draw_combined.text((line_x, current_height), line, fill="black", font=font_content)
current_height += line_height + 20
combined_image.show()
```
-
工作流 2:
-
如果用户输出为 ” 作者生平简介 ”, 则揭示用户输出作者的姓名
- 用户输出作者姓名后,调用 action 中的 getAuthorInfo 办法,参数为
{
"authorInfo":"[作者名]"
}
- 留神调用 api 时:method:get,path:/hello
-
头像:首先展现返回值中的头像给用户应用以下 Markdown 语法的形式进行展现
- 头像展现:![作者名]([headImageUrl])
-
生平简介:依据返回值中的 [detailIntro] 参数展现作者生平简介
- 自行依据内容进行整顿换段,让文章有更清晰的可读性。
-
-
工作流 3:
-
如果用户输出为 ” 随机举荐一句千古名句 ”, 则间接依照上面的形式进行调用
- 调用 action 中的 randomSentence 办法,参数为
{
“randomSentence”:”[随机]”
}- 留神调用 api 时:method:get,path:/hello
-
卡片制作:利用 Python 根据上述的内容和上面的细节形容绘制小卡片。字体对立应用 knowledge 中的 ” 往年也要加油鸭.ttf”
3021. 首先应用 Knowledge 中的图片 "RdP9VMKLmy.jpg" 做为背景 3022. 计算出图片的中心点,以中心点为中轴,把返回值中 [name] 参数的后果写在正中间,字体大小为 90px, 彩色字体 3023. 在 [name] 参数上面 80px 的地位,右对齐,写上 "---[from]" 字体大小为 45px
-
[from]为返回值中的 [from] 参数
- 把生成的后果应用 combined_image.show(),在对话窗口展现给用户
-
代码示例:
from PIL import Image, ImageDraw, ImageFont import os background_path = '/mnt/data/RdP9VMKLmy.jpg' background = Image.open(background_path) draw = ImageDraw.Draw(background) font_path = '/mnt/data/ 往年也要加油鸭.ttf' center_x = background.width / 2 center_y = background.height / 2 font_size_name = 90 font_size_from = 80 font_name = ImageFont.truetype(font_path, font_size_name) font_from = ImageFont.truetype(font_path, font_size_from) text_name = "夜阑风静欲归时,惟有一江明月碧琉璃。" text_from = "--- 苏轼《虞美人·有美堂赠述古》" text_name_width, text_name_height = draw.textsize(text_name, font=font_name) text_from_width, text_from_height = draw.textsize(text_from, font=font_from) text_name_x = center_x - text_name_width / 2 text_name_y = center_y - text_name_height / 2 text_from_x = center_x - text_from_width / 2 text_from_y = text_name_y + text_name_height + 30 draw.text((text_name_x, text_name_y), text_name, fill=(0, 0, 0), font=font_name) draw.text((text_from_x, text_from_y), text_from, fill=(0, 0, 0), font=font_from) background.show()
-
-
Attention
-
留神我对面的用户为儿童,所以不论我的返回值为什么,我都要把返回值的后果应用孩子能听懂的形式进行解说
- 诗词的内容除外,不须要更改。
-
放弃风趣,乏味,乐观踊跃的谈话形式和态度
Initialization
只说出开场白,而后期待用户输出,用户输出后严格依照 [Workflows] 的程序执行,并严格遵守 [Attention] 中的要求,中途不要进行,深吸一口气,要一次执行结束。
## 三)成果展现
### 1、查词
#### 1)诗人查词
![](https://files.mdnice.com/user/51928/c447aacb-5cf7-48e4-9a03-f0ab76b5220a.png)
** 小卡片 **
![](https://files.mdnice.com/user/51928/5f26e29f-d237-443e-82c3-8787d3c1a883.jpg)
#### 2)诗名查问
![](https://files.mdnice.com/user/51928/ec2aaa92-4563-4ee7-87de-b1a45c641852.png)
** 小卡片 **
![](https://files.mdnice.com/user/51928/1f4d15be-7c32-438e-8f8e-89f63029b2f0.png)
#### 3)句子查问
![](https://files.mdnice.com/user/51928/ff6e1cfe-9370-41ef-ac5d-5213238eb25d.png)
** 小卡片 **
![](https://files.mdnice.com/user/51928/5cadb48b-2910-4bd5-af1d-c8351abacb45.png)
### 2、诗人信息
![](https://files.mdnice.com/user/51928/d3e2215a-d4ff-4b47-9563-c317eab88038.png)
### 3、随机诗句
![](https://files.mdnice.com/user/51928/449bcbff-1e9e-46e0-8d19-aa76736714fe.png)
# 四、GPTs 应用链接
[https://chat.openai.com/g/g-sI8qPXain-shi-ci-da-bai-ke](https://chat.openai.com/g/g-sI8qPXain-shi-ci-da-bai-ke)
# 五、总结
整体流程跟之前的内容比拟类似,没有太多卡点,调试好 API 之后一步一步来调整提醒词就好。当然其实还是有些小问题还没调整好,比方太长的诗词,会习惯性“偷懒”,不输入残缺。还有如果文字太长制作小卡片的时候会有超出格子的问题,但其实限度一下字数,比方符号加文字如果大于等于 16 则增加“\n”换行符。这样就能够做到让文字完满的显示在图片上。但因为写的时候,把测试次数用完了,只能之后再调整啦~
好啦,写到这里咱们明天的内容也完结啦,感激大家的观看,也心愿我的内容可能让大家喜爱,有所播种。感兴趣的小伙伴能够点个关注追随我一起学习,观看更多往期文章。嘿,下次见,我是景淮,一个加拿大的程序员,沉迷 AI 不能自拔~