KiWA001 commited on
Commit
27f1381
Β·
1 Parent(s): 54cc194

Update HuggingChat with login and prefixed model names

Browse files

- Add automatic login with provided credentials
- Prefix all HuggingChat models with 'huggingface-'
- Add new models:
* huggingface-omni
* huggingface-llama-3.3-70b
* huggingface-qwen-72b
* huggingface-deepseek-r1
* huggingface-kimi-k2
- Remove old Copilot files

config.py CHANGED
@@ -25,9 +25,11 @@ MODEL_RANKING = [
25
  ("gpt-4o-mini", "g4f", "gpt-4o-mini"),
26
  ("glm-5", "zai", "glm-5"),
27
  ("gemini-3-flash", "gemini", "gemini-3-flash"),
28
- ("huggingchat-omni", "huggingchat", "omni"),
29
- ("llama-3.3-70b", "huggingchat", "meta-llama/Llama-3.3-70B-Instruct"),
30
- ("qwen2.5-72b", "huggingchat", "Qwen/Qwen2.5-72B-Instruct"),
 
 
31
  ("gpt-oss-20b", "pollinations", "openai"),
32
  ("mistral-small-3.2", "pollinations", "mistral"),
33
 
@@ -85,12 +87,11 @@ PROVIDER_MODELS = {
85
  "gemini-3-flash",
86
  ],
87
  "huggingchat": [
88
- "omni",
89
- "meta-llama/Llama-3.3-70B-Instruct",
90
- "Qwen/Qwen2.5-72B-Instruct",
91
- "deepseek-ai/DeepSeek-R1",
92
- "meta-llama/Llama-3.1-8B-Instruct",
93
- "mistralai/Mistral-7B-Instruct-v0.3",
94
  ],
95
  "pollinations": [
96
  "gpt-oss-20b",
 
25
  ("gpt-4o-mini", "g4f", "gpt-4o-mini"),
26
  ("glm-5", "zai", "glm-5"),
27
  ("gemini-3-flash", "gemini", "gemini-3-flash"),
28
+ ("huggingface-omni", "huggingchat", "omni"),
29
+ ("huggingface-llama-3.3-70b", "huggingchat", "meta-llama/Llama-3.3-70B-Instruct"),
30
+ ("huggingface-qwen-72b", "huggingchat", "Qwen/Qwen2.5-72B-Instruct"),
31
+ ("huggingface-deepseek-r1", "huggingchat", "deepseek-ai/DeepSeek-R1"),
32
+ ("huggingface-kimi-k2", "huggingchat", "moonshotai/Kimi-K2-Instruct"),
33
  ("gpt-oss-20b", "pollinations", "openai"),
34
  ("mistral-small-3.2", "pollinations", "mistral"),
35
 
 
87
  "gemini-3-flash",
88
  ],
89
  "huggingchat": [
90
+ "huggingface-omni",
91
+ "huggingface-llama-3.3-70b",
92
+ "huggingface-qwen-72b",
93
+ "huggingface-deepseek-r1",
94
+ "huggingface-kimi-k2",
 
95
  ],
96
  "pollinations": [
97
  "gpt-oss-20b",
providers/huggingchat_provider.py CHANGED
@@ -4,8 +4,8 @@ HuggingChat Provider (Browser-Based)
4
  Uses Playwright Chromium to interact with https://huggingface.co/chat as a real browser.
5
 
6
  Strategy:
7
- - Handles the welcome modal by clicking "Start chatting"
8
- - Uses EPHEMERAL contexts per request
9
  - Supports model selection via the model dropdown
10
  - Scrapes AI response from the DOM
11
  """
@@ -22,6 +22,10 @@ _playwright = None
22
  _browser = None
23
  _lock = asyncio.Lock()
24
 
 
 
 
 
25
 
26
  class HuggingChatProvider(BaseProvider):
27
  """AI provider using HuggingChat via Persistent Playwright Browser."""
@@ -34,7 +38,7 @@ class HuggingChatProvider(BaseProvider):
34
  return "huggingchat"
35
 
36
  def get_available_models(self) -> list[str]:
37
- return PROVIDER_MODELS.get("huggingchat", ["omni", "meta-llama/Llama-3.3-70B-Instruct"])
38
 
39
  @staticmethod
40
  def is_available() -> bool:
@@ -68,6 +72,56 @@ class HuggingChatProvider(BaseProvider):
68
  )
69
  logger.info("βœ… HuggingChat: Browser is Ready.")
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  async def send_message(
72
  self,
73
  prompt: str,
@@ -80,9 +134,9 @@ class HuggingChatProvider(BaseProvider):
80
  raise RuntimeError("Playwright not installed.")
81
 
82
  await self._ensure_browser()
83
- selected_model = model or "omni"
84
 
85
- # Create Ephemeral Context
86
  context = await _browser.new_context(
87
  viewport={"width": 1920, "height": 1080},
88
  user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
@@ -96,6 +150,12 @@ class HuggingChatProvider(BaseProvider):
96
  Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
97
  """)
98
 
 
 
 
 
 
 
99
  page = await context.new_page()
100
 
101
  try:
@@ -104,22 +164,14 @@ class HuggingChatProvider(BaseProvider):
104
  # Navigate to HuggingChat
105
  await page.goto("https://huggingface.co/chat", timeout=60000)
106
 
107
- # Handle welcome modal if present
108
- try:
109
- start_btn = await page.wait_for_selector(
110
- 'button:has-text("Start chatting")',
111
- timeout=5000
112
- )
113
- if start_btn:
114
- logger.info("HuggingChat: Clicking 'Start chatting' button...")
115
- await start_btn.click()
116
- await asyncio.sleep(1)
117
- except:
118
- logger.info("HuggingChat: No welcome modal found, continuing...")
119
 
120
  # If specific model requested (not omni), try to select it
121
- if selected_model and selected_model != "omni":
122
- await self._select_model(page, selected_model)
 
 
123
 
124
  await asyncio.sleep(self.HYDRATION_DELAY)
125
 
@@ -175,6 +227,7 @@ class HuggingChatProvider(BaseProvider):
175
  await asyncio.sleep(1)
176
 
177
  # Try to find and click the specific model
 
178
  model_option = await page.query_selector(
179
  f'text={model}'
180
  )
 
4
  Uses Playwright Chromium to interact with https://huggingface.co/chat as a real browser.
5
 
6
  Strategy:
7
+ - Handles login with provided credentials
8
+ - Saves session cookies for reuse
9
  - Supports model selection via the model dropdown
10
  - Scrapes AI response from the DOM
11
  """
 
22
  _browser = None
23
  _lock = asyncio.Lock()
24
 
25
+ # Hugging Face credentials
26
+ HF_USERNAME = "one@bo5.store"
27
+ HF_PASSWORD = "Zzzzz1$."
28
+
29
 
30
  class HuggingChatProvider(BaseProvider):
31
  """AI provider using HuggingChat via Persistent Playwright Browser."""
 
38
  return "huggingchat"
39
 
40
  def get_available_models(self) -> list[str]:
41
+ return PROVIDER_MODELS.get("huggingchat", ["huggingface-omni"])
42
 
43
  @staticmethod
44
  def is_available() -> bool:
 
72
  )
73
  logger.info("βœ… HuggingChat: Browser is Ready.")
74
 
75
+ async def _login(self, context) -> bool:
76
+ """
77
+ Perform login to Hugging Face.
78
+ Returns True if login successful.
79
+ """
80
+ page = await context.new_page()
81
+
82
+ try:
83
+ logger.info("HuggingChat: Navigating to login page...")
84
+ await page.goto("https://huggingface.co/login", timeout=60000)
85
+
86
+ # Wait for login form
87
+ await page.wait_for_selector('input[name="username"]', timeout=10000)
88
+
89
+ logger.info("HuggingChat: Filling login credentials...")
90
+
91
+ # Fill username/email
92
+ await page.fill('input[name="username"]', HF_USERNAME)
93
+ await asyncio.sleep(0.5)
94
+
95
+ # Fill password
96
+ await page.fill('input[name="password"]', HF_PASSWORD)
97
+ await asyncio.sleep(0.5)
98
+
99
+ # Click login button
100
+ await page.click('button[type="submit"]')
101
+
102
+ # Wait for navigation after login
103
+ try:
104
+ await page.wait_for_url("https://huggingface.co/", timeout=10000)
105
+ logger.info("βœ… HuggingChat: Login successful!")
106
+ await page.close()
107
+ return True
108
+ except:
109
+ # Check if we're still on login page (login failed)
110
+ current_url = page.url
111
+ if "login" in current_url:
112
+ logger.error("❌ HuggingChat: Login failed - still on login page")
113
+ await page.close()
114
+ return False
115
+ else:
116
+ logger.info("βœ… HuggingChat: Login successful (redirected)")
117
+ await page.close()
118
+ return True
119
+
120
+ except Exception as e:
121
+ logger.error(f"❌ HuggingChat: Login error: {e}")
122
+ await page.close()
123
+ return False
124
+
125
  async def send_message(
126
  self,
127
  prompt: str,
 
134
  raise RuntimeError("Playwright not installed.")
135
 
136
  await self._ensure_browser()
137
+ selected_model = model or "huggingface-omni"
138
 
139
+ # Create persistent context (for session/cookies)
140
  context = await _browser.new_context(
141
  viewport={"width": 1920, "height": 1080},
142
  user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
 
150
  Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
151
  """)
