Files
EvoScientist-Multi/EvoScientist/llm/deepseek.py
T

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)