前言
近期需要利用chatgpt制作一个翻译脚本,同时为了一次请求尽可能多的处理翻译,多条翻译结果是通过json进行封装,之后请求gpt的,但实际使用过程中,gpt的返回结果并没有那么让人满意,也可能是我用的只是3.5模型的原因,以下是对常见的一些gpt返回的错误格式的结果处理
Prompt
GPTJsonPromptFormat = "1.你是一个翻译引擎, 只需要翻译内容而不要解释它;" +
"2.我需要你将日文翻译为简体中文,我会给你一个json结构的数组, 键Original内的值是需要翻译的原文,请不要更改他的内容," +
"你需要逐个翻译每个结构的内容,并将翻译结果补充至键Translation的值里,并按照json格式返回给我;"
请求json
[{"Original":"「えーっと、カエデさん……?」","Translation":""},{"Original":"「甘い!甘すぎるわ!クリームなんていらないくらい甘いわ!」","Translation":""},{"Original":"「こういうときはまったりほうじ茶が飲みたくなるわね……」","Translation":""},{"Original":"「でも、泰矢くんたちがすごく幸せなのが良~くわかったわ」","Translation":""},{"Original":"「そ、それなら良かったです」","Translation":""}]
gpt返回数据条数与请求条数不符
问题描述
例如json数组内请求了20条数据,但可能返回结果只有18条,请求所消耗的tokens也只有2000多,并没有超过上限4096,只能理解为gpt抽风
处理方式
在请求前记录请求内数组数量和返回后数组数量,如果数量对不上,重试请求
返回的结果在最后少一个引号,导致json格式错误无法解析
问题描述
返回结果可能是如下这样,很多次都是固定倒数第三个字符少一个引号,很难说不是gpt故意的,细思极恐
[{"Original":"「えーっと、カエデさん……?」","Translation":"「嗯……卡惠姐姐……?」"},{"Original":"「甘い!甘すぎるわ!クリームなんていらないくらい甘いわ!」","Translation":"「太甜了!太过甜了!不需要奶油什么的,已经够甜了!」"},{"Original":"「こういうときはまったりほうじ茶が飲みたくなるわね……」","Translation":"「这种时候总想喝上一杯悠闲的焙茶呢……」"},{"Original":"「でも、泰矢くんたちがすごく幸せなのが良~くわかったわ」","Translation":"「不过,太矢君他们的幸福感真的~能够好好理解呢」"},{"Original":"「そ、それなら良かったです」","Translation":"「那、那样就好」}]
错误的地方在这里,值的结束位置少一个引号
"Translation":"「那、那样就好」}]
处理方式
如果碰到json格式错误,先在倒数第三个字符的位置添加引号后再处理
// GptJsonErrorHandling gpt返回的json解析失败时处理
func GptJsonErrorHandling(str string) (newStr string) {
strLen := len(str)
index := strLen - 2
newStr = str[:index] + "\"" + str[index:]
return newStr
}
返回结果错误的翻译为了其他语言
问题描述
偶发情况,gpt不遵守prompt要求的从日文翻译为中文,而是翻译为了英文结果返回;或没有翻译,直接日文原文返回了
处理方式
使用正则判断全部的翻译结果,如果满足英文句子正则的结果超过了一半,认为翻译结果无效,重新请求gpt,判断英文句子使用的正则如下
([a-zA-Z]{2,}\s){2,}
判断日文句子使用的正则如下
[\u3040-\u309F\u30A0-\u30FF]+
返回json内出现了额外的引号
问题描述
这可能和我请求内容有关,请求的内容内的 「
和 」
是日语的引号,但是gpt对此有三种处理,不翻译,翻译为中文引号 “”
,翻译为英文引号 "
,最头疼的是翻译为英文引号 "
,会导致json结构错误无法解析
处理方式
这里用到的正则语句比较复杂,go官方正则库regexp不支持,需要安装另一个开源的正则库
go get github.com/dlclark/regexp2
之后是处理代码
// GptResTextReplace gpt返回文本替换,将全部"替换为\"
func GptResTextReplace(str string) (newStr string) {
r := regexp2.MustCompile("(?<={"Original":")(.*?)(?=","Translation":")|(?<=","Translation":")(.*?)(?="})", 0)
//定义一个替换函数
var evaluator = func(m regexp2.Match) string {
s := m.String()
s = strings.ReplaceAll(s, "\"", "\\\"")
return s
}
//查找子函数进行替换
newStr, err := r.ReplaceFunc(str, evaluator, -1, -1)
if err != nil {
return ""
}
return
}
返回内容出现繁体字
问题描述
哪怕在prompt声明了需要翻译为简体中文
,gpt依旧不管这些,日文翻译为中文时会出现很多繁体文字,这些还是需要代码进行替换
处理方式
方案一(放弃)
判断繁体中文句子使用的正则如下,实际使用发现这个繁体中文的正则可能匹配的只是生僻字,一些复杂的汉字仍属于简体字,但存在繁体形式,故放弃正则匹配
[\u3400-\u4db5]+
方案二
对全部翻译结果直接进行处理,用到的一个繁体简体文字处理的依赖包
go get github.com/go-creed/sat
实现代码超级简单,str为待处理文本,似乎在性能上损耗也不是很大
dicter := sat.DefaultDict()
str = dicter.Read(str)
返回内容为空值
问题描述
返回的json中Translation
字段的值为空值
处理方式
判断非空,为空时重新请求gpt
翻译文本错位
问题描述
返回的json中Original
字段的值也被翻译了
处理方式
一般出现这种情况,Original
字段的值和Translation
字段的值都会变成译文,且文本相同,判断他们文本是否相同,相同时重新请求gpt
返回内容不完整
问题描述
请求和回复的内容所消耗的tokens都并没有超过4096,但有时就会突然结束文本,末尾是省略号...
处理方式
只能重新请求gpt
返回内容奇怪格式
问题描述
返回了这种这样奇怪键值的json
{"Original":"Translation":""}
处理方式
只能重新请求gpt
英文引号被翻译为了中文引号
问题描述
json的键与键之间只能用英文逗号,
进行分割,gpt返回的内容中用的却是中文逗号,
分割,导致json无法解析
{"Original":"「ちょ、ちょっとカエデ様!いきなり何を言ってるんですか!」||「念のためよ、念のため」","Translation":"等等,等等啊,楓大人!你突然說什麼啊!||預先說一下,預先說一下"}
处理方式
其实先用正则取出所有的键值分割符号,再全部进行替换也可以,但这种情况出现的很少,没那个必要单独进行处理,直接重新请求更方便