首页 > 其他分享 >【基于星火大模型的群聊对话分角色要素提取BaseLine学习笔记】

【基于星火大模型的群聊对话分角色要素提取BaseLine学习笔记】

时间:2024-07-02 20:30:33浏览次数:1  
标签:群聊 BaseLine 信息 json 客户 星火 str 预算 string

@

目录

项目背景

在数字化时代,企业积累了大量对话数据,这些数据不仅是交流记录,还隐藏着宝贵的信息。群聊对话分角色要素提取是企业营销和服务的重要策略,通过分析这些数据,企业可以更好地理解客户需求,提供个性化服务,提升客户满意度和商业价值。

项目任务

从给定的<客服>与<客户>的群聊对话中,提取出指定的字段信息,具体待提取的字段信息见下文。

我的思路

Q:题解析当中能否提一提这个赛题是一个经典NLP任务,以往的处理方案和用大模型处理各自的优势点是什么?
A:其实看数据的话也不经典,知识数据的实体抽取任务以前的SOTA方案是使用UIE。(https://www.cnblogs.com/ting1/p/17637546.html)往往能拿到高分,但是和大模型的本质思路类似。还有这个赛题的数据量之大,可能只有大模型一条路了。在大模型出来之前百度在抽取任务国际领先的,现在大模型出来对抽取任务有降维打击的味道了。
从赛题本身要求看,只支持api与微调,可以说是半开放命题。所以只选用了大模型方法解决这个赛题咯。

Baseline 详解

这里的prompt编写规则可以进行这样的理解:
任务目标——抽取数据定义——抽取内容引入——抽取规则强调
以这样的prompt模版配合强大的星火3.5模型,可以完成我们的抽取任务。

# prompt 设计
PROMPT_EXTRACT = """
你将获得一段群聊对话记录。你的任务是根据给定的表单格式从对话记录中提取结构化信息。在提取信息时,请确保它与类型信息完全匹配,不要添加任何没有出现在下面模式中的属性。

表单格式如下:
info: Array<Dict(
    "基本信息-姓名": string | "",  // 客户的姓名。
    "基本信息-手机号码": string | "",  // 客户的手机号码。
    "基本信息-邮箱": string | "",  // 客户的电子邮箱地址。
    "基本信息-地区": string | "",  // 客户所在的地区或城市。
    "基本信息-详细地址": string | "",  // 客户的详细地址。
    "基本信息-性别": string | "",  // 客户的性别。
    "基本信息-年龄": string | "",  // 客户的年龄。
    "基本信息-生日": string | "",  // 客户的生日。
    "咨询类型": string[] | [],  // 客户的咨询类型,如询价、答疑等。
    "意向产品": string[] | [],  // 客户感兴趣的产品。
    "购买异议点": string[] | [],  // 客户在购买过程中提出的异议或问题。
    "客户预算-预算是否充足": string | "",  // 客户的预算是否充足。示例:充足, 不充足
    "客户预算-总体预算金额": string | "",  // 客户的总体预算金额。
    "客户预算-预算明细": string | "",  // 客户预算的具体明细。
    "竞品信息": string | "",  // 竞争对手的信息。
    "客户是否有意向": string | "",  // 客户是否有购买意向。示例:有意向, 无意向
    "客户是否有卡点": string | "",  // 客户在购买过程中是否遇到阻碍或卡点。示例:有卡点, 无卡点
    "客户购买阶段": string | "",  // 客户当前的购买阶段,如合同中、方案交流等。
    "下一步跟进计划-参与人": string[] | [],  // 下一步跟进计划中涉及的人员(客服人员)。
    "下一步跟进计划-时间点": string | "",  // 下一步跟进的时间点。
    "下一步跟进计划-具体事项": string | ""  // 下一步需要进行的具体事项。
)>

请分析以下群聊对话记录,并根据上述格式提取信息:

**对话记录:**

{content}


请将提取的信息以JSON格式输出。
不要添加任何澄清信息。
输出必须遵循上面的模式。
不要添加任何没有出现在模式中的附加字段。
不要随意删除字段。

**输出:**

[{{
"基本信息-姓名": "姓名",
"基本信息-手机号码": "手机号码",
"基本信息-邮箱": "邮箱",
"基本信息-地区": "地区",
"基本信息-详细地址": "详细地址",
"基本信息-性别": "性别",
"基本信息-年龄": "年龄",
"基本信息-生日": "生日",
"咨询类型": ["咨询类型"],
"意向产品": ["意向产品"],
"购买异议点": ["购买异议点"],
"客户预算-预算是否充足": "充足或不充足",
"客户预算-总体预算金额": "总体预算金额",
"客户预算-预算明细": "预算明细",
"竞品信息": "竞品信息",
"客户是否有意向": "有意向或无意向",
"客户是否有卡点": "有卡点或无卡点",
"客户购买阶段": "购买阶段",
"下一步跟进计划-参与人": ["跟进计划参与人"],
"下一步跟进计划-时间点": "跟进计划时间点",
"下一步跟进计划-具体事项": "跟进计划具体事项"
}}, ...]

"""

数据抽取

使用prompt进行调试发现以下几个问题:
1. 大模型总是不能直接输出python直接可读取的json格式,如:

[
    {
        "基本信息-姓名": "张三",
        "基本信息-手机号码": "12345678901",
        "基本信息-邮箱": "[email protected]",
        "基本信息-地区": "北京市",
        "基本信息-详细地址": "朝阳区某街道",
        "基本信息-性别": "男",
        "基本信息-年龄": "30",
        "基本信息-生日": "1990-01-01",
        "咨询类型": ["询价"],
        "意向产品": ["产品A"],
        "购买异议点": ["价格高"],
        "客户预算-预算是否充足": "充足",
        "客户预算-总体预算金额": "10000",
        "客户预算-预算明细": "详细预算内容",
        "竞品信息": "竞争对手B",
        "客户是否有意向": "有意向",
        "客户是否有卡点": "无卡点",
        "客户购买阶段": "合同中",
        "下一步跟进计划-参与人": ["客服A"],
        "下一步跟进计划-时间点": "2024-07-01",
        "下一步跟进计划-具体事项": "沟通具体事项"
    }
]
  故使用函数convert_all_json_in_text_to_dict对json数据进行提取

def convert_all_json_in_text_to_dict(text):
"""提取LLM输出文本中的json字符串"""
dicts, stack = [], []
for i in range(len(text)):
if text[i] == '{':
stack.append(i)
elif text[i] == '}':
begin = stack.pop()
if not stack:
dicts.append(json.loads(text[begin:i+1]))
return dicts
2. 大模型偶尔会出现缺少字段的情况,故使用check_and_complete_json_format函数对大模型抽取的结果进行字段格式的检查以及缺少的字段进行补全。
import json

class JsonFormatError(Exception):
def init(self, message):
self.message = message
super().init(self.message)

def check_and_complete_json_format(data):
required_keys = {
"基本信息-姓名": str,
"基本信息-手机号码": str,
"基本信息-邮箱": str,
"基本信息-地区": str,
"基本信息-详细地址": str,
"基本信息-性别": str,
"基本信息-年龄": str,
"基本信息-生日": str,
"咨询类型": list,
"意向产品": list,
"购买异议点": list,
"客户预算-预算是否充足": str,
"客户预算-总体预算金额": str,
"客户预算-预算明细": str,
"竞品信息": str,
"客户是否有意向": str,
"客户是否有卡点": str,
"客户购买阶段": str,
"下一步跟进计划-参与人": list,
"下一步跟进计划-时间点": str,
"下一步跟进计划-具体事项": str
}

if not isinstance(data, list):
    raise JsonFormatError("Data is not a list")

for item in data:
    if not isinstance(item, dict):
        raise JsonFormatError("Item is not a dictionary")
    for key, value_type in required_keys.items():
        if key not in item:
            item[key] = [] if value_type == list else ""
        if not isinstance(item[key], value_type):
            raise JsonFormatError(f"Key '{key}' is not of type {value_type.__name__}")
        if value_type == list and not all(isinstance(i, str) for i in item[key]):
            raise JsonFormatError(f"Key '{key}' does not contain all strings in the list")

return data

完整代码

from sparkai.llm.llm import ChatSparkLLM, ChunkPrintHandler
from sparkai.core.messages import ChatMessage
import json
from tqdm import tqdm

星火认知大模型Spark3.5 Max的URL值,其他版本大模型URL值请前往文档(https://www.xfyun.cn/doc/spark/Web.html)查看

SPARKAI_URL = 'wss://spark-api.xf-yun.com/v3.5/chat'

星火认知大模型调用秘钥信息,请前往讯飞开放平台控制台(https://console.xfyun.cn/services/bm35)查看

SPARKAI_APP_ID = ''
SPARKAI_API_SECRET = ''
SPARKAI_API_KEY = ''

星火认知大模型Spark3.5 Max的domain值,其他版本大模型domain值请前往文档(https://www.xfyun.cn/doc/spark/Web.html)查看

SPARKAI_DOMAIN = 'generalv3.5'

prompt 设计

PROMPT_EXTRACT = """
你将获得一段群聊对话记录。你的任务是根据给定的表单格式从对话记录中提取结构化信息。在提取信息时,请确保它与类型信息完全匹配,不要添加任何没有出现在下面模式中的属性。

表单格式如下:
info: Array<Dict(
"基本信息-姓名": string | "", // 客户的姓名。
"基本信息-手机号码": string | "", // 客户的手机号码。
"基本信息-邮箱": string | "", // 客户的电子邮箱地址。
"基本信息-地区": string | "", // 客户所在的地区或城市。
"基本信息-详细地址": string | "", // 客户的详细地址。
"基本信息-性别": string | "", // 客户的性别。
"基本信息-年龄": string | "", // 客户的年龄。
"基本信息-生日": string | "", // 客户的生日。
"咨询类型": string[] | [], // 客户的咨询类型,如询价、答疑等。
"意向产品": string[] | [], // 客户感兴趣的产品。
"购买异议点": string[] | [], // 客户在购买过程中提出的异议或问题。
"客户预算-预算是否充足": string | "", // 客户的预算是否充足。示例:充足, 不充足
"客户预算-总体预算金额": string | "", // 客户的总体预算金额。
"客户预算-预算明细": string | "", // 客户预算的具体明细。
"竞品信息": string | "", // 竞争对手的信息。
"客户是否有意向": string | "", // 客户是否有购买意向。示例:有意向, 无意向
"客户是否有卡点": string | "", // 客户在购买过程中是否遇到阻碍或卡点。示例:有卡点, 无卡点
"客户购买阶段": string | "", // 客户当前的购买阶段,如合同中、方案交流等。
"下一步跟进计划-参与人": string[] | [], // 下一步跟进计划中涉及的人员(客服人员)。
"下一步跟进计划-时间点": string | "", // 下一步跟进的时间点。
"下一步跟进计划-具体事项": string | "" // 下一步需要进行的具体事项。
)>

请分析以下群聊对话记录,并根据上述格式提取信息:

对话记录:

{content}

请将提取的信息以JSON格式输出。
不要添加任何澄清信息。
输出必须遵循上面的模式。
不要添加任何没有出现在模式中的附加字段。
不要随意删除字段。

输出:

[{{
    "基本信息-姓名": "姓名",
    "基本信息-手机号码": "手机号码",
    "基本信息-邮箱": "邮箱",
    "基本信息-地区": "地区",
    "基本信息-详细地址": "详细地址",
    "基本信息-性别": "性别",
    "基本信息-年龄": "年龄",
    "基本信息-生日": "生日",
    "咨询类型": ["咨询类型"],
    "意向产品": ["意向产品"],
    "购买异议点": ["购买异议点"],
    "客户预算-预算是否充足": "充足或不充足",
    "客户预算-总体预算金额": "总体预算金额",
    "客户预算-预算明细": "预算明细",
    "竞品信息": "竞品信息",
    "客户是否有意向": "有意向或无意向",
    "客户是否有卡点": "有卡点或无卡点",
    "客户购买阶段": "购买阶段",
    "下一步跟进计划-参与人": ["跟进计划参与人"],
    "下一步跟进计划-时间点": "跟进计划时间点",
    "下一步跟进计划-具体事项": "跟进计划具体事项"
}}, ...]

"""

def read_json(json_file_path):
"""读取json文件"""
with open(json_file_path, 'r') as f:
data = json.load(f)
return data

def write_json(json_file_path, data):
"""写入json文件"""
with open(json_file_path, 'w') as f:
json.dump(data, f, ensure_ascii=False, indent=4)

def get_completions(text):
messages = [ChatMessage(
role="user",
content=text
)]
spark = ChatSparkLLM(
spark_api_url=SPARKAI_URL,
spark_app_id=SPARKAI_APP_ID,
spark_api_key=SPARKAI_API_KEY,
spark_api_secret=SPARKAI_API_SECRET,
spark_llm_domain=SPARKAI_DOMAIN,
streaming=False,
)
handler = ChunkPrintHandler()
a = spark.generate([messages], callbacks=[handler])
return a.generations[0][0].text

def convert_all_json_in_text_to_dict(text):
"""提取LLM输出文本中的json字符串"""
dicts, stack = [], []
for i in range(len(text)):
if text[i] == '{':
stack.append(i)
elif text[i] == '}':
begin = stack.pop()
if not stack:
dicts.append(json.loads(text[begin:i+1]))
return dicts

class JsonFormatError(Exception):
def init(self, message):
self.message = message
super().init(self.message)

def check_and_complete_json_format(data):
required_keys = {
"基本信息-姓名": str,
"基本信息-手机号码": str,
"基本信息-邮箱": str,
"基本信息-地区": str,
"基本信息-详细地址": str,
"基本信息-性别": str,
"基本信息-年龄": str,
"基本信息-生日": str,
"咨询类型": list,
"意向产品": list,
"购买异议点": list,
"客户预算-预算是否充足": str,
"客户预算-总体预算金额": str,
"客户预算-预算明细": str,
"竞品信息": str,
"客户是否有意向": str,
"客户是否有卡点": str,
"客户购买阶段": str,
"下一步跟进计划-参与人": list,
"下一步跟进计划-时间点": str,
"下一步跟进计划-具体事项": str
}

if not isinstance(data, list):
    raise JsonFormatError("Data is not a list")

for item in data:
    if not isinstance(item, dict):
        raise JsonFormatError("Item is not a dictionary")
    for key, value_type in required_keys.items():
        if key not in item:
            item[key] = [] if value_type == list else ""
        if not isinstance(item[key], value_type):
            raise JsonFormatError(f"Key '{key}' is not of type {value_type.__name__}")
        if value_type == list and not all(isinstance(i, str) for i in item[key]):
            raise JsonFormatError(f"Key '{key}' does not contain all strings in the list")

if name == "main":
retry_count = 5 # 重试次数
result = []
error_data = []

# 读取数据
train_data = read_json("dataset/train.json")
test_data = read_json("dataset/test_data.json")

for index, data in tqdm(enumerate(test_data)):
    index += 1
    is_success = False
    for i in range(retry_count):
        try:
            res = get_completions(PROMPT_EXTRACT.format(content=data["chat_text"]))
            infos = convert_all_json_in_text_to_dict(res)
            infos = check_and_complete_json_format(infos)
            result.append({
                "infos": infos,
                "index": index
            })
            is_success = True
            break
        except Exception as e:
            print("index:", index, ", error:", e)
            continue
    if not is_success:
        data["index"] = index
        error_data.append(data)
write_json("output.json", result)

标签:群聊,BaseLine,信息,json,客户,星火,str,预算,string
From: https://www.cnblogs.com/HuZhuorui/p/18280511

相关文章

  • 英伟达连跌3日,传字节与博通合作研发AI芯片,讯飞星火V4.0周四发布
      ChatGPT狂飙160天,世界已经不是之前的样子。更多资源欢迎关注每日行业新闻1、英伟达单日下跌6.7%,拖累标普500指数和纳指走低昨夜,英伟达暴跌6.7%,创两个月以来最大单日跌幅,为连续三个交易日下跌,市值落于3万亿美元之下。且在技术上已经进入回调状态,即从近期收盘峰值下跌1......
  • QQ机器人开发教程:智能群聊助手
    随着社交媒体的普及,QQ群已成为人们日常生活中重要的交流平台。本文将介绍如何开发一款智能的QQ机器人,作为群聊助手,提供便捷的服务和娱乐功能。一、开发环境搭建首先,需要搭建开发环境。安装Python解释器,并配置好相关的开发工具和库。同时,需要申请一个QQ号作为机器人的登录账......
  • 用故事绘就生活:探索星火绘镜Typemovie的艺术魅力
    在快节奏的生活中,我们常常渴望用一种独特的方式记录和分享我们的故事。星火绘镜Typemovie,一个创新的短视频创作平台,以其独特的即时创作功能,让我们的故事以视频的形式轻松呈现。Typemovie的核心魅力在于它的简单易用和创意无限。用户只需通过描述自己的想法,平台就能智能地将这......
  • 激发创作灵感:星火网文助手的写作之旅
    在文字的世界里,每个创作者都渴望找到一片属于自己的创作天地。星火网文助手,一个专为写作爱好者设计的平台,正以其独特的魅力,点燃每一位写作者心中的创作火花。星火网文助手以其简洁直观的界面,为用户提供了一个专注于写作的环境。在这里,你可以不受外界干扰,沉浸在自己的创作世界......
  • AI工具箱 国产 AI 大模型 智谱-智谱清言 字节跳动-豆包 讯飞-星火大模型 百度-文心一
    文章目录......
  • 【人工智能】讯飞星火Prompt提示词工程基础学习
    AIPrompt工程师认证学习为什么要创建AI助手1)解决重复性操作,使用Prompt结构化的模板将AI大模型的特定能力固定,一劳永逸2)减少输入,减少反复思考压力3)更稳定,效率提升,可以直接使用已经调整好参数的AI助手所提供的服务(提高生产力)4)便于分享,将助手分享给其他用户共同体验解......
  • 文心一言 VS 讯飞星火 VS chatgpt (279)-- 算法导论20.3 6题
    六、创建一个全域大小为u的vEB树,需要O(u)的运行时间。假设我们想得到确切时间。如果vEB树中每个操作的摊还时间为〇(lglgu),那么最小的操作数n是多少?如果要写代码,请用go语言。文心一言:首先,让我们澄清一下vEB(vanEmdeBoas)树的基本概念。vEB树是一种特殊的搜索......
  • 文心一言 VS 讯飞星火 VS chatgpt (275)-- 算法导论20.3 2题
    二、修改vEB树以支持带有卫星数据的关键字。如果要写代码,请用go语言。文心一言:vEB树(vanEmdeBoas树)是一种用于处理稀疏位集合的高效数据结构,它允许在常数时间内执行查找、插入、删除和前驱/后继操作。然而,标准的vEB树并不直接支持带有卫星数据的关键字。要支持带有......
  • 文心一言 VS 讯飞星火 VS chatgpt (273)-- 算法导论20.2 8题
    八、假设设计了这样一个proto-vEB结构,其中每个簇数组仅有u14u^\frac{1}{......
  • 全开源源码---小红书卡片-跳转微信-自动回复跳转卡片-商品卡片-发私信-发群聊-安全导
    做小红书的人都知道小红书的用户商业价值非常高,消费能力很强,很多做高客单产品的都想从小红书平台上引流到私域成交,但是都会遇到账号违规、被封的问题,因为小红书的平台是所有平台里对引流导流最严的。不允许留公众号、手机号、微信号等联系方式,一旦被发现就会面临封禁等处罚。......