From 99bd6f65d75ed3b4322cc7ddbe95d28ce5d03732 Mon Sep 17 00:00:00 2001 From: zhaoxi Date: Tue, 28 Apr 2026 05:35:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0deepseek?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model_adapter/deepseek_reasoner.py | 59 +++++++++++++++++++ .../model_adapter/model_protocol/__init__.py | 14 ----- 2 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 pretor/adapter/model_adapter/deepseek_reasoner.py delete mode 100644 pretor/adapter/model_adapter/model_protocol/__init__.py diff --git a/pretor/adapter/model_adapter/deepseek_reasoner.py b/pretor/adapter/model_adapter/deepseek_reasoner.py new file mode 100644 index 0000000..e25a320 --- /dev/null +++ b/pretor/adapter/model_adapter/deepseek_reasoner.py @@ -0,0 +1,59 @@ +import re +import os +from typing import Type, TypeVar, Any, Generic +from pydantic import BaseModel, ValidationError +from pydantic_ai import Agent, RunContext +from pydantic_ai.models.openai import OpenAIChatModel + +T = TypeVar('T', bound=BaseModel) + + +class DeepSeekReasonerAgent(Generic[T]): + """ + 专为 DeepSeek-V4/R1 设计的适配器。 + 将结构化输出降级为文本解析模式,以规避工具调用(Tool Calling)的兼容性问题。 + """ + + def __init__( + self, + model_id: str = "deepseek-v4-pro", + output_type: Type[T] = str, + system_prompt: str = "", + deps_type: Type[Any] = None + ): + # 1. 强制声明输出为 str,确保底层不发送 tools 字段 + self.output_schema = output_type + + # 2. 注入强制格式指令到 System Prompt + format_instruction = ( + f"\n\nCRITICAL: 你必须输出且只能输出一段纯 JSON 格式的数据," + f"并包裹在 ```json 和 ``` 之间。格式必须符合以下 Pydantic 模型结构:\n" + f"{self.output_schema.model_json_schema()}" + ) + + self.agent = Agent( + model=OpenAIChatModel(model_id), + output_type=str, # 内部通信用字符串 + system_prompt=system_prompt + format_instruction, + deps_type=deps_type, + retries=0 + ) + + async def run(self, user_prompt: str, deps: Any = None) -> T: + # 调用 PydanticAI 原生 run + result = await self.agent.run(user_prompt, deps=deps) + return self._parse_json(result.output) + + def _parse_json(self, text: str) -> T: + # 使用正则提取 JSON 块 + match = re.search(r'```json\s*(.*?)\s*```', text, re.DOTALL) + json_str = match.group(1).strip() if match else text + + # 如果正则没抓到,尝试寻找首尾大括号 + if not json_str.startswith('{'): + json_str = text[text.find('{'):text.rfind('}') + 1] + + try: + return self.output_schema.model_validate_json(json_str) + except ValidationError as e: + raise ValueError(f"DeepSeek 返回格式非法: {e}\n原文: {text}") \ No newline at end of file diff --git a/pretor/adapter/model_adapter/model_protocol/__init__.py b/pretor/adapter/model_adapter/model_protocol/__init__.py deleted file mode 100644 index 5fa7362..0000000 --- a/pretor/adapter/model_adapter/model_protocol/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright 2026 zhaoxi826 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -