DeepSeekAPI.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from __future__ import annotations
  2. import os
  3. import json
  4. import time
  5. from typing import AsyncIterator
  6. import asyncio
  7. from ..base_provider import AsyncAuthedProvider
  8. from ...providers.helper import get_last_user_message
  9. from ... import requests
  10. from ...errors import MissingAuthError
  11. from ...requests import get_args_from_nodriver, get_nodriver
  12. from ...providers.response import AuthResult, RequestLogin, Reasoning, JsonConversation, FinishReason
  13. from ...typing import AsyncResult, Messages
  14. from ... import debug
  15. try:
  16. from curl_cffi import requests
  17. from dsk.api import DeepSeekAPI, AuthenticationError, DeepSeekPOW
  18. class DeepSeekAPIArgs(DeepSeekAPI):
  19. def __init__(self, args: dict):
  20. self.auth_token = args.pop("api_key")
  21. if not self.auth_token or not isinstance(self.auth_token, str):
  22. raise AuthenticationError("Invalid auth token provided")
  23. self.args = args
  24. self.pow_solver = DeepSeekPOW()
  25. def _make_request(self, method: str, endpoint: str, json_data: dict, pow_required: bool = False, **kwargs):
  26. url = f"{self.BASE_URL}{endpoint}"
  27. headers = self._get_headers()
  28. if pow_required:
  29. challenge = self._get_pow_challenge()
  30. pow_response = self.pow_solver.solve_challenge(challenge)
  31. headers = self._get_headers(pow_response)
  32. response = requests.request(
  33. method=method,
  34. url=url,
  35. json=json_data, **{
  36. **self.args,
  37. "headers": {**headers, **self.args["headers"]},
  38. "timeout":None,
  39. },
  40. **kwargs
  41. )
  42. if response.status_code == 403:
  43. raise MissingAuthError()
  44. response.raise_for_status()
  45. return response.json()
  46. has_dsk = True
  47. except ImportError:
  48. has_dsk = False
  49. class DeepSeekAPI(AsyncAuthedProvider):
  50. url = "https://chat.deepseek.com"
  51. working = has_dsk
  52. needs_auth = True
  53. use_nodriver = True
  54. _access_token = None
  55. @classmethod
  56. async def on_auth_async(cls, proxy: str = None, **kwargs) -> AsyncIterator:
  57. if not hasattr(cls, "browser"):
  58. cls.browser, cls.stop_browser = await get_nodriver()
  59. yield RequestLogin(cls.__name__, os.environ.get("G4F_LOGIN_URL") or "")
  60. async def callback(page):
  61. while True:
  62. await asyncio.sleep(1)
  63. cls._access_token = json.loads(await page.evaluate("localStorage.getItem('userToken')") or "{}").get("value")
  64. if cls._access_token:
  65. break
  66. args = await get_args_from_nodriver(cls.url, proxy, callback=callback, browser=cls.browser)
  67. yield AuthResult(
  68. api_key=cls._access_token,
  69. **args
  70. )
  71. @classmethod
  72. async def create_authed(
  73. cls,
  74. model: str,
  75. messages: Messages,
  76. auth_result: AuthResult,
  77. conversation: JsonConversation = None,
  78. **kwargs
  79. ) -> AsyncResult:
  80. # Initialize with your auth token
  81. api = DeepSeekAPIArgs(auth_result.get_dict())
  82. # Create a new chat session
  83. if conversation is None:
  84. chat_id = api.create_chat_session()
  85. conversation = JsonConversation(chat_id=chat_id)
  86. yield conversation
  87. is_thinking = 0
  88. for chunk in api.chat_completion(
  89. conversation.chat_id,
  90. get_last_user_message(messages),
  91. thinking_enabled=True
  92. ):
  93. if chunk['type'] == 'thinking':
  94. if not is_thinking:
  95. yield Reasoning(None, "Is thinking...")
  96. is_thinking = time.time()
  97. yield Reasoning(chunk['content'])
  98. elif chunk['type'] == 'text':
  99. if is_thinking:
  100. yield Reasoning(None, f"Thought for {time.time() - is_thinking:.2f}s")
  101. is_thinking = 0
  102. if chunk['content']:
  103. yield chunk['content']
  104. if chunk['finish_reason']:
  105. yield FinishReason(chunk['finish_reason'])