diff --git a/apps/locales/en_US/LC_MESSAGES/django.po b/apps/locales/en_US/LC_MESSAGES/django.po
index a6d7abfc2a0..3829042d2f5 100644
--- a/apps/locales/en_US/LC_MESSAGES/django.po
+++ b/apps/locales/en_US/LC_MESSAGES/django.po
@@ -9646,3 +9646,90 @@ msgstr ""
#: apps/models_provider/impl/tencent_model_provider/credential/tokenhub_stt.py:76
msgid "Tokenhub sync_transcribe endpoint"
msgstr ""
+
+msgid "Add logo"
+msgstr "Add logo"
+
+msgid "Custom watermark content, at most 16 characters, drawn in the bottom-right."
+msgstr "Custom watermark content, at most 16 characters, drawn in the bottom-right."
+
+msgid "Designed for Agent workloads, using a MoE architecture that supports interleaved thinking, structured output, Function Calling and Cache caching."
+msgstr "Designed for Agent workloads, using a MoE architecture that supports interleaved thinking, structured output, Function Calling and Cache caching."
+
+msgid "Frame rate"
+msgstr "Frame rate"
+
+msgid "Hunyuan HY-Video 1.5 image-to-video model."
+msgstr "Hunyuan HY-Video 1.5 image-to-video model."
+
+msgid "Hunyuan HY-Video 1.5 text-to-video model."
+msgstr "Hunyuan HY-Video 1.5 text-to-video model."
+
+msgid "Hunyuan Hy-Image 3.0 text-to-image model."
+msgstr "Hunyuan Hy-Image 3.0 text-to-image model."
+
+msgid "Hunyuan's latest role-playing model based on the Hunyuan model with role-playing scene fine-tuning."
+msgstr "Hunyuan's latest role-playing model based on the Hunyuan model with role-playing scene fine-tuning."
+
+msgid "Hunyuan's role-playing model with better basic effects in role-playing scenarios."
+msgstr "Hunyuan's role-playing model with better basic effects in role-playing scenarios."
+
+msgid "Output video frame rate: 16, 24, 30."
+msgstr "Output video frame rate: 16, 24, 30."
+
+msgid "Output video resolution: 480p, 720p, 1080p."
+msgstr "Output video resolution: 480p, 720p, 1080p."
+
+msgid "Prompt rewrite"
+msgstr "Prompt rewrite"
+
+msgid "Tencent Hybrid multilingual translation model."
+msgstr "Tencent Hybrid multilingual translation model."
+
+msgid "Tencent TokenHub multimodal embedding model, 2048 dimensions."
+msgstr "Tencent TokenHub multimodal embedding model, 2048 dimensions."
+
+msgid "Tencent TokenHub multimodal embedding model, 4096 dimensions."
+msgstr "Tencent TokenHub multimodal embedding model, 4096 dimensions."
+
+msgid "Tencent TokenHub text embedding model, 1024 dimensions."
+msgstr "Tencent TokenHub text embedding model, 1024 dimensions."
+
+msgid "Tencent TokenHub text embedding model, 2560 dimensions."
+msgstr "Tencent TokenHub text embedding model, 2560 dimensions."
+
+msgid "Tencent YT-Video 2.0 image-to-video model."
+msgstr "Tencent YT-Video 2.0 image-to-video model."
+
+msgid "The latest generation productivity model with upgraded Agent and complex task execution capabilities."
+msgstr "The latest generation productivity model with upgraded Agent and complex task execution capabilities."
+
+msgid "TokenHub Hy-Image v3-generation endpoint"
+msgstr "TokenHub Hy-Image v3-generation endpoint"
+
+msgid "TokenHub OpenAI compatible embeddings endpoint"
+msgstr "TokenHub OpenAI compatible embeddings endpoint"
+
+msgid "TokenHub OpenAI compatible endpoint"
+msgstr "TokenHub OpenAI compatible endpoint"
+
+msgid "TokenHub video endpoint. Use the base (e.g. https://tokenhub.tencentmaas.com/v1) or a full submit/query URL."
+msgstr "TokenHub video endpoint. Use the base (e.g. https://tokenhub.tencentmaas.com/v1) or a full submit/query URL."
+
+msgid "Tuned on real business scenarios, balancing effectiveness and cost-effectiveness, with reinforced Coding, long-text, reasoning and Agent capabilities."
+msgstr "Tuned on real business scenarios, balancing effectiveness and cost-effectiveness, with reinforced Coding, long-text, reasoning and Agent capabilities."
+
+msgid "Watermark footnote"
+msgstr "Watermark footnote"
+
+msgid "Whether the model should rewrite and optimize the prompt before generation."
+msgstr "Whether the model should rewrite and optimize the prompt before generation."
+
+msgid "Whether to add the AI-generated logo to the video. 1: add logo; 0: no logo (requires console approval for independent control)."
+msgstr "Whether to add the AI-generated logo to the video. 1: add logo; 0: no logo (requires console approval for independent control)."
+
+msgid "Width and height must be in [512, 2048] and the area must not exceed 1024x1024. If not passed, the model auto-selects the closest preset size."
+msgstr "Width and height must be in [512, 2048] and the area must not exceed 1024x1024. If not passed, the model auto-selects the closest preset size."
+
+msgid "api_key is required"
+msgstr "api_key is required"
diff --git a/apps/locales/zh_CN/LC_MESSAGES/django.po b/apps/locales/zh_CN/LC_MESSAGES/django.po
index b6bc4e199a7..ab60b13717a 100644
--- a/apps/locales/zh_CN/LC_MESSAGES/django.po
+++ b/apps/locales/zh_CN/LC_MESSAGES/django.po
@@ -9787,4 +9787,119 @@ msgstr "自动"
#: apps/models_provider/impl/tencent_model_provider/credential/tokenhub_stt.py:76
msgid "Tokenhub sync_transcribe endpoint"
-msgstr "Tokenhub 同步转写接口地址"
\ No newline at end of file
+msgstr "Tokenhub 同步转写接口地址"
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Add logo"
+msgstr "添加标识"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Custom watermark content, at most 16 characters, drawn in the bottom-right."
+msgstr "自定义水印内容,最多16个字符,绘制在右下角。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Designed for Agent workloads, using a MoE architecture that supports interleaved thinking, structured output, Function Calling and Cache caching."
+msgstr "专为 Agent 场景设计,采用 MoE 架构,支持交织思考、结构化输出、Function Calling 和 Cache 缓存。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Frame rate"
+msgstr "帧率"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan HY-Video 1.5 image-to-video model."
+msgstr "混元 HY-Video 1.5 图生视频模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan HY-Video 1.5 text-to-video model."
+msgstr "混元 HY-Video 1.5 文生视频模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan Hy-Image 3.0 text-to-image model."
+msgstr "混元 Hy-Image 3.0 文生图模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan's latest role-playing model based on the Hunyuan model with role-playing scene fine-tuning."
+msgstr "基于混元模型并在角色扮演场景微调的最新角色扮演模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan's role-playing model with better basic effects in role-playing scenarios."
+msgstr "在角色扮演场景中基础效果更优的混元角色扮演模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Output video frame rate: 16, 24, 30."
+msgstr "输出视频帧率:16、24、30。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Output video resolution: 480p, 720p, 1080p."
+msgstr "输出视频分辨率:480p、720p、1080p。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Prompt rewrite"
+msgstr "提示词改写"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent Hybrid multilingual translation model."
+msgstr "腾讯混元多语言翻译模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent TokenHub multimodal embedding model, 2048 dimensions."
+msgstr "腾讯 TokenHub 多模态向量模型,2048 维。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent TokenHub multimodal embedding model, 4096 dimensions."
+msgstr "腾讯 TokenHub 多模态向量模型,4096 维。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent TokenHub text embedding model, 1024 dimensions."
+msgstr "腾讯 TokenHub 文本向量模型,1024 维。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent TokenHub text embedding model, 2560 dimensions."
+msgstr "腾讯 TokenHub 文本向量模型,2560 维。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent YT-Video 2.0 image-to-video model."
+msgstr "腾讯 YT-Video 2.0 图生视频模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "The latest generation productivity model with upgraded Agent and complex task execution capabilities."
+msgstr "采用全新一代生产力模型,升级了 Agent 与复杂任务执行能力。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "TokenHub Hy-Image v3-generation endpoint"
+msgstr "TokenHub Hy-Image v3-generation 接口"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/embedding.py
+msgid "TokenHub OpenAI compatible embeddings endpoint"
+msgstr "TokenHub OpenAI 兼容向量接口"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/llm.py
+msgid "TokenHub OpenAI compatible endpoint"
+msgstr "TokenHub OpenAI 兼容接口"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "TokenHub video endpoint. Use the base (e.g. https://tokenhub.tencentmaas.com/v1) or a full submit/query URL."
+msgstr "TokenHub 视频接口。可使用根地址(如 https://tokenhub.tencentmaas.com/v1)或完整的 submit/query 地址。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tuned on real business scenarios, balancing effectiveness and cost-effectiveness, with reinforced Coding, long-text, reasoning and Agent capabilities."
+msgstr "针对真实业务场景调优,兼顾效果与成本,强化了 Coding、长文本、推理和 Agent 能力。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Watermark footnote"
+msgstr "水印角标"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Whether the model should rewrite and optimize the prompt before generation."
+msgstr "模型是否在生成前改写并优化提示词。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Whether to add the AI-generated logo to the video. 1: add logo; 0: no logo (requires console approval for independent control)."
+msgstr "是否为生成视频添加 AI 标识。1:添加标识;0:不添加标识(需在控制台申请开启独立控制)。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Width and height must be in [512, 2048] and the area must not exceed 1024x1024. If not passed, the model auto-selects the closest preset size."
+msgstr "宽和高必须在 [512, 2048] 之间,且面积不得超过 1024x1024。不传时由模型自动选择最接近的预设尺寸。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/embedding.py
+msgid "api_key is required"
+msgstr "api_key 必填"
diff --git a/apps/locales/zh_Hant/LC_MESSAGES/django.po b/apps/locales/zh_Hant/LC_MESSAGES/django.po
index 0b513faf124..d78fd2ad100 100644
--- a/apps/locales/zh_Hant/LC_MESSAGES/django.po
+++ b/apps/locales/zh_Hant/LC_MESSAGES/django.po
@@ -9785,3 +9785,119 @@ msgstr "自動"
#: apps/models_provider/impl/tencent_model_provider/credential/tokenhub_stt.py:76
msgid "Tokenhub sync_transcribe endpoint"
msgstr "Tokenhub 同步轉寫接口地址"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Add logo"
+msgstr "加入標示"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Custom watermark content, at most 16 characters, drawn in the bottom-right."
+msgstr "自訂浮水印內容,最多16個字元,繪製在右下角。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Designed for Agent workloads, using a MoE architecture that supports interleaved thinking, structured output, Function Calling and Cache caching."
+msgstr "專為 Agent 場景設計,採用 MoE 架構,支援交織思考、結構化輸出、Function Calling 與 Cache 快取。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Frame rate"
+msgstr "幀率"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan HY-Video 1.5 image-to-video model."
+msgstr "混元 HY-Video 1.5 圖生影片模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan HY-Video 1.5 text-to-video model."
+msgstr "混元 HY-Video 1.5 文生影片模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan Hy-Image 3.0 text-to-image model."
+msgstr "混元 Hy-Image 3.0 文生圖模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan's latest role-playing model based on the Hunyuan model with role-playing scene fine-tuning."
+msgstr "基於混元模型並在角色扮演場景微調的最新角色扮演模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Hunyuan's role-playing model with better basic effects in role-playing scenarios."
+msgstr "在角色扮演場景中基礎效果更優的混元角色扮演模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Output video frame rate: 16, 24, 30."
+msgstr "輸出影片幀率:16、24、30。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Output video resolution: 480p, 720p, 1080p."
+msgstr "輸出影片解析度:480p、720p、1080p。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Prompt rewrite"
+msgstr "提示詞改寫"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent Hybrid multilingual translation model."
+msgstr "騰訊混元多語言翻譯模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent TokenHub multimodal embedding model, 2048 dimensions."
+msgstr "騰訊 TokenHub 多模態向量模型,2048 維。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent TokenHub multimodal embedding model, 4096 dimensions."
+msgstr "騰訊 TokenHub 多模態向量模型,4096 維。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent TokenHub text embedding model, 1024 dimensions."
+msgstr "騰訊 TokenHub 文字向量模型,1024 維。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent TokenHub text embedding model, 2560 dimensions."
+msgstr "騰訊 TokenHub 文字向量模型,2560 維。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tencent YT-Video 2.0 image-to-video model."
+msgstr "騰訊 YT-Video 2.0 圖生影片模型。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "The latest generation productivity model with upgraded Agent and complex task execution capabilities."
+msgstr "採用全新一代生產力模型,升級了 Agent 與複雜任務執行能力。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "TokenHub Hy-Image v3-generation endpoint"
+msgstr "TokenHub Hy-Image v3-generation 介面"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/embedding.py
+msgid "TokenHub OpenAI compatible embeddings endpoint"
+msgstr "TokenHub OpenAI 相容向量介面"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/llm.py
+msgid "TokenHub OpenAI compatible endpoint"
+msgstr "TokenHub OpenAI 相容介面"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "TokenHub video endpoint. Use the base (e.g. https://tokenhub.tencentmaas.com/v1) or a full submit/query URL."
+msgstr "TokenHub 影片介面。可使用根位址(如 https://tokenhub.tencentmaas.com/v1)或完整的 submit/query 位址。"
+
+#: apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+msgid "Tuned on real business scenarios, balancing effectiveness and cost-effectiveness, with reinforced Coding, long-text, reasoning and Agent capabilities."
+msgstr "針對真實業務場景調優,兼顧效果與成本,強化了 Coding、長文本、推理和 Agent 能力。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Watermark footnote"
+msgstr "浮水印角標"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Whether the model should rewrite and optimize the prompt before generation."
+msgstr "模型是否在生成前改寫並最佳化提示詞。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/ttv.py
+msgid "Whether to add the AI-generated logo to the video. 1: add logo; 0: no logo (requires console approval for independent control)."
+msgstr "是否為生成影片加入 AI 標示。1:加入標示;0:不加入標示(需在控制台申請開啟獨立控制)。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/tti.py
+msgid "Width and height must be in [512, 2048] and the area must not exceed 1024x1024. If not passed, the model auto-selects the closest preset size."
+msgstr "寬和高必須在 [512, 2048] 之間,且面積不得超過 1024x1024。未傳時由模型自動選擇最接近的預設尺寸。"
+
+#: apps/models_provider/impl/tencent_model_provider/credential/embedding.py
+msgid "api_key is required"
+msgstr "api_key 必填"
diff --git a/apps/models_provider/impl/tencent_model_provider/credential/embedding.py b/apps/models_provider/impl/tencent_model_provider/credential/embedding.py
index bb5d0bba79c..b71630af869 100644
--- a/apps/models_provider/impl/tencent_model_provider/credential/embedding.py
+++ b/apps/models_provider/impl/tencent_model_provider/credential/embedding.py
@@ -1,30 +1,31 @@
+# coding=utf-8
+
from typing import Dict
from django.utils.translation import gettext as _
from common import forms
from common.exception.app_exception import AppApiException
-from common.forms import BaseForm
+from common.forms import BaseForm, TooltipLabel
from models_provider.base_model_provider import BaseModelCredential, ValidCode
from common.utils.logger import maxkb_logger
class TencentEmbeddingCredential(BaseForm, BaseModelCredential):
def is_valid(
- self,
- model_type: str,
- model_name,
- model_credential: Dict[str, object],
- model_params,
- provider,
- raise_exception=True,
- ) -> bool:
+ self, model_type, model_name, model_credential: Dict[str, object], model_params, provider, raise_exception=True
+ ):
model_type_list = provider.get_model_type_list()
- if not any(list(filter(lambda mt: mt.get("value") == model_type, model_type_list))):
+ if not any(mt.get("value") == model_type for mt in model_type_list):
raise AppApiException(
ValidCode.valid_error.value, _("{model_type} Model type is not supported").format(model_type=model_type)
)
- self.valid_form(model_credential)
+
+ if "api_key" not in model_credential:
+ if raise_exception:
+ raise AppApiException(ValidCode.valid_error.value, _("api_key is required"))
+ return False
+
try:
model = provider.get_model(model_type, model_name, model_credential)
model.embed_query(_("Hello"))
@@ -43,9 +44,12 @@ def is_valid(
return False
return True
- def encryption_dict(self, model: Dict[str, object]) -> Dict[str, object]:
- encrypted_secret_key = super().encryption(model.get("SecretKey", ""))
- return {**model, "SecretKey": encrypted_secret_key}
+ def encryption_dict(self, model: Dict[str, object]):
+ return {**model, "api_key": super().encryption(model.get("api_key", ""))}
- SecretId = forms.PasswordInputField("SecretId", required=True)
- SecretKey = forms.PasswordInputField("SecretKey", required=True)
+ base_url = forms.TextInputField(
+ label=TooltipLabel(_("API URL"), _("TokenHub OpenAI compatible embeddings endpoint")),
+ required=False,
+ default_value="https://tokenhub.tencentmaas.com/v1",
+ )
+ api_key = forms.PasswordInputField(_("API Key"), required=True)
diff --git a/apps/models_provider/impl/tencent_model_provider/credential/image.py b/apps/models_provider/impl/tencent_model_provider/credential/image.py
index b96fe1fe9b1..1ca90803a4b 100644
--- a/apps/models_provider/impl/tencent_model_provider/credential/image.py
+++ b/apps/models_provider/impl/tencent_model_provider/credential/image.py
@@ -91,7 +91,7 @@ def is_valid(
def encryption_dict(self, model: Dict[str, object]):
return {**model, "api_key": super().encryption(model.get("api_key", ""))}
- api_base = forms.TextInputField("API URL", required=True, default_value="https://api.hunyuan.cloud.tencent.com/v1")
+ api_base = forms.TextInputField("API URL", required=True, default_value="https://tokenhub.tencentmaas.com/v1")
api_key = forms.PasswordInputField("API Key", required=True)
def get_model_params_setting_form(self, model_name):
diff --git a/apps/models_provider/impl/tencent_model_provider/credential/llm.py b/apps/models_provider/impl/tencent_model_provider/credential/llm.py
index 3eff292f0f7..931105203e0 100644
--- a/apps/models_provider/impl/tencent_model_provider/credential/llm.py
+++ b/apps/models_provider/impl/tencent_model_provider/credential/llm.py
@@ -1,5 +1,7 @@
# coding=utf-8
+from typing import Dict
+
from django.utils.translation import gettext_lazy as _, gettext
from langchain_core.messages import HumanMessage
@@ -24,43 +26,49 @@ class TencentLLMModelParams(BaseForm):
precision=2,
)
+ max_tokens = forms.SliderField(
+ TooltipLabel(
+ _("Output the maximum Tokens"), _("Specify the maximum number of tokens that the model can generate")
+ ),
+ required=True,
+ default_value=8192,
+ _min=1,
+ _max=100000,
+ _step=1,
+ precision=0,
+ )
-class TencentLLMModelCredential(BaseForm, BaseModelCredential):
- REQUIRED_FIELDS = ["hunyuan_app_id", "hunyuan_secret_id", "hunyuan_secret_key"]
- @classmethod
- def _validate_model_type(cls, model_type, provider, raise_exception=False):
- if not any(mt["value"] == model_type for mt in provider.get_model_type_list()):
- if raise_exception:
- raise AppApiException(
- ValidCode.valid_error.value,
- gettext("{model_type} Model type is not supported").format(model_type=model_type),
- )
- return False
- return True
-
- @classmethod
- def _validate_credential_fields(cls, model_credential, raise_exception=False):
- missing_keys = [key for key in cls.REQUIRED_FIELDS if key not in model_credential]
- if missing_keys:
- if raise_exception:
- raise AppApiException(
- ValidCode.valid_error.value, gettext("{keys} is required").format(keys=", ".join(missing_keys))
- )
- return False
- return True
+class TencentLLMModelCredential(BaseForm, BaseModelCredential):
+ def is_valid(
+ self,
+ model_type: str,
+ model_name,
+ model_credential: Dict[str, object],
+ model_params,
+ provider,
+ raise_exception=False,
+ ):
+ model_type_list = provider.get_model_type_list()
+ if not any(list(filter(lambda mt: mt.get("value") == model_type, model_type_list))):
+ raise AppApiException(
+ ValidCode.valid_error.value,
+ gettext("{model_type} Model type is not supported").format(model_type=model_type),
+ )
- def is_valid(self, model_type, model_name, model_credential, model_params, provider, raise_exception=False):
- if not (
- self._validate_model_type(model_type, provider, raise_exception)
- and self._validate_credential_fields(model_credential, raise_exception)
- ):
- return False
+ for key in ["api_base", "api_key"]:
+ if key not in model_credential:
+ if raise_exception:
+ raise AppApiException(ValidCode.valid_error.value, gettext("{key} is required").format(key=key))
+ else:
+ return False
try:
model = provider.get_model(model_type, model_name, model_credential, **model_params)
model.invoke([HumanMessage(content=gettext("Hello"))])
except Exception as e:
maxkb_logger.error(f"Exception: {e}", exc_info=True)
+ if isinstance(e, AppApiException):
+ raise e
if raise_exception:
raise AppApiException(
ValidCode.valid_error.value,
@@ -68,15 +76,19 @@ def is_valid(self, model_type, model_name, model_credential, model_params, provi
error=str(e)
),
)
- return False
+ else:
+ return False
return True
- def encryption_dict(self, model):
- return {**model, "hunyuan_secret_key": super().encryption(model.get("hunyuan_secret_key", ""))}
+ def encryption_dict(self, model: Dict[str, object]):
+ return {**model, "api_key": super().encryption(model.get("api_key", ""))}
- hunyuan_app_id = forms.TextInputField("APP ID", required=True)
- hunyuan_secret_id = forms.PasswordInputField("SecretId", required=True)
- hunyuan_secret_key = forms.PasswordInputField("SecretKey", required=True)
+ api_base = forms.TextInputField(
+ label=TooltipLabel(_("API URL"), _("TokenHub OpenAI compatible endpoint")),
+ required=True,
+ default_value="https://tokenhub.tencentmaas.com/v1",
+ )
+ api_key = forms.PasswordInputField(_("API Key"), required=True)
def get_model_params_setting_form(self, model_name):
return TencentLLMModelParams()
diff --git a/apps/models_provider/impl/tencent_model_provider/credential/tti.py b/apps/models_provider/impl/tencent_model_provider/credential/tti.py
index 3f77d2c8062..4d63943bcde 100644
--- a/apps/models_provider/impl/tencent_model_provider/credential/tti.py
+++ b/apps/models_provider/impl/tencent_model_provider/credential/tti.py
@@ -5,70 +5,87 @@
from common import forms
from common.exception.app_exception import AppApiException
from common.forms import BaseForm, TooltipLabel
-from models_provider.base_model_provider import BaseModelCredential, ValidCode
+from common.forms.switch_field import SwitchField
from common.utils.logger import maxkb_logger
+from models_provider.base_model_provider import BaseModelCredential, ValidCode
+
+# 37 preset sizes from the TokenHub Hy-Image docs (width x height, area <= 1024x1024).
+_HY_IMAGE_SIZES = [
+ "2048x512",
+ "1984x512",
+ "1920x512",
+ "1856x512",
+ "1792x512",
+ "1728x512",
+ "1664x512",
+ "1600x512",
+ "1536x512",
+ "1472x576",
+ "1408x640",
+ "1344x704",
+ "1280x768",
+ "1216x832",
+ "1152x896",
+ "1088x960",
+ "1024x1024",
+ "960x1088",
+ "896x1152",
+ "832x1216",
+ "768x1280",
+ "704x1344",
+ "640x1408",
+ "576x1472",
+ "512x1536",
+ "512x1600",
+ "512x1664",
+ "512x1728",
+ "512x1792",
+ "512x1856",
+ "512x1920",
+ "512x1984",
+ "512x2048",
+ "768x1024",
+ "720x1280",
+ "1024x768",
+ "1280x720",
+]
class TencentTTIModelParams(BaseForm):
- Style = forms.SingleSelect(
- TooltipLabel(_("painting style"), _("If not passed, the default value is 201 (Japanese anime style)")),
- required=True,
- default_value="201",
- option_list=[
- {"value": "000", "label": _("Not limited to style")},
- {"value": "101", "label": _("ink painting")},
- {"value": "102", "label": _("concept art")},
- {"value": "103", "label": _("Oil painting 1")},
- {"value": "118", "label": _("Oil Painting 2 (Van Gogh)")},
- {"value": "104", "label": _("watercolor painting")},
- {"value": "105", "label": _("pixel art")},
- {"value": "106", "label": _("impasto style")},
- {"value": "107", "label": _("illustration")},
- {"value": "108", "label": _("paper cut style")},
- {"value": "109", "label": _("Impressionism 1 (Monet)")},
- {"value": "119", "label": _("Impressionism 2")},
- {"value": "110", "label": "2.5D"},
- {"value": "111", "label": _("classical portraiture")},
- {"value": "112", "label": _("black and white sketch")},
- {"value": "113", "label": _("cyberpunk")},
- {"value": "114", "label": _("science fiction style")},
- {"value": "115", "label": _("dark style")},
- {"value": "116", "label": "3D"},
- {"value": "117", "label": _("vaporwave")},
- {"value": "201", "label": _("Japanese animation")},
- {"value": "202", "label": _("monster style")},
- {"value": "203", "label": _("Beautiful ancient style")},
- {"value": "204", "label": _("retro anime")},
- {"value": "301", "label": _("Game cartoon hand drawing")},
- {"value": "401", "label": _("Universal realistic style")},
- ],
+ size = forms.SingleSelect(
+ TooltipLabel(
+ _("Image size"),
+ _(
+ "Width and height must be in [512, 2048] and the area must not exceed 1024x1024. If not passed, the "
+ "model auto-selects the closest preset size."
+ ),
+ ),
+ required=False,
+ default_value="1024x1024",
+ option_list=[{"value": value, "label": value} for value in _HY_IMAGE_SIZES],
value_field="value",
text_field="label",
)
- Resolution = forms.SingleSelect(
- TooltipLabel(_("Generate image resolution"), _("If not transmitted, the default value is 768:768.")),
- required=True,
- default_value="768:768",
- option_list=[
- {"value": "768:768", "label": "768:768(1:1)"},
- {"value": "768:1024", "label": "768:1024(3:4)"},
- {"value": "1024:768", "label": "1024:768(4:3)"},
- {"value": "1024:1024", "label": "1024:1024(1:1)"},
- {"value": "720:1280", "label": "720:1280(9:16)"},
- {"value": "1280:720", "label": "1280:720(16:9)"},
- {"value": "768:1280", "label": "768:1280(3:5)"},
- {"value": "1280:768", "label": "1280:768(5:3)"},
- {"value": "1080:1920", "label": "1080:1920(9:16)"},
- {"value": "1920:1080", "label": "1920:1080(16:9)"},
- ],
- value_field="value",
- text_field="label",
+ revise = SwitchField(
+ TooltipLabel(
+ _("Prompt rewrite"), _("Whether the model should rewrite and optimize the prompt before generation.")
+ ),
+ attrs={"active-value": True, "inactive-value": False},
+ default_value=True,
+ )
+
+ footnote = forms.TextInputField(
+ TooltipLabel(
+ _("Watermark footnote"), _("Custom watermark content, at most 16 characters, drawn in the bottom-right.")
+ ),
+ required=False,
+ default_value="",
)
class TencentTTIModelCredential(BaseForm, BaseModelCredential):
- REQUIRED_FIELDS = ["hunyuan_secret_id", "hunyuan_secret_key"]
+ REQUIRED_FIELDS = ["api_key"]
@classmethod
def _validate_model_type(cls, model_type, provider, raise_exception=False):
@@ -114,10 +131,14 @@ def is_valid(self, model_type, model_name, model_credential, model_params, provi
return True
def encryption_dict(self, model):
- return {**model, "hunyuan_secret_key": super().encryption(model.get("hunyuan_secret_key", ""))}
+ return {**model, "api_key": super().encryption(model.get("api_key", ""))}
- hunyuan_secret_id = forms.PasswordInputField("SecretId", required=True)
- hunyuan_secret_key = forms.PasswordInputField("SecretKey", required=True)
+ base_url = forms.TextInputField(
+ label=TooltipLabel(_("API URL"), _("TokenHub Hy-Image v3-generation endpoint")),
+ required=False,
+ default_value="https://tokenhub.tencentmaas.com/v1/wand/hunyuan-image/v3-generation",
+ )
+ api_key = forms.PasswordInputField(_("API Key"), required=True)
def get_model_params_setting_form(self, model_name):
return TencentTTIModelParams()
diff --git a/apps/models_provider/impl/tencent_model_provider/credential/ttv.py b/apps/models_provider/impl/tencent_model_provider/credential/ttv.py
new file mode 100644
index 00000000000..48400feff94
--- /dev/null
+++ b/apps/models_provider/impl/tencent_model_provider/credential/ttv.py
@@ -0,0 +1,107 @@
+# coding=utf-8
+
+from django.utils.translation import gettext_lazy as _, gettext
+
+from common import forms
+from common.exception.app_exception import AppApiException
+from common.forms import BaseForm, TooltipLabel
+from common.forms.switch_field import SwitchField
+from common.utils.logger import maxkb_logger
+from models_provider.base_model_provider import BaseModelCredential, ValidCode
+
+
+class TencentVideoModelParams(BaseForm):
+ resolution = forms.SingleSelect(
+ TooltipLabel(_("Resolution"), _("Output video resolution: 480p, 720p, 1080p.")),
+ required=False,
+ default_value="720p",
+ option_list=[{"value": value, "label": value} for value in ["480p", "720p", "1080p"]],
+ value_field="value",
+ text_field="label",
+ )
+
+ fps = forms.SingleSelect(
+ TooltipLabel(_("Frame rate"), _("Output video frame rate: 16, 24, 30.")),
+ required=False,
+ default_value="30",
+ option_list=[{"value": value, "label": value} for value in ["16", "24", "30"]],
+ value_field="value",
+ text_field="label",
+ )
+
+ logo_add = SwitchField(
+ TooltipLabel(
+ _("Add logo"),
+ _(
+ "Whether to add the AI-generated logo to the video. 1: add logo; 0: no logo "
+ "(requires console approval for independent control)."
+ ),
+ ),
+ attrs={"active-value": 1, "inactive-value": 0},
+ default_value=1,
+ )
+
+
+class TencentTTVModelCredential(BaseForm, BaseModelCredential):
+ REQUIRED_FIELDS = ["api_key"]
+
+ @classmethod
+ def _validate_model_type(cls, model_type, provider, raise_exception=False):
+ if not any(mt["value"] == model_type for mt in provider.get_model_type_list()):
+ if raise_exception:
+ raise AppApiException(
+ ValidCode.valid_error.value,
+ gettext("{model_type} Model type is not supported").format(model_type=model_type),
+ )
+ return False
+ return True
+
+ @classmethod
+ def _validate_credential_fields(cls, model_credential, raise_exception=False):
+ missing_keys = [key for key in cls.REQUIRED_FIELDS if key not in model_credential]
+ if missing_keys:
+ if raise_exception:
+ raise AppApiException(
+ ValidCode.valid_error.value, gettext("{keys} is required").format(keys=", ".join(missing_keys))
+ )
+ return False
+ return True
+
+ def is_valid(self, model_type, model_name, model_credential, model_params, provider, raise_exception=False):
+ if not (
+ self._validate_model_type(model_type, provider, raise_exception)
+ and self._validate_credential_fields(model_credential, raise_exception)
+ ):
+ return False
+ try:
+ model = provider.get_model(model_type, model_name, model_credential, **model_params)
+ model.check_auth()
+ except Exception as e:
+ maxkb_logger.error(f"Exception: {e}", exc_info=True)
+ if raise_exception:
+ raise AppApiException(
+ ValidCode.valid_error.value,
+ gettext("Verification failed, please check whether the parameters are correct: {error}").format(
+ error=str(e)
+ ),
+ )
+ return False
+ return True
+
+ def encryption_dict(self, model):
+ return {**model, "api_key": super().encryption(model.get("api_key", ""))}
+
+ base_url = forms.TextInputField(
+ label=TooltipLabel(
+ _("API URL"),
+ _(
+ "TokenHub video endpoint. Use the base (e.g. https://tokenhub.tencentmaas.com/v1) or a full submit/query URL."
+ ),
+ ),
+ required=False,
+ default_value="https://tokenhub.tencentmaas.com/v1",
+ )
+ api_key = forms.PasswordInputField(_("API Key"), required=True)
+
+ def get_model_params_setting_form(self, model_name):
+ return TencentVideoModelParams()
diff --git a/apps/models_provider/impl/tencent_model_provider/icon/tencent_icon_svg b/apps/models_provider/impl/tencent_model_provider/icon/tencent_icon_svg
index 6cec08b74c2..622cc802394 100644
--- a/apps/models_provider/impl/tencent_model_provider/icon/tencent_icon_svg
+++ b/apps/models_provider/impl/tencent_model_provider/icon/tencent_icon_svg
@@ -1,5 +1,4 @@
-
+
+
\ No newline at end of file
diff --git a/apps/models_provider/impl/tencent_model_provider/model/embedding.py b/apps/models_provider/impl/tencent_model_provider/model/embedding.py
index a7893bbb48d..8357a30a76a 100644
--- a/apps/models_provider/impl/tencent_model_provider/model/embedding.py
+++ b/apps/models_provider/impl/tencent_model_provider/model/embedding.py
@@ -1,41 +1,84 @@
+# coding=utf-8
+
from typing import Dict, List
-from langchain_core.embeddings import Embeddings
-from tencentcloud.common import credential
-from tencentcloud.hunyuan.v20230901.hunyuan_client import HunyuanClient
-from tencentcloud.hunyuan.v20230901.models import GetEmbeddingRequest
+import requests
+from common.utils.logger import maxkb_logger
from models_provider.base_model_provider import MaxKBBaseEmbeddingModel
-class TencentEmbeddingModel(MaxKBBaseEmbeddingModel, Embeddings):
- def supports_image_embedding(self) -> bool:
- return False
+class TencentEmbeddingModel(MaxKBBaseEmbeddingModel):
+ """腾讯 TokenHub 向量模型(OpenAI Embeddings 兼容接口)。
- def embed_documents(self, texts: List[str]) -> List[List[float]]:
- return [self.embed_query(text) for text in texts]
+ 文本向量:POST /v1/embeddings
+ 多模态向量:POST /v1/embeddings/multimodal(kinfra-vl-embedding-* 支持文本、图片、视频)
+ """
- def embed_query(self, text: str) -> List[float]:
- request = GetEmbeddingRequest()
- request.Input = text
- res = self.client.GetEmbedding(request)
- return res.Data[0].Embedding
-
- def __init__(self, secret_id: str, secret_key: str, model_name: str):
- self.secret_id = secret_id
- self.secret_key = secret_key
+ DEFAULT_BASE_URL: str = "https://tokenhub.tencentmaas.com/v1"
+ REQUEST_TIMEOUT: tuple = (10, 60)
+
+ def __init__(self, api_key: str, model_name: str, base_url: str, params: dict = None):
+ self.api_key = api_key
self.model_name = model_name
- cred = credential.Credential(secret_id, secret_key)
- self.client = HunyuanClient(cred, "")
+ self.base_url = (base_url or self.DEFAULT_BASE_URL).rstrip("/")
+ self.params = params or {}
@staticmethod
- def new_instance(model_type: str, model_name: str, model_credential: Dict[str, str], **model_kwargs):
+ def is_cache_model():
+ return False
+
+ @staticmethod
+ def new_instance(model_type: str, model_name: str, model_credential: Dict[str, object], **model_kwargs):
+ optional_params = MaxKBBaseEmbeddingModel.filter_optional_params(model_kwargs)
return TencentEmbeddingModel(
- secret_id=model_credential.get("SecretId"),
- secret_key=model_credential.get("SecretKey"),
+ api_key=model_credential.get("api_key"),
model_name=model_name,
+ base_url=model_credential.get("base_url") or TencentEmbeddingModel.DEFAULT_BASE_URL,
+ params=optional_params,
)
- def _generate_auth_token(self):
- # Example method to generate an authentication token for the model API
- return f"{self.secret_id}:{self.secret_key}"
+ def supports_image_embedding(self) -> bool:
+ return "vl-embedding" in self.model_name
+
+ def _embedding_url(self) -> str:
+ if self.supports_image_embedding():
+ return f"{self.base_url}/embeddings/multimodal"
+ return f"{self.base_url}/embeddings"
+
+ def _post(self, payload: dict) -> dict:
+ headers = {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}
+ response = requests.post(self._embedding_url(), headers=headers, json=payload, timeout=self.REQUEST_TIMEOUT)
+ response.raise_for_status()
+ return response.json()
+
+ @staticmethod
+ def _extract_embedding(result: dict) -> List[float]:
+ data = result.get("data") or []
+ if not data:
+ maxkb_logger.error(f"Tencent TokenHub embedding returned no data: {result}")
+ raise RuntimeError("Tencent TokenHub embedding API returned no embedding")
+ return data[0].get("embedding", [])
+
+ def embed_documents(self, texts: List[str]) -> List[List[float]]:
+ if self.supports_image_embedding():
+ # 多模态接口单次请求融合为一个向量,逐条处理
+ return [self._embed_multimodal([{"type": "text", "text": text}]) for text in texts]
+ payload = {"model": self.model_name, "input": texts, "encoding_format": "float", **self.params}
+ result = self._post(payload)
+ return [item.get("embedding", []) for item in result.get("data", [])]
+
+ def embed_query(self, text: str) -> List[float]:
+ if self.supports_image_embedding():
+ return self._embed_multimodal([{"type": "text", "text": text}])
+ payload = {"model": self.model_name, "input": text, "encoding_format": "float", **self.params}
+ return self._extract_embedding(self._post(payload))
+
+ def embed_images(self, images: List[str]) -> List[List[float]]:
+ if not self.supports_image_embedding():
+ return []
+ return [self._embed_multimodal([{"type": "image_url", "image_url": {"url": url}}]) for url in images]
+
+ def _embed_multimodal(self, items: list) -> List[float]:
+ payload = {"model": self.model_name, "input": items, "encoding_format": "float", **self.params}
+ return self._extract_embedding(self._post(payload))
diff --git a/apps/models_provider/impl/tencent_model_provider/model/hunyuan.py b/apps/models_provider/impl/tencent_model_provider/model/hunyuan.py
deleted file mode 100644
index 9b97762c014..00000000000
--- a/apps/models_provider/impl/tencent_model_provider/model/hunyuan.py
+++ /dev/null
@@ -1,275 +0,0 @@
-import json
-import logging
-from typing import Any, Dict, Iterator, List, Mapping, Optional, Type
-
-from langchain_core.callbacks import CallbackManagerForLLMRun
-from langchain_core.language_models.chat_models import (
- BaseChatModel,
- generate_from_stream,
-)
-from langchain_core.messages import (
- AIMessage,
- AIMessageChunk,
- BaseMessage,
- BaseMessageChunk,
- ChatMessage,
- ChatMessageChunk,
- HumanMessage,
- HumanMessageChunk,
- SystemMessage,
-)
-from langchain_core.outputs import ChatGeneration, ChatGenerationChunk, ChatResult
-from pydantic import Field, SecretStr, root_validator
-from langchain_core.utils import (
- convert_to_secret_str,
- get_from_dict_or_env,
- get_pydantic_field_names,
- pre_init,
-)
-
-logger = logging.getLogger(__name__)
-
-
-def _convert_message_to_dict(message: BaseMessage) -> dict:
- message_dict: Dict[str, Any]
- if isinstance(message, ChatMessage):
- message_dict = {"Role": message.role, "Content": message.content}
- elif isinstance(message, HumanMessage):
- message_dict = {"Role": "user", "Content": message.content}
- elif isinstance(message, AIMessage):
- message_dict = {"Role": "assistant", "Content": message.content}
- elif isinstance(message, SystemMessage):
- message_dict = {"Role": "system", "Content": message.content}
- else:
- raise TypeError(f"Got unknown type {message}")
-
- return message_dict
-
-
-def _convert_dict_to_message(_dict: Mapping[str, Any]) -> BaseMessage:
- role = _dict["Role"]
- if role == "user":
- return HumanMessage(content=_dict["Content"])
- elif role == "assistant":
- return AIMessage(content=_dict.get("Content", "") or "")
- else:
- return ChatMessage(content=_dict["Content"], role=role)
-
-
-def _convert_delta_to_message_chunk(
- _dict: Mapping[str, Any], default_class: Type[BaseMessageChunk]
-) -> BaseMessageChunk:
- role = _dict.get("Role")
- content = _dict.get("Content") or ""
-
- if role == "user" or default_class == HumanMessageChunk:
- return HumanMessageChunk(content=content)
- elif role == "assistant" or default_class == AIMessageChunk:
- return AIMessageChunk(content=content)
- elif role or default_class == ChatMessageChunk:
- return ChatMessageChunk(content=content, role=role) # type: ignore[arg-type]
- else:
- return default_class(content=content) # type: ignore[call-arg]
-
-
-def _create_chat_result(response: Mapping[str, Any]) -> ChatResult:
- generations = []
- for choice in response["Choices"]:
- message = _convert_dict_to_message(choice["Message"])
- generations.append(ChatGeneration(message=message))
-
- token_usage = response["Usage"]
- llm_output = {"token_usage": token_usage}
- return ChatResult(generations=generations, llm_output=llm_output)
-
-
-class ChatHunyuan(BaseChatModel):
- """Tencent Hunyuan chat models API by Tencent.
-
- For more information, see https://cloud.tencent.com/document/product/1729
- """
-
- @property
- def lc_secrets(self) -> Dict[str, str]:
- return {
- "hunyuan_app_id": "HUNYUAN_APP_ID",
- "hunyuan_secret_id": "HUNYUAN_SECRET_ID",
- "hunyuan_secret_key": "HUNYUAN_SECRET_KEY",
- }
-
- @property
- def lc_serializable(self) -> bool:
- return True
-
- hunyuan_app_id: Optional[int] = None
- """Hunyuan App ID"""
- hunyuan_secret_id: Optional[str] = None
- """Hunyuan Secret ID"""
- hunyuan_secret_key: Optional[SecretStr] = None
- """Hunyuan Secret Key"""
- streaming: bool = False
- """Whether to stream the results or not."""
- request_timeout: int = 60
- """Timeout for requests to Hunyuan API. Default is 60 seconds."""
- temperature: float = 1.0
- """What sampling temperature to use."""
- top_p: float = 1.0
- """What probability mass to use."""
- model: str = "hunyuan-lite"
- """What Model to use.
- Optional model:
- - hunyuan-lite、
- - hunyuan-standard
- - hunyuan-standard-256K
- - hunyuan-pro
- - hunyuan-code
- - hunyuan-role
- - hunyuan-functioncall
- - hunyuan-vision
- """
- stream_moderation: bool = False
- """Whether to review the results or not when streaming is true."""
- enable_enhancement: bool = True
- """Whether to enhancement the results or not."""
-
- model_kwargs: Dict[str, Any] = Field(default_factory=dict)
- """Holds any model parameters valid for API call not explicitly specified."""
-
- class Config:
- """Configuration for this pydantic object."""
-
- validate_by_name = True
-
- @root_validator(pre=True)
- def build_extra(cls, values: Dict[str, Any]) -> Dict[str, Any]:
- """Build extra kwargs from additional params that were passed in."""
- all_required_field_names = get_pydantic_field_names(cls)
- extra = values.get("model_kwargs", {})
- for field_name in list(values):
- if field_name in extra:
- raise ValueError(f"Found {field_name} supplied twice.")
- if field_name not in all_required_field_names:
- logger.warning(
- f"""WARNING! {field_name} is not default parameter.
- {field_name} was transferred to model_kwargs.
- Please confirm that {field_name} is what you intended."""
- )
- extra[field_name] = values.pop(field_name)
-
- invalid_model_kwargs = all_required_field_names.intersection(extra.keys())
- if invalid_model_kwargs:
- raise ValueError(
- f"Parameters {invalid_model_kwargs} should be specified explicitly. "
- f"Instead they were passed in as part of `model_kwargs` parameter."
- )
-
- values["model_kwargs"] = extra
- return values
-
- @pre_init
- def validate_environment(cls, values: Dict) -> Dict:
- values["hunyuan_app_id"] = get_from_dict_or_env(
- values,
- "hunyuan_app_id",
- "HUNYUAN_APP_ID",
- )
- values["hunyuan_secret_id"] = get_from_dict_or_env(
- values,
- "hunyuan_secret_id",
- "HUNYUAN_SECRET_ID",
- )
- values["hunyuan_secret_key"] = convert_to_secret_str(
- get_from_dict_or_env(
- values,
- "hunyuan_secret_key",
- "HUNYUAN_SECRET_KEY",
- )
- )
- return values
-
- @property
- def _default_params(self) -> Dict[str, Any]:
- """Get the default parameters for calling Hunyuan API."""
- normal_params = {
- "Temperature": self.temperature,
- "TopP": self.top_p,
- "Model": self.model,
- "Stream": self.streaming,
- "StreamModeration": self.stream_moderation,
- "EnableEnhancement": self.enable_enhancement,
- }
- return {**normal_params, **self.model_kwargs}
-
- def _generate(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> ChatResult:
- if self.streaming:
- stream_iter = self._stream(messages=messages, stop=stop, run_manager=run_manager, **kwargs)
- return generate_from_stream(stream_iter)
-
- res = self._chat(messages, **kwargs)
- return _create_chat_result(json.loads(res.to_json_string()))
-
- usage_metadata: dict = {}
-
- def _stream(
- self,
- messages: List[BaseMessage],
- stop: Optional[List[str]] = None,
- run_manager: Optional[CallbackManagerForLLMRun] = None,
- **kwargs: Any,
- ) -> Iterator[ChatGenerationChunk]:
- res = self._chat(messages, **kwargs)
-
- default_chunk_class = AIMessageChunk
- for chunk in res:
- chunk = chunk.get("data", "")
- if len(chunk) == 0:
- continue
- response = json.loads(chunk)
- if "error" in response:
- raise ValueError(f"Error from Hunyuan api response: {response}")
-
- for choice in response["Choices"]:
- chunk = _convert_delta_to_message_chunk(choice["Delta"], default_chunk_class)
- default_chunk_class = chunk.__class__
- # FinishReason === stop
- if choice.get("FinishReason") == "stop":
- self.usage_metadata = response.get("Usage", {})
- cg_chunk = ChatGenerationChunk(message=chunk)
- if run_manager:
- run_manager.on_llm_new_token(chunk.content, chunk=cg_chunk)
- yield cg_chunk
-
- def _chat(self, messages: List[BaseMessage], **kwargs: Any) -> Any:
- if self.hunyuan_secret_key is None:
- raise ValueError("Hunyuan secret key is not set.")
-
- try:
- from tencentcloud.common import credential
- from tencentcloud.hunyuan.v20230901 import hunyuan_client, models
- except ImportError:
- raise ImportError(
- "Could not import tencentcloud python package. "
- "Please install it with `pip install tencentcloud-sdk-python`."
- )
-
- parameters = {**self._default_params, **kwargs}
- cred = credential.Credential(self.hunyuan_secret_id, str(self.hunyuan_secret_key.get_secret_value()))
- client = hunyuan_client.HunyuanClient(cred, "")
- req = models.ChatCompletionsRequest()
- params = {
- "Messages": [_convert_message_to_dict(m) for m in messages],
- **parameters,
- }
- req.from_json_string(json.dumps(params))
- resp = client.ChatCompletions(req)
- return resp
-
- @property
- def _llm_type(self) -> str:
- return "hunyuan-chat"
diff --git a/apps/models_provider/impl/tencent_model_provider/model/image.py b/apps/models_provider/impl/tencent_model_provider/model/image.py
index 19894c05557..617a2361ac0 100644
--- a/apps/models_provider/impl/tencent_model_provider/model/image.py
+++ b/apps/models_provider/impl/tencent_model_provider/model/image.py
@@ -10,7 +10,7 @@ def new_instance(model_type, model_name, model_credential: Dict[str, object], **
optional_params = MaxKBBaseModel.filter_optional_params(model_kwargs)
return TencentVision(
model_name=model_name,
- openai_api_base=model_credential.get("api_base") or "https://api.hunyuan.cloud.tencent.com/v1",
+ openai_api_base=model_credential.get("api_base") or "https://tokenhub.tencentmaas.com/v1",
openai_api_key=model_credential.get("api_key"),
# stream_options={"include_usage": True},
streaming=True,
diff --git a/apps/models_provider/impl/tencent_model_provider/model/llm.py b/apps/models_provider/impl/tencent_model_provider/model/llm.py
index 274c3b80bc7..151e0973ec8 100644
--- a/apps/models_provider/impl/tencent_model_provider/model/llm.py
+++ b/apps/models_provider/impl/tencent_model_provider/model/llm.py
@@ -1,51 +1,54 @@
# coding=utf-8
-from typing import List, Dict, Optional, Any
+from typing import Dict, List
-from langchain_core.messages import BaseMessage
+from langchain_core.messages import BaseMessage, get_buffer_string
+from common.config.tokenizer_manage_config import TokenizerManage
from models_provider.base_model_provider import MaxKBBaseModel
-from models_provider.impl.tencent_model_provider.model.hunyuan import ChatHunyuan
+from models_provider.impl.base_chat_open_ai import BaseChatOpenAI
-class TencentModel(MaxKBBaseModel, ChatHunyuan):
- @staticmethod
- def is_cache_model():
- return False
+def custom_get_token_ids(text: str):
+ tokenizer = TokenizerManage.get_tokenizer()
+ return tokenizer.encode(text)
- def __init__(self, model_name: str, credentials: Dict[str, str], streaming: bool = False, **kwargs):
- hunyuan_app_id = credentials.get("hunyuan_app_id")
- hunyuan_secret_id = credentials.get("hunyuan_secret_id")
- hunyuan_secret_key = credentials.get("hunyuan_secret_key")
- optional_params = MaxKBBaseModel.filter_optional_params(kwargs)
+class TencentModel(MaxKBBaseModel, BaseChatOpenAI):
+ """Tencent TokenHub LLM model.
- if not all([hunyuan_app_id, hunyuan_secret_id, hunyuan_secret_key]):
- raise ValueError(
- "All of 'hunyuan_app_id', 'hunyuan_secret_id', and 'hunyuan_secret_key' must be provided in credentials."
- )
+ TokenHub aggregates Tencent Hunyuan and other providers behind an
+ OpenAI Chat Completions compatible API, see
+ https://cloud.tencent.com/document/product/1823/132252
+ """
- super().__init__(
+ @staticmethod
+ def is_cache_model():
+ return False
+
+ @staticmethod
+ def new_instance(model_type, model_name, model_credential: Dict[str, object], **model_kwargs):
+ optional_params = MaxKBBaseModel.filter_optional_params(model_kwargs)
+ streaming = model_kwargs.get("streaming", False)
+ return TencentModel(
model=model_name,
- hunyuan_app_id=hunyuan_app_id,
- hunyuan_secret_id=hunyuan_secret_id,
- hunyuan_secret_key=hunyuan_secret_key,
+ openai_api_base=model_credential.get("api_base"),
+ openai_api_key=model_credential.get("api_key"),
streaming=streaming,
- temperature=optional_params.get("temperature", 1.0),
+ custom_get_token_ids=custom_get_token_ids,
+ **optional_params,
)
- @staticmethod
- def new_instance(
- model_type: str, model_name: str, model_credential: Dict[str, object], **model_kwargs
- ) -> "TencentModel":
- streaming = model_kwargs.pop("streaming", False)
- return TencentModel(model_name=model_name, credentials=model_credential, streaming=streaming, **model_kwargs)
-
- def get_last_generation_info(self) -> Optional[Dict[str, Any]]:
- return self.usage_metadata
-
def get_num_tokens_from_messages(self, messages: List[BaseMessage]) -> int:
- return self.usage_metadata.get("PromptTokens", 0)
+ try:
+ return super().get_num_tokens_from_messages(messages)
+ except Exception:
+ tokenizer = TokenizerManage.get_tokenizer()
+ return sum([len(tokenizer.encode(get_buffer_string([m]))) for m in messages])
def get_num_tokens(self, text: str) -> int:
- return self.usage_metadata.get("CompletionTokens", 0)
+ try:
+ return super().get_num_tokens(text)
+ except Exception:
+ tokenizer = TokenizerManage.get_tokenizer()
+ return len(tokenizer.encode(text))
diff --git a/apps/models_provider/impl/tencent_model_provider/model/tti.py b/apps/models_provider/impl/tencent_model_provider/model/tti.py
index 290858a3467..8dcc73dd2c9 100644
--- a/apps/models_provider/impl/tencent_model_provider/model/tti.py
+++ b/apps/models_provider/impl/tencent_model_provider/model/tti.py
@@ -1,90 +1,79 @@
# coding=utf-8
-import json
-from typing import Dict
+import traceback
+from typing import Dict, Optional
+import requests
from django.utils.translation import gettext as _
-from tencentcloud.common import credential
-from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
-from tencentcloud.common.profile.client_profile import ClientProfile
-from tencentcloud.common.profile.http_profile import HttpProfile
-from tencentcloud.hunyuan.v20230901 import hunyuan_client, models
from common.utils.logger import maxkb_logger
from models_provider.base_model_provider import MaxKBBaseModel
from models_provider.impl.base_tti import BaseTextToImage
-from models_provider.impl.tencent_model_provider.model.hunyuan import ChatHunyuan
+
+
+DEFAULT_WAND_IMAGE_BASE_URL = "https://tokenhub.tencentmaas.com/v1/wand/hunyuan-image/v3-generation"
class TencentTextToImageModel(MaxKBBaseModel, BaseTextToImage):
- hunyuan_secret_id: str
- hunyuan_secret_key: str
+ api_key: str
model: str
params: dict
+ base_url: Optional[str] = DEFAULT_WAND_IMAGE_BASE_URL
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.api_key = kwargs.get("api_key")
+ self.model = kwargs.get("model")
+ self.params = kwargs.get("params") or {}
+ self.base_url = kwargs.get("base_url") or DEFAULT_WAND_IMAGE_BASE_URL
@staticmethod
def is_cache_model():
return False
- def __init__(self, **kwargs):
- super().__init__(**kwargs)
- self.hunyuan_secret_id = kwargs.get("hunyuan_secret_id")
- self.hunyuan_secret_key = kwargs.get("hunyuan_secret_key")
- self.model = kwargs.get("model_name")
- self.params = kwargs.get("params")
-
@staticmethod
def new_instance(
model_type: str, model_name: str, model_credential: Dict[str, object], **model_kwargs
) -> "TencentTextToImageModel":
- optional_params = {"params": {"Style": "201", "Resolution": "768:768"}}
+ optional_params = {"params": {"size": "1024x1024"}}
for key, value in model_kwargs.items():
if key not in ["model_id", "use_local", "streaming"]:
optional_params["params"][key] = value
- return TencentTextToImageModel(
- model=model_name,
- hunyuan_secret_id=model_credential.get("hunyuan_secret_id"),
- hunyuan_secret_key=model_credential.get("hunyuan_secret_key"),
+ instance_kwargs = {
+ "api_key": model_credential.get("api_key"),
+ "model": model_name,
+ "params": optional_params["params"],
**optional_params,
- )
+ }
+ base_url = model_credential.get("base_url")
+ if base_url:
+ instance_kwargs["base_url"] = base_url
+ return TencentTextToImageModel(**instance_kwargs)
def check_auth(self):
- chat = ChatHunyuan(
- hunyuan_app_id="111111",
- hunyuan_secret_id=self.hunyuan_secret_id,
- hunyuan_secret_key=self.hunyuan_secret_key,
- model="hunyuan-standard",
- )
- res = chat.invoke(_("Hello"))
- # print(res)
+ self.generate_image(_("Hello"), None)
def generate_image(self, prompt: str, negative_prompt: str = None):
try:
- # 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
- # 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
- # 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
- cred = credential.Credential(self.hunyuan_secret_id, self.hunyuan_secret_key)
- # 实例化一个http选项,可选的,没有特殊需求可以跳过
- httpProfile = HttpProfile()
- httpProfile.endpoint = "hunyuan.tencentcloudapi.com"
-
- # 实例化一个client选项,可选的,没有特殊需求可以跳过
- clientProfile = ClientProfile()
- clientProfile.httpProfile = httpProfile
- # 实例化要请求产品的client对象,clientProfile是可选的
- client = hunyuan_client.HunyuanClient(cred, "ap-guangzhou", clientProfile)
-
- # 实例化一个请求对象,每个接口都会对应一个request对象
- req = models.TextToImageLiteRequest()
- params = {"Prompt": prompt, "NegativePrompt": negative_prompt, "RspImgType": "url", **self.params}
- req.from_json_string(json.dumps(params))
-
- # 返回的resp是一个TextToImageLiteResponse的实例,与请求对象对应
- resp = client.TextToImageLite(req)
+ payload = {"model": self.model, "prompt": prompt}
+ payload.update({key: value for key, value in self.params.items() if value not in (None, "")})
+ headers = {
+ "Authorization": f"Bearer {self.api_key}",
+ "Content-Type": "application/json",
+ }
+ response = requests.post(self.base_url, headers=headers, json=payload, timeout=300)
+ response.raise_for_status()
+ result = response.json()
+ data = result.get("data") or []
file_urls = []
-
- file_urls.append(resp.ResultImage)
+ for item in data:
+ url = item.get("url")
+ if url:
+ file_urls.append(url)
+ if not file_urls:
+ maxkb_logger.error(f"Tencent Text to Image API returned no urls: {result}")
+ raise RuntimeError("Tencent Text to Image API returned no image urls")
return file_urls
- except TencentCloudSDKException as err:
- maxkb_logger.error(f"Tencent Text to Image API call failed: {err}")
+ except requests.RequestException as err:
+ maxkb_logger.error(f"Tencent Text to Image API call failed: {err}: {traceback.format_exc()}")
raise RuntimeError(f"Tencent Text to Image API call failed: {err}") from err
diff --git a/apps/models_provider/impl/tencent_model_provider/model/ttv.py b/apps/models_provider/impl/tencent_model_provider/model/ttv.py
new file mode 100644
index 00000000000..d01709bf18f
--- /dev/null
+++ b/apps/models_provider/impl/tencent_model_provider/model/ttv.py
@@ -0,0 +1,152 @@
+# coding=utf-8
+
+import time
+from typing import ClassVar, Dict
+
+import requests
+
+from common.utils.logger import maxkb_logger
+from models_provider.base_model_provider import MaxKBBaseModel
+from models_provider.base_ttv import BaseGenerationVideo
+
+
+class TencentVideoModel(MaxKBBaseModel, BaseGenerationVideo):
+ """腾讯混元/优图视频生成模型(TokenHub OpenAI 兼容视频接口)。
+
+ 同时兼容文生视频(HY-Video-1.5)与图生视频/首尾帧(YT-Video-2.0):
+ - 提交任务:POST /v1/api/video/submit
+ - 查询任务:POST /v1/api/video/query
+ """
+
+ DEFAULT_BASE_URL: ClassVar[str] = "https://tokenhub.tencentmaas.com/v1"
+ REQUEST_TIMEOUT: ClassVar[tuple] = (10, 120) # (连接超时, 读取超时)
+ MAX_POLL_ATTEMPTS: ClassVar[int] = 120 # 最多轮询 120 次(约 6 分钟)
+ POLL_INTERVAL: ClassVar[int] = 3 # 秒
+ COMPLETED_STATUS: ClassVar[str] = "completed"
+ FAILED_STATUSES: ClassVar[frozenset] = frozenset({"failed", "error", "cancelled", "canceled"})
+
+ api_key: str
+ model_name: str
+ params: dict = {}
+ base_url: str = DEFAULT_BASE_URL
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ self.api_key = kwargs.get("api_key")
+ self.model_name = kwargs.get("model_name")
+ self.params = kwargs.get("params") or {}
+ self.base_url = (kwargs.get("base_url") or self.DEFAULT_BASE_URL).rstrip("/")
+
+ @staticmethod
+ def is_cache_model():
+ return False
+
+ @staticmethod
+ def new_instance(
+ model_type: str, model_name: str, model_credential: Dict[str, object], **model_kwargs
+ ) -> "TencentVideoModel":
+ optional_params = {"params": {}}
+ for key, value in model_kwargs.items():
+ if key not in ["model_id", "use_local", "streaming"]:
+ optional_params["params"][key] = value
+ return TencentVideoModel(
+ api_key=model_credential.get("api_key"),
+ model_name=model_name,
+ base_url=model_credential.get("base_url") or TencentVideoModel.DEFAULT_BASE_URL,
+ **optional_params,
+ )
+
+ def _endpoints(self) -> tuple:
+ """根据 base_url 推导 submit/query 地址。
+
+ base_url 可以是根地址(如 https://tokenhub.tencentmaas.com/v1),
+ 也可以是完整的 submit 或 query 地址,均能正确推导出两个接口地址。
+ """
+ base = self.base_url.rstrip("/")
+ if "/api/video/submit" in base:
+ submit = base
+ query = base[: base.index("/api/video/submit")] + "/api/video/query"
+ elif "/api/video/query" in base:
+ query = base
+ submit = base[: base.index("/api/video/query")] + "/api/video/submit"
+ else:
+ submit = f"{base}/api/video/submit"
+ query = f"{base}/api/video/query"
+ return submit, query
+
+ @property
+ def submit_url(self) -> str:
+ return self._endpoints()[0]
+
+ @property
+ def query_url(self) -> str:
+ return self._endpoints()[1]
+
+ def check_auth(self):
+ if not self.api_key:
+ raise RuntimeError("api_key is required")
+ return True
+
+ def _headers(self) -> dict:
+ return {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}
+
+ def _build_payload(self, prompt: str, first_frame_url=None, last_frame_url=None) -> dict:
+ payload = {"model": self.model_name, "prompt": prompt}
+ # 图生视频/首尾帧模式:优先使用首帧,其次使用尾帧作为输入图片
+ image_url = first_frame_url or last_frame_url
+ if image_url:
+ payload["image"] = {"url": image_url}
+ # 合并模型参数(resolution、fps、logo_add 等),过滤空值
+ for key, value in self.params.items():
+ if value not in (None, ""):
+ payload[key] = value
+ return payload
+
+ def _submit(self, prompt: str, first_frame_url=None, last_frame_url=None):
+ payload = self._build_payload(prompt, first_frame_url, last_frame_url)
+ maxkb_logger.info(f"提交腾讯视频生成任务,模型: {self.model_name}, url: {self.submit_url}")
+ response = requests.post(self.submit_url, headers=self._headers(), json=payload, timeout=self.REQUEST_TIMEOUT)
+ response.raise_for_status()
+ result = response.json()
+ task_id = result.get("id")
+ if not task_id:
+ raise RuntimeError(f"腾讯视频提交任务失败,未获取到 id: {result}")
+ return task_id, result.get("status")
+
+ def _query(self, task_id: str) -> dict:
+ payload = {"model": self.model_name, "id": task_id}
+ response = requests.post(self.query_url, headers=self._headers(), json=payload, timeout=self.REQUEST_TIMEOUT)
+ response.raise_for_status()
+ return response.json()
+
+ def _wait_for_result(self, task_id: str) -> dict:
+ for attempt in range(1, self.MAX_POLL_ATTEMPTS + 1):
+ result = self._query(task_id)
+ status = result.get("status")
+ maxkb_logger.info(
+ f"查询腾讯视频任务 {task_id} 状态: {status}, 进度: {result.get('progress')}, 第 {attempt} 次"
+ )
+ if status == self.COMPLETED_STATUS:
+ return result
+ if status in self.FAILED_STATUSES:
+ message = (
+ result.get("message")
+ or result.get("error_message")
+ or result.get("error")
+ or result.get("msg")
+ or "未知错误"
+ )
+ raise RuntimeError(f"腾讯视频任务 {task_id} 执行失败: {message}")
+ time.sleep(self.POLL_INTERVAL)
+ raise RuntimeError(f"腾讯视频任务 {task_id} 轮询超时({self.MAX_POLL_ATTEMPTS * self.POLL_INTERVAL} 秒)")
+
+ def generate_video(
+ self, prompt: str, negative_prompt: str = None, first_frame_url=None, last_frame_url=None, **kwargs
+ ):
+ task_id, _ = self._submit(prompt, first_frame_url, last_frame_url)
+ result = self._wait_for_result(task_id)
+ data = result.get("data") or {}
+ video_url = data.get("url")
+ if not video_url:
+ raise RuntimeError(f"腾讯视频任务完成但未获取到视频 URL: {result}")
+ return video_url
diff --git a/apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py b/apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
index 6d7c8fdcffb..336a47dc079 100644
--- a/apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
+++ b/apps/models_provider/impl/tencent_model_provider/tencent_model_provider.py
@@ -16,11 +16,13 @@
from models_provider.impl.tencent_model_provider.credential.stt import TencentSTTModelCredential
from models_provider.impl.tencent_model_provider.credential.tokenhub_stt import TencentTokenhubSTTModelCredential
from models_provider.impl.tencent_model_provider.credential.tti import TencentTTIModelCredential
+from models_provider.impl.tencent_model_provider.credential.ttv import TencentTTVModelCredential
from models_provider.impl.tencent_model_provider.model.embedding import TencentEmbeddingModel
from models_provider.impl.tencent_model_provider.model.image import TencentVision
from models_provider.impl.tencent_model_provider.model.llm import TencentModel
from models_provider.impl.tencent_model_provider.model.stt import TencentSpeechToText, TencentWandSpeechToText
from models_provider.impl.tencent_model_provider.model.tti import TencentTextToImageModel
+from models_provider.impl.tencent_model_provider.model.ttv import TencentVideoModel
from maxkb.conf import PROJECT_DIR
from django.utils.translation import gettext as _
@@ -44,55 +46,61 @@ def _get_tencent_icon_path():
def _initialize_model_info():
model_info_list = [
_create_model_info(
- "hunyuan-pro",
- _(
- "The most effective version of the current hybrid model, the trillion-level parameter scale MOE-32K long article model. Reaching the absolute leading level on various benchmarks, with complex instructions and reasoning, complex mathematical capabilities, support for function call, and application focus optimization in fields such as multi-language translation, finance, law, and medical care"
- ),
+ "hy4-preview",
+ _("The latest generation productivity model with upgraded Agent and complex task execution capabilities."),
ModelTypeConst.LLM,
TencentLLMModelCredential,
TencentModel,
),
_create_model_info(
- "hunyuan-standard",
+ "hy3",
_(
- "A better routing strategy is adopted to simultaneously alleviate the problems of load balancing and expert convergence. For long articles, the needle-in-a-haystack index reaches 99.9%"
+ "Tuned on real business scenarios, balancing effectiveness and cost-effectiveness, with reinforced Coding, long-text, reasoning and Agent capabilities."
),
ModelTypeConst.LLM,
TencentLLMModelCredential,
TencentModel,
),
_create_model_info(
- "hunyuan-lite",
+ "hy3-preview",
_(
- "Upgraded to MOE structure, the context window is 256k, leading many open source models in multiple evaluation sets such as NLP, code, mathematics, industry, etc."
+ "Designed for Agent workloads, using a MoE architecture that supports interleaved thinking, structured output, Function Calling and Cache caching."
),
ModelTypeConst.LLM,
TencentLLMModelCredential,
TencentModel,
),
_create_model_info(
- "hunyuan-role",
- _(
- "Hunyuan's latest version of the role-playing model, a role-playing model launched by Hunyuan's official fine-tuning training, is based on the Hunyuan model combined with the role-playing scene data set for additional training, and has better basic effects in role-playing scenes."
- ),
+ "hy-mt2-pro",
+ _("Tencent Hybrid multilingual translation model."),
ModelTypeConst.LLM,
TencentLLMModelCredential,
TencentModel,
),
_create_model_info(
- "hunyuan-functioncall",
- _(
- "Hunyuan's latest MOE architecture FunctionCall model has been trained with high-quality FunctionCall data and has a context window of 32K, leading in multiple dimensions of evaluation indicators."
- ),
+ "hy-mt2-plus",
+ _("Tencent Hybrid multilingual translation model."),
ModelTypeConst.LLM,
TencentLLMModelCredential,
TencentModel,
),
_create_model_info(
- "hunyuan-code",
- _(
- "Hunyuan's latest code generation model, after training the base model with 200B high-quality code data, and iterating on high-quality SFT data for half a year, the context long window length has been increased to 8K, and it ranks among the top in the automatic evaluation indicators of code generation in the five major languages; the five major languages In the manual high-quality evaluation of 10 comprehensive code tasks that consider all aspects, the performance is in the first echelon."
- ),
+ "hy-mt2-lite",
+ _("Tencent Hybrid multilingual translation model."),
+ ModelTypeConst.LLM,
+ TencentLLMModelCredential,
+ TencentModel,
+ ),
+ _create_model_info(
+ "hunyuan-role-latest",
+ _("Hunyuan's latest role-playing model based on the Hunyuan model with role-playing scene fine-tuning."),
+ ModelTypeConst.LLM,
+ TencentLLMModelCredential,
+ TencentModel,
+ ),
+ _create_model_info(
+ "hy-role",
+ _("Hunyuan's role-playing model with better basic effects in role-playing scenarios."),
ModelTypeConst.LLM,
TencentLLMModelCredential,
TencentModel,
@@ -114,17 +122,37 @@ def _initialize_model_info():
),
]
- tencent_embedding_model_info = _create_model_info(
- "hunyuan-embedding",
- _(
- "Tencent's Hunyuan Embedding interface can convert text into high-quality vector data. The vector dimension is 1024 dimensions."
+ model_info_embedding_list = [
+ _create_model_info(
+ "kinfra-text-embedding-0.6b",
+ _("Tencent TokenHub text embedding model, 1024 dimensions."),
+ ModelTypeConst.EMBEDDING,
+ TencentEmbeddingCredential,
+ TencentEmbeddingModel,
),
- ModelTypeConst.EMBEDDING,
- TencentEmbeddingCredential,
- TencentEmbeddingModel,
- )
-
- model_info_embedding_list = [tencent_embedding_model_info]
+ _create_model_info(
+ "kinfra-text-embedding-4b",
+ _("Tencent TokenHub text embedding model, 2560 dimensions."),
+ ModelTypeConst.EMBEDDING,
+ TencentEmbeddingCredential,
+ TencentEmbeddingModel,
+ ),
+ _create_model_info(
+ "kinfra-vl-embedding-2b",
+ _("Tencent TokenHub multimodal embedding model, 2048 dimensions."),
+ ModelTypeConst.EMBEDDING,
+ TencentEmbeddingCredential,
+ TencentEmbeddingModel,
+ ),
+ _create_model_info(
+ "kinfra-vl-embedding-8b",
+ _("Tencent TokenHub multimodal embedding model, 4096 dimensions."),
+ ModelTypeConst.EMBEDDING,
+ TencentEmbeddingCredential,
+ TencentEmbeddingModel,
+ ),
+ ]
+ tencent_embedding_model_info = model_info_embedding_list[0]
model_info_vision_list = [
_create_model_info(
@@ -138,14 +166,41 @@ def _initialize_model_info():
model_info_tti_list = [
_create_model_info(
- "hunyuan-dit",
- _("Hunyuan graph model"),
+ "hy-image-v3",
+ _("Hunyuan Hy-Image 3.0 text-to-image model."),
ModelTypeConst.TTI,
TencentTTIModelCredential,
TencentTextToImageModel,
)
]
+ model_info_ttv_list = [
+ _create_model_info(
+ "hy-video-1.5",
+ _("Hunyuan HY-Video 1.5 text-to-video model."),
+ ModelTypeConst.TTV,
+ TencentTTVModelCredential,
+ TencentVideoModel,
+ )
+ ]
+
+ model_info_itv_list = [
+ _create_model_info(
+ "hy-video-1.5",
+ _("Hunyuan HY-Video 1.5 image-to-video model."),
+ ModelTypeConst.ITV,
+ TencentTTVModelCredential,
+ TencentVideoModel,
+ ),
+ _create_model_info(
+ "yt-video-2.0",
+ _("Tencent YT-Video 2.0 image-to-video model."),
+ ModelTypeConst.ITV,
+ TencentTTVModelCredential,
+ TencentVideoModel,
+ ),
+ ]
+
model_info_manage = (
ModelInfoManage.builder()
.append_model_info_list(model_info_list)
@@ -154,6 +209,10 @@ def _initialize_model_info():
.append_default_model_info(model_info_vision_list[0])
.append_model_info_list(model_info_tti_list)
.append_default_model_info(model_info_tti_list[0])
+ .append_model_info_list(model_info_ttv_list)
+ .append_default_model_info(model_info_ttv_list[0])
+ .append_model_info_list(model_info_itv_list)
+ .append_default_model_info(model_info_itv_list[0])
.append_default_model_info(model_info_list[0])
.append_default_model_info(tencent_embedding_model_info)
.build()