HuggingChat.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. from __future__ import annotations
  2. import json, requests, re
  3. from curl_cffi import requests as cf_reqs
  4. from ..typing import CreateResult, Messages
  5. from .base_provider import ProviderModelMixin, AbstractProvider
  6. from .helper import format_prompt
  7. class HuggingChat(AbstractProvider, ProviderModelMixin):
  8. url = "https://huggingface.co/chat"
  9. working = True
  10. supports_stream = True
  11. default_model = "meta-llama/Meta-Llama-3.1-70B-Instruct"
  12. models = [
  13. 'meta-llama/Meta-Llama-3.1-70B-Instruct',
  14. 'CohereForAI/c4ai-command-r-plus-08-2024',
  15. 'Qwen/Qwen2.5-72B-Instruct',
  16. 'nvidia/Llama-3.1-Nemotron-70B-Instruct-HF',
  17. 'meta-llama/Llama-3.2-11B-Vision-Instruct',
  18. 'NousResearch/Hermes-3-Llama-3.1-8B',
  19. 'mistralai/Mistral-Nemo-Instruct-2407',
  20. 'microsoft/Phi-3.5-mini-instruct',
  21. ]
  22. model_aliases = {
  23. "llama-3.1-70b": "meta-llama/Meta-Llama-3.1-70B-Instruct",
  24. "command-r-plus": "CohereForAI/c4ai-command-r-plus-08-2024",
  25. "qwen-2-72b": "Qwen/Qwen2.5-72B-Instruct",
  26. "nemotron-70b": "nvidia/Llama-3.1-Nemotron-70B-Instruct-HF",
  27. "llama-3.2-11b": "meta-llama/Llama-3.2-11B-Vision-Instruct",
  28. "hermes-3": "NousResearch/Hermes-3-Llama-3.1-8B",
  29. "mistral-nemo": "mistralai/Mistral-Nemo-Instruct-2407",
  30. "phi-3.5-mini": "microsoft/Phi-3.5-mini-instruct",
  31. }
  32. @classmethod
  33. def get_model(cls, model: str) -> str:
  34. if model in cls.models:
  35. return model
  36. elif model in cls.model_aliases:
  37. return cls.model_aliases[model]
  38. else:
  39. return cls.default_model
  40. @classmethod
  41. def create_completion(
  42. cls,
  43. model: str,
  44. messages: Messages,
  45. stream: bool,
  46. **kwargs
  47. ) -> CreateResult:
  48. model = cls.get_model(model)
  49. if model in cls.models:
  50. session = cf_reqs.Session()
  51. session.headers = {
  52. 'accept': '*/*',
  53. 'accept-language': 'en',
  54. 'cache-control': 'no-cache',
  55. 'origin': 'https://huggingface.co',
  56. 'pragma': 'no-cache',
  57. 'priority': 'u=1, i',
  58. 'referer': 'https://huggingface.co/chat/',
  59. 'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
  60. 'sec-ch-ua-mobile': '?0',
  61. 'sec-ch-ua-platform': '"macOS"',
  62. 'sec-fetch-dest': 'empty',
  63. 'sec-fetch-mode': 'cors',
  64. 'sec-fetch-site': 'same-origin',
  65. 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
  66. }
  67. print(model)
  68. json_data = {
  69. 'model': model,
  70. }
  71. response = session.post('https://huggingface.co/chat/conversation', json=json_data)
  72. conversationId = response.json()['conversationId']
  73. response = session.get(f'https://huggingface.co/chat/conversation/{conversationId}/__data.json?x-sveltekit-invalidated=11',)
  74. data: list = (response.json())["nodes"][1]["data"]
  75. keys: list[int] = data[data[0]["messages"]]
  76. message_keys: dict = data[keys[0]]
  77. messageId: str = data[message_keys["id"]]
  78. settings = {
  79. "inputs": format_prompt(messages),
  80. "id": messageId,
  81. "is_retry": False,
  82. "is_continue": False,
  83. "web_search": False,
  84. "tools": []
  85. }
  86. headers = {
  87. 'accept': '*/*',
  88. 'accept-language': 'en',
  89. 'cache-control': 'no-cache',
  90. 'origin': 'https://huggingface.co',
  91. 'pragma': 'no-cache',
  92. 'priority': 'u=1, i',
  93. 'referer': f'https://huggingface.co/chat/conversation/{conversationId}',
  94. 'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
  95. 'sec-ch-ua-mobile': '?0',
  96. 'sec-ch-ua-platform': '"macOS"',
  97. 'sec-fetch-dest': 'empty',
  98. 'sec-fetch-mode': 'cors',
  99. 'sec-fetch-site': 'same-origin',
  100. 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
  101. }
  102. files = {
  103. 'data': (None, json.dumps(settings, separators=(',', ':'))),
  104. }
  105. response = requests.post(f'https://huggingface.co/chat/conversation/{conversationId}',
  106. cookies=session.cookies,
  107. headers=headers,
  108. files=files,
  109. )
  110. first_token = True
  111. for line in response.iter_lines():
  112. line = json.loads(line)
  113. if "type" not in line:
  114. raise RuntimeError(f"Response: {line}")
  115. elif line["type"] == "stream":
  116. token = line["token"]
  117. if first_token:
  118. token = token.lstrip().replace('\u0000', '')
  119. first_token = False
  120. else:
  121. token = token.replace('\u0000', '')
  122. yield token
  123. elif line["type"] == "finalAnswer":
  124. break