一、学习目标
学会使用prompt工程改造讯飞星火大模型,使大模型能够提取群聊对话里面的客户信息。Datawhale文档链接
二、代码理解
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
# 测试模型配置是否正确
text = "你好"
get_completions(text)
'你好!有什么可以帮助你的吗?'
这段代码搭建了和星火大模型连接,代码其实来自于星火认知大模型演示文档。可以用该函数试用别的例子,例如:
get_completions('请用李白的口吻写一首诗')
'标题:《月下独酌》\n\n月光如水,洒在我的衣襟上,\n我孤独地坐在这空旷的地方。\n酒杯在手,我却不想独饮,\n邀请明月,与它共度这美好的时光。\n\n月亮不懂饮酒,但它的光芒如此明亮,\n我的舞影随着月光起舞,显得那么悠扬。\n在这寂静的夜晚,我与月亮为伴,\n时而清醒,时而沉醉,享受着这宁静的时光。\n\n月亮,你是我唯一的伴侣,\n在这空旷的夜晚,你的光芒照亮了我的心灵。\n我与你共饮,虽然你不懂酒的滋味,\n但我能感受到你的温暖,你的情意。\n\n月亮,你是我永恒的朋友,\n在这寂静的夜晚,你的光芒照亮了我的前方。\n我愿与你共醉,虽然你不能说话,\n但我能感受到你的陪伴,你的关怀。\n\n月亮,你是我孤独的慰藉,\n在这漆黑的夜晚,你的光芒照亮了我的希望。\n我愿与你共舞,虽然你不能看见,\n但我能感受到你的支持,你的鼓励。\n\n月亮,你是我永恒的寄托,\n在这无尽的夜晚,你的光芒照亮了我的梦想。\n我愿与你共歌,虽然你不能听见,\n但我能感受到你的欣赏,你的赞美。\n\n我醉了,我醒了,我在月光中徜徉,\n月亮,你是我生命中的一道光。\n我愿与你共度每一个夜晚,\n直到永恒,直到天荒。\n\n月亮,你是我心中的一片净土,\n在这纷扰的世界,你的光芒照亮了我的心灵。\n我愿与你共度每一个时刻,\n直到永远,直到天涯。\n\n我醉了,我醒了,我在月光中徜徉,\n月亮,你是我生命中的一道光。\n我愿与你共度每一个夜晚,\n直到永恒,直到天荒。\n\n月亮,你是我心中的一片净土,\n在这纷扰的世界,你的光芒照亮了我的心灵。\n我愿与你共度每一个时刻,\n直到永远,直到天涯。'
随后可以看下baseline会用到的数据,在主程序中用到了test_data的数据
test_data[2]
{'chat_text': '王勇7:李强总 手办到了 我下午给你带过去\n王勇7:大概2点前到\n王勇7:你在公司嘛\n李强5:好的,在公司\n王勇7:哦了\n李强5:[小程序消息]\n李强5:[图片]\n李强5:王勇7总,这个你们是不是没弄清楚?\n王勇7:现在应该是可以了\n王勇7:李强总 你看这周什么时间方便,我让企鹅和eric再来做下拜访\n王勇7:上次线下有说在拜访多交流嘛\n王勇7:刚好是把月初我们沟通四期的一些定制UI这些需求也强调一下\n李强5:王勇7总,估计还得在等一等,我们现在又有变化,要把业务划到下面公司去\n王勇7:下面公司是脱离北燃的组织架构了吗\n李强5:不是脱离,就是业务下沉\n王勇7:明白\n李强5:等正式确定了,在推进业务\n王勇7:企鹅他们也是正常的回访交流,我想着上回针对北燃优选有些建议嘛,可以强调,等业务正式确认就不用在拉高层领导了,以后前期做好铺垫\n王勇7:我这也都可以,看李强总这边方便\n李强5:还是先等等王勇7总\n王勇7:可以的,按你的节奏来\n李强5:集团变化太快\n王勇7:哈哈,明白\n王勇7:我最近出差了几个城市,湖南省杭州市银泰商城\n王勇7:包括一些水务 供热单位\n王勇7:做了几个方案\n王勇7:我发你瞅瞅\n李强5:他们都做商城吗\n王勇7:对\n李强5:嗯嗯,多谢\n王勇7:都打算往增值业务这边转型\n李强5:正好我们借鉴一下\n王勇7:但是很多企业太单薄有些,要不就是下面业务公司太多,各是各的主体单独运作\n李强5:那没问题\n王勇7:要不就是基础没搭建好,0-1\n李强5:只要他们有这个意向就行\n王勇7:我们做的方案比较长线,可以李强总参考大致看下每家的方向\n李强5:好的\n王勇7:腾飞有限公司大领导往下压的强指标,所以各副总都要响应落实\n王勇7:[文件]\n王勇7:这个是中国燃气的\n李强5:嗯,壹品慧我八月份去调研过\n王勇7:这个是上个月我们的汇报材料\n王勇7:[文件]\n王勇7:这个是武汉燃气的汇报材料\n李强5:这个企微SCRM平台是什么\n王勇7:就是巨石蓝海的基于企业微信接口开发的工具\n李强5:那这个平台和商城平台是融合一起的吗\n王勇7:对的,咱们四期规划就是做企微工具跟咱们北燃优选做关联打通\n王勇7:北燃优选赋能企微的能力\n李强5:你们实地调研的效果挺好\n王勇7:腾飞有限公司的上周我调研了2天,见了他们5个公司,目前大方案在梳理中,到时做好也同步你一下\n王勇7:涉及他们的燃气,供热,内部私有化,兼容这一部分\n李强5:[抱拳]\n李强5:你说的热力公司有吗\n王勇7:对的 热力的\n王勇7:[文件]\n王勇7:这个是华润燃气的24年我们运营汇报材料\n李强5:我先学习学习\n王勇7:行的李强总 你先看看',
'infos': []}
baseline文档提供了一个prompt模板,如下:
```python
# 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格式输出。
不要添加任何澄清信息。
输出必须遵循上面的模式。
不要添加任何没有出现在模式中的附加字段。
不要随意删除字段。
**输出:**
[{{
"基本信息-姓名": "姓名",
"基本信息-手机号码": "手机号码",
"基本信息-邮箱": "邮箱",
"基本信息-地区": "地区",
"基本信息-详细地址": "详细地址",
"基本信息-性别": "性别",
"基本信息-年龄": "年龄",
"基本信息-生日": "生日",
"咨询类型": ["咨询类型"],
"意向产品": ["意向产品"],
"购买异议点": ["购买异议点"],
"客户预算-预算是否充足": "充足或不充足",
"客户预算-总体预算金额": "总体预算金额",
"客户预算-预算明细": "预算明细",
"竞品信息": "竞品信息",
"客户是否有意向": "有意向或无意向",
"客户是否有卡点": "有卡点或无卡点",
"客户购买阶段": "购买阶段",
"下一步跟进计划-参与人": ["跟进计划参与人"],
"下一步跟进计划-时间点": "跟进计划时间点",
"下一步跟进计划-具体事项": "跟进计划具体事项"
}}, ...]
我们可以用一个训练集的例子来测试一下,可以看到大模型返回的结果不是标准json格式,还需要进行数据处理。
get_completions(PROMPT_EXTRACT.format(content=train_data[0]))
'```json\n[{\n "基本信息-姓名": "动漫周边配送中心",\n "咨询类型": ["答疑"],\n "购买异议点": ["产品功能"],\n "客户是否有卡点": "有卡点"\n}]\n```'
所以最后的主程序就是在使用test_data里的chat_text来填充prompt,再输入给大模型以输出结果。get_completions(PROMPT_EXTRACT.format(content=data["chat_text"]))
就是一个用测试集数据来替换prompt中的’chat_text’的过程,再输入到上文提到的get_completion函数,得到大模型的回复。
from tqdm import tqdm
retry_count = 5 # 重试次数
result = []
error_data = []
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)