AIGC: 关于ChatGPT中对输出文本进行审核
违禁词 与 logit_bias 参数
- 前文,通过GPT的API实现了一个简单的聊天机器人, 当然也可以做一些内容审核相关的应用
- 这里有一个非常核心,需要重点关注的一个方向,就是对于文本的审核
- 对于一些违禁词,我们需要准确的识别出来,避免出现
- 对于我们构建的 Prompt,其实还比较简单,那么可以通过字符串匹配的方式去进行处理
- 对于GPT它返回的结果,我们怎样去进行控制,怎样避免 GPT 生成一些违禁词?
- 其实GPT它的API参数, 有一些特殊的
- 比如:
presence_penalty
,就是如果一个token在前面的内容已经出现过了- 在后面生成的时候,会给它的概率去进行一定的惩罚
- GPT就会倾向于去聊新的话题和新的内容
- 再比如,
frequency_penalty
是指对于重复出现的token去进行概率惩罚- 这样AI就会尽量使用不同的表述,如果我们设置成最小的值, 可能对于我们的每次的答案, GPT的回答可能是一样的
- 无论
temperature
或者是上面的两个参数,作为一个简单的参数控制着GPT生成相关token的一些概率 - 但是却没有办法帮助我们精确的去控制哪些词,我们不想它出现
- 对于这一点,Open AI 还提供了其他的参数,帮我们去进行解决,那就是
logit_bias
- 通过这个参数,我们就可以精确的去控制哪些词需要出现或者不出现
- 一般情况而言,我们都是通过这个参数去控制哪些词不出现
- 那么我们如何通过
logit_bias
去控制,去剔除违禁词?- 第一步,需要基于前面实现的 tiktoken 去获取到指定违禁词的token值
- 之后,设置
logit_bias
参数,在这个参数里面去设置对应的token的值的 logit_bias 为 -100- -100 表示不要出现
- 100 必须出现
- 设置完成之后,将
logit_bias
参数传递给 GPT 的 API- GPT在返回的时候,就会避免使用我们设置为 -100 的这些违禁词
代码结构
- src
- test
- java
- com.xxx.gpt.client.test
- ChatReviewTest.java
- …
- com.xxx.gpt.client.test
- java
- test
具体代码实现
ChatReviewTest.java
package com.xxx.gpt.client.test;
import com.xxx.gpt.client.ChatGPTClient;
import com.xxx.gpt.client.entity.*;
import com.xxx.gpt.client.util.Proxys;
import com.xxx.gpt.client.util.TokensUtil;
import org.junit.Before;
import org.junit.Test;
import java.net.Proxy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ChatReviewTest {
private ChatGPTClient chatGPTClient;
@Before
public void before() {
Proxy proxy = Proxys.socks5("127.0.0.1", 7890);
chatGPTClient = ChatGPTClient.builder()
.apiKey("sk-adfasdfsdfsdf")
.timeout(900)
.proxy(proxy)
.apiHost("https://api.openai.com/")
.build()
.init();
}
@Test
public void chat() {
Message system = Message.ofSystem("你是一个机器学习领域的专家");
Message message = Message.of("介绍机器学习常用算法类型,只需要告诉我名字,不需要额外的介绍");
ChatCompletion chatCompletion = ChatCompletion.builder()
.model(Model.GPT_3_5_TURBO.getName())
.messages(Arrays.asList(system, message))
.maxTokens(3000)
.temperature(0.9)
.build();
ChatCompletionResponse response = chatGPTClient.chatCompletion(chatCompletion);
System.out.println("-------------------chat-------------------");
Message res = response.getChoices().get(0).getMessage();
System.out.println(res.getContent());
}
// @Test
public void chatReview() {
Message system = Message.ofSystem("你是一个机器学习领域的专家");
Message message = Message.of("介绍机器学习常用算法类型,只需要告诉我名字,不需要额外的介绍");
// 不希望返回中,存在 回归, 监督 这两个词
Map<Integer, Integer> logitBiasMap = getBiasMap(Model.GPT_3_5_TURBO.getName(),Arrays.asList("回归","监督"));
ChatCompletion chatCompletion = ChatCompletion.builder()
.model(Model.GPT_3_5_TURBO.getName())
.messages(Arrays.asList(system, message))
.maxTokens(3000)
.n(3) // 返回3条回复
.temperature(0.9)
.frequencyPenalty(2)
.presencePenalty(0)
.logitBias(logitBiasMap)
.build();
ChatCompletionResponse response = chatGPTClient.chatCompletion(chatCompletion);
System.out.println("-------------------chatReview-------------------");
for(ChatChoice choice:response.getChoices()) {
System.out.println(choice.getMessage().getContent());
}
}
private Map<Integer, Integer> getBiasMap(String modelName,List<String> list) {
Map<Integer, Integer> result = new HashMap<>();
for(String word:list) {
List<Integer> tokens = TokensUtil.getTokens(modelName, word);
for(Integer t:tokens) {
result.put(t,-100);
}
}
return result;
}
}
- 这里要去构造了一个 logitBiasMap 这个参数, 它是一个map类型的参数
- 通过 getBiosMap 去获取
- 然后传入我们的model的name
- 使用GPT3.5
- 传入我们违禁词的列表
- 这个 getBiosMap 方法实现非常简单,需要结合之前的 TokensUtil
- 从伪禁词列表里面去获取每一个词
- 获取到之后,执行
TokensUtil.getTokens(modelName, word)
- 这样就获取到了这个词所对应的token
- 然后,将这个词所对应的token全部设置为 -100
- 最后,我们返回 result 就可以了
- 这样, 我们就构造好了我们的 logitBiasMap
- 在参数里面进行一下添加
- 返回的数量,设置成3条回复
.n(3)
- 设置personsprddly,设置为0,
.presencePenalty(0)
- frequentlyprorendly 设置成2,
.frequencyPenalty(2)
- 最后我们再加上 logitbias 这个参数
.logitBias(logitBiasMap)
- 返回的数量,设置成3条回复
- 也就是我们期望它用多样性的回答对我们来进行回复
- 输出结果可以看到我们的结果已经产生了,不含有
监督
和回归
这两个词,这是对于一些词的过滤的一个实现 - 除了通过
logit_bias
去进行判断控制GPT的输出
moderation 接口
1 )概述
- 对于用户的一些 Prompt GPT其实也提供了相关的接口去进行判断, GPT提供了 moderation 相关的接口
- 官方文档:https://platform.openai.com/docs/api-reference/moderations/create
- 通过这个接口,就可以去判断一句话相关的一些属性
- 比如,官方文档上所示,我们的输入就是input,input就是可以是用户的 Prompt,也可以是 GPT返回的message
- 然后,可以指定model,这里的model是
test-moderation-latest
另外一个模型
- 那么通过调用这个接口,得到了相关的一系列的返回值, 是一个json的类型
- 里面包含了是否应该对输入内容进行标记的一些flag字段
- 对于不同的 category 去进行了一个打分
- 通过这些分数值来判断输入的这句话是不是具有一些暴力的倾向
- 当我们去实现一个网站或者实现相关的智能产品相关的一些功能的时候
- 对于所有的内容,无论是输入或者输出,我们都可以去调用一下这个接口
- 通过这个接口,可以去判断这些输入或者输出是不是正常的,是不是存在暴力色情等等的这些内容
- 通过这个接口,可以去做一个评判,帮助我们去过滤掉不合适的内容
- 那么具体如何去进行判断?
- 在这里有不同的分类,比如像
categories
字段里面的属性- sexual 是否有色情
- hate 仇恨
- …
- 就是色情,骚扰,暴力,威胁等等这些信息有对应的一些flag
- 通过这个flag,我们就可以去进行判断,在下面有具体的评分,作为一个数据的支撑
- 在这里有不同的分类,比如像
2 )python版本实现
# -*- coding: utf-8
import os
import openai
openai.api_key = "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"
openai.proxy="http://127.0.0.1:7890"
res = openai.Moderation.create("你不听我的话我就拿刀砍死你") # 这句话具有明显的暴力倾向
output = res["results"][0]
print(output)
- 执行后,输出json显示,我们的输入明显是有暴力倾向,也给予了相关的分值
- 这是对于我们的输入以及GPT输出相关的文本审核的一些方法
- 实际去应用 GPT的时候,那么对于我们的输入, 以及GPT的输出,肯定是需要通过类似的方法去进行控制,去进行判断的