From 72ddb94979b56ca417ded19d8f29b5b3e5bccdb5 Mon Sep 17 00:00:00 2001 From: zhulj <1643600218@qq.com> Date: Thu, 20 Jun 2024 09:10:36 +0800 Subject: [PATCH 1/3] feat: add tencent hunyuan api --- config/examples/tencent-hunyuan.yaml | 6 ++ metagpt/configs/llm_config.py | 5 ++ metagpt/provider/__init__.py | 2 + metagpt/provider/hunyuan_api.py | 108 +++++++++++++++++++++++++++ metagpt/utils/token_counter.py | 10 +++ requirements.txt | 3 +- 6 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 config/examples/tencent-hunyuan.yaml create mode 100644 metagpt/provider/hunyuan_api.py diff --git a/config/examples/tencent-hunyuan.yaml b/config/examples/tencent-hunyuan.yaml new file mode 100644 index 000000000..fbf5f1ee1 --- /dev/null +++ b/config/examples/tencent-hunyuan.yaml @@ -0,0 +1,6 @@ +llm: + api_type: "hunyuan" # 腾讯混元大模型 + model: "hunyuan-standard" # 可选 hunyuan-lite、hunyuan-standard 、hunyuan-standard-256K、hunyuan-pro + endpoint: "hunyuan.tencentcloudapi.com" #默认 hunyuan.tencentcloudapi.com + secret_id: "" #腾讯云账户 SecretId 和 SecretKey,请注意保密。申请链接:https://console.cloud.tencent.com/cam/capi + secret_key: "" diff --git a/metagpt/configs/llm_config.py b/metagpt/configs/llm_config.py index 12bb8541e..c42f30bff 100644 --- a/metagpt/configs/llm_config.py +++ b/metagpt/configs/llm_config.py @@ -34,6 +34,7 @@ class LLMType(Enum): OPENROUTER = "openrouter" BEDROCK = "bedrock" ARK = "ark" + HUNYUAN = "hunyuan" # Tencent Hunyuan def __missing__(self, key): return self.OPENAI @@ -59,6 +60,10 @@ class LLMConfig(YamlModel): secret_key: Optional[str] = None endpoint: Optional[str] = None # for self-deployed model on the cloud + # For Tencent Hunyuan + secret_id: Optional[str] = None + secret_key: Optional[str] = None + # For Spark(Xunfei), maybe remove later app_id: Optional[str] = None api_secret: Optional[str] = None diff --git a/metagpt/provider/__init__.py b/metagpt/provider/__init__.py index c90f5774a..e75991121 100644 --- a/metagpt/provider/__init__.py +++ b/metagpt/provider/__init__.py @@ -19,6 +19,7 @@ from metagpt.provider.anthropic_api import AnthropicLLM from metagpt.provider.bedrock_api import BedrockLLM from metagpt.provider.ark_api import ArkLLM +from metagpt.provider.hunyuan_api import HunYuanLLM __all__ = [ "GeminiLLM", @@ -34,4 +35,5 @@ "AnthropicLLM", "BedrockLLM", "ArkLLM", + "HunYuanLLM", ] diff --git a/metagpt/provider/hunyuan_api.py b/metagpt/provider/hunyuan_api.py new file mode 100644 index 000000000..ed73640f3 --- /dev/null +++ b/metagpt/provider/hunyuan_api.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +import json +import types + +from tencentcloud.common import credential +from tencentcloud.common.profile.client_profile import ClientProfile +from tencentcloud.common.profile.http_profile import HttpProfile +from tencentcloud.hunyuan.v20230901.hunyuan_client import HunyuanClient +from tencentcloud.hunyuan.v20230901.models import ( + ChatCompletionsRequest, + ChatCompletionsResponse, +) + +from metagpt.configs.llm_config import LLMConfig, LLMType +from metagpt.const import USE_CONFIG_TIMEOUT +from metagpt.logs import log_llm_stream +from metagpt.provider.base_llm import BaseLLM +from metagpt.provider.llm_provider_registry import register_provider +from metagpt.utils.cost_manager import CostManager +from metagpt.utils.token_counter import HUNYUAN_MODEL_TOKEN_COSTS + + +@register_provider(LLMType.HUNYUAN) +class HunYuanLLM(BaseLLM): + """参考资料 + 腾讯混元大模型产品概述:https://cloud.tencent.com/document/product/1729/104753 + 腾讯混元API接口说明:https://cloud.tencent.com/document/api/1729/105701 + 腾讯混元Python SDK源码:https://github.com/TencentCloud/tencentcloud-sdk-python/blob/master/tencentcloud/hunyuan/v20230901/models.py + 腾讯云控制台API密钥管理:https://console.cloud.tencent.com/cam/capi + """ + + def __init__(self, config: LLMConfig): + self.config = config + self.secret_id = self.config.secret_id + self.secret_key = self.config.secret_key + self.endpoint = self.config.endpoint + self.model = self.config.model + self.region = "" + self._init_client() + self.cost_manager = CostManager(token_costs=HUNYUAN_MODEL_TOKEN_COSTS) + + def _init_client(self): + """实例化一个认证客户端对象""" + cred = credential.Credential(self.secret_id, self.secret_key) + httpProfile = HttpProfile() + httpProfile.endpoint = self.endpoint + clientProfile = ClientProfile() + clientProfile.httpProfile = httpProfile + self.aclient: HunyuanClient = HunyuanClient(cred, self.region, clientProfile) + + def _format_messages(self, messages: list[dict]) -> list[dict]: + """将role和content转换为Role和Content""" + new_messages = [] + for message in messages: + new_messages.append({"Role": message["role"], "Content": message["content"]}) + return new_messages + + def _make_request( + self, + messages: list[dict], + timeout=USE_CONFIG_TIMEOUT, + stream=True, + ): + """构造请求参数对象""" + req = ChatCompletionsRequest() + params = { + "Model": self.model, + "Messages": self._format_messages(messages), + "Stream": stream, + } + req.from_json_string(json.dumps(params)) + return req + + async def _achat_completion(self, messages: list[dict], timeout=USE_CONFIG_TIMEOUT) -> ChatCompletionsResponse: + resp: ChatCompletionsResponse = self.aclient.ChatCompletions( + self._make_request(messages, timeout, stream=False) + ) + # 转换为字典格式 + usage = { + "prompt_tokens": resp.Usage.PromptTokens, + "completion_tokens": resp.Usage.CompletionTokens, + } + self._update_costs(usage) + return resp + + async def acompletion(self, messages: list[dict], timeout=USE_CONFIG_TIMEOUT) -> ChatCompletionsResponse: + return await self._achat_completion(messages, timeout) + + async def _achat_completion_stream(self, messages: list[dict], timeout: int = USE_CONFIG_TIMEOUT) -> str: + resp = self.aclient.ChatCompletions(self._make_request(messages, timeout, stream=True)) + full_reply_content = "" + usage = {} + if isinstance(resp, types.GeneratorType): # 流式响应 + for event in resp: + data = json.loads(event["data"]) + usage = data.get("Usage", {}) + for choice in data["Choices"]: + content = choice["Delta"]["Content"] + log_llm_stream(content) + full_reply_content += content + self._update_costs( + { + "prompt_tokens": usage.get("PromptTokens", 0), + "completion_tokens": usage.get("CompletionTokens", 0), + } + ) + log_llm_stream("\n") + return full_reply_content diff --git a/metagpt/utils/token_counter.py b/metagpt/utils/token_counter.py index ef6f886e2..481c1f599 100644 --- a/metagpt/utils/token_counter.py +++ b/metagpt/utils/token_counter.py @@ -79,6 +79,16 @@ "llama3-8b-llama3-8b-instruct": {"prompt": 0.0, "completion": 0.0}, } +""" +腾讯混元大模型价格说明:https://cloud.tencent.com/document/product/1729/97731 +""" +HUNYUAN_MODEL_TOKEN_COSTS = { + "hunyuan-pro": {"prompt": 0.03, "completion": 0.1}, + "hunyuan-standard": {"prompt": 0.0045, "completion": 0.005}, + "hunyuan-standard-256k": {"prompt": 0.015, "completion": 0.06}, + "hunyuan-lite": {"prompt": 0.0, "completion": 0.0}, + "hunyuan-embedding": {"prompt": 0.0007, "completion": 0.0007}, +} """ QianFan Token Price https://cloud.baidu.com/doc/WENXINWORKSHOP/s/hlrk4akp7#tokens%E5%90%8E%E4%BB%98%E8%B4%B9 diff --git a/requirements.txt b/requirements.txt index 240ab2300..7f7ad3b0f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -71,4 +71,5 @@ dashscope==1.14.1 rank-bm25==0.2.2 # for tool recommendation gymnasium==0.29.1 boto3~=1.34.69 -spark_ai_python~=0.3.30 \ No newline at end of file +spark_ai_python~=0.3.30 +tencentcloud-sdk-python-hunyuan==3.0.1163 # for tencent hunyuan \ No newline at end of file From a67f27f0a73d7e3c55adff48af3302ed0c1225a6 Mon Sep 17 00:00:00 2001 From: zhulj <1643600218@qq.com> Date: Thu, 25 Jul 2024 08:22:49 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=88=A0=E9=99=A4=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E8=A1=8C=EF=BC=9B=E4=BF=AE=E6=AD=A3=E4=BB=B7=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- metagpt/configs/llm_config.py | 2 -- metagpt/utils/token_counter.py | 7 +++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/metagpt/configs/llm_config.py b/metagpt/configs/llm_config.py index c42f30bff..455743872 100644 --- a/metagpt/configs/llm_config.py +++ b/metagpt/configs/llm_config.py @@ -59,10 +59,8 @@ class LLMConfig(YamlModel): access_key: Optional[str] = None secret_key: Optional[str] = None endpoint: Optional[str] = None # for self-deployed model on the cloud - # For Tencent Hunyuan secret_id: Optional[str] = None - secret_key: Optional[str] = None # For Spark(Xunfei), maybe remove later app_id: Optional[str] = None diff --git a/metagpt/utils/token_counter.py b/metagpt/utils/token_counter.py index 481c1f599..a23dc2945 100644 --- a/metagpt/utils/token_counter.py +++ b/metagpt/utils/token_counter.py @@ -83,11 +83,10 @@ 腾讯混元大模型价格说明:https://cloud.tencent.com/document/product/1729/97731 """ HUNYUAN_MODEL_TOKEN_COSTS = { - "hunyuan-pro": {"prompt": 0.03, "completion": 0.1}, - "hunyuan-standard": {"prompt": 0.0045, "completion": 0.005}, - "hunyuan-standard-256k": {"prompt": 0.015, "completion": 0.06}, + "hunyuan-pro": {"prompt": 0.0042, "completion": 0.014}, + "hunyuan-standard": {"prompt": 0.00063, "completion": 0.0007}, + "hunyuan-standard-256k": {"prompt": 0.0021, "completion": 0.0084}, "hunyuan-lite": {"prompt": 0.0, "completion": 0.0}, - "hunyuan-embedding": {"prompt": 0.0007, "completion": 0.0007}, } """ From 4a35e8a9144eb09804f5c1f6bb5f385a1153b388 Mon Sep 17 00:00:00 2001 From: zhulj <1643600218@qq.com> Date: Mon, 21 Oct 2024 15:28:03 +0800 Subject: [PATCH 3/3] feat(hunyuan): add hunyuan-turbo, hunyuan-code models and remove unused timeout in hunyuan_api.py; fix price in token_counter.py --- config/examples/tencent-hunyuan.yaml | 2 +- metagpt/provider/hunyuan_api.py | 1 - metagpt/utils/token_counter.py | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config/examples/tencent-hunyuan.yaml b/config/examples/tencent-hunyuan.yaml index fbf5f1ee1..86473411f 100644 --- a/config/examples/tencent-hunyuan.yaml +++ b/config/examples/tencent-hunyuan.yaml @@ -1,6 +1,6 @@ llm: api_type: "hunyuan" # 腾讯混元大模型 - model: "hunyuan-standard" # 可选 hunyuan-lite、hunyuan-standard 、hunyuan-standard-256K、hunyuan-pro + model: "hunyuan-standard" # 可选 hunyuan-lite、hunyuan-standard 、hunyuan-standard-256K、hunyuan-pro、hunyuan-turbo、hunyuan-code endpoint: "hunyuan.tencentcloudapi.com" #默认 hunyuan.tencentcloudapi.com secret_id: "" #腾讯云账户 SecretId 和 SecretKey,请注意保密。申请链接:https://console.cloud.tencent.com/cam/capi secret_key: "" diff --git a/metagpt/provider/hunyuan_api.py b/metagpt/provider/hunyuan_api.py index ed73640f3..61868d675 100644 --- a/metagpt/provider/hunyuan_api.py +++ b/metagpt/provider/hunyuan_api.py @@ -58,7 +58,6 @@ def _format_messages(self, messages: list[dict]) -> list[dict]: def _make_request( self, messages: list[dict], - timeout=USE_CONFIG_TIMEOUT, stream=True, ): """构造请求参数对象""" diff --git a/metagpt/utils/token_counter.py b/metagpt/utils/token_counter.py index 2fcab0505..912402d13 100644 --- a/metagpt/utils/token_counter.py +++ b/metagpt/utils/token_counter.py @@ -85,10 +85,12 @@ 腾讯混元大模型价格说明:https://cloud.tencent.com/document/product/1729/97731 """ HUNYUAN_MODEL_TOKEN_COSTS = { + "hunyuan-turbo": {"prompt": 0.00211, "completion": 0.00703}, "hunyuan-pro": {"prompt": 0.0042, "completion": 0.014}, "hunyuan-standard": {"prompt": 0.00063, "completion": 0.0007}, "hunyuan-standard-256k": {"prompt": 0.0021, "completion": 0.0084}, "hunyuan-lite": {"prompt": 0.0, "completion": 0.0}, + "hunyuan-code": {"prompt": 0.00056, "completion": 0.00113}, } """