81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
"""DeepSeek chat model integration."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from collections.abc import Mapping
|
|
from typing import Any
|
|
|
|
from langchain_core.language_models import LanguageModelInput
|
|
from langchain_core.messages import AIMessage, BaseMessage
|
|
from langchain_deepseek import ChatDeepSeek
|
|
|
|
from .openai_compat import OpenAICompatContentMixin
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
DEEPSEEK_THINKING_DISABLED = {"type": "disabled"}
|
|
|
|
|
|
def is_deepseek_thinking_disabled(
|
|
extra_body: Mapping[str, object] | None,
|
|
) -> bool:
|
|
"""Return whether a request body explicitly disables DeepSeek thinking."""
|
|
if not extra_body:
|
|
return False
|
|
thinking = extra_body.get("thinking")
|
|
return isinstance(thinking, Mapping) and thinking.get("type") == "disabled"
|
|
|
|
|
|
def _inject_reasoning_content(
|
|
messages: list[BaseMessage],
|
|
payload: dict[str, object],
|
|
) -> dict[str, object]:
|
|
"""Copy captured DeepSeek reasoning into serialized assistant messages."""
|
|
reasoning = [
|
|
message.additional_kwargs.get("reasoning_content")
|
|
for message in messages
|
|
if isinstance(message, AIMessage)
|
|
]
|
|
serialized = payload.get("messages")
|
|
if not isinstance(serialized, list):
|
|
return payload
|
|
|
|
ai_index = 0
|
|
for message in serialized:
|
|
if not isinstance(message, dict) or message.get("role") != "assistant":
|
|
continue
|
|
value = reasoning[ai_index] if ai_index < len(reasoning) else None
|
|
if value:
|
|
message["reasoning_content"] = value
|
|
elif "reasoning_content" not in message:
|
|
message["reasoning_content"] = ""
|
|
ai_index += 1
|
|
return payload
|
|
|
|
|
|
class EvoChatDeepSeek(OpenAICompatContentMixin, ChatDeepSeek):
|
|
"""ChatDeepSeek with EvoScientist's media and history compatibility."""
|
|
|
|
def _get_request_payload(
|
|
self,
|
|
input_: LanguageModelInput,
|
|
*,
|
|
stop: list[str] | None = None,
|
|
**kwargs: Any,
|
|
) -> dict[str, Any]:
|
|
payload = super()._get_request_payload(input_, stop=stop, **kwargs)
|
|
if is_deepseek_thinking_disabled(self.extra_body):
|
|
return payload
|
|
|
|
try:
|
|
messages = self._convert_input(input_).to_messages()
|
|
except Exception:
|
|
logger.warning(
|
|
"DeepSeek reasoning passback: input conversion failed",
|
|
exc_info=True,
|
|
)
|
|
return payload
|
|
|
|
return _inject_reasoning_content(messages, payload)
|