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()