akhaliq HF Staff commited on
Commit
80eb86a
·
1 Parent(s): e2ce9d8

add gpt-5 with poe

Browse files
Files changed (1) hide show
  1. app.py +68 -8
app.py CHANGED
@@ -587,9 +587,10 @@ def get_inference_client(model_id, provider="auto"):
587
  base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
588
  )
589
  elif model_id == "gpt-5":
590
- # Use OpenAI client for GPT-5 model
591
  return OpenAI(
592
- api_key=os.getenv("OPENAI_API_KEY"),
 
593
  )
594
  elif model_id == "step-3":
595
  # Use StepFun API client for Step-3 model
@@ -699,10 +700,24 @@ def remove_code_block(text):
699
  # Remove a leading language marker line (e.g., 'python') if present
700
  if extracted.split('\n', 1)[0].strip().lower() in ['python', 'html', 'css', 'javascript', 'json', 'c', 'cpp', 'markdown', 'latex', 'jinja2', 'typescript', 'yaml', 'dockerfile', 'shell', 'r', 'sql', 'sql-mssql', 'sql-mysql', 'sql-mariadb', 'sql-sqlite', 'sql-cassandra', 'sql-plSQL', 'sql-hive', 'sql-pgsql', 'sql-gql', 'sql-gpsql', 'sql-sparksql', 'sql-esper']:
701
  return extracted.split('\n', 1)[1] if '\n' in extracted else ''
 
 
 
 
 
 
 
 
702
  return extracted
703
  # If no code block is found, check if the entire text is HTML
704
- if text.strip().startswith('<!DOCTYPE html>') or text.strip().startswith('<html') or text.strip().startswith('<'):
705
- return text.strip()
 
 
 
 
 
 
706
  # Special handling for python: remove python marker
707
  if text.strip().startswith('```python'):
708
  return text.strip()[9:-3].strip()
@@ -712,6 +727,13 @@ def remove_code_block(text):
712
  return lines[1] if len(lines) > 1 else ''
713
  return text.strip()
714
 
 
 
 
 
 
 
 
715
  def parse_transformers_js_output(text):
716
  """Parse transformers.js output and extract the three files (index.html, index.js, style.css)"""
717
  files = {
@@ -2500,13 +2522,13 @@ This will help me create a better design for you."""
2500
  )
2501
 
2502
  else:
2503
- # Use max_completion_tokens for GPT-5, max_tokens for others
2504
  if _current_model["id"] == "gpt-5":
2505
  completion = client.chat.completions.create(
2506
- model=_current_model["id"],
2507
  messages=messages,
2508
  stream=True,
2509
- max_completion_tokens=16384
2510
  )
2511
  else:
2512
  completion = client.chat.completions.create(
@@ -2516,6 +2538,9 @@ This will help me create a better design for you."""
2516
  max_tokens=16384
2517
  )
2518
  content = ""
 
 
 
2519
  for chunk in completion:
2520
  # Handle different response formats for Mistral vs others
2521
  chunk_content = None
