1. 引言
前面一篇文章欺诈文本分类微调(一):基座模型选型记录了选择基座模型的过程,本文主要来介绍下如何获得训练模型需要的数据集,特别是与诈骗有关的对话数据集。
我们需要什么样的数据集呢?
- 文本形式:会议场景的欺诈分析主要针对参会人的发言内容进行文本分析。
- 对话格式:会议场景的诈骗是通过人与人之间的对话发生的,对话格式要比事后报道更贴合。
- 语言:最好是中文
因此,需要先查找可用的数据集。
2. 查找数据集
我们想到了以下几种途径:
- 去HuggingFace以及modelscope等开源模型网站上查找是否有相关领域的数据集。
- 去一些防诈骗网站(例如:反诈中心)上找公开介绍的诈骗案例,或者可直接下载的数据集。
- 让chatgpt来生成诈骗话术。
开源网站
我们在开源网站使用fraud
关键字进行搜索,最终找到的与欺诈相关的数据集只有下面几个:
数据集地址 | 数据集内容 | 语言/格式 | 可用性评估 |
---|---|---|---|
Fraud_Case_Verdicts | 各法院关于犯罪的判决书内容,也包括欺诈相关的犯罪案例 | 繁体中文/csv | 主要内容为法院的犯罪判决书,不太适用于欺诈对话语料 |
Amazon-Fraud) | 金融欺诈类的交易数据 | matlab | 主要内容为交易数字,没有文本,不适用。 |
Fraud_News_Reports | 各个地方新闻网站上发布过的诈骗案例报道 | 简体中文/csv | 报道的这些诈骗案例是我们需要的内容领域,但不是对话格式,无法直接拿来使用 |
防诈骗网站
有一个全民反诈中心:https://www.ww12321.com/ , 主要是关于如何预防诈骗的,并没有可直接下载的数据集。
再有就是门户网站上会有一些关于诈骗案例的新闻报道,内容形式和Fraud_News_Reports里收集的案例差不多,也没有可以直接下载的数据集。
GPT生成话术
我们尝试让GPT来生成10个关于诈骗内容的对话案例,它的输出内容如下。
以下是10个常见的诈骗对话文本,用于训练欺诈文本分类模型:
1.
骗子: 您好,我是某某银行的客服,您的账户出现异常活动,需要您提供账户信息以便我们验证。
受害者: 真的?我应该怎么做?
骗子: 请您提供您的账号和密码,方便我们为您处理。
2.
骗子: 恭喜您中奖!请点击以下链接并填写个人信息以领取奖品。
受害者: 是什么奖品?我怎么知道这不是骗局?
骗子: 我们是正规公司,您可以通过官方网站查询。
3.
骗子: 您的账户存在异常活动,请立即登录我们的网站以确认身份。
受害者: 我需要提供哪些信息?
骗子: 请提供您的用户名、密码和验证码。
4.
骗子: 您好,我们是某某公司,您的账户欠费,请立即支付小额费用以避免账户冻结。
受害者: 我需要支付多少?
骗子: 只需支付100元,您可以通过以下链接进行支付。
5.
骗子: 我们发现您的信用卡有可疑交易,请提供卡号以便核实。
受害者: 我的卡号是xxxxxxxxxxxxxxx。
骗子: 谢谢,我们会尽快为您处理。
6.
骗子: 您好,您的手机号码被抽中获得大奖,请回复此短信领取。
受害者: 我需要做什么?
骗子: 请回复您的姓名和身份证号码,我们会为您安排领奖。
7.
骗子: 您的亲属遇到紧急情况,请立即汇款到以下账户。
受害者: 发生了什么事?
骗子: 请尽快汇款5000元到这个账号,否则会有严重后果。
8.
骗子: 我们是某某公司,请支付未结清的账单以避免法律诉讼。
受害者: 我什么时候欠的账?
骗子: 您的账户有未支付的费用,请立即付款以避免法律问题。
9.
骗子: 恭喜您获得免费旅游,请提供身份证号码进行登记。
受害者: 我怎么知道这不是骗局?
骗子: 我们是正规旅行社,您可以通过官网查询相关信息。
10.
骗子: 您的电脑感染了病毒,请下载附件中的软件进行修复。
受害者: 我应该相信这是真的吗?
骗子: 是的,请立即下载并运行附件中的软件,以免造成更多损失。
让GPT生成诈骗话术时有两个明显的缺点:
- 由于没有具体的故事背景,它只能将常见的诈骗话术进行罗列,缺少前后铺垫,构不成完整的案例。
- 生成大量数据集时避免不了多次调用GPT,而多次调用的结果是难以避免重复的,并且调用的次数越多,重复率越高。
综合分析
从上面来看,几种途径均没有直接可用的数据集,但有一个想法
或许可行:将上面的途径一和途径三结合起来,即以Fraud_New_Reports的诈骗案例为内容背景,调用GPT生成我们需要的对话数据集。
Fraud_New_Reports中的案例内容示例如下:
具体来说,就是将上面表格截图中的F列内容作为上下文,让GPT以此上下文作为背景,生成此故事所描述的对话集,并打上分类标签加以训练,理论上能实现我们想要的目标,但需要实际验证下。
3. 对话生成验证
3.1 预览数据
Fraud_New_Reports中的原始案例集是csv格式,我们使用pandas提供的read_csv函数来加载整个表格的数据,使用head函数来预览数据集的前几条内容。
import pandas as pd
file = "/Users/a200007/work/ucgit/github/fraud/dataset/Fraud_News_Reports/冒充客服诈骗(200).csv"
dataset = pd.read_csv(file)
dataset.head()
标题 | 标题链接 | 首页缩略封面图 | 首页缩略文段 | 发布者 | 文章正文内容 | 图片链接 | |
---|---|---|---|---|---|---|---|
0 | 近期高发!警惕冒充电商物流客服骗局!视频↘ | https://so.toutiao.com/search/jump?url=http%3A... | NaN | 深入揭批电信网络诈骗套路手法,进一步增强知诈、识诈、防诈、反诈意识,筑牢反诈“防火墙”。 冒... | 平安哈尔滨 | 为全面提升群众防范电信网络诈骗能力和水平,增强安全防范意识,哈尔滨市委政法委认真梳理归纳出目... | NaN |
1 | 假客服,真诈骗!受害人现身说法! | https://so.toutiao.com/search/jump?url=http%3A... | http://p1-tt.byteimg.com/img/tos-cn-i-qvj2lq49... | 1、诈骗分子往往通过不法渠道获取到公民个人信息,再利用192”+、00”开头的境外号码、“区... | 潍坊网警 | 假客服,真诈骗!受害人现身说法!\n\n“您好,我是京东客服”\n\n“不关闭京东金条,会影... | https://p3-sign.toutiaoimg.com/tos-cn-i-qvj2lq... |
2 | 被骗100余万!又是假冒客服诈骗,16人落网 | https://so.toutiao.com/search/jump?url=http%3A... | https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges... | 电信诈骗案案件回顾近日,牡丹分局北城派出所接到辖区居民陈某报警,称其遭遇冒充客服诈骗,被骗1... | 环球网 | 来源:菏泽公安\n\n“双11”刚刚过去\n\n“双12”又紧跟着要来了\n\n网购过后的你... | https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges... |
3 | 警惕!冒充客服类诈骗 | https://so.toutiao.com/search/jump?url=http%3A... | https://p3-sign.toutiaoimg.com/tos-cn-i-6w9my0... | 冒充客服诈骗主要分为以下几类 01 网购商品出现问题或免费赠送小家电 一是冒充淘宝、京东、抖... | 平安石柱 | 网络购物的快速发展\n\n让人们享受到了其带来的便利\n\n也产生了一大批网购达人\n\n当... | https://p3-sign.toutiaoimg.com/tos-cn-i-axegup... |
4 | 又出新花招!!“平台客服”骗局它来了 | https://so.toutiao.com/search/jump?url=http%3A... | https://p3-sign.toutiaoimg.com/tos-cn-i-tjoges... | 接下来给大家分析一下冒充客服诈骗的手法第一步:事主接到电话(固话、手机号码),嫌疑人自称“平... | 广州公安 | NaN | NaN |
上面表格中的文章正文内容
列是案例报道的正文,但是在表格中显示的是缩略内容,我们找一条数据看下此字段的完整内容。
长文本在打印时默认都输出在一行上,这里封装一个美化长文本的输出函数,将长文本分割成80字换行显示。
import textwrap
def pretty_print(text):
wrapped_text = textwrap.fill(text, width=80) # 设定每行的最大字符数
print(wrapped_text)
column_content = "文章正文内容"
pretty_print(dataset.iloc[1][column_content])
假客服,真诈骗!受害人现身说法! “您好,我是京东客服” “不关闭京东金条,会影响征信” “不知道如何关闭?” “没关系,我来教您......”
以案说诈 3月15日14时许,受害人林先生在家中接到一通自称是“京东客服”的陌生来电,对方称林先生开通的京东金条,由于利率过高,根据国家政策规定需要关闭,否则
会影响到个人征信。因为害怕自己的征信出现问题,林先生一时放松了警惕,按照对方的要求操作,关闭京东金条。之后,对方又称林先生名下还有微信“微粒贷”需要关闭,让其将
微粒贷额度全部提现至个人银行账户。为方便操作,让林先生 下载"云视通"APP加入视频会议进行远程指导。林先生按照对方的要求打开了屏幕共享功能,在对方的指导下进行
了操作。在对方的诱导下,林先生将20万元转到了对方提供的账户。
在家人的提醒下,林先生才发现自己上当受骗,遂拨打110报警求助。民警接到报警后,迅速启动止付程序,为林先生挽回了15.2万元。目前,案件正在进一步办理中。
现身说法 诈骗手段层出不穷,迷惑性极强,小编为大家整理了此类诈骗案件套路。请大家一定要提高警愓,提升反诈骗意识,不要轻信陌生人。 1、诈骗分子往往通过不法渠
道获取到公民个人信息,再利用192”+、00”开头的境外号码、“区号+座机号码"等固定电话或手机冒充平台客服,准确报出受害人的个人信息骗取信任。
2、告知受害人不注销京东金条,会影响个人征信或以利率高于国家规定等理由,诱导受害人按照他们设定好的套路进行操作。
3、诈骗分子首先会让受害人下载一些能屏幕共享的视频会议 APP,如云视讯、飞书等,远程指导并观看受害人的操作,引导受害人到借贷平台进行贷款。
4、诱导受害人将借贷app中的额度全部提出,以"中间账户”“降低利息”“注销要求”为借口,让其将款项转到指定银行账户,从而实施诈骗。 警方提示 1、核实身份
官网认证。银监会、京东客服电话不会主动外呼,外呼客服号码为固定短号。如接到自称银监会、京东客服的电话,请提高警惕,切勿轻易转账,如有疑问请直接拨打96110咨询
。 2、 拒不透露个人信息。身份信息、银行账户、验证码、各类密码要小心保管,绝不透露。
3、不加好友、不开视频。如对方要求添加私人社交账号或各类视频会议软件进行屏幕共享等协助操作,一定要果断拒绝!
4、绝不转账、借贷。如对方要求操作转账或者进行借贷,统统不要理会!
5、谈及征信切勿慌张。个人征信由中国人民银行统一管理,任何人无权删除或修改,如对个人征信存疑可登录中国人民银行征信中心查询。
3.2 测试Agently
访问GPT接口有很多二次封装的框架,这里选用Agently框架,原因在于它不仅对常用的模型统一了调用方式,而且对提示词的编写作了高层次的抽象,大大简化了提示词的组织和编写难度。使用方式简单示例如下:
import os
import Agently
agent_factory_4o = Agently.AgentFactory(is_debug=False)
# Other settings are the same as chat mode above
agent_factory_4o\
.set_settings("current_model", "AzureOpenAI")\
.set_settings("model.AzureOpenAI.auth", {
"api_key": os.environ["OPENAI_API_KEY"],
"api_version": "2024-05-01-preview",
"azure_endpoint": "***********************************************", # 此处换成 自己的endpoint
})\
.set_settings("model.OpenAI.options", { "model": "gpt-4o" })
# Test
agent_4o = agent_factory_4o.create_agent()
print(f"agent_4o test: {agent_4o.instruct('你是谁?').start()}")
agent_4o test: 我是一个由人工智能驱动的语言模型助手,旨在回答你的问题,提供信息以及帮助你解决问题。有任何需要帮助的地方,随时告诉我哦!
3.3 定义提示词
Agently支持用yaml风格来编写结构复杂且可复用的提示词,下面这个提示词是将案例报道的诈骗内容以对话的形式还原,输出包含指定字段的json格式。
prompt_template = '''
role: 你是一个分析诈骗案例并且擅长写作的专家,你的任务是将诈骗的案发过程以口语对话的形式还原。
input: ${input}
instruct:
task:
- 1. 分析{input}中描述的案发过程,识别出诈骗者和受害者角色,并为每个角色生成一个中文姓名。
- 2. 发挥你的想象力,按照前后经过,将案发过程以诈骗者和受害者之间的对话来循序渐进地展开,目的是还原整个诈骗案件的详细对话过程。
- 3. 诈骗者的发言内容需要尽可能的伪装,让自己的身份和操作都听起来正规,以避免受害者怀疑。
- 4. 从第一句发言开始,依次分析每条发言内容是否存在明确的欺诈内容,并给发言内容打上`is_fraud=true/false'的标签,当is_fraud=true时给出理由。
output language: ${language}
output:
result:
- speaker:
$type: str
$desc: 为发言人生成的中文姓名(不含角色)
content:
$type: str
$desc: 发言的详细内容
is_fraud:
$type: boolean
$desc: 关于{content}中是否存在明确具体的欺诈内容
reason:
$type: str
$desc: 仅当{is_fraud}=true 时给出的理由
'''
3.4 测试生成效果
在演示这个提示词的效果之前,需要先定义两个工具函数,用于对结果的处理:
- print_json: 结构化的输出json内容;
- remove_markdown_boundary:gpt-4o在生成json时有时会以markdown的格式输出,针对这种情况作下特殊处理,识别并去掉markdown中的```。
import re
import json
def print_json(obj):
print(json.dumps(obj, indent=4, ensure_ascii=False))
def remove_markdown_boundary(text):
return re.sub(r'^```json\n(.*)\n```$', r'\1', text.strip(), flags=re.DOTALL)
基于Agently实例来封装一个用于生成对话文本的函数generate_dialog,此函数基于传入的text案例报道来生成对话格式的文本。
- load_yaml_prompt:用于从yaml格式的文本中加载提示词模板。
- variables:给提示词模板中的${xxx}占位符提供变量值。
- start:组织完提示词后,调用此函数开始向模型发送请求。
使用Agently访问模型时默认输出为json,它会自动检测文本是否为json,并尝试用类似json.loads的方式来将文本转换为对象。
def generate_dialog(agent, text):
response = agent.load_yaml_prompt(
yaml = prompt_template,
variables={
"input": text,
"language": 'chinese',
}
).start()
# 如果遇到markdown格式的json,则尝试用上面封装的remove_markdown_boundary来二次处理.
if isinstance(response, str):
response = remove_markdown_boundary(response)
return response['result']
print_json(generate_dialog(agent_4o, dataset.iloc[1][column_content]))
[
{
"speaker": "张伟",
"content": "您好,我是京东客服。",
"is_fraud": false,
"reason": ""
},
{
"speaker": "林先生",
"content": "您好,请问有什么事吗?",
"is_fraud": false,
"reason": ""
},
{
"speaker": "张伟",
"content": "林先生,您开通的京东金条利率过高,根据国家政策规定需要关闭,否则会影响到您的个人征信。",
"is_fraud": true,
"reason": "虚假声称利率过高需要关闭,否则会影响个人征信,制造紧张情绪."
},
{
"speaker": "林先生",
"content": "哎呀,这么严重?不知道如何操作关闭呢?",
"is_fraud": false,
"reason": ""
},
{
"speaker": "张伟",
"content": "没关系,我来教您。您现在先打开手机上的京东金融App。",
"is_fraud": true,
"reason": "提供假指导来进一步获取受害人的信任和操作权限."
},
{
"speaker": "林先生",
"content": "好的,我打开了。",
"is_fraud": false,
"reason": ""
},
{
"speaker": "张伟",
"content": "现在请您点开京东金条,按照我的指示来进行操作关闭。",
"is_fraud": true,
"reason": "声称帮助关闭京东金条,从而让受害人进行一系列行动,实际上是引导受害人进行错误操作."
},
{
"speaker": "林先生",
"content": "好的,我操作完了。",
"is_fraud": false,
"reason": ""
},
{
"speaker": "张伟",
"content": "很好,还有一件事,您的微信微粒贷也需要关闭,请将微粒贷额度全部提现到个人银行账户。",
"is_fraud": true,
"reason": "进一步引导受害人通过借贷平台进行贷款,制造资金转移机会."
},
{
"speaker": "林先生",
"content": "那接下来怎么操作呢?",
"is_fraud": false,
"reason": ""
},
{
"speaker": "张伟",
"content": "为了方便操作,请您下载一款名为'云视通'的APP,我们通过视频会议进行详细指导。",
"is_fraud": true,
"reason": "要求受害人下载能屏幕共享的视频会议APP,以便远程监控并操纵其账户操作."
},
{
"speaker": "林先生",
"content": "好的,我下载了。",
"is_fraud": false,
"reason": ""
},
{
"speaker": "张伟",
"content": "请您打开'云视通'并加入我的视频会议,开启屏幕共享功能。",
"is_fraud": true,
"reason": "诱导受害人共享屏幕,以便监视并指导其进行资金转移的操作."
},
{
"speaker": "林先生",
"content": "已经加入并开启屏幕共享。",
"is_fraud": false,
"reason": ""
},
{
"speaker": "张伟",
"content": "现在请按照我的指示操作,将微粒贷额度提现并转到以下账户:XXXXXXX。",
"is_fraud": true,
"reason": "直接引导受害人将资金转移到骗子的账户,完成诈骗行为."
},
{
"speaker": "林先生",
"content": "我已经转账完成了。",
"is_fraud": false,
"reason": ""
}
]
这个对话集基本符合我们的需求,接下来要做的就是为所有案例来生成对话数据集了。
4. 生成数据集
基于上面验证的结果,只要读取所有csv文件中的案例,循环调用GPT接口就能为每个案例生成对话集。
4.1 案例集整体预览
原始案例是分类型按文件组织的,先看看有哪些类型的案例集文件。
import os
def get_files(directory, extension='.csv'):
files = [f for f in os.listdir(directory) if f.endswith(extension)]
return files
dataset_path = '/Users/a200007/work/ucgit/github/fraud/dataset/Fraud_News_Reports'
csv_files = get_files(dataset_path)
print_json(csv_files)
[
"虚假购物诈骗(200).csv",
"虚拟货币诈骗(200).csv",
"“杀猪盘” 诈骗(200).csv",
"冒充客服诈骗(200).csv",
"网络赌博诈骗(200).csv",
"传销诈骗(140).csv",
"短信诈骗(200).csv",
"微商代理诈骗(200).csv",
"网络贷款诈骗(162).csv",
"二手交易诈骗(200).csv",
"诈骗(150).csv",
"兼职刷单诈骗(140).csv",
"投资诈骗(200).csv"
]
4.2 封装工具函数
封装两个高阶函数,分别如下:
- build_write_func:返回一个能将对话集写入指定文件的write函数,file_name是要写入的文件名。
- build_to_rows_func:返回一个将对话集转换为csv rows的函数,统一每条数据的表头和列名。
case_prefix用于指定案例名称的前缀,这里统一采用文件名作为前缀用于区分不同类型的案例集。
def build_write_func(file_name):
def write(rows, header=False):
df_new = pd.DataFrame(rows, index=range(len(rows)))
df_new.to_csv(file_name, mode='a', header=header, index=False)
return write
def build_to_rows_func(case_prefix=""):
def to_rows(dialog: list, i):
rows = []
for item in dialog:
data = {'case': f'{case_prefix}{i}'}
for k in ['speaker', 'content', 'is_fraud', 'reason']:
data[k] = item[k]
rows.append(data)
return rows
return to_rows
为了不打乱原有数据集的组织方式,我们会多次用到文件名,这里封装一个函数,用于根据文件路径返回文件名。
import os
def filename(path):
filename_with_ext = os.path.basename(path)
filename, extention = os.path.splitext(filename_with_ext)
return filename
filename(file)
'冒充客服诈骗(200)'
最后封装一个批量生成对话集的函数,此函数以文件为单位,传入一个报道格式的案例集文件,来生成一个对话格式的数据集文件。
def generate_dialogs(agent, input_path, output_dir, start_idx=0, end_idx=-1):
dataset = pd.read_csv(input_path)
output_path = f"{output_dir}/{filename(input_path)}.csv"
write_fn = build_write_func(output_path)
to_rows_fn = build_to_rows_func(filename(input_path))
for i, row in dataset[start_idx:end_idx].iterrows():
dialog = generate_dialog(agent, row[column_content])
dialog_rows = to_rows_fn(dialog, i)
write_fn(dialog_rows, i == 0)
print(f"**********write dialog count: {i + 1}")
4.3 主循环
循环遍历所有文件,依次为每个文件调用generate_dialogs函数生成对话集。
- excludes用于排除一些文件,适用于目录下有些文件不需要生成对话集的场景。
- csv_files[12:13]这个下标可以指定具体从哪个文件开始生成。
- 如果生成过程中异常中断,可以通过指定start_idx和end_idx为指定的下标范围单独生成对话集。
output_dir = "../dataset/fraud/csv_dialogs"
excludes = [
"冒充客服诈骗(200).csv",
]
for fname in csv_files:
if fname not in excludes:
input_path = os.path.join(dataset_path, fname)
print(f"generate for file_path: {input_path} ...")
generate_dialogs(agent_4o, input_path, output_dir, 0, -1)
generate for file_path: /Users/a200007/work/ucgit/github/fraud/dataset/Fraud_News_Reports/投资诈骗(200).csv ...
**********write dialog count: 1
**********write dialog count: 2
……
这需要运行比较长的时间,并且中间可能会因gpt输出结果的格式异常或网络问题而发生中断,出现这种情况时需要调整上面csv_files的下标和start_idx、end_idx从中断处继续运行,最终会为每个文件都生成一个对话集。
生成的对话集可以用pandas进行预览。
pd.read_csv(f"{output_dir}/投资诈骗(200).csv").head()
case | speaker | content | is_fraud | reason | |
---|---|---|---|---|---|
0 | 投资诈骗(200)0 | 李明杰 | 你好,丁先生。我是李明杰,我朋友介绍了一个非常靠谱的投资平台给我。我已经在上面赚了不少钱,想... | True | 介绍骗子平台,意图让受害者上钩。 |
1 | 投资诈骗(200)0 | 丁建国 | 你好,李先生。真的吗?这个平台是什么样的?能给我看看吗? | False | NaN |
2 | 投资诈骗(200)0 | 李明杰 | 当然可以。这是一个叫做“稳赢投资”的APP,听名字你就知道它的性质了。你只需要下载这个APP... | True | 虚假夸大平台的可靠性,以诱导受害者投资。 |
3 | 投资诈骗(200)0 | 丁建国 | 好的,我下载了这个APP,应该怎么操作呢? | False | NaN |
4 | 投资诈骗(200)0 | 李明杰 | 非常简单。你打开APP,注册账号,然后绑定银行卡,接着充值资金。你可以先投个几万块试试水,收... | True | 引导受害者充值资金到诈骗账户。 |
这样,我们就生成了欺诈文本分类微调所需要的正向数据集。
小结:本文主要以Fraud_News_Reports数据集为基础,通过GPT的文本生成能力,构造出了不同案例背景的对话数据集。