From fe78de5d3cd7dfb1bcd8d004fcc05bb4e2db234e Mon Sep 17 00:00:00 2001
From: wxg0103 <727495428@qq.com>
Date: Thu, 10 Jul 2025 15:01:56 +0800
Subject: [PATCH] feat: add email templates for verification codes in English,
Chinese, and Traditional Chinese
---
apps/common/template/email_template_en.html | 122 +++++++++++++++
apps/common/template/email_template_zh.html | 121 +++++++++++++++
.../template/email_template_zh_Hant.html | 123 +++++++++++++++
.../credential/tti.py | 7 +-
.../model/tti.py | 145 +++---------------
.../volcanic_engine_model_provider.py | 29 +---
6 files changed, 395 insertions(+), 152 deletions(-)
create mode 100644 apps/common/template/email_template_en.html
create mode 100644 apps/common/template/email_template_zh.html
create mode 100644 apps/common/template/email_template_zh_Hant.html
diff --git a/apps/common/template/email_template_en.html b/apps/common/template/email_template_en.html
new file mode 100644
index 000000000..5d5515c44
--- /dev/null
+++ b/apps/common/template/email_template_en.html
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+ Intelligent Knowledge Q&A System
+
+ |
+
+
+
+
+
+
+
+
+ Dear user:
+
+
+
+
+ ${code} This is your dynamic verification code. Please fill it in within 30 minutes. To protect the security of your account, please do not provide this verification code to anyone.
+
+
+
+
+
+ Intelligent knowledge base project team
+
+
+ Please do not reply to this system email
+
+
+
+
+
+ |
+
+
+
+
+
+
diff --git a/apps/common/template/email_template_zh.html b/apps/common/template/email_template_zh.html
new file mode 100644
index 000000000..29c1fc65d
--- /dev/null
+++ b/apps/common/template/email_template_zh.html
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+ 智能知识库问答系统
+
+ |
+
+
+
+
+
+
+
+ 尊敬的用户:
+
+
+
+
+ ${code} 为您的动态验证码,请于30分钟内填写,为保障帐户安全,请勿向任何人提供此验证码。
+
+
+
+
+
+ 智能知识库项目组
+
+
+ 此为系统邮件,请勿回复
+
+
+
+
+
+ |
+
+
+
+
+
+
diff --git a/apps/common/template/email_template_zh_Hant.html b/apps/common/template/email_template_zh_Hant.html
new file mode 100644
index 000000000..d54d40231
--- /dev/null
+++ b/apps/common/template/email_template_zh_Hant.html
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+ 智慧知識庫問答系統
+
+ |
+
+
+
+
+
+
+
+
+ 尊敬的用戶:
+
+
+
+
+ ${code} 為您的動態驗證碼,請於30分鐘內填寫,為保障帳戶安全,請勿向任何人提供此驗證碼。
+
+
+
+
+
+ 智慧知識庫專案組
+
+
+ 此為系統郵件,請勿回覆
+
+
+
+
+
+ |
+
+
+
+
+
+
diff --git a/apps/models_provider/impl/volcanic_engine_model_provider/credential/tti.py b/apps/models_provider/impl/volcanic_engine_model_provider/credential/tti.py
index af9bea144..88a26386c 100644
--- a/apps/models_provider/impl/volcanic_engine_model_provider/credential/tti.py
+++ b/apps/models_provider/impl/volcanic_engine_model_provider/credential/tti.py
@@ -30,8 +30,7 @@ class VolcanicEngineTTIModelGeneralParams(BaseForm):
class VolcanicEngineTTIModelCredential(BaseForm, BaseModelCredential):
- access_key = forms.PasswordInputField('Access Key ID', required=True)
- secret_key = forms.PasswordInputField('Secret Access Key', required=True)
+ api_key = forms.PasswordInputField('Api key', required=True)
def is_valid(self, model_type: str, model_name, model_credential: Dict[str, object], model_params, provider,
raise_exception=False):
@@ -40,7 +39,7 @@ class VolcanicEngineTTIModelCredential(BaseForm, BaseModelCredential):
raise AppApiException(ValidCode.valid_error.value,
gettext('{model_type} Model type is not supported').format(model_type=model_type))
- for key in ['access_key', 'secret_key']:
+ for key in ['api_key']:
if key not in model_credential:
if raise_exception:
raise AppApiException(ValidCode.valid_error.value, gettext('{key} is required').format(key=key))
@@ -62,7 +61,7 @@ class VolcanicEngineTTIModelCredential(BaseForm, BaseModelCredential):
return True
def encryption_dict(self, model: Dict[str, object]):
- return {**model, 'secret_key': super().encryption(model.get('secret_key', ''))}
+ return {**model, 'api_key': super().encryption(model.get('api_key', ''))}
def get_model_params_setting_form(self, model_name):
return VolcanicEngineTTIModelGeneralParams()
diff --git a/apps/models_provider/impl/volcanic_engine_model_provider/model/tti.py b/apps/models_provider/impl/volcanic_engine_model_provider/model/tti.py
index 5ad6f733b..038c283b2 100644
--- a/apps/models_provider/impl/volcanic_engine_model_provider/model/tti.py
+++ b/apps/models_provider/impl/volcanic_engine_model_provider/model/tti.py
@@ -7,122 +7,21 @@ pip install asyncio
pip install websockets
'''
-
-import datetime
-import hashlib
-import hmac
-import json
-import logging
-import sys
from typing import Dict
-
-import requests
-
-from common.utils.logger import maxkb_logger
from models_provider.base_model_provider import MaxKBBaseModel
from models_provider.impl.base_tti import BaseTextToImage
-method = 'POST'
-host = 'visual.volcengineapi.com'
-region = 'cn-north-1'
-endpoint = 'https://visual.volcengineapi.com'
-service = 'cv'
-
-req_key_dict = {
- 'general_v1.4': 'high_aes_general_v14',
- 'general_v2.0': 'high_aes_general_v20',
- 'general_v2.0_L': 'high_aes_general_v20_L',
- 'anime_v1.3': 'high_aes',
- 'anime_v1.3.1': 'high_aes',
-}
-
-
-def sign(key, msg):
- return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
-
-
-def getSignatureKey(key, dateStamp, regionName, serviceName):
- kDate = sign(key.encode('utf-8'), dateStamp)
- kRegion = sign(kDate, regionName)
- kService = sign(kRegion, serviceName)
- kSigning = sign(kService, 'request')
- return kSigning
-
-
-def formatQuery(parameters):
- request_parameters_init = ''
- for key in sorted(parameters):
- request_parameters_init += key + '=' + parameters[key] + '&'
- request_parameters = request_parameters_init[:-1]
- return request_parameters
-
-
-def signV4Request(access_key, secret_key, service, req_query, req_body):
- if access_key is None or secret_key is None:
- maxkb_logger.info('No access key is available.')
- sys.exit()
-
- t = datetime.datetime.utcnow()
- current_date = t.strftime('%Y%m%dT%H%M%SZ')
- # current_date = '20210818T095729Z'
- datestamp = t.strftime('%Y%m%d') # Date w/o time, used in credential scope
- canonical_uri = '/'
- canonical_querystring = req_query
- signed_headers = 'content-type;host;x-content-sha256;x-date'
- payload_hash = hashlib.sha256(req_body.encode('utf-8')).hexdigest()
- content_type = 'application/json'
- canonical_headers = 'content-type:' + content_type + '\n' + 'host:' + host + \
- '\n' + 'x-content-sha256:' + payload_hash + \
- '\n' + 'x-date:' + current_date + '\n'
- canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + \
- '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
- algorithm = 'HMAC-SHA256'
- credential_scope = datestamp + '/' + region + '/' + service + '/' + 'request'
- string_to_sign = algorithm + '\n' + current_date + '\n' + credential_scope + '\n' + hashlib.sha256(
- canonical_request.encode('utf-8')).hexdigest()
- signing_key = getSignatureKey(secret_key, datestamp, region, service)
- signature = hmac.new(signing_key, (string_to_sign).encode(
- 'utf-8'), hashlib.sha256).hexdigest()
-
- authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + \
- credential_scope + ', ' + 'SignedHeaders=' + \
- signed_headers + ', ' + 'Signature=' + signature
- headers = {'X-Date': current_date,
- 'Authorization': authorization_header,
- 'X-Content-Sha256': payload_hash,
- 'Content-Type': content_type
- }
-
- # ************* SEND THE REQUEST *************
- request_url = endpoint + '?' + canonical_querystring
-
- maxkb_logger.info('\nBEGIN REQUEST++++++++++++++++++++++++++++++++++++')
- maxkb_logger.info('Request URL = ' + request_url)
- try:
- r = requests.post(request_url, headers=headers, data=req_body)
- except Exception as err:
- maxkb_logger.info(f'error occurred: {err}')
- raise
- else:
- maxkb_logger.info('\nRESPONSE++++++++++++++++++++++++++++++++++++')
- maxkb_logger.info(f'Response code: {r.status_code}\n')
- # 使用 replace 方法将 \u0026 替换为 &
- resp_str = r.text.replace("\\u0026", "&")
- if r.status_code != 200:
- raise Exception(f'Error: {resp_str}')
- return json.loads(resp_str)['data']['image_urls']
+from volcenginesdkarkruntime import Ark
class VolcanicEngineTextToImage(MaxKBBaseModel, BaseTextToImage):
- access_key: str
- secret_key: str
+ api_key: str
model_version: str
params: dict
def __init__(self, **kwargs):
super().__init__(**kwargs)
- self.access_key = kwargs.get('access_key')
- self.secret_key = kwargs.get('secret_key')
+ self.api_key = kwargs.get('api_key')
self.model_version = kwargs.get('model_version')
self.params = kwargs.get('params')
@@ -138,33 +37,25 @@ class VolcanicEngineTextToImage(MaxKBBaseModel, BaseTextToImage):
optional_params['params'][key] = value
return VolcanicEngineTextToImage(
model_version=model_name,
- access_key=model_credential.get('access_key'),
- secret_key=model_credential.get('secret_key'),
+ api_key=model_credential.get('api_key'),
**optional_params
)
def check_auth(self):
- res = self.generate_image('生成一张小猫图片')
+ return True
def generate_image(self, prompt: str, negative_prompt: str = None):
- # 请求Query,按照接口文档中填入即可
- query_params = {
- 'Action': 'CVProcess',
- 'Version': '2022-08-31',
- }
- formatted_query = formatQuery(query_params)
- size = self.params.pop('size', '512*512').split('*')
- body_params = {
- "req_key": req_key_dict[self.model_version],
- "prompt": prompt,
- "model_version": self.model_version,
- "return_url": True,
- "width": int(size[0]),
- "height": int(size[1]),
+ client = Ark(
+ # 此为默认路径,您可根据业务所在地域进行配置
+ base_url="https://ark.cn-beijing.volces.com/api/v3",
+ # 从环境变量中获取您的 API Key。此为默认方式,您可根据需要进行修改
+ api_key=self.api_key,
+ )
+ file_urls = []
+ imagesResponse = client.images.generate(
+ model=self.model_version,
+ prompt=prompt,
**self.params
- }
- formatted_body = json.dumps(body_params)
- return signV4Request(self.access_key, self.secret_key, service, formatted_query, formatted_body)
-
- def is_cache_model(self):
- return False
+ )
+ file_urls.append(imagesResponse.data[0].url)
+ return file_urls
diff --git a/apps/models_provider/impl/volcanic_engine_model_provider/volcanic_engine_model_provider.py b/apps/models_provider/impl/volcanic_engine_model_provider/volcanic_engine_model_provider.py
index efb1cc8b5..5f9460d76 100644
--- a/apps/models_provider/impl/volcanic_engine_model_provider/volcanic_engine_model_provider.py
+++ b/apps/models_provider/impl/volcanic_engine_model_provider/volcanic_engine_model_provider.py
@@ -55,23 +55,8 @@ model_info_list = [
ModelTypeConst.TTS,
volcanic_engine_tts_model_credential, VolcanicEngineTextToSpeech
),
- ModelInfo('general_v2.0',
- _('Universal 2.0-Vincent Diagram'),
- ModelTypeConst.TTI,
- volcanic_engine_tti_model_credential, VolcanicEngineTextToImage
- ),
- ModelInfo('general_v2.0_L',
- _('Universal 2.0Pro-Vincent Chart'),
- ModelTypeConst.TTI,
- volcanic_engine_tti_model_credential, VolcanicEngineTextToImage
- ),
- ModelInfo('general_v1.4',
- _('Universal 1.4-Vincent Chart'),
- ModelTypeConst.TTI,
- volcanic_engine_tti_model_credential, VolcanicEngineTextToImage
- ),
- ModelInfo('anime_v1.3.1',
- _('Animation 1.3.1-Vincent Picture'),
+ ModelInfo('doubao-seedream-3-0-t2i-250415',
+ _(''),
ModelTypeConst.TTI,
volcanic_engine_tti_model_credential, VolcanicEngineTextToImage
),
@@ -105,7 +90,9 @@ class VolcanicEngineModelProvider(IModelProvider):
return model_info_manage
def get_model_provide_info(self):
- return ModelProvideInfo(provider='model_volcanic_engine_provider', name=_('volcano engine'), icon=get_file_content(
- os.path.join(PROJECT_DIR, "apps", 'models_provider', 'impl', 'volcanic_engine_model_provider',
- 'icon',
- 'volcanic_engine_icon_svg')))
+ return ModelProvideInfo(provider='model_volcanic_engine_provider', name=_('volcano engine'),
+ icon=get_file_content(
+ os.path.join(PROJECT_DIR, "apps", 'models_provider', 'impl',
+ 'volcanic_engine_model_provider',
+ 'icon',
+ 'volcanic_engine_icon_svg')))