Spaces:
Running
Running
add gpt-5 with poe
Browse files
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("
|
|
|
|
| 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 |
-
|
| 705 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
#
|
| 2504 |
if _current_model["id"] == "gpt-5":
|
| 2505 |
completion = client.chat.completions.create(
|
| 2506 |
-
model=
|
| 2507 |
messages=messages,
|
| 2508 |
stream=True,
|
| 2509 |
-
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|