赛题背景
在当今数字化时代,企业积累了大量对话数据,这些数据不仅是客户与企业之间交流的记录,更是隐藏着宝贵信息的宝库。通过分析群聊对话数据,企业可以更好地理解客户需求,提供个性化服务,提升客户满意度和商业价值。群聊对话分角色要素提取是企业营销和服务的一项重要策略,通过分析这些数据,企业可以精准把握客户需求,提供更加优质的服务。
赛事任务与数据
任务是从给定的客服与客户的群聊对话中提取指定字段信息,数据集包含184条群聊对话数据,分为训练数据129条和测试数据55条。根据字段提取的难易程度,设置了1、2、3三种难度分数。字段包括基本信息、咨询类型、意向产品、客户预算、竞品信息、客户购买阶段和下一步跟进计划等。
评价指标
测试集包含21个字段,总计满分36分。答案唯一字段使用完全匹配的方式计算得分,非唯一字段综合考虑提取完整性、语义相似度等维度判定匹配分数。最终得分为所有字段累计得分的平均值。
解题思路
我们选择使用大语言模型进行信息抽取,需要对原始数据进行读取后,编写合适的抽取提示(prompt)。设计prompt时需强调抽取的数据格式和内容,将测试集的每一条通过大语言模型抽取得到结果。我们采用讯飞星火大模型V3.5进行处理。
Baseline详解
环境配置
!pip install --upgrade -q spark_ai_python tqdm
数据处理
读取训练集和测试集数据,了解具体需要处理的内容。
import json
def read_json(json_file_path):
with open(json_file_path, 'r') as f:
data = json.load(f)
return data
train_data = read_json("dataset/train.json")
test_data = read_json("dataset/test_data.json")
print(train_data[100]['chat_text'])
Prompt工程
设计适合的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 | ""
)>
请分析以下群聊对话记录,并根据上述格式提取信息:
**对话记录:**
数据抽取
使用prompt进行数据抽取,并处理JSON格式问题和字段检查。
from sparkai.llm.llm import ChatSparkLLM, ChunkPrintHandler
from sparkai.core.messages import ChatMessage
import json
from tqdm import tqdm
# 星火认知大模型配置信息
SPARKAI_URL = 'wss://spark-api.xf-yun.com/v3.5/chat'
SPARKAI_APP_ID = 'YOUR_APP_ID'
SPARKAI_API_SECRET = 'YOUR_API_SECRET'
SPARKAI_API_KEY = 'YOUR_API_KEY'
SPARKAI_DOMAIN = 'generalv3.5'
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):
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")
return data
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)
结语
在基于星火大模型的群聊对话分角色要素提取任务中,我们利用大语言模型对群聊对话数据进行深度分析和信息抽取,取得了显著成果。通过设计适合的prompt模板,结合规范化的数据处理和字段检查,确保了提取结果的准确性和完整性。未来,进一步优化特征工程和模型集成,将为提升信息提取的精度和效率提供更多可能性。这不仅有助于提升企业的客户服务质量,还将带来更多商业价值和竞争优势。
如果你觉得这篇博文对你有帮助,请点赞、收藏、关注我,并且可以打赏支持我!
欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。
谢谢大家的支持!