? ? ? ? gpt也好,国内的一众语言模型也罢,它们目前似乎都只注重最表层交互层的使用体验,也就是和人进行对话是非常顺畅丝滑的。但如果把这些AI模型,应用到数据底层,用以解析原文,用以生成数据等底层生产力工具的时候,就会出现太多太多坑了。本文就详细记载这一年来使用gpt等AI模型做底层数据支持的时候遇到的问题和解决办法。若想具体看哪个解决办法和源码算法的,可以留言告诉我哦~?
? ? ? ? 如标题所言,gpt等AI的回答的内容太长,真正有用的答案不到全部回答的一小半,人阅读起来会感觉不错,但让你的算法阅读起来就要麻烦了,各种无用的文案非常难以剔除。导致其这样的原因无外乎两个:
????????1. 更多的回答可以浪费更多的tokens,也就是需要你花费更多$。
????????2. AI学习的那些资料本就是这样的语境或者书面语,所以学成归来的AI也不会说话很简洁干脆。
? ? ? ? 举例:你问gpt? 1+1等于几?
? ? ? ? gpt回答:
????????
? ? ? ? 效果如下:
? ? ? ? 如标题所言,举个例子:
????????现在有一份简历提交给gpt,让其帮忙找出简历中应聘者的姓名,联系方式,地址三项。
? ? ? ? 但是结果往往是,gpt帮你找出了很多其他的你压根没要的信息,比如邮箱。因为在gpt的学习认知里,别人要解析简历信息的都是一次就要全了 姓名、联系方式、地址、邮箱。这还不算完,gpt甚至会给你展现出简历中不存在的信息,也就是虚假信息,这些信息是gpt自行推断猜测出来的。这样的随意结果,如果当成重要的底层数据,那将是一场灾难。
? ? ? ? 当然,一些好的模型是很少出现这个问题的,但为了保险起见,我觉得这种大文本的解析中,应该要至少对预期结果 和 实际结果 做一个比对验证层,在比对通过了之后,才能进行下一步。而这个比对包括以下几点:
? ? ? ? 1. 找出 实际结果中 缺少的 要求字段。
? ? ? ? 2. 删掉 实际结果中 额外的 非要求字段。
? ? ? ? 3. 验证 实际结果的每个字段是否真实(通过字符串词组在原文中的相似度得分来判断)。
? ? ? ? 4. 检查 实际结果中 缺少的字段 重新提问获取。
? ? ? ? 在这个对比层结束之后。如果答案质量不高,没有通过比对验证层,那我们就可以再次发问,这次在最后要加上:
? ? ? ? "刚刚的答案要更加严格规范一点,不要加任何联想和推测,要依据客观事实"
? ? ? ? 然后gpt就会先给你个道歉,然后重新给你生成一次不错的回答了。
? ? ? ??
? ? ? ? gpt出圈的原因,就在于其模仿人类一样的自然语言,流畅而合乎语境。但在我们提取的时候则遇到了麻烦,你的算法也好,正则也罢,都不可能百分百的解析一段纯自然话术。
? ? ? ? 比如这个例子:
????????
? ? ? ? 哪怕是同一个问题,再次的回答也会有格式上的差异:注意看,前面的点·没了。 你再问还会有其他各种类型的答案。
????????
? ? ? ? 面对这样不可控的回答,你怎么提取出来有效信息呢?或者说,本来原文就是一段自然语言,经过gpt的解析后结果仍然是一段自然语言,意义何在?
? ? ? ? 所以,解决方案就是,用json进行强制要求!
????????
? ? ? ? 而我们解析json那是真的简单快速了就,起码代码不会频繁报错,也不用写复杂的解析算法正则等等了。
????????
? ? ? ? 如果你不满意或者无法预料json答案的字段名,导致提取失败。那你可以强制要求字段的名称key,一开始就写好这个空的json,让gpt帮你添上。这样,数据的字段就是固定的,后面提取更精确了。
? ? ? ? 其实一直以来,对这种第三方接口的返回值很慢很贵的情况,我们开发时候都会做一个Mock层:就是把某次的回答写死,来让接口不真的去请求第三方服务器,直接返回写死的返回值。
? ? ? ? 但是,gpt的接口回答,却不能这么简单。因为它每次回答的结果都很难保持一致。如果你用了其中某次的结果作为mock值,那么根据此你写的算法和代码,都没啥用了。因为下了mock后,你随便测试一下,就会发现报错,然后查询发现,gpt的回答和你mock的完全不一致,格式也好,正错也好,数量都出现了偏差,甚至很大很大。
? ? ? ? 小的偏差还好,但是大的偏差就很糟糕了。比如下面这个例子,同一个问题,问了两次,结果如下:
????????
? ? ? ? 不但格式不同,就算是结果都不相同了,第一次失败,第二次成功。
? ? ? ? 这个原因在于AI模型的路线随机性所致,大家都知道,AI模型的基础结构一般分为三部分:
? ? ? ? 输入层 - 中间层 - 输出层。
? ? ? ? 输入层和输出层都是固定的,唯一变数就是中间层。
? ? ? ? 中间层会包含很多层,每个层会有很多个节点,每个节点代表某个因素。而这也就是随机的本质。
? ? ? ? 如果中间层只有2层,每层2个节点,那么理论上来讲,结果只会有2*2 = 4种,而且相邻如此近,这4种答案都几乎差不多,这种时候,我们随机用其中1种答案作为mock来开发调试没啥问题。
? ? ? ? 但实际上的gpt解析中,中间层可能有几百上千层,每层有成百上千个节点,这取决与你要问的问题是什么,要解析的原文有多长,有多少个tokens。
? ? ? ? 古人云:失之毫厘谬以千里 。 如果这条路线在最开始就走偏了,那么最终的结果可能和你预期的就相去甚远了。虽然有几乎百万种生成结果,但是大体分类上,可能只有十几种类别(相邻差不多的结果偶尔个别字不同无关大雅),而这种类别之间的区别就非常大了。就像上面的问题一样,甚至说一个成功,一个失败。
? ? ? ? 那针对这种情况,我们期望的结果,其实就是其中那1-2种结果罢了,当然,根据GPT用户不断的人为校对反馈,最终生成这预期1-2种结果的概率很大,甚至接近于90%。但总有那一丁点小概率,走了其他结果很糟糕的类别。这时候,你怎么办?你的代码只能是报错或者给了用户错误的结果产生误导,造成巨大损失。
? ? ? ? 那这样看来,我的解决办法就是做一个结果类别甄选层:通过一个大数字循环,收集所有可能的结果,每发现一个新的结果就将其存放到一个列表数组中,当连续上百次都无法发现新的结果的时候,就可以宣告99.99%的概率是列表中的几大结果类别了。然后如果要mock的话,则每次顺序或随机循环的取出这个列表数组的元素,作为mock值,方便我们后续代码可以每次调试都对所有可能情况进行验证,这其中,你还可以做一个过滤,把不符合要求的大多数类别直接pass掉。只保留那1-2种可接受的结果作为mock值。在之后代码正式运行时也是如此,一旦检测到结果不属于可接受结果,则直接pass掉,然后重新问,再问的时候,就要加上要求了以便gpt来矫正答案。
????????
? ? ? ? 在你用gpt生成一些故事或者概括,简介的时候。gpt生成的结果乍一看没毛病,但是等你真上线了并且观察埋点数据就会发现,用户基本不看。原因之一,就是gpt生成的文案看着没劲。
? ? ? ? 比如这个:
? ? ? ? 虽然说的全对,精准无比,总结到位。但就总少了那么一点耐人寻味,引人入胜,精神调味。
? ? ? ? 解决方案也很简单,对其进行要求即可。
? ? ? ? 当然,这个具体要求就看你的尝试了,我目前用gpt做的工具里基本就是这样进行简介,效果是有提升的,后需还要继续探索出更好的问题技巧。
? ? ? ? 我用gpt做底层的一些小工具中总结了这个方法论:
? ? ? ? 【前期轻度】:因为gpt作为公共语言模型的不稳定性,本地化专业化也不够,导致简历优化的最终结果非常差,可以说和预期相差太大。所以前期的时候,不要重用gpt,只需要轻轻引入即可,让其做一些简单的打下手的任务,重要的功能还是要我们自己写的算法来做。算法做出的预期结果更符合我们需求。然后最多让gpt优化一下成为自然语言即可。这样是最安全的。
? ? ? ? 【中期养膘】:gpt刚引入的时候就像一个蹒跚学步的孩童,我们虽不能委之大用,但也不能不指着gpt,在每次我们的算法+人工的运行下,结果都要喂给gpt,让其慢慢的学,慢慢的矫正,帮我们训练出一个针对公共模型的矫正层。随着时间推移,矫正层的数据慢慢变大,而公共大模型gpt进入矫正层后,出来的答案就会越来越符合我们的具体需求。可以帮我们的任务比例就会慢慢变大,总体程序也会越来越轻便快速和丝滑。
? ? ? ? 【后期重用】:在我们经过一段时间的抚养后,gpt慢慢的就长成了我们要求的样子,此时便可以停止喂养(毕竟喂养训练是有巨大成本的),停止我们人工维护,停止我们一开始的各种算法,来让gpt尝试独立去解决业务问题。当一段时间测试通过后,这个工具就算成了。此时,也算是形成了技术壁垒,别人想山寨你一时半会都山寨不出来了。