@@ -2540,7 +2565,42 @@ This will help me create a better design for you."""
2540
  chunk_content = chunk.choices[0].delta.content
2541
 
2542
  if chunk_content:
2543
- content += chunk_content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2544
  search_status = " (with web search)" if enable_search and tavily_client else ""
2545
 
2546
  # Handle transformers.js output differently
 
587
  base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
588
  )
589
  elif model_id == "gpt-5":
590
+ # Use Poe (OpenAI-compatible) client for GPT-5 model
591
  return OpenAI(
592
+ api_key=os.getenv("POE_API_KEY"),
593
+ base_url="https://api.poe.com/v1"
594
  )
595
  elif model_id == "step-3":
596
  # Use StepFun API client for Step-3 model
 
700
  # Remove a leading language marker line (e.g., 'python') if present
701
  if extracted.split('\n', 1)[0].strip().lower() in ['python', 'html', 'css', 'javascript', 'json', 'c', 'cpp', 'markdown', 'latex', 'jinja2', 'typescript', 'yaml', 'dockerfile', 'shell', 'r', 'sql', 'sql-mssql', 'sql-mysql', 'sql-mariadb', 'sql-sqlite', 'sql-cassandra', 'sql-plSQL', 'sql-hive', 'sql-pgsql', 'sql-gql', 'sql-gpsql', 'sql-sparksql', 'sql-esper']:
702
  return extracted.split('\n', 1)[1] if '\n' in extracted else ''
703
+ # If HTML markup starts later in the block (e.g., Poe injected preface), trim to first HTML root
704
+ html_root_idx = None
705
+ for tag in ['<!DOCTYPE html', '<html']:
706
+ idx = extracted.find(tag)
707
+ if idx != -1:
708
+ html_root_idx = idx if html_root_idx is None else min(html_root_idx, idx)
709
+ if html_root_idx is not None and html_root_idx > 0:
710
+ return extracted[html_root_idx:].strip()
711
  return extracted
712
  # If no code block is found, check if the entire text is HTML
713
+ stripped = text.strip()
714
+ if stripped.startswith('<!DOCTYPE html>') or stripped.startswith('<html') or stripped.startswith('<'):
715
+ # If HTML root appears later (e.g., Poe preface), trim to first HTML root
716
+ for tag in ['<!DOCTYPE html', '<html']:
717
+ idx = stripped.find(tag)
718
+ if idx > 0:
719
+ return stripped[idx:].strip()
720
+ return stripped
721
  # Special handling for python: remove python marker
722
  if text.strip().startswith('```python'):
723
  return text.strip()[9:-3].strip()
 
727
  return lines[1] if len(lines) > 1 else ''
728
  return text.strip()
729
 
730
+ def strip_placeholder_thinking(text: str) -> str:
731
+ """Remove placeholder 'Thinking...' status lines from streamed text."""
732
+ if not text:
733
+ return text
734
+ # Matches lines like: "Thinking..." or "Thinking... (12s elapsed)"
735
+ return re.sub(r"(?mi)^[\t ]*Thinking\.\.\.(?:\s*\(\d+s elapsed\))?[\t ]*$\n?", "", text)
736
+
737
  def parse_transformers_js_output(text):
738
  """Parse transformers.js output and extract the three files (index.html, index.js, style.css)"""
739
  files = {
 
2522
  )
2523
 
2524
  else:
2525
+ # Poe expects model id "GPT-5" and uses max_tokens
2526
  if _current_model["id"] == "gpt-5":
2527
  completion = client.chat.completions.create(
2528
+ model="GPT-5",
2529
  messages=messages,
2530
  stream=True,
2531
+ max_tokens=16384
2532
  )
2533
  else:
2534
  completion = client.chat.completions.create(
 
2538
  max_tokens=16384
2539
  )
2540
  content = ""
2541
+ # For Poe/GPT-5, maintain a simple code-fence state machine to only accumulate code
2542
+ poe_inside_code_block = False
2543
+ poe_partial_buffer = ""
2544
  for chunk in completion:
2545
  # Handle different response formats for Mistral vs others
2546
  chunk_content = None
 
2565
  chunk_content = chunk.choices[0].delta.content
2566
 
2567
  if chunk_content:
2568
+ if _current_model["id"] == "gpt-5":
2569
+ # Filter placeholders
2570
+ incoming = strip_placeholder_thinking(chunk_content)
2571
+ # Process code fences incrementally, only keep content inside fences
2572
+ s = poe_partial_buffer + incoming
2573
+ append_text = ""
2574
+ i = 0
2575
+ # Find all triple backticks positions
2576
+ for m in re.finditer(r"```", s):
2577
+ if not poe_inside_code_block:
2578
+ # Opening fence. Require a newline to confirm full opener so we can skip optional language line
2579
+ nl = s.find("\n", m.end())
2580
+ if nl == -1:
2581
+ # Incomplete opener; buffer from this fence and wait for more
2582
+ poe_partial_buffer = s[m.start():]
2583
+ s = None
2584
+ break
2585
+ # Enter code, skip past newline after optional language token
2586
+ poe_inside_code_block = True
2587
+ i = nl + 1
2588
+ else:
2589
+ # Closing fence, append content inside and exit code
2590
+ append_text += s[i:m.start()]
2591
+ poe_inside_code_block = False
2592
+ i = m.end()
2593
+ if s is not None:
2594
+ if poe_inside_code_block:
2595
+ append_text += s[i:]
2596
+ poe_partial_buffer = ""
2597
+ else:
2598
+ poe_partial_buffer = s[i:]
2599
+ if append_text:
2600
+ content += append_text
2601
+ else:
2602
+ # Append content, filtering out placeholder thinking lines
2603
+ content += strip_placeholder_thinking(chunk_content)
2604
  search_status = " (with web search)" if enable_search and tavily_client else ""
2605
 
2606
  # Handle transformers.js output differently