152
 
153
+ # Try to login first
154
+ login_success = await self._login(context)
155
+ if not login_success:
156
+ await context.close()
157
+ raise RuntimeError("Failed to login to Hugging Face. Check credentials.")
158
+
159
  page = await context.new_page()
160
 
161
  try:
 
164
  # Navigate to HuggingChat
165
  await page.goto("https://huggingface.co/chat", timeout=60000)
166
 
167
+ # Wait for chat interface to load
168
+ await asyncio.sleep(2)
 
 
 
 
 
 
 
 
 
 
169
 
170
  # If specific model requested (not omni), try to select it
171
+ if selected_model and selected_model != "huggingface-omni":
172
+ # Extract actual model name from prefixed name
173
+ actual_model = selected_model.replace("huggingface-", "")
174
+ await self._select_model(page, actual_model)
175
 
176
  await asyncio.sleep(self.HYDRATION_DELAY)
177
 
 
227
  await asyncio.sleep(1)
228
 
229
  # Try to find and click the specific model
230
+ # Model names in HuggingChat are full paths like "meta-llama/Llama-3.3-70B-Instruct"
231
  model_option = await page.query_selector(
232
  f'text={model}'
233
  )
test_huggingchat_browser.py CHANGED
@@ -45,13 +45,13 @@ async def test_huggingchat():
45
  return False
46
 
47
  # Test with specific model
48
- print("\nπŸ“ Test 2: Using Llama 3.3 70B")
49
  print("-" * 50)
50
 
51
  try:
52
  result = await provider.send_message(
53
  "What is 2+2? Answer with just the number.",
54
- model="meta-llama/Llama-3.3-70B-Instruct"
55
  )
56
  print(f"βœ… SUCCESS!")
57
  print(f"πŸ€– Model: {result['model']}")
 
45
  return False
46
 
47
  # Test with specific model
48
+ print("\nπŸ“ Test 2: Using DeepSeek R1")
49
  print("-" * 50)
50
 
51
  try:
52
  result = await provider.send_message(
53
  "What is 2+2? Answer with just the number.",
54
+ model="huggingface-deepseek-r1"
55
  )
56
  print(f"βœ… SUCCESS!")
57
  print(f"πŸ€– Model: {result['model']}")