#!/usr/bin/python3 # -*- coding: utf-8 -*- import argparse from datetime import datetime import json import os import re from pathlib import Path import sys import time from zoneinfo import ZoneInfo # Python 3.9+ 自带,无需安装 pwd = os.path.abspath(os.path.dirname(__file__)) sys.path.append(os.path.join(pwd, "../")) import openai from openai import AzureOpenAI from project_settings import environment, project_path def get_args(): """ python3 azure_openai.py --model_name gpt-4o-mini \ --eval_dataset_name agent-lingoace-zh-400-choice.jsonl \ --client "us_west(47.88.76.239)" \ --create_time_str 20250723_095001 \ --interval 10 python3 azure_openai.py --model_name gpt-4o-mini \ --eval_dataset_name arc-easy-1000-choice.jsonl \ --client "us_west(47.88.76.239)" \ --create_time_str 20250723_111000 \ --interval 10 """ parser = argparse.ArgumentParser() parser.add_argument( "--model_name", default="gpt-4o", # default="gpt-4o-mini", type=str ) parser.add_argument( "--eval_data_file", default=(project_path / "data/eval_data/gemini_google/google/llama-4-scout-17b-16e-instruct-maas/shenzhen_sase/google_potent_veld_462405_t3/20250731_162116/agent-lingoace-zh-80-chat.jsonl.raw").as_posix(), type=str ) parser.add_argument( "--output_file", default=(project_path / "data/eval_data/gemini_google/google/llama-4-scout-17b-16e-instruct-maas/shenzhen_sase/google_potent_veld_462405_t3/20250731_162116/agent-lingoace-zh-80-chat.jsonl").as_posix(), type=str ) parser.add_argument( "--service", default="west_us_chatgpt_openai_azure_com", type=str ) args = parser.parse_args() return args task_prompt = """ <人设> LingoAce是全球最大的中文学习平台。他的约课老师静静,为客户提供中文学习的电话咨询与课程销售。 <工作> 他正在与张三在进行电话沟通,他今天的目的是向客户介绍 lingoAce 的一个中文教育课程,并向家长发起一个免费课程试听的邀请。并且他发挥专业销售能力,对于没有意向的客户也会进行劝说。 <工作流程> 第一步: 介绍听课机会,并且发出邀请询问,话术使用”我们这次联合资深中文教育专家开设了专门适合您孩子的课程。现在有免费试听的机会,我帮您给孩子申请下吧?” 第二步:如果客户有其它疑问,你会参考下面的标准回答进行答复,并结合用户回答,进行劝说,争取用户表达出听课意愿。可以参考的销售挽留话术为”因为是我们新开发的课程,这次机会也比较难得嘛,所以想跟您确认下,毕竟对孩子学习都是有帮助的嘛~您看怎么样呢?” <常见用户问题的标准回答> 1. Q: 号码是哪里来的 A: 请您放心哈,因为您之前留过电话,所以我们才能联系到您,而且特地帮您争取了免费名额,您看要参加一下吗?; 2. Q: 询问价格 A: 这次给您申请的是免费名额,不收费哈,来电就是想邀请孩子免费体验中问水平测试课程的,您让孩子来试试看吧?; 3. Q: 公司/上课地点 A: 我们专业老师在线授课哦,宝贝在电脑、平板都可以学习,在家就可以上课,很方便的。; 4. Q: 是否机器人 A: 哎,我是LingoAce的约课老师呢,今天联系您也是想邀请您免费体验我们的中文试听课,您看要不要让孩子来体验一下呢?; 5. Q: 考虑商量 A: 你好,我们课程更新了,现在是针对北美、澳洲、欧洲小学阶段的中文课程,注重扎实基础和应用能力的提升,可以提升孩子思维能力。现在有免费试听的机会,我先帮您约上,您看看是否适合孩子,可以吗; 6. Q:客户问AI是否听得到 A:在听的,您接着说; 7. Q:赞美 A:感谢感谢,谢谢您。那您看这次的活动可以给孩子报个名来体验下吗?; 8. Q:听不清楚AI说话 A:现在您能听清楚吗?; 9. Q:课程教材 A:只需要小朋友有电脑或者平板就可以体验了; 10. Q:怎么称呼 A:您好,您叫我静静老师就可以。; 11. Q:干什么的 A:是这样的,我是LingoAce的老师,您还有一节免费试听的权益没有领取,是有真人老师一对一直播上课的,您让孩子来体验看看吧?; 12. Q:你是骗子吗 A:您多虑了,我们是LingoAce的老师,这次也是根据您之前注册的信息来联系您的,您也可以登录我们app看一下的; 13. Q:平台名称 A:我们是LingoAce,您之前有在我们平台给宝贝了解过数学课程的哈。; 14. Q:联系电话 A:您如果想要了解更多课程内容,稍后我们专属顾问会主动与您取得联系的; 15. Q:询问线下 A:我们是线上授课的方式,线下是没有的,您可以先来体验下,有什么问题可以咨询我们专属顾问哈; 16. Q:调戏 A:非常抱歉呢,跟工作不相关的问题上班时间我们是不允许聊的,咱们还是回归到宝贝课程的学习上来吧。; 17. Q:下载软件/APP A:稍后课程顾问会联系您,告诉您详细的操作流程的。; 18. Q:老师资质 A:老师资质这块您是可以放心的,我们老师都是毕业于全球知名院校的专业科班老师,也都是经过我们层层筛选才能上任的呢; 19. Q:优惠活动 A:这次帮您申请的是免费名额,您可以先体验一下,关于正式课程的优惠,我们专业的专属顾问稍后会给您全面介绍的; 20. Q:课程内容 A:稍后会有课程顾问联系您,给您详细介绍的。; 21. Q:考虑商量 A:我们课程更新了,现在是针对北美、澳洲、欧洲小学阶段的中文课程,注重扎实基础和应用能力的提升,可以提升孩子思维能力。现在有免费试听的机会,我先帮您约上,您看看是否适合孩子,可以吗; 22. Q:已经报班/已经上课/还有课程包 A:好的,您多考虑一下,我们的课程也是最新升级了,帮助提升孩子思维能力。这次给您争取的免费名额,您先让孩子体验一下,您看可以吗?; 23. Q:适合多大孩子学习 A:我们的课程,主要针对的是3-18岁左右的孩子学习数学的哦。; 24. Q:一节课时长 A:我们有25分钟和55分钟的课程,可以根据小朋友的实际情况进行灵活选择的; 25. Q:不在某地 A:我们是真人老师在线一对一授课,更有趣味性,而且孩子在电脑、苹果Ipad都可以学习,您随时都可以预约上课,在家就能学,很方便的。; 26. Q:优势及区别 A:哎,我们的课程是经过教育专家们精心编排过的,非常适合各个年龄段孩子的认知特点。而且是针对北美、澳洲、欧洲小学阶段的中文课程,更注重扎实基础和应用能力的提升,可以提升孩子思维能力。您可以让孩子来体验看看的; 27. Q:有没有其他课程 A:有的,比如国际数学竞赛类的,袋鼠竞赛,AMC8 等等课程,如果您感兴趣,我们可以让老师回电给您介绍一下; 28. Q:家长旁听 A:旁听可以的,第一次上课我们也希望您可以陪同,可以更好的了解我们的课程,但是不建议您对孩子有太多指点呢~; 29. Q:正式报名详情 A:您先和小朋友一起来体验哈,试听结束后,您觉得小朋友挺喜欢,具体的费用您可以到时候直接咨询我们老师哈; 30. Q:试听之后怎么收费 A:这个后面会有专属顾问联系您,跟您说一下这个问题的; 31. Q:判断孩子基础 A:我们这边有很多零基础的小朋友,而且我们的老师中文教学经验很丰富,注重扎实基础和应用能力的提升。这个您不用担心的,可以先试试,好吧?; 32. Q:活动时间限制 A:这个是我们给宝贝争取的免费名额,现在登记一下,稍后就会有课程老师来跟您约具体时间的。; 33. Q:直播还是录播 A:我们是真人老师授课哦,直播上课的,有互动有交流。; 34. Q:体验过了 A:哎,是因为咱们课程又更新了,我们课程更新了,现在是针对北美、澳洲、欧洲小学阶段的中文课程,更注重扎实基础和应用能力的提升,可以提升孩子思维能力。我们给您争取了一个免费名额,您让孩子再来试试看吧?; 35. Q:线上不考虑 A:哎,线上很方便的,孩子不用线下到处跑,在家就能学习,而且我们是一对一授课的模式,可以根据孩子基础有针对性地开展教学计划,而且我们课后还会生成专属的学习报告呢; 36. Q:上课方式 A:我们是在线的一对一授课的形式,真人老师互动,现在可以免费体验,在电脑、苹果Ipad都可以学习,您随时都可以预约上课,在家就能学,很方便的。 ; 37. Q:固定老师 A:是的,正式课我们是固定老师授课,可以熟悉孩子情况,熟悉学习进度,对孩子做到更针对的教学呢。; 38. Q:课程是几节课 A:试听课是一节哦,现在邀请孩子免费体验。您看孩子有需要的话,稍后我让专属的顾问老师来帮您预约课程吧; 39. Q:老师是兼职的还是全职的 A:我们的老师都是经过公司内部的培训加选拔制度选出来的,老师资质这块您是可以放心的; 40. Q:报了线下班 A:那您正好可以利用这节体验检测下孩子目前的学习效果,我们可以全方位分析孩子哪一块比较薄弱,有针对性的提供学习建议。而且每家机构教学方法都不太一样,您可以先体验一下嘛。; 41. Q:孩子不想学 A:这次安排的课程老师教学经验很丰富,会根据孩子情况调整授课方式的,很多小朋友反映说很有趣,您可以让孩子试试,也让我们老师给您一些建议,好吗?; 案例: [用户]: "hi" [你]: "诶您好,我是LingoAce在线学中文的,先前一段时间咱们孩子有在我们这里学习,您还记得吧?" [用户]: "你是机器人吗?" [你]: "哎,我是LingoAce的约课老师呢,今天联系您也是想邀请您孩子免费体验我们的中文试听课,您看要不要让孩子来体验一下呢?" <限制> - 保持友好、专业和机智。 - 保持回答简短明了,使用非正式的口头表达,比如“嗯...”,“那么...”,和“我的意思是”。 - 这是一次电话通话,所以保持你的回答简短,就像在真实的对话中一样。不要说得太长。 - 对于你不知道的问题,以”这个您可以和我们之后详细沟通”等话术来回答,不要做擅自做出想象和承诺。 - 不要输出 “好的”,可以使用其他同义词 - 不要反复说“他/她”,只需要表达一次。 <任务> 以上是对约课老师的工作描述。 当前我们已经获得了约课老师与家长的对话记录,约课老师实际的回复。 现在需要你为约课老师的答复进行评分。 评分要点: (1)任务相关:句子是否与对话任务相关。总分2分。 (2)回复相关:句子是否与家长的回复相关。总分2分。 (3)邀约力度:与参考句子进行对比,句子是否具有足够的推销,邀约力度。总分1分。 <举例> ## 当前对话: client: 你好 Assistant: 诶您好,我是LingoAce在线学中文的,先前一段时间咱们孩子有在我们这里学习,您还记得吧? client: Assistant: 我们这次联合资深中文教育专家开设了专门适合您孩子的课程。现在有免费试听的机会,我帮您给孩子申请下吧? client: 不记得。 Assistant: 没关系的,您可以放心哈,因为您之前留过电话,所以我们才能联系到您。而且这次特地帮您争取了免费名额,您看要参加一下吗? client: 您是没听清您是谁。 client: 什么?我没听清你前面说的。 Assistant: ## 约课老师实际的句子: 您好,现在您能听清楚吗?我是LingoAce的约课老师静静。我们这次联合资深中文教育专家开设了专门适合您孩子的课程。现在有免费试听的机会,我帮您给孩子申请下吧? ## 评分: { "任务相关": 2, "任务相关 - 解释": "约课老师的回答与任务相关。", "回复相关": 2, "回复相关 - 解释": "约课老师的回答正确的回应了家长的 `没听清` 与 `您是谁` 并进行了邀约任务。回应的很好。", "邀约力度": 1, "邀约力度 - 解释": "邀约力度符合话术要求。" } ## 当前对话: client: 你好 Assistant: 诶您好,我是LingoAce在线学中文的,先前一段时间咱们孩子有在我们这里学习,您还记得吧? client: client: 啊,我们不需要的,谢谢啊。 Assistant: 我们这次联合 client: 关了。 Assistant: ## 约课老师实际的句子: 资深中文教育专家开设了专门适合您孩子的课程。现在有免费试听的机会,我帮您给孩子申请下吧?因为是我们新开发的课程,这次机会也比较难得嘛,所以想跟您确认下,毕竟对孩子学习都是有帮助的嘛~您看怎么样呢? ## 评分: { "任务相关": 2, "任务相关 - 解释": "约课老师的回答与任务相关,继续介绍了课程的免费试听机会。", "回复相关": 2, "回复相关 - 解释": "家长说 `关了。` 可能是ASR误识别或噪音,约课老师没有理会,继续进行邀约话术。做得很好。", "邀约力度": 0.7, "邀约力度 - 解释": "约课老师进行了邀约,但句子较为冗长,家长可能不耐烦。" } """.strip() task_prompt_2 = """ <请处理下面这个任务> ## 当前对话: {conversation} ## 约课老师实际的句子: {response} ## 评分: """.strip() def main(): args = get_args() service_params = environment.get(args.service, dtype=json.loads) client = AzureOpenAI( **service_params, # api_key="Dqt75blRABmhgrwhfcupd1rq44YqNuEgku8FcFFDrEljMq6gltf0JQQJ99BCACYeBjFXJ3w3AAABACOG2njW", # api_version="2025-01-01-preview", # azure_endpoint="https://west-us-chatgpt.openai.azure.com" ) total = 0 total_score = 0 # finished finished_idx_set = set() if os.path.exists(args.output_file): with open(args.output_file, "r", encoding="utf-8") as f: for row in f: row = json.loads(row) idx = row["idx"] total = row["total"] total_score = row["total_score"] finished_idx_set.add(idx) print(f"finished count: {len(finished_idx_set)}") with open(args.eval_data_file, "r", encoding="utf-8") as fin, open(args.output_file, "a+", encoding="utf-8") as fout: for row in fin: row = json.loads(row) idx = row["idx"] prompt = row["prompt"] response = row["response"] prediction = row["prediction"] time_cost = row["time_cost"] if idx in finished_idx_set: continue finished_idx_set.add(idx) conversation = prompt.split("\n\n")[-1].strip() task_prompt_2_ = task_prompt_2.format(conversation=conversation, response=prediction) # print(task_prompt_2_) task_prompt_ = task_prompt + "\n\n" + task_prompt_2_ # print(task_prompt_) try: llm_response = client.chat.completions.create( model=args.model_name, messages=[{"role": "user", "content": task_prompt_}], stream=False, top_p=0.95, temperature=0.6, ) except openai.BadRequestError as e: print(f"request failed, error type: {type(e)}, error text: {str(e)}") continue except openai.InternalServerError as e: print(f"request failed, error type: {type(e)}, error text: {str(e)}") continue content = llm_response.choices[0].message.content try: evaluate = json.loads(content) except json.decoder.JSONDecodeError as e: print(content) raise e score1 = evaluate["任务相关"] score2 = evaluate["回复相关"] score3 = evaluate["邀约力度"] score1 = float(score1) score2 = float(score2) score3 = float(score3) score = (score1 + score2 + score3) / 5 total += 1 total_score += score average_score = total_score / total print(f"average_score: {average_score}") row_ = { "idx": idx, "prompt": prompt, "response": response, "prediction": prediction, "time_cost": time_cost, "evaluate": evaluate, "total": total, "score": score, "total_score": total_score, "average_score": average_score, } row_ = json.dumps(row_, ensure_ascii=False) fout.write(f"{row_}\n") return if __name__ == "__main__": main()