llm_eval_system / examples /test_metrics /lingoace_chat_metric.py
HoneyTian's picture
update
1e55fa2
#!/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()