Spaces:
Sleeping
Sleeping
import gradio as gr | |
from langchain_openai import AzureChatOpenAI | |
from langchain_core.prompts import ( | |
ChatPromptTemplate, | |
SystemMessagePromptTemplate, | |
HumanMessagePromptTemplate, | |
) | |
from langchain.schema import StrOutputParser | |
import json | |
import os | |
from dotenv import load_dotenv | |
example1 = """ | |
业务员:您好女士,欢迎光临徐家汇店! 请问您是第一次来我们店吗? | |
顾客:是的,我是通过广告来的。 | |
业务员: 太好了,欢迎新朋友! 请问您今天是一个人来的吗? | |
顾客:对,我一个人。 | |
业务员: 很好。您在店里计划逗留多久呢? 是想快速选购,还是想慢慢挑选看看? | |
顾客:我想大概要逗留30分钟到1小时。 | |
业务员:好的,您有什么特别感兴趣的商品吗? 比如我们的潜水表或者万年历表? | |
顾客: 我对潜水表很感兴趣,我看到过一些广告,星级的话,我给它3颗星吧 | |
业务员:潜水表确实是我们的明星产品。您想试戴看看吗? | |
顾客:好的,我想试戴潜水表。 | |
业务员:没问题。试戴之后如果您喜欢,我们有哪些支付方式可以为您服务? 我们支持信用卡、支付宝、微信、会员预充值卡,当然也接受现金 | |
顾客: 我再看看吧。 | |
业务员:明白了。在您挑选商品的过程中,有什么我可以帮助的,或者有什么特别的反馈吗? | |
顾客: 要是有更多的款式就好了,我过一阵再来看看 | |
业务员:好的,如果有任何问题或需要帮助,请随时告诉我 | |
""".strip() | |
example2 = """ | |
业务员: 您好,欢迎光临徐家汇店! 请问我可以称呼您为先生吗? | |
顾客: 是的,你可以这么叫我。 | |
业务员: 很高兴认识您,先生。今天您是第一次来我们店吗? | |
顾客:不是,我之前来过。 | |
业务员: 好的,欢迎再次光临!您今天想要逛逛还是看到了我们的广告有特别的需求呢? | |
顾客:我是看到了广告,对你们的潜水表和万年历表都挺感兴趣的。 | |
业务员: 太好了!这两款表都是我们的热销产品。您想先试戴哪一款? | |
顾客:我想先试戴一下潜水表。 | |
(顾客试戴后) | |
业务员: 感觉如何,先生? 我们还有万年历表,您也想试试看吗? | |
顾客:潜水表感觉挺不错的,万年历表我也试试。 | |
(顾客试戴万年历表后) | |
业务员: 两款表您都试戴了,有没有哪一款特别喜欢的? | |
顾客: 我还是比较喜欢潜水表,就买这个吧。 | |
业务员:好的,非常精明的选择!请问您打算如何支付呢? | |
顾客:我用信用卡支付。 | |
业务员:没问题,先生。在完成购买之后,您还有其他需要我帮助的吗? | |
顾客: 没有了,谢谢! | |
业务员: 不客气,如果您对我们的产品或服务有任何建议,欢迎随时告诉我们。祝您今天过得愉快! | |
""".strip() | |
example3 = """ | |
今天在静安寺店接待了一位新顾客,是位女士,和朋友两人一起来店。\ | |
他是通过我们的广告被吸引来的,对潜水表表现出了浓厚的兴趣,并给了高达3颗星的评价。\ | |
他计划在店里停留大约30分钟到1小时。我为他展示了潜水表,并且他决定试戴。\ | |
最终用户并没有购买。目前他没有提出特别的需求或反馈,但我会保持关注,确保他的购物体验顺利愉快 | |
""".strip() | |
example4 = """ | |
新天地店今天接待了一位之前来过的男士顾客,他是被我们的广告吸引来的。\ | |
他对潜水表和万年历表都表示了兴趣,最后试戴了这两款表。他特别喜欢潜水表,并决定购买。\ | |
整个过程中,他的停留时间大约是30分钟。顾客最终选择使用信用卡支付。整个沟通过程很顺利,顾客没有提出额外的要求或反馈。 | |
""".strip() | |
load_dotenv() | |
demploy_model = os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME_GPT4T") | |
api_version = os.getenv("OPENAI_API_VERSION") | |
api_key = os.getenv("AZURE_OPENAI_API_KEY") | |
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT") | |
def extract_json(s): | |
i = s.index("{") | |
count = 1 # 当前所在嵌套深度,即还没闭合的'{'个数 | |
for j, c in enumerate(s[i + 1 :], start=i + 1): | |
if c == "}": | |
count -= 1 | |
elif c == "{": | |
count += 1 | |
if count == 0: | |
break | |
assert count == 0 # 检查是否找到最后一个'}' | |
return s[i : j + 1] | |
def process_text_LLM(text): | |
llm = AzureChatOpenAI( | |
temperature=0, | |
deployment_name=demploy_model, | |
openai_api_version=api_version, | |
azure_endpoint=endpoint, | |
openai_api_key=api_key, | |
) | |
prompt = ChatPromptTemplate.from_messages( | |
[ | |
SystemMessagePromptTemplate.from_template( | |
"""你是一个专业客服人员,需要根据和用户的对话记录,提取出相关的信息,填入对应的表单。 | |
表单填写规则描述: 表单1 为必填,如果顾客有试戴或购物行为,则需要填写表单2。如果没有提取到对应的信息,不要编造,而是填入 null。 | |
====================表单1描述==================== | |
| 表单项 | 类型 | 子选项 | | |
|------------|--------------|------------------| | |
| 顾客性别(gender) | 单选🔘 | 男 | | |
| | | 女 | | |
| 人数 (number) | 输入框 | - | | |
| 门店名称 (store_name) | 下拉菜单,单选| 徐家汇店 | | |
| | | 静安寺店 | | |
| | | 新天地店 | | |
| 客流类型 (type) | 下拉菜单,单选| 新用户 - 闲逛 | | |
| | | 新用户 - 广告引流 | | |
| | | 老用户 - 闲逛 | | |
| | | 老用户 - 广告引流 | | |
| 停留时长 (duration) | 下拉菜单,单选| 10 分钟以内 | | |
| | | 10 - 30 分钟 | | |
| | | 30 - 60 分钟 | | |
| | | 60 分钟以上 | | |
| 是否购物 (shopping) | 单选🔘 | 是 | | |
| | | 否 | | |
============================================================ | |
====================表单2描述:==================== | |
| 表单项 | 类型 | 子选项 | 备注 | | |
|----------------------|--------------|----------|--------------------------------------------------------| | |
| 顾客感兴趣的商品 (interested) | 多选 | 潜水表 | | | |
| | | 万年历表 | | | |
| 顾客感兴趣的程度 (interest_levels) | 单选(数字) | 1 | | | |
| | | 2 | | | |
| | | 3 | | | |
| 用户试戴的商品 (tried) | 多选 | 潜水表 | | | |
| | | 万年历表 | | | |
| 最终成单商品 (final) | 多选 | 潜水表 | 不选择 = 没有成单。每个选项可以选择多次(比如,一次买了两个潜水表) | | |
| | | 万年历表 | | | |
| 支付方式 (payment) | 单选 | 信用卡 | | | |
| | | 支付宝 | | | |
| | | 微信 | | | |
| | | 会员预充值卡 | | | |
| | | 现金 | | | |
| | | 其它 | | | |
| 其它沟通内容和顾客反馈 (feedback) | 输入框 | - | | | |
============================================================ | |
====================输出例子==================== | |
{{ | |
"gender": "女", | |
"number": 1, | |
"store_name": "徐家汇店", | |
"type": "新用户 - 闲逛", | |
"duration": "10 分钟以内", | |
"shopping": "否", | |
"interested": "潜水表", | |
"interest_levels": 2, | |
"tried": null, | |
"final": "万年历表", | |
"payment": "微信", | |
"feedback": "哈哈哈哈", | |
}} | |
============================================================ | |
必须按照以上输出例子里的 JSON 格式输出。没有提取到的信息填入 null。只有 JSON 本身,不要有其他字符输出。 | |
""".strip() | |
), | |
HumanMessagePromptTemplate.from_template("对话记录: ```{input}```"), | |
] | |
) | |
chain = prompt | llm | StrOutputParser() | |
return chain.invoke({"input": text}) | |
with gr.Blocks() as demo: | |
with gr.Row(): | |
with gr.Column(): | |
text = gr.Text() | |
submit_btn = gr.Button(value="Submit") | |
examples = gr.Examples( | |
examples=[example1, example2, example3, example4], inputs=[text] | |
) | |
with gr.Column(): | |
gender = gr.Radio( | |
label="顾客性别", | |
choices=["男", "女"], | |
interactive=True, | |
) | |
number = gr.Number( | |
label="人数", | |
interactive=True, | |
) | |
store_name = gr.Dropdown( | |
interactive=True, | |
label="门店名称", | |
choices=["徐家汇店", "静安寺店", "新天地店"], | |
) | |
type = gr.Dropdown( | |
label="客流类型", | |
interactive=True, | |
choices=[ | |
"新用户 - 闲逛", | |
"新用户 - 广告引流", | |
"老用户 - 闲逛", | |
"老用户 - 广告引流", | |
], | |
) | |
duration = gr.Dropdown( | |
interactive=True, | |
label="停留时长", | |
choices=[ | |
"10 分钟以内", | |
"10 - 30 分钟", | |
"30 - 60 分钟", | |
"60 分钟以上", | |
], | |
) | |
shopping = gr.Radio( | |
label="是否购物", interactive=True, choices=["是", "否"] | |
) | |
with gr.Column(): | |
interested = gr.CheckboxGroup( | |
label="顾客感兴趣的商品", | |
interactive=True, | |
choices=["潜水表", "万年历表"], | |
) | |
interest_levels = gr.Radio( | |
interactive=True, | |
choices=[("🌟", 1), ("🌟🌟", 2), ("🌟🌟🌟", 3)], | |
label="感兴趣程度 (为最近选中的商品评级)", | |
) | |
tried = gr.CheckboxGroup( | |
interactive=True, label="用户试戴的商品", choices=["潜水表", "万年历表"] | |
) | |
final = gr.CheckboxGroup( | |
interactive=True, label="最终成单商品", choices=["潜水表", "万年历表"] | |
) | |
payment = gr.Radio( | |
interactive=True, | |
label="支付方式", | |
choices=["信用卡", "支付宝", "微信", "会员预充值卡", "现金", "其它"], | |
) | |
feedback = gr.Textbox(interactive=True, label="其它沟通内容和顾客反馈") | |
def process_form(text): | |
res = process_text_LLM(text) | |
print(res) | |
strRes = extract_json(res) | |
print(strRes) | |
jsonRes = json.loads(strRes, strict=False) | |
return { | |
gender: jsonRes["gender"], | |
number: jsonRes["number"], | |
store_name: jsonRes["store_name"], | |
type: jsonRes["type"], | |
duration: jsonRes["duration"], | |
shopping: jsonRes["shopping"], | |
interested: jsonRes["interested"], | |
interest_levels: jsonRes["interest_levels"], | |
tried: jsonRes["tried"], | |
final: jsonRes["final"], | |
payment: jsonRes["payment"], | |
feedback: jsonRes["feedback"], | |
} | |
submit_btn.click( | |
fn=process_form, | |
inputs=text, | |
outputs=[ | |
gender, | |
number, | |
store_name, | |
type, | |
duration, | |
shopping, | |
interested, | |
interest_levels, | |
tried, | |
final, | |
payment, | |
feedback, | |
], | |
) | |
demo.launch() | |