mirror of
https://github.com/langgenius/dify.git
synced 2024-11-16 11:42:29 +08:00
feat: add tencent asr (#6091)
This commit is contained in:
parent
f17d4fe412
commit
7c55c39085
|
@ -23,6 +23,7 @@
|
|||
- tongyi
|
||||
- wenxin
|
||||
- moonshot
|
||||
- tencent
|
||||
- jina
|
||||
- chatglm
|
||||
- yi
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<svg viewBox="0 83.15545000000002 402.45098039215685 76.44" data-name="图层 1" id="图层_1"
|
||||
xmlns="http://www.w3.org/2000/svg" style="max-height: 500px" width="402.45098039215685"
|
||||
height="76.44">
|
||||
<defs>
|
||||
<style>.cls-1{fill:#4999d4}</style>
|
||||
</defs>
|
||||
<title>tencent-cloud</title>
|
||||
<path
|
||||
d="M27.569 113.353a17.56 17.56 0 0 1 33.148-3.743.158.158 0 0 0 .194.105 21.267 21.267 0 0 1 7.008-.729c.235.018.327-.116.25-.33a24.828 24.828 0 0 0-47.933 4.444.082.082 0 0 0 .016 0 18.537 18.537 0 0 0-9.85 31.533 18.007 18.007 0 0 0 10.325 5h-.001a43.066 43.066 0 0 0 5.266.282c1.68.011 33.725.008 35.067.008 2.7 0 4.457-.002 6.345-.14a18.245 18.245 0 0 0 11.723-5.15 18.532 18.532 0 0 0-12.901-31.789 18.06 18.06 0 0 0-11.704 4.285c-1.467 1.196-3.006 2.626-4.944 4.508-.642.625-13.336 12.94-21.67 21.028-1.16-.005-2.828-.021-4.306-.07a11.704 11.704 0 0 1-8.125-3.148A11.275 11.275 0 0 1 23.33 120.1a11.706 11.706 0 0 1 7.646 3.062c1.44 1.192 4.633 4 6.035 5.263a.17.17 0 0 0 .24.002l4.945-4.825a.176.176 0 0 0-.004-.27c-2.378-2.15-5.749-5.158-7.778-6.669a18.874 18.874 0 0 0-6.844-3.31zm46.482 26.094a11.704 11.704 0 0 1-8.125 3.147 168.92 168.92 0 0 1-5.204.073h-22.38c8.142-7.91 15.245-14.808 16.051-15.59.738-.717 2.398-2.306 3.83-3.595 3.145-2.831 5.974-3.4 7.976-3.382a11.275 11.275 0 0 1 7.852 19.347z"
|
||||
class="cls-1" />
|
||||
<path
|
||||
d="M302.794 129.138a.24.24 0 0 0-.419-.163 16.062 16.062 0 0 1-11.961 5.469c-7.7 0-12.674-5.32-12.674-13.552 0-8.388 4.74-13.599 12.37-13.599a17.274 17.274 0 0 1 11.828 4.996.24.24 0 0 0 .414-.168v-4.245a18.595 18.595 0 0 0-12.243-4.502 15.358 15.358 0 0 0-11.733 4.845c-2.857 3.138-4.366 7.52-4.366 12.674 0 10.478 6.592 17.518 16.404 17.518a18.517 18.517 0 0 0 12.38-4.624zM93.47 104.248v3.638h11.506v29.657h3.982v-29.657h11.506v-3.638H93.47zM390.972 115.625c-2.059-2.232-5.501-3.043-7.978-3.043a11.24 11.24 0 0 0-8.363 3.475 13.26 13.26 0 0 0-3.277 9.243c0 8.883 5.894 12.86 11.735 12.86 3.412 0 6.228-1.22 7.883-3.38v2.812h3.971V104.3h-3.97zm-.105 9.769c0 4.545-2.639 9.147-7.683 9.147-3.788 0-7.865-2.803-7.865-8.958 0-4.522 2.388-9.389 7.63-9.389 5.844 0 7.918 4.956 7.918 9.2zM308.064 104.3h4.031v33.292h-4.031zM192.033 131.427a.24.24 0 0 0-.403-.18 13.772 13.772 0 0 1-8.006 3.255c-5.344 0-8.796-3.583-8.796-9.128 0-5.546 3.452-9.129 8.796-9.129a12.973 12.973 0 0 1 8.01 2.8.24.24 0 0 0 .399-.183v-3.668a17.567 17.567 0 0 0-8.621-2.615c-7.38 0-12.34 5.142-12.34 12.795 0 7.652 4.96 12.794 12.34 12.794a14.903 14.903 0 0 0 8.62-2.624zM139.984 130.642a.241.241 0 0 0-.436-.143 12.896 12.896 0 0 1-8.605 4.214 8.725 8.725 0 0 1-6.104-2.141 8.634 8.634 0 0 1-2.372-6.07h18.629v-.285c0-5.254-.896-8.233-3.194-10.625a10.42 10.42 0 0 0-7.849-3.01c-6.969 0-11.472 4.987-11.471 12.715.254 8.04 4.822 12.84 12.218 12.84a13.447 13.447 0 0 0 9.184-3.52zm-2.653-7.564h-14.872l.006-.075a7.37 7.37 0 0 1 7.481-6.93c4.341 0 7.17 2.657 7.38 6.933zM362.877 125.584c0 6.632-3.825 8.985-7.1 8.985a6.287 6.287 0 0 1-6.549-6.263V113.15h-3.79v15.088c0 5.842 4.172 9.922 10.145 9.922 3.308 0 5.89-1.114 7.53-3.235v2.66h3.614V113.15h-3.85zM156.747 112.583a9.79 9.79 0 0 0-7.364 2.887v-2.334h-3.762v24.456h3.846v-13.935a7.592 7.592 0 0 1 1.982-5.51 6.75 6.75 0 0 1 5.197-1.91 5.994 5.994 0 0 1 6.055 6.339v15.016h3.847v-15.197a9.756 9.756 0 0 0-2.767-7.26 9.907 9.907 0 0 0-7.034-2.552zM217.156 130.642a.241.241 0 0 0-.436-.143 12.896 12.896 0 0 1-8.605 4.214 8.725 8.725 0 0 1-6.104-2.141 8.634 8.634 0 0 1-2.372-6.07h18.629v-.285c0-5.254-.895-8.233-3.193-10.625a10.42 10.42 0 0 0-7.85-3.01c-6.968 0-11.471 4.987-11.471 12.715.254 8.04 4.822 12.84 12.218 12.84a13.447 13.447 0 0 0 9.184-3.52zm-2.653-7.564h-14.871l.005-.075a7.37 7.37 0 0 1 7.481-6.93c4.342 0 7.17 2.657 7.381 6.933zM233.857 112.583a9.79 9.79 0 0 0-7.365 2.887v-2.334h-3.762v24.456h3.847v-13.935a7.592 7.592 0 0 1 1.982-5.51 6.75 6.75 0 0 1 5.196-1.91 5.994 5.994 0 0 1 6.056 6.339v15.016h3.846v-15.197a9.756 9.756 0 0 0-2.767-7.26 9.907 9.907 0 0 0-7.033-2.552zM256.236 137.917a19.963 19.963 0 0 0 5.009-1.138v-3.683a.241.241 0 0 0-.321-.229A29.455 29.455 0 0 1 256.8 134c-.402.064-.756.12-1.02-.104a.897.897 0 0 1-.263-.777V116.69h7.04v-3.559h-7.04v-6.516h-3.997v6.516h-4.012v3.558h4.012v16.815a4.207 4.207 0 0 0 1.309 3.327 5.088 5.088 0 0 0 3.406 1.085zM329.224 112.63c-7.093 0-11.859 5.13-11.859 12.764s4.766 12.764 11.859 12.764 11.858-5.13 11.858-12.764-4.765-12.764-11.858-12.764zm-8.18 12.739l-.001-.01c.014-5.41 3.299-9.043 8.18-9.043 4.893 0 8.18 3.648 8.182 9.078-.002 5.429-3.29 9.078-8.181 9.078-4.89 0-8.175-3.678-8.18-9.103z" />
|
||||
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
|
@ -0,0 +1,13 @@
|
|||
<svg viewBox="0 83.15545000000002 402.45098039215685 76.44" data-name="图层 1" id="图层_1"
|
||||
xmlns="http://www.w3.org/2000/svg" style="max-height: 500px" width="402.45098039215685"
|
||||
height="76.44">
|
||||
<defs>
|
||||
<style>.cls-1{fill:#4999d4}</style>
|
||||
</defs>
|
||||
<title>tencent-cloud</title>
|
||||
<path
|
||||
d="M27.569 113.353a17.56 17.56 0 0 1 33.148-3.743.158.158 0 0 0 .194.105 21.267 21.267 0 0 1 7.008-.729c.235.018.327-.116.25-.33a24.828 24.828 0 0 0-47.933 4.444.082.082 0 0 0 .016 0 18.537 18.537 0 0 0-9.85 31.533 18.007 18.007 0 0 0 10.325 5h-.001a43.066 43.066 0 0 0 5.266.282c1.68.011 33.725.008 35.067.008 2.7 0 4.457-.002 6.345-.14a18.245 18.245 0 0 0 11.723-5.15 18.532 18.532 0 0 0-12.901-31.789 18.06 18.06 0 0 0-11.704 4.285c-1.467 1.196-3.006 2.626-4.944 4.508-.642.625-13.336 12.94-21.67 21.028-1.16-.005-2.828-.021-4.306-.07a11.704 11.704 0 0 1-8.125-3.148A11.275 11.275 0 0 1 23.33 120.1a11.706 11.706 0 0 1 7.646 3.062c1.44 1.192 4.633 4 6.035 5.263a.17.17 0 0 0 .24.002l4.945-4.825a.176.176 0 0 0-.004-.27c-2.378-2.15-5.749-5.158-7.778-6.669a18.874 18.874 0 0 0-6.844-3.31zm46.482 26.094a11.704 11.704 0 0 1-8.125 3.147 168.92 168.92 0 0 1-5.204.073h-22.38c8.142-7.91 15.245-14.808 16.051-15.59.738-.717 2.398-2.306 3.83-3.595 3.145-2.831 5.974-3.4 7.976-3.382a11.275 11.275 0 0 1 7.852 19.347z"
|
||||
class="cls-1" />
|
||||
<path
|
||||
d="M302.794 129.138a.24.24 0 0 0-.419-.163 16.062 16.062 0 0 1-11.961 5.469c-7.7 0-12.674-5.32-12.674-13.552 0-8.388 4.74-13.599 12.37-13.599a17.274 17.274 0 0 1 11.828 4.996.24.24 0 0 0 .414-.168v-4.245a18.595 18.595 0 0 0-12.243-4.502 15.358 15.358 0 0 0-11.733 4.845c-2.857 3.138-4.366 7.52-4.366 12.674 0 10.478 6.592 17.518 16.404 17.518a18.517 18.517 0 0 0 12.38-4.624zM93.47 104.248v3.638h11.506v29.657h3.982v-29.657h11.506v-3.638H93.47zM390.972 115.625c-2.059-2.232-5.501-3.043-7.978-3.043a11.24 11.24 0 0 0-8.363 3.475 13.26 13.26 0 0 0-3.277 9.243c0 8.883 5.894 12.86 11.735 12.86 3.412 0 6.228-1.22 7.883-3.38v2.812h3.971V104.3h-3.97zm-.105 9.769c0 4.545-2.639 9.147-7.683 9.147-3.788 0-7.865-2.803-7.865-8.958 0-4.522 2.388-9.389 7.63-9.389 5.844 0 7.918 4.956 7.918 9.2zM308.064 104.3h4.031v33.292h-4.031zM192.033 131.427a.24.24 0 0 0-.403-.18 13.772 13.772 0 0 1-8.006 3.255c-5.344 0-8.796-3.583-8.796-9.128 0-5.546 3.452-9.129 8.796-9.129a12.973 12.973 0 0 1 8.01 2.8.24.24 0 0 0 .399-.183v-3.668a17.567 17.567 0 0 0-8.621-2.615c-7.38 0-12.34 5.142-12.34 12.795 0 7.652 4.96 12.794 12.34 12.794a14.903 14.903 0 0 0 8.62-2.624zM139.984 130.642a.241.241 0 0 0-.436-.143 12.896 12.896 0 0 1-8.605 4.214 8.725 8.725 0 0 1-6.104-2.141 8.634 8.634 0 0 1-2.372-6.07h18.629v-.285c0-5.254-.896-8.233-3.194-10.625a10.42 10.42 0 0 0-7.849-3.01c-6.969 0-11.472 4.987-11.471 12.715.254 8.04 4.822 12.84 12.218 12.84a13.447 13.447 0 0 0 9.184-3.52zm-2.653-7.564h-14.872l.006-.075a7.37 7.37 0 0 1 7.481-6.93c4.341 0 7.17 2.657 7.38 6.933zM362.877 125.584c0 6.632-3.825 8.985-7.1 8.985a6.287 6.287 0 0 1-6.549-6.263V113.15h-3.79v15.088c0 5.842 4.172 9.922 10.145 9.922 3.308 0 5.89-1.114 7.53-3.235v2.66h3.614V113.15h-3.85zM156.747 112.583a9.79 9.79 0 0 0-7.364 2.887v-2.334h-3.762v24.456h3.846v-13.935a7.592 7.592 0 0 1 1.982-5.51 6.75 6.75 0 0 1 5.197-1.91 5.994 5.994 0 0 1 6.055 6.339v15.016h3.847v-15.197a9.756 9.756 0 0 0-2.767-7.26 9.907 9.907 0 0 0-7.034-2.552zM217.156 130.642a.241.241 0 0 0-.436-.143 12.896 12.896 0 0 1-8.605 4.214 8.725 8.725 0 0 1-6.104-2.141 8.634 8.634 0 0 1-2.372-6.07h18.629v-.285c0-5.254-.895-8.233-3.193-10.625a10.42 10.42 0 0 0-7.85-3.01c-6.968 0-11.471 4.987-11.471 12.715.254 8.04 4.822 12.84 12.218 12.84a13.447 13.447 0 0 0 9.184-3.52zm-2.653-7.564h-14.871l.005-.075a7.37 7.37 0 0 1 7.481-6.93c4.342 0 7.17 2.657 7.381 6.933zM233.857 112.583a9.79 9.79 0 0 0-7.365 2.887v-2.334h-3.762v24.456h3.847v-13.935a7.592 7.592 0 0 1 1.982-5.51 6.75 6.75 0 0 1 5.196-1.91 5.994 5.994 0 0 1 6.056 6.339v15.016h3.846v-15.197a9.756 9.756 0 0 0-2.767-7.26 9.907 9.907 0 0 0-7.033-2.552zM256.236 137.917a19.963 19.963 0 0 0 5.009-1.138v-3.683a.241.241 0 0 0-.321-.229A29.455 29.455 0 0 1 256.8 134c-.402.064-.756.12-1.02-.104a.897.897 0 0 1-.263-.777V116.69h7.04v-3.559h-7.04v-6.516h-3.997v6.516h-4.012v3.558h4.012v16.815a4.207 4.207 0 0 0 1.309 3.327 5.088 5.088 0 0 0 3.406 1.085zM329.224 112.63c-7.093 0-11.859 5.13-11.859 12.764s4.766 12.764 11.859 12.764 11.858-5.13 11.858-12.764-4.765-12.764-11.858-12.764zm-8.18 12.739l-.001-.01c.014-5.41 3.299-9.043 8.18-9.043 4.893 0 8.18 3.648 8.182 9.078-.002 5.429-3.29 9.078-8.181 9.078-4.89 0-8.175-3.678-8.18-9.103z" />
|
||||
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
|
@ -0,0 +1,11 @@
|
|||
<svg viewBox="0 83.15545000000002 85 76.44" data-name="图层 1" id="图层_1"
|
||||
xmlns="http://www.w3.org/2000/svg" style="max-height: 500px" width="85"
|
||||
height="76.44">
|
||||
<defs>
|
||||
<style>.cls-1{fill:#4999d4}</style>
|
||||
</defs>
|
||||
<title>tencent-cloud</title>
|
||||
<path
|
||||
d="M27.569 113.353a17.56 17.56 0 0 1 33.148-3.743.158.158 0 0 0 .194.105 21.267 21.267 0 0 1 7.008-.729c.235.018.327-.116.25-.33a24.828 24.828 0 0 0-47.933 4.444.082.082 0 0 0 .016 0 18.537 18.537 0 0 0-9.85 31.533 18.007 18.007 0 0 0 10.325 5h-.001a43.066 43.066 0 0 0 5.266.282c1.68.011 33.725.008 35.067.008 2.7 0 4.457-.002 6.345-.14a18.245 18.245 0 0 0 11.723-5.15 18.532 18.532 0 0 0-12.901-31.789 18.06 18.06 0 0 0-11.704 4.285c-1.467 1.196-3.006 2.626-4.944 4.508-.642.625-13.336 12.94-21.67 21.028-1.16-.005-2.828-.021-4.306-.07a11.704 11.704 0 0 1-8.125-3.148A11.275 11.275 0 0 1 23.33 120.1a11.706 11.706 0 0 1 7.646 3.062c1.44 1.192 4.633 4 6.035 5.263a.17.17 0 0 0 .24.002l4.945-4.825a.176.176 0 0 0-.004-.27c-2.378-2.15-5.749-5.158-7.778-6.669a18.874 18.874 0 0 0-6.844-3.31zm46.482 26.094a11.704 11.704 0 0 1-8.125 3.147 168.92 168.92 0 0 1-5.204.073h-22.38c8.142-7.91 15.245-14.808 16.051-15.59.738-.717 2.398-2.306 3.83-3.595 3.145-2.831 5.974-3.4 7.976-3.382a11.275 11.275 0 0 1 7.852 19.347z"
|
||||
class="cls-1" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,156 @@
|
|||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class Credential:
|
||||
def __init__(self, secret_id, secret_key):
|
||||
self.secret_id = secret_id
|
||||
self.secret_key = secret_key
|
||||
|
||||
|
||||
class FlashRecognitionRequest:
|
||||
def __init__(self, voice_format="mp3", engine_type="16k_zh"):
|
||||
self.engine_type = engine_type
|
||||
self.speaker_diarization = 0
|
||||
self.hotword_id = ""
|
||||
self.customization_id = ""
|
||||
self.filter_dirty = 0
|
||||
self.filter_modal = 0
|
||||
self.filter_punc = 0
|
||||
self.convert_num_mode = 1
|
||||
self.word_info = 0
|
||||
self.voice_format = voice_format
|
||||
self.first_channel_only = 1
|
||||
self.reinforce_hotword = 0
|
||||
self.sentence_max_length = 0
|
||||
|
||||
def set_first_channel_only(self, first_channel_only):
|
||||
self.first_channel_only = first_channel_only
|
||||
|
||||
def set_speaker_diarization(self, speaker_diarization):
|
||||
self.speaker_diarization = speaker_diarization
|
||||
|
||||
def set_filter_dirty(self, filter_dirty):
|
||||
self.filter_dirty = filter_dirty
|
||||
|
||||
def set_filter_modal(self, filter_modal):
|
||||
self.filter_modal = filter_modal
|
||||
|
||||
def set_filter_punc(self, filter_punc):
|
||||
self.filter_punc = filter_punc
|
||||
|
||||
def set_convert_num_mode(self, convert_num_mode):
|
||||
self.convert_num_mode = convert_num_mode
|
||||
|
||||
def set_word_info(self, word_info):
|
||||
self.word_info = word_info
|
||||
|
||||
def set_hotword_id(self, hotword_id):
|
||||
self.hotword_id = hotword_id
|
||||
|
||||
def set_customization_id(self, customization_id):
|
||||
self.customization_id = customization_id
|
||||
|
||||
def set_voice_format(self, voice_format):
|
||||
self.voice_format = voice_format
|
||||
|
||||
def set_sentence_max_length(self, sentence_max_length):
|
||||
self.sentence_max_length = sentence_max_length
|
||||
|
||||
def set_reinforce_hotword(self, reinforce_hotword):
|
||||
self.reinforce_hotword = reinforce_hotword
|
||||
|
||||
|
||||
class FlashRecognizer:
|
||||
"""
|
||||
reponse:
|
||||
request_id string
|
||||
status Integer
|
||||
message String
|
||||
audio_duration Integer
|
||||
flash_result Result Array
|
||||
|
||||
Result:
|
||||
text String
|
||||
channel_id Integer
|
||||
sentence_list Sentence Array
|
||||
|
||||
Sentence:
|
||||
text String
|
||||
start_time Integer
|
||||
end_time Integer
|
||||
speaker_id Integer
|
||||
word_list Word Array
|
||||
|
||||
Word:
|
||||
word String
|
||||
start_time Integer
|
||||
end_time Integer
|
||||
stable_flag: Integer
|
||||
"""
|
||||
|
||||
def __init__(self, appid, credential):
|
||||
self.credential = credential
|
||||
self.appid = appid
|
||||
|
||||
def _format_sign_string(self, param):
|
||||
signstr = "POSTasr.cloud.tencent.com/asr/flash/v1/"
|
||||
for t in param:
|
||||
if 'appid' in t:
|
||||
signstr += str(t[1])
|
||||
break
|
||||
signstr += "?"
|
||||
for x in param:
|
||||
tmp = x
|
||||
if 'appid' in x:
|
||||
continue
|
||||
for t in tmp:
|
||||
signstr += str(t)
|
||||
signstr += "="
|
||||
signstr = signstr[:-1]
|
||||
signstr += "&"
|
||||
signstr = signstr[:-1]
|
||||
return signstr
|
||||
|
||||
def _build_header(self):
|
||||
header = {"Host": "asr.cloud.tencent.com"}
|
||||
return header
|
||||
|
||||
def _sign(self, signstr, secret_key):
|
||||
hmacstr = hmac.new(secret_key.encode('utf-8'),
|
||||
signstr.encode('utf-8'), hashlib.sha1).digest()
|
||||
s = base64.b64encode(hmacstr)
|
||||
s = s.decode('utf-8')
|
||||
return s
|
||||
|
||||
def _build_req_with_signature(self, secret_key, params, header):
|
||||
query = sorted(params.items(), key=lambda d: d[0])
|
||||
signstr = self._format_sign_string(query)
|
||||
signature = self._sign(signstr, secret_key)
|
||||
header["Authorization"] = signature
|
||||
requrl = "https://"
|
||||
requrl += signstr[4::]
|
||||
return requrl
|
||||
|
||||
def _create_query_arr(self, req):
|
||||
return {
|
||||
'appid': self.appid, 'secretid': self.credential.secret_id, 'timestamp': str(int(time.time())),
|
||||
'engine_type': req.engine_type, 'voice_format': req.voice_format,
|
||||
'speaker_diarization': req.speaker_diarization, 'hotword_id': req.hotword_id,
|
||||
'customization_id': req.customization_id, 'filter_dirty': req.filter_dirty,
|
||||
'filter_modal': req.filter_modal, 'filter_punc': req.filter_punc,
|
||||
'convert_num_mode': req.convert_num_mode, 'word_info': req.word_info,
|
||||
'first_channel_only': req.first_channel_only, 'reinforce_hotword': req.reinforce_hotword,
|
||||
'sentence_max_length': req.sentence_max_length
|
||||
}
|
||||
|
||||
def recognize(self, req, data):
|
||||
header = self._build_header()
|
||||
query_arr = self._create_query_arr(req)
|
||||
req_url = self._build_req_with_signature(self.credential.secret_key, query_arr, header)
|
||||
r = requests.post(req_url, headers=header, data=data)
|
||||
return r.text
|
|
@ -0,0 +1,92 @@
|
|||
import json
|
||||
from typing import IO, Optional
|
||||
|
||||
import requests
|
||||
|
||||
from core.model_runtime.errors.invoke import (
|
||||
InvokeAuthorizationError,
|
||||
InvokeConnectionError,
|
||||
InvokeError,
|
||||
)
|
||||
from core.model_runtime.errors.validate import CredentialsValidateFailedError
|
||||
from core.model_runtime.model_providers.__base.speech2text_model import Speech2TextModel
|
||||
from core.model_runtime.model_providers.tencent.speech2text.flash_recognizer import (
|
||||
Credential,
|
||||
FlashRecognitionRequest,
|
||||
FlashRecognizer,
|
||||
)
|
||||
|
||||
|
||||
class TencentSpeech2TextModel(Speech2TextModel):
|
||||
def _invoke(self, model: str, credentials: dict,
|
||||
file: IO[bytes], user: Optional[str] = None) \
|
||||
-> str:
|
||||
"""
|
||||
Invoke speech2text model
|
||||
|
||||
:param model: model name
|
||||
:param credentials: model credentials
|
||||
:param file: audio file
|
||||
:param user: unique user id
|
||||
:return: text for given audio file
|
||||
"""
|
||||
return self._speech2text_invoke(model, credentials, file)
|
||||
|
||||
def validate_credentials(self, model: str, credentials: dict) -> None:
|
||||
"""
|
||||
Validate model credentials
|
||||
|
||||
:param model: model name
|
||||
:param credentials: model credentials
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
audio_file_path = self._get_demo_file_path()
|
||||
|
||||
with open(audio_file_path, 'rb') as audio_file:
|
||||
self._speech2text_invoke(model, credentials, audio_file)
|
||||
except Exception as ex:
|
||||
raise CredentialsValidateFailedError(str(ex))
|
||||
|
||||
def _speech2text_invoke(self, model: str, credentials: dict, file: IO[bytes]) -> str:
|
||||
"""
|
||||
Invoke speech2text model
|
||||
|
||||
:param model: model name
|
||||
:param credentials: model credentials
|
||||
:param file: audio file
|
||||
:return: text for given audio file
|
||||
"""
|
||||
app_id = credentials["app_id"]
|
||||
secret_id = credentials["secret_id"]
|
||||
secret_key = credentials["secret_key"]
|
||||
voice_format = file.voice_format if hasattr(file, "voice_format") else "mp3"
|
||||
tencent_voice_recognizer = FlashRecognizer(app_id, Credential(secret_id, secret_key))
|
||||
resp = tencent_voice_recognizer.recognize(FlashRecognitionRequest(voice_format), file)
|
||||
resp = json.loads(resp)
|
||||
code = resp["code"]
|
||||
message = resp["message"]
|
||||
if code == 4002:
|
||||
raise CredentialsValidateFailedError(str(message))
|
||||
elif code != 0:
|
||||
return f"Tencent ASR Recognition failed with code {code} and message {message}"
|
||||
return "\n".join(item["text"] for item in resp["flash_result"])
|
||||
|
||||
@property
|
||||
def _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]]]:
|
||||
"""
|
||||
Map model invoke error to unified error
|
||||
The key is the error type thrown to the caller
|
||||
The value is the error type thrown by the model,
|
||||
which needs to be converted into a unified error type for the caller.
|
||||
|
||||
:return: Invoke error mapping
|
||||
"""
|
||||
return {
|
||||
InvokeConnectionError: [
|
||||
requests.exceptions.ConnectionError
|
||||
],
|
||||
InvokeAuthorizationError: [
|
||||
CredentialsValidateFailedError
|
||||
]
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
model: tencent
|
||||
model_type: speech2text
|
||||
model_properties:
|
||||
file_upload_limit: 25
|
||||
supported_file_extensions: flac,mp3,mp4,mpeg,mpga,m4a,ogg,wav,webm
|
29
api/core/model_runtime/model_providers/tencent/tencent.py
Normal file
29
api/core/model_runtime/model_providers/tencent/tencent.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
import logging
|
||||
|
||||
from core.model_runtime.entities.model_entities import ModelType
|
||||
from core.model_runtime.errors.validate import CredentialsValidateFailedError
|
||||
from core.model_runtime.model_providers.__base.model_provider import ModelProvider
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TencentProvider(ModelProvider):
|
||||
def validate_provider_credentials(self, credentials: dict) -> None:
|
||||
"""
|
||||
Validate provider credentials
|
||||
|
||||
if validate failed, raise exception
|
||||
|
||||
:param credentials: provider credentials, credentials form defined in `provider_credential_schema`.
|
||||
"""
|
||||
try:
|
||||
model_instance = self.get_model_instance(ModelType.SPEECH2TEXT)
|
||||
model_instance.validate_credentials(
|
||||
model='tencent',
|
||||
credentials=credentials
|
||||
)
|
||||
except CredentialsValidateFailedError as ex:
|
||||
raise ex
|
||||
except Exception as ex:
|
||||
logger.exception(f'{self.get_provider_schema().provider} credentials validate failed')
|
||||
raise ex
|
49
api/core/model_runtime/model_providers/tencent/tencent.yaml
Normal file
49
api/core/model_runtime/model_providers/tencent/tencent.yaml
Normal file
|
@ -0,0 +1,49 @@
|
|||
provider: tencent
|
||||
label:
|
||||
zh_Hans: 腾讯云
|
||||
en_US: Tencent
|
||||
icon_small:
|
||||
en_US: icon_s_en.svg
|
||||
icon_large:
|
||||
zh_Hans: icon_l_zh.svg
|
||||
en_US: icon_l_en.svg
|
||||
background: "#E5E7EB"
|
||||
help:
|
||||
title:
|
||||
en_US: Get your API key from Tencent AI
|
||||
zh_Hans: 从腾讯云获取 API Key
|
||||
url:
|
||||
en_US: https://cloud.tencent.com/product/asr
|
||||
supported_model_types:
|
||||
- speech2text
|
||||
configurate_methods:
|
||||
- predefined-model
|
||||
provider_credential_schema:
|
||||
credential_form_schemas:
|
||||
- variable: app_id
|
||||
label:
|
||||
zh_Hans: APPID
|
||||
en_US: APPID
|
||||
type: text-input
|
||||
required: true
|
||||
placeholder:
|
||||
zh_Hans: 在此输入您的腾讯语音识别服务的 APPID
|
||||
en_US: Enter the APPID of your Tencent Cloud ASR service
|
||||
- variable: secret_id
|
||||
label:
|
||||
zh_Hans: SecretId
|
||||
en_US: SecretId
|
||||
type: secret-input
|
||||
required: true
|
||||
placeholder:
|
||||
zh_Hans: 在此输入您的腾讯语音识别服务的 SecretId
|
||||
en_US: Enter the SecretId of your Tencent Cloud ASR service
|
||||
- variable: secret_key
|
||||
label:
|
||||
zh_Hans: SecretKey
|
||||
en_US: SecretKey
|
||||
type: secret-input
|
||||
required: true
|
||||
placeholder:
|
||||
zh_Hans: 在此输入您的腾讯语音识别服务的 SecretKey
|
||||
en_US: Enter the SecretKey of your Tencent Cloud ASR service
|
Loading…
Reference in New Issue
Block a user