mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-12 20:29:02 +08:00
Fix Deepseek Function/Tool Calling (#11023)
This commit is contained in:
parent
87c831e5dd
commit
aae29e72ae
@ -5,6 +5,7 @@ label:
|
|||||||
model_type: llm
|
model_type: llm
|
||||||
features:
|
features:
|
||||||
- agent-thought
|
- agent-thought
|
||||||
|
- tool-call
|
||||||
- multi-tool-call
|
- multi-tool-call
|
||||||
- stream-tool-call
|
- stream-tool-call
|
||||||
model_properties:
|
model_properties:
|
||||||
@ -72,7 +73,7 @@ parameter_rules:
|
|||||||
- text
|
- text
|
||||||
- json_object
|
- json_object
|
||||||
pricing:
|
pricing:
|
||||||
input: '1'
|
input: "1"
|
||||||
output: '2'
|
output: "2"
|
||||||
unit: '0.000001'
|
unit: "0.000001"
|
||||||
currency: RMB
|
currency: RMB
|
||||||
|
@ -5,6 +5,7 @@ label:
|
|||||||
model_type: llm
|
model_type: llm
|
||||||
features:
|
features:
|
||||||
- agent-thought
|
- agent-thought
|
||||||
|
- tool-call
|
||||||
- multi-tool-call
|
- multi-tool-call
|
||||||
- stream-tool-call
|
- stream-tool-call
|
||||||
model_properties:
|
model_properties:
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from typing import Optional, Union
|
from typing import Optional, Union
|
||||||
from urllib.parse import urlparse
|
|
||||||
|
|
||||||
import tiktoken
|
from yarl import URL
|
||||||
|
|
||||||
from core.model_runtime.entities.llm_entities import LLMResult
|
from core.model_runtime.entities.llm_entities import LLMMode, LLMResult
|
||||||
from core.model_runtime.entities.message_entities import (
|
from core.model_runtime.entities.message_entities import (
|
||||||
PromptMessage,
|
PromptMessage,
|
||||||
PromptMessageTool,
|
PromptMessageTool,
|
||||||
)
|
)
|
||||||
from core.model_runtime.model_providers.openai.llm.llm import OpenAILargeLanguageModel
|
from core.model_runtime.model_providers.openai_api_compatible.llm.llm import OAIAPICompatLargeLanguageModel
|
||||||
|
|
||||||
|
|
||||||
class DeepSeekLargeLanguageModel(OpenAILargeLanguageModel):
|
class DeepseekLargeLanguageModel(OAIAPICompatLargeLanguageModel):
|
||||||
def _invoke(
|
def _invoke(
|
||||||
self,
|
self,
|
||||||
model: str,
|
model: str,
|
||||||
@ -25,92 +24,15 @@ class DeepSeekLargeLanguageModel(OpenAILargeLanguageModel):
|
|||||||
user: Optional[str] = None,
|
user: Optional[str] = None,
|
||||||
) -> Union[LLMResult, Generator]:
|
) -> Union[LLMResult, Generator]:
|
||||||
self._add_custom_parameters(credentials)
|
self._add_custom_parameters(credentials)
|
||||||
|
return super()._invoke(model, credentials, prompt_messages, model_parameters, tools, stop, stream)
|
||||||
return super()._invoke(model, credentials, prompt_messages, model_parameters, tools, stop, stream, user)
|
|
||||||
|
|
||||||
def validate_credentials(self, model: str, credentials: dict) -> None:
|
def validate_credentials(self, model: str, credentials: dict) -> None:
|
||||||
self._add_custom_parameters(credentials)
|
self._add_custom_parameters(credentials)
|
||||||
super().validate_credentials(model, credentials)
|
super().validate_credentials(model, credentials)
|
||||||
|
|
||||||
# refactored from openai model runtime, use cl100k_base for calculate token number
|
|
||||||
def _num_tokens_from_string(self, model: str, text: str, tools: Optional[list[PromptMessageTool]] = None) -> int:
|
|
||||||
"""
|
|
||||||
Calculate num tokens for text completion model with tiktoken package.
|
|
||||||
|
|
||||||
:param model: model name
|
|
||||||
:param text: prompt text
|
|
||||||
:param tools: tools for tool calling
|
|
||||||
:return: number of tokens
|
|
||||||
"""
|
|
||||||
encoding = tiktoken.get_encoding("cl100k_base")
|
|
||||||
num_tokens = len(encoding.encode(text))
|
|
||||||
|
|
||||||
if tools:
|
|
||||||
num_tokens += self._num_tokens_for_tools(encoding, tools)
|
|
||||||
|
|
||||||
return num_tokens
|
|
||||||
|
|
||||||
# refactored from openai model runtime, use cl100k_base for calculate token number
|
|
||||||
def _num_tokens_from_messages(
|
|
||||||
self, model: str, messages: list[PromptMessage], tools: Optional[list[PromptMessageTool]] = None
|
|
||||||
) -> int:
|
|
||||||
"""Calculate num tokens for gpt-3.5-turbo and gpt-4 with tiktoken package.
|
|
||||||
|
|
||||||
Official documentation: https://github.com/openai/openai-cookbook/blob/
|
|
||||||
main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb"""
|
|
||||||
encoding = tiktoken.get_encoding("cl100k_base")
|
|
||||||
tokens_per_message = 3
|
|
||||||
tokens_per_name = 1
|
|
||||||
|
|
||||||
num_tokens = 0
|
|
||||||
messages_dict = [self._convert_prompt_message_to_dict(m) for m in messages]
|
|
||||||
for message in messages_dict:
|
|
||||||
num_tokens += tokens_per_message
|
|
||||||
for key, value in message.items():
|
|
||||||
# Cast str(value) in case the message value is not a string
|
|
||||||
# This occurs with function messages
|
|
||||||
# TODO: The current token calculation method for the image type is not implemented,
|
|
||||||
# which need to download the image and then get the resolution for calculation,
|
|
||||||
# and will increase the request delay
|
|
||||||
if isinstance(value, list):
|
|
||||||
text = ""
|
|
||||||
for item in value:
|
|
||||||
if isinstance(item, dict) and item["type"] == "text":
|
|
||||||
text += item["text"]
|
|
||||||
|
|
||||||
value = text
|
|
||||||
|
|
||||||
if key == "tool_calls":
|
|
||||||
for tool_call in value:
|
|
||||||
for t_key, t_value in tool_call.items():
|
|
||||||
num_tokens += len(encoding.encode(t_key))
|
|
||||||
if t_key == "function":
|
|
||||||
for f_key, f_value in t_value.items():
|
|
||||||
num_tokens += len(encoding.encode(f_key))
|
|
||||||
num_tokens += len(encoding.encode(f_value))
|
|
||||||
else:
|
|
||||||
num_tokens += len(encoding.encode(t_key))
|
|
||||||
num_tokens += len(encoding.encode(t_value))
|
|
||||||
else:
|
|
||||||
num_tokens += len(encoding.encode(str(value)))
|
|
||||||
|
|
||||||
if key == "name":
|
|
||||||
num_tokens += tokens_per_name
|
|
||||||
|
|
||||||
# every reply is primed with <im_start>assistant
|
|
||||||
num_tokens += 3
|
|
||||||
|
|
||||||
if tools:
|
|
||||||
num_tokens += self._num_tokens_for_tools(encoding, tools)
|
|
||||||
|
|
||||||
return num_tokens
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _add_custom_parameters(credentials: dict) -> None:
|
def _add_custom_parameters(credentials) -> None:
|
||||||
credentials["mode"] = "chat"
|
credentials["endpoint_url"] = str(URL(credentials.get("endpoint_url", "https://api.deepseek.com")))
|
||||||
credentials["openai_api_key"] = credentials["api_key"]
|
credentials["mode"] = LLMMode.CHAT.value
|
||||||
if "endpoint_url" not in credentials or credentials["endpoint_url"] == "":
|
credentials["function_calling_type"] = "tool_call"
|
||||||
credentials["openai_api_base"] = "https://api.deepseek.com"
|
credentials["stream_function_calling"] = "support"
|
||||||
else:
|
|
||||||
parsed_url = urlparse(credentials["endpoint_url"])
|
|
||||||
credentials["openai_api_base"] = f"{parsed_url.scheme}://{parsed_url.netloc}"
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user