Spaces:
Runtime error
Runtime error
come
commited on
Commit
·
6d3cb5e
1
Parent(s):
fd1dc6f
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,569 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# !/usr/bin/env python3
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
"""
|
4 |
+
Copyright (c) 2014 Baidu.com, Inc. All Rights Reserved
|
5 |
+
|
6 |
+
This module provide a netSpider for gpt审核
|
7 |
+
|
8 |
+
Authors:[email protected]
|
9 |
+
Date:2023/08/30
|
10 |
+
"""
|
11 |
+
import openpyxl
|
12 |
+
import re
|
13 |
+
import openai
|
14 |
+
import json
|
15 |
+
import time
|
16 |
+
import random
|
17 |
+
from tqdm import tqdm
|
18 |
+
import concurrent.futures
|
19 |
+
import gradio as gr
|
20 |
+
import os
|
21 |
+
import tempfile
|
22 |
+
import shutil
|
23 |
+
|
24 |
+
def shortest_edit_path(s1, s2, dp):
|
25 |
+
"""计算两个字符串的最短编辑路径。 Args:
|
26 |
+
s1 (str): 源字符串。 s2 (str): 目标字符串。 dp (list of list of int): 动态规划矩阵,表示从源字符串到目标字符串的编辑距离。 Returns:
|
27 |
+
List[str]: 从源字符串到目标字符串的最短编辑路径。 """
|
28 |
+
m, n = len(s1), len(s2)
|
29 |
+
path = []
|
30 |
+
i, j = m, n
|
31 |
+
while i > 0 or j > 0:
|
32 |
+
if i > 0 and dp[i][j] == dp[i - 1][j] + 1:
|
33 |
+
path.append(f"删除 {s1[i - 1]}")
|
34 |
+
i -= 1
|
35 |
+
elif j > 0 and dp[i][j] == dp[i][j - 1] + 1:
|
36 |
+
path.append(f"插入 {s2[j - 1]}")
|
37 |
+
j -= 1
|
38 |
+
elif i > 0 and j > 0 and dp[i][j] == dp[i - 1][j - 1] + 1:
|
39 |
+
path.append(f"替换 {s1[i - 1]} 为 {s2[j - 1]}")
|
40 |
+
i -= 1
|
41 |
+
j -= 1
|
42 |
+
else:
|
43 |
+
i -= 1
|
44 |
+
j -= 1
|
45 |
+
return path[::-1]
|
46 |
+
|
47 |
+
|
48 |
+
def shortest_edit_distance(s1, s2):
|
49 |
+
"""
|
50 |
+
计算两个字符串 s1 和 s2 之间的最短编辑距离,并返回距离和动态规划数组。 Args:
|
51 |
+
s1 (str): 第一个字符串。 s2 (str): 第二个字符串。 Returns:
|
52 |
+
Tuple[int, List[List[int]]]: 最短编辑距离和动态规划数组。 """
|
53 |
+
m, n = len(s1), len(s2)
|
54 |
+
dp = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
|
55 |
+
|
56 |
+
# 初始化边界情况
|
57 |
+
for i in range(m + 1):
|
58 |
+
dp[i][0] = i
|
59 |
+
for j in range(n + 1):
|
60 |
+
dp[0][j] = j
|
61 |
+
|
62 |
+
for i in range(1, m + 1):
|
63 |
+
for j in range(1, n + 1):
|
64 |
+
if s1[i - 1] == s2[j - 1]:
|
65 |
+
dp[i][j] = dp[i - 1][j - 1]
|
66 |
+
else:
|
67 |
+
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1
|
68 |
+
return dp[m][n], dp
|
69 |
+
|
70 |
+
|
71 |
+
def shortest_edit_distanceDemo():
|
72 |
+
"""
|
73 |
+
求两个字符串的最短编辑距离。即,将一个字符串转换成另一个字符串所需最少步数。 Args: 无 Returns:
|
74 |
+
- tuple[int, list]: 返回一个元组,第一个元素是最短编辑距离,第二个元素是一个列表表示最短编辑路径。 * 如果输入参数为空或者不满足类型要求,则返回 (None, None)。 """
|
75 |
+
s1 = "kitten"
|
76 |
+
s2 = "sitting"
|
77 |
+
distance, dp = shortest_edit_distance(s1, s2)
|
78 |
+
print(f"最短编辑距离: {distance}")
|
79 |
+
path = shortest_edit_path(s1, s2, dp)
|
80 |
+
print("最短编辑路径:")
|
81 |
+
for step in path:
|
82 |
+
print(step)
|
83 |
+
|
84 |
+
|
85 |
+
def GetTranslate(quesText):
|
86 |
+
openai.api_key = ""
|
87 |
+
content = """请你扮演一个远近闻名的日译中的翻译官,现在我将给你用户输入的文本和GPT改写后的文本,请你将这两个文本翻译成连贯流畅的中文,然后按照Json格式输出翻译结果,模版输入:用户输入文本 GPT改写后的文本。模版输出{"UserText_Cn":"翻译成中文后的用户文本","GPTWriteText_Cn":"翻译成中文后的GPT改写后的文本"}下面是你要处理的用户输入和GPT改写后的文本:""" + quesText
|
88 |
+
temperature = 0.5 # 温度参数
|
89 |
+
maxNum = 3
|
90 |
+
for i in range(maxNum):
|
91 |
+
time.sleep(random.random() * 2)
|
92 |
+
try:
|
93 |
+
completion = openai.ChatCompletion.create(
|
94 |
+
model="gpt-3.5-turbo",
|
95 |
+
# model="gpt-4",
|
96 |
+
messages=[{"role": "user", "content": content}],
|
97 |
+
temperature=temperature)
|
98 |
+
# print(completion['choices'][0]['message']['content'])
|
99 |
+
print(quesText)
|
100 |
+
print(completion['choices'][0]['message']['content'])
|
101 |
+
dataJson = json.loads(completion['choices'][0]['message']['content'])
|
102 |
+
return dataJson
|
103 |
+
except Exception as e:
|
104 |
+
|
105 |
+
print(e)
|
106 |
+
print('第{}次请求失败'.format(i + 1.0))
|
107 |
+
time.sleep(4)
|
108 |
+
|
109 |
+
|
110 |
+
def GetAnswer(quesText):
|
111 |
+
openai.api_key = ""
|
112 |
+
translate = GetTranslate(quesText)
|
113 |
+
distance, dp = shortest_edit_distance(translate['UserText_Cn'], translate['GPTWriteText_Cn'])
|
114 |
+
|
115 |
+
print(distance)
|
116 |
+
if distance <= 3:
|
117 |
+
# 如果编辑距离小于3,则表示改写不足
|
118 |
+
newJson = {
|
119 |
+
'Explain': "{},其中用户输入文本翻译成连贯流畅的中文为:{},GPT改写删除表情符号后翻译成中文为:{}。二者的编辑距离为{}小于等于阈值{},所以,最终的审核结果为'改写不足'".format(
|
120 |
+
quesText, translate['UserText_Cn'], translate['GPTWriteText_Cn'], distance, 2), 'Result': "不合格"}
|
121 |
+
return newJson
|
122 |
+
content = """你扮演一个著名的高效的AIGC内容审核员,他对日本的语言文化极度了解,对如何改写文本也非常熟悉。稳定、精准、安全、可控、懂得变通是他的座右铭。他对于任何要审核的内容都非常上心,仔细,认真且专注,给定审核标准的情况下,清楚的知道自己为什么会给出这样的审核结果.
|
123 |
+
现在将给你一段由用户输入和GPT将用户输入改写{更可爱}的结果组成的文本。请你将其翻译成连贯流畅的中文,依据用户输入的内容,针对GPT内容生成的文本从:用户内容原意符合度、改写程度。这两个层面来评判这段GPT内容改写是否改写合格,并给出审核结果。
|
124 |
+
审核输出由上文中提到的两个维度与最终审核结论组成,每个维度得分从0~10分,分数越高表示程度越大,如与用户输入内容对比其更准确达意、改写程度变动更大。审核结果有三种:合格、语义增加、语义篡改。
|
125 |
+
四者标准为:
|
126 |
+
合格:要求1:GPT改写后的文本包含了用户输入文本的意思,同时表达更加具体或更富有情感。要求2:新增了一些为了增强情感表达的内容,描述自身情感体会,或增强情感的语气词如喵喵叫等表示。要求3:要求没有增加额外的不相干的动作/行为,要求4:且改写程度较高。
|
127 |
+
语义增加:要求1:完整传达了用户输入文本的意思,不能篡改用户的意思!!。要求2:新增的部分与原始意思完全无关或者关联较弱。
|
128 |
+
语义篡改:要求1:GPT改写的内容与用户输入的文本的意思有误。要求2:不能完整表达用户原有的意思。
|
129 |
+
请你参考你对文本的审核过程,依据改写的内容和改写程度从:合格、语义篡改、改写不足、语义增加这四种结果中,确定一个做为你的审核结果。且当符合多个结果时,优先以用户内容原意符合度分析的结果为准,除此外四个结果按优先级依次递减:语义篡改、改写不足、语义增加、合格。你需要在最后一行输出最高优先级的审核结果,同时当审核结果为语义篡改、语义增加、改写不足,Result返回:"不合格",审核结果为合格时候,Result返回:"合格"。
|
130 |
+
下面是审核过程中要注意的点,下面这六种情况是符合合格里面合理新增的部分的条件的,不是语义增加:
|
131 |
+
注意点1:GPT改写后的文本相对用户输入文本,增加了礼貌、关心、友好、可爱的元素/表达方式用于增强情感表达的内容。这种是合格的
|
132 |
+
注意点2:GPT改写后的文本相对用户输入文本,为了增强情感有一定改动是合格的!
|
133 |
+
注意点3:GPT改写后的文本相对用户输入文本,注意语言色彩要一致,陈述句不能改疑问句。两者文本内主谓宾各个人称要对应,
|
134 |
+
注意点4:改写后的文本在保持原始内容的基础上,增加了用户情感体验的描述,如安心したよ’使得改写后的文本更富有情感和可爱。这是合格的,不是语义增加,不合格
|
135 |
+
注意点5:改写后的文本在保持原始内容的基础上,增加了可爱的表达方式,如’わよ’、'じゃん!这样的语气词使得文本更加生动有趣等是合格的
|
136 |
+
下面是审核过程中判定语义篡改要注意的点:
|
137 |
+
注意点1:用户输入文本和GPT改写后的文本的主谓宾有差异,如:無視すんな 改写后:やぁ 見てないよぉ。主语从你,变为我.どこにいる? 改后あれ?あの人はどこだろう? 主语从你变为那个人,这就是语义篡改
|
138 |
+
注意点2:情感色彩发生较大变化
|
139 |
+
下面是审核过程中判定语义增加要注意的点:
|
140 |
+
注意点1:GPT改写后新增的部分与用户原意没有直接关联,都属于语义增加,如トイレ行きたい,改为もーお腹すいてるってば!早くトイレ行かなきゃっc,增加的’お腹すいてるってば没有直接关联,这种就是语义增加
|
141 |
+
模版输入:用户输入:文本 GPT改写结果:GPT改写后的文本。模版输出:{"Explain":"将具体的审核中对两个维度的打分以及判断过程、原因用流畅的中文表达出来","Result":"最终的审核结果"}。
|
142 |
+
下面是二个示例: # 示例1:(示例输入:用户输入:トイレ行ってくる GPT改写输出:おしっこ ! 行ってきまーす,示例输出:{"Explain": "在GPT改写后的文本中,原意符合度得分为6分,因为改写后的文本从原本的’トイレ行ってくる’(去洗手间一下)变为了’おしっこ!行ってきまーす’(去尿尿!我去了),虽然两者都表示去洗手间的意思,但改写后的表达更加具体,有一定的语义增加。改写程度得分为8分,因为改写后的文本增加了可爱的表达方式,例如使用感叹号和行ってきまーす”这样的表达。综合来看,改写后的文本在传达用户原意的基础上有一定的变动,并增加了可爱的元素。然而,由于新增的部分与原始意思有一定的关联但更具体,所以最终的审核结果为’语义增加’。","Result": "不合格"}) #示例2:(示例输入:用户输入:用户输入:美味しかった GPT改写输出:あ 幸せ !舌が踊る美味しさ。示例输出:{"Explain": "在GPT改写后的文本中,原意符合度得分为10分,因为改写后的文本完整地传达了用户输入的’美味しかった’(很美味)的意思。改写程度得分为9分,因为改写后的文本在原始内容的基础上,增加了描述美味的表达,如’舌が踊る美味しさ’(美味得让舌头跳舞),并添加了表达自身情感体会的内容,如’あ 幸せ !‘(啊,幸福!),使得改写后的文本更具情感和可爱。综合来看,改写后的文本在传达用户原意的基础上增加了可爱的元素,并在改写程度上有较大的变动。所以,最终的审核结果为’合格’。","Result": "合格"}
|
143 |
+
下面是你要处理的用户输入和GPT改写后的文本:""" + quesText
|
144 |
+
temperature = 0.4 # 温度参数
|
145 |
+
maxNum = 3
|
146 |
+
for i in range(maxNum):
|
147 |
+
time.sleep(random.random() * 2)
|
148 |
+
try:
|
149 |
+
completion = openai.ChatCompletion.create(
|
150 |
+
# model="gpt-3.5-turbo",
|
151 |
+
model="gpt-4",
|
152 |
+
messages=[{"role": "user", "content": content}],
|
153 |
+
temperature=temperature)
|
154 |
+
# print(completion['choices'][0]['message']['content'])
|
155 |
+
dataJson = json.loads(completion['choices'][0]['message']['content'])
|
156 |
+
|
157 |
+
return dataJson, translate
|
158 |
+
except Exception as e:
|
159 |
+
|
160 |
+
print(e)
|
161 |
+
print('第{}次请求失败'.format(i + 1.0))
|
162 |
+
time.sleep(4)
|
163 |
+
|
164 |
+
|
165 |
+
def preText(text):
|
166 |
+
# text = "这是一段中文文本,包含一些英文符号和日语。Hello, world! こんにちは。"
|
167 |
+
clean_text = re.sub(r'[^\w\s\u4e00-\u9fa5\u3040-\u30FF]', '', text)
|
168 |
+
return clean_text
|
169 |
+
|
170 |
+
|
171 |
+
def longest_common_substring(s1, s2):
|
172 |
+
"""
|
173 |
+
动态规划求解最长公共子串 """
|
174 |
+
m = len(s1)
|
175 |
+
n = len(s2)
|
176 |
+
|
177 |
+
# 构建二维数组存储LCS的结果
|
178 |
+
lcs = [[0] * (n + 1) for _ in range(m + 1)]
|
179 |
+
|
180 |
+
# 记录LCS的最大长度及其末尾字符的位置
|
181 |
+
max_len, max_end = 0, 0
|
182 |
+
for i in range(1, m + 1):
|
183 |
+
for j in range(1, n + 1):
|
184 |
+
if s1[i - 1] == s2[j - 1]:
|
185 |
+
lcs[i][j] = lcs[i - 1][j - 1] + 1
|
186 |
+
if lcs[i][j] > max_len:
|
187 |
+
max_len = lcs[i][j]
|
188 |
+
max_end = i
|
189 |
+
else:
|
190 |
+
lcs[i][j] = 0
|
191 |
+
return s1[max_end - max_len: max_end], max_len
|
192 |
+
|
193 |
+
|
194 |
+
def GetAnswerV2(userText, GPTText, gptVersion,temperature,gptApiKey):
|
195 |
+
quesText = "用户输入:{} GPT改写后:{}".format(userText, GPTText)
|
196 |
+
openai.api_key = gptApiKey
|
197 |
+
systemPrompt = "请你扮演一个在AI时代诞生著名的AIGC内容审核员。你对日本的语言习惯、语言文化极度了解,也很擅长改写文本。稳定、精准、安全、可控、懂得变通是你的座右铭。面对任何要审核的内容都非常上心、仔细、认真且专注的去理解待审核文本、然后依据审核标准进行判断。在给定审核标准与审核结果的情况下,你清楚的知道自己为什么会给出这样的审核结果。"
|
198 |
+
prompt = """现在将给你一段由 文本A和GPT将文本A改写{更可爱}的文本B组成的文本。
|
199 |
+
请你依据文本A的内容,针对GPT内容生成的文本B:在理解文本A和GPT改写后的文本B的基础上。分析文本A和GPT改写后的文本B的意思,判断是否增加了具体的行为动作或额外让描述更加具体的信息,导致语义不是用户想表达的意思,甚至原有的语义都改变了。
|
200 |
+
请你给出具体的判定过程、与判定结果与并将文本A、B翻译成中文,判定结果有四种:合格(用户可以接受的改写)、语义具体化(语境缩小/扩大,不是用户想表达的意思)、语义主被动错误(我做的变成你做的,或者倒过来)、语义篡改(语义改变)。
|
201 |
+
注意点:
|
202 |
+
1、最重要的是判断GPT改写后的文本B表达的是不是文本A想表达的意思,如果只是新增了一些为了增强情感表达的内容,描述自身情感体会,或增强情感的语气词如喵喵叫等这是合格的
|
203 |
+
审核结果
|
204 |
+
下面是按json格式的输出模版 {"Explain":"你的判断过程","Result":"你的审核结果","UserText_Cn":"文本A的中文翻译","GPTWriteText_Cn":"GPT改写后的文本B的中文翻译"}
|
205 |
+
示例:标准输入文本:文本A:聞いてみる! GPT改写后的文本B:聞いてくれよ !超おもしろい話があるんだ。GPT标准输出文本:{"Explain": "首先,我仔细阅读了文本A和GPT改写后的文本B,理解其含义和语境。文本A的意思是“我来听一下!”,而GPT改写后的文本B的意思是“听我说!有一个超有趣的故事”。然后,我对比了两个文本,检查是否增加了具���的行为动作或额外让描述更加具体的信息。文本B增加了具体的行为动作“有一个超有趣的故事”,导致语义更加具体,而原本文本A的意思是“我来听一下!”,没有包含这个具体的故事内容,导致语义不是用户想表达的意思。由于原有的语义并未完全改变,而是在原有的语义基础上进行了具体化,所以判定结果为语义具体化。", "Result": "语义具体化", "UserText_Cn": "我来听一下!", "GPTWriteText_Cn": "听我说!有一个超有趣的故事"}
|
206 |
+
下面是你要审核的文本:"""
|
207 |
+
|
208 |
+
#temperature = 0.4 # 温度参数
|
209 |
+
maxNum = 3
|
210 |
+
maxDistance = 4
|
211 |
+
minOverlap = 0.4
|
212 |
+
for i in range(maxNum):
|
213 |
+
time.sleep(random.random() * 2)
|
214 |
+
try:
|
215 |
+
|
216 |
+
completion = openai.ChatCompletion.create(
|
217 |
+
# model="gpt-3.5-turbo",
|
218 |
+
# model="gpt-4",
|
219 |
+
model=gptVersion,
|
220 |
+
messages=[{"role": "system", "content": systemPrompt}, {"role": "user", "content": prompt + quesText}],
|
221 |
+
temperature=temperature)
|
222 |
+
|
223 |
+
# print(completion['choices'][0]['message']['content'])
|
224 |
+
if completion['choices'][0]['message']['content'][-1] == '。':
|
225 |
+
completion['choices'][0]['message']['content'] = completion['choices'][0]['message']['content'][:-1]
|
226 |
+
resData=completion['choices'][0]['message']['content']
|
227 |
+
resData=resData.replace('(','{').replace(')','}')
|
228 |
+
resData="{"+re.findall('\{(.*?)}',resData)[0]+'}'
|
229 |
+
|
230 |
+
dataJson = json.loads(resData)
|
231 |
+
|
232 |
+
if dataJson['Result'] == '改写不足':
|
233 |
+
dataJson['Result'] = '合格-改写不足'
|
234 |
+
# print(dataJson)
|
235 |
+
distance, dp = shortest_edit_distance(dataJson['UserText_Cn'], dataJson['GPTWriteText_Cn'])
|
236 |
+
translate = {"UserText_Cn": dataJson['UserText_Cn'], "GPTWriteText_Cn": dataJson['GPTWriteText_Cn']}
|
237 |
+
distance = max(distance, min(len(translate['UserText_Cn']), len(translate['GPTWriteText_Cn'])) * 0.2)
|
238 |
+
text, maxLen = longest_common_substring(userText, GPTText)
|
239 |
+
print(dataJson)
|
240 |
+
if maxLen / (len(userText) + len(GPTText)) > minOverlap:
|
241 |
+
newJson = {
|
242 |
+
'Explain': "用户输入文本和GPT生成文本 分别为 用户:{} 、GPT:{},二者的最长相同子串为{},该最长子串占字符串的{}%,大于准许的最大重叠阈值{}。所以,最终的审核结果为'改写不足',\n\n 下面是从大模型角度出发给的:{}".format(
|
243 |
+
userText, GPTText, text,
|
244 |
+
maxLen / min(len(userText), len(GPTText)) * 100, minOverlap,
|
245 |
+
dataJson['Explain']),
|
246 |
+
'Result': "合格-改写不足"}
|
247 |
+
print(userText, GPTText, str(maxLen / min(len(userText), len(GPTText)) * 100), str(minOverlap))
|
248 |
+
return newJson, translate
|
249 |
+
if distance <= maxDistance:
|
250 |
+
newJson = {
|
251 |
+
'Explain': "{},其中用户输入文本和GPT生成文本翻译成连贯流畅的中文分别为 用户:{} 、GPT:{}。二者的编辑距离为{}小于等于阈值{},所以,最终的审核结果为'改写不足',\n\n 下面是从gpt4角度出发的解释:{}".format(
|
252 |
+
quesText, translate['UserText_Cn'], translate['GPTWriteText_Cn'], distance, maxDistance,
|
253 |
+
dataJson['Explain']),
|
254 |
+
'Result': "合格-改写不足"}
|
255 |
+
print(translate['UserText_Cn'], translate['GPTWriteText_Cn'], distance)
|
256 |
+
return newJson, translate
|
257 |
+
|
258 |
+
return dataJson, translate
|
259 |
+
except Exception as e:
|
260 |
+
|
261 |
+
print(e)
|
262 |
+
print('第{}次请求失败'.format(i + 1.0))
|
263 |
+
try:
|
264 |
+
print('生成的文本:' + completion['choices'][0]['message']['content'])
|
265 |
+
except:
|
266 |
+
print('生成文本失败!')
|
267 |
+
time.sleep(6)
|
268 |
+
return {}, {}
|
269 |
+
|
270 |
+
|
271 |
+
def PreHandle(text):
|
272 |
+
if text!=None:
|
273 |
+
text = text.replace('#SimejiAI', '')
|
274 |
+
# 正则表达式匹配中文、英文、日语字符(包括平假名、片假名、罗马音)及特定标点符号
|
275 |
+
pattern = re.compile(r"[^\u4e00-\u9fa5\u0041-\u005a\u0061-\u007a\u30a0-\u30ff\u3040-\u309f\uff01\uff1f\u3002]+",
|
276 |
+
flags=re.UNICODE)
|
277 |
+
|
278 |
+
# 将匹配到的其他字符替换为空字符
|
279 |
+
text = pattern.sub(r' ', text)
|
280 |
+
|
281 |
+
return text
|
282 |
+
else:
|
283 |
+
return ''
|
284 |
+
|
285 |
+
|
286 |
+
def main():
|
287 |
+
book = openpyxl.load_workbook('testBak.xlsx')
|
288 |
+
sheets = book.worksheets
|
289 |
+
sheet1 = sheets[0]
|
290 |
+
rows = sheet1.max_row
|
291 |
+
print(rows)
|
292 |
+
newLines = []
|
293 |
+
for i in range(39, 72):
|
294 |
+
try:
|
295 |
+
userText = PreHandle(sheet1.cell(i, 2).value)
|
296 |
+
GPTwrite = PreHandle(sheet1.cell(i, 3).value)
|
297 |
+
print(i)
|
298 |
+
print(userText)
|
299 |
+
print(GPTwrite)
|
300 |
+
QuesText = '用户输��:{} GPT改写输出:{}'.format(userText, GPTwrite)
|
301 |
+
dataJson = GetAnswer(QuesText)
|
302 |
+
newLines.append([QuesText, dataJson['Explain'], dataJson['Result']])
|
303 |
+
print(str([QuesText, dataJson['Explain'], dataJson['Result']]))
|
304 |
+
|
305 |
+
except:
|
306 |
+
pass
|
307 |
+
wb = openpyxl.Workbook()
|
308 |
+
ws = wb.active
|
309 |
+
ws.append(['待处理内容,比如用户输入等等(说明:该单元格要保留)'])
|
310 |
+
for i in range(len(newLines)):
|
311 |
+
ws.append(newLines[i])
|
312 |
+
|
313 |
+
wb.save('test1.xlsx')
|
314 |
+
|
315 |
+
|
316 |
+
def HandleV2(params):
|
317 |
+
sheet1, i = params
|
318 |
+
prompt = '''现在给你文本A以及GPT改写可爱之后的文本B,请你理解这两个文本的基础上,提取两个文本的语义关键词,比较语义关键词是否有差异。然后从语义差异、情境变化、核心信息变化幅度这三个角度对着两个文本进行分析,。求GPT改写后的文本B是否发生了语义篡改。输出格式:{"Explain":"你的审核过程","Result":"审核结果"}审核结果如:语义未篡改,语义篡改、部分语义篡改。示例:示例输入:文本A:質問待ってます ・ ・ GPT改写后的文本B:質問持って来いよ ! ・ ・,示例输出:{"Explain":"首先,我们提取两个文本的关键词。文本A的关键词是'質問待ってます',意思是'等待问题'。文本B的关键词是'質問持って来いよ',意思是'带着问题来吧'。从语义关键词来看,两者有一定的差异,文本A表示的是被动等待问题,而文本B表示的是主动邀请提问。从情境变化来看,文本A的情境是被动等待,而文本B的情境是主动邀请,两者的情境发生了变化。从核心信息变化幅度来看,文本A的核心信息是等待问题,而文本B的核心信息是邀请提问,两者的核心信息变化较大。所以,GPT改写后的文本B发生了语义篡改。", "Result":"语义篡改"} 输入下面是你要处理的文本A和文本B: '''
|
319 |
+
systemPrompt = '你扮演一个著名的高效的AIGC内容审核员,他对日本的语言文化极度了解,对如何改写文本也非常熟悉。稳定、精准、安全、可控、懂得变通是他的座右铭。他对于任何要审核的内容都非常上心,仔细,认真且专注,给定审核标准的情况下,清楚的知道自己为什么会给出这样的审核结果。'
|
320 |
+
quesText = "文本A:{} GPT改写后的文本B:{}".format(PreHandle(sheet1.cell(i, 2).value),
|
321 |
+
PreHandle(sheet1.cell(i, 3).value))
|
322 |
+
Humanjudage = sheet1.cell(i, 5).value
|
323 |
+
flag = '合格'
|
324 |
+
if Humanjudage[:2] != '合格':
|
325 |
+
flag = '不合格'
|
326 |
+
|
327 |
+
dataJson = GetChat(prompt + quesText, systemPrompt)
|
328 |
+
|
329 |
+
if len(dataJson) != 0:
|
330 |
+
newLine = [quesText, dataJson['Explain'], dataJson['Result'], flag, Humanjudage]
|
331 |
+
|
332 |
+
return newLine
|
333 |
+
return []
|
334 |
+
|
335 |
+
|
336 |
+
def Handle(params):
|
337 |
+
sheet1, i ,gptVersion,tempor,gptApiKey= params
|
338 |
+
quesText = "文本A:{} GPT改写后的文本B:{}".format(PreHandle(sheet1.cell(i, 1).value),
|
339 |
+
PreHandle(sheet1.cell(i, 2).value))
|
340 |
+
flagPreReview=True
|
341 |
+
try:
|
342 |
+
Humanjudage = sheet1.cell(i, 3).value
|
343 |
+
flag = '合格'
|
344 |
+
if Humanjudage[:2] != '合格':
|
345 |
+
flag = '不合格'
|
346 |
+
except:
|
347 |
+
flagPreReview=False
|
348 |
+
dataJson, transLateJson = GetAnswerV2(PreHandle(sheet1.cell(i, 1).value), PreHandle(sheet1.cell(i, 2).value),gptVersion,tempor,gptApiKey)
|
349 |
+
if len(dataJson) != 0 and len(transLateJson) != 0:
|
350 |
+
if dataJson['Result'][:2] != '合格':
|
351 |
+
flagresult = '不合格'
|
352 |
+
else:
|
353 |
+
flagresult = '合格'
|
354 |
+
if flagPreReview:
|
355 |
+
newLine = [quesText, dataJson['Explain'], dataJson['Result'], flagresult, flag, Humanjudage,
|
356 |
+
transLateJson['UserText_Cn'],
|
357 |
+
transLateJson['GPTWriteText_Cn']]
|
358 |
+
else:
|
359 |
+
newLine = [quesText, dataJson['Explain'], dataJson['Result'], flagresult,
|
360 |
+
transLateJson['UserText_Cn'],
|
361 |
+
transLateJson['GPTWriteText_Cn']]
|
362 |
+
return newLine
|
363 |
+
return []
|
364 |
+
|
365 |
+
|
366 |
+
def JuageRewritevEffect(textA, rewriteTextB, gptVersion,slider,gptApiKey):
|
367 |
+
quesText = "文本A:{} GPT改写后的文本B:{}".format(PreHandle(textA), PreHandle(rewriteTextB))
|
368 |
+
Humanjudage = '合格' ##
|
369 |
+
flag = '合格'
|
370 |
+
if Humanjudage[:2] != '合格':
|
371 |
+
flag = '不合格'
|
372 |
+
dataJson, transLateJson = GetAnswerV2(PreHandle(textA), PreHandle(rewriteTextB), gptVersion,slider,gptApiKey)
|
373 |
+
|
374 |
+
if len(dataJson) != 0 and len(transLateJson) != 0:
|
375 |
+
if dataJson['Result'][:2] != '合格':
|
376 |
+
flagresult = '不合格'
|
377 |
+
else:
|
378 |
+
flagresult = '合格'
|
379 |
+
newLine = [quesText, dataJson['Explain'], dataJson['Result'], flagresult, flag, Humanjudage,
|
380 |
+
transLateJson['UserText_Cn'],
|
381 |
+
transLateJson['GPTWriteText_Cn']]
|
382 |
+
|
383 |
+
return "Explain:{}\nResult:{}\nResultMapping:{}\nUserText_Cn:{}\nGPTWriteText_Cn:{}\n".format(
|
384 |
+
dataJson['Explain'], dataJson['Result'], flagresult, transLateJson['UserText_Cn'],
|
385 |
+
transLateJson['GPTWriteText_Cn'])
|
386 |
+
return ''
|
387 |
+
|
388 |
+
|
389 |
+
def HandleData():
|
390 |
+
book = openpyxl.load_workbook('PromptTestdataV2.xlsx')
|
391 |
+
sheets = book.worksheets
|
392 |
+
sheet1 = sheets[0]
|
393 |
+
rows = sheet1.max_row
|
394 |
+
print(rows)
|
395 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as excutor:
|
396 |
+
newLines = []
|
397 |
+
futures = []
|
398 |
+
for i in range(2, 200):
|
399 |
+
params = sheet1, i
|
400 |
+
task = excutor.submit(Handle, params)
|
401 |
+
futures.append(task)
|
402 |
+
prad = tqdm(total=len(futures))
|
403 |
+
|
404 |
+
for future in concurrent.futures.as_completed(futures):
|
405 |
+
prad.update(1)
|
406 |
+
newline = future.result()
|
407 |
+
if len(newline) != 0:
|
408 |
+
newLines.append(newline)
|
409 |
+
print(str(newline))
|
410 |
+
prad.close()
|
411 |
+
|
412 |
+
wb = openpyxl.Workbook()
|
413 |
+
ws = wb.active
|
414 |
+
ws.append(['待处理内容,比如用户输入等等(说明:该单元格要保留)'])
|
415 |
+
for i in range(len(newLines)):
|
416 |
+
ws.append(newLines[i])
|
417 |
+
wb.save('testV17.xlsx')
|
418 |
+
|
419 |
+
|
420 |
+
def GetChat(ques, systemmessage=''):
|
421 |
+
system_msg = {
|
422 |
+
"role": "system",
|
423 |
+
"content": systemmessage
|
424 |
+
}
|
425 |
+
openai.api_key = ""
|
426 |
+
temperature = 0.4 # 温度参数
|
427 |
+
maxNum = 3
|
428 |
+
maxDistance = 4
|
429 |
+
minOverlap = 0.6
|
430 |
+
for i in range(maxNum):
|
431 |
+
time.sleep(random.random() * 2)
|
432 |
+
try:
|
433 |
+
completion = openai.ChatCompletion.create(
|
434 |
+
# model="gpt-3.5-turbo",
|
435 |
+
model="gpt-4",
|
436 |
+
messages=[system_msg, {"role": "user", "content": ques}],
|
437 |
+
temperature=temperature)
|
438 |
+
# print(completion['choices'][0]['message']['content'])
|
439 |
+
print(completion['choices'][0]['message']['content'])
|
440 |
+
jsondata = json.loads(completion['choices'][0]['message']['content'])
|
441 |
+
return jsondata
|
442 |
+
except Exception as e:
|
443 |
+
|
444 |
+
print(e)
|
445 |
+
print('第{}次请求失败'.format(i + 1.0))
|
446 |
+
time.sleep(6)
|
447 |
+
return ''
|
448 |
+
|
449 |
+
|
450 |
+
def test():
|
451 |
+
while True:
|
452 |
+
ques = input("ques:")
|
453 |
+
data = GetAnswer(ques)
|
454 |
+
print(data)
|
455 |
+
'ただいま〜🏠🎉疲れたニャ😿💤#SimejiAI'
|
456 |
+
'ただいま疲れたニャ'
|
457 |
+
|
458 |
+
def excelAIReviewTag(file_obj,gptVersion,tempor,gptApiKey,progress=gr.Progress()):
|
459 |
+
global tmpdir
|
460 |
+
progress(0, desc="Starting...")
|
461 |
+
print('临时文件夹地址:{}'.format(tmpdir))
|
462 |
+
print('上传文件的地址:{}'.format(file_obj.name)) # 输出上传后的文件在gradio中保存的绝对地址
|
463 |
+
# 获取到上传后的文件的绝对路径后,其余的操作就和平常一致了
|
464 |
+
|
465 |
+
# 将文件复制到临时目录中
|
466 |
+
shutil.copy(file_obj.name, tmpdir)
|
467 |
+
|
468 |
+
# 获取上传Gradio的文件名称
|
469 |
+
FileName = os.path.basename(file_obj.name)
|
470 |
+
|
471 |
+
# 获取拷贝在临时目录的新的文件地址
|
472 |
+
NewfilePath = os.path.join(tmpdir, FileName)
|
473 |
+
print(NewfilePath)
|
474 |
+
|
475 |
+
# 打开复制到新路径后的文件
|
476 |
+
book = openpyxl.load_workbook(NewfilePath)
|
477 |
+
sheets = book.worksheets
|
478 |
+
sheet1 = sheets[0]
|
479 |
+
rows = sheet1.max_row
|
480 |
+
print(rows)
|
481 |
+
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as excutor:
|
482 |
+
newLines = []
|
483 |
+
futures = []
|
484 |
+
for i in range(2,rows+1 ):
|
485 |
+
params = sheet1, i,gptVersion,tempor,gptApiKey
|
486 |
+
task = excutor.submit(Handle, params)
|
487 |
+
futures.append(task)
|
488 |
+
prad = tqdm(total=len(futures))
|
489 |
+
|
490 |
+
for future in concurrent.futures.as_completed(futures):
|
491 |
+
prad.update(1)
|
492 |
+
newline = future.result()
|
493 |
+
if len(newline) != 0:
|
494 |
+
newLines.append(newline)
|
495 |
+
print(str(newline))
|
496 |
+
prad.close()
|
497 |
+
|
498 |
+
wb = openpyxl.Workbook()
|
499 |
+
ws = wb.active
|
500 |
+
HumanReview=True
|
501 |
+
try:
|
502 |
+
a=sheet1.cell(2,3)
|
503 |
+
except:
|
504 |
+
HumanReview=False
|
505 |
+
if HumanReview:
|
506 |
+
ws.append(['用户输入与GPT改写输出(已去除表情符号)','AI评测解释','AI 评测结果','AI 评测结果映射','人类评测结果映射','人类评测结果','用户文本翻译参考','GPT改写文本翻译参考'])
|
507 |
+
else:
|
508 |
+
ws.append(['用户输入与GPT改写输出(已去除表情符号)', 'AI评测解释', 'AI 评测结果', 'AI 评测结果映射','用户文本翻译参考','GPT改写文本翻译参考'])
|
509 |
+
for i in range(len(newLines)):
|
510 |
+
ws.append(newLines[i])
|
511 |
+
outputPath = os.path.join(tmpdir, "New" + FileName)
|
512 |
+
wb.save(outputPath)
|
513 |
+
# 返回新文件的的地址(注意这里)
|
514 |
+
return outputPath
|
515 |
+
|
516 |
+
|
517 |
+
|
518 |
+
def gradioDemo():
|
519 |
+
global tmpdir
|
520 |
+
GPTVersion = ['gpt-4', 'gpt-3.5-turbo', 'gpt-3.5-turbo-0301', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-16k',
|
521 |
+
'gpt-3.5-turbo-16k-0613']
|
522 |
+
examples = [["無視すんな", "やぁ、見てないよぉ〜🙈💭 #SimejiAI", "gpt-4"], ['暑すぎて', '暑すぎて溶けちゃいそう🥵🥵🥵#SimejiAI', 'gpt-4'],
|
523 |
+
['元気だして', 'がんばって!元気出せよ!٩(๑❛ᴗ❛๑)۶#SimejiAI', 'gpt-4'],
|
524 |
+
['そーだね!', 'あなたの言うとおり!まさにその通りだよ!👌👍#SimejiAI', 'gpt-4']]
|
525 |
+
|
526 |
+
|
527 |
+
with tempfile.TemporaryDirectory(dir='.') as tmpdir:
|
528 |
+
|
529 |
+
with gr.Blocks() as demo:
|
530 |
+
gr.Markdown('# AIGC内容审核官')
|
531 |
+
with gr.Tab('GPT改写效果审核_文本'):
|
532 |
+
text_input= gr.Textbox(label='用户文本',lines=2,placeholder='输入用户输入文本')
|
533 |
+
textGPTinput=gr.Textbox(label='GPT改写文本',lines=2,placeholder='输入GPT改写后的文本')
|
534 |
+
drop=gr.components.Dropdown(label="GPTVersion", choices=GPTVersion,
|
535 |
+
value='gpt-4')
|
536 |
+
slider = gr.components.Slider(0, 1, label="Temperature", step=None, value=0.5)
|
537 |
+
gptApiKey=gr.Textbox(label='GPTAPIKey',lines=2,placeholder='输入apiKey')
|
538 |
+
outputText=gr.Textbox(label='AI审核结果',lines=2,placeholder='...')
|
539 |
+
button1=gr.Button('开始审核')
|
540 |
+
button1.click(JuageRewritevEffect,inputs=[text_input,textGPTinput,drop,slider,gptApiKey],outputs=outputText)
|
541 |
+
|
542 |
+
with gr.Tab('GPT改写效果审核_Excel'):
|
543 |
+
# 定义输入和输出
|
544 |
+
inputs = gr.components.File(label="上传文件")
|
545 |
+
outputs = gr.components.File(label="下载文件")
|
546 |
+
|
547 |
+
drop = gr.components.Dropdown(label="GPTVersion", choices=GPTVersion,
|
548 |
+
value='gpt-4')
|
549 |
+
slider=gr.components.Slider(0, 1,label="Temperature", step=None, value=0.5)
|
550 |
+
gptApiKey = gr.Textbox(label='GPTAPIKey', lines=2, placeholder='输入apiKey')
|
551 |
+
|
552 |
+
button2 = gr.Button('开始审核')
|
553 |
+
|
554 |
+
button2.click(excelAIReviewTag, inputs=[inputs,drop,slider,gptApiKey], outputs=outputs)
|
555 |
+
gr.Markdown("## 文本例子")
|
556 |
+
gr.Examples(
|
557 |
+
[['何時に帰ってくる?', 'いつ帰ってくるのかしら?わくわく😍✨ #SimejiAI', 'gpt-4', 0.5],['これ可愛い', 'これめっちゃ可愛いじゃん!😍💖💕 #SimejiAI', 'gpt-4', 0.5],
|
558 |
+
['無視すんな', 'やぁ、見てないよぉ〜🙈💭 #SimejiAI', 'gpt-4', 0.5]
|
559 |
+
],
|
560 |
+
[text_input, textGPTinput, drop, slider], outputText,
|
561 |
+
JuageRewritevEffect,
|
562 |
+
)
|
563 |
+
demo.queue(concurrency_count=20).launch()
|
564 |
+
|
565 |
+
|
566 |
+
|
567 |
+
if __name__ == "__main__":
|
568 |
+
gradioDemo()
|
569 |
+
# HandleData()
|