diff --git a/dsLightRag/KeDaXunFei/1.mp3 b/dsLightRag/KeDaXunFei/1.mp3 new file mode 100644 index 00000000..d0e69013 Binary files /dev/null and b/dsLightRag/KeDaXunFei/1.mp3 differ diff --git a/dsLightRag/KeDaXunFei/XunFeiAudioEvaluator.py b/dsLightRag/KeDaXunFei/XunFeiAudioEvaluator.py new file mode 100644 index 00000000..cb2b13fa --- /dev/null +++ b/dsLightRag/KeDaXunFei/XunFeiAudioEvaluator.py @@ -0,0 +1,269 @@ +import base64 +import datetime +import hashlib +import hmac +import json +import ssl +import time +import xml.etree.ElementTree as ET +from datetime import datetime +from time import mktime +from urllib.parse import urlencode +from wsgiref.handlers import format_date_time +import websocket + +class XunFeiAudioEvaluator: + """讯飞语音评测类""" + + def __init__(self, appid, api_key, api_secret, audio_file): + self.appid = appid + self.api_key = api_key + self.api_secret = api_secret + self.audio_file = audio_file + self.host_url = "ws://ise-api.xfyun.cn/v2/open-ise" + self.websocket_url = "" + self.evaluation_results = {} + + def generate_auth_url(self): + """生成鉴权URL""" + now_time = datetime.now() + now_date = format_date_time(mktime(now_time.timetuple())) + + origin_base = "host: " + "ise-api.xfyun.cn" + "\n" + origin_base += "date: " + now_date + "\n" + origin_base += "GET " + "/v2/open-ise " + "HTTP/1.1" + + # SHA256加密 + signature_sha = hmac.new( + self.api_secret.encode('utf-8'), + origin_base.encode('utf-8'), + digestmod=hashlib.sha256 + ).digest() + signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8') + + authorization_origin = f'api_key="{self.api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha}"' + authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8') + + dict_data = { + "authorization": authorization, + "date": now_date, + "host": "ise-api.xfyun.cn" + } + + return self.host_url + '?' + urlencode(dict_data) + + def on_message(self, ws, message): + """WebSocket消息处理""" + print(f"Received message: {message}") + data = json.loads(message) + status = data["data"]["status"] + + if status == 2: + # 解析评测结果 + xml_data = base64.b64decode(data["data"]["data"]) + xml_content = xml_data.decode("utf-8") + #print(xml_content) + + # 解析XML并提取得分信息 + self.parse_evaluation_results(xml_content) + ws.close() + + def on_error(self, ws, error): + """错误处理""" + print(f"Error: {error},{ws}") + + def on_close(self, ws, reason, res): + """连接关闭处理""" + print(f"WebSocket connection closed,{ws}") + + def on_open(self, ws): + """连接建立处理""" + print(f"WebSocket connection opened,{ws},ws连接建立成功...") + + # 发送初始参数 + send_dict = { + "common": { + "app_id": self.appid + }, + "business": { + "category": "read_sentence", + "rstcd": "utf8", + "sub": "ise", + "group": "pupil", + "ent": "en_vip", + "tte": "utf-8", + "cmd": "ssb", + "auf": "audio/L16;rate=16000", + "aue": "lame", + "text": '\uFEFF' + "[content]\nnice to meet you." + }, + "data": { + "status": 0, + "data": "" + } + } + ws.send(json.dumps(send_dict)) + + # 发送音频数据 + with open(self.audio_file, "rb") as file_flag: + while True: + buffer = file_flag.read(1280) + if not buffer: + # 发送最后一帧 + my_dict = { + "business": { + "cmd": "auw", + "aus": 4, + "aue": "lame" + }, + "data": { + "status": 2, + "data": str(base64.b64encode(buffer).decode()) + } + } + ws.send(json.dumps(my_dict)) + #print("发送最后一帧") + time.sleep(1) + break + + # 发送中间音频帧 + send_dict = { + "business": { + "cmd": "auw", + "aus": 1, + "aue": "lame" + }, + "data": { + "status": 1, + "data": str(base64.b64encode(buffer).decode()), + "data_type": 1, + "encoding": "raw" + } + } + ws.send(json.dumps(send_dict)) + time.sleep(0.04) + + def parse_evaluation_results(self, xml_content): + """解析评测结果XML并提取得分信息""" + try: + root = ET.fromstring(xml_content) + + # 查找read_chapter节点 + read_chapter = root.find('.//read_chapter') + if read_chapter is not None: + self.evaluation_results = { + 'accuracy_score': float(read_chapter.get('accuracy_score', 0)), + 'fluency_score': float(read_chapter.get('fluency_score', 0)), + 'integrity_score': float(read_chapter.get('integrity_score', 0)), + 'standard_score': float(read_chapter.get('standard_score', 0)), + 'total_score': float(read_chapter.get('total_score', 0)), + 'word_count': int(read_chapter.get('word_count', 0)), + 'is_rejected': read_chapter.get('is_rejected', 'false') == 'true' + } + + # 提取句子级别得分 + sentence = read_chapter.find('.//sentence') + if sentence is not None: + self.evaluation_results['sentence'] = { + 'accuracy_score': float(sentence.get('accuracy_score', 0)), + 'fluency_score': float(sentence.get('fluency_score', 0)), + 'total_score': float(sentence.get('total_score', 0)) + } + + # 提取单词级别得分 + words = [] + for word in read_chapter.findall('.//word'): + word_data = { + 'content': word.get('content', ''), + 'total_score': float(word.get('total_score', 0)), + 'dp_message': int(word.get('dp_message', 0)) + } + words.append(word_data) + + self.evaluation_results['words'] = words + + except ET.ParseError as e: + print(f"XML解析错误: {e}") + + def get_evaluation_summary(self): + """获取评测结果摘要""" + if not self.evaluation_results: + return "暂无评测结果" + + summary = "=== 语音评测结果摘要 ===\n" + summary += f"总得分: {self.evaluation_results.get('total_score', 0):.4f}\n" + summary += f"准确度得分: {self.evaluation_results.get('accuracy_score', 0):.4f}\n" + summary += f"流畅度得分: {self.evaluation_results.get('fluency_score', 0):.4f}\n" + summary += f"完整度得分: {self.evaluation_results.get('integrity_score', 0):.4f}\n" + summary += f"标准度得分: {self.evaluation_results.get('standard_score', 0):.4f}\n" + summary += f"单词数量: {self.evaluation_results.get('word_count', 0)}\n" + summary += f"是否被拒绝: {'是' if self.evaluation_results.get('is_rejected', False) else '否'}\n" + + if 'sentence' in self.evaluation_results: + sentence = self.evaluation_results['sentence'] + summary += f"\n=== 句子级别得分 ===\n" + summary += f"句子准确度: {sentence.get('accuracy_score', 0):.4f}\n" + summary += f"句子流畅度: {sentence.get('fluency_score', 0):.4f}\n" + summary += f"句子总分: {sentence.get('total_score', 0):.4f}\n" + + if 'words' in self.evaluation_results: + summary += f"\n=== 单词级别得分 ===\n" + for i, word in enumerate(self.evaluation_results['words']): + dp_msg = self._get_dp_message_description(word['dp_message']) + summary += f"{i+1}. {word['content']}: {word['total_score']:.4f} ({dp_msg})\n" + + return summary + + def _get_dp_message_description(self, dp_message): + """获取dp_message描述""" + descriptions = { + 0: "正常", + 16: "漏读", + 32: "增读", + 64: "回读", + 128: "替换" + } + return descriptions.get(dp_message, f"未知({dp_message})") + + def run_evaluation(self): + """运行评测""" + start_time = datetime.now() + websocket.enableTrace(False) + + ws_url = self.generate_auth_url() + ws_entity = websocket.WebSocketApp( + ws_url, + on_message=self.on_message, + on_error=self.on_error, + on_close=self.on_close, + on_open=self.on_open + ) + + ws_entity.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE}) + + end_time = datetime.now() + evaluation_time = end_time - start_time + print(f"评测耗时: {evaluation_time}") + + return self.evaluation_results, evaluation_time + + +# 使用示例 +if __name__ == '__main__': + # 配置参数 + appid = "5b83f8d6" + api_secret = "604fa6cb9c5ab664a0d153fe0ccc6802" + api_key = "5beb887923204000bfcb402046bb05a6" + audio_file = "./1.mp3" + + # 创建评测器实例 + evaluator = XunFeiAudioEvaluator(appid, api_key, api_secret, audio_file) + + # 运行评测 + results, eval_time = evaluator.run_evaluation() + + # 输出评测结果摘要 + print("\n" + "="*50) + print(evaluator.get_evaluation_summary()) + print(f"总评测时间: {eval_time}") + print("="*50) diff --git a/dsLightRag/KeDaXunFei/__pycache__/XunFeiAudioEvaluator.cpython-310.pyc b/dsLightRag/KeDaXunFei/__pycache__/XunFeiAudioEvaluator.cpython-310.pyc new file mode 100644 index 00000000..5d007a03 Binary files /dev/null and b/dsLightRag/KeDaXunFei/__pycache__/XunFeiAudioEvaluator.cpython-310.pyc differ diff --git a/dsLightRag/KeDaXunFei/参数说明.txt b/dsLightRag/KeDaXunFei/参数说明.txt new file mode 100644 index 00000000..ac5c2db4 --- /dev/null +++ b/dsLightRag/KeDaXunFei/参数说明.txt @@ -0,0 +1,240 @@ +请求参数 +请求数据均为json字符串 + +参数名 类型 必传 描述 +common object 是 公共参数,仅在握手成功后首帧请求时上传,详见下方 +business object 是 业务参数,在握手成功后首帧请求与后续数据发送时上传,详见下方 +data object 是 业务数据流参数,在握手成功后的所有请求中都需要上传,详见下方 +#公共参数说明(common) +参数名 类型 必传 描述 +app_id string 是 在平台申请的APPID信息 +#业务参数说明(business) +参数名 类型 必传 描述 示例 +sub string 是 服务类型指定 +ise(开放评测) "ise" +ent string 是 中文:cn_vip +英文:en_vip "cn_vip" +category string 是 中文题型: +read_syllable(单字朗读,汉语专有) +read_word(词语朗读) +read_sentence(句子朗读) +read_chapter(篇章朗读) +英文题型: +read_word(词语朗读) +read_sentence(句子朗读) +read_chapter(篇章朗读) +simple_expression(英文情景反应) +read_choice(英文选择题) +topic(英文自由题) +retell(英文复述题) +picture_talk(英文看图说话) +oral_translation(英文口头翻译) "read_sentence" +aus int 是 上传音频时来区分音频的状态(在cmd=auw即音频上传阶段为必传参数) +1:第一帧音频 +2:中间的音频 +4:最后一帧音频 根据上传阶段取值 +cmd string 是 用于区分数据上传阶段 +ssb:参数上传阶段 +ttp:文本上传阶段(ttp_skip=true时该阶段可以跳过,直接使用text字段中的文本) +auw:音频上传阶段 根据上传阶段取值 +text string 是 待评测文本 utf8 编码,需要加utf8bom 头 '\uFEFF'+text +tte string 是 待评测文本编码 +utf-8 +gbk "utf-8" +ttp_skip bool 是 跳过ttp直接使用ssb中的文本进行评测(使用时结合cmd参数查看),默认值true true +extra_ability string 否 拓展能力(生效条件ise_unite="1", rst="entirety") +多维度分信息显示(准确度分、流畅度分、完整度打分) +extra_ability值为multi_dimension(字词句篇均适用,如选多个能力,用分号;隔开。例如:add("extra_ability"," syll_phone_err_msg;pitch;multi_dimension")) +单词基频信息显示(基频开始值、结束值) +extra_ability值为pitch ,仅适用于单词和句子题型 +音素错误信息显示(声韵、调型是否正确) +extra_ability值为syll_phone_err_msg(字词句篇均适用,如选多个能力,用分号;隔开。例如:add("extra_ability"," syll_phone_err_msg;pitch;multi_dimension")) "multi_dimension" +aue string 否 音频格式 +raw: 未压缩的pcm格式音频或wav(如果用wav格式音频,建议去掉头部) +lame: mp3格式音频 +speex-wb;7: 讯飞定制speex格式音频(默认值) "raw" +auf string 否 音频采样率 +默认 audio/L16;rate=16000 "audio L16;rate=16000" +rstcd string 否 返回结果格式 +utf8 +gbk (默认值) "utf8" +group string 否 针对群体不同,相同试卷音频评分结果不同 (仅中文字、词、句、篇章题型支持),此参数会影响准确度得分 +adult(成人群体,不设置群体参数时默认为成人) +youth(中学群体) +pupil(小学群体,中文句、篇题型设置此参数值会有accuracy_score得分的返回) "adult" +check_type string 否 设置评测的打分及检错松严门限(仅中文引擎支持) +easy:容易 +common:普通 +hard:困难 "common" +grade string 否 设置评测的学段参数 (仅中文题型:中小学的句子、篇章题型支持) +junior(1,2年级) +middle(3,4年级) +senior(5,6年级) "middle" +rst string 否 评测返回结果与分制控制(评测返回结果与分制控制也会受到ise_unite与plev参数的影响) +完整:entirety(默认值) +中文百分制推荐传参(rst="entirety"且ise_unite="1"且配合extra_ability参数使用) +英文百分制推荐传参(rst="entirety"且ise_unite="1"且配合extra_ability参数使用) +精简:plain(评测返回结果将只有总分),如: + "entirety" +ise_unite string 否 返回结果控制 +0:不控制(默认值) +1:控制(extra_ability参数将影响全维度等信息的返回) "0" +plev string 否 在rst="entirety"(默认值)且ise_unite="0"(默认值)的情况下plev的取值不同对返回结果有影响。 +plev:0(给出全部信息,汉语包含rec_node_type、perr_msg、fluency_score、phone_score信息的返回;英文包含accuracy_score、serr_msg、 syll_accent、fluency_score、standard_score、pitch信息的返回) "0" +请求参数示例: + +第一次数据发送: + +{ + "common": { + "app_id": "xxxxxxx" + }, + "business": { + "aue": "raw", + "auf": "audio/L16;rate=16000", + "category": "read_sentence", + "cmd": "ssb", + "ent": "en_vip", + "sub": "ise", + "text": "[content]When you don't know what you're doing, it's helpful to begin by learning about what you should not do. ", + "ttp_skip": true + }, + "data": { + "status": 0 + } +} +#请求数据音频参数(data) +参数名 类型 必传 描述 示例 +data string 是 音频数据,base64编码 音频数据,base64编码后作为值 +status string 是 发送数据的状态 +第一次为0 +中间数据为1 +最后一次为2 根据发送数据的状态改变值 +后续数据发送 + +{ + "business": { + "cmd": "auw", + "aus":1 + }, + "data": { + "status": 1, + "data":"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4K" + } +} + +#返回参数 +#请求数据音频返回参数说明 +返回参数名称 类型 描述 +sid string 本次会话的id,同一次会话返回的sid相同 +code int 返回码,0 表示请求成功,遇到其他的错误码时表示请求失败,客户端应该立即断开连接结束会话, +错误码列表详情见错误码 +message string 出错时具体的错误描述类型 +data object 返回的数据 +data.data string 评测结果,base64字符串,解析后为xml格式 +status int 返回结果的状态,当status=2时,表示所有结果全部返回,客户端应该以status=2时的结果为最终结果。 +返回示例: + +{ + "code": 0, + "message": "success", + "sid": "isexxxxxxxxxxxxxxxxxxxxxxxxx", + "data": { + "status": 2, + "data": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KICA8eG1sX3Jlc3VsdD4KICAgICAgPHJlYWRfc2VudGVuY2UgbGFuPSJjbiIgdHlwZT0ic3R1ZHkiIHZlcnNpb249IjcsMCwwLDEwMjQiPgogICAgICAgICAgPHJlY19wYXBlcj4KICAgICAgICAgICAgICA8cmVhZF9zZW50ZW5jZSBhY2N1cmFjeV9zY29yZT0iMTAwLjAwMDAwMCIgYmVnX3Bvcz0iMCIgY29udGVudD0i5LuK5aSp5aSp5rCU5oCO5LmI5qC344CCIiBlbW90aW9uX3Njb3JlPSI4Ny4zMTUzNjEiIGVuZF9wb3M9IjE1MCIgZXhjZXB0X2luZm89IjAiIGZsdWVuY3lfc2NvcmU9Ijg3LjYyMDMwMCIgaW50ZWdyaXR5X3Njb3JlPSIxMDAuMDAwMDAwIiBpc19yZWplY3RlZD0iZmFsc2UiIHBob25lX3Njb3JlPSIxMDAuMDAwMDAwIiB0aW1lX2xlbj0iMTUwIiB0b25lX3Njb3JlPSIxMDAuMDAwMDAwIiB0b3RhbF9zY29yZT0iOTIuNTExMjAwIj4KICAgICAgICAgICAgICAgICAgPHNlbnRlbmNlIGJlZ19wb3M9IjAiIGNvbnRlbnQ9IuS7iuWkqeWkqeawlOaAjuS5iOagtyIgZW5kX3Bvcz0iMTUwIiBmbHVlbmN5X3Njb3JlPSIwLjAwMDAwMCIgcGhvbmVfc2NvcmU9IjEwMC4wMDAwMDAiIHRpbWVfbGVuPSIxNTAiIHRvbmVfc2NvcmU9IjEwMC4wMDAwMDAiIHRvdGFsX3Njb3JlPSI4Ni45NTk5ODQiPgogICAgICAgICAgICAgICAgICAgICAgPHdvcmQgYmVnX3Bvcz0iMCIgY29udGVudD0i5LuKIiBlbmRfcG9zPSIyMiIgc3ltYm9sPSJqaW4xIiB0aW1lX2xlbj0iMjIiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxzeWxsIGJlZ19wb3M9IjAiIGNvbnRlbnQ9ImZpbCIgZHBfbWVzc2FnZT0iMzIiIGVuZF9wb3M9IjEiIHJlY19ub2RlX3R5cGU9ImZpbCIgdGltZV9sZW49IjEiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGhvbmUgYmVnX3Bvcz0iMCIgY29udGVudD0iZmlsIiBkcF9tZXNzYWdlPSIzMiIgZW5kX3Bvcz0iMSIgcmVjX25vZGVfdHlwZT0iZmlsIiB0aW1lX2xlbj0iMSI+PC9waG9uZT4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N5bGw+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPHN5bGwgYmVnX3Bvcz0iMSIgY29udGVudD0i5LuKIiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSIyMiIgcmVjX25vZGVfdHlwZT0icGFwZXIiIHN5bWJvbD0iamluMSIgdGltZV9sZW49IjIxIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBob25lIGJlZ19wb3M9IjEiIGNvbnRlbnQ9ImoiIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9IjQiIGlzX3l1bj0iMCIgcGVycl9sZXZlbF9tc2c9IjIiIHBlcnJfbXNnPSIwIiByZWNfbm9kZV90eXBlPSJwYXBlciIgdGltZV9sZW49IjMiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSI0IiBjb250ZW50PSJpbiIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iMjIiIGlzX3l1bj0iMSIgbW9ub190b25lPSJUT05FMSIgcGVycl9sZXZlbF9tc2c9IjEiIHBlcnJfbXNnPSIwIiByZWNfbm9kZV90eXBlPSJwYXBlciIgdGltZV9sZW49IjE4Ij48L3Bob25lPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3lsbD4KICAgICAgICAgICAgICAgICAgICAgIDwvd29yZD4KICAgICAgICAgICAgICAgICAgICAgIDx3b3JkIGJlZ19wb3M9IjIyIiBjb250ZW50PSLlpKkiIGVuZF9wb3M9IjQwIiBzeW1ib2w9InRpYW4xIiB0aW1lX2xlbj0iMTgiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxzeWxsIGJlZ19wb3M9IjIyIiBjb250ZW50PSLlpKkiIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9IjQwIiByZWNfbm9kZV90eXBlPSJwYXBlciIgc3ltYm9sPSJ0aWFuMSIgdGltZV9sZW49IjE4Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBob25lIGJlZ19wb3M9IjIyIiBjb250ZW50PSJ0IiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSIzMCIgaXNfeXVuPSIwIiBwZXJyX2xldmVsX21zZz0iMSIgcGVycl9tc2c9IjAiIHJlY19ub2RlX3R5cGU9InBhcGVyIiB0aW1lX2xlbj0iOCI+PC9waG9uZT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBob25lIGJlZ19wb3M9IjMwIiBjb250ZW50PSJpYW4iIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9IjQwIiBpc195dW49IjEiIG1vbm9fdG9uZT0iVE9ORTEiIHBlcnJfbGV2ZWxfbXNnPSIxIiBwZXJyX21zZz0iMCIgcmVjX25vZGVfdHlwZT0icGFwZXIiIHRpbWVfbGVuPSIxMCI+PC9waG9uZT4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N5bGw+CiAgICAgICAgICAgICAgICAgICAgICA8L3dvcmQ+CiAgICAgICAgICAgICAgICAgICAgICA8d29yZCBiZWdfcG9zPSI0MCIgY29udGVudD0i5aSpIiBlbmRfcG9zPSI1OCIgc3ltYm9sPSJ0aWFuMSIgdGltZV9sZW49IjE4Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICA8c3lsbCBiZWdfcG9zPSI0MCIgY29udGVudD0i5aSpIiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSI1OCIgcmVjX25vZGVfdHlwZT0icGFwZXIiIHN5bWJvbD0idGlhbjEiIHRpbWVfbGVuPSIxOCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSI0MCIgY29udGVudD0idCIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iNDYiIGlzX3l1bj0iMCIgcGVycl9sZXZlbF9tc2c9IjEiIHBlcnJfbXNnPSIwIiByZWNfbm9kZV90eXBlPSJwYXBlciIgdGltZV9sZW49IjYiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSI0NiIgY29udGVudD0iaWFuIiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSI1OCIgaXNfeXVuPSIxIiBtb25vX3RvbmU9IlRPTkUxIiBwZXJyX2xldmVsX21zZz0iMSIgcGVycl9tc2c9IjAiIHJlY19ub2RlX3R5cGU9InBhcGVyIiB0aW1lX2xlbj0iMTIiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zeWxsPgogICAgICAgICAgICAgICAgICAgICAgPC93b3JkPgogICAgICAgICAgICAgICAgICAgICAgPHdvcmQgYmVnX3Bvcz0iNTgiIGNvbnRlbnQ9IuawlCIgZW5kX3Bvcz0iNzQiIHN5bWJvbD0icWk5IiB0aW1lX2xlbj0iMTYiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxzeWxsIGJlZ19wb3M9IjU4IiBjb250ZW50PSLmsJQiIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9Ijc0IiByZWNfbm9kZV90eXBlPSJwYXBlciIgc3ltYm9sPSJxaTAiIHRpbWVfbGVuPSIxNiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSI1OCIgY29udGVudD0icSIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iNjYiIGlzX3l1bj0iMCIgcGVycl9sZXZlbF9tc2c9IjEiIHBlcnJfbXNnPSIwIiByZWNfbm9kZV90eXBlPSJwYXBlciIgdGltZV9sZW49IjgiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSI2NiIgY29udGVudD0iaSIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iNzQiIGlzX3l1bj0iMSIgbW9ub190b25lPSJUT05FMCIgcGVycl9sZXZlbF9tc2c9IjEiIHBlcnJfbXNnPSIwIiByZWNfbm9kZV90eXBlPSJwYXBlciIgdGltZV9sZW49IjgiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zeWxsPgogICAgICAgICAgICAgICAgICAgICAgPC93b3JkPgogICAgICAgICAgICAgICAgICAgICAgPHdvcmQgYmVnX3Bvcz0iNzQiIGNvbnRlbnQ9IuaAjiIgZW5kX3Bvcz0iODQiIHN5bWJvbD0iemVuMyIgdGltZV9sZW49IjEwIj4KICAgICAgICAgICAgICAgICAgICAgICAgICA8c3lsbCBiZWdfcG9zPSI3NCIgY29udGVudD0i5oCOIiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSI4NCIgcmVjX25vZGVfdHlwZT0icGFwZXIiIHN5bWJvbD0iemVuMyIgdGltZV9sZW49IjEwIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBob25lIGJlZ19wb3M9Ijc0IiBjb250ZW50PSJ6IiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSI3OSIgaXNfeXVuPSIwIiBwZXJyX2xldmVsX21zZz0iMSIgcGVycl9tc2c9IjAiIHJlY19ub2RlX3R5cGU9InBhcGVyIiB0aW1lX2xlbj0iNSI+PC9waG9uZT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBob25lIGJlZ19wb3M9Ijc5IiBjb250ZW50PSJlbiIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iODQiIGlzX3l1bj0iMSIgbW9ub190b25lPSJUT05FMyIgcGVycl9sZXZlbF9tc2c9IjIiIHBlcnJfbXNnPSIwIiByZWNfbm9kZV90eXBlPSJwYXBlciIgdGltZV9sZW49IjUiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zeWxsPgogICAgICAgICAgICAgICAgICAgICAgPC93b3JkPgogICAgICAgICAgICAgICAgICAgICAgPHdvcmQgYmVnX3Bvcz0iODQiIGNvbnRlbnQ9IuS5iCIgZW5kX3Bvcz0iOTMiIHN5bWJvbD0ibWU1IiB0aW1lX2xlbj0iOSI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPHN5bGwgYmVnX3Bvcz0iODQiIGNvbnRlbnQ9IuS5iCIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iOTMiIHJlY19ub2RlX3R5cGU9InBhcGVyIiBzeW1ib2w9Im1lMCIgdGltZV9sZW49IjkiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGhvbmUgYmVnX3Bvcz0iODQiIGNvbnRlbnQ9Im0iIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9Ijg4IiBpc195dW49IjAiIHBlcnJfbGV2ZWxfbXNnPSIxIiBwZXJyX21zZz0iMCIgcmVjX25vZGVfdHlwZT0icGFwZXIiIHRpbWVfbGVuPSI0Ij48L3Bob25lPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGhvbmUgYmVnX3Bvcz0iODgiIGNvbnRlbnQ9ImUiIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9IjkzIiBpc195dW49IjEiIG1vbm9fdG9uZT0iVE9ORTAiIHBlcnJfbGV2ZWxfbXNnPSIxIiBwZXJyX21zZz0iMCIgcmVjX25vZGVfdHlwZT0icGFwZXIiIHRpbWVfbGVuPSI1Ij48L3Bob25lPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3lsbD4KICAgICAgICAgICAgICAgICAgICAgIDwvd29yZD4KICAgICAgICAgICAgICAgICAgICAgIDx3b3JkIGJlZ19wb3M9IjkzIiBjb250ZW50PSLmoLciIGVuZF9wb3M9IjE1MCIgc3ltYm9sPSJ5YW5nNCIgdGltZV9sZW49IjU3Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICA8c3lsbCBiZWdfcG9zPSI5MyIgY29udGVudD0i5qC3IiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSIxMTIiIHJlY19ub2RlX3R5cGU9InBhcGVyIiBzeW1ib2w9Inlhbmc0IiB0aW1lX2xlbj0iMTkiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGhvbmUgYmVnX3Bvcz0iOTMiIGNvbnRlbnQ9Il9pIiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSI5NiIgaXNfeXVuPSIwIiBwZXJyX2xldmVsX21zZz0iMSIgcGVycl9tc2c9IjAiIHJlY19ub2RlX3R5cGU9InBhcGVyIiB0aW1lX2xlbj0iMyI+PC9waG9uZT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBob25lIGJlZ19wb3M9Ijk2IiBjb250ZW50PSJpYW5nIiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSIxMTIiIGlzX3l1bj0iMSIgbW9ub190b25lPSJUT05FNCIgcGVycl9sZXZlbF9tc2c9IjEiIHBlcnJfbXNnPSIwIiByZWNfbm9kZV90eXBlPSJwYXBlciIgdGltZV9sZW49IjE2Ij48L3Bob25lPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3lsbD4KICAgICAgICAgICAgICAgICAgICAgICAgICA8c3lsbCBiZWdfcG9zPSIxMTIiIGNvbnRlbnQ9InNpbCIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iMTUwIiByZWNfbm9kZV90eXBlPSJzaWwiIHRpbWVfbGVuPSIzOCI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSIxMTIiIGNvbnRlbnQ9InNpbCIgZW5kX3Bvcz0iMTUwIiB0aW1lX2xlbj0iMzgiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zeWxsPgogICAgICAgICAgICAgICAgICAgICAgPC93b3JkPgogICAgICAgICAgICAgICAgICA8L3NlbnRlbmNlPgogICAgICAgICAgICAgIDwvcmVhZF9zZW50ZW5jZT4KICAgICAgICAgIDwvcmVjX3BhcGVyPgogICAgICA8L3JlYWRfc2VudGVuY2U+CiAgPC94bWxfcmVzdWx0Pg==" + } +} +#中文评测返回参数说明 +题型 节点 字段信息 +字、词题型(小学、成人) read_syllable +或者 +read_word phone_score:声韵分 +tone_score:调型分 +total_score:总分 【(phone_score + tone_score)/2】 +字、词题型(小学、成人) sentence 无重要信息 +字、词题型(小学、成人) word 无重要信息 +字、词题型(小学、成人) syll dp_message:0正常;16漏读;32增读;64回读;128替换; +字、词题型(小学、成人) phone dp_message:0正常;16漏读;32增读;64回读;128替换(当dp_message不为0时,perr_msg可能出现与dp_message值保持一致的情况); +mono_tone:调型 +perr_level_msg:返回检错结果的置信度(共1,2,3三个数值,1最好,3最差。如果出现为0的情况可以不考虑) +is_yun:0声母,1韵母: +当is_yun=0时:perr_msg有两种状态:0 声母正确 ;1 声母错误 +当is_yun=1时:perr_msg有四种状态:0韵母和调型均正确1韵母错误;2调型错误;3韵母和调型均错误; +句篇题型(小学) read_sentence 或者 read_chapter accuracy_score:准确度 +emotion_score:整体印象分(朗读是否清晰流畅,是否富有感情等) +fluency_score:流畅度分 +integrity_score:完整度分 +phone_score:声韵分 +tone_score:调型分 +total_score:总分【总分 = 准确度分*0.4 + 流畅度分*0.4 + 整体印象分*0.2】 +句篇题型(小学) sentence phone_score:声韵分 +tone_score:调型分 +total_score:总分【模型回归】 +句篇题型(小学) word 无重要信息 +句篇题型(小学) syll dp_message:0正常;16漏读;32增读;64回读;128替换; +句篇题型(小学) phone dp_message:0正常;16漏读;32增读;64回读;128替换(当dp_message不为0时,perr_msg可能出现与dp_message值保持一致的情况); +mono_tone:调型 +perr_level_msg:返回检错结果的置信度(共1,2,3三个数值,1最好,3最差。如果出现为0的情况可以不考虑) +is_yun:0声母,1韵母: +当is_yun=0时:perr_msg有两种状态:0 声母正确 ;1 声母错误 +当is_yun=1时:perr_msg有四种状态:0韵母和调型均正确1韵母错误;2调型错误;3韵母和调型均错误; +句篇题型(成人) read_sentence 或者 read_chapter fluency_score:流畅度分 +integrity_score:完整度分 +phone_score:声韵分 +tone_score:调型分 +total_score:总分【模型回归】 +句篇题型(成人) sentence phone_score:声韵分 +tone_score:调型分 +total_score:总分【模型回归】 +句篇题型(成人) word 无重要信息 +句篇题型(成人) syll dp_message:0正常;16漏读;32增读;64回读;128替换; +句篇题型(成人) phone dp_message:0正常;16漏读;32增读;64回读;128替换(当dp_message不为0时,perr_msg可能出现与dp_message值保持一致的情况); +mono_tone:调型 +perr_level_msg:返回检错结果的置信度(共1,2,3三个数值,1最好,3最差。如果出现为0的情况可以不考虑) +is_yun:0声母,1韵母: +当is_yun=0时:perr_msg有两种状态:0 声母正确 ;1 声母错误 +当is_yun=1时:perr_msg有四种状态:0韵母和调型均正确1韵母错误;2调型错误;3韵母和调型均错误; +#英文评测返回参数说明 +题型 节点 字段信息 +单词题型(成人) read_word 【成人单词】total_score:总分【模型回归】 +单词题型(成人) sentence 无重要信息 +单词题型(成人) word dp_message:0正常;16漏读;32增读;64回读;128替换; +total_score:每个词的分 +单词题型(成人) syll syll_score:每个音节的得分 +serr_msg:音节检错【1或者2049,则表示朗读错误;当serr_msg=2049时,表示音节和重音皆错】 +syll_accent:重读检错【如果为0,表明该音节无需重读,引擎也不做检测;为1,表明该音节需要重读,同时再去解析serr_msg,如果为2048或者2049,则表示朗读错误,效果优化中,可以不关注此情况】 +单词题型(成人) phone dp_message:0正常;16漏读;32增读;64回读;128替换; +句子、篇章题型(成人) read_sentence 或者 read_chapter accuracy_score:准确度分 +standard_score:标准度分 +fluency_score:流利度分 +integrity_score:完整度分 +【成人句子】 +total_score:总分 = (0.6*accuracy_score + fluency_score*0.3 + standard_score*0.1)* integrity_score/100 +【成人篇章】 +total_score:总分 = (0.5*accuracy_score + fluency_score*0.3 + standard_score*0.2)* integrity_score/100 +句子、篇章题型(成人) sentence accuracy_score:准确度分 +standard_score:标准度分 +fluency_score:流利度分 +【成人句子】 +total_score:总分 = (0.6*accuracy_score + fluency_score*0.3 + standard_score*0.1) +【成人篇章】 +total_score:总分 = (0.5*accuracy_score + fluency_score*0.3 + standard_score*0.2) +句子、篇章题型(成人) word dp_message:0正常;16漏读;32增读;64回读;128替换; +total_score:每个词的分 +停顿、连读、重读、句末升降调检错: +1. 将xml中word层property值的2进制与右表中Property值的2进制进行与运算。(效果优化中,无需关注) +2. 如果运算结果与上表Property值相等,说明此处进行了该类型的检测。若运算结果与上表Property值不等,则说明这里未进行任何检测。(效果优化中,无需关注) +3. 判断xml中word层是否出现werr_msg,若未出现,说明朗读正确。(效果优化中,无需关注) +4. 若出现,则将xml中werr_msg的值与上表Werr_msg对应的值进行与运算,若仍等于该类型的值,则说明该类型朗读错误。(效果优化中,无需关注) +句子、篇章题型(成人) syll syll_score:每个音节的得分 +serr_msg:音节检错【1或者2049,则表示朗读错误,效果优化中,可以不关注此情况】 +句子、篇章题型(成人) phone dp_message:0正常;16漏读;32增读;64回读;128替换; +情景反应 rec_paper total_score:总分【模型回归】 +故事复述-topic rec_paper total_score:总分【模型回归】 +复述题、口头翻译、要点题、看图说话 rec_paper accuracy_score:准确度分 +standard_score:标准度分 +fluency_score:流利度分 +integrity_score:完整度分 +total_score:总分【模型回归】 +口头作文 rec_paper total_score:总分【模型回归】 +# \ No newline at end of file diff --git a/dsLightRag/KeDaXunFei/文档.txt b/dsLightRag/KeDaXunFei/文档.txt new file mode 100644 index 00000000..e8d6d8db --- /dev/null +++ b/dsLightRag/KeDaXunFei/文档.txt @@ -0,0 +1,8 @@ +Websocket服务接口认证信息 +APPID +5b83f8d6 +APISecret +604fa6cb9c5ab664a0d153fe0ccc6802 +APIKey +5beb887923204000bfcb402046bb05a6 +*SDK调用方式只需APPID。APIKey或APISecret适用于WebAPI调用方式。 \ No newline at end of file diff --git a/dsLightRag/KeDaXunFei/评测结果.txt b/dsLightRag/KeDaXunFei/评测结果.txt new file mode 100644 index 00000000..a4be9c77 --- /dev/null +++ b/dsLightRag/KeDaXunFei/评测结果.txt @@ -0,0 +1,55 @@ +D:\anaconda3\envs\py310\python.exe D:\dsWork\dsProject\dsLightRag\KeDaXunFei\TestAudio.py +AnOp6W+XdH5vjjQRb+NQDtPD02VqtNCkfz8jAdi/rPI= +YXBpX2tleT0iNWJlYjg4NzkyMzIwNDAwMGJmY2I0MDIwNDZiYjA1YTYiLCBhbGdvcml0aG09ImhtYWMtc2hhMjU2IiwgaGVhZGVycz0iaG9zdCBkYXRlIHJlcXVlc3QtbGluZSIsIHNpZ25hdHVyZT0iQW5PcDZXK1hkSDV2ampRUmIrTlFEdFBEMDJWcXROQ2tmejhqQWRpL3JQST0i +WebSocket connection opened,,ws连接建立成功... +发送最后一帧 +Received message: {"code":0,"message":"success","sid":"ise000d05f4@gz19919aba9995095812","data":{"status":1,"data":null}} +Received message: {"code":0,"message":"success","sid":"ise000d05f4@gz19919aba9995095812","data":{"status":1,"data":null}} +Received message: {"code":0,"message":"success","sid":"ise000d05f4@gz19919aba9995095812","data":{"data":null,"status":1}} +Received message: {"code":0,"message":"success","sid":"ise000d05f4@gz19919aba9995095812","data":{"status":1,"data":null}} +Received message: {"code":0,"message":"success","sid":"ise000d05f4@gz19919aba9995095812","data":{"status":1,"data":null}} +Received message: {"code":0,"message":"success","sid":"ise000d05f4@gz19919aba9995095812","data":{"data":null,"status":1}} +Received message: {"code":0,"message":"success","sid":"ise000d05f4@gz19919aba9995095812","data":{"status":1,"data":null}} +Received message: {"code":0,"message":"success","sid":"ise000d05f4@gz19919aba9995095812","data":{"status":1,"data":null}} +Received message: {"code":0,"message":"success","sid":"ise000d05f4@gz19919aba9995095812","data":{"status":2,"data":"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KICA8eG1sX3Jlc3VsdD4KICAgICAgPHJlYWRfc2VudGVuY2UgbGFuPSJlbiIgdHlwZT0ic3R1ZHkiIHZlcnNpb249IjcuMC4wLjEwMjAiPgogICAgICAgICAgPHJlY19wYXBlcj4KICAgICAgICAgICAgICA8cmVhZF9jaGFwdGVyIGFjY3VyYWN5X3Njb3JlPSI0Ljk5MTkxNSIgYmVnX3Bvcz0iMCIgY29udGVudD0ibmljZSB0byBtZWV0IHlvdS4iIGVuZF9wb3M9IjI0NiIgZXhjZXB0X2luZm89IjAiIGZsdWVuY3lfc2NvcmU9IjUuMDAwMDAwIiBpbnRlZ3JpdHlfc2NvcmU9IjUuMDAwMDAwIiBpc19yZWplY3RlZD0iZmFsc2UiIHJlamVjdF90eXBlPSIwIiBzY29yZV9wYXR0ZXJuPSJsb29zZSIgc3RhbmRhcmRfc2NvcmU9IjQuNDE1MTQyIiB0b3RhbF9zY29yZT0iNC45OTQzNDEiIHdvcmRfY291bnQ9IjQiPgogICAgICAgICAgICAgICAgICA8c2VudGVuY2UgYWNjdXJhY3lfc2NvcmU9IjQuNzQxOTE1IiBiZWdfcG9zPSIwIiBjb250ZW50PSJuaWNlIHRvIG1lZXQgeW91IiBlbmRfcG9zPSIyNDYiIGZsdWVuY3lfc2NvcmU9IjQuODI2MTA5IiBpbmRleD0iMCIgc3RhbmRhcmRfc2NvcmU9IjQuMTY1MTQyIiB0b3RhbF9zY29yZT0iNC43NjcxNzMiIHdvcmRfY291bnQ9IjQiPgogICAgICAgICAgICAgICAgICAgICAgPHdvcmQgYmVnX3Bvcz0iMzgiIGNvbnRlbnQ9Im5pY2UiIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9Ijk2IiBnbG9iYWxfaW5kZXg9IjAiIGluZGV4PSIwIiBwaXRjaD0iICAxMjkuMjYgIDEyOS4yNiAgMTI4LjQ3ICAxMjkuMjMgIDEzMC41MSAgMTMxLjU0ICAxMzIuNjYgIDEzMy42MyAgMTM1LjA5ICAxMzYuNTQgIDEzNy45NSAgMTM5LjE2ICAxNDAuMTIgIDE0MS4xOCAgMTQyLjIzICAxNDMuMTQgIDE0My42NSAgMTQzLjUxICAxNDMuMTcgIDE0My43NCAgMTQ1LjYyIiBwaXRjaF9iZWc9IjYxIiBwaXRjaF9lbmQ9IjgyIiBwcm9wZXJ0eT0iMCIgdG90YWxfc2NvcmU9IjQuODQ2OTA1Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICA8c3lsbCBiZWdfcG9zPSIzOCIgY29udGVudD0ibiBheSBzIiBlbmRfcG9zPSI5NiIgc2Vycl9tc2c9IjAiIHN5bGxfYWNjZW50PSIwIiBzeWxsX3Njb3JlPSI0LjY0MTkzNiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSIzOCIgY29udGVudD0ibiIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iNjIiIGd3cHA9Ii0wLjQ2MDU3MCI+PC9waG9uZT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBob25lIGJlZ19wb3M9IjYyIiBjb250ZW50PSJheSIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iODAiIGd3cHA9Ii0wLjAwMTExOCI+PC9waG9uZT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBob25lIGJlZ19wb3M9IjgwIiBjb250ZW50PSJzIiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSI5NiIgZ3dwcD0iLTAuNDg2NTAyIj48L3Bob25lPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3lsbD4KICAgICAgICAgICAgICAgICAgICAgIDwvd29yZD4KICAgICAgICAgICAgICAgICAgICAgIDx3b3JkIGJlZ19wb3M9Ijk2IiBjb250ZW50PSJ0byIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iMTE5IiBnbG9iYWxfaW5kZXg9IjEiIGluZGV4PSIxIiBwaXRjaD0iICAxMjguNzggIDEyOC43OCAgMTI5LjcwICAxMzIuNTMgIDEzMi45MSAgMTMyLjQ0ICAxMzEuMDAgIDEyOS42OCAgMTI2LjIxICAxMjUuNDQgIDEyNi45MCAgMTMxLjE5IiBwaXRjaF9iZWc9IjEwNyIgcGl0Y2hfZW5kPSIxMTkiIHByb3BlcnR5PSIwIiB0b3RhbF9zY29yZT0iNC44ODExNjYiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxzeWxsIGJlZ19wb3M9Ijk2IiBjb250ZW50PSJ0IHV3IiBlbmRfcG9zPSIxMTkiIHNlcnJfbXNnPSIwIiBzeWxsX2FjY2VudD0iMCIgc3lsbF9zY29yZT0iNC43ODUyMTgiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGhvbmUgYmVnX3Bvcz0iOTYiIGNvbnRlbnQ9InQiIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9IjEwOSIgZ3dwcD0iLTAuMjA3MTk0Ij48L3Bob25lPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGhvbmUgYmVnX3Bvcz0iMTA5IiBjb250ZW50PSJ1dyIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iMTE5IiBnd3BwPSItMC40NTMxOTUiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zeWxsPgogICAgICAgICAgICAgICAgICAgICAgPC93b3JkPgogICAgICAgICAgICAgICAgICAgICAgPHdvcmQgYmVnX3Bvcz0iMTE5IiBjb250ZW50PSJtZWV0IiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSIxNDYiIGdsb2JhbF9pbmRleD0iMiIgaW5kZXg9IjIiIHBpdGNoPSIgIDEzMi43MSAgMTMyLjcxICAxMzMuMDUgIDEzMy44MiAgMTM0LjY0ICAxMzUuNTggIDEzNy4wMyAgMTM4LjI1ICAxMzkuMzMgIDEzOS43MiAgMTQwLjIyICAxNDAuNjkgIDE0MC44MSAgMTQwLjYxICAxMzguMDYgIDEzNS44NSAgMTMxLjk3ICAxMzEuMTAgIDEzMC44NSAgMTMzLjIyICAxMzUuNjAgIDEzNy45OCAgMTM3LjQ4ICAxMzUuMzMgIDEzMS4zMiAgMTI4LjUxICAxMjUuNjgiIHBpdGNoX2JlZz0iMTE5IiBwaXRjaF9lbmQ9IjE0NiIgcHJvcGVydHk9IjAiIHRvdGFsX3Njb3JlPSI0Ljk2MzE3NyI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgPHN5bGwgYmVnX3Bvcz0iMTE5IiBjb250ZW50PSJtIGl5IHQiIGVuZF9wb3M9IjE0NiIgc2Vycl9tc2c9IjAiIHN5bGxfYWNjZW50PSIwIiBzeWxsX3Njb3JlPSI0Ljk5NzM2NiI+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSIxMTkiIGNvbnRlbnQ9Im0iIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9IjEyNiIgZ3dwcD0iLTAuMDAyMTkyIj48L3Bob25lPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGhvbmUgYmVnX3Bvcz0iMTI2IiBjb250ZW50PSJpeSIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iMTM2IiBnd3BwPSItMC4wMDAwMzgiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSIxMzYiIGNvbnRlbnQ9InQiIGRwX21lc3NhZ2U9IjAiIGVuZF9wb3M9IjE0NiIgZ3dwcD0iLTAuMDA2MDk3Ij48L3Bob25lPgogICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3lsbD4KICAgICAgICAgICAgICAgICAgICAgIDwvd29yZD4KICAgICAgICAgICAgICAgICAgICAgIDx3b3JkIGJlZ19wb3M9IjE0NiIgY29udGVudD0ieW91IiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSIxNzIiIGdsb2JhbF9pbmRleD0iMyIgaW5kZXg9IjMiIHBpdGNoPSIgIDEyMi41NSAgMTIyLjU1ICAxMjEuNzMgIDEyMS4yNyAgMTIxLjE2ICAxMjAuODcgIDEyMC40NyAgMTIwLjE4ICAxMjAuMTcgIDEyMC41OCAgMTIxLjI0ICAxMjIuMDYgIDEyMi43MyAgMTIzLjE3ICAxMjMuMzIgIDEyMy4yMCAgMTIyLjg5ICAxMjIuMTIgIDEyMS4yMCAgMTE5LjQ4ICAxMTcuMzYgIDExNS4yMyAgMTEzLjczIiBwaXRjaF9iZWc9IjE0NiIgcGl0Y2hfZW5kPSIxNjkiIHByb3BlcnR5PSIwIiB0b3RhbF9zY29yZT0iNC45NjM4NzgiPgogICAgICAgICAgICAgICAgICAgICAgICAgIDxzeWxsIGJlZ19wb3M9IjE0NiIgY29udGVudD0ieSB1dyIgZW5kX3Bvcz0iMTcyIiBzZXJyX21zZz0iMCIgc3lsbF9hY2NlbnQ9IjAiIHN5bGxfc2NvcmU9IjQuOTk5MzIxIj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBob25lIGJlZ19wb3M9IjE0NiIgY29udGVudD0ieSIgZHBfbWVzc2FnZT0iMCIgZW5kX3Bvcz0iMTY2IiBnd3BwPSItMC4wMDAzMDUiPjwvcGhvbmU+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwaG9uZSBiZWdfcG9zPSIxNjYiIGNvbnRlbnQ9InV3IiBkcF9tZXNzYWdlPSIwIiBlbmRfcG9zPSIxNzIiIGd3cHA9Ii0wLjAwMjA3NCI+PC9waG9uZT4KICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N5bGw+CiAgICAgICAgICAgICAgICAgICAgICA8L3dvcmQ+CiAgICAgICAgICAgICAgICAgIDwvc2VudGVuY2U+CiAgICAgICAgICAgICAgPC9yZWFkX2NoYXB0ZXI+CiAgICAgICAgICA8L3JlY19wYXBlcj4KICAgICAgPC9yZWFkX3NlbnRlbmNlPgogIDwveG1sX3Jlc3VsdD4="}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +WebSocket connection closed, +评测耗时: 0:00:01.489215 + +进程已结束,退出代码为 0 \ No newline at end of file diff --git a/dsLightRag/Routes/XunFeiRoute.py b/dsLightRag/Routes/XunFeiRoute.py new file mode 100644 index 00000000..e914d1d0 --- /dev/null +++ b/dsLightRag/Routes/XunFeiRoute.py @@ -0,0 +1,140 @@ +import logging +import os +import uuid +import time +from fastapi import APIRouter, HTTPException, BackgroundTasks, Query, UploadFile, File +from pydantic import BaseModel +from typing import Optional +import tempfile +from Util.ObsUtil import ObsUploader +from Config.Config import OBS_BUCKET, OBS_SERVER +from fastapi.responses import StreamingResponse +import requests + +# 导入讯飞语音评测类 +from KeDaXunFei.XunFeiAudioEvaluator import XunFeiAudioEvaluator + +# 配置日志 +logger = logging.getLogger(__name__) +router = APIRouter(prefix="/api/xunFei", tags=["讯飞"]) + +# 请求模型 +class AudioEvaluationRequest(BaseModel): + language: str = "chinese" # chinese 或 english + text: str # 评测文本内容 + group: Optional[str] = "adult" # 群体:adult, youth, pupil + check_type: Optional[str] = "common" # 检错严格程度:easy, common, hard + grade: Optional[str] = "middle" # 学段:junior, middle, senior + +# 响应模型 +class AudioEvaluationResponse(BaseModel): + evaluation_id: str + status: str + results: Optional[dict] = None + evaluation_time: Optional[float] = None + error_message: Optional[str] = None + +# 科大讯飞API配置(需要根据实际情况配置) +XUNFEI_CONFIG = { + "appid": "your_appid_here", + "api_key": "your_api_key_here", + "api_secret": "your_api_secret_here" +} + +@router.post("/evaluate-audio", response_model=AudioEvaluationResponse) +async def evaluate_audio( + background_tasks: BackgroundTasks, + language: str = Query("chinese", description="评测语言: chinese 或 english"), + text: str = Query(..., description="评测文本内容"), + group: str = Query("adult", description="群体类型: adult, youth, pupil"), + check_type: str = Query("common", description="检错严格程度: easy, common, hard"), + grade: str = Query("middle", description="学段: junior, middle, senior"), + audio_file: UploadFile = File(...)): + """ + 语音评测接口 - 支持中文和英文篇章朗读判分 + """ + try: + # 验证语言参数 + if language not in ["chinese", "english"]: + raise HTTPException(status_code=400, detail="language参数必须是'chinese'或'english'") + + # 验证群体参数 + if group not in ["adult", "youth", "pupil"]: + raise HTTPException(status_code=400, detail="group参数必须是'adult', 'youth'或'pupil'") + + # 创建临时文件保存上传的音频 + with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as temp_audio: + audio_content = await audio_file.read() + temp_audio.write(audio_content) + temp_audio_path = temp_audio.name + + # 创建评测器实例 + evaluator = XunFeiAudioEvaluator( + appid=XUNFEI_CONFIG["appid"], + api_key=XUNFEI_CONFIG["api_key"], + api_secret=XUNFEI_CONFIG["api_secret"], + audio_file=temp_audio_path + ) + + # 根据语言设置不同的评测参数 + if language == "chinese": + # 中文评测配置 + evaluator.business_params = { + "category": "read_chapter", + "ent": "cn_vip", + "group": group, + "check_type": check_type, + "grade": grade, + "text": '\uFEFF' + f"[content]\n{text}" + } + else: + # 英文评测配置 + evaluator.business_params = { + "category": "read_chapter", + "ent": "en_vip", + "text": '\uFEFF' + f"[content]\n{text}" + } + + # 运行评测 + results, eval_time = evaluator.run_evaluation() + + # 清理临时文件 + os.unlink(temp_audio_path) + + # 生成评测ID + evaluation_id = str(uuid.uuid4()) + + return AudioEvaluationResponse( + evaluation_id=evaluation_id, + status="success", + results=results, + evaluation_time=eval_time.total_seconds() if eval_time else None + ) + + except Exception as e: + logger.error(f"语音评测失败: {str(e)}") + # 确保临时文件被清理 + if 'temp_audio_path' in locals() and os.path.exists(temp_audio_path): + os.unlink(temp_audio_path) + + return AudioEvaluationResponse( + evaluation_id=str(uuid.uuid4()), + status="error", + error_message=f"评测失败: {str(e)}" + ) + +@router.get("/evaluation-result/{evaluation_id}") +async def get_evaluation_result(evaluation_id: str): + """ + 获取评测结果(示例接口,实际需要实现结果存储) + """ + # 这里需要实现从数据库或缓存中获取评测结果 + # 目前返回示例数据 + return { + "evaluation_id": evaluation_id, + "status": "completed", + "message": "请实现结果存储逻辑" + } + +# 需要修改XunFeiAudioEvaluator类以支持参数配置 +# 在XunFeiAudioEvaluator类中添加business_params属性并在on_open方法中使用 \ No newline at end of file diff --git a/dsLightRag/Routes/__pycache__/XunFeiRoute.cpython-310.pyc b/dsLightRag/Routes/__pycache__/XunFeiRoute.cpython-310.pyc new file mode 100644 index 00000000..c09079bd Binary files /dev/null and b/dsLightRag/Routes/__pycache__/XunFeiRoute.cpython-310.pyc differ diff --git a/dsLightRag/Start.py b/dsLightRag/Start.py index 3b6e8b90..f8134e31 100644 --- a/dsLightRag/Start.py +++ b/dsLightRag/Start.py @@ -32,6 +32,7 @@ from Routes.ttsRoute import router as tts_router from Routes.CopyFaceRoute import router as copyFace_router from Routes.WenShengTu import router as wenshengtu_router from Routes.TeacherHelperRoute import router as teacherHelper_router +from Routes.XunFeiRoute import router as xunfei_router # 控制日志输出 logger = logging.getLogger('lightrag') logger.setLevel(logging.INFO) @@ -90,6 +91,7 @@ app.include_router(tts_router) # 文本转语音 app.include_router(copyFace_router) # 抄脸 app.include_router(wenshengtu_router) # 文生图 app.include_router(teacherHelper_router) # 教师助手 +app.include_router(xunfei_router) # 讯飞 # Teaching Model 相关路由 # 登录相关(不用登录) diff --git a/dsLightRag/static/XunFei/audio_evaluation.html b/dsLightRag/static/XunFei/audio_evaluation.html new file mode 100644 index 00000000..eb9ea657 --- /dev/null +++ b/dsLightRag/static/XunFei/audio_evaluation.html @@ -0,0 +1,318 @@ + + + + + + 语音评测系统 + + + +
+

语音评测系统

+ +
+ + +
+ +
+ + +
+ +
+ + + +
+ +
准备就绪
+ + +
+ + + + \ No newline at end of file