| |
|
|
| from typing import List, Tuple, Dict |
| import re |
| import gradio as gr |
| import io, base64 |
| import numpy as np |
| from PIL import Image |
|
|
| |
| History = List[Tuple[str, str]] |
| Messages = List[Dict[str, str]] |
|
|
| def history_to_messages(history: History, system: str) -> Messages: |
| messages = [{'role': 'system', 'content': system}] |
| for h in history: |
| user_content = h[0] |
| if isinstance(user_content, list): |
| text_content = "" |
| for item in user_content: |
| if isinstance(item, dict) and item.get("type") == "text": |
| text_content += item.get("text", "") |
| user_content = text_content if text_content else str(user_content) |
| messages.append({'role': 'user', 'content': user_content}) |
| messages.append({'role': 'assistant', 'content': h[1]}) |
| return messages |
|
|
| def messages_to_history(messages: Messages) -> Tuple[str, History]: |
| assert messages[0]['role'] == 'system' |
| history = [] |
| for q, r in zip(messages[1::2], messages[2::2]): |
| user_content = q['content'] |
| if isinstance(user_content, list): |
| text_content = "" |
| for item in user_content: |
| if isinstance(item, dict) and item.get("type") == "text": |
| text_content += item.get("text", "") |
| user_content = text_content if text_content else str(user_content) |
| history.append([user_content, r['content']]) |
| return history |
|
|
| def history_render(history: History): |
| return gr.update(visible=True), history |
|
|
| def clear_history(): |
| return [], [], None, "" |
|
|
| def update_image_input_visibility(model): |
| is_ernie_vl = model.get("id") == "baidu/ERNIE-4.5-VL-424B-A47B-Base-PT" |
| is_glm_vl = model.get("id") == "THUDM/GLM-4.1V-9B-Thinking" |
| return gr.update(visible=is_ernie_vl or is_glm_vl) |
|
|
| def process_image_for_model(image): |
| if image is None: |
| return None |
| if isinstance(image, np.ndarray): |
| image = Image.fromarray(image) |
| buffer = io.BytesIO() |
| image.save(buffer, format='PNG') |
| img_str = base64.b64encode(buffer.getvalue()).decode() |
| return f"data:image/png;base64,{img_str}" |
|
|
| def create_multimodal_message(text, image=None): |
| if image is None: |
| return {"role": "user", "content": text} |
| content = [ |
| {"type": "text", "text": text}, |
| {"type": "image_url", "image_url": {"url": process_image_for_model(image)}} |
| ] |
| return {"role": "user", "content": content} |
|
|
| |
| def remove_code_block(text): |
| patterns = [ |
| r'```(?:html|HTML)\n([\s\S]+?)\n```', |
| r'```\n([\s\S]+?)\n```', |
| r'```([\s\S]+?)```' |
| ] |
| for pattern in patterns: |
| match = re.search(pattern, text, re.DOTALL) |
| if match: |
| extracted = match.group(1).strip() |
| lines = extracted.split('\n', 1) |
| if lines[0].strip().lower() in ['python', 'html', 'css', 'javascript']: |
| return lines[1] if len(lines) > 1 else '' |
| return extracted |
| return text.strip() |
|
|
| def parse_transformers_js_output(text): |
| files = {'index.html': '', 'index.js': '', 'style.css': ''} |
| files['index.html'] = re.search(r'```html\s*\n([\s\S]+?)\n```', text, re.IGNORECASE).group(1).strip() if re.search(r'```html\s*\n([\s\S]+?)\n```', text, re.IGNORECASE) else '' |
| files['index.js'] = re.search(r'```javascript\s*\n([\s\S]+?)\n```', text, re.IGNORECASE).group(1).strip() if re.search(r'```javascript\s*\n([\s\S]+?)\n```', text, re.IGNORECASE) else '' |
| files['style.css'] = re.search(r'```css\s*\n([\s\S]+?)\n```', text, re.IGNORECASE).group(1).strip() if re.search(r'```css\s*\n([\s\S]+?)\n```', text, re.IGNORECASE) else '' |
| return files |
|
|
| def format_transformers_js_output(files): |
| return f"=== index.html ===\n{files['index.html']}\n=== index.js ===\n{files['index.js']}\n=== style.css ===\n{files['style.css']}" |
|
|