{"repo": "autolab-sai-sjtu/autopage", "files": {".env": {"bebd9007ee35871fc7dad316f1bf8efbee6dfe29": {"t": 1785674038.807483, "n": 679, "h": "2d18f3855e4c564c", "c": "\n\n#qwen\n# export QWEN_API_KEY='your_qwen_api_key' # openai\n# export QWEN_API_BASE_URL='https://dashscope.aliyuncs.com/compatible-mode/v1' # openai\n\n# deepseek\n# export OPENAI_API_KEY='your_deepseek_api_key'\n# export OPENAI_API_BASE_URL='https://api.deepseek.com'\n\n# export OPENAI_API_KEY='your_openai_api_key' # openai\n# export OPENAI_API_BASE_URL='https://api.openai.com' # openai\n\n# gemini\n# export GEMINI_API_KEY=\"your_gemini_key\"\n\n# ZhiPu glm\n# export ZHIPUAI_API_KEY='your_glm_api_key'\n# export OPENAI_API_BASE_URL='https://open.bigmodel.cn/api/paas/v4/'\n\n\n# export OPENROUTER_API_KEY=\"your_openrouter_key\"\n# export OPENROUTER_API_BASE_URL=\"https://openrouter.ai/api/v1\"\n\n\n\n"}, "df7f5beaea02d1d7e482b81ad26374c1f709105a": {"t": 1785747552.6111557, "n": 679, "h": "2d18f3855e4c564c", "c": "\n\n#qwen\n# export QWEN_API_KEY='your_qwen_api_key' # openai\n# export QWEN_API_BASE_URL='https://dashscope.aliyuncs.com/compatible-mode/v1' # openai\n\n# deepseek\n# export OPENAI_API_KEY='your_deepseek_api_key'\n# export OPENAI_API_BASE_URL='https://api.deepseek.com'\n\n# export OPENAI_API_KEY='your_openai_api_key' # openai\n# export OPENAI_API_BASE_URL='https://api.openai.com' # openai\n\n# gemini\n# export GEMINI_API_KEY=\"your_gemini_key\"\n\n# ZhiPu glm\n# export ZHIPUAI_API_KEY='your_glm_api_key'\n# export OPENAI_API_BASE_URL='https://open.bigmodel.cn/api/paas/v4/'\n\n\n# export OPENROUTER_API_KEY=\"your_openrouter_key\"\n# export OPENROUTER_API_BASE_URL=\"https://openrouter.ai/api/v1\"\n\n\n\n"}, "ecd0ca309215d137e33bd278abaa8d73d250957b": {"t": 1785846821.0229964, "n": 679, "h": "2d18f3855e4c564c", "c": "\n\n#qwen\n# export QWEN_API_KEY='your_qwen_api_key' # openai\n# export QWEN_API_BASE_URL='https://dashscope.aliyuncs.com/compatible-mode/v1' # openai\n\n# deepseek\n# export OPENAI_API_KEY='your_deepseek_api_key'\n# export OPENAI_API_BASE_URL='https://api.deepseek.com'\n\n# export OPENAI_API_KEY='your_openai_api_key' # openai\n# export OPENAI_API_BASE_URL='https://api.openai.com' # openai\n\n# gemini\n# export GEMINI_API_KEY=\"your_gemini_key\"\n\n# ZhiPu glm\n# export ZHIPUAI_API_KEY='your_glm_api_key'\n# export OPENAI_API_BASE_URL='https://open.bigmodel.cn/api/paas/v4/'\n\n\n# export OPENROUTER_API_KEY=\"your_openrouter_key\"\n# export OPENROUTER_API_BASE_URL=\"https://openrouter.ai/api/v1\"\n\n\n\n"}}, "app.py": {"bebd9007ee35871fc7dad316f1bf8efbee6dfe29": {"t": 1785674160.9252, "n": 63193, "h": "af0414489db141ed", "c": "import gradio as gr\nimport os\nimport json\nfrom pathlib import Path\nimport base64\nimport re\nfrom threading import Thread\nfrom http.server import HTTPServer, SimpleHTTPRequestHandler\nimport socket\nfrom dotenv import load_dotenv\nfrom ProjectPageAgent.parse_paper import parse_paper_for_project_page, save_parsed_content\nfrom ProjectPageAgent.html_finder import HtmlFinder\nfrom ProjectPageAgent.content_planner import ProjectPageContentPlanner\nfrom ProjectPageAgent.html_generator import ProjectPageHTMLGenerator, to_url\nfrom utils.wei_utils import get_agent_config\nimport os\nimport subprocess\n\nfrom ProjectPageAgent.content_planner import filter_references\nfrom utils.src.utils import run_sync_screenshots\nfrom ProjectPageAgent.main_pipline import matching, copy_static_files\n\nload_dotenv()\n\n\n\ndef get_agent_config_with_keys(model_type, openai_api_key=\"\", gemini_api_key=\"\", \n qwen_api_key=\"\", zhipuai_api_key=\"\", openrouter_api_key=\"\"):\n \"\"\"\n Get agent configuration with user-provided API keys.\n Falls back to environment variables if user keys are not provided.\n Note: This function sets environment variables but does NOT restore them.\n The environment variables will remain set for the duration of the application.\n \"\"\"\n # Set environment variables with user-provided keys\n api_keys = {\n 'OPENAI_API_KEY': openai_api_key,\n 'GEMINI_API_KEY': gemini_api_key, \n 'QWEN_API_KEY': qwen_api_key,\n 'ZHIPUAI_API_KEY': zhipuai_api_key,\n 'OPENROUTER_API_KEY': openrouter_api_key\n }\n \n # Set new API keys in environment\n for key, value in api_keys.items():\n if value and value.strip():\n os.environ[key] = value\n \n # Get agent config with the new API keys\n config = get_agent_config(model_type)\n return config\n\ndef validate_api_keys(model_name_t, model_name_v, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key):\n \"\"\"\n Validate that required API keys are provided for the selected models.\n \"\"\"\n errors = []\n \n # Check text model requirements\n if model_name_t in ['4o', '4o-mini', 'gpt-4.1', 'gpt-4.1-mini', 'o1', 'o3', 'o3-mini']:\n if not openai_api_key or not openai_api_key.strip():\n errors.append(\"OpenAI API key is required for GPT models\")\n elif model_name_t in ['gemini', 'gemini-2.5-pro', 'gemini-2.5-flash']:\n if not gemini_api_key or not gemini_api_key.strip():\n errors.append(\"Gemini API key is required for Gemini models\")\n elif model_name_t in ['qwen', 'qwen-plus', 'qwen-max', 'qwen-long']:\n if not qwen_api_key or not qwen_api_key.strip():\n errors.append(\"Qwen API key is required for Qwen models\")\n elif model_name_t.startswith('openrouter_'):\n if not openrouter_api_key or not openrouter_api_key.strip():\n errors.append(\"OpenRouter API key is required for OpenRouter models\")\n \n # Check vision model requirements\n if model_name_v in ['4o', '4o-mini']:\n if not openai_api_key or not openai_api_key.strip():\n errors.append(\"OpenAI API key is required for GPT vision models\")\n elif model_name_v in ['gemini', 'gemini-2.5-pro', 'gemini-2.5-flash']:\n if not gemini_api_key or not gemini_api_key.strip():\n errors.append(\"Gemini API key is required for Gemini vision models\")\n elif model_name_v in ['qwen-vl-max', 'qwen-2.5-vl-72b']:\n if not qwen_api_key or not qwen_api_key.strip():\n errors.append(\"Qwen API key is required for Qwen vision models\")\n elif model_name_v.startswith('openrouter_'):\n if not openrouter_api_key or not openrouter_api_key.strip():\n errors.append(\"OpenRouter API key is required for OpenRouter vision models\")\n \n return errors\n\n# Global Variables\ncurrent_html_dir = None\npreview_server = None\npreview_port = None\ntemplate_preview_servers = []\n\nclass CustomHTTPRequestHandler(SimpleHTTPRequestHandler):\n def __init__(self, *args, **kwargs):\n super().__init__(*args, directory=current_html_dir, **kwargs)\n \n def log_message(self, format, *args):\n pass\n\ndef find_free_port(start_port=8000, max_attempts=100):\n for port in range(start_port, start_port + max_attempts):\n try:\n with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:\n s.bind(('', port))\n return port\n except OSError:\n continue\n raise RuntimeError(f\"Could not find available port\")\n\ndef start_preview_server(html_dir):\n global current_html_dir, preview_server, preview_port\n stop_preview_server()\n current_html_dir = html_dir\n preview_port = find_free_port()\n preview_server = HTTPServer(('0.0.0.0', preview_port), CustomHTTPRequestHandler)\n server_thread = Thread(target=preview_server.serve_forever, daemon=True)\n server_thread.start()\n return preview_port\n\ndef stop_preview_server():\n global preview_server, preview_port\n if preview_server:\n preview_server.shutdown()\n preview_server = None\n preview_port = None\n\ndef start_ephemeral_server_for_dir(html_dir):\n port = find_free_port()\n class _TempHandler(SimpleHTTPRequestHandler):\n def __init__(self, *args, **kwargs):\n super().__init__(*args, directory=html_dir, **kwargs)\n def log_message(self, format, *args):\n pass\n srv = HTTPServer(('0.0.0.0', port), _TempHandler)\n t = Thread(target=srv.serve_forever, daemon=True)\n t.start()\n template_preview_servers.append((srv, port))\n return port\n\ndef stop_all_template_preview_servers():\n global template_preview_servers\n for srv, _ in template_preview_servers:\n try:\n srv.shutdown()\n except Exception:\n pass\n template_preview_servers = []\n\nclass GenerationArgs:\n def __init__(self, paper_path, model_name_t, model_name_v, template_root, \n template_dir, template_file, output_dir, style_preference, tmp_dir,\n full_content_check_times, background_color, has_navigation, \n has_hero_section, title_color, page_density, image_layout, \n html_check_times, resume, human_input):\n self.paper_path = paper_path\n self.model_name_t = model_name_t\n self.model_name_v = model_name_v\n self.template_root = template_root\n self.template_dir = template_dir\n self.template_file = template_file\n self.output_dir = output_dir\n self.style_preference = style_preference\n self.tmp_dir = tmp_dir\n self.full_content_check_times = full_content_check_times\n self.background_color = background_color\n self.has_navigation = has_navigation\n self.has_hero_section = has_hero_section\n self.title_color = title_color\n self.page_density = page_density\n self.image_layout = image_layout\n self.html_check_times = html_check_times\n self.resume = resume\n self.human_input = human_input\n self.paper_name = None\n\n# ==================== Formatting Functions ====================\n\ndef format_section_to_markdown(section_data):\n \"\"\"\n Convert Section JSON to beautifully formatted Markdown\n \n Args:\n section_data: Section JSON data\n \n Returns:\n str: Formatted Markdown string\n \"\"\"\n if not section_data:\n return \"No data available\"\n \n md_lines = []\n \n # Title\n md_lines.append(\"# šŸ“„ Paper Page Structure Preview\\n\")\n \n # Basic Information\n if \"title\" in section_data:\n md_lines.append(f\"## šŸ“Œ Title\\n**{section_data['title']}**\\n\")\n \n if \"authors\" in section_data:\n md_lines.append(f\"## šŸ‘„ Authors\\n{section_data['authors']}\\n\")\n \n if \"affiliation\" in section_data:\n md_lines.append(f\"## šŸ›ļø Affiliation\\n{section_data['affiliation']}\\n\")\n \n # Other Sections\n md_lines.append(\"## šŸ“‘ Page Sections\\n\")\n \n section_count = 0\n for key, value in section_data.items():\n if key in [\"title\", \"authors\", \"affiliation\"]:\n continue\n \n section_count += 1\n \n # Section Title\n section_title = key.replace(\"_\", \" \").title()\n md_lines.append(f\"### {section_count}. {section_title}\\n\")\n \n # Section Content\n if isinstance(value, dict):\n # If dictionary, process recursively\n for sub_key, sub_value in value.items():\n sub_title = sub_key.replace(\"_\", \" \").title()\n md_lines.append(f\"**{sub_title}**: {sub_value}\\n\")\n elif isinstance(value, list):\n # If list\n for item in value:\n if isinstance(item, str):\n md_lines.append(f\"- {item}\\n\")\n elif isinstance(item, dict):\n for k, v in item.items():\n md_lines.append(f\"- **{k}**: {v}\\n\")\n else:\n # Simple value\n md_lines.append(f\"{value}\\n\")\n \n md_lines.append(\"\") # Empty line\n \n # Add Statistics\n md_lines.append(\"---\\n\")\n md_lines.append(f\"**šŸ“Š Total {section_count} sections**\\n\")\n \n return \"\\n\".join(md_lines)\n\n\ndef format_full_content_to_markdown(content_data, figures=None):\n \"\"\"\n Convert Full Content JSON to beautifully formatted Markdown\n \n Args:\n content_data: Full Content JSON data\n figures: Images and tables data (optional)\n \n Returns:\n str: Formatted Markdown string\n \"\"\"\n if not content_data:\n return \"No data available\"\n \n md_lines = []\n \n # Title\n md_lines.append(\"# šŸ“„ Full Content Preview\\n\")\n \n # Basic Information\n if \"title\" in content_data:\n md_lines.append(f\"# {content_data['title']}\\n\")\n \n if \"authors\" in content_data:\n md_lines.append(f\"**Authors**: {content_data['authors']}\\n\")\n \n if \"affiliation\" in content_data:\n md_lines.append(f\"**Affiliation**: {content_data['affiliation']}\\n\")\n \n md_lines.append(\"---\\n\")\n \n # Process Each Section\n section_count = 0\n image_count = 0\n table_count = 0\n \n for key, value in content_data.items():\n if key in [\"title\", \"authors\", \"affiliation\"]:\n continue\n \n section_count += 1\n \n # Section Title\n section_title = key.replace(\"_\", \" \").title()\n md_lines.append(f\"## {section_count}. {section_title}\\n\")\n \n # Process Content\n if isinstance(value, dict):\n # Process dictionary type content\n for sub_key, sub_value in value.items():\n if sub_key.lower() in ['content', 'description', 'text']:\n # Main text content\n md_lines.append(f\"{sub_value}\\n\")\n elif sub_key.lower() in ['image', 'figure', 'img']:\n # Image\n image_count += 1\n if isinstance(sub_value, dict):\n caption = sub_value.get('caption', f'Figure {image_count}')\n path = sub_value.get('path', '')\n md_lines.append(f\"\\n**šŸ–¼ļø {caption}**\\n\")\n if path:\n md_lines.append(f\"*Image path: `{path}`*\\n\")\n else:\n md_lines.append(f\"\\n**šŸ–¼ļø Figure {image_count}**: {sub_value}\\n\")\n elif sub_key.lower() in ['table']:\n # Table\n table_count += 1\n md_lines.append(f\"\\n**šŸ“Š Table {table_count}**\\n\")\n if isinstance(sub_value, dict):\n caption = sub_value.get('caption', f'Table {table_count}')\n md_lines.append(f\"*{caption}*\\n\")\n else:\n md_lines.append(f\"{sub_value}\\n\")\n elif sub_key.lower() in ['code']:\n # Code block\n md_lines.append(f\"\\n```\\n{sub_value}\\n```\\n\")\n else:\n # Other subtitles\n sub_title = sub_key.replace(\"_\", \" \").title()\n md_lines.append(f\"\\n### {sub_title}\\n\")\n md_lines.append(f\"{sub_value}\\n\")\n \n elif isinstance(value, list):\n # Process list type content\n for idx, item in enumerate(value):\n if isinstance(item, dict):\n # Dictionary items in list\n if 'title' in item or 'name' in item:\n item_title = item.get('title', item.get('name', f'Item {idx+1}'))\n md_lines.append(f\"\\n### {item_title}\\n\")\n \n for k, v in item.items():\n if k not in ['title', 'name']:\n if k.lower() in ['content', 'description', 'text']:\n md_lines.append(f\"{v}\\n\")\n elif k.lower() in ['image', 'figure']:\n image_count += 1\n md_lines.append(f\"\\n**šŸ–¼ļø Figure {image_count}**: {v}\\n\")\n elif k.lower() == 'table':\n table_count += 1\n md_lines.append(f\"\\n**šŸ“Š Table {table_count}**: {v}\\n\")\n else:\n k_title = k.replace(\"_\", \" \").title()\n md_lines.append(f\"**{k_title}**: {v}\\n\")\n else:\n # Simple list item\n md_lines.append(f\"- {item}\\n\")\n \n else:\n # Simple text value\n md_lines.append(f\"{value}\\n\")\n \n md_lines.append(\"\") # Empty line between sections\n \n # Add Statistics\n md_lines.append(\"\\n---\\n\")\n stats = []\n stats.append(f\"šŸ“Š **Statistics**\")\n stats.append(f\"- Sections: {section_count}\")\n if image_count > 0:\n stats.append(f\"- Images: {image_count}\")\n if table_count > 0:\n stats.append(f\"- Tables: {table_count}\")\n \n # If figures data is provided, add more information\n if figures:\n if 'images' in figures and figures['images']:\n stats.append(f\"- Available images: {len(figures['images'])}\")\n if 'tables' in figures and figures['tables']:\n stats.append(f\"- Available tables: {len(figures['tables'])}\")\n \n md_lines.append(\"\\n\".join(stats))\n md_lines.append(\"\\n\")\n \n return \"\\n\".join(md_lines)\n\n# ==================== Global State Management ====================\n\nclass GenerationState:\n def __init__(self):\n self.reset()\n \n def reset(self):\n self.args = None\n self.paper_content = None\n self.figures = None\n self.generated_section = None\n self.text_page_content = None\n self.generated_content = None\n self.html_content = None\n self.html_file_path = None\n self.html_dir = None\n self.planner = None\n self.html_generator = None\n self.agent_config_t = None\n self.total_input_tokens_t = 0\n self.total_output_tokens_t = 0\n self.current_stage = \"init\"\n self.preview_url = None\n\nstate = GenerationState()\n\ndef create_project_zip(project_dir, output_dir, paper_name):\n \"\"\"\n Create project archive\n \n Args:\n project_dir: Project directory path\n output_dir: Output directory\n paper_name: Paper name\n \n Returns:\n str: Archive path, None if failed\n \"\"\"\n import zipfile\n \n zip_filename = f\"{paper_name}_project_page.zip\"\n zip_path = os.path.join(output_dir, zip_filename)\n \n print(f\"Creating project archive: {zip_path}\")\n \n try:\n with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:\n # Traverse project directory, add all files\n for root, dirs, files in os.walk(project_dir):\n for file in files:\n file_path = os.path.join(root, file)\n # Calculate relative path\n arcname = os.path.relpath(file_path, output_dir)\n zipf.write(file_path, arcname)\n \n print(f\"Archive created successfully: {zip_path}\")\n \n # Get archive size\n zip_size = os.path.getsize(zip_path)\n zip_size_mb = zip_size / (1024 * 1024)\n print(f\"Archive size: {zip_size_mb:.2f} MB\")\n \n return zip_path\n \n except Exception as e:\n print(f\"Archive creation failed: {e}\")\n return None\n\ndef start_generation(pdf_file, model_name_t, model_name_v, template_root, \n template_dir, template_file, output_dir, style_preference, \n tmp_dir, full_content_check_times, background_color, \n has_navigation, has_hero_section, title_color, page_density, \n image_layout, html_check_times, resume, human_input, \n template_choice_value, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key):\n \"\"\"Start generation process\"\"\"\n if pdf_file is None:\n return \"āŒ Please upload a PDF file\", gr.update(visible=False), \"\", \"\", gr.update(), gr.update(), \"\"\n \n # Validate API keys\n validation_errors = validate_api_keys(\n model_name_t, model_name_v, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key\n )\n \n if validation_errors:\n error_msg = \"āŒ API Key Validation Failed:\\n\" + \"\\n\".join(f\"• {error}\" for error in validation_errors)\n return error_msg, gr.update(visible=False), \"\", \"\", gr.update(), gr.update(), \"\"\n \n state.reset()\n \n # Handle template selection\n if not (template_dir and str(template_dir).strip()):\n if not template_choice_value:\n stop_all_template_preview_servers()\n template_requirement = {\n \"background_color\": background_color,\n \"has_hero_section\": has_hero_section,\n \"Page density\": page_density,\n \"image_layout\": image_layout,\n \"has_navigation\": has_navigation,\n \"title_color\": title_color\n }\n try:\n matched = matching(template_requirement)\n except Exception as e:\n return f\"āŒ Template recommendation failed: {e}\", gr.update(visible=False), \"\", \"\", gr.update(choices=[], value=None), gr.update(visible=False, value=\"\"), \"\"\n \n html_finder_ = HtmlFinder()\n with open('templates/template_link.json','r') as f:\n template_link = json.load(f)\n previews = []\n for name in matched:\n t_dir = os.path.join(template_root, name)\n try:\n html_path = html_finder_.find_html(t_dir)\n if not os.path.exists(html_path):\n continue\n html_dir = os.path.dirname(os.path.abspath(html_path))\n filename = os.path.basename(html_path)\n port = start_ephemeral_server_for_dir(html_dir)\n url = template_link[name]\n previews.append((name, html_path, url))\n except Exception:\n continue\n \n if not previews:\n return \"āŒ No previewable templates found\", gr.update(visible=False), \"\", \"\", gr.update(choices=[], value=None), gr.update(visible=False, value=\"\"), \"\"\n \n md_lines = [\"### šŸ” Please select a template to preview before clicking **Start Generation**\", \"\"]\n for name, _, url in previews:\n md_lines.append(f\"- **{name}** → [{url}]({url})\")\n md = \"\\n\".join(md_lines)\n \n return \"Recommended 3 templates, please select one to continue\", gr.update(visible=False), \"\", \"\", gr.update(choices=[n for n, _, _ in previews], value=None), gr.update(visible=True, value=md), \"\"\n \n template_dir = os.path.join(template_root, template_choice_value)\n \n # Create arguments object\n args = GenerationArgs(\n paper_path=pdf_file.name,\n model_name_t=model_name_t,\n model_name_v=model_name_v,\n template_root=template_root,\n template_dir=template_dir,\n template_file=template_file,\n output_dir=output_dir,\n style_preference=style_preference,\n tmp_dir=tmp_dir,\n full_content_check_times=full_content_check_times,\n background_color=background_color,\n has_navigation=has_navigation,\n has_hero_section=has_hero_section,\n title_color=title_color,\n page_density=page_density,\n image_layout=image_layout,\n html_check_times=html_check_times,\n resume=resume,\n human_input=human_input\n )\n \n if not args.template_dir:\n return \"āŒ Please select a template\", gr.update(visible=False), \"\", \"\", gr.update(), gr.update(), \"\"\n \n if not args.template_file:\n html_finder_ = HtmlFinder()\n args.template_file = html_finder_.find_html(args.template_dir)\n \n paper_name = args.paper_path.split('/')[-1].replace('.pdf', '') if '/' in args.paper_path else args.paper_path.replace('.pdf', '')\n args.paper_name = paper_name\n \n os.makedirs(args.tmp_dir, exist_ok=True)\n \n try:\n # Initialization\n agent_config_t = get_agent_config_with_keys(\n args.model_name_t, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key\n )\n state.agent_config_t = agent_config_t\n state.args = args\n \n # Step 1: Parse PDF\n print(\"=\"*50)\n print(\"STEP 1: Parsing Research Paper\")\n print(\"=\"*50)\n \n raw_content_path = f'project_contents/{args.paper_name}_raw_content.json'\n if not os.path.exists(raw_content_path):\n agent_config_v = get_agent_config_with_keys(\n args.model_name_v, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key\n )\n input_token, output_token, raw_result, images, tables = parse_paper_for_project_page(args, agent_config_t)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n raw_content_path, _ = save_parsed_content(args, raw_result, images, tables, input_token, output_token)\n \n with open(raw_content_path, 'r') as f:\n paper_content = json.load(f)\n \n images = paper_content.get('images', [])\n tables = paper_content.get('tables', [])\n figures = {'images': images, 'tables': tables}\n paper_content = paper_content.get('markdown_content', \"\")\n \n state.paper_content = paper_content\n state.figures = figures\n \n # Step 2: Filter content\n print(\"=\"*50)\n print(\"STEP 2: Filtering Content\")\n print(\"=\"*50)\n \n planner = ProjectPageContentPlanner(agent_config_t, args)\n state.planner = planner\n \n paper_content, figures, input_token, output_token = planner.filter_raw_content(paper_content, figures)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n state.paper_content = paper_content\n state.figures = figures\n \n # Step 3: Generate Section\n print(\"=\"*50)\n print(\"STEP 3: Generating Sections\")\n print(\"=\"*50)\n \n state.current_stage = \"section\"\n \n generated_section, input_token, output_token = generate_section_initial()\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n # Use Markdown formatting\n section_display_md = format_section_to_markdown(generated_section)\n section_display_json = json.dumps(generated_section, indent=2, ensure_ascii=False)\n \n return (\n f\"āœ… Section generation completed, please review and provide feedback\\n\\nTokens: {input_token} → {output_token}\",\n gr.update(visible=True), # feedback_section\n section_display_md, # Markdown format\n section_display_json, # JSON format (hidden)\n gr.update(),\n gr.update(visible=False, value=\"\"),\n \"\"\n )\n \n except Exception as e:\n import traceback\n error_msg = f\"āŒ Generation failed: {str(e)}\\n{traceback.format_exc()}\"\n return error_msg, gr.update(visible=False), \"\", \"\", gr.update(), gr.update(), \"\"\n\ndef create_dynamic_page_dict(sections):\n poster_dict = {\n \"title\": \"Title of the paper\",\n \"authors\": \"Authors of the paper\",\n \"affiliation\": \"Affiliation of the authors\",\n }\n poster_dict.update(sections)\n return poster_dict\ndef generate_section_initial():\n \"\"\"Generate initial Section\"\"\"\n import yaml\n from jinja2 import Environment, StrictUndefined\n from utils.wei_utils import account_token\n from utils.src.utils import get_json_from_response\n \n with open('utils/prompt_templates/page_templates/section_generation.yaml', 'r') as f:\n planner_config = yaml.safe_load(f)\n \n jinja_env = Environment(undefined=StrictUndefined)\n template = jinja_env.from_string(planner_config[\"template\"])\n \n jinja_args = {\n 'paper_content': state.paper_content,\n 'json_format_example': json.dumps(state.paper_content, indent=2)\n }\n \n prompt = template.render(**jinja_args)\n \n state.planner.planner_agent.reset()\n response = state.planner.planner_agent.step(prompt)\n input_token, output_token = account_token(response)\n generated_section = get_json_from_response(response.msgs[0].content)\n generated_section = create_dynamic_page_dict(generated_section)\n state.generated_section = generated_section\n \n generated_path = f'project_contents/{state.args.paper_name}_generated_section.json'\n with open(generated_path, 'w') as f:\n json.dump(generated_section, f, indent=4)\n \n return generated_section, input_token, output_token\n\ndef submit_section_feedback(feedback_text):\n \"\"\"Submit Section feedback\"\"\"\n if not feedback_text or feedback_text.strip().lower() == 'yes':\n # User satisfied, proceed to next stage\n result = proceed_to_text_content()\n status, fc_section_visible, fc_display_visible, fc_display_md, fc_display_json, fc_feedback_visible = result\n return (\n status,\n \"\", # section_display_md clear\n \"\", # section_display_json clear\n \"\", # section_feedback_input clear\n gr.update(visible=False), # feedback_section hide\n fc_section_visible, # feedback_full_content show\n fc_display_visible, # full_content_display_md show\n fc_display_md, # full_content_display_md content\n fc_display_json, # full_content_display_json content\n fc_feedback_visible # full_content_feedback_input show\n )\n \n # User provides feedback, modify Section\n from camel.messages import BaseMessage\n from utils.wei_utils import account_token\n from utils.src.utils import get_json_from_response\n \n message = BaseMessage.make_assistant_message(\n role_name='User',\n content=f'human feedback: {feedback_text}\\n\\nPlease make modifications based on this feedback. Output format as specified above.'\n )\n response = state.planner.planner_agent.step(message)\n input_token, output_token = account_token(response)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n generated_section = get_json_from_response(response.msgs[0].content)\n generated_section = create_dynamic_page_dict(generated_section)\n state.generated_section = generated_section\n \n generated_path = f'project_contents/{state.args.paper_name}_generated_section.json'\n with open(generated_path, 'w') as f:\n json.dump(generated_section, f, indent=4)\n \n # Use Markdown formatting\n section_display_md = format_section_to_markdown(generated_section)\n section_display_json = json.dumps(generated_section, indent=2, ensure_ascii=False)\n \n return (\n f\"āœ… Section updated, please continue reviewing\\n\\nTokens: {input_token} → {output_token}\",\n section_display_md, # Markdown format\n section_display_json, # JSON format\n \"\", # Clear input box\n gr.update(visible=True), # feedback_section keep visible\n gr.update(visible=False), # feedback_full_content keep hidden\n gr.update(visible=False), # full_content_display_md keep hidden\n \"\", # full_content_display_md content\n \"\", # full_content_display_json content\n gr.update(visible=False) # full_content_feedback_input keep hidden\n )\n\ndef proceed_to_text_content():\n \"\"\"Enter Text Content generation stage\"\"\"\n print(\"=\"*50)\n print(\"STEP 4: Generating Text Content\")\n print(\"=\"*50)\n \n text_page_content, input_token, output_token = state.planner.text_content_generation(\n state.paper_content, state.figures, state.generated_section\n )\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n state.text_page_content = text_page_content\n \n # Enter Full Content stage\n return proceed_to_full_content()\n\ndef proceed_to_full_content():\n \"\"\"Enter Full Content generation stage\"\"\"\n print(\"=\"*50)\n print(\"STEP 5: Generating Full Content\")\n print(\"=\"*50)\n \n state.current_stage = \"full_content\"\n \n generated_content, input_token, output_token = generate_full_content_initial()\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n # Use Markdown formatting\n content_display_md = format_full_content_to_markdown(generated_content, state.figures)\n content_display_json = json.dumps(generated_content, indent=2, ensure_ascii=False)\n \n return (\n f\"āœ… Full Content generation completed, please review and provide feedback\\n\\nTokens: {input_token} → {output_token}\",\n gr.update(visible=True), # feedback_full_content show\n gr.update(visible=True), # full_content_display_md show\n content_display_md, # Markdown format\n content_display_json, # JSON format\n gr.update(visible=True) # full_content_feedback_input show\n )\n\ndef generate_full_content_initial():\n \"\"\"Generate initial Full Content\"\"\"\n import yaml\n from jinja2 import Environment, StrictUndefined\n from utils.wei_utils import account_token\n from utils.src.utils import get_json_from_response\n \n with open('utils/prompt_templates/page_templates/full_content_generation.yaml', 'r') as f:\n planner_config = yaml.safe_load(f)\n \n jinja_env = Environment(undefined=StrictUndefined)\n template = jinja_env.from_string(planner_config[\"template\"])\n \n jinja_args = {\n 'paper_content': state.paper_content,\n 'figures': json.dumps(state.figures, indent=2),\n 'project_page_content': json.dumps(state.text_page_content, indent=2)\n }\n \n prompt = template.render(**jinja_args)\n \n state.planner.planner_agent.reset()\n response = state.planner.planner_agent.step(prompt)\n input_token, output_token = account_token(response)\n generated_content = get_json_from_response(response.msgs[0].content)\n \n state.generated_content = generated_content\n \n first_path = f'project_contents/{state.args.paper_name}_generated_full_content.v0.json'\n with open(first_path, 'w', encoding='utf-8') as f:\n json.dump(generated_content, f, ensure_ascii=False, indent=2)\n \n return generated_content, input_token, output_token\n\ndef submit_full_content_feedback(feedback_text):\n \"\"\"Submit Full Content feedback\"\"\"\n if not feedback_text or feedback_text.strip().lower() == 'yes':\n # User satisfied, proceed to HTML generation\n result = proceed_to_html_generation()\n status, html_feedback_visible, preview_info, preview_url, open_btn_visible = result\n return (\n status,\n \"\", # full_content_display_md clear\n \"\", # full_content_display_json clear\n \"\", # full_content_feedback_input clear\n gr.update(visible=False), # feedback_full_content hide\n html_feedback_visible, # feedback_html show\n preview_info, # preview_info_display\n preview_url, # preview_url_state\n open_btn_visible # open_preview_btn show\n )\n \n # User provides feedback\n from camel.messages import BaseMessage\n from utils.wei_utils import account_token\n from utils.src.utils import get_json_from_response\n \n message = BaseMessage.make_assistant_message(\n role_name='User',\n content=f'human feedback: {feedback_text}\\n\\nPlease make modifications based on this feedback. Output format as specified above.'\n )\n response = state.planner.planner_agent.step(message)\n input_token, output_token = account_token(response)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n generated_content = get_json_from_response(response.msgs[0].content)\n state.generated_content = generated_content\n \n final_path = f'project_contents/{state.args.paper_name}_generated_full_content.json'\n with open(final_path, 'w', encoding='utf-8') as f:\n json.dump(generated_content, f, ensure_ascii=False, indent=2)\n \n # Use Markdown formatting\n content_display_md = format_full_content_to_markdown(generated_content, state.figures)\n content_display_json = json.dumps(generated_content, indent=2, ensure_ascii=False)\n \n return (\n f\"āœ… Full Content updated, please continue reviewing\\n\\nTokens: {input_token} → {output_token}\",\n content_display_md, # Markdown format\n content_display_json, # JSON format\n \"\", # Clear input box\n gr.update(visible=True), # feedback_full_content keep visible\n gr.update(visible=False), # feedback_html keep hidden\n \"\", # preview_info_display\n \"\", # preview_url_state\n gr.update(visible=False) # open_preview_btn keep hidden\n )\n\ndef proceed_to_html_generation():\n \"\"\"Enter HTML generation stage\"\"\"\n print(\"=\"*50)\n print(\"STEP 6: Generating HTML\")\n print(\"=\"*50)\n \n state.current_stage = \"html\"\n \n # Copy static files\n static_dir = copy_static_files(\n state.args.template_file, \n state.args.template_dir, \n state.args.output_dir, \n state.args.paper_name\n )\n \n # Generate HTML\n html_relative_path = os.path.relpath(state.args.template_file, state.args.template_dir)\n html_dir = '/'.join(html_relative_path.strip().split('/')[:-1])\n state.html_dir = html_dir\n \n html_generator = ProjectPageHTMLGenerator(state.agent_config_t, state.args)\n state.html_generator = html_generator\n \n with open(state.args.template_file, 'r', encoding='utf-8') as file:\n html_template = file.read()\n \n # Create assets directory\n assets_dir = html_generator.create_assets_directory(state.args, html_dir, state.args.output_dir)\n \n # Generate HTML\n html_content, input_token, output_token = html_generator.generate_complete_html(\n state.args, state.generated_content, html_dir, html_template\n )\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n # Save HTML (before table modification)\n html_dir_path = os.path.join(state.args.output_dir, state.args.paper_name, html_dir)\n os.makedirs(html_dir_path, exist_ok=True)\n \n html_file_path_no_modify = os.path.join(html_dir_path, 'index_no_modify_table.html')\n with open(html_file_path_no_modify, 'w', encoding='utf-8') as file:\n file.write(html_content)\n \n # Generate screenshot (before table modification)\n screenshot_path_no_modify = os.path.join(html_dir_path, 'page_final_no_modify_table.png')\n run_sync_screenshots(to_url(html_file_path_no_modify), screenshot_path_no_modify)\n \n # Modify tables\n html_content, input_token, output_token = html_generator.modify_html_table(html_content, html_dir)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n state.html_content = html_content\n \n # Save HTML (after table modification)\n html_file_path = os.path.join(html_dir_path, 'index.html')\n with open(html_file_path, 'w', encoding='utf-8') as file:\n file.write(html_content)\n \n state.html_file_path = html_file_path\n \n # Generate screenshot (after table modification)\n run_sync_screenshots(\n to_url(html_file_path), \n os.path.join(html_dir_path, 'page_final.png')\n )\n \n # Start preview server\n html_full_dir = os.path.dirname(os.path.abspath(html_file_path))\n port = start_preview_server(html_full_dir)\n preview_url = f\"http://localhost:{port}/index.html\"\n state.preview_url = preview_url\n \n # Create preview info display\n preview_info = f\"\"\"\n### 🌐 HTML Generation Completed\n\n**Preview URL**: {preview_url}\n\n**Instructions**:\n1. Click the **\"🌐 Open Preview in New Tab\"** button below to view the generated webpage\n2. Carefully review the page in the new tab\n3. If satisfied, enter **'yes'** in the feedback box and submit\n4. If modifications are needed, provide detailed feedback and submit\n\n**Token Usage**: {input_token} → {output_token}\n\"\"\"\n \n return (\n f\"āœ… HTML generation completed\\n\\nTokens: {input_token} → {output_token}\",\n gr.update(visible=True), # feedback_html show\n preview_info, # preview_info_display\n preview_url, # preview_url_state\n gr.update(visible=True) # open_preview_btn show\n )\n\ndef submit_html_feedback(feedback_text):\n \"\"\"Submit HTML feedback\"\"\"\n if not feedback_text or feedback_text.strip().lower() == 'yes':\n # User satisfied, complete generation\n result = finalize_generation()\n status, html_file = result\n return (\n status,\n \"\", # preview_info_display clear\n \"\", # html_feedback_input clear\n gr.update(visible=False), # feedback_html hide\n gr.update(visible=False), # open_preview_btn hide\n html_file # html_file_output\n )\n \n # User provides feedback\n html_content, input_token, output_token = state.html_generator.modify_html_from_human_feedback(\n state.html_content, feedback_text\n )\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n state.html_content = html_content\n \n # Save updated HTML\n html_dir_path = os.path.dirname(state.html_file_path)\n \n # Save as temporary version (for possible feedback iteration)\n import time\n timestamp = int(time.time())\n html_file_feedback = os.path.join(html_dir_path, f'index_feedback_{timestamp}.html')\n with open(html_file_feedback, 'w', encoding='utf-8') as file:\n file.write(html_content)\n \n # Also update main file\n with open(state.html_file_path, 'w', encoding='utf-8') as file:\n file.write(html_content)\n \n # Regenerate screenshot\n screenshot_path = os.path.join(html_dir_path, 'page_final.png')\n try:\n run_sync_screenshots(to_url(state.html_file_path), screenshot_path)\n except Exception as e:\n print(f\"Screenshot generation failed: {e}\")\n \n # Update preview info\n preview_info = f\"\"\"\n### 🌐 HTML Updated\n\n**Preview URL**: {state.preview_url}\n\n**Instructions**:\n1. Click the **\"🌐 Open Preview in New Tab\"** button below to view the updated webpage\n2. **Refresh the browser** to see the latest version\n3. If satisfied, enter **'yes'** in the feedback box and submit\n4. If further modifications are needed, continue providing feedback\n\n**Token Usage**: {input_token} → {output_token}\n\"\"\"\n \n return (\n f\"āœ… HTML updated, please refresh the preview page\\n\\nTokens: {input_token} → {output_token}\",\n preview_info, # preview_info_display\n \"\", # Clear input box\n gr.update(visible=True), # feedback_html keep visible\n gr.update(visible=True), # open_preview_btn keep visible\n None # html_file_output no download yet\n )\n\ndef finalize_generation():\n \"\"\"Complete generation and save final results\"\"\"\n import time\n \n # Ensure final HTML is saved\n html_dir_path = os.path.dirname(state.html_file_path)\n \n # Save final version\n final_html_path = os.path.join(html_dir_path, 'index_final.html')\n with open(final_html_path, 'w', encoding='utf-8') as file:\n file.write(state.html_content)\n \n # Also update main file\n with open(state.html_file_path, 'w', encoding='utf-8') as file:\n file.write(state.html_content)\n \n # Save metadata\n metadata = state.html_generator.generate_metadata(state.generated_content, state.args)\n metadata_path = state.html_generator.save_metadata(metadata, state.args, state.args.output_dir)\n \n # Create README file\n readme_path = os.path.join(state.args.output_dir, state.args.paper_name, 'README.md')\n readme_content = f\"\"\"# {state.args.paper_name} - Project Page\n\n## šŸ“„ Project Information\n\n- **Paper Name**: {state.args.paper_name}\n- **Generation Time**: {time.strftime('%Y-%m-%d %H:%M:%S')}\n- **Text Model**: {state.args.model_name_t}\n- **Vision Model**: {state.args.model_name_v}\n\n## šŸš€ Usage\n\n1. Extract this archive to any directory\n2. Open `index.html` to view the project page\n3. All resources (CSS, images, etc.) are included\n\n## šŸ“ File Structure\n\n- `index.html` - Main page file\n- `index_final.html` - Final confirmed version\n- `assets/` - Image and table resources\n- `css/` or `styles/` - Style files\n- `js/` or `scripts/` - JavaScript files\n- `metadata.json` - Page metadata\n- `generation_log.json` - Generation log\n\n## šŸ’” Tips\n\n- Recommended browsers: Chrome, Firefox, Safari, Edge\n- For web deployment, simply upload the entire folder\n- Feel free to modify HTML and CSS for customization\n\n---\nGenerated by Paper2ProjectPage\n\"\"\"\n \n with open(readme_path, 'w', encoding='utf-8') as f:\n f.write(readme_content)\n \n # Save generation log\n log_data = {\n 'paper_name': state.args.paper_name,\n 'paper_path': state.args.paper_path,\n 'models': {\n 'text_model': state.args.model_name_t,\n 'vision_model': state.args.model_name_v\n },\n 'token_usage': {\n 'text_input_tokens': state.total_input_tokens_t,\n 'text_output_tokens': state.total_output_tokens_t\n },\n 'output_files': {\n 'html_file': state.html_file_path,\n 'final_html_file': final_html_path,\n 'metadata_file': metadata_path,\n 'readme_file': readme_path\n },\n 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S')\n }\n \n log_path = f\"{state.args.output_dir}/{state.args.paper_name}/generation_log.json\"\n with open(log_path, 'w') as f:\n json.dump(log_data, f, indent=4, ensure_ascii=False)\n \n # Create project archive\n project_dir = os.path.join(state.args.output_dir, state.args.paper_name)\n zip_path = create_project_zip(project_dir, state.args.output_dir, state.args.paper_name)\n \n if zip_path and os.path.exists(zip_path):\n # Get archive size\n zip_size = os.path.getsize(zip_path)\n zip_size_mb = zip_size / (1024 * 1024)\n zip_filename = os.path.basename(zip_path)\n \n success_msg = f\"\"\"\nāœ… Project page generation completed!\n\nšŸ“ Output directory: {state.args.output_dir}/{state.args.paper_name}\n🌐 HTML file: {state.html_file_path}\n🌐 Final version: {final_html_path}\nšŸ“‹ Metadata: {metadata_path}\nšŸ“– README: {readme_path}\nšŸ“Š Log file: {log_path}\nšŸ“¦ Archive: {zip_filename} ({zip_size_mb:.2f} MB)\nšŸ”¢ Total token usage: {state.total_input_tokens_t} → {state.total_output_tokens_t}\n\nšŸŽ‰ All feedback completed, page successfully generated!\nClick the button below to download the complete project archive (including HTML, CSS, images, README, and all resources).\n\"\"\"\n \n return (\n success_msg,\n zip_path # Return archive for download\n )\n \n else:\n error_msg = f\"\"\"\nāš ļø Project page generated, but archive creation failed!\n\nšŸ“ Output directory: {state.args.output_dir}/{state.args.paper_name}\n🌐 HTML file: {state.html_file_path}\nšŸ“‹ Metadata: {metadata_path}\n\nYou can manually retrieve all files from the output directory {project_dir}.\n\"\"\"\n return (\n error_msg,\n state.html_file_path # Return HTML file\n )\n\n# ==================== Gradio Interface ====================\n\n# Custom CSS for better English font rendering\ncustom_css = \"\"\"\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');\n\n* {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !important;\n}\n\ncode, pre, .code {\n font-family: 'JetBrains Mono', 'Courier New', Consolas, Monaco, monospace !important;\n}\n\nh1, h2, h3, h4, h5, h6 {\n font-weight: 600 !important;\n letter-spacing: -0.02em !important;\n}\n\n.markdown-text {\n line-height: 1.7 !important;\n font-size: 15px !important;\n}\n\n.gr-button {\n font-weight: 500 !important;\n letter-spacing: 0.01em !important;\n}\n\n.gr-input, .gr-textarea {\n font-size: 14px !important;\n line-height: 1.6 !important;\n}\n\n.gr-box {\n border-radius: 8px !important;\n}\n\n/* Better spacing for English content */\n.gr-markdown p {\n margin-bottom: 0.8em !important;\n}\n\n.gr-markdown ul, .gr-markdown ol {\n margin-left: 1.2em !important;\n}\n\n.gr-markdown li {\n margin-bottom: 0.4em !important;\n}\n\"\"\"\n\nwith gr.Blocks(title=\"Paper2ProjectPage Generator\", theme=gr.themes.Soft(), css=custom_css) as demo:\n \n gr.Markdown(\"\"\"\n # šŸ“„ AutoPage Generator with Interactive Feedback\n \n Upload your research paper PDF and generate beautiful project pages through multi-round interactive feedback\n \"\"\")\n \n with gr.Row():\n with gr.Column(scale=1):\n # PDF Upload\n pdf_input = gr.File(\n label=\"šŸ“Ž Upload PDF Paper\",\n file_types=[\".pdf\"],\n type=\"filepath\"\n )\n \n gr.Markdown(\"### šŸ”‘ API Keys Configuration\")\n gr.Markdown(\"\"\"\n **āš ļø Security Notice**: Your API keys are only stored in memory during the session and are never saved to disk.\n \n **šŸ’” Note**: You only need to fill in ONE API key corresponding to the models you selected below.\n \n **šŸ“‹ How to get API keys:**\n - **OpenAI**: Get your API key from [OpenAI Platform](https://platform.openai.com/api-keys)\n - **Gemini**: Get your API key from [Google AI Studio](https://aistudio.google.com/app/apikey)\n - **Qwen**: Get your API key from [DashScope](https://dashscope.console.aliyun.com/apiKey)\n - **ZhipuAI**: Get your API key from [ZhipuAI Console](https://open.bigmodel.cn/usercenter/apikeys)\n - **OpenRouter**: Get your API key from [OpenRouter](https://openrouter.ai/keys)\n \n **šŸš€ For HuggingFace Spaces**: You can also set these as environment variables in your Space settings.\n \"\"\")\n \n with gr.Row():\n openai_api_key = gr.Textbox(\n label=\"OpenAI API Key\",\n value=os.getenv(\"OPENAI_API_KEY\", \"\"),\n type=\"password\",\n placeholder=\"sk-...\",\n info=\"Required for GPT models\"\n )\n gemini_api_key = gr.Textbox(\n label=\"Gemini API Key\", \n value=os.getenv(\"GEMINI_API_KEY\", \"\"),\n type=\"password\",\n placeholder=\"AI...\",\n info=\"Required for Gemini models\"\n )\n \n with gr.Row():\n qwen_api_key = gr.Textbox(\n label=\"Qwen API Key\",\n value=os.getenv(\"QWEN_API_KEY\", \"\"),\n type=\"password\", \n placeholder=\"sk-...\",\n info=\"Required for Qwen models\"\n )\n zhipuai_api_key = gr.Textbox(\n label=\"ZhipuAI API Key\",\n value=os.getenv(\"ZHIPUAI_API_KEY\", \"\"),\n type=\"password\",\n placeholder=\"...\",\n info=\"Required for GLM models\"\n )\n \n openrouter_api_key = gr.Textbox(\n label=\"OpenRouter API Key\",\n value=os.getenv(\"OPENROUTER_API_KEY\", \"\"),\n type=\"password\",\n placeholder=\"sk-or-...\",\n info=\"Required for OpenRouter models\"\n )\n \n gr.Markdown(\"### šŸ¤– Model Configuration\")\n \n # Text Model Options\n text_model_options = [\n (\"GPT-4o\", \"4o\"),\n (\"GPT-4o Mini\", \"4o-mini\"),\n (\"GPT-4.1\", \"gpt-4.1\"),\n (\"GPT-4.1 Mini\", \"gpt-4.1-mini\"),\n (\"O1\", \"o1\"),\n (\"O3\", \"o3\"),\n (\"O3 Mini\", \"o3-mini\"),\n (\"Gemini 2.5 Pro\", \"gemini\"),\n (\"Gemini 2.5 Pro (Alt)\", \"gemini-2.5-pro\"),\n (\"Gemini 2.5 Flash\", \"gemini-2.5-flash\"),\n (\"Qwen\", \"qwen\"),\n (\"Qwen Plus\", \"qwen-plus\"),\n (\"Qwen Max\", \"qwen-max\"),\n (\"Qwen Long\", \"qwen-long\"),\n (\"OpenRouter Qwen Plus\", \"openrouter_qwen-plus\"),\n (\"OpenRouter GPT-4o Mini\", \"openrouter_gpt-4o-mini\"),\n (\"OpenRouter Gemini 2.5 Flash\", \"openrouter_gemini-2.5-flash\"),\n (\"OpenRouter O3\", \"openrouter_openai/o3\"),\n (\"OpenRouter Claude Sonnet 4.5\", \"openrouter_claude-sonnet-4.5\"),\n ]\n \n # Vision Model Options\n vision_model_options = [\n (\"GPT-4o\", \"4o\"),\n (\"GPT-4o Mini\", \"4o-mini\"),\n (\"Gemini 2.5 Pro\", \"gemini\"),\n (\"Gemini 2.5 Pro (Alt)\", \"gemini-2.5-pro\"),\n (\"Gemini 2.5 Flash\", \"gemini-2.5-flash\"),\n (\"Qwen VL Max\", \"qwen-vl-max\"),\n (\"Qwen 2.5 VL 72B\", \"qwen-2.5-vl-72b\"),\n (\"OpenRouter Qwen VL 72B\", \"openrouter_qwen_vl_72b\"),\n (\"OpenRouter Qwen VL 7B\", \"openrouter_qwen_vl_7b\"),\n (\"OpenRouter Qwen VL Max\", \"openrouter_qwen-vl-max\"),\n (\"OpenRouter Gemini 2.5 Flash\", \"openrouter_gemini-2.5-flash\"),\n ]\n \n with gr.Row():\n model_name_t = gr.Dropdown(\n label=\"Text Model\",\n choices=text_model_options,\n value=\"gemini\",\n info=\"Select model for text processing\"\n )\n model_name_v = gr.Dropdown(\n label=\"Vision Model\", \n choices=vision_model_options,\n value=\"gemini\",\n info=\"Select model for vision processing\"\n )\n \n # Hidden backend configuration fields\n template_root = gr.Textbox(\n label=\"Template Root\",\n value=\"templates\",\n visible=False\n )\n template_dir = gr.Textbox(\n label=\"Template Directory\",\n value=\"\",\n visible=False\n )\n template_file = gr.Textbox(\n label=\"Template File\",\n value=\"\",\n visible=False\n )\n output_dir = gr.Textbox(\n label=\"Output Directory\",\n value=\"generated_project_pages\",\n visible=False\n )\n style_preference = gr.Textbox(\n label=\"Style Preference JSON\",\n value=\"\",\n visible=False\n )\n tmp_dir = gr.Textbox(\n label=\"Temporary Directory\",\n value=\"tmp\",\n visible=False\n )\n \n # Hidden parameters with default values\n resume = gr.Radio(\n label=\"Resume From Step\",\n choices=['parse_pdf', 'generate_content','full_content_check', 'generate_html', 'html_check','modify_table','html_feedback'],\n value='parse_pdf',\n visible=False\n )\n \n human_input = gr.Radio(\n label=\"Enable Human Feedback\",\n choices=[0, 1],\n value=1,\n visible=False\n )\n \n full_content_check_times = gr.Number(\n label=\"Full Content Check Times\",\n value=1,\n precision=0,\n visible=False\n )\n \n html_check_times = gr.Number(\n label=\"HTML Check Times\",\n value=1,\n precision=0,\n visible=False\n )\n \n with gr.Column(scale=1):\n gr.Markdown(\"\"\"\n ### šŸ’” User Guide\n \n 1. **Upload PDF**: Select your research paper PDF file\n 2. **Configure API Key**: Fill in ONE API key for your selected models\n 3. **Select Models**: Choose text and vision models from dropdowns\n 4. **Configure Style**: Adjust style preferences below\n 5. **Start Generation**: Click the \"Start Generation\" button\n 6. **Three-Stage Feedback**:\n - šŸ“ **Section Feedback**: Review the generated page structure (Markdown preview + JSON data)\n - šŸ“„ **Full Content Feedback**: Review the generated complete content (Markdown preview + JSON data)\n - 🌐 **HTML Feedback**: View the generated webpage in a new tab\n 7. **Download Results**: Download the complete project archive after completion\n \n āš ļø **Tips**: \n - Each stage supports multiple rounds of feedback until you're satisfied\n - Enter 'yes' to proceed to the next stage\n - The final ZIP download includes the complete project folder with all resources\n \"\"\")\n \n gr.Markdown(\"### šŸŽØ Style Configuration\")\n \n with gr.Row():\n with gr.Column():\n background_color = gr.Radio(\n label=\"Background Color\",\n choices=[\"light\", \"dark\"],\n value=\"light\",\n info=\"Background color theme\"\n )\n \n has_navigation = gr.Radio(\n label=\"Has Navigation\",\n choices=[\"yes\", \"no\"],\n value=\"yes\",\n info=\"Include navigation bar\"\n )\n \n has_hero_section = gr.Radio(\n label=\"Has Hero Section\",\n choices=[\"yes\", \"no\"],\n value=\"yes\",\n info=\"Include hero/header section\"\n )\n \n with gr.Column():\n title_color = gr.Radio(\n label=\"Title Color\",\n choices=[\"pure\", \"colorful\"],\n value=\"pure\",\n info=\"Title color style\"\n )\n \n page_density = gr.Radio(\n label=\"Page Density\",\n choices=[\"spacious\", \"compact\"],\n value=\"spacious\",\n info=\"Page spacing density\"\n )\n \n image_layout = gr.Radio(\n label=\"Image Layout\",\n choices=[\"rotation\", \"parallelism\"],\n value=\"parallelism\",\n info=\"Image layout style\"\n )\n \n gr.Markdown(\"### šŸ“ Template Selection\")\n \n template_choice = gr.Radio(\n label=\"Recommended Templates\",\n choices=[],\n value=None,\n info=\"Select from recommended templates\"\n )\n \n template_preview_links = gr.Markdown(\n value=\"\",\n visible=False\n )\n \n # Start Generation Button\n start_btn = gr.Button(\"šŸš€ Start Generation\", variant=\"primary\", size=\"lg\")\n \n # Status Output\n status_output = gr.Textbox(\n label=\"šŸ“Š Generation Status\",\n lines=5,\n interactive=False\n )\n \n # Section Feedback Area\n with gr.Group(visible=False) as feedback_section:\n gr.Markdown(\"### šŸ“ Section Generation Results\")\n gr.Markdown(\"Please review the generated section structure. If satisfied, enter **'yes'**, otherwise provide modification feedback:\")\n \n with gr.Tabs():\n with gr.Tab(\"šŸ“– Preview (Markdown)\"):\n section_display_md = gr.Markdown(\n label=\"Section Preview\",\n value=\"\"\n )\n with gr.Tab(\"šŸ“‹ Raw Data (JSON)\"):\n section_display_json = gr.Code(\n label=\"Section JSON\",\n language=\"json\",\n value=\"\",\n lines=15\n )\n \n section_feedback_input = gr.TextArea(\n label=\"Your Feedback\",\n placeholder=\"Enter 'yes' to continue, or provide modification feedback...\",\n lines=3\n )\n section_submit_btn = gr.Button(\"Submit Feedback\", variant=\"primary\")\n \n # Full Content Feedback Area\n with gr.Group(visible=False) as feedback_full_content:\n gr.Markdown(\"### šŸ“„ Full Content Generation Results\")\n gr.Markdown(\"Please review the generated full content. If satisfied, enter **'yes'**, otherwise provide modification feedback:\")\n \n with gr.Tabs():\n with gr.Tab(\"šŸ“– Preview (Markdown)\"):\n full_content_display_md = gr.Markdown(\n label=\"Full Content Preview\",\n value=\"\"\n )\n with gr.Tab(\"šŸ“‹ Raw Data (JSON)\"):\n full_content_display_json = gr.Code(\n label=\"Full Content JSON\",\n language=\"json\",\n value=\"\",\n lines=15\n )\n \n full_content_feedback_input = gr.TextArea(\n label=\"Your Feedback\",\n placeholder=\"Enter 'yes' to continue, or provide modification feedback...\",\n lines=3\n )\n full_content_submit_btn = gr.Button(\"Submit Feedback\", variant=\"primary\")\n \n # HTML Feedback Area\n with gr.Group(visible=False) as feedback_html:\n gr.Markdown(\"### 🌐 HTML Generation Results\")\n \n # Preview Info Display\n preview_info_display = gr.Markdown(\n value=\"\",\n label=\"Preview Information\"\n )\n \n # Preview URL (hidden state for JS)\n preview_url_state = gr.Textbox(visible=False)\n \n # Open Preview in New Tab Button\n open_preview_btn = gr.Button(\n \"🌐 Open Preview in New Tab\",\n variant=\"secondary\",\n size=\"lg\",\n visible=False\n )\n \n gr.Markdown(\"---\")\n \n # Feedback Input Area\n html_feedback_input = gr.TextArea(\n label=\"Your Feedback\",\n placeholder=\"Enter 'yes' to finalize, or provide modification feedback...\",\n lines=3\n )\n html_submit_btn = gr.Button(\"Submit Feedback\", variant=\"primary\")\n \n # Final Output\n html_file_output = gr.File(\n label=\"šŸ“„ Download Project Archive\",\n interactive=False\n )\n \n # Bind Events\n start_btn.click(\n fn=start_generation,\n inputs=[\n pdf_input, model_name_t, model_name_v, template_root,\n template_dir, template_file, output_dir, style_preference,\n tmp_dir, full_content_check_times, background_color,\n has_navigation, has_hero_section, title_color, page_density,\n image_layout, html_check_times, resume, human_input,\n template_choice, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key\n ],\n outputs=[\n status_output,\n feedback_section,\n section_display_md,\n section_display_json,\n template_choice,\n template_preview_links,\n section_feedback_input\n ]\n )\n \n section_submit_btn.click(\n fn=submit_section_feedback,\n inputs=[section_feedback_input],\n outputs=[\n status_output,\n section_display_md,\n section_display_json,\n section_feedback_input,\n feedback_section,\n feedback_full_content,\n full_content_display_md,\n full_content_display_md,\n full_content_display_json,\n full_content_feedback_input\n ]\n )\n \n full_content_submit_btn.click(\n fn=submit_full_content_feedback,\n inputs=[full_content_feedback_input],\n outputs=[\n status_output,\n full_content_display_md,\n full_content_display_json,\n full_content_feedback_input,\n feedback_full_content,\n feedback_html,\n preview_info_display,\n preview_url_state,\n open_preview_btn\n ]\n )\n \n html_submit_btn.click(\n fn=submit_html_feedback,\n inputs=[html_feedback_input],\n outputs=[\n status_output,\n preview_info_display,\n html_feedback_input,\n feedback_html,\n open_preview_btn,\n html_file_output\n ]\n )\n \n # Open Preview Button - Use JavaScript to open in new tab\n open_preview_btn.click(\n fn=None,\n inputs=[preview_url_state],\n outputs=None,\n js=\"(url) => window.open(url, '_blank')\"\n )\n\n# Launch Application\nif __name__ == \"__main__\":\n demo.launch(\n server_name=\"0.0.0.0\",\n server_port=7860,\n share=False,\n show_error=True\n )"}, "ecd0ca309215d137e33bd278abaa8d73d250957b": {"t": 1785846841.2051988, "n": 63193, "h": "af0414489db141ed", "c": "import gradio as gr\nimport os\nimport json\nfrom pathlib import Path\nimport base64\nimport re\nfrom threading import Thread\nfrom http.server import HTTPServer, SimpleHTTPRequestHandler\nimport socket\nfrom dotenv import load_dotenv\nfrom ProjectPageAgent.parse_paper import parse_paper_for_project_page, save_parsed_content\nfrom ProjectPageAgent.html_finder import HtmlFinder\nfrom ProjectPageAgent.content_planner import ProjectPageContentPlanner\nfrom ProjectPageAgent.html_generator import ProjectPageHTMLGenerator, to_url\nfrom utils.wei_utils import get_agent_config\nimport os\nimport subprocess\n\nfrom ProjectPageAgent.content_planner import filter_references\nfrom utils.src.utils import run_sync_screenshots\nfrom ProjectPageAgent.main_pipline import matching, copy_static_files\n\nload_dotenv()\n\n\n\ndef get_agent_config_with_keys(model_type, openai_api_key=\"\", gemini_api_key=\"\", \n qwen_api_key=\"\", zhipuai_api_key=\"\", openrouter_api_key=\"\"):\n \"\"\"\n Get agent configuration with user-provided API keys.\n Falls back to environment variables if user keys are not provided.\n Note: This function sets environment variables but does NOT restore them.\n The environment variables will remain set for the duration of the application.\n \"\"\"\n # Set environment variables with user-provided keys\n api_keys = {\n 'OPENAI_API_KEY': openai_api_key,\n 'GEMINI_API_KEY': gemini_api_key, \n 'QWEN_API_KEY': qwen_api_key,\n 'ZHIPUAI_API_KEY': zhipuai_api_key,\n 'OPENROUTER_API_KEY': openrouter_api_key\n }\n \n # Set new API keys in environment\n for key, value in api_keys.items():\n if value and value.strip():\n os.environ[key] = value\n \n # Get agent config with the new API keys\n config = get_agent_config(model_type)\n return config\n\ndef validate_api_keys(model_name_t, model_name_v, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key):\n \"\"\"\n Validate that required API keys are provided for the selected models.\n \"\"\"\n errors = []\n \n # Check text model requirements\n if model_name_t in ['4o', '4o-mini', 'gpt-4.1', 'gpt-4.1-mini', 'o1', 'o3', 'o3-mini']:\n if not openai_api_key or not openai_api_key.strip():\n errors.append(\"OpenAI API key is required for GPT models\")\n elif model_name_t in ['gemini', 'gemini-2.5-pro', 'gemini-2.5-flash']:\n if not gemini_api_key or not gemini_api_key.strip():\n errors.append(\"Gemini API key is required for Gemini models\")\n elif model_name_t in ['qwen', 'qwen-plus', 'qwen-max', 'qwen-long']:\n if not qwen_api_key or not qwen_api_key.strip():\n errors.append(\"Qwen API key is required for Qwen models\")\n elif model_name_t.startswith('openrouter_'):\n if not openrouter_api_key or not openrouter_api_key.strip():\n errors.append(\"OpenRouter API key is required for OpenRouter models\")\n \n # Check vision model requirements\n if model_name_v in ['4o', '4o-mini']:\n if not openai_api_key or not openai_api_key.strip():\n errors.append(\"OpenAI API key is required for GPT vision models\")\n elif model_name_v in ['gemini', 'gemini-2.5-pro', 'gemini-2.5-flash']:\n if not gemini_api_key or not gemini_api_key.strip():\n errors.append(\"Gemini API key is required for Gemini vision models\")\n elif model_name_v in ['qwen-vl-max', 'qwen-2.5-vl-72b']:\n if not qwen_api_key or not qwen_api_key.strip():\n errors.append(\"Qwen API key is required for Qwen vision models\")\n elif model_name_v.startswith('openrouter_'):\n if not openrouter_api_key or not openrouter_api_key.strip():\n errors.append(\"OpenRouter API key is required for OpenRouter vision models\")\n \n return errors\n\n# Global Variables\ncurrent_html_dir = None\npreview_server = None\npreview_port = None\ntemplate_preview_servers = []\n\nclass CustomHTTPRequestHandler(SimpleHTTPRequestHandler):\n def __init__(self, *args, **kwargs):\n super().__init__(*args, directory=current_html_dir, **kwargs)\n \n def log_message(self, format, *args):\n pass\n\ndef find_free_port(start_port=8000, max_attempts=100):\n for port in range(start_port, start_port + max_attempts):\n try:\n with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:\n s.bind(('', port))\n return port\n except OSError:\n continue\n raise RuntimeError(f\"Could not find available port\")\n\ndef start_preview_server(html_dir):\n global current_html_dir, preview_server, preview_port\n stop_preview_server()\n current_html_dir = html_dir\n preview_port = find_free_port()\n preview_server = HTTPServer(('0.0.0.0', preview_port), CustomHTTPRequestHandler)\n server_thread = Thread(target=preview_server.serve_forever, daemon=True)\n server_thread.start()\n return preview_port\n\ndef stop_preview_server():\n global preview_server, preview_port\n if preview_server:\n preview_server.shutdown()\n preview_server = None\n preview_port = None\n\ndef start_ephemeral_server_for_dir(html_dir):\n port = find_free_port()\n class _TempHandler(SimpleHTTPRequestHandler):\n def __init__(self, *args, **kwargs):\n super().__init__(*args, directory=html_dir, **kwargs)\n def log_message(self, format, *args):\n pass\n srv = HTTPServer(('0.0.0.0', port), _TempHandler)\n t = Thread(target=srv.serve_forever, daemon=True)\n t.start()\n template_preview_servers.append((srv, port))\n return port\n\ndef stop_all_template_preview_servers():\n global template_preview_servers\n for srv, _ in template_preview_servers:\n try:\n srv.shutdown()\n except Exception:\n pass\n template_preview_servers = []\n\nclass GenerationArgs:\n def __init__(self, paper_path, model_name_t, model_name_v, template_root, \n template_dir, template_file, output_dir, style_preference, tmp_dir,\n full_content_check_times, background_color, has_navigation, \n has_hero_section, title_color, page_density, image_layout, \n html_check_times, resume, human_input):\n self.paper_path = paper_path\n self.model_name_t = model_name_t\n self.model_name_v = model_name_v\n self.template_root = template_root\n self.template_dir = template_dir\n self.template_file = template_file\n self.output_dir = output_dir\n self.style_preference = style_preference\n self.tmp_dir = tmp_dir\n self.full_content_check_times = full_content_check_times\n self.background_color = background_color\n self.has_navigation = has_navigation\n self.has_hero_section = has_hero_section\n self.title_color = title_color\n self.page_density = page_density\n self.image_layout = image_layout\n self.html_check_times = html_check_times\n self.resume = resume\n self.human_input = human_input\n self.paper_name = None\n\n# ==================== Formatting Functions ====================\n\ndef format_section_to_markdown(section_data):\n \"\"\"\n Convert Section JSON to beautifully formatted Markdown\n \n Args:\n section_data: Section JSON data\n \n Returns:\n str: Formatted Markdown string\n \"\"\"\n if not section_data:\n return \"No data available\"\n \n md_lines = []\n \n # Title\n md_lines.append(\"# šŸ“„ Paper Page Structure Preview\\n\")\n \n # Basic Information\n if \"title\" in section_data:\n md_lines.append(f\"## šŸ“Œ Title\\n**{section_data['title']}**\\n\")\n \n if \"authors\" in section_data:\n md_lines.append(f\"## šŸ‘„ Authors\\n{section_data['authors']}\\n\")\n \n if \"affiliation\" in section_data:\n md_lines.append(f\"## šŸ›ļø Affiliation\\n{section_data['affiliation']}\\n\")\n \n # Other Sections\n md_lines.append(\"## šŸ“‘ Page Sections\\n\")\n \n section_count = 0\n for key, value in section_data.items():\n if key in [\"title\", \"authors\", \"affiliation\"]:\n continue\n \n section_count += 1\n \n # Section Title\n section_title = key.replace(\"_\", \" \").title()\n md_lines.append(f\"### {section_count}. {section_title}\\n\")\n \n # Section Content\n if isinstance(value, dict):\n # If dictionary, process recursively\n for sub_key, sub_value in value.items():\n sub_title = sub_key.replace(\"_\", \" \").title()\n md_lines.append(f\"**{sub_title}**: {sub_value}\\n\")\n elif isinstance(value, list):\n # If list\n for item in value:\n if isinstance(item, str):\n md_lines.append(f\"- {item}\\n\")\n elif isinstance(item, dict):\n for k, v in item.items():\n md_lines.append(f\"- **{k}**: {v}\\n\")\n else:\n # Simple value\n md_lines.append(f\"{value}\\n\")\n \n md_lines.append(\"\") # Empty line\n \n # Add Statistics\n md_lines.append(\"---\\n\")\n md_lines.append(f\"**šŸ“Š Total {section_count} sections**\\n\")\n \n return \"\\n\".join(md_lines)\n\n\ndef format_full_content_to_markdown(content_data, figures=None):\n \"\"\"\n Convert Full Content JSON to beautifully formatted Markdown\n \n Args:\n content_data: Full Content JSON data\n figures: Images and tables data (optional)\n \n Returns:\n str: Formatted Markdown string\n \"\"\"\n if not content_data:\n return \"No data available\"\n \n md_lines = []\n \n # Title\n md_lines.append(\"# šŸ“„ Full Content Preview\\n\")\n \n # Basic Information\n if \"title\" in content_data:\n md_lines.append(f\"# {content_data['title']}\\n\")\n \n if \"authors\" in content_data:\n md_lines.append(f\"**Authors**: {content_data['authors']}\\n\")\n \n if \"affiliation\" in content_data:\n md_lines.append(f\"**Affiliation**: {content_data['affiliation']}\\n\")\n \n md_lines.append(\"---\\n\")\n \n # Process Each Section\n section_count = 0\n image_count = 0\n table_count = 0\n \n for key, value in content_data.items():\n if key in [\"title\", \"authors\", \"affiliation\"]:\n continue\n \n section_count += 1\n \n # Section Title\n section_title = key.replace(\"_\", \" \").title()\n md_lines.append(f\"## {section_count}. {section_title}\\n\")\n \n # Process Content\n if isinstance(value, dict):\n # Process dictionary type content\n for sub_key, sub_value in value.items():\n if sub_key.lower() in ['content', 'description', 'text']:\n # Main text content\n md_lines.append(f\"{sub_value}\\n\")\n elif sub_key.lower() in ['image', 'figure', 'img']:\n # Image\n image_count += 1\n if isinstance(sub_value, dict):\n caption = sub_value.get('caption', f'Figure {image_count}')\n path = sub_value.get('path', '')\n md_lines.append(f\"\\n**šŸ–¼ļø {caption}**\\n\")\n if path:\n md_lines.append(f\"*Image path: `{path}`*\\n\")\n else:\n md_lines.append(f\"\\n**šŸ–¼ļø Figure {image_count}**: {sub_value}\\n\")\n elif sub_key.lower() in ['table']:\n # Table\n table_count += 1\n md_lines.append(f\"\\n**šŸ“Š Table {table_count}**\\n\")\n if isinstance(sub_value, dict):\n caption = sub_value.get('caption', f'Table {table_count}')\n md_lines.append(f\"*{caption}*\\n\")\n else:\n md_lines.append(f\"{sub_value}\\n\")\n elif sub_key.lower() in ['code']:\n # Code block\n md_lines.append(f\"\\n```\\n{sub_value}\\n```\\n\")\n else:\n # Other subtitles\n sub_title = sub_key.replace(\"_\", \" \").title()\n md_lines.append(f\"\\n### {sub_title}\\n\")\n md_lines.append(f\"{sub_value}\\n\")\n \n elif isinstance(value, list):\n # Process list type content\n for idx, item in enumerate(value):\n if isinstance(item, dict):\n # Dictionary items in list\n if 'title' in item or 'name' in item:\n item_title = item.get('title', item.get('name', f'Item {idx+1}'))\n md_lines.append(f\"\\n### {item_title}\\n\")\n \n for k, v in item.items():\n if k not in ['title', 'name']:\n if k.lower() in ['content', 'description', 'text']:\n md_lines.append(f\"{v}\\n\")\n elif k.lower() in ['image', 'figure']:\n image_count += 1\n md_lines.append(f\"\\n**šŸ–¼ļø Figure {image_count}**: {v}\\n\")\n elif k.lower() == 'table':\n table_count += 1\n md_lines.append(f\"\\n**šŸ“Š Table {table_count}**: {v}\\n\")\n else:\n k_title = k.replace(\"_\", \" \").title()\n md_lines.append(f\"**{k_title}**: {v}\\n\")\n else:\n # Simple list item\n md_lines.append(f\"- {item}\\n\")\n \n else:\n # Simple text value\n md_lines.append(f\"{value}\\n\")\n \n md_lines.append(\"\") # Empty line between sections\n \n # Add Statistics\n md_lines.append(\"\\n---\\n\")\n stats = []\n stats.append(f\"šŸ“Š **Statistics**\")\n stats.append(f\"- Sections: {section_count}\")\n if image_count > 0:\n stats.append(f\"- Images: {image_count}\")\n if table_count > 0:\n stats.append(f\"- Tables: {table_count}\")\n \n # If figures data is provided, add more information\n if figures:\n if 'images' in figures and figures['images']:\n stats.append(f\"- Available images: {len(figures['images'])}\")\n if 'tables' in figures and figures['tables']:\n stats.append(f\"- Available tables: {len(figures['tables'])}\")\n \n md_lines.append(\"\\n\".join(stats))\n md_lines.append(\"\\n\")\n \n return \"\\n\".join(md_lines)\n\n# ==================== Global State Management ====================\n\nclass GenerationState:\n def __init__(self):\n self.reset()\n \n def reset(self):\n self.args = None\n self.paper_content = None\n self.figures = None\n self.generated_section = None\n self.text_page_content = None\n self.generated_content = None\n self.html_content = None\n self.html_file_path = None\n self.html_dir = None\n self.planner = None\n self.html_generator = None\n self.agent_config_t = None\n self.total_input_tokens_t = 0\n self.total_output_tokens_t = 0\n self.current_stage = \"init\"\n self.preview_url = None\n\nstate = GenerationState()\n\ndef create_project_zip(project_dir, output_dir, paper_name):\n \"\"\"\n Create project archive\n \n Args:\n project_dir: Project directory path\n output_dir: Output directory\n paper_name: Paper name\n \n Returns:\n str: Archive path, None if failed\n \"\"\"\n import zipfile\n \n zip_filename = f\"{paper_name}_project_page.zip\"\n zip_path = os.path.join(output_dir, zip_filename)\n \n print(f\"Creating project archive: {zip_path}\")\n \n try:\n with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:\n # Traverse project directory, add all files\n for root, dirs, files in os.walk(project_dir):\n for file in files:\n file_path = os.path.join(root, file)\n # Calculate relative path\n arcname = os.path.relpath(file_path, output_dir)\n zipf.write(file_path, arcname)\n \n print(f\"Archive created successfully: {zip_path}\")\n \n # Get archive size\n zip_size = os.path.getsize(zip_path)\n zip_size_mb = zip_size / (1024 * 1024)\n print(f\"Archive size: {zip_size_mb:.2f} MB\")\n \n return zip_path\n \n except Exception as e:\n print(f\"Archive creation failed: {e}\")\n return None\n\ndef start_generation(pdf_file, model_name_t, model_name_v, template_root, \n template_dir, template_file, output_dir, style_preference, \n tmp_dir, full_content_check_times, background_color, \n has_navigation, has_hero_section, title_color, page_density, \n image_layout, html_check_times, resume, human_input, \n template_choice_value, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key):\n \"\"\"Start generation process\"\"\"\n if pdf_file is None:\n return \"āŒ Please upload a PDF file\", gr.update(visible=False), \"\", \"\", gr.update(), gr.update(), \"\"\n \n # Validate API keys\n validation_errors = validate_api_keys(\n model_name_t, model_name_v, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key\n )\n \n if validation_errors:\n error_msg = \"āŒ API Key Validation Failed:\\n\" + \"\\n\".join(f\"• {error}\" for error in validation_errors)\n return error_msg, gr.update(visible=False), \"\", \"\", gr.update(), gr.update(), \"\"\n \n state.reset()\n \n # Handle template selection\n if not (template_dir and str(template_dir).strip()):\n if not template_choice_value:\n stop_all_template_preview_servers()\n template_requirement = {\n \"background_color\": background_color,\n \"has_hero_section\": has_hero_section,\n \"Page density\": page_density,\n \"image_layout\": image_layout,\n \"has_navigation\": has_navigation,\n \"title_color\": title_color\n }\n try:\n matched = matching(template_requirement)\n except Exception as e:\n return f\"āŒ Template recommendation failed: {e}\", gr.update(visible=False), \"\", \"\", gr.update(choices=[], value=None), gr.update(visible=False, value=\"\"), \"\"\n \n html_finder_ = HtmlFinder()\n with open('templates/template_link.json','r') as f:\n template_link = json.load(f)\n previews = []\n for name in matched:\n t_dir = os.path.join(template_root, name)\n try:\n html_path = html_finder_.find_html(t_dir)\n if not os.path.exists(html_path):\n continue\n html_dir = os.path.dirname(os.path.abspath(html_path))\n filename = os.path.basename(html_path)\n port = start_ephemeral_server_for_dir(html_dir)\n url = template_link[name]\n previews.append((name, html_path, url))\n except Exception:\n continue\n \n if not previews:\n return \"āŒ No previewable templates found\", gr.update(visible=False), \"\", \"\", gr.update(choices=[], value=None), gr.update(visible=False, value=\"\"), \"\"\n \n md_lines = [\"### šŸ” Please select a template to preview before clicking **Start Generation**\", \"\"]\n for name, _, url in previews:\n md_lines.append(f\"- **{name}** → [{url}]({url})\")\n md = \"\\n\".join(md_lines)\n \n return \"Recommended 3 templates, please select one to continue\", gr.update(visible=False), \"\", \"\", gr.update(choices=[n for n, _, _ in previews], value=None), gr.update(visible=True, value=md), \"\"\n \n template_dir = os.path.join(template_root, template_choice_value)\n \n # Create arguments object\n args = GenerationArgs(\n paper_path=pdf_file.name,\n model_name_t=model_name_t,\n model_name_v=model_name_v,\n template_root=template_root,\n template_dir=template_dir,\n template_file=template_file,\n output_dir=output_dir,\n style_preference=style_preference,\n tmp_dir=tmp_dir,\n full_content_check_times=full_content_check_times,\n background_color=background_color,\n has_navigation=has_navigation,\n has_hero_section=has_hero_section,\n title_color=title_color,\n page_density=page_density,\n image_layout=image_layout,\n html_check_times=html_check_times,\n resume=resume,\n human_input=human_input\n )\n \n if not args.template_dir:\n return \"āŒ Please select a template\", gr.update(visible=False), \"\", \"\", gr.update(), gr.update(), \"\"\n \n if not args.template_file:\n html_finder_ = HtmlFinder()\n args.template_file = html_finder_.find_html(args.template_dir)\n \n paper_name = args.paper_path.split('/')[-1].replace('.pdf', '') if '/' in args.paper_path else args.paper_path.replace('.pdf', '')\n args.paper_name = paper_name\n \n os.makedirs(args.tmp_dir, exist_ok=True)\n \n try:\n # Initialization\n agent_config_t = get_agent_config_with_keys(\n args.model_name_t, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key\n )\n state.agent_config_t = agent_config_t\n state.args = args\n \n # Step 1: Parse PDF\n print(\"=\"*50)\n print(\"STEP 1: Parsing Research Paper\")\n print(\"=\"*50)\n \n raw_content_path = f'project_contents/{args.paper_name}_raw_content.json'\n if not os.path.exists(raw_content_path):\n agent_config_v = get_agent_config_with_keys(\n args.model_name_v, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key\n )\n input_token, output_token, raw_result, images, tables = parse_paper_for_project_page(args, agent_config_t)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n raw_content_path, _ = save_parsed_content(args, raw_result, images, tables, input_token, output_token)\n \n with open(raw_content_path, 'r') as f:\n paper_content = json.load(f)\n \n images = paper_content.get('images', [])\n tables = paper_content.get('tables', [])\n figures = {'images': images, 'tables': tables}\n paper_content = paper_content.get('markdown_content', \"\")\n \n state.paper_content = paper_content\n state.figures = figures\n \n # Step 2: Filter content\n print(\"=\"*50)\n print(\"STEP 2: Filtering Content\")\n print(\"=\"*50)\n \n planner = ProjectPageContentPlanner(agent_config_t, args)\n state.planner = planner\n \n paper_content, figures, input_token, output_token = planner.filter_raw_content(paper_content, figures)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n state.paper_content = paper_content\n state.figures = figures\n \n # Step 3: Generate Section\n print(\"=\"*50)\n print(\"STEP 3: Generating Sections\")\n print(\"=\"*50)\n \n state.current_stage = \"section\"\n \n generated_section, input_token, output_token = generate_section_initial()\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n # Use Markdown formatting\n section_display_md = format_section_to_markdown(generated_section)\n section_display_json = json.dumps(generated_section, indent=2, ensure_ascii=False)\n \n return (\n f\"āœ… Section generation completed, please review and provide feedback\\n\\nTokens: {input_token} → {output_token}\",\n gr.update(visible=True), # feedback_section\n section_display_md, # Markdown format\n section_display_json, # JSON format (hidden)\n gr.update(),\n gr.update(visible=False, value=\"\"),\n \"\"\n )\n \n except Exception as e:\n import traceback\n error_msg = f\"āŒ Generation failed: {str(e)}\\n{traceback.format_exc()}\"\n return error_msg, gr.update(visible=False), \"\", \"\", gr.update(), gr.update(), \"\"\n\ndef create_dynamic_page_dict(sections):\n poster_dict = {\n \"title\": \"Title of the paper\",\n \"authors\": \"Authors of the paper\",\n \"affiliation\": \"Affiliation of the authors\",\n }\n poster_dict.update(sections)\n return poster_dict\ndef generate_section_initial():\n \"\"\"Generate initial Section\"\"\"\n import yaml\n from jinja2 import Environment, StrictUndefined\n from utils.wei_utils import account_token\n from utils.src.utils import get_json_from_response\n \n with open('utils/prompt_templates/page_templates/section_generation.yaml', 'r') as f:\n planner_config = yaml.safe_load(f)\n \n jinja_env = Environment(undefined=StrictUndefined)\n template = jinja_env.from_string(planner_config[\"template\"])\n \n jinja_args = {\n 'paper_content': state.paper_content,\n 'json_format_example': json.dumps(state.paper_content, indent=2)\n }\n \n prompt = template.render(**jinja_args)\n \n state.planner.planner_agent.reset()\n response = state.planner.planner_agent.step(prompt)\n input_token, output_token = account_token(response)\n generated_section = get_json_from_response(response.msgs[0].content)\n generated_section = create_dynamic_page_dict(generated_section)\n state.generated_section = generated_section\n \n generated_path = f'project_contents/{state.args.paper_name}_generated_section.json'\n with open(generated_path, 'w') as f:\n json.dump(generated_section, f, indent=4)\n \n return generated_section, input_token, output_token\n\ndef submit_section_feedback(feedback_text):\n \"\"\"Submit Section feedback\"\"\"\n if not feedback_text or feedback_text.strip().lower() == 'yes':\n # User satisfied, proceed to next stage\n result = proceed_to_text_content()\n status, fc_section_visible, fc_display_visible, fc_display_md, fc_display_json, fc_feedback_visible = result\n return (\n status,\n \"\", # section_display_md clear\n \"\", # section_display_json clear\n \"\", # section_feedback_input clear\n gr.update(visible=False), # feedback_section hide\n fc_section_visible, # feedback_full_content show\n fc_display_visible, # full_content_display_md show\n fc_display_md, # full_content_display_md content\n fc_display_json, # full_content_display_json content\n fc_feedback_visible # full_content_feedback_input show\n )\n \n # User provides feedback, modify Section\n from camel.messages import BaseMessage\n from utils.wei_utils import account_token\n from utils.src.utils import get_json_from_response\n \n message = BaseMessage.make_assistant_message(\n role_name='User',\n content=f'human feedback: {feedback_text}\\n\\nPlease make modifications based on this feedback. Output format as specified above.'\n )\n response = state.planner.planner_agent.step(message)\n input_token, output_token = account_token(response)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n generated_section = get_json_from_response(response.msgs[0].content)\n generated_section = create_dynamic_page_dict(generated_section)\n state.generated_section = generated_section\n \n generated_path = f'project_contents/{state.args.paper_name}_generated_section.json'\n with open(generated_path, 'w') as f:\n json.dump(generated_section, f, indent=4)\n \n # Use Markdown formatting\n section_display_md = format_section_to_markdown(generated_section)\n section_display_json = json.dumps(generated_section, indent=2, ensure_ascii=False)\n \n return (\n f\"āœ… Section updated, please continue reviewing\\n\\nTokens: {input_token} → {output_token}\",\n section_display_md, # Markdown format\n section_display_json, # JSON format\n \"\", # Clear input box\n gr.update(visible=True), # feedback_section keep visible\n gr.update(visible=False), # feedback_full_content keep hidden\n gr.update(visible=False), # full_content_display_md keep hidden\n \"\", # full_content_display_md content\n \"\", # full_content_display_json content\n gr.update(visible=False) # full_content_feedback_input keep hidden\n )\n\ndef proceed_to_text_content():\n \"\"\"Enter Text Content generation stage\"\"\"\n print(\"=\"*50)\n print(\"STEP 4: Generating Text Content\")\n print(\"=\"*50)\n \n text_page_content, input_token, output_token = state.planner.text_content_generation(\n state.paper_content, state.figures, state.generated_section\n )\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n state.text_page_content = text_page_content\n \n # Enter Full Content stage\n return proceed_to_full_content()\n\ndef proceed_to_full_content():\n \"\"\"Enter Full Content generation stage\"\"\"\n print(\"=\"*50)\n print(\"STEP 5: Generating Full Content\")\n print(\"=\"*50)\n \n state.current_stage = \"full_content\"\n \n generated_content, input_token, output_token = generate_full_content_initial()\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n # Use Markdown formatting\n content_display_md = format_full_content_to_markdown(generated_content, state.figures)\n content_display_json = json.dumps(generated_content, indent=2, ensure_ascii=False)\n \n return (\n f\"āœ… Full Content generation completed, please review and provide feedback\\n\\nTokens: {input_token} → {output_token}\",\n gr.update(visible=True), # feedback_full_content show\n gr.update(visible=True), # full_content_display_md show\n content_display_md, # Markdown format\n content_display_json, # JSON format\n gr.update(visible=True) # full_content_feedback_input show\n )\n\ndef generate_full_content_initial():\n \"\"\"Generate initial Full Content\"\"\"\n import yaml\n from jinja2 import Environment, StrictUndefined\n from utils.wei_utils import account_token\n from utils.src.utils import get_json_from_response\n \n with open('utils/prompt_templates/page_templates/full_content_generation.yaml', 'r') as f:\n planner_config = yaml.safe_load(f)\n \n jinja_env = Environment(undefined=StrictUndefined)\n template = jinja_env.from_string(planner_config[\"template\"])\n \n jinja_args = {\n 'paper_content': state.paper_content,\n 'figures': json.dumps(state.figures, indent=2),\n 'project_page_content': json.dumps(state.text_page_content, indent=2)\n }\n \n prompt = template.render(**jinja_args)\n \n state.planner.planner_agent.reset()\n response = state.planner.planner_agent.step(prompt)\n input_token, output_token = account_token(response)\n generated_content = get_json_from_response(response.msgs[0].content)\n \n state.generated_content = generated_content\n \n first_path = f'project_contents/{state.args.paper_name}_generated_full_content.v0.json'\n with open(first_path, 'w', encoding='utf-8') as f:\n json.dump(generated_content, f, ensure_ascii=False, indent=2)\n \n return generated_content, input_token, output_token\n\ndef submit_full_content_feedback(feedback_text):\n \"\"\"Submit Full Content feedback\"\"\"\n if not feedback_text or feedback_text.strip().lower() == 'yes':\n # User satisfied, proceed to HTML generation\n result = proceed_to_html_generation()\n status, html_feedback_visible, preview_info, preview_url, open_btn_visible = result\n return (\n status,\n \"\", # full_content_display_md clear\n \"\", # full_content_display_json clear\n \"\", # full_content_feedback_input clear\n gr.update(visible=False), # feedback_full_content hide\n html_feedback_visible, # feedback_html show\n preview_info, # preview_info_display\n preview_url, # preview_url_state\n open_btn_visible # open_preview_btn show\n )\n \n # User provides feedback\n from camel.messages import BaseMessage\n from utils.wei_utils import account_token\n from utils.src.utils import get_json_from_response\n \n message = BaseMessage.make_assistant_message(\n role_name='User',\n content=f'human feedback: {feedback_text}\\n\\nPlease make modifications based on this feedback. Output format as specified above.'\n )\n response = state.planner.planner_agent.step(message)\n input_token, output_token = account_token(response)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n generated_content = get_json_from_response(response.msgs[0].content)\n state.generated_content = generated_content\n \n final_path = f'project_contents/{state.args.paper_name}_generated_full_content.json'\n with open(final_path, 'w', encoding='utf-8') as f:\n json.dump(generated_content, f, ensure_ascii=False, indent=2)\n \n # Use Markdown formatting\n content_display_md = format_full_content_to_markdown(generated_content, state.figures)\n content_display_json = json.dumps(generated_content, indent=2, ensure_ascii=False)\n \n return (\n f\"āœ… Full Content updated, please continue reviewing\\n\\nTokens: {input_token} → {output_token}\",\n content_display_md, # Markdown format\n content_display_json, # JSON format\n \"\", # Clear input box\n gr.update(visible=True), # feedback_full_content keep visible\n gr.update(visible=False), # feedback_html keep hidden\n \"\", # preview_info_display\n \"\", # preview_url_state\n gr.update(visible=False) # open_preview_btn keep hidden\n )\n\ndef proceed_to_html_generation():\n \"\"\"Enter HTML generation stage\"\"\"\n print(\"=\"*50)\n print(\"STEP 6: Generating HTML\")\n print(\"=\"*50)\n \n state.current_stage = \"html\"\n \n # Copy static files\n static_dir = copy_static_files(\n state.args.template_file, \n state.args.template_dir, \n state.args.output_dir, \n state.args.paper_name\n )\n \n # Generate HTML\n html_relative_path = os.path.relpath(state.args.template_file, state.args.template_dir)\n html_dir = '/'.join(html_relative_path.strip().split('/')[:-1])\n state.html_dir = html_dir\n \n html_generator = ProjectPageHTMLGenerator(state.agent_config_t, state.args)\n state.html_generator = html_generator\n \n with open(state.args.template_file, 'r', encoding='utf-8') as file:\n html_template = file.read()\n \n # Create assets directory\n assets_dir = html_generator.create_assets_directory(state.args, html_dir, state.args.output_dir)\n \n # Generate HTML\n html_content, input_token, output_token = html_generator.generate_complete_html(\n state.args, state.generated_content, html_dir, html_template\n )\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n # Save HTML (before table modification)\n html_dir_path = os.path.join(state.args.output_dir, state.args.paper_name, html_dir)\n os.makedirs(html_dir_path, exist_ok=True)\n \n html_file_path_no_modify = os.path.join(html_dir_path, 'index_no_modify_table.html')\n with open(html_file_path_no_modify, 'w', encoding='utf-8') as file:\n file.write(html_content)\n \n # Generate screenshot (before table modification)\n screenshot_path_no_modify = os.path.join(html_dir_path, 'page_final_no_modify_table.png')\n run_sync_screenshots(to_url(html_file_path_no_modify), screenshot_path_no_modify)\n \n # Modify tables\n html_content, input_token, output_token = html_generator.modify_html_table(html_content, html_dir)\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n \n state.html_content = html_content\n \n # Save HTML (after table modification)\n html_file_path = os.path.join(html_dir_path, 'index.html')\n with open(html_file_path, 'w', encoding='utf-8') as file:\n file.write(html_content)\n \n state.html_file_path = html_file_path\n \n # Generate screenshot (after table modification)\n run_sync_screenshots(\n to_url(html_file_path), \n os.path.join(html_dir_path, 'page_final.png')\n )\n \n # Start preview server\n html_full_dir = os.path.dirname(os.path.abspath(html_file_path))\n port = start_preview_server(html_full_dir)\n preview_url = f\"http://localhost:{port}/index.html\"\n state.preview_url = preview_url\n \n # Create preview info display\n preview_info = f\"\"\"\n### 🌐 HTML Generation Completed\n\n**Preview URL**: {preview_url}\n\n**Instructions**:\n1. Click the **\"🌐 Open Preview in New Tab\"** button below to view the generated webpage\n2. Carefully review the page in the new tab\n3. If satisfied, enter **'yes'** in the feedback box and submit\n4. If modifications are needed, provide detailed feedback and submit\n\n**Token Usage**: {input_token} → {output_token}\n\"\"\"\n \n return (\n f\"āœ… HTML generation completed\\n\\nTokens: {input_token} → {output_token}\",\n gr.update(visible=True), # feedback_html show\n preview_info, # preview_info_display\n preview_url, # preview_url_state\n gr.update(visible=True) # open_preview_btn show\n )\n\ndef submit_html_feedback(feedback_text):\n \"\"\"Submit HTML feedback\"\"\"\n if not feedback_text or feedback_text.strip().lower() == 'yes':\n # User satisfied, complete generation\n result = finalize_generation()\n status, html_file = result\n return (\n status,\n \"\", # preview_info_display clear\n \"\", # html_feedback_input clear\n gr.update(visible=False), # feedback_html hide\n gr.update(visible=False), # open_preview_btn hide\n html_file # html_file_output\n )\n \n # User provides feedback\n html_content, input_token, output_token = state.html_generator.modify_html_from_human_feedback(\n state.html_content, feedback_text\n )\n state.total_input_tokens_t += input_token\n state.total_output_tokens_t += output_token\n state.html_content = html_content\n \n # Save updated HTML\n html_dir_path = os.path.dirname(state.html_file_path)\n \n # Save as temporary version (for possible feedback iteration)\n import time\n timestamp = int(time.time())\n html_file_feedback = os.path.join(html_dir_path, f'index_feedback_{timestamp}.html')\n with open(html_file_feedback, 'w', encoding='utf-8') as file:\n file.write(html_content)\n \n # Also update main file\n with open(state.html_file_path, 'w', encoding='utf-8') as file:\n file.write(html_content)\n \n # Regenerate screenshot\n screenshot_path = os.path.join(html_dir_path, 'page_final.png')\n try:\n run_sync_screenshots(to_url(state.html_file_path), screenshot_path)\n except Exception as e:\n print(f\"Screenshot generation failed: {e}\")\n \n # Update preview info\n preview_info = f\"\"\"\n### 🌐 HTML Updated\n\n**Preview URL**: {state.preview_url}\n\n**Instructions**:\n1. Click the **\"🌐 Open Preview in New Tab\"** button below to view the updated webpage\n2. **Refresh the browser** to see the latest version\n3. If satisfied, enter **'yes'** in the feedback box and submit\n4. If further modifications are needed, continue providing feedback\n\n**Token Usage**: {input_token} → {output_token}\n\"\"\"\n \n return (\n f\"āœ… HTML updated, please refresh the preview page\\n\\nTokens: {input_token} → {output_token}\",\n preview_info, # preview_info_display\n \"\", # Clear input box\n gr.update(visible=True), # feedback_html keep visible\n gr.update(visible=True), # open_preview_btn keep visible\n None # html_file_output no download yet\n )\n\ndef finalize_generation():\n \"\"\"Complete generation and save final results\"\"\"\n import time\n \n # Ensure final HTML is saved\n html_dir_path = os.path.dirname(state.html_file_path)\n \n # Save final version\n final_html_path = os.path.join(html_dir_path, 'index_final.html')\n with open(final_html_path, 'w', encoding='utf-8') as file:\n file.write(state.html_content)\n \n # Also update main file\n with open(state.html_file_path, 'w', encoding='utf-8') as file:\n file.write(state.html_content)\n \n # Save metadata\n metadata = state.html_generator.generate_metadata(state.generated_content, state.args)\n metadata_path = state.html_generator.save_metadata(metadata, state.args, state.args.output_dir)\n \n # Create README file\n readme_path = os.path.join(state.args.output_dir, state.args.paper_name, 'README.md')\n readme_content = f\"\"\"# {state.args.paper_name} - Project Page\n\n## šŸ“„ Project Information\n\n- **Paper Name**: {state.args.paper_name}\n- **Generation Time**: {time.strftime('%Y-%m-%d %H:%M:%S')}\n- **Text Model**: {state.args.model_name_t}\n- **Vision Model**: {state.args.model_name_v}\n\n## šŸš€ Usage\n\n1. Extract this archive to any directory\n2. Open `index.html` to view the project page\n3. All resources (CSS, images, etc.) are included\n\n## šŸ“ File Structure\n\n- `index.html` - Main page file\n- `index_final.html` - Final confirmed version\n- `assets/` - Image and table resources\n- `css/` or `styles/` - Style files\n- `js/` or `scripts/` - JavaScript files\n- `metadata.json` - Page metadata\n- `generation_log.json` - Generation log\n\n## šŸ’” Tips\n\n- Recommended browsers: Chrome, Firefox, Safari, Edge\n- For web deployment, simply upload the entire folder\n- Feel free to modify HTML and CSS for customization\n\n---\nGenerated by Paper2ProjectPage\n\"\"\"\n \n with open(readme_path, 'w', encoding='utf-8') as f:\n f.write(readme_content)\n \n # Save generation log\n log_data = {\n 'paper_name': state.args.paper_name,\n 'paper_path': state.args.paper_path,\n 'models': {\n 'text_model': state.args.model_name_t,\n 'vision_model': state.args.model_name_v\n },\n 'token_usage': {\n 'text_input_tokens': state.total_input_tokens_t,\n 'text_output_tokens': state.total_output_tokens_t\n },\n 'output_files': {\n 'html_file': state.html_file_path,\n 'final_html_file': final_html_path,\n 'metadata_file': metadata_path,\n 'readme_file': readme_path\n },\n 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S')\n }\n \n log_path = f\"{state.args.output_dir}/{state.args.paper_name}/generation_log.json\"\n with open(log_path, 'w') as f:\n json.dump(log_data, f, indent=4, ensure_ascii=False)\n \n # Create project archive\n project_dir = os.path.join(state.args.output_dir, state.args.paper_name)\n zip_path = create_project_zip(project_dir, state.args.output_dir, state.args.paper_name)\n \n if zip_path and os.path.exists(zip_path):\n # Get archive size\n zip_size = os.path.getsize(zip_path)\n zip_size_mb = zip_size / (1024 * 1024)\n zip_filename = os.path.basename(zip_path)\n \n success_msg = f\"\"\"\nāœ… Project page generation completed!\n\nšŸ“ Output directory: {state.args.output_dir}/{state.args.paper_name}\n🌐 HTML file: {state.html_file_path}\n🌐 Final version: {final_html_path}\nšŸ“‹ Metadata: {metadata_path}\nšŸ“– README: {readme_path}\nšŸ“Š Log file: {log_path}\nšŸ“¦ Archive: {zip_filename} ({zip_size_mb:.2f} MB)\nšŸ”¢ Total token usage: {state.total_input_tokens_t} → {state.total_output_tokens_t}\n\nšŸŽ‰ All feedback completed, page successfully generated!\nClick the button below to download the complete project archive (including HTML, CSS, images, README, and all resources).\n\"\"\"\n \n return (\n success_msg,\n zip_path # Return archive for download\n )\n \n else:\n error_msg = f\"\"\"\nāš ļø Project page generated, but archive creation failed!\n\nšŸ“ Output directory: {state.args.output_dir}/{state.args.paper_name}\n🌐 HTML file: {state.html_file_path}\nšŸ“‹ Metadata: {metadata_path}\n\nYou can manually retrieve all files from the output directory {project_dir}.\n\"\"\"\n return (\n error_msg,\n state.html_file_path # Return HTML file\n )\n\n# ==================== Gradio Interface ====================\n\n# Custom CSS for better English font rendering\ncustom_css = \"\"\"\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');\n\n* {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif !important;\n}\n\ncode, pre, .code {\n font-family: 'JetBrains Mono', 'Courier New', Consolas, Monaco, monospace !important;\n}\n\nh1, h2, h3, h4, h5, h6 {\n font-weight: 600 !important;\n letter-spacing: -0.02em !important;\n}\n\n.markdown-text {\n line-height: 1.7 !important;\n font-size: 15px !important;\n}\n\n.gr-button {\n font-weight: 500 !important;\n letter-spacing: 0.01em !important;\n}\n\n.gr-input, .gr-textarea {\n font-size: 14px !important;\n line-height: 1.6 !important;\n}\n\n.gr-box {\n border-radius: 8px !important;\n}\n\n/* Better spacing for English content */\n.gr-markdown p {\n margin-bottom: 0.8em !important;\n}\n\n.gr-markdown ul, .gr-markdown ol {\n margin-left: 1.2em !important;\n}\n\n.gr-markdown li {\n margin-bottom: 0.4em !important;\n}\n\"\"\"\n\nwith gr.Blocks(title=\"Paper2ProjectPage Generator\", theme=gr.themes.Soft(), css=custom_css) as demo:\n \n gr.Markdown(\"\"\"\n # šŸ“„ AutoPage Generator with Interactive Feedback\n \n Upload your research paper PDF and generate beautiful project pages through multi-round interactive feedback\n \"\"\")\n \n with gr.Row():\n with gr.Column(scale=1):\n # PDF Upload\n pdf_input = gr.File(\n label=\"šŸ“Ž Upload PDF Paper\",\n file_types=[\".pdf\"],\n type=\"filepath\"\n )\n \n gr.Markdown(\"### šŸ”‘ API Keys Configuration\")\n gr.Markdown(\"\"\"\n **āš ļø Security Notice**: Your API keys are only stored in memory during the session and are never saved to disk.\n \n **šŸ’” Note**: You only need to fill in ONE API key corresponding to the models you selected below.\n \n **šŸ“‹ How to get API keys:**\n - **OpenAI**: Get your API key from [OpenAI Platform](https://platform.openai.com/api-keys)\n - **Gemini**: Get your API key from [Google AI Studio](https://aistudio.google.com/app/apikey)\n - **Qwen**: Get your API key from [DashScope](https://dashscope.console.aliyun.com/apiKey)\n - **ZhipuAI**: Get your API key from [ZhipuAI Console](https://open.bigmodel.cn/usercenter/apikeys)\n - **OpenRouter**: Get your API key from [OpenRouter](https://openrouter.ai/keys)\n \n **šŸš€ For HuggingFace Spaces**: You can also set these as environment variables in your Space settings.\n \"\"\")\n \n with gr.Row():\n openai_api_key = gr.Textbox(\n label=\"OpenAI API Key\",\n value=os.getenv(\"OPENAI_API_KEY\", \"\"),\n type=\"password\",\n placeholder=\"sk-...\",\n info=\"Required for GPT models\"\n )\n gemini_api_key = gr.Textbox(\n label=\"Gemini API Key\", \n value=os.getenv(\"GEMINI_API_KEY\", \"\"),\n type=\"password\",\n placeholder=\"AI...\",\n info=\"Required for Gemini models\"\n )\n \n with gr.Row():\n qwen_api_key = gr.Textbox(\n label=\"Qwen API Key\",\n value=os.getenv(\"QWEN_API_KEY\", \"\"),\n type=\"password\", \n placeholder=\"sk-...\",\n info=\"Required for Qwen models\"\n )\n zhipuai_api_key = gr.Textbox(\n label=\"ZhipuAI API Key\",\n value=os.getenv(\"ZHIPUAI_API_KEY\", \"\"),\n type=\"password\",\n placeholder=\"...\",\n info=\"Required for GLM models\"\n )\n \n openrouter_api_key = gr.Textbox(\n label=\"OpenRouter API Key\",\n value=os.getenv(\"OPENROUTER_API_KEY\", \"\"),\n type=\"password\",\n placeholder=\"sk-or-...\",\n info=\"Required for OpenRouter models\"\n )\n \n gr.Markdown(\"### šŸ¤– Model Configuration\")\n \n # Text Model Options\n text_model_options = [\n (\"GPT-4o\", \"4o\"),\n (\"GPT-4o Mini\", \"4o-mini\"),\n (\"GPT-4.1\", \"gpt-4.1\"),\n (\"GPT-4.1 Mini\", \"gpt-4.1-mini\"),\n (\"O1\", \"o1\"),\n (\"O3\", \"o3\"),\n (\"O3 Mini\", \"o3-mini\"),\n (\"Gemini 2.5 Pro\", \"gemini\"),\n (\"Gemini 2.5 Pro (Alt)\", \"gemini-2.5-pro\"),\n (\"Gemini 2.5 Flash\", \"gemini-2.5-flash\"),\n (\"Qwen\", \"qwen\"),\n (\"Qwen Plus\", \"qwen-plus\"),\n (\"Qwen Max\", \"qwen-max\"),\n (\"Qwen Long\", \"qwen-long\"),\n (\"OpenRouter Qwen Plus\", \"openrouter_qwen-plus\"),\n (\"OpenRouter GPT-4o Mini\", \"openrouter_gpt-4o-mini\"),\n (\"OpenRouter Gemini 2.5 Flash\", \"openrouter_gemini-2.5-flash\"),\n (\"OpenRouter O3\", \"openrouter_openai/o3\"),\n (\"OpenRouter Claude Sonnet 4.5\", \"openrouter_claude-sonnet-4.5\"),\n ]\n \n # Vision Model Options\n vision_model_options = [\n (\"GPT-4o\", \"4o\"),\n (\"GPT-4o Mini\", \"4o-mini\"),\n (\"Gemini 2.5 Pro\", \"gemini\"),\n (\"Gemini 2.5 Pro (Alt)\", \"gemini-2.5-pro\"),\n (\"Gemini 2.5 Flash\", \"gemini-2.5-flash\"),\n (\"Qwen VL Max\", \"qwen-vl-max\"),\n (\"Qwen 2.5 VL 72B\", \"qwen-2.5-vl-72b\"),\n (\"OpenRouter Qwen VL 72B\", \"openrouter_qwen_vl_72b\"),\n (\"OpenRouter Qwen VL 7B\", \"openrouter_qwen_vl_7b\"),\n (\"OpenRouter Qwen VL Max\", \"openrouter_qwen-vl-max\"),\n (\"OpenRouter Gemini 2.5 Flash\", \"openrouter_gemini-2.5-flash\"),\n ]\n \n with gr.Row():\n model_name_t = gr.Dropdown(\n label=\"Text Model\",\n choices=text_model_options,\n value=\"gemini\",\n info=\"Select model for text processing\"\n )\n model_name_v = gr.Dropdown(\n label=\"Vision Model\", \n choices=vision_model_options,\n value=\"gemini\",\n info=\"Select model for vision processing\"\n )\n \n # Hidden backend configuration fields\n template_root = gr.Textbox(\n label=\"Template Root\",\n value=\"templates\",\n visible=False\n )\n template_dir = gr.Textbox(\n label=\"Template Directory\",\n value=\"\",\n visible=False\n )\n template_file = gr.Textbox(\n label=\"Template File\",\n value=\"\",\n visible=False\n )\n output_dir = gr.Textbox(\n label=\"Output Directory\",\n value=\"generated_project_pages\",\n visible=False\n )\n style_preference = gr.Textbox(\n label=\"Style Preference JSON\",\n value=\"\",\n visible=False\n )\n tmp_dir = gr.Textbox(\n label=\"Temporary Directory\",\n value=\"tmp\",\n visible=False\n )\n \n # Hidden parameters with default values\n resume = gr.Radio(\n label=\"Resume From Step\",\n choices=['parse_pdf', 'generate_content','full_content_check', 'generate_html', 'html_check','modify_table','html_feedback'],\n value='parse_pdf',\n visible=False\n )\n \n human_input = gr.Radio(\n label=\"Enable Human Feedback\",\n choices=[0, 1],\n value=1,\n visible=False\n )\n \n full_content_check_times = gr.Number(\n label=\"Full Content Check Times\",\n value=1,\n precision=0,\n visible=False\n )\n \n html_check_times = gr.Number(\n label=\"HTML Check Times\",\n value=1,\n precision=0,\n visible=False\n )\n \n with gr.Column(scale=1):\n gr.Markdown(\"\"\"\n ### šŸ’” User Guide\n \n 1. **Upload PDF**: Select your research paper PDF file\n 2. **Configure API Key**: Fill in ONE API key for your selected models\n 3. **Select Models**: Choose text and vision models from dropdowns\n 4. **Configure Style**: Adjust style preferences below\n 5. **Start Generation**: Click the \"Start Generation\" button\n 6. **Three-Stage Feedback**:\n - šŸ“ **Section Feedback**: Review the generated page structure (Markdown preview + JSON data)\n - šŸ“„ **Full Content Feedback**: Review the generated complete content (Markdown preview + JSON data)\n - 🌐 **HTML Feedback**: View the generated webpage in a new tab\n 7. **Download Results**: Download the complete project archive after completion\n \n āš ļø **Tips**: \n - Each stage supports multiple rounds of feedback until you're satisfied\n - Enter 'yes' to proceed to the next stage\n - The final ZIP download includes the complete project folder with all resources\n \"\"\")\n \n gr.Markdown(\"### šŸŽØ Style Configuration\")\n \n with gr.Row():\n with gr.Column():\n background_color = gr.Radio(\n label=\"Background Color\",\n choices=[\"light\", \"dark\"],\n value=\"light\",\n info=\"Background color theme\"\n )\n \n has_navigation = gr.Radio(\n label=\"Has Navigation\",\n choices=[\"yes\", \"no\"],\n value=\"yes\",\n info=\"Include navigation bar\"\n )\n \n has_hero_section = gr.Radio(\n label=\"Has Hero Section\",\n choices=[\"yes\", \"no\"],\n value=\"yes\",\n info=\"Include hero/header section\"\n )\n \n with gr.Column():\n title_color = gr.Radio(\n label=\"Title Color\",\n choices=[\"pure\", \"colorful\"],\n value=\"pure\",\n info=\"Title color style\"\n )\n \n page_density = gr.Radio(\n label=\"Page Density\",\n choices=[\"spacious\", \"compact\"],\n value=\"spacious\",\n info=\"Page spacing density\"\n )\n \n image_layout = gr.Radio(\n label=\"Image Layout\",\n choices=[\"rotation\", \"parallelism\"],\n value=\"parallelism\",\n info=\"Image layout style\"\n )\n \n gr.Markdown(\"### šŸ“ Template Selection\")\n \n template_choice = gr.Radio(\n label=\"Recommended Templates\",\n choices=[],\n value=None,\n info=\"Select from recommended templates\"\n )\n \n template_preview_links = gr.Markdown(\n value=\"\",\n visible=False\n )\n \n # Start Generation Button\n start_btn = gr.Button(\"šŸš€ Start Generation\", variant=\"primary\", size=\"lg\")\n \n # Status Output\n status_output = gr.Textbox(\n label=\"šŸ“Š Generation Status\",\n lines=5,\n interactive=False\n )\n \n # Section Feedback Area\n with gr.Group(visible=False) as feedback_section:\n gr.Markdown(\"### šŸ“ Section Generation Results\")\n gr.Markdown(\"Please review the generated section structure. If satisfied, enter **'yes'**, otherwise provide modification feedback:\")\n \n with gr.Tabs():\n with gr.Tab(\"šŸ“– Preview (Markdown)\"):\n section_display_md = gr.Markdown(\n label=\"Section Preview\",\n value=\"\"\n )\n with gr.Tab(\"šŸ“‹ Raw Data (JSON)\"):\n section_display_json = gr.Code(\n label=\"Section JSON\",\n language=\"json\",\n value=\"\",\n lines=15\n )\n \n section_feedback_input = gr.TextArea(\n label=\"Your Feedback\",\n placeholder=\"Enter 'yes' to continue, or provide modification feedback...\",\n lines=3\n )\n section_submit_btn = gr.Button(\"Submit Feedback\", variant=\"primary\")\n \n # Full Content Feedback Area\n with gr.Group(visible=False) as feedback_full_content:\n gr.Markdown(\"### šŸ“„ Full Content Generation Results\")\n gr.Markdown(\"Please review the generated full content. If satisfied, enter **'yes'**, otherwise provide modification feedback:\")\n \n with gr.Tabs():\n with gr.Tab(\"šŸ“– Preview (Markdown)\"):\n full_content_display_md = gr.Markdown(\n label=\"Full Content Preview\",\n value=\"\"\n )\n with gr.Tab(\"šŸ“‹ Raw Data (JSON)\"):\n full_content_display_json = gr.Code(\n label=\"Full Content JSON\",\n language=\"json\",\n value=\"\",\n lines=15\n )\n \n full_content_feedback_input = gr.TextArea(\n label=\"Your Feedback\",\n placeholder=\"Enter 'yes' to continue, or provide modification feedback...\",\n lines=3\n )\n full_content_submit_btn = gr.Button(\"Submit Feedback\", variant=\"primary\")\n \n # HTML Feedback Area\n with gr.Group(visible=False) as feedback_html:\n gr.Markdown(\"### 🌐 HTML Generation Results\")\n \n # Preview Info Display\n preview_info_display = gr.Markdown(\n value=\"\",\n label=\"Preview Information\"\n )\n \n # Preview URL (hidden state for JS)\n preview_url_state = gr.Textbox(visible=False)\n \n # Open Preview in New Tab Button\n open_preview_btn = gr.Button(\n \"🌐 Open Preview in New Tab\",\n variant=\"secondary\",\n size=\"lg\",\n visible=False\n )\n \n gr.Markdown(\"---\")\n \n # Feedback Input Area\n html_feedback_input = gr.TextArea(\n label=\"Your Feedback\",\n placeholder=\"Enter 'yes' to finalize, or provide modification feedback...\",\n lines=3\n )\n html_submit_btn = gr.Button(\"Submit Feedback\", variant=\"primary\")\n \n # Final Output\n html_file_output = gr.File(\n label=\"šŸ“„ Download Project Archive\",\n interactive=False\n )\n \n # Bind Events\n start_btn.click(\n fn=start_generation,\n inputs=[\n pdf_input, model_name_t, model_name_v, template_root,\n template_dir, template_file, output_dir, style_preference,\n tmp_dir, full_content_check_times, background_color,\n has_navigation, has_hero_section, title_color, page_density,\n image_layout, html_check_times, resume, human_input,\n template_choice, openai_api_key, gemini_api_key, \n qwen_api_key, zhipuai_api_key, openrouter_api_key\n ],\n outputs=[\n status_output,\n feedback_section,\n section_display_md,\n section_display_json,\n template_choice,\n template_preview_links,\n section_feedback_input\n ]\n )\n \n section_submit_btn.click(\n fn=submit_section_feedback,\n inputs=[section_feedback_input],\n outputs=[\n status_output,\n section_display_md,\n section_display_json,\n section_feedback_input,\n feedback_section,\n feedback_full_content,\n full_content_display_md,\n full_content_display_md,\n full_content_display_json,\n full_content_feedback_input\n ]\n )\n \n full_content_submit_btn.click(\n fn=submit_full_content_feedback,\n inputs=[full_content_feedback_input],\n outputs=[\n status_output,\n full_content_display_md,\n full_content_display_json,\n full_content_feedback_input,\n feedback_full_content,\n feedback_html,\n preview_info_display,\n preview_url_state,\n open_preview_btn\n ]\n )\n \n html_submit_btn.click(\n fn=submit_html_feedback,\n inputs=[html_feedback_input],\n outputs=[\n status_output,\n preview_info_display,\n html_feedback_input,\n feedback_html,\n open_preview_btn,\n html_file_output\n ]\n )\n \n # Open Preview Button - Use JavaScript to open in new tab\n open_preview_btn.click(\n fn=None,\n inputs=[preview_url_state],\n outputs=None,\n js=\"(url) => window.open(url, '_blank')\"\n )\n\n# Launch Application\nif __name__ == \"__main__\":\n demo.launch(\n server_name=\"0.0.0.0\",\n server_port=7860,\n share=False,\n show_error=True\n )"}}, "camel/types/enums.py": {"bebd9007ee35871fc7dad316f1bf8efbee6dfe29": {"t": 1785674651.178309, "n": 70958, "h": "31041e19c42e5c5b", "c": "# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========\nimport os\nfrom enum import Enum, EnumMeta\nfrom typing import Union, cast\n\nfrom camel.logger import get_logger\nfrom camel.types.unified_model_type import UnifiedModelType\n\nlogger = get_logger(__name__)\n\n\nclass RoleType(Enum):\n ASSISTANT = \"assistant\"\n USER = \"user\"\n CRITIC = \"critic\"\n EMBODIMENT = \"embodiment\"\n DEFAULT = \"default\"\n\n\nclass ModelType(UnifiedModelType, Enum):\n DEFAULT = os.getenv(\"DEFAULT_MODEL_TYPE\", \"gpt-5-mini\")\n\n GPT_3_5_TURBO = \"gpt-3.5-turbo\"\n GPT_4 = \"gpt-4\"\n GPT_4_TURBO = \"gpt-4-turbo\"\n GPT_4O = \"gpt-4o\"\n GPT_4O_MINI = \"gpt-4o-mini\"\n GPT_4_5_PREVIEW = \"gpt-4.5-preview\"\n O1 = \"o1\"\n O1_PREVIEW = \"o1-preview\"\n O1_MINI = \"o1-mini\"\n O3_MINI = \"o3-mini\"\n GPT_4_1 = \"gpt-4.1-2025-04-14\"\n GPT_4_1_MINI = \"gpt-4.1-mini-2025-04-14\"\n GPT_4_1_NANO = \"gpt-4.1-nano-2025-04-14\"\n O4_MINI = \"o4-mini\"\n O3 = \"o3\"\n O3_PRO = \"o3-pro\"\n GPT_5 = \"gpt-5\"\n GPT_5_MINI = \"gpt-5-mini\"\n GPT_5_NANO = \"gpt-5-nano\"\n\n AWS_CLAUDE_3_7_SONNET = \"anthropic.claude-3-7-sonnet-20250219-v1:0\"\n AWS_CLAUDE_3_5_SONNET = \"anthropic.claude-3-5-sonnet-20241022-v2:0\"\n AWS_CLAUDE_3_HAIKU = \"anthropic.claude-3-haiku-20240307-v1:0\"\n AWS_CLAUDE_3_SONNET = \"anthropic.claude-3-sonnet-20240229-v1:0\"\n AWS_DEEPSEEK_R1 = \"us.deepseek.r1-v1:0\"\n AWS_LLAMA_3_3_70B_INSTRUCT = \"us.meta.llama3-3-70b-instruct-v1:0\"\n AWS_LLAMA_3_2_90B_INSTRUCT = \"us.meta.llama3-2-90b-instruct-v1:0\"\n AWS_LLAMA_3_2_11B_INSTRUCT = \"us.meta.llama3-2-11b-instruct-v1:0\"\n AWS_CLAUDE_SONNET_4 = \"anthropic.claude-sonnet-4-20250514-v1:0\"\n AWS_CLAUDE_OPUS_4 = \"anthropic.claude-opus-4-20250514-v1:0\"\n AWS_CLAUDE_OPUS_4_1 = \"anthropic.claude-opus-4-1-20250805-v1:0\"\n\n AMD_GPT4 = \"dvue-aoai-001-gpt-4.1\"\n\n GLM_4 = \"glm-4\"\n GLM_4V = \"glm-4v\"\n GLM_4V_FLASH = \"glm-4v-flash\"\n GLM_4V_PLUS_0111 = \"glm-4v-plus-0111\"\n GLM_4_PLUS = \"glm-4-plus\"\n GLM_4_AIR = \"glm-4-air\"\n GLM_4_AIR_0111 = \"glm-4-air-0111\"\n GLM_4_AIRX = \"glm-4-airx\"\n GLM_4_LONG = \"glm-4-long\"\n GLM_4_FLASHX = \"glm-4-flashx\"\n GLM_4_FLASH = \"glm-4-flash\"\n GLM_ZERO_PREVIEW = \"glm-zero-preview\"\n GLM_3_TURBO = \"glm-3-turbo\"\n\n # Groq platform models\n GROQ_LLAMA_3_1_8B = \"llama-3.1-8b-instant\"\n GROQ_LLAMA_3_3_70B = \"llama-3.3-70b-versatile\"\n GROQ_LLAMA_3_3_70B_PREVIEW = \"llama-3.3-70b-specdec\"\n GROQ_LLAMA_3_8B = \"llama3-8b-8192\"\n GROQ_LLAMA_3_70B = \"llama3-70b-8192\"\n GROQ_MIXTRAL_8_7B = \"mixtral-8x7b-32768\"\n GROQ_GEMMA_2_9B_IT = \"gemma2-9b-it\"\n\n # Nebius AI Studio platform models\n NEBIUS_GPT_OSS_120B = \"gpt-oss-120b\"\n NEBIUS_GPT_OSS_20B = \"gpt-oss-20b\"\n NEBIUS_GLM_4_5 = \"GLM-4.5\"\n NEBIUS_DEEPSEEK_V3 = \"deepseek-ai/DeepSeek-V3\"\n NEBIUS_DEEPSEEK_R1 = \"deepseek-ai/DeepSeek-R1\"\n NEBIUS_LLAMA_3_1_70B = \"meta-llama/Meta-Llama-3.1-70B-Instruct\"\n NEBIUS_MISTRAL_7B_INSTRUCT = \"mistralai/Mistral-7B-Instruct-v0.3\"\n\n # CometAPI platform models\n COMETAPI_GPT_5_CHAT_LATEST = \"gpt-5-chat-latest\"\n COMETAPI_CHATGPT_4O_LATEST = \"chatgpt-4o-latest\"\n COMETAPI_GPT_5_MINI = \"gpt-5-mini\"\n COMETAPI_GPT_5_NANO = \"gpt-5-nano\"\n COMETAPI_GPT_5 = \"gpt-5\"\n COMETAPI_GPT_4_1 = \"gpt-4.1\"\n COMETAPI_GPT_4O_MINI = \"gpt-4o-mini\"\n COMETAPI_O4_MINI_2025_04_16 = \"o4-mini-2025-04-16\"\n COMETAPI_O3_PRO_2025_06_10 = \"o3-pro-2025-06-10\"\n COMETAPI_CLAUDE_OPUS_4_1_20250805 = \"claude-opus-4-1-20250805\"\n COMETAPI_CLAUDE_OPUS_4_1_20250805_THINKING = (\n \"claude-opus-4-1-20250805-thinking\"\n )\n COMETAPI_CLAUDE_SONNET_4_20250514 = \"claude-sonnet-4-20250514\"\n COMETAPI_CLAUDE_SONNET_4_20250514_THINKING = (\n \"claude-sonnet-4-20250514-thinking\"\n )\n COMETAPI_CLAUDE_3_7_SONNET_LATEST = \"claude-3-7-sonnet-latest\"\n COMETAPI_CLAUDE_3_5_HAIKU_LATEST = \"claude-3-5-haiku-latest\"\n COMETAPI_GEMINI_2_5_PRO = \"gemini-2.5-pro\"\n COMETAPI_GEMINI_2_5_FLASH = \"gemini-2.5-flash\"\n COMETAPI_GEMINI_2_5_FLASH_LITE = \"gemini-2.5-flash-lite\"\n COMETAPI_GEMINI_2_0_FLASH = \"gemini-2.0-flash\"\n COMETAPI_GROK_4_0709 = \"grok-4-0709\"\n COMETAPI_GROK_3 = \"grok-3\"\n COMETAPI_GROK_3_MINI = \"grok-3-mini\"\n COMETAPI_GROK_2_IMAGE_1212 = \"grok-2-image-1212\"\n COMETAPI_DEEPSEEK_V3_1 = \"deepseek-v3.1\"\n COMETAPI_DEEPSEEK_V3 = \"deepseek-v3\"\n COMETAPI_DEEPSEEK_R1_0528 = \"deepseek-r1-0528\"\n COMETAPI_DEEPSEEK_CHAT = \"deepseek-chat\"\n COMETAPI_DEEPSEEK_REASONER = \"deepseek-reasoner\"\n COMETAPI_QWEN3_30B_A3B = \"qwen3-30b-a3b\"\n COMETAPI_QWEN3_CODER_PLUS_2025_07_22 = \"qwen3-coder-plus-2025-07-22\"\n\n # OpenRouter models\n OPENROUTER_LLAMA_3_1_405B = \"meta-llama/llama-3.1-405b-instruct\"\n OPENROUTER_LLAMA_3_1_70B = \"meta-llama/llama-3.1-70b-instruct\"\n OPENROUTER_LLAMA_4_MAVERICK = \"meta-llama/llama-4-maverick\"\n OPENROUTER_LLAMA_4_MAVERICK_FREE = \"meta-llama/llama-4-maverick:free\"\n OPENROUTER_LLAMA_4_SCOUT = \"meta-llama/llama-4-scout\"\n OPENROUTER_LLAMA_4_SCOUT_FREE = \"meta-llama/llama-4-scout:free\"\n OPENROUTER_OLYMPICODER_7B = \"open-r1/olympiccoder-7b:free\"\n OPENROUTER_HORIZON_ALPHA = \"openrouter/horizon-alpha\"\n OPENROUTER_GROK_4_FAST = \"x-ai/grok-4-fast\"\n OPENROUTER_GEMINI_2_5_FLASH = \"google/gemini-2.5-flash\"\n OPENROUTER_GPT_4O_MINI = 'openai/gpt-4o-mini'\n OPENROUTER_QWEN_PLUS = 'qwen/qwen-plus'\n OPENROUTER_QWEN_VL_MAX = 'qwen/qwen-vl-max'\n OPENROUTER_o3 = 'openai/o3'\n OPENROUTER_CLAUDE_SONNET_4_5 = 'anthropic/claude-sonnet-4.5'\n \n # LMStudio models\n LMSTUDIO_GEMMA_3_1B = \"gemma-3-1b\"\n LMSTUDIO_GEMMA_3_4B = \"gemma-3-4b\"\n LMSTUDIO_GEMMA_3_12B = \"gemma-3-12b\"\n LMSTUDIO_GEMMA_3_27B = \"gemma-3-27b\"\n\n # TogetherAI platform models support tool calling\n TOGETHER_LLAMA_3_1_8B = \"meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo\"\n TOGETHER_LLAMA_3_1_70B = \"meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo\"\n TOGETHER_LLAMA_3_1_405B = \"meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo\"\n TOGETHER_LLAMA_3_3_70B = \"meta-llama/Llama-3.3-70B-Instruct-Turbo\"\n TOGETHER_MIXTRAL_8_7B = \"mistralai/Mixtral-8x7B-Instruct-v0.1\"\n TOGETHER_MISTRAL_7B = \"mistralai/Mistral-7B-Instruct-v0.1\"\n TOGETHER_LLAMA_4_MAVERICK = (\n \"meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8\"\n )\n TOGETHER_LLAMA_4_SCOUT = \"meta-llama/Llama-4-Scout-17B-16E-Instruct\"\n\n # PPIO platform models support tool calling\n PPIO_DEEPSEEK_PROVER_V2_671B = \"deepseek/deepseek-prover-v2-671b\"\n PPIO_DEEPSEEK_R1_TURBO = \"deepseek/deepseek-r1-turbo\"\n PPIO_DEEPSEEK_V3_TURBO = \"deepseek/deepseek-v3-turbo\"\n PPIO_DEEPSEEK_R1_COMMUNITY = \"deepseek/deepseek-r1/community\"\n PPIO_DEEPSEEK_V3_COMMUNITY = \"deepseek/deepseek-v3/community\"\n PPIO_DEEPSEEK_R1 = \"deepseek/deepseek-r1\"\n PPIO_DEEPSEEK_V3 = \"deepseek/deepseek-v3\"\n PPIO_QWEN_2_5_72B = \"qwen/qwen-2.5-72b-instruct\"\n PPIO_BAICHUAN_2_13B_CHAT = \"baichuan/baichuan2-13b-chat\"\n PPIO_LLAMA_3_3_70B = \"meta-llama/llama-3.3-70b-instruct\"\n PPIO_LLAMA_3_1_70B = \"meta-llama/llama-3.1-70b-instruct\"\n PPIO_YI_1_5_34B_CHAT = \"01-ai/yi-1.5-34b-chat\"\n\n # SambaNova Cloud platform models support tool calling\n SAMBA_LLAMA_3_1_8B = \"Meta-Llama-3.1-8B-Instruct\"\n SAMBA_LLAMA_3_1_70B = \"Meta-Llama-3.1-70B-Instruct\"\n SAMBA_LLAMA_3_1_405B = \"Meta-Llama-3.1-405B-Instruct\"\n\n # SGLang models support tool calling\n SGLANG_LLAMA_3_1_8B = \"meta-llama/Meta-Llama-3.1-8B-Instruct\"\n SGLANG_LLAMA_3_1_70B = \"meta-llama/Meta-Llama-3.1-70B-Instruct\"\n SGLANG_LLAMA_3_1_405B = \"meta-llama/Meta-Llama-3.1-405B-Instruct\"\n SGLANG_LLAMA_3_2_1B = \"meta-llama/Llama-3.2-1B-Instruct\"\n SGLANG_MIXTRAL_NEMO = \"mistralai/Mistral-Nemo-Instruct-2407\"\n SGLANG_MISTRAL_7B = \"mistralai/Mistral-7B-Instruct-v0.3\"\n SGLANG_QWEN_2_5_7B = \"Qwen/Qwen2.5-7B-Instruct\"\n SGLANG_QWEN_2_5_32B = \"Qwen/Qwen2.5-32B-Instruct\"\n SGLANG_QWEN_2_5_72B = \"Qwen/Qwen2.5-72B-Instruct\"\n\n STUB = \"stub\"\n\n # Legacy anthropic models\n # NOTE: anthropic legacy models only Claude 2.1 has system prompt support\n CLAUDE_2_1 = \"claude-2.1\"\n CLAUDE_2_0 = \"claude-2.0\"\n CLAUDE_INSTANT_1_2 = \"claude-instant-1.2\"\n\n # Claude models\n CLAUDE_3_OPUS = \"claude-3-opus-latest\"\n CLAUDE_3_SONNET = \"claude-3-sonnet-20240229\"\n CLAUDE_3_HAIKU = \"claude-3-haiku-20240307\"\n CLAUDE_3_5_SONNET = \"claude-3-5-sonnet-latest\"\n CLAUDE_3_5_HAIKU = \"claude-3-5-haiku-latest\"\n CLAUDE_3_7_SONNET = \"claude-3-7-sonnet-latest\"\n CLAUDE_SONNET_4 = \"claude-sonnet-4-20250514\"\n CLAUDE_OPUS_4 = \"claude-opus-4-20250514\"\n CLAUDE_OPUS_4_1 = \"claude-opus-4-1-20250805\"\n\n # Netmind models\n NETMIND_LLAMA_4_MAVERICK_17B_128E_INSTRUCT = (\n \"meta-llama/Llama-4-Maverick-17B-128E-Instruct\"\n )\n NETMIND_LLAMA_4_SCOUT_17B_16E_INSTRUCT = (\n \"meta-llama/Llama-4-Scout-17B-16E-Instruct\"\n )\n NETMIND_DEEPSEEK_R1 = \"deepseek-ai/DeepSeek-R1\"\n NETMIND_DEEPSEEK_V3 = \"deepseek-ai/DeepSeek-V3-0324\"\n NETMIND_DOUBAO_1_5_PRO = \"doubao/Doubao-1.5-pro\"\n NETMIND_QWQ_32B = \"Qwen/QwQ-32B\"\n\n # Nvidia models\n NVIDIA_NEMOTRON_340B_INSTRUCT = \"nvidia/nemotron-4-340b-instruct\"\n NVIDIA_NEMOTRON_340B_REWARD = \"nvidia/nemotron-4-340b-reward\"\n NVIDIA_YI_LARGE = \"01-ai/yi-large\"\n NVIDIA_MISTRAL_LARGE = \"mistralai/mistral-large\"\n NVIDIA_MIXTRAL_8X7B = \"mistralai/mixtral-8x7b-instruct\"\n NVIDIA_LLAMA3_70B = \"meta/llama3-70b\"\n NVIDIA_LLAMA3_1_8B_INSTRUCT = \"meta/llama-3.1-8b-instruct\"\n NVIDIA_LLAMA3_1_70B_INSTRUCT = \"meta/llama-3.1-70b-instruct\"\n NVIDIA_LLAMA3_1_405B_INSTRUCT = \"meta/llama-3.1-405b-instruct\"\n NVIDIA_LLAMA3_2_1B_INSTRUCT = \"meta/llama-3.2-1b-instruct\"\n NVIDIA_LLAMA3_2_3B_INSTRUCT = \"meta/llama-3.2-3b-instruct\"\n NVIDIA_LLAMA3_3_70B_INSTRUCT = \"meta/llama-3.3-70b-instruct\"\n\n # Gemini models\n GEMINI_2_5_FLASH = \"gemini-2.5-flash\"\n GEMINI_2_5_PRO = \"gemini-2.5-pro\"\n GEMINI_2_0_FLASH = \"gemini-2.0-flash\"\n GEMINI_2_0_FLASH_EXP = \"gemini-2.0-flash-exp\"\n GEMINI_2_0_FLASH_THINKING = \"gemini-2.0-flash-thinking-exp\"\n GEMINI_2_0_PRO_EXP = \"gemini-2.0-pro-exp-02-05\"\n GEMINI_2_0_FLASH_LITE = \"gemini-2.0-flash-lite\"\n GEMINI_2_0_FLASH_LITE_PREVIEW = \"gemini-2.0-flash-lite-preview-02-05\"\n GEMINI_1_5_FLASH = \"gemini-1.5-flash\"\n GEMINI_1_5_PRO = \"gemini-1.5-pro\"\n\n # Mistral AI models\n MISTRAL_3B = \"ministral-3b-latest\"\n MISTRAL_7B = \"open-mistral-7b\"\n MISTRAL_8B = \"ministral-8b-latest\"\n MISTRAL_CODESTRAL = \"codestral-latest\"\n MISTRAL_CODESTRAL_MAMBA = \"open-codestral-mamba\"\n MISTRAL_LARGE = \"mistral-large-latest\"\n MISTRAL_MIXTRAL_8x7B = \"open-mixtral-8x7b\"\n MISTRAL_MIXTRAL_8x22B = \"open-mixtral-8x22b\"\n MISTRAL_NEMO = \"open-mistral-nemo\"\n MISTRAL_PIXTRAL_12B = \"pixtral-12b-2409\"\n MISTRAL_MEDIUM_3_1 = \"mistral-medium-2508\"\n MISTRAL_SMALL_3_2 = \"mistral-small-2506\"\n MAGISTRAL_SMALL_1_2 = \"magistral-small-1.2\"\n MAGISTRAL_MEDIUM_1_2 = \"magistral-medium-1.2\"\n\n # Reka models\n REKA_CORE = \"reka-core\"\n REKA_FLASH = \"reka-flash\"\n REKA_EDGE = \"reka-edge\"\n\n # Cohere models\n COHERE_COMMAND_R_PLUS = \"command-r-plus\"\n COHERE_COMMAND_R = \"command-r\"\n COHERE_COMMAND_LIGHT = \"command-light\"\n COHERE_COMMAND = \"command\"\n COHERE_COMMAND_NIGHTLY = \"command-nightly\"\n\n # Qwen models (Aliyun)\n QWEN_MAX = \"qwen-max\"\n QWEN_PLUS = \"qwen-plus\"\n QWEN_TURBO = \"qwen-turbo\"\n QWEN_PLUS_LATEST = \"qwen-plus-latest\"\n QWEN_PLUS_2025_04_28 = \"qwen-plus-2025-04-28\"\n QWEN_TURBO_LATEST = \"qwen-turbo-latest\"\n QWEN_TURBO_2025_04_28 = \"qwen-turbo-2025-04-28\"\n QWEN_LONG = \"qwen-long\"\n QWEN_VL_MAX = \"qwen-vl-max\"\n QWEN_VL_PLUS = \"qwen-vl-plus\"\n QWEN_MATH_PLUS = \"qwen-math-plus\"\n QWEN_MATH_TURBO = \"qwen-math-turbo\"\n QWEN_CODER_TURBO = \"qwen-coder-turbo\"\n QWEN_2_5_CODER_32B = \"qwen2.5-coder-32b-instruct\"\n QWEN_2_5_VL_72B = \"qwen2.5-vl-72b-instruct\"\n QWEN_2_5_72B = \"qwen2.5-72b-instruct\"\n QWEN_2_5_32B = \"qwen2.5-32b-instruct\"\n QWEN_2_5_14B = \"qwen2.5-14b-instruct\"\n QWEN_QWQ_32B = \"qwq-32b-preview\"\n QWEN_QVQ_72B = \"qvq-72b-preview\"\n QWEN_QWQ_PLUS = \"qwq-plus\"\n QWEN_3_CODER_PLUS = \"qwen3-coder-plus\"\n\n # Yi models (01-ai)\n YI_LIGHTNING = \"yi-lightning\"\n YI_LARGE = \"yi-large\"\n YI_MEDIUM = \"yi-medium\"\n YI_LARGE_TURBO = \"yi-large-turbo\"\n YI_VISION = \"yi-vision\"\n YI_MEDIUM_200K = \"yi-medium-200k\"\n YI_SPARK = \"yi-spark\"\n YI_LARGE_RAG = \"yi-large-rag\"\n YI_LARGE_FC = \"yi-large-fc\"\n\n # DeepSeek models\n DEEPSEEK_CHAT = \"deepseek-chat\"\n DEEPSEEK_REASONER = \"deepseek-reasoner\"\n # InternLM models\n INTERNLM3_LATEST = \"internlm3-latest\"\n INTERNLM3_8B_INSTRUCT = \"internlm3-8b-instruct\"\n INTERNLM2_5_LATEST = \"internlm2.5-latest\"\n INTERNLM2_PRO_CHAT = \"internlm2-pro-chat\"\n\n # Moonshot models\n MOONSHOT_V1_8K = \"moonshot-v1-8k\"\n MOONSHOT_V1_32K = \"moonshot-v1-32k\"\n MOONSHOT_V1_128K = \"moonshot-v1-128k\"\n MOONSHOT_KIMI_K2 = \"kimi-k2-0711-preview\"\n\n # SiliconFlow models support tool calling\n SILICONFLOW_DEEPSEEK_V2_5 = \"deepseek-ai/DeepSeek-V2.5\"\n SILICONFLOW_DEEPSEEK_V3 = \"deepseek-ai/DeepSeek-V3\"\n SILICONFLOW_INTERN_LM2_5_20B_CHAT = \"internlm/internlm2_5-20b-chat\"\n SILICONFLOW_INTERN_LM2_5_7B_CHAT = \"internlm/internlm2_5-7b-chat\"\n SILICONFLOW_PRO_INTERN_LM2_5_7B_CHAT = \"Pro/internlm/internlm2_5-7b-chat\"\n SILICONFLOW_QWEN2_5_72B_INSTRUCT = \"Qwen/Qwen2.5-72B-Instruct\"\n SILICONFLOW_QWEN2_5_32B_INSTRUCT = \"Qwen/Qwen2.5-32B-Instruct\"\n SILICONFLOW_QWEN2_5_14B_INSTRUCT = \"Qwen/Qwen2.5-14B-Instruct\"\n SILICONFLOW_QWEN2_5_7B_INSTRUCT = \"Qwen/Qwen2.5-7B-Instruct\"\n SILICONFLOW_PRO_QWEN2_5_7B_INSTRUCT = \"Pro/Qwen/Qwen2.5-7B-Instruct\"\n SILICONFLOW_THUDM_GLM_4_9B_CHAT = \"THUDM/glm-4-9b-chat\"\n SILICONFLOW_PRO_THUDM_GLM_4_9B_CHAT = \"Pro/THUDM/glm-4-9b-chat\"\n\n # AIML models support tool calling\n AIML_MIXTRAL_8X7B = \"mistralai/Mixtral-8x7B-Instruct-v0.1\"\n AIML_MISTRAL_7B_INSTRUCT = \"mistralai/Mistral-7B-Instruct-v0.1\"\n\n # Novita platform models support tool calling\n NOVITA_LLAMA_4_MAVERICK_17B = (\n \"meta-llama/llama-4-maverick-17b-128e-instruct-fp8\"\n )\n NOVITA_LLAMA_4_SCOUT_17B = \"meta-llama/llama-4-scout-17b-16e-instruct\"\n NOVITA_DEEPSEEK_V3_0324 = \"deepseek/deepseek-v3-0324\"\n NOVITA_QWEN_2_5_V1_72B = \"qwen/qwen2.5-vl-72b-instruct\"\n NOVITA_DEEPSEEK_V3_TURBO = \"deepseek/deepseek-v3-turbo\"\n NOVITA_DEEPSEEK_R1_TURBO = \"deepseek/deepseek-r1-turbo\"\n NOVITA_GEMMA_3_27B_IT = \"google/gemma-3-27b-it\"\n NOVITA_QWEN_32B = \"qwen/qwq-32b\"\n NOVITA_L3_8B_STHENO_V3_2 = \"Sao10K/L3-8B-Stheno-v3.2\"\n NOVITA_MYTHOMAX_L2_13B = \"gryphe/mythomax-l2-13b\"\n NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_8B = (\n \"deepseek/deepseek-r1-distill-llama-8b\"\n )\n NOVITA_DEEPSEEK_V3 = \"deepseek/deepseek_v3\"\n NOVITA_LLAMA_3_1_8B = \"meta-llama/llama-3.1-8b-instruct\"\n NOVITA_DEEPSEEK_R1_DISTILL_QWEN_14B = (\n \"deepseek/deepseek-r1-distill-qwen-14b\"\n )\n NOVITA_LLAMA_3_3_70B = \"meta-llama/llama-3.3-70b-instruct\"\n NOVITA_QWEN_2_5_72B = \"qwen/qwen-2.5-72b-instruct\"\n NOVITA_MISTRAL_NEMO = \"mistralai/mistral-nemo\"\n NOVITA_DEEPSEEK_R1_DISTILL_QWEN_32B = (\n \"deepseek/deepseek-r1-distill-qwen-32b\"\n )\n NOVITA_LLAMA_3_8B = \"meta-llama/llama-3-8b-instruct\"\n NOVITA_WIZARDLM_2_8X22B = \"microsoft/wizardlm-2-8x22b\"\n NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_70B = (\n \"deepseek/deepseek-r1-distill-llama-70b\"\n )\n NOVITA_LLAMA_3_1_70B = \"meta-llama/llama-3.1-70b-instruct\"\n NOVITA_GEMMA_2_9B_IT = \"google/gemma-2-9b-it\"\n NOVITA_MISTRAL_7B = \"mistralai/mistral-7b-instruct\"\n NOVITA_LLAMA_3_70B = \"meta-llama/llama-3-70b-instruct\"\n NOVITA_DEEPSEEK_R1 = \"deepseek/deepseek-r1\"\n NOVITA_HERMES_2_PRO_LLAMA_3_8B = \"nousresearch/hermes-2-pro-llama-3-8b\"\n NOVITA_L3_70B_EURYALE_V2_1 = \"sao10k/l3-70b-euryale-v2.1\"\n NOVITA_DOLPHIN_MIXTRAL_8X22B = (\n \"cognitivecomputations/dolphin-mixtral-8x22b\"\n )\n NOVITA_AIROBOROS_L2_70B = \"jondurbin/airoboros-l2-70b\"\n NOVITA_MIDNIGHT_ROSE_70B = \"sophosympatheia/midnight-rose-70b\"\n NOVITA_L3_8B_LUNARIS = \"sao10k/l3-8b-lunaris\"\n NOVITA_GLM_4_9B_0414 = \"thudm/glm-4-9b-0414\"\n NOVITA_GLM_Z1_9B_0414 = \"thudm/glm-z1-9b-0414\"\n NOVITA_GLM_Z1_32B_0414 = \"thudm/glm-z1-32b-0414\"\n NOVITA_GLM_4_32B_0414 = \"thudm/glm-4-32b-0414\"\n NOVITA_GLM_Z1_RUMINATION_32B_0414 = \"thudm/glm-z1-rumination-32b-0414\"\n NOVITA_QWEN_2_5_7B = \"qwen/qwen2.5-7b-instruct\"\n NOVITA_LLAMA_3_2_1B = \"meta-llama/llama-3.2-1b-instruct\"\n NOVITA_LLAMA_3_2_11B_VISION = \"meta-llama/llama-3.2-11b-vision-instruct\"\n NOVITA_LLAMA_3_2_3B = \"meta-llama/llama-3.2-3b-instruct\"\n NOVITA_LLAMA_3_1_8B_BF16 = \"meta-llama/llama-3.1-8b-instruct-bf16\"\n NOVITA_L31_70B_EURYALE_V2_2 = \"sao10k/l31-70b-euryale-v2.2\"\n\n # ModelScope models support tool calling\n MODELSCOPE_QWEN_2_5_7B_INSTRUCT = \"Qwen/Qwen2.5-7B-Instruct\"\n MODELSCOPE_QWEN_2_5_14B_INSTRUCT = \"Qwen/Qwen2.5-14B-Instruct\"\n MODELSCOPE_QWEN_2_5_32B_INSTRUCT = \"Qwen/Qwen2.5-32B-Instruct\"\n MODELSCOPE_QWEN_2_5_72B_INSTRUCT = \"Qwen/Qwen2.5-72B-Instruct\"\n MODELSCOPE_QWEN_2_5_CODER_7B_INSTRUCT = \"Qwen/Qwen2.5-Coder-7B-Instruct\"\n MODELSCOPE_QWEN_2_5_CODER_14B_INSTRUCT = \"Qwen/Qwen2.5-Coder-14B-Instruct\"\n MODELSCOPE_QWEN_2_5_CODER_32B_INSTRUCT = \"Qwen/Qwen2.5-Coder-32B-Instruct\"\n MODELSCOPE_QWEN_3_235B_A22B = \"Qwen/Qwen3-235B-A22B\"\n MODELSCOPE_QWEN_3_32B = \"Qwen/Qwen3-32B\"\n MODELSCOPE_QWQ_32B = \"Qwen/QwQ-32B\"\n MODELSCOPE_QWQ_32B_PREVIEW = \"Qwen/QwQ-32B-Preview\"\n MODELSCOPE_LLAMA_3_1_8B_INSTRUCT = (\n \"LLM-Research/Meta-Llama-3.1-8B-Instruct\"\n )\n MODELSCOPE_LLAMA_3_1_70B_INSTRUCT = (\n \"LLM-Research/Meta-Llama-3.1-70B-Instruct\"\n )\n MODELSCOPE_LLAMA_3_1_405B_INSTRUCT = (\n \"LLM-Research/Meta-Llama-3.1-405B-Instruct\"\n )\n MODELSCOPE_LLAMA_3_3_70B_INSTRUCT = \"LLM-Research/Llama-3.3-70B-Instruct\"\n MODELSCOPE_MINISTRAL_8B_INSTRUCT = \"mistralai/Ministral-8B-Instruct-2410\"\n MODELSCOPE_DEEPSEEK_V3_0324 = \"deepseek-ai/DeepSeek-V3-0324\"\n\n # WatsonX models\n WATSONX_GRANITE_3_8B_INSTRUCT = \"ibm/granite-3-8b-instruct\"\n WATSONX_LLAMA_3_3_70B_INSTRUCT = \"meta-llama/llama-3-3-70b-instruct\"\n WATSONX_LLAMA_3_2_1B_INSTRUCT = \"meta-llama/llama-3-2-1b-instruct\"\n WATSONX_LLAMA_3_2_3B_INSTRUCT = \"meta-llama/llama-3-2-3b-instruct\"\n WATSONX_LLAMA_3_2_11B_VISION_INSTRUCT = (\n \"meta-llama/llama-3-2-11b-vision-instruct\"\n )\n WATSONX_LLAMA_3_2_90B_VISION_INSTRUCT = (\n \"meta-llama/llama-3-2-90b-vision-instruct\"\n )\n WATSONX_LLAMA_GUARD_3_11B_VISION_INSTRUCT = (\n \"meta-llama/llama-guard-3-11b-vision-instruct\"\n )\n WATSONX_MISTRAL_LARGE = \"mistralai/mistral-large\"\n\n # Qianfan models\n ERNIE_X1_TURBO_32K = \"ernie-x1-turbo-32k\"\n ERNIE_X1_32K = \"ernie-x1-32k\"\n ERNIE_X1_32K_PREVIEW = \"ernie-x1-32k-preview\"\n ERNIE_4_5_TURBO_128K = \"ernie-4.5-turbo-128k\"\n ERNIE_4_5_TURBO_32K = \"ernie-4.5-turbo-32k\"\n DEEPSEEK_V3 = \"deepseek-v3\"\n DEEPSEEK_R1 = \"deepseek-r1\"\n QWEN3_235B_A22B = \"qwen3-235b-a22b\"\n\n # Crynux models\n CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_1_5B = (\n \"deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B\"\n )\n CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_7B = (\n \"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\"\n )\n CRYNUX_DEEPSEEK_R1_DISTILL_LLAMA_8B = (\n \"deepseek-ai/DeepSeek-R1-Distill-Llama-8B\"\n )\n\n CRYNUX_QWEN_3_4_B = \"Qwen/Qwen3-4B\"\n CRYNUX_QWEN_3_8_B = \"Qwen/Qwen3-8B\"\n CRYNUX_QWEN_2_5_7B = \"Qwen/Qwen2.5-7B\"\n CRYNUX_QWEN_2_5_7B_INSTRUCT = \"Qwen/Qwen2.5-7B-Instruct\"\n\n CRYNUX_NOUS_HERMES_3_LLAMA_3_1_8B = \"NousResearch/Hermes-3-Llama-3.1-8B\"\n CRYNUX_NOUS_HERMES_3_LLAMA_3_2_3B = \"NousResearch/Hermes-3-Llama-3.2-3B\"\n\n def __str__(self):\n return self.value\n\n def __repr__(self):\n return self.value\n\n def __new__(cls, value: Union[\"ModelType\", str]) -> \"ModelType\":\n return cast(\"ModelType\", UnifiedModelType.__new__(cls, value))\n\n @classmethod\n def from_name(cls, name: str) -> \"ModelType\":\n r\"\"\"Returns the ModelType enum value from a string.\"\"\"\n for model_type in cls:\n if model_type.value == name:\n return model_type\n raise ValueError(f\"Unknown ModelType name: {name}\")\n\n @property\n def value_for_tiktoken(self) -> str:\n if self.is_openai:\n return self.value\n return \"gpt-4o-mini\"\n\n @property\n def support_native_structured_output(self) -> bool:\n return any(\n [\n self.is_openai,\n ]\n )\n\n @property\n def support_native_tool_calling(self) -> bool:\n return any(\n [\n self.is_openai,\n self.is_gemini,\n self.is_mistral,\n self.is_qwen,\n self.is_deepseek,\n self.is_ppio,\n self.is_cohere,\n self.is_internlm,\n self.is_together,\n self.is_sambanova,\n self.is_groq,\n self.is_openrouter,\n self.is_lmstudio,\n self.is_sglang,\n self.is_moonshot,\n self.is_siliconflow,\n self.is_modelscope,\n self.is_zhipuai,\n self.is_aiml,\n self.is_azure_openai,\n self.is_novita,\n ]\n )\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this type of models is an OpenAI-released model.\"\"\"\n return self in {\n ModelType.GPT_3_5_TURBO,\n ModelType.GPT_4,\n ModelType.GPT_4_TURBO,\n ModelType.GPT_4O,\n ModelType.GPT_4O_MINI,\n ModelType.O1,\n ModelType.O1_PREVIEW,\n ModelType.O1_MINI,\n ModelType.O3_PRO,\n ModelType.O3_MINI,\n ModelType.GPT_4_5_PREVIEW,\n ModelType.GPT_4_1,\n ModelType.GPT_4_1_MINI,\n ModelType.GPT_4_1_NANO,\n ModelType.GPT_5,\n ModelType.GPT_5_MINI,\n ModelType.GPT_5_NANO,\n ModelType.O4_MINI,\n ModelType.O3,\n }\n\n @property\n def is_amd(self) -> bool:\n r\"\"\"Returns whether this type of models is a AMD model.\"\"\"\n return self in {\n ModelType.AMD_GPT4,\n }\n\n @property\n def is_aws_bedrock(self) -> bool:\n r\"\"\"Returns whether this type of models is an AWS Bedrock model.\"\"\"\n return self in {\n ModelType.AWS_CLAUDE_3_7_SONNET,\n ModelType.AWS_CLAUDE_3_5_SONNET,\n ModelType.AWS_CLAUDE_3_HAIKU,\n ModelType.AWS_CLAUDE_3_SONNET,\n ModelType.AWS_DEEPSEEK_R1,\n ModelType.AWS_LLAMA_3_3_70B_INSTRUCT,\n ModelType.AWS_LLAMA_3_2_90B_INSTRUCT,\n ModelType.AWS_LLAMA_3_2_11B_INSTRUCT,\n ModelType.AWS_CLAUDE_SONNET_4,\n ModelType.AWS_CLAUDE_OPUS_4,\n ModelType.AWS_CLAUDE_OPUS_4_1,\n }\n\n @property\n def is_azure_openai(self) -> bool:\n r\"\"\"Returns whether this type of models is an OpenAI-released model\n from Azure.\n \"\"\"\n return self in {\n ModelType.GPT_3_5_TURBO,\n ModelType.GPT_4,\n ModelType.GPT_4_TURBO,\n ModelType.GPT_4O,\n ModelType.GPT_4O_MINI,\n ModelType.O1,\n ModelType.O1_PREVIEW,\n ModelType.O1_MINI,\n ModelType.O3_MINI,\n ModelType.O3_PRO,\n ModelType.GPT_4_5_PREVIEW,\n ModelType.GPT_4_1,\n ModelType.GPT_4_1_MINI,\n ModelType.GPT_4_1_NANO,\n ModelType.GPT_5,\n ModelType.O4_MINI,\n ModelType.O3,\n }\n\n @property\n def is_zhipuai(self) -> bool:\n r\"\"\"Returns whether this type of models is an ZhipuAI model.\"\"\"\n return self in {\n ModelType.GLM_3_TURBO,\n ModelType.GLM_4,\n ModelType.GLM_4V,\n ModelType.GLM_4V_FLASH,\n ModelType.GLM_4V_PLUS_0111,\n ModelType.GLM_4_PLUS,\n ModelType.GLM_4_AIR,\n ModelType.GLM_4_AIR_0111,\n ModelType.GLM_4_AIRX,\n ModelType.GLM_4_LONG,\n ModelType.GLM_4_FLASHX,\n ModelType.GLM_4_FLASH,\n ModelType.GLM_ZERO_PREVIEW,\n }\n\n @property\n def is_anthropic(self) -> bool:\n r\"\"\"Returns whether this type of models is Anthropic-released model.\n\n Returns:\n bool: Whether this type of models is anthropic.\n \"\"\"\n return self in {\n ModelType.CLAUDE_INSTANT_1_2,\n ModelType.CLAUDE_2_0,\n ModelType.CLAUDE_2_1,\n ModelType.CLAUDE_3_OPUS,\n ModelType.CLAUDE_3_SONNET,\n ModelType.CLAUDE_3_HAIKU,\n ModelType.CLAUDE_3_5_SONNET,\n ModelType.CLAUDE_3_5_HAIKU,\n ModelType.CLAUDE_3_7_SONNET,\n ModelType.CLAUDE_SONNET_4,\n ModelType.CLAUDE_OPUS_4,\n ModelType.CLAUDE_OPUS_4_1,\n }\n\n @property\n def is_groq(self) -> bool:\n r\"\"\"Returns whether this type of models is served by Groq.\"\"\"\n return self in {\n ModelType.GROQ_LLAMA_3_1_8B,\n ModelType.GROQ_LLAMA_3_3_70B,\n ModelType.GROQ_LLAMA_3_3_70B_PREVIEW,\n ModelType.GROQ_LLAMA_3_8B,\n ModelType.GROQ_LLAMA_3_70B,\n ModelType.GROQ_MIXTRAL_8_7B,\n ModelType.GROQ_GEMMA_2_9B_IT,\n }\n\n @property\n def is_nebius(self) -> bool:\n r\"\"\"Returns whether this type of models is served by Nebius AI\n Studio.\"\"\"\n return self in {\n ModelType.NEBIUS_GPT_OSS_120B,\n ModelType.NEBIUS_GPT_OSS_20B,\n ModelType.NEBIUS_GLM_4_5,\n ModelType.NEBIUS_DEEPSEEK_V3,\n ModelType.NEBIUS_DEEPSEEK_R1,\n ModelType.NEBIUS_LLAMA_3_1_70B,\n ModelType.NEBIUS_MISTRAL_7B_INSTRUCT,\n }\n\n @property\n def is_cometapi(self) -> bool:\n r\"\"\"Returns whether this type of models is served by CometAPI.\"\"\"\n return self in {\n ModelType.COMETAPI_GPT_5_CHAT_LATEST,\n ModelType.COMETAPI_CHATGPT_4O_LATEST,\n ModelType.COMETAPI_GPT_5_MINI,\n ModelType.COMETAPI_GPT_5_NANO,\n ModelType.COMETAPI_GPT_5,\n ModelType.COMETAPI_GPT_4_1,\n ModelType.COMETAPI_GPT_4O_MINI,\n ModelType.COMETAPI_O4_MINI_2025_04_16,\n ModelType.COMETAPI_O3_PRO_2025_06_10,\n ModelType.COMETAPI_CLAUDE_OPUS_4_1_20250805,\n ModelType.COMETAPI_CLAUDE_OPUS_4_1_20250805_THINKING,\n ModelType.COMETAPI_CLAUDE_SONNET_4_20250514,\n ModelType.COMETAPI_CLAUDE_SONNET_4_20250514_THINKING,\n ModelType.COMETAPI_CLAUDE_3_7_SONNET_LATEST,\n ModelType.COMETAPI_CLAUDE_3_5_HAIKU_LATEST,\n ModelType.COMETAPI_GEMINI_2_5_PRO,\n ModelType.COMETAPI_GEMINI_2_5_FLASH,\n ModelType.COMETAPI_GEMINI_2_5_FLASH_LITE,\n ModelType.COMETAPI_GEMINI_2_0_FLASH,\n ModelType.COMETAPI_GROK_4_0709,\n ModelType.COMETAPI_GROK_3,\n ModelType.COMETAPI_GROK_3_MINI,\n ModelType.COMETAPI_GROK_2_IMAGE_1212,\n ModelType.COMETAPI_DEEPSEEK_V3_1,\n ModelType.COMETAPI_DEEPSEEK_V3,\n ModelType.COMETAPI_DEEPSEEK_R1_0528,\n ModelType.COMETAPI_DEEPSEEK_CHAT,\n ModelType.COMETAPI_DEEPSEEK_REASONER,\n ModelType.COMETAPI_QWEN3_30B_A3B,\n ModelType.COMETAPI_QWEN3_CODER_PLUS_2025_07_22,\n }\n\n @property\n def is_openrouter(self) -> bool:\n r\"\"\"Returns whether this type of models is served by OpenRouter.\"\"\"\n return self in {\n ModelType.OPENROUTER_LLAMA_3_1_405B,\n ModelType.OPENROUTER_LLAMA_3_1_70B,\n ModelType.OPENROUTER_LLAMA_4_MAVERICK,\n ModelType.OPENROUTER_LLAMA_4_MAVERICK_FREE,\n ModelType.OPENROUTER_LLAMA_4_SCOUT,\n ModelType.OPENROUTER_LLAMA_4_SCOUT_FREE,\n ModelType.OPENROUTER_OLYMPICODER_7B,\n ModelType.OPENROUTER_HORIZON_ALPHA,\n ModelType.OPENROUTER_GROK_4_FAST,\n ModelType.OPENROUTER_GEMINI_2_5_FLASH,\n ModelType.OPENROUTER_GPT_4O_MINI,\n ModelType.OPENROUTER_QWEN_PLUS,\n ModelType.OPENROUTER_QWEN_VL_MAX,\n ModelType.OPENROUTER_o3,\n ModelType.OPENROUTER_CLAUDE_SONNET_4_5\n }\n\n @property\n def is_lmstudio(self) -> bool:\n r\"\"\"Returns whether this type of models is served by LMStudio.\"\"\"\n return self in {\n ModelType.LMSTUDIO_GEMMA_3_1B,\n ModelType.LMSTUDIO_GEMMA_3_4B,\n ModelType.LMSTUDIO_GEMMA_3_12B,\n ModelType.LMSTUDIO_GEMMA_3_27B,\n }\n\n @property\n def is_together(self) -> bool:\n r\"\"\"Returns whether this type of models is served by Together AI.\"\"\"\n return self in {\n ModelType.TOGETHER_LLAMA_3_1_405B,\n ModelType.TOGETHER_LLAMA_3_1_70B,\n ModelType.TOGETHER_LLAMA_3_3_70B,\n ModelType.TOGETHER_LLAMA_3_3_70B,\n ModelType.TOGETHER_MISTRAL_7B,\n ModelType.TOGETHER_MIXTRAL_8_7B,\n }\n\n @property\n def is_sambanova(self) -> bool:\n r\"\"\"Returns whether this type of model is served by SambaNova AI.\"\"\"\n return self in {\n ModelType.SAMBA_LLAMA_3_1_8B,\n ModelType.SAMBA_LLAMA_3_1_70B,\n ModelType.SAMBA_LLAMA_3_1_405B,\n }\n\n @property\n def is_mistral(self) -> bool:\n r\"\"\"Returns whether this type of models is served by Mistral.\"\"\"\n return self in {\n ModelType.MISTRAL_LARGE,\n ModelType.MISTRAL_NEMO,\n ModelType.MISTRAL_CODESTRAL,\n ModelType.MISTRAL_7B,\n ModelType.MISTRAL_MIXTRAL_8x7B,\n ModelType.MISTRAL_MIXTRAL_8x22B,\n ModelType.MISTRAL_CODESTRAL_MAMBA,\n ModelType.MISTRAL_PIXTRAL_12B,\n ModelType.MISTRAL_8B,\n ModelType.MISTRAL_3B,\n ModelType.MISTRAL_MEDIUM_3_1,\n ModelType.MISTRAL_SMALL_3_2,\n ModelType.MAGISTRAL_SMALL_1_2,\n ModelType.MAGISTRAL_MEDIUM_1_2,\n }\n\n @property\n def is_nvidia(self) -> bool:\n r\"\"\"Returns whether this type of models is a NVIDIA model.\"\"\"\n return self in {\n ModelType.NVIDIA_NEMOTRON_340B_INSTRUCT,\n ModelType.NVIDIA_NEMOTRON_340B_REWARD,\n ModelType.NVIDIA_YI_LARGE,\n ModelType.NVIDIA_MISTRAL_LARGE,\n ModelType.NVIDIA_LLAMA3_70B,\n ModelType.NVIDIA_MIXTRAL_8X7B,\n ModelType.NVIDIA_LLAMA3_1_8B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_1_70B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_1_405B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_2_1B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_2_3B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_3_70B_INSTRUCT,\n }\n\n @property\n def is_gemini(self) -> bool:\n r\"\"\"Returns whether this type of models is Gemini model.\n\n Returns:\n bool: Whether this type of models is gemini.\n \"\"\"\n return self in {\n ModelType.GEMINI_2_5_FLASH,\n ModelType.GEMINI_2_5_PRO,\n ModelType.GEMINI_2_0_FLASH,\n ModelType.GEMINI_2_0_FLASH_EXP,\n ModelType.GEMINI_2_0_FLASH_THINKING,\n ModelType.GEMINI_2_0_PRO_EXP,\n ModelType.GEMINI_2_0_FLASH_LITE,\n ModelType.GEMINI_2_0_FLASH_LITE_PREVIEW,\n ModelType.GEMINI_1_5_FLASH,\n ModelType.GEMINI_1_5_PRO,\n }\n\n @property\n def is_reka(self) -> bool:\n r\"\"\"Returns whether this type of models is Reka model.\n\n Returns:\n bool: Whether this type of models is Reka.\n \"\"\"\n return self in {\n ModelType.REKA_CORE,\n ModelType.REKA_EDGE,\n ModelType.REKA_FLASH,\n }\n\n @property\n def is_cohere(self) -> bool:\n r\"\"\"Returns whether this type of models is a Cohere model.\n\n Returns:\n bool: Whether this type of models is Cohere.\n \"\"\"\n return self in {\n ModelType.COHERE_COMMAND_R_PLUS,\n ModelType.COHERE_COMMAND_R,\n ModelType.COHERE_COMMAND_LIGHT,\n ModelType.COHERE_COMMAND,\n ModelType.COHERE_COMMAND_NIGHTLY,\n }\n\n @property\n def is_yi(self) -> bool:\n r\"\"\"Returns whether this type of models is Yi model.\n\n Returns:\n bool: Whether this type of models is Yi.\n \"\"\"\n return self in {\n ModelType.YI_LIGHTNING,\n ModelType.YI_LARGE,\n ModelType.YI_MEDIUM,\n ModelType.YI_LARGE_TURBO,\n ModelType.YI_VISION,\n ModelType.YI_MEDIUM_200K,\n ModelType.YI_SPARK,\n ModelType.YI_LARGE_RAG,\n ModelType.YI_LARGE_FC,\n }\n\n @property\n def is_qwen(self) -> bool:\n return self in {\n ModelType.QWEN_MAX,\n ModelType.QWEN_PLUS,\n ModelType.QWEN_TURBO,\n ModelType.QWEN_LONG,\n ModelType.QWEN_VL_MAX,\n ModelType.QWEN_VL_PLUS,\n ModelType.QWEN_MATH_PLUS,\n ModelType.QWEN_MATH_TURBO,\n ModelType.QWEN_CODER_TURBO,\n ModelType.QWEN_2_5_CODER_32B,\n ModelType.QWEN_2_5_VL_72B,\n ModelType.QWEN_2_5_72B,\n ModelType.QWEN_2_5_32B,\n ModelType.QWEN_2_5_14B,\n ModelType.QWEN_QWQ_32B,\n ModelType.QWEN_QVQ_72B,\n ModelType.QWEN_QWQ_PLUS,\n ModelType.QWEN_PLUS_LATEST,\n ModelType.QWEN_PLUS_2025_04_28,\n ModelType.QWEN_TURBO_LATEST,\n ModelType.QWEN_TURBO_2025_04_28,\n ModelType.QWEN_3_CODER_PLUS,\n }\n\n @property\n def is_deepseek(self) -> bool:\n return self in {\n ModelType.DEEPSEEK_CHAT,\n ModelType.DEEPSEEK_REASONER,\n }\n\n @property\n def is_netmind(self) -> bool:\n return self in {\n ModelType.NETMIND_LLAMA_4_MAVERICK_17B_128E_INSTRUCT,\n ModelType.NETMIND_LLAMA_4_SCOUT_17B_16E_INSTRUCT,\n ModelType.NETMIND_DEEPSEEK_R1,\n ModelType.NETMIND_DEEPSEEK_V3,\n ModelType.NETMIND_DOUBAO_1_5_PRO,\n ModelType.NETMIND_QWQ_32B,\n }\n\n @property\n def is_ppio(self) -> bool:\n return self in {\n ModelType.PPIO_DEEPSEEK_PROVER_V2_671B,\n ModelType.PPIO_DEEPSEEK_R1_TURBO,\n ModelType.PPIO_DEEPSEEK_V3_TURBO,\n ModelType.PPIO_DEEPSEEK_R1_COMMUNITY,\n ModelType.PPIO_DEEPSEEK_V3_COMMUNITY,\n ModelType.PPIO_DEEPSEEK_R1,\n ModelType.PPIO_DEEPSEEK_V3,\n ModelType.PPIO_QWEN_2_5_72B,\n ModelType.PPIO_BAICHUAN_2_13B_CHAT,\n ModelType.PPIO_LLAMA_3_3_70B,\n ModelType.PPIO_LLAMA_3_1_70B,\n ModelType.PPIO_YI_1_5_34B_CHAT,\n }\n\n @property\n def is_internlm(self) -> bool:\n return self in {\n ModelType.INTERNLM3_LATEST,\n ModelType.INTERNLM3_8B_INSTRUCT,\n ModelType.INTERNLM2_5_LATEST,\n ModelType.INTERNLM2_PRO_CHAT,\n }\n\n @property\n def is_modelscope(self) -> bool:\n return self in {\n ModelType.MODELSCOPE_QWEN_2_5_7B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_14B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_32B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_72B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_7B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_14B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_32B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_3_235B_A22B,\n ModelType.MODELSCOPE_QWEN_3_32B,\n ModelType.MODELSCOPE_QWQ_32B,\n ModelType.MODELSCOPE_QWQ_32B_PREVIEW,\n ModelType.MODELSCOPE_LLAMA_3_1_8B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_1_70B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_1_405B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_3_70B_INSTRUCT,\n ModelType.MODELSCOPE_MINISTRAL_8B_INSTRUCT,\n ModelType.MODELSCOPE_DEEPSEEK_V3_0324,\n }\n\n @property\n def is_moonshot(self) -> bool:\n return self in {\n ModelType.MOONSHOT_V1_8K,\n ModelType.MOONSHOT_V1_32K,\n ModelType.MOONSHOT_V1_128K,\n ModelType.MOONSHOT_KIMI_K2,\n }\n\n @property\n def is_sglang(self) -> bool:\n return self in {\n ModelType.SGLANG_LLAMA_3_1_8B,\n ModelType.SGLANG_LLAMA_3_1_70B,\n ModelType.SGLANG_LLAMA_3_1_405B,\n ModelType.SGLANG_LLAMA_3_2_1B,\n ModelType.SGLANG_MIXTRAL_NEMO,\n ModelType.SGLANG_MISTRAL_7B,\n ModelType.SGLANG_QWEN_2_5_7B,\n ModelType.SGLANG_QWEN_2_5_32B,\n ModelType.SGLANG_QWEN_2_5_72B,\n }\n\n @property\n def is_siliconflow(self) -> bool:\n return self in {\n ModelType.SILICONFLOW_DEEPSEEK_V2_5,\n ModelType.SILICONFLOW_DEEPSEEK_V3,\n ModelType.SILICONFLOW_INTERN_LM2_5_20B_CHAT,\n ModelType.SILICONFLOW_INTERN_LM2_5_7B_CHAT,\n ModelType.SILICONFLOW_PRO_INTERN_LM2_5_7B_CHAT,\n ModelType.SILICONFLOW_QWEN2_5_72B_INSTRUCT,\n ModelType.SILICONFLOW_QWEN2_5_32B_INSTRUCT,\n ModelType.SILICONFLOW_QWEN2_5_14B_INSTRUCT,\n ModelType.SILICONFLOW_QWEN2_5_7B_INSTRUCT,\n ModelType.SILICONFLOW_PRO_QWEN2_5_7B_INSTRUCT,\n ModelType.SILICONFLOW_THUDM_GLM_4_9B_CHAT,\n ModelType.SILICONFLOW_PRO_THUDM_GLM_4_9B_CHAT,\n }\n\n @property\n def is_watsonx(self) -> bool:\n return self in {\n ModelType.WATSONX_GRANITE_3_8B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_3_70B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_1B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_3B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_11B_VISION_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_90B_VISION_INSTRUCT,\n ModelType.WATSONX_LLAMA_GUARD_3_11B_VISION_INSTRUCT,\n ModelType.WATSONX_MISTRAL_LARGE,\n }\n\n @property\n def is_qianfan(self) -> bool:\n return self in {\n ModelType.ERNIE_X1_TURBO_32K,\n ModelType.ERNIE_X1_32K,\n ModelType.ERNIE_X1_32K_PREVIEW,\n ModelType.ERNIE_4_5_TURBO_128K,\n ModelType.ERNIE_4_5_TURBO_32K,\n ModelType.DEEPSEEK_V3,\n ModelType.DEEPSEEK_R1,\n ModelType.QWEN3_235B_A22B,\n }\n\n @property\n def is_novita(self) -> bool:\n return self in {\n ModelType.NOVITA_LLAMA_4_MAVERICK_17B,\n ModelType.NOVITA_LLAMA_4_SCOUT_17B,\n ModelType.NOVITA_DEEPSEEK_V3_0324,\n ModelType.NOVITA_QWEN_2_5_V1_72B,\n ModelType.NOVITA_DEEPSEEK_V3_TURBO,\n ModelType.NOVITA_DEEPSEEK_R1_TURBO,\n ModelType.NOVITA_GEMMA_3_27B_IT,\n ModelType.NOVITA_QWEN_32B,\n ModelType.NOVITA_L3_8B_STHENO_V3_2,\n ModelType.NOVITA_MYTHOMAX_L2_13B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_8B,\n ModelType.NOVITA_DEEPSEEK_V3,\n ModelType.NOVITA_LLAMA_3_1_8B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_QWEN_14B,\n ModelType.NOVITA_LLAMA_3_3_70B,\n ModelType.NOVITA_QWEN_2_5_72B,\n ModelType.NOVITA_MISTRAL_NEMO,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_QWEN_32B,\n ModelType.NOVITA_LLAMA_3_8B,\n ModelType.NOVITA_WIZARDLM_2_8X22B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_70B,\n ModelType.NOVITA_LLAMA_3_1_70B,\n ModelType.NOVITA_GEMMA_2_9B_IT,\n ModelType.NOVITA_MISTRAL_7B,\n ModelType.NOVITA_LLAMA_3_70B,\n ModelType.NOVITA_DEEPSEEK_R1,\n ModelType.NOVITA_HERMES_2_PRO_LLAMA_3_8B,\n ModelType.NOVITA_L3_70B_EURYALE_V2_1,\n ModelType.NOVITA_DOLPHIN_MIXTRAL_8X22B,\n ModelType.NOVITA_AIROBOROS_L2_70B,\n ModelType.NOVITA_MIDNIGHT_ROSE_70B,\n ModelType.NOVITA_L3_8B_LUNARIS,\n ModelType.NOVITA_GLM_4_9B_0414,\n ModelType.NOVITA_GLM_Z1_9B_0414,\n ModelType.NOVITA_GLM_Z1_32B_0414,\n ModelType.NOVITA_GLM_4_32B_0414,\n ModelType.NOVITA_GLM_Z1_RUMINATION_32B_0414,\n ModelType.NOVITA_QWEN_2_5_7B,\n ModelType.NOVITA_LLAMA_3_2_1B,\n ModelType.NOVITA_LLAMA_3_2_11B_VISION,\n ModelType.NOVITA_LLAMA_3_2_3B,\n ModelType.NOVITA_LLAMA_3_1_8B_BF16,\n ModelType.NOVITA_L31_70B_EURYALE_V2_2,\n }\n\n @property\n def is_crynux(self) -> bool:\n return self in {\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_1_5B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_7B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_LLAMA_8B,\n ModelType.CRYNUX_QWEN_3_4_B,\n ModelType.CRYNUX_QWEN_3_8_B,\n ModelType.CRYNUX_QWEN_2_5_7B,\n ModelType.CRYNUX_QWEN_2_5_7B_INSTRUCT,\n ModelType.CRYNUX_NOUS_HERMES_3_LLAMA_3_1_8B,\n ModelType.CRYNUX_NOUS_HERMES_3_LLAMA_3_2_3B,\n }\n\n @property\n def is_aiml(self) -> bool:\n return self in {\n ModelType.AIML_MIXTRAL_8X7B,\n ModelType.AIML_MISTRAL_7B_INSTRUCT,\n }\n\n @property\n def token_limit(self) -> int:\n r\"\"\"Returns the maximum token limit for a given model.\n\n Returns:\n int: The maximum token limit for the given model.\n \"\"\"\n if self is ModelType.GLM_4V:\n return 1024\n elif self in {\n ModelType.STUB,\n ModelType.REKA_CORE,\n ModelType.REKA_EDGE,\n ModelType.REKA_FLASH,\n ModelType.QWEN_MATH_PLUS,\n ModelType.QWEN_MATH_TURBO,\n ModelType.COHERE_COMMAND,\n ModelType.COHERE_COMMAND_LIGHT,\n ModelType.NVIDIA_NEMOTRON_340B_INSTRUCT,\n ModelType.NVIDIA_NEMOTRON_340B_REWARD,\n ModelType.NOVITA_MYTHOMAX_L2_13B,\n ModelType.NOVITA_AIROBOROS_L2_70B,\n ModelType.NOVITA_MIDNIGHT_ROSE_70B,\n }:\n return 4_096\n elif self in {\n ModelType.GPT_4,\n ModelType.GROQ_LLAMA_3_8B,\n ModelType.GROQ_LLAMA_3_70B,\n ModelType.GROQ_LLAMA_3_3_70B_PREVIEW,\n ModelType.GROQ_GEMMA_2_9B_IT,\n ModelType.GLM_3_TURBO,\n ModelType.GLM_4,\n ModelType.QWEN_VL_PLUS,\n ModelType.NVIDIA_LLAMA3_70B,\n ModelType.TOGETHER_MISTRAL_7B,\n ModelType.MOONSHOT_V1_8K,\n ModelType.GLM_4V_FLASH,\n ModelType.GLM_4_AIRX,\n ModelType.OPENROUTER_OLYMPICODER_7B,\n ModelType.LMSTUDIO_GEMMA_3_1B,\n ModelType.LMSTUDIO_GEMMA_3_4B,\n ModelType.LMSTUDIO_GEMMA_3_12B,\n ModelType.LMSTUDIO_GEMMA_3_27B,\n ModelType.WATSONX_GRANITE_3_8B_INSTRUCT,\n ModelType.NOVITA_L3_8B_STHENO_V3_2,\n ModelType.NOVITA_LLAMA_3_8B,\n ModelType.NOVITA_GEMMA_2_9B_IT,\n ModelType.NOVITA_LLAMA_3_70B,\n ModelType.NOVITA_HERMES_2_PRO_LLAMA_3_8B,\n ModelType.NOVITA_L3_70B_EURYALE_V2_1,\n ModelType.NOVITA_L3_8B_LUNARIS,\n ModelType.NOVITA_LLAMA_3_1_8B_BF16,\n ModelType.NOVITA_L31_70B_EURYALE_V2_2,\n }:\n return 8_192\n elif self in {\n ModelType.PPIO_BAICHUAN_2_13B_CHAT,\n }:\n return 14_336\n elif self in {\n ModelType.PPIO_DEEPSEEK_PROVER_V2_671B,\n ModelType.NOVITA_DOLPHIN_MIXTRAL_8X22B,\n }:\n return 16_000\n elif self in {\n ModelType.GPT_3_5_TURBO,\n ModelType.YI_LIGHTNING,\n ModelType.YI_MEDIUM,\n ModelType.YI_LARGE_TURBO,\n ModelType.YI_VISION,\n ModelType.YI_SPARK,\n ModelType.YI_LARGE_RAG,\n ModelType.SAMBA_LLAMA_3_1_8B,\n ModelType.SAMBA_LLAMA_3_1_405B,\n ModelType.GLM_4V_PLUS_0111,\n ModelType.GLM_ZERO_PREVIEW,\n ModelType.PPIO_YI_1_5_34B_CHAT,\n ModelType.NOVITA_LLAMA_3_1_8B,\n }:\n return 16_384\n elif self in {\n ModelType.NETMIND_DOUBAO_1_5_PRO,\n ModelType.NOVITA_GEMMA_3_27B_IT,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_8B,\n ModelType.NOVITA_QWEN_2_5_72B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_70B,\n ModelType.NOVITA_GLM_4_9B_0414,\n ModelType.NOVITA_GLM_Z1_9B_0414,\n ModelType.NOVITA_GLM_Z1_32B_0414,\n ModelType.NOVITA_GLM_4_32B_0414,\n ModelType.NOVITA_GLM_Z1_RUMINATION_32B_0414,\n ModelType.NOVITA_QWEN_2_5_7B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_1_5B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_7B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_LLAMA_8B,\n ModelType.CRYNUX_QWEN_3_4_B,\n ModelType.CRYNUX_QWEN_3_8_B,\n ModelType.CRYNUX_QWEN_2_5_7B,\n ModelType.CRYNUX_QWEN_2_5_7B_INSTRUCT,\n ModelType.CRYNUX_NOUS_HERMES_3_LLAMA_3_1_8B,\n ModelType.CRYNUX_NOUS_HERMES_3_LLAMA_3_2_3B,\n ModelType.ERNIE_X1_TURBO_32K,\n ModelType.ERNIE_X1_32K,\n ModelType.ERNIE_X1_32K_PREVIEW,\n ModelType.ERNIE_4_5_TURBO_32K,\n ModelType.QWEN3_235B_A22B,\n }:\n return 32_000\n elif self in {\n ModelType.MISTRAL_CODESTRAL,\n ModelType.MISTRAL_7B,\n ModelType.MISTRAL_MIXTRAL_8x7B,\n ModelType.GROQ_MIXTRAL_8_7B,\n ModelType.YI_LARGE,\n ModelType.YI_LARGE_FC,\n ModelType.QWEN_MAX,\n ModelType.QWEN_VL_MAX,\n ModelType.NVIDIA_YI_LARGE,\n ModelType.NVIDIA_MISTRAL_LARGE,\n ModelType.NVIDIA_MIXTRAL_8X7B,\n ModelType.QWEN_QWQ_32B,\n ModelType.QWEN_QWQ_PLUS,\n ModelType.QWEN_QVQ_72B,\n ModelType.INTERNLM3_8B_INSTRUCT,\n ModelType.INTERNLM3_LATEST,\n ModelType.INTERNLM2_5_LATEST,\n ModelType.INTERNLM2_PRO_CHAT,\n ModelType.TOGETHER_MIXTRAL_8_7B,\n ModelType.SGLANG_MISTRAL_7B,\n ModelType.MOONSHOT_V1_32K,\n ModelType.AIML_MIXTRAL_8X7B,\n ModelType.AIML_MISTRAL_7B_INSTRUCT,\n ModelType.PPIO_QWEN_2_5_72B,\n ModelType.PPIO_LLAMA_3_1_70B,\n ModelType.MODELSCOPE_QWEN_2_5_7B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_14B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_32B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_72B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_7B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_14B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_32B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_3_235B_A22B,\n ModelType.MODELSCOPE_QWEN_3_32B,\n ModelType.MODELSCOPE_QWQ_32B,\n ModelType.MODELSCOPE_QWQ_32B_PREVIEW,\n ModelType.MODELSCOPE_LLAMA_3_1_8B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_1_70B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_1_405B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_3_70B_INSTRUCT,\n ModelType.MODELSCOPE_MINISTRAL_8B_INSTRUCT,\n ModelType.MODELSCOPE_DEEPSEEK_V3_0324,\n ModelType.OPENROUTER_LLAMA_3_1_405B,\n ModelType.WATSONX_MISTRAL_LARGE,\n ModelType.NOVITA_QWEN_32B,\n ModelType.NOVITA_LLAMA_3_1_70B,\n ModelType.NOVITA_MISTRAL_7B,\n ModelType.NOVITA_LLAMA_3_2_11B_VISION,\n ModelType.NOVITA_LLAMA_3_2_3B,\n ModelType.NEBIUS_MISTRAL_7B_INSTRUCT,\n }:\n return 32_768\n elif self in {\n ModelType.MISTRAL_MIXTRAL_8x22B,\n ModelType.DEEPSEEK_CHAT,\n ModelType.DEEPSEEK_REASONER,\n ModelType.PPIO_DEEPSEEK_R1_TURBO,\n ModelType.PPIO_DEEPSEEK_V3_TURBO,\n ModelType.PPIO_DEEPSEEK_R1_COMMUNITY,\n ModelType.PPIO_DEEPSEEK_V3_COMMUNITY,\n ModelType.PPIO_DEEPSEEK_R1,\n ModelType.PPIO_DEEPSEEK_V3,\n ModelType.AWS_DEEPSEEK_R1,\n ModelType.NETMIND_QWQ_32B,\n ModelType.NOVITA_DEEPSEEK_V3_TURBO,\n ModelType.NOVITA_DEEPSEEK_R1_TURBO,\n ModelType.NOVITA_DEEPSEEK_V3,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_QWEN_14B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_QWEN_32B,\n ModelType.NOVITA_DEEPSEEK_R1,\n }:\n return 64_000\n elif self in {\n ModelType.NOVITA_WIZARDLM_2_8X22B,\n }:\n return 65_535\n elif self in {\n ModelType.NOVITA_QWEN_2_5_V1_72B,\n ModelType.DEEPSEEK_R1,\n }:\n return 96_000\n elif self in {\n ModelType.CLAUDE_2_0,\n ModelType.CLAUDE_INSTANT_1_2,\n }:\n return 100_000\n elif self in {\n ModelType.GPT_4O,\n ModelType.GPT_4O_MINI,\n ModelType.GPT_4_TURBO,\n ModelType.O1_PREVIEW,\n ModelType.O1_MINI,\n ModelType.GPT_4_5_PREVIEW,\n ModelType.GPT_5,\n ModelType.GPT_5_NANO,\n ModelType.GPT_5_MINI,\n ModelType.MISTRAL_LARGE,\n ModelType.MISTRAL_NEMO,\n ModelType.MISTRAL_PIXTRAL_12B,\n ModelType.MISTRAL_8B,\n ModelType.MISTRAL_3B,\n ModelType.MISTRAL_SMALL_3_2,\n ModelType.MAGISTRAL_SMALL_1_2,\n ModelType.QWEN_2_5_CODER_32B,\n ModelType.QWEN_2_5_VL_72B,\n ModelType.QWEN_2_5_72B,\n ModelType.QWEN_2_5_32B,\n ModelType.QWEN_2_5_14B,\n ModelType.COHERE_COMMAND_R,\n ModelType.COHERE_COMMAND_R_PLUS,\n ModelType.COHERE_COMMAND_NIGHTLY,\n ModelType.NVIDIA_LLAMA3_1_8B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_1_70B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_1_405B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_2_1B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_2_3B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_3_70B_INSTRUCT,\n ModelType.GROQ_LLAMA_3_3_70B,\n ModelType.SAMBA_LLAMA_3_1_70B,\n ModelType.SGLANG_LLAMA_3_1_8B,\n ModelType.SGLANG_LLAMA_3_1_70B,\n ModelType.SGLANG_LLAMA_3_1_405B,\n ModelType.SGLANG_LLAMA_3_2_1B,\n ModelType.SGLANG_MIXTRAL_NEMO,\n ModelType.MOONSHOT_V1_128K,\n ModelType.GLM_4_PLUS,\n ModelType.GLM_4_AIR,\n ModelType.GLM_4_AIR_0111,\n ModelType.GLM_4_FLASHX,\n ModelType.GLM_4_FLASH,\n ModelType.AWS_LLAMA_3_3_70B_INSTRUCT,\n ModelType.AWS_LLAMA_3_2_90B_INSTRUCT,\n ModelType.AWS_LLAMA_3_2_11B_INSTRUCT,\n ModelType.NETMIND_DEEPSEEK_R1,\n ModelType.NETMIND_DEEPSEEK_V3,\n ModelType.NOVITA_DEEPSEEK_V3_0324,\n ModelType.MISTRAL_MEDIUM_3_1,\n ModelType.MAGISTRAL_MEDIUM_1_2,\n ModelType.ERNIE_4_5_TURBO_128K,\n ModelType.DEEPSEEK_V3,\n ModelType.MOONSHOT_KIMI_K2,\n ModelType.NEBIUS_GLM_4_5,\n ModelType.NEBIUS_DEEPSEEK_V3,\n ModelType.NEBIUS_DEEPSEEK_R1,\n ModelType.NEBIUS_GPT_OSS_120B,\n ModelType.NEBIUS_GPT_OSS_20B,\n ModelType.COMETAPI_GPT_5_CHAT_LATEST,\n ModelType.COMETAPI_CHATGPT_4O_LATEST,\n ModelType.COMETAPI_GPT_5_MINI,\n ModelType.COMETAPI_GPT_5_NANO,\n ModelType.COMETAPI_GPT_5,\n ModelType.COMETAPI_GPT_4_1,\n ModelType.COMETAPI_GPT_4O_MINI,\n ModelType.COMETAPI_O4_MINI_2025_04_16,\n ModelType.COMETAPI_O3_PRO_2025_06_10,\n ModelType.COMETAPI_CLAUDE_OPUS_4_1_20250805,\n ModelType.COMETAPI_CLAUDE_OPUS_4_1_20250805_THINKING,\n ModelType.COMETAPI_CLAUDE_SONNET_4_20250514,\n ModelType.COMETAPI_CLAUDE_SONNET_4_20250514_THINKING,\n ModelType.COMETAPI_CLAUDE_3_7_SONNET_LATEST,\n ModelType.COMETAPI_CLAUDE_3_5_HAIKU_LATEST,\n ModelType.COMETAPI_GEMINI_2_5_PRO,\n ModelType.COMETAPI_GEMINI_2_5_FLASH,\n ModelType.COMETAPI_GEMINI_2_5_FLASH_LITE,\n ModelType.COMETAPI_GEMINI_2_0_FLASH,\n ModelType.COMETAPI_GROK_4_0709,\n ModelType.COMETAPI_GROK_3,\n ModelType.COMETAPI_GROK_3_MINI,\n ModelType.COMETAPI_GROK_2_IMAGE_1212,\n ModelType.COMETAPI_DEEPSEEK_V3_1,\n ModelType.COMETAPI_DEEPSEEK_V3,\n ModelType.COMETAPI_DEEPSEEK_R1_0528,\n ModelType.COMETAPI_DEEPSEEK_CHAT,\n ModelType.COMETAPI_DEEPSEEK_REASONER,\n ModelType.COMETAPI_QWEN3_30B_A3B,\n ModelType.COMETAPI_QWEN3_CODER_PLUS_2025_07_22,\n }:\n return 128_000\n elif self in {\n ModelType.NOVITA_LLAMA_3_2_1B,\n }:\n return 131_000\n elif self in {\n ModelType.GROQ_LLAMA_3_1_8B,\n ModelType.QWEN_PLUS,\n ModelType.QWEN_TURBO,\n ModelType.QWEN_CODER_TURBO,\n ModelType.QWEN_PLUS_LATEST,\n ModelType.QWEN_PLUS_2025_04_28,\n ModelType.QWEN_TURBO_LATEST,\n ModelType.QWEN_TURBO_2025_04_28,\n ModelType.TOGETHER_LLAMA_3_1_8B,\n ModelType.TOGETHER_LLAMA_3_1_70B,\n ModelType.TOGETHER_LLAMA_3_1_405B,\n ModelType.TOGETHER_LLAMA_3_3_70B,\n ModelType.SGLANG_QWEN_2_5_7B,\n ModelType.SGLANG_QWEN_2_5_32B,\n ModelType.SGLANG_QWEN_2_5_72B,\n ModelType.OPENROUTER_LLAMA_3_1_70B,\n ModelType.PPIO_LLAMA_3_3_70B,\n ModelType.OPENROUTER_LLAMA_4_SCOUT,\n ModelType.WATSONX_LLAMA_3_3_70B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_1B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_3B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_11B_VISION_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_90B_VISION_INSTRUCT,\n ModelType.WATSONX_LLAMA_GUARD_3_11B_VISION_INSTRUCT,\n ModelType.NOVITA_LLAMA_4_SCOUT_17B,\n ModelType.NOVITA_LLAMA_3_3_70B,\n ModelType.NOVITA_MISTRAL_NEMO,\n ModelType.NEBIUS_LLAMA_3_1_70B,\n }:\n return 131_072\n elif self in {\n ModelType.O1,\n ModelType.O3_MINI,\n ModelType.O3_PRO,\n ModelType.CLAUDE_2_1,\n ModelType.CLAUDE_3_OPUS,\n ModelType.CLAUDE_3_SONNET,\n ModelType.CLAUDE_3_HAIKU,\n ModelType.CLAUDE_3_5_SONNET,\n ModelType.CLAUDE_3_5_HAIKU,\n ModelType.CLAUDE_3_7_SONNET,\n ModelType.CLAUDE_SONNET_4,\n ModelType.CLAUDE_OPUS_4,\n ModelType.CLAUDE_OPUS_4_1,\n ModelType.YI_MEDIUM_200K,\n ModelType.AWS_CLAUDE_3_5_SONNET,\n ModelType.AWS_CLAUDE_3_HAIKU,\n ModelType.AWS_CLAUDE_3_SONNET,\n ModelType.AWS_CLAUDE_3_7_SONNET,\n ModelType.AWS_CLAUDE_SONNET_4,\n ModelType.AWS_CLAUDE_OPUS_4,\n ModelType.AWS_CLAUDE_OPUS_4_1,\n ModelType.O4_MINI,\n ModelType.O3,\n }:\n return 200_000\n elif self in {\n ModelType.MISTRAL_CODESTRAL_MAMBA,\n ModelType.OPENROUTER_LLAMA_4_MAVERICK_FREE,\n ModelType.OPENROUTER_HORIZON_ALPHA,\n }:\n return 256_000\n\n elif self in {\n ModelType.NETMIND_LLAMA_4_SCOUT_17B_16E_INSTRUCT,\n }:\n return 320_000\n elif self in {\n ModelType.OPENROUTER_LLAMA_4_SCOUT_FREE,\n ModelType.NETMIND_LLAMA_4_MAVERICK_17B_128E_INSTRUCT,\n }:\n return 512_000\n elif self in {\n ModelType.GEMINI_2_5_FLASH,\n ModelType.GEMINI_2_5_PRO,\n ModelType.GEMINI_2_0_FLASH,\n ModelType.GEMINI_2_0_FLASH_EXP,\n ModelType.GEMINI_2_0_FLASH_THINKING,\n ModelType.GEMINI_2_0_FLASH_LITE,\n ModelType.GEMINI_2_0_FLASH_LITE_PREVIEW,\n ModelType.GEMINI_1_5_FLASH,\n ModelType.GEMINI_1_5_PRO,\n ModelType.GEMINI_2_0_PRO_EXP, # Not given in doc, assume the same\n ModelType.GLM_4_LONG,\n ModelType.TOGETHER_LLAMA_4_MAVERICK,\n ModelType.OPENROUTER_LLAMA_4_MAVERICK,\n ModelType.AMD_GPT4,\n ModelType.GPT_4_1,\n ModelType.GPT_4_1_MINI,\n ModelType.GPT_4_1_NANO,\n ModelType.NOVITA_LLAMA_4_MAVERICK_17B,\n }:\n return 1_048_576\n elif self in {\n ModelType.QWEN_3_CODER_PLUS,\n }:\n return 1_000_000\n elif self in {\n ModelType.QWEN_LONG,\n ModelType.TOGETHER_LLAMA_4_SCOUT,\n }:\n return 10_000_000\n\n else:\n logger.warning(\n f\"Unknown model type {self}, set maximum token limit \"\n f\"to 999_999_999\"\n )\n return 999_999_999\n\n\nclass EmbeddingModelType(Enum):\n TEXT_EMBEDDING_ADA_2 = \"text-embedding-ada-002\"\n TEXT_EMBEDDING_3_SMALL = \"text-embedding-3-small\"\n TEXT_EMBEDDING_3_LARGE = \"text-embedding-3-large\"\n\n JINA_EMBEDDINGS_V3 = \"jina-embeddings-v3\"\n JINA_CLIP_V2 = \"jina-clip-v2\"\n JINA_COLBERT_V2 = \"jina-colbert-v2\"\n JINA_EMBEDDINGS_V2_BASE_CODE = \"jina-embeddings-v2-base-code\"\n\n MISTRAL_EMBED = \"mistral-embed\"\n\n GEMINI_EMBEDDING_EXP = \"gemini-embedding-exp-03-07\"\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this type of models is an OpenAI-released model.\"\"\"\n return self in {\n EmbeddingModelType.TEXT_EMBEDDING_ADA_2,\n EmbeddingModelType.TEXT_EMBEDDING_3_SMALL,\n EmbeddingModelType.TEXT_EMBEDDING_3_LARGE,\n }\n\n @property\n def is_jina(self) -> bool:\n r\"\"\"Returns whether this type of models is an Jina model.\"\"\"\n return self in {\n EmbeddingModelType.JINA_EMBEDDINGS_V3,\n EmbeddingModelType.JINA_CLIP_V2,\n EmbeddingModelType.JINA_COLBERT_V2,\n EmbeddingModelType.JINA_EMBEDDINGS_V2_BASE_CODE,\n }\n\n @property\n def is_mistral(self) -> bool:\n r\"\"\"Returns whether this type of models is an Mistral-released\n model.\n \"\"\"\n return self in {\n EmbeddingModelType.MISTRAL_EMBED,\n }\n\n @property\n def is_gemini(self) -> bool:\n r\"\"\"Returns whether this type of models is an Gemini-released model.\"\"\"\n return self in {\n EmbeddingModelType.GEMINI_EMBEDDING_EXP,\n }\n\n @property\n def output_dim(self) -> int:\n if self in {\n EmbeddingModelType.JINA_COLBERT_V2,\n }:\n return 128\n elif self in {\n EmbeddingModelType.JINA_EMBEDDINGS_V2_BASE_CODE,\n }:\n return 768\n elif self in {\n EmbeddingModelType.JINA_EMBEDDINGS_V3,\n EmbeddingModelType.JINA_CLIP_V2,\n }:\n return 1024\n elif self is EmbeddingModelType.TEXT_EMBEDDING_ADA_2:\n return 1536\n elif self is EmbeddingModelType.TEXT_EMBEDDING_3_SMALL:\n return 1536\n elif self is EmbeddingModelType.TEXT_EMBEDDING_3_LARGE:\n return 3072\n elif self is EmbeddingModelType.MISTRAL_EMBED:\n return 1024\n elif self is EmbeddingModelType.GEMINI_EMBEDDING_EXP:\n return 3072\n else:\n raise ValueError(f\"Unknown model type {self}.\")\n\n\nclass GeminiEmbeddingTaskType(str, Enum):\n r\"\"\"Task types for Gemini embedding models.\n\n For more information, please refer to:\n https://ai.google.dev/gemini-api/docs/embeddings#task-types\n \"\"\"\n\n SEMANTIC_SIMILARITY = \"SEMANTIC_SIMILARITY\"\n CLASSIFICATION = \"CLASSIFICATION\"\n CLUSTERING = \"CLUSTERING\"\n RETRIEVAL_DOCUMENT = \"RETRIEVAL_DOCUMENT\"\n RETRIEVAL_QUERY = \"RETRIEVAL_QUERY\"\n QUESTION_ANSWERING = \"QUESTION_ANSWERING\"\n FACT_VERIFICATION = \"FACT_VERIFICATION\"\n CODE_RETRIEVAL_QUERY = \"CODE_RETRIEVAL_QUERY\"\n\n\nclass TaskType(Enum):\n AI_SOCIETY = \"ai_society\"\n CODE = \"code\"\n MISALIGNMENT = \"misalignment\"\n TRANSLATION = \"translation\"\n EVALUATION = \"evaluation\"\n SOLUTION_EXTRACTION = \"solution_extraction\"\n ROLE_DESCRIPTION = \"role_description\"\n GENERATE_TEXT_EMBEDDING_DATA = \"generate_text_embedding_data\"\n OBJECT_RECOGNITION = \"object_recognition\"\n IMAGE_CRAFT = \"image_craft\"\n MULTI_CONDITION_IMAGE_CRAFT = \"multi_condition_image_craft\"\n DEFAULT = \"default\"\n VIDEO_DESCRIPTION = \"video_description\"\n\n\nclass VectorDistance(Enum):\n r\"\"\"Distance metrics used in a vector database.\"\"\"\n\n DOT = \"dot\"\n r\"\"\"Dot product. https://en.wikipedia.org/wiki/Dot_product\"\"\"\n\n COSINE = \"cosine\"\n r\"\"\"Cosine similarity. https://en.wikipedia.org/wiki/Cosine_similarity\"\"\"\n\n EUCLIDEAN = \"euclidean\"\n r\"\"\"Euclidean distance. https://en.wikipedia.org/wiki/Euclidean_distance\"\"\"\n\n\nclass OpenAIBackendRole(Enum):\n ASSISTANT = \"assistant\"\n SYSTEM = \"system\"\n DEVELOPER = \"developer\"\n USER = \"user\"\n FUNCTION = \"function\"\n TOOL = \"tool\"\n\n\nclass TerminationMode(Enum):\n ANY = \"any\"\n ALL = \"all\"\n\n\nclass OpenAIImageTypeMeta(EnumMeta):\n def __contains__(cls, image_type: object) -> bool:\n try:\n cls(image_type)\n except ValueError:\n return False\n return True\n\n\nclass OpenAIImageType(Enum, metaclass=OpenAIImageTypeMeta):\n r\"\"\"Image types supported by OpenAI vision model.\"\"\"\n\n # https://platform.openai.com/docs/guides/vision\n PNG = \"png\"\n JPEG = \"jpeg\"\n JPG = \"jpg\"\n WEBP = \"webp\"\n GIF = \"gif\"\n\n\nclass OpenAIVisionDetailType(Enum):\n AUTO = \"auto\"\n LOW = \"low\"\n HIGH = \"high\"\n\n\nclass StorageType(Enum):\n MILVUS = \"milvus\"\n QDRANT = \"qdrant\"\n TIDB = \"tidb\"\n\n\nclass OpenAPIName(Enum):\n COURSERA = \"coursera\"\n KLARNA = \"klarna\"\n SPEAK = \"speak\"\n NASA_APOD = \"nasa_apod\"\n BIZTOC = \"biztoc\"\n CREATE_QR_CODE = \"create_qr_code\"\n OUTSCHOOL = \"outschool\"\n WEB_SCRAPER = \"web_scraper\"\n\n\nclass ModelPlatformType(Enum):\n DEFAULT = os.getenv(\"DEFAULT_MODEL_PLATFORM_TYPE\", \"openai\")\n\n OPENAI = \"openai\"\n AWS_BEDROCK = \"aws-bedrock\"\n AZURE = \"azure\"\n ANTHROPIC = \"anthropic\"\n GROQ = \"groq\"\n NEBIUS = \"nebius\"\n COMETAPI = \"cometapi\"\n OPENROUTER = \"openrouter\"\n OLLAMA = \"ollama\"\n LITELLM = \"litellm\"\n LMSTUDIO = \"lmstudio\"\n ZHIPU = \"zhipuai\"\n GEMINI = \"gemini\"\n VLLM = \"vllm\"\n MISTRAL = \"mistral\"\n REKA = \"reka\"\n TOGETHER = \"together\"\n STUB = \"stub\"\n OPENAI_COMPATIBLE_MODEL = \"openai-compatible-model\"\n SAMBA = \"samba-nova\"\n COHERE = \"cohere\"\n YI = \"lingyiwanwu\"\n QWEN = \"tongyi-qianwen\"\n AMD = \"amd\"\n NVIDIA = \"nvidia\"\n DEEPSEEK = \"deepseek\"\n PPIO = \"ppio\"\n SGLANG = \"sglang\"\n INTERNLM = \"internlm\"\n MOONSHOT = \"moonshot\"\n MODELSCOPE = \"modelscope\"\n SILICONFLOW = \"siliconflow\"\n AIML = \"aiml\"\n VOLCANO = \"volcano\"\n NETMIND = \"netmind\"\n NOVITA = \"novita\"\n WATSONX = \"watsonx\"\n QIANFAN = \"qianfan\"\n CRYNUX = \"crynux\"\n\n @classmethod\n def from_name(cls, name):\n r\"\"\"Returns the ModelPlatformType enum value from a string.\"\"\"\n for model_platfrom_type in cls:\n if model_platfrom_type.value == name:\n return model_platfrom_type\n raise ValueError(f\"Unknown ModelPlatformType name: {name}\")\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this platform is openai.\"\"\"\n return self is ModelPlatformType.OPENAI\n\n @property\n def is_aws_bedrock(self) -> bool:\n r\"\"\"Returns whether this platform is aws-bedrock.\"\"\"\n return self is ModelPlatformType.AWS_BEDROCK\n\n @property\n def is_azure(self) -> bool:\n r\"\"\"Returns whether this platform is azure.\"\"\"\n return self is ModelPlatformType.AZURE\n\n @property\n def is_anthropic(self) -> bool:\n r\"\"\"Returns whether this platform is anthropic.\"\"\"\n return self is ModelPlatformType.ANTHROPIC\n\n @property\n def is_groq(self) -> bool:\n r\"\"\"Returns whether this platform is groq.\"\"\"\n return self is ModelPlatformType.GROQ\n\n @property\n def is_openrouter(self) -> bool:\n r\"\"\"Returns whether this platform is openrouter.\"\"\"\n return self is ModelPlatformType.OPENROUTER\n\n @property\n def is_lmstudio(self) -> bool:\n r\"\"\"Returns whether this platform is lmstudio.\"\"\"\n return self is ModelPlatformType.LMSTUDIO\n\n @property\n def is_ollama(self) -> bool:\n r\"\"\"Returns whether this platform is ollama.\"\"\"\n return self is ModelPlatformType.OLLAMA\n\n @property\n def is_vllm(self) -> bool:\n r\"\"\"Returns whether this platform is vllm.\"\"\"\n return self is ModelPlatformType.VLLM\n\n @property\n def is_sglang(self) -> bool:\n r\"\"\"Returns whether this platform is sglang.\"\"\"\n return self is ModelPlatformType.SGLANG\n\n @property\n def is_together(self) -> bool:\n r\"\"\"Returns whether this platform is together.\"\"\"\n return self is ModelPlatformType.TOGETHER\n\n @property\n def is_litellm(self) -> bool:\n r\"\"\"Returns whether this platform is litellm.\"\"\"\n return self is ModelPlatformType.LITELLM\n\n @property\n def is_zhipuai(self) -> bool:\n r\"\"\"Returns whether this platform is zhipu.\"\"\"\n return self is ModelPlatformType.ZHIPU\n\n @property\n def is_mistral(self) -> bool:\n r\"\"\"Returns whether this platform is mistral.\"\"\"\n return self is ModelPlatformType.MISTRAL\n\n @property\n def is_openai_compatible_model(self) -> bool:\n r\"\"\"Returns whether this is a platform supporting openai\n compatibility\"\"\"\n return self is ModelPlatformType.OPENAI_COMPATIBLE_MODEL\n\n @property\n def is_gemini(self) -> bool:\n r\"\"\"Returns whether this platform is Gemini.\"\"\"\n return self is ModelPlatformType.GEMINI\n\n @property\n def is_reka(self) -> bool:\n r\"\"\"Returns whether this platform is Reka.\"\"\"\n return self is ModelPlatformType.REKA\n\n @property\n def is_samba(self) -> bool:\n r\"\"\"Returns whether this platform is Samba Nova.\"\"\"\n return self is ModelPlatformType.SAMBA\n\n @property\n def is_cohere(self) -> bool:\n r\"\"\"Returns whether this platform is Cohere.\"\"\"\n return self is ModelPlatformType.COHERE\n\n @property\n def is_yi(self) -> bool:\n r\"\"\"Returns whether this platform is Yi.\"\"\"\n return self is ModelPlatformType.YI\n\n @property\n def is_qwen(self) -> bool:\n r\"\"\"Returns whether this platform is Qwen.\"\"\"\n return self is ModelPlatformType.QWEN\n\n @property\n def is_nvidia(self) -> bool:\n r\"\"\"Returns whether this platform is Nvidia.\"\"\"\n return self is ModelPlatformType.NVIDIA\n\n @property\n def is_deepseek(self) -> bool:\n r\"\"\"Returns whether this platform is DeepSeek.\"\"\"\n return self is ModelPlatformType.DEEPSEEK\n\n @property\n def is_netmind(self) -> bool:\n r\"\"\"Returns whether this platform is Netmind.\"\"\"\n return self is ModelPlatformType.NETMIND\n\n @property\n def is_ppio(self) -> bool:\n r\"\"\"Returns whether this platform is PPIO.\"\"\"\n return self is ModelPlatformType.PPIO\n\n @property\n def is_internlm(self) -> bool:\n r\"\"\"Returns whether this platform is InternLM.\"\"\"\n return self is ModelPlatformType.INTERNLM\n\n @property\n def is_moonshot(self) -> bool:\n r\"\"\"Returns whether this platform is Moonshot model.\"\"\"\n return self is ModelPlatformType.MOONSHOT\n\n @property\n def is_modelscope(self) -> bool:\n r\"\"\"Returns whether this platform is ModelScope model.\"\"\"\n return self is ModelPlatformType.MODELSCOPE\n\n @property\n def is_siliconflow(self) -> bool:\n r\"\"\"Returns whether this platform is SiliconFlow.\"\"\"\n return self is ModelPlatformType.SILICONFLOW\n\n @property\n def is_aiml(self) -> bool:\n r\"\"\"Returns whether this platform is AIML.\"\"\"\n return self is ModelPlatformType.AIML\n\n @property\n def is_volcano(self) -> bool:\n r\"\"\"Returns whether this platform is volcano.\"\"\"\n return self is ModelPlatformType.VOLCANO\n\n @property\n def is_novita(self) -> bool:\n r\"\"\"Returns whether this platform is Novita.\"\"\"\n return self is ModelPlatformType.NOVITA\n\n @property\n def is_watsonx(self) -> bool:\n r\"\"\"Returns whether this platform is WatsonX.\"\"\"\n return self is ModelPlatformType.WATSONX\n\n @property\n def is_crynux(self) -> bool:\n r\"\"\"Returns whether this platform is Crynux.\"\"\"\n return self is ModelPlatformType.CRYNUX\n\n\nclass AudioModelType(Enum):\n TTS_1 = \"tts-1\"\n TTS_1_HD = \"tts-1-hd\"\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this type of audio models is an OpenAI-released\n model.\"\"\"\n return self in {\n AudioModelType.TTS_1,\n AudioModelType.TTS_1_HD,\n }\n\n\nclass VoiceType(Enum):\n ALLOY = \"alloy\"\n ECHO = \"echo\"\n FABLE = \"fable\"\n ONYX = \"onyx\"\n NOVA = \"nova\"\n SHIMMER = \"shimmer\"\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this type of voice is an OpenAI-released voice.\"\"\"\n return self in {\n VoiceType.ALLOY,\n VoiceType.ECHO,\n VoiceType.FABLE,\n VoiceType.ONYX,\n VoiceType.NOVA,\n VoiceType.SHIMMER,\n }\n\n\nclass JinaReturnFormat(Enum):\n DEFAULT = None\n MARKDOWN = \"markdown\"\n HTML = \"html\"\n TEXT = \"text\"\n\n\nclass HuggingFaceRepoType(str, Enum):\n DATASET = \"dataset\"\n MODEL = \"model\"\n SPACE = \"space\""}, "ecd0ca309215d137e33bd278abaa8d73d250957b": {"t": 1785846918.0701218, "n": 70958, "h": "31041e19c42e5c5b", "c": "# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========\nimport os\nfrom enum import Enum, EnumMeta\nfrom typing import Union, cast\n\nfrom camel.logger import get_logger\nfrom camel.types.unified_model_type import UnifiedModelType\n\nlogger = get_logger(__name__)\n\n\nclass RoleType(Enum):\n ASSISTANT = \"assistant\"\n USER = \"user\"\n CRITIC = \"critic\"\n EMBODIMENT = \"embodiment\"\n DEFAULT = \"default\"\n\n\nclass ModelType(UnifiedModelType, Enum):\n DEFAULT = os.getenv(\"DEFAULT_MODEL_TYPE\", \"gpt-5-mini\")\n\n GPT_3_5_TURBO = \"gpt-3.5-turbo\"\n GPT_4 = \"gpt-4\"\n GPT_4_TURBO = \"gpt-4-turbo\"\n GPT_4O = \"gpt-4o\"\n GPT_4O_MINI = \"gpt-4o-mini\"\n GPT_4_5_PREVIEW = \"gpt-4.5-preview\"\n O1 = \"o1\"\n O1_PREVIEW = \"o1-preview\"\n O1_MINI = \"o1-mini\"\n O3_MINI = \"o3-mini\"\n GPT_4_1 = \"gpt-4.1-2025-04-14\"\n GPT_4_1_MINI = \"gpt-4.1-mini-2025-04-14\"\n GPT_4_1_NANO = \"gpt-4.1-nano-2025-04-14\"\n O4_MINI = \"o4-mini\"\n O3 = \"o3\"\n O3_PRO = \"o3-pro\"\n GPT_5 = \"gpt-5\"\n GPT_5_MINI = \"gpt-5-mini\"\n GPT_5_NANO = \"gpt-5-nano\"\n\n AWS_CLAUDE_3_7_SONNET = \"anthropic.claude-3-7-sonnet-20250219-v1:0\"\n AWS_CLAUDE_3_5_SONNET = \"anthropic.claude-3-5-sonnet-20241022-v2:0\"\n AWS_CLAUDE_3_HAIKU = \"anthropic.claude-3-haiku-20240307-v1:0\"\n AWS_CLAUDE_3_SONNET = \"anthropic.claude-3-sonnet-20240229-v1:0\"\n AWS_DEEPSEEK_R1 = \"us.deepseek.r1-v1:0\"\n AWS_LLAMA_3_3_70B_INSTRUCT = \"us.meta.llama3-3-70b-instruct-v1:0\"\n AWS_LLAMA_3_2_90B_INSTRUCT = \"us.meta.llama3-2-90b-instruct-v1:0\"\n AWS_LLAMA_3_2_11B_INSTRUCT = \"us.meta.llama3-2-11b-instruct-v1:0\"\n AWS_CLAUDE_SONNET_4 = \"anthropic.claude-sonnet-4-20250514-v1:0\"\n AWS_CLAUDE_OPUS_4 = \"anthropic.claude-opus-4-20250514-v1:0\"\n AWS_CLAUDE_OPUS_4_1 = \"anthropic.claude-opus-4-1-20250805-v1:0\"\n\n AMD_GPT4 = \"dvue-aoai-001-gpt-4.1\"\n\n GLM_4 = \"glm-4\"\n GLM_4V = \"glm-4v\"\n GLM_4V_FLASH = \"glm-4v-flash\"\n GLM_4V_PLUS_0111 = \"glm-4v-plus-0111\"\n GLM_4_PLUS = \"glm-4-plus\"\n GLM_4_AIR = \"glm-4-air\"\n GLM_4_AIR_0111 = \"glm-4-air-0111\"\n GLM_4_AIRX = \"glm-4-airx\"\n GLM_4_LONG = \"glm-4-long\"\n GLM_4_FLASHX = \"glm-4-flashx\"\n GLM_4_FLASH = \"glm-4-flash\"\n GLM_ZERO_PREVIEW = \"glm-zero-preview\"\n GLM_3_TURBO = \"glm-3-turbo\"\n\n # Groq platform models\n GROQ_LLAMA_3_1_8B = \"llama-3.1-8b-instant\"\n GROQ_LLAMA_3_3_70B = \"llama-3.3-70b-versatile\"\n GROQ_LLAMA_3_3_70B_PREVIEW = \"llama-3.3-70b-specdec\"\n GROQ_LLAMA_3_8B = \"llama3-8b-8192\"\n GROQ_LLAMA_3_70B = \"llama3-70b-8192\"\n GROQ_MIXTRAL_8_7B = \"mixtral-8x7b-32768\"\n GROQ_GEMMA_2_9B_IT = \"gemma2-9b-it\"\n\n # Nebius AI Studio platform models\n NEBIUS_GPT_OSS_120B = \"gpt-oss-120b\"\n NEBIUS_GPT_OSS_20B = \"gpt-oss-20b\"\n NEBIUS_GLM_4_5 = \"GLM-4.5\"\n NEBIUS_DEEPSEEK_V3 = \"deepseek-ai/DeepSeek-V3\"\n NEBIUS_DEEPSEEK_R1 = \"deepseek-ai/DeepSeek-R1\"\n NEBIUS_LLAMA_3_1_70B = \"meta-llama/Meta-Llama-3.1-70B-Instruct\"\n NEBIUS_MISTRAL_7B_INSTRUCT = \"mistralai/Mistral-7B-Instruct-v0.3\"\n\n # CometAPI platform models\n COMETAPI_GPT_5_CHAT_LATEST = \"gpt-5-chat-latest\"\n COMETAPI_CHATGPT_4O_LATEST = \"chatgpt-4o-latest\"\n COMETAPI_GPT_5_MINI = \"gpt-5-mini\"\n COMETAPI_GPT_5_NANO = \"gpt-5-nano\"\n COMETAPI_GPT_5 = \"gpt-5\"\n COMETAPI_GPT_4_1 = \"gpt-4.1\"\n COMETAPI_GPT_4O_MINI = \"gpt-4o-mini\"\n COMETAPI_O4_MINI_2025_04_16 = \"o4-mini-2025-04-16\"\n COMETAPI_O3_PRO_2025_06_10 = \"o3-pro-2025-06-10\"\n COMETAPI_CLAUDE_OPUS_4_1_20250805 = \"claude-opus-4-1-20250805\"\n COMETAPI_CLAUDE_OPUS_4_1_20250805_THINKING = (\n \"claude-opus-4-1-20250805-thinking\"\n )\n COMETAPI_CLAUDE_SONNET_4_20250514 = \"claude-sonnet-4-20250514\"\n COMETAPI_CLAUDE_SONNET_4_20250514_THINKING = (\n \"claude-sonnet-4-20250514-thinking\"\n )\n COMETAPI_CLAUDE_3_7_SONNET_LATEST = \"claude-3-7-sonnet-latest\"\n COMETAPI_CLAUDE_3_5_HAIKU_LATEST = \"claude-3-5-haiku-latest\"\n COMETAPI_GEMINI_2_5_PRO = \"gemini-2.5-pro\"\n COMETAPI_GEMINI_2_5_FLASH = \"gemini-2.5-flash\"\n COMETAPI_GEMINI_2_5_FLASH_LITE = \"gemini-2.5-flash-lite\"\n COMETAPI_GEMINI_2_0_FLASH = \"gemini-2.0-flash\"\n COMETAPI_GROK_4_0709 = \"grok-4-0709\"\n COMETAPI_GROK_3 = \"grok-3\"\n COMETAPI_GROK_3_MINI = \"grok-3-mini\"\n COMETAPI_GROK_2_IMAGE_1212 = \"grok-2-image-1212\"\n COMETAPI_DEEPSEEK_V3_1 = \"deepseek-v3.1\"\n COMETAPI_DEEPSEEK_V3 = \"deepseek-v3\"\n COMETAPI_DEEPSEEK_R1_0528 = \"deepseek-r1-0528\"\n COMETAPI_DEEPSEEK_CHAT = \"deepseek-chat\"\n COMETAPI_DEEPSEEK_REASONER = \"deepseek-reasoner\"\n COMETAPI_QWEN3_30B_A3B = \"qwen3-30b-a3b\"\n COMETAPI_QWEN3_CODER_PLUS_2025_07_22 = \"qwen3-coder-plus-2025-07-22\"\n\n # OpenRouter models\n OPENROUTER_LLAMA_3_1_405B = \"meta-llama/llama-3.1-405b-instruct\"\n OPENROUTER_LLAMA_3_1_70B = \"meta-llama/llama-3.1-70b-instruct\"\n OPENROUTER_LLAMA_4_MAVERICK = \"meta-llama/llama-4-maverick\"\n OPENROUTER_LLAMA_4_MAVERICK_FREE = \"meta-llama/llama-4-maverick:free\"\n OPENROUTER_LLAMA_4_SCOUT = \"meta-llama/llama-4-scout\"\n OPENROUTER_LLAMA_4_SCOUT_FREE = \"meta-llama/llama-4-scout:free\"\n OPENROUTER_OLYMPICODER_7B = \"open-r1/olympiccoder-7b:free\"\n OPENROUTER_HORIZON_ALPHA = \"openrouter/horizon-alpha\"\n OPENROUTER_GROK_4_FAST = \"x-ai/grok-4-fast\"\n OPENROUTER_GEMINI_2_5_FLASH = \"google/gemini-2.5-flash\"\n OPENROUTER_GPT_4O_MINI = 'openai/gpt-4o-mini'\n OPENROUTER_QWEN_PLUS = 'qwen/qwen-plus'\n OPENROUTER_QWEN_VL_MAX = 'qwen/qwen-vl-max'\n OPENROUTER_o3 = 'openai/o3'\n OPENROUTER_CLAUDE_SONNET_4_5 = 'anthropic/claude-sonnet-4.5'\n \n # LMStudio models\n LMSTUDIO_GEMMA_3_1B = \"gemma-3-1b\"\n LMSTUDIO_GEMMA_3_4B = \"gemma-3-4b\"\n LMSTUDIO_GEMMA_3_12B = \"gemma-3-12b\"\n LMSTUDIO_GEMMA_3_27B = \"gemma-3-27b\"\n\n # TogetherAI platform models support tool calling\n TOGETHER_LLAMA_3_1_8B = \"meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo\"\n TOGETHER_LLAMA_3_1_70B = \"meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo\"\n TOGETHER_LLAMA_3_1_405B = \"meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo\"\n TOGETHER_LLAMA_3_3_70B = \"meta-llama/Llama-3.3-70B-Instruct-Turbo\"\n TOGETHER_MIXTRAL_8_7B = \"mistralai/Mixtral-8x7B-Instruct-v0.1\"\n TOGETHER_MISTRAL_7B = \"mistralai/Mistral-7B-Instruct-v0.1\"\n TOGETHER_LLAMA_4_MAVERICK = (\n \"meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8\"\n )\n TOGETHER_LLAMA_4_SCOUT = \"meta-llama/Llama-4-Scout-17B-16E-Instruct\"\n\n # PPIO platform models support tool calling\n PPIO_DEEPSEEK_PROVER_V2_671B = \"deepseek/deepseek-prover-v2-671b\"\n PPIO_DEEPSEEK_R1_TURBO = \"deepseek/deepseek-r1-turbo\"\n PPIO_DEEPSEEK_V3_TURBO = \"deepseek/deepseek-v3-turbo\"\n PPIO_DEEPSEEK_R1_COMMUNITY = \"deepseek/deepseek-r1/community\"\n PPIO_DEEPSEEK_V3_COMMUNITY = \"deepseek/deepseek-v3/community\"\n PPIO_DEEPSEEK_R1 = \"deepseek/deepseek-r1\"\n PPIO_DEEPSEEK_V3 = \"deepseek/deepseek-v3\"\n PPIO_QWEN_2_5_72B = \"qwen/qwen-2.5-72b-instruct\"\n PPIO_BAICHUAN_2_13B_CHAT = \"baichuan/baichuan2-13b-chat\"\n PPIO_LLAMA_3_3_70B = \"meta-llama/llama-3.3-70b-instruct\"\n PPIO_LLAMA_3_1_70B = \"meta-llama/llama-3.1-70b-instruct\"\n PPIO_YI_1_5_34B_CHAT = \"01-ai/yi-1.5-34b-chat\"\n\n # SambaNova Cloud platform models support tool calling\n SAMBA_LLAMA_3_1_8B = \"Meta-Llama-3.1-8B-Instruct\"\n SAMBA_LLAMA_3_1_70B = \"Meta-Llama-3.1-70B-Instruct\"\n SAMBA_LLAMA_3_1_405B = \"Meta-Llama-3.1-405B-Instruct\"\n\n # SGLang models support tool calling\n SGLANG_LLAMA_3_1_8B = \"meta-llama/Meta-Llama-3.1-8B-Instruct\"\n SGLANG_LLAMA_3_1_70B = \"meta-llama/Meta-Llama-3.1-70B-Instruct\"\n SGLANG_LLAMA_3_1_405B = \"meta-llama/Meta-Llama-3.1-405B-Instruct\"\n SGLANG_LLAMA_3_2_1B = \"meta-llama/Llama-3.2-1B-Instruct\"\n SGLANG_MIXTRAL_NEMO = \"mistralai/Mistral-Nemo-Instruct-2407\"\n SGLANG_MISTRAL_7B = \"mistralai/Mistral-7B-Instruct-v0.3\"\n SGLANG_QWEN_2_5_7B = \"Qwen/Qwen2.5-7B-Instruct\"\n SGLANG_QWEN_2_5_32B = \"Qwen/Qwen2.5-32B-Instruct\"\n SGLANG_QWEN_2_5_72B = \"Qwen/Qwen2.5-72B-Instruct\"\n\n STUB = \"stub\"\n\n # Legacy anthropic models\n # NOTE: anthropic legacy models only Claude 2.1 has system prompt support\n CLAUDE_2_1 = \"claude-2.1\"\n CLAUDE_2_0 = \"claude-2.0\"\n CLAUDE_INSTANT_1_2 = \"claude-instant-1.2\"\n\n # Claude models\n CLAUDE_3_OPUS = \"claude-3-opus-latest\"\n CLAUDE_3_SONNET = \"claude-3-sonnet-20240229\"\n CLAUDE_3_HAIKU = \"claude-3-haiku-20240307\"\n CLAUDE_3_5_SONNET = \"claude-3-5-sonnet-latest\"\n CLAUDE_3_5_HAIKU = \"claude-3-5-haiku-latest\"\n CLAUDE_3_7_SONNET = \"claude-3-7-sonnet-latest\"\n CLAUDE_SONNET_4 = \"claude-sonnet-4-20250514\"\n CLAUDE_OPUS_4 = \"claude-opus-4-20250514\"\n CLAUDE_OPUS_4_1 = \"claude-opus-4-1-20250805\"\n\n # Netmind models\n NETMIND_LLAMA_4_MAVERICK_17B_128E_INSTRUCT = (\n \"meta-llama/Llama-4-Maverick-17B-128E-Instruct\"\n )\n NETMIND_LLAMA_4_SCOUT_17B_16E_INSTRUCT = (\n \"meta-llama/Llama-4-Scout-17B-16E-Instruct\"\n )\n NETMIND_DEEPSEEK_R1 = \"deepseek-ai/DeepSeek-R1\"\n NETMIND_DEEPSEEK_V3 = \"deepseek-ai/DeepSeek-V3-0324\"\n NETMIND_DOUBAO_1_5_PRO = \"doubao/Doubao-1.5-pro\"\n NETMIND_QWQ_32B = \"Qwen/QwQ-32B\"\n\n # Nvidia models\n NVIDIA_NEMOTRON_340B_INSTRUCT = \"nvidia/nemotron-4-340b-instruct\"\n NVIDIA_NEMOTRON_340B_REWARD = \"nvidia/nemotron-4-340b-reward\"\n NVIDIA_YI_LARGE = \"01-ai/yi-large\"\n NVIDIA_MISTRAL_LARGE = \"mistralai/mistral-large\"\n NVIDIA_MIXTRAL_8X7B = \"mistralai/mixtral-8x7b-instruct\"\n NVIDIA_LLAMA3_70B = \"meta/llama3-70b\"\n NVIDIA_LLAMA3_1_8B_INSTRUCT = \"meta/llama-3.1-8b-instruct\"\n NVIDIA_LLAMA3_1_70B_INSTRUCT = \"meta/llama-3.1-70b-instruct\"\n NVIDIA_LLAMA3_1_405B_INSTRUCT = \"meta/llama-3.1-405b-instruct\"\n NVIDIA_LLAMA3_2_1B_INSTRUCT = \"meta/llama-3.2-1b-instruct\"\n NVIDIA_LLAMA3_2_3B_INSTRUCT = \"meta/llama-3.2-3b-instruct\"\n NVIDIA_LLAMA3_3_70B_INSTRUCT = \"meta/llama-3.3-70b-instruct\"\n\n # Gemini models\n GEMINI_2_5_FLASH = \"gemini-2.5-flash\"\n GEMINI_2_5_PRO = \"gemini-2.5-pro\"\n GEMINI_2_0_FLASH = \"gemini-2.0-flash\"\n GEMINI_2_0_FLASH_EXP = \"gemini-2.0-flash-exp\"\n GEMINI_2_0_FLASH_THINKING = \"gemini-2.0-flash-thinking-exp\"\n GEMINI_2_0_PRO_EXP = \"gemini-2.0-pro-exp-02-05\"\n GEMINI_2_0_FLASH_LITE = \"gemini-2.0-flash-lite\"\n GEMINI_2_0_FLASH_LITE_PREVIEW = \"gemini-2.0-flash-lite-preview-02-05\"\n GEMINI_1_5_FLASH = \"gemini-1.5-flash\"\n GEMINI_1_5_PRO = \"gemini-1.5-pro\"\n\n # Mistral AI models\n MISTRAL_3B = \"ministral-3b-latest\"\n MISTRAL_7B = \"open-mistral-7b\"\n MISTRAL_8B = \"ministral-8b-latest\"\n MISTRAL_CODESTRAL = \"codestral-latest\"\n MISTRAL_CODESTRAL_MAMBA = \"open-codestral-mamba\"\n MISTRAL_LARGE = \"mistral-large-latest\"\n MISTRAL_MIXTRAL_8x7B = \"open-mixtral-8x7b\"\n MISTRAL_MIXTRAL_8x22B = \"open-mixtral-8x22b\"\n MISTRAL_NEMO = \"open-mistral-nemo\"\n MISTRAL_PIXTRAL_12B = \"pixtral-12b-2409\"\n MISTRAL_MEDIUM_3_1 = \"mistral-medium-2508\"\n MISTRAL_SMALL_3_2 = \"mistral-small-2506\"\n MAGISTRAL_SMALL_1_2 = \"magistral-small-1.2\"\n MAGISTRAL_MEDIUM_1_2 = \"magistral-medium-1.2\"\n\n # Reka models\n REKA_CORE = \"reka-core\"\n REKA_FLASH = \"reka-flash\"\n REKA_EDGE = \"reka-edge\"\n\n # Cohere models\n COHERE_COMMAND_R_PLUS = \"command-r-plus\"\n COHERE_COMMAND_R = \"command-r\"\n COHERE_COMMAND_LIGHT = \"command-light\"\n COHERE_COMMAND = \"command\"\n COHERE_COMMAND_NIGHTLY = \"command-nightly\"\n\n # Qwen models (Aliyun)\n QWEN_MAX = \"qwen-max\"\n QWEN_PLUS = \"qwen-plus\"\n QWEN_TURBO = \"qwen-turbo\"\n QWEN_PLUS_LATEST = \"qwen-plus-latest\"\n QWEN_PLUS_2025_04_28 = \"qwen-plus-2025-04-28\"\n QWEN_TURBO_LATEST = \"qwen-turbo-latest\"\n QWEN_TURBO_2025_04_28 = \"qwen-turbo-2025-04-28\"\n QWEN_LONG = \"qwen-long\"\n QWEN_VL_MAX = \"qwen-vl-max\"\n QWEN_VL_PLUS = \"qwen-vl-plus\"\n QWEN_MATH_PLUS = \"qwen-math-plus\"\n QWEN_MATH_TURBO = \"qwen-math-turbo\"\n QWEN_CODER_TURBO = \"qwen-coder-turbo\"\n QWEN_2_5_CODER_32B = \"qwen2.5-coder-32b-instruct\"\n QWEN_2_5_VL_72B = \"qwen2.5-vl-72b-instruct\"\n QWEN_2_5_72B = \"qwen2.5-72b-instruct\"\n QWEN_2_5_32B = \"qwen2.5-32b-instruct\"\n QWEN_2_5_14B = \"qwen2.5-14b-instruct\"\n QWEN_QWQ_32B = \"qwq-32b-preview\"\n QWEN_QVQ_72B = \"qvq-72b-preview\"\n QWEN_QWQ_PLUS = \"qwq-plus\"\n QWEN_3_CODER_PLUS = \"qwen3-coder-plus\"\n\n # Yi models (01-ai)\n YI_LIGHTNING = \"yi-lightning\"\n YI_LARGE = \"yi-large\"\n YI_MEDIUM = \"yi-medium\"\n YI_LARGE_TURBO = \"yi-large-turbo\"\n YI_VISION = \"yi-vision\"\n YI_MEDIUM_200K = \"yi-medium-200k\"\n YI_SPARK = \"yi-spark\"\n YI_LARGE_RAG = \"yi-large-rag\"\n YI_LARGE_FC = \"yi-large-fc\"\n\n # DeepSeek models\n DEEPSEEK_CHAT = \"deepseek-chat\"\n DEEPSEEK_REASONER = \"deepseek-reasoner\"\n # InternLM models\n INTERNLM3_LATEST = \"internlm3-latest\"\n INTERNLM3_8B_INSTRUCT = \"internlm3-8b-instruct\"\n INTERNLM2_5_LATEST = \"internlm2.5-latest\"\n INTERNLM2_PRO_CHAT = \"internlm2-pro-chat\"\n\n # Moonshot models\n MOONSHOT_V1_8K = \"moonshot-v1-8k\"\n MOONSHOT_V1_32K = \"moonshot-v1-32k\"\n MOONSHOT_V1_128K = \"moonshot-v1-128k\"\n MOONSHOT_KIMI_K2 = \"kimi-k2-0711-preview\"\n\n # SiliconFlow models support tool calling\n SILICONFLOW_DEEPSEEK_V2_5 = \"deepseek-ai/DeepSeek-V2.5\"\n SILICONFLOW_DEEPSEEK_V3 = \"deepseek-ai/DeepSeek-V3\"\n SILICONFLOW_INTERN_LM2_5_20B_CHAT = \"internlm/internlm2_5-20b-chat\"\n SILICONFLOW_INTERN_LM2_5_7B_CHAT = \"internlm/internlm2_5-7b-chat\"\n SILICONFLOW_PRO_INTERN_LM2_5_7B_CHAT = \"Pro/internlm/internlm2_5-7b-chat\"\n SILICONFLOW_QWEN2_5_72B_INSTRUCT = \"Qwen/Qwen2.5-72B-Instruct\"\n SILICONFLOW_QWEN2_5_32B_INSTRUCT = \"Qwen/Qwen2.5-32B-Instruct\"\n SILICONFLOW_QWEN2_5_14B_INSTRUCT = \"Qwen/Qwen2.5-14B-Instruct\"\n SILICONFLOW_QWEN2_5_7B_INSTRUCT = \"Qwen/Qwen2.5-7B-Instruct\"\n SILICONFLOW_PRO_QWEN2_5_7B_INSTRUCT = \"Pro/Qwen/Qwen2.5-7B-Instruct\"\n SILICONFLOW_THUDM_GLM_4_9B_CHAT = \"THUDM/glm-4-9b-chat\"\n SILICONFLOW_PRO_THUDM_GLM_4_9B_CHAT = \"Pro/THUDM/glm-4-9b-chat\"\n\n # AIML models support tool calling\n AIML_MIXTRAL_8X7B = \"mistralai/Mixtral-8x7B-Instruct-v0.1\"\n AIML_MISTRAL_7B_INSTRUCT = \"mistralai/Mistral-7B-Instruct-v0.1\"\n\n # Novita platform models support tool calling\n NOVITA_LLAMA_4_MAVERICK_17B = (\n \"meta-llama/llama-4-maverick-17b-128e-instruct-fp8\"\n )\n NOVITA_LLAMA_4_SCOUT_17B = \"meta-llama/llama-4-scout-17b-16e-instruct\"\n NOVITA_DEEPSEEK_V3_0324 = \"deepseek/deepseek-v3-0324\"\n NOVITA_QWEN_2_5_V1_72B = \"qwen/qwen2.5-vl-72b-instruct\"\n NOVITA_DEEPSEEK_V3_TURBO = \"deepseek/deepseek-v3-turbo\"\n NOVITA_DEEPSEEK_R1_TURBO = \"deepseek/deepseek-r1-turbo\"\n NOVITA_GEMMA_3_27B_IT = \"google/gemma-3-27b-it\"\n NOVITA_QWEN_32B = \"qwen/qwq-32b\"\n NOVITA_L3_8B_STHENO_V3_2 = \"Sao10K/L3-8B-Stheno-v3.2\"\n NOVITA_MYTHOMAX_L2_13B = \"gryphe/mythomax-l2-13b\"\n NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_8B = (\n \"deepseek/deepseek-r1-distill-llama-8b\"\n )\n NOVITA_DEEPSEEK_V3 = \"deepseek/deepseek_v3\"\n NOVITA_LLAMA_3_1_8B = \"meta-llama/llama-3.1-8b-instruct\"\n NOVITA_DEEPSEEK_R1_DISTILL_QWEN_14B = (\n \"deepseek/deepseek-r1-distill-qwen-14b\"\n )\n NOVITA_LLAMA_3_3_70B = \"meta-llama/llama-3.3-70b-instruct\"\n NOVITA_QWEN_2_5_72B = \"qwen/qwen-2.5-72b-instruct\"\n NOVITA_MISTRAL_NEMO = \"mistralai/mistral-nemo\"\n NOVITA_DEEPSEEK_R1_DISTILL_QWEN_32B = (\n \"deepseek/deepseek-r1-distill-qwen-32b\"\n )\n NOVITA_LLAMA_3_8B = \"meta-llama/llama-3-8b-instruct\"\n NOVITA_WIZARDLM_2_8X22B = \"microsoft/wizardlm-2-8x22b\"\n NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_70B = (\n \"deepseek/deepseek-r1-distill-llama-70b\"\n )\n NOVITA_LLAMA_3_1_70B = \"meta-llama/llama-3.1-70b-instruct\"\n NOVITA_GEMMA_2_9B_IT = \"google/gemma-2-9b-it\"\n NOVITA_MISTRAL_7B = \"mistralai/mistral-7b-instruct\"\n NOVITA_LLAMA_3_70B = \"meta-llama/llama-3-70b-instruct\"\n NOVITA_DEEPSEEK_R1 = \"deepseek/deepseek-r1\"\n NOVITA_HERMES_2_PRO_LLAMA_3_8B = \"nousresearch/hermes-2-pro-llama-3-8b\"\n NOVITA_L3_70B_EURYALE_V2_1 = \"sao10k/l3-70b-euryale-v2.1\"\n NOVITA_DOLPHIN_MIXTRAL_8X22B = (\n \"cognitivecomputations/dolphin-mixtral-8x22b\"\n )\n NOVITA_AIROBOROS_L2_70B = \"jondurbin/airoboros-l2-70b\"\n NOVITA_MIDNIGHT_ROSE_70B = \"sophosympatheia/midnight-rose-70b\"\n NOVITA_L3_8B_LUNARIS = \"sao10k/l3-8b-lunaris\"\n NOVITA_GLM_4_9B_0414 = \"thudm/glm-4-9b-0414\"\n NOVITA_GLM_Z1_9B_0414 = \"thudm/glm-z1-9b-0414\"\n NOVITA_GLM_Z1_32B_0414 = \"thudm/glm-z1-32b-0414\"\n NOVITA_GLM_4_32B_0414 = \"thudm/glm-4-32b-0414\"\n NOVITA_GLM_Z1_RUMINATION_32B_0414 = \"thudm/glm-z1-rumination-32b-0414\"\n NOVITA_QWEN_2_5_7B = \"qwen/qwen2.5-7b-instruct\"\n NOVITA_LLAMA_3_2_1B = \"meta-llama/llama-3.2-1b-instruct\"\n NOVITA_LLAMA_3_2_11B_VISION = \"meta-llama/llama-3.2-11b-vision-instruct\"\n NOVITA_LLAMA_3_2_3B = \"meta-llama/llama-3.2-3b-instruct\"\n NOVITA_LLAMA_3_1_8B_BF16 = \"meta-llama/llama-3.1-8b-instruct-bf16\"\n NOVITA_L31_70B_EURYALE_V2_2 = \"sao10k/l31-70b-euryale-v2.2\"\n\n # ModelScope models support tool calling\n MODELSCOPE_QWEN_2_5_7B_INSTRUCT = \"Qwen/Qwen2.5-7B-Instruct\"\n MODELSCOPE_QWEN_2_5_14B_INSTRUCT = \"Qwen/Qwen2.5-14B-Instruct\"\n MODELSCOPE_QWEN_2_5_32B_INSTRUCT = \"Qwen/Qwen2.5-32B-Instruct\"\n MODELSCOPE_QWEN_2_5_72B_INSTRUCT = \"Qwen/Qwen2.5-72B-Instruct\"\n MODELSCOPE_QWEN_2_5_CODER_7B_INSTRUCT = \"Qwen/Qwen2.5-Coder-7B-Instruct\"\n MODELSCOPE_QWEN_2_5_CODER_14B_INSTRUCT = \"Qwen/Qwen2.5-Coder-14B-Instruct\"\n MODELSCOPE_QWEN_2_5_CODER_32B_INSTRUCT = \"Qwen/Qwen2.5-Coder-32B-Instruct\"\n MODELSCOPE_QWEN_3_235B_A22B = \"Qwen/Qwen3-235B-A22B\"\n MODELSCOPE_QWEN_3_32B = \"Qwen/Qwen3-32B\"\n MODELSCOPE_QWQ_32B = \"Qwen/QwQ-32B\"\n MODELSCOPE_QWQ_32B_PREVIEW = \"Qwen/QwQ-32B-Preview\"\n MODELSCOPE_LLAMA_3_1_8B_INSTRUCT = (\n \"LLM-Research/Meta-Llama-3.1-8B-Instruct\"\n )\n MODELSCOPE_LLAMA_3_1_70B_INSTRUCT = (\n \"LLM-Research/Meta-Llama-3.1-70B-Instruct\"\n )\n MODELSCOPE_LLAMA_3_1_405B_INSTRUCT = (\n \"LLM-Research/Meta-Llama-3.1-405B-Instruct\"\n )\n MODELSCOPE_LLAMA_3_3_70B_INSTRUCT = \"LLM-Research/Llama-3.3-70B-Instruct\"\n MODELSCOPE_MINISTRAL_8B_INSTRUCT = \"mistralai/Ministral-8B-Instruct-2410\"\n MODELSCOPE_DEEPSEEK_V3_0324 = \"deepseek-ai/DeepSeek-V3-0324\"\n\n # WatsonX models\n WATSONX_GRANITE_3_8B_INSTRUCT = \"ibm/granite-3-8b-instruct\"\n WATSONX_LLAMA_3_3_70B_INSTRUCT = \"meta-llama/llama-3-3-70b-instruct\"\n WATSONX_LLAMA_3_2_1B_INSTRUCT = \"meta-llama/llama-3-2-1b-instruct\"\n WATSONX_LLAMA_3_2_3B_INSTRUCT = \"meta-llama/llama-3-2-3b-instruct\"\n WATSONX_LLAMA_3_2_11B_VISION_INSTRUCT = (\n \"meta-llama/llama-3-2-11b-vision-instruct\"\n )\n WATSONX_LLAMA_3_2_90B_VISION_INSTRUCT = (\n \"meta-llama/llama-3-2-90b-vision-instruct\"\n )\n WATSONX_LLAMA_GUARD_3_11B_VISION_INSTRUCT = (\n \"meta-llama/llama-guard-3-11b-vision-instruct\"\n )\n WATSONX_MISTRAL_LARGE = \"mistralai/mistral-large\"\n\n # Qianfan models\n ERNIE_X1_TURBO_32K = \"ernie-x1-turbo-32k\"\n ERNIE_X1_32K = \"ernie-x1-32k\"\n ERNIE_X1_32K_PREVIEW = \"ernie-x1-32k-preview\"\n ERNIE_4_5_TURBO_128K = \"ernie-4.5-turbo-128k\"\n ERNIE_4_5_TURBO_32K = \"ernie-4.5-turbo-32k\"\n DEEPSEEK_V3 = \"deepseek-v3\"\n DEEPSEEK_R1 = \"deepseek-r1\"\n QWEN3_235B_A22B = \"qwen3-235b-a22b\"\n\n # Crynux models\n CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_1_5B = (\n \"deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B\"\n )\n CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_7B = (\n \"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\"\n )\n CRYNUX_DEEPSEEK_R1_DISTILL_LLAMA_8B = (\n \"deepseek-ai/DeepSeek-R1-Distill-Llama-8B\"\n )\n\n CRYNUX_QWEN_3_4_B = \"Qwen/Qwen3-4B\"\n CRYNUX_QWEN_3_8_B = \"Qwen/Qwen3-8B\"\n CRYNUX_QWEN_2_5_7B = \"Qwen/Qwen2.5-7B\"\n CRYNUX_QWEN_2_5_7B_INSTRUCT = \"Qwen/Qwen2.5-7B-Instruct\"\n\n CRYNUX_NOUS_HERMES_3_LLAMA_3_1_8B = \"NousResearch/Hermes-3-Llama-3.1-8B\"\n CRYNUX_NOUS_HERMES_3_LLAMA_3_2_3B = \"NousResearch/Hermes-3-Llama-3.2-3B\"\n\n def __str__(self):\n return self.value\n\n def __repr__(self):\n return self.value\n\n def __new__(cls, value: Union[\"ModelType\", str]) -> \"ModelType\":\n return cast(\"ModelType\", UnifiedModelType.__new__(cls, value))\n\n @classmethod\n def from_name(cls, name: str) -> \"ModelType\":\n r\"\"\"Returns the ModelType enum value from a string.\"\"\"\n for model_type in cls:\n if model_type.value == name:\n return model_type\n raise ValueError(f\"Unknown ModelType name: {name}\")\n\n @property\n def value_for_tiktoken(self) -> str:\n if self.is_openai:\n return self.value\n return \"gpt-4o-mini\"\n\n @property\n def support_native_structured_output(self) -> bool:\n return any(\n [\n self.is_openai,\n ]\n )\n\n @property\n def support_native_tool_calling(self) -> bool:\n return any(\n [\n self.is_openai,\n self.is_gemini,\n self.is_mistral,\n self.is_qwen,\n self.is_deepseek,\n self.is_ppio,\n self.is_cohere,\n self.is_internlm,\n self.is_together,\n self.is_sambanova,\n self.is_groq,\n self.is_openrouter,\n self.is_lmstudio,\n self.is_sglang,\n self.is_moonshot,\n self.is_siliconflow,\n self.is_modelscope,\n self.is_zhipuai,\n self.is_aiml,\n self.is_azure_openai,\n self.is_novita,\n ]\n )\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this type of models is an OpenAI-released model.\"\"\"\n return self in {\n ModelType.GPT_3_5_TURBO,\n ModelType.GPT_4,\n ModelType.GPT_4_TURBO,\n ModelType.GPT_4O,\n ModelType.GPT_4O_MINI,\n ModelType.O1,\n ModelType.O1_PREVIEW,\n ModelType.O1_MINI,\n ModelType.O3_PRO,\n ModelType.O3_MINI,\n ModelType.GPT_4_5_PREVIEW,\n ModelType.GPT_4_1,\n ModelType.GPT_4_1_MINI,\n ModelType.GPT_4_1_NANO,\n ModelType.GPT_5,\n ModelType.GPT_5_MINI,\n ModelType.GPT_5_NANO,\n ModelType.O4_MINI,\n ModelType.O3,\n }\n\n @property\n def is_amd(self) -> bool:\n r\"\"\"Returns whether this type of models is a AMD model.\"\"\"\n return self in {\n ModelType.AMD_GPT4,\n }\n\n @property\n def is_aws_bedrock(self) -> bool:\n r\"\"\"Returns whether this type of models is an AWS Bedrock model.\"\"\"\n return self in {\n ModelType.AWS_CLAUDE_3_7_SONNET,\n ModelType.AWS_CLAUDE_3_5_SONNET,\n ModelType.AWS_CLAUDE_3_HAIKU,\n ModelType.AWS_CLAUDE_3_SONNET,\n ModelType.AWS_DEEPSEEK_R1,\n ModelType.AWS_LLAMA_3_3_70B_INSTRUCT,\n ModelType.AWS_LLAMA_3_2_90B_INSTRUCT,\n ModelType.AWS_LLAMA_3_2_11B_INSTRUCT,\n ModelType.AWS_CLAUDE_SONNET_4,\n ModelType.AWS_CLAUDE_OPUS_4,\n ModelType.AWS_CLAUDE_OPUS_4_1,\n }\n\n @property\n def is_azure_openai(self) -> bool:\n r\"\"\"Returns whether this type of models is an OpenAI-released model\n from Azure.\n \"\"\"\n return self in {\n ModelType.GPT_3_5_TURBO,\n ModelType.GPT_4,\n ModelType.GPT_4_TURBO,\n ModelType.GPT_4O,\n ModelType.GPT_4O_MINI,\n ModelType.O1,\n ModelType.O1_PREVIEW,\n ModelType.O1_MINI,\n ModelType.O3_MINI,\n ModelType.O3_PRO,\n ModelType.GPT_4_5_PREVIEW,\n ModelType.GPT_4_1,\n ModelType.GPT_4_1_MINI,\n ModelType.GPT_4_1_NANO,\n ModelType.GPT_5,\n ModelType.O4_MINI,\n ModelType.O3,\n }\n\n @property\n def is_zhipuai(self) -> bool:\n r\"\"\"Returns whether this type of models is an ZhipuAI model.\"\"\"\n return self in {\n ModelType.GLM_3_TURBO,\n ModelType.GLM_4,\n ModelType.GLM_4V,\n ModelType.GLM_4V_FLASH,\n ModelType.GLM_4V_PLUS_0111,\n ModelType.GLM_4_PLUS,\n ModelType.GLM_4_AIR,\n ModelType.GLM_4_AIR_0111,\n ModelType.GLM_4_AIRX,\n ModelType.GLM_4_LONG,\n ModelType.GLM_4_FLASHX,\n ModelType.GLM_4_FLASH,\n ModelType.GLM_ZERO_PREVIEW,\n }\n\n @property\n def is_anthropic(self) -> bool:\n r\"\"\"Returns whether this type of models is Anthropic-released model.\n\n Returns:\n bool: Whether this type of models is anthropic.\n \"\"\"\n return self in {\n ModelType.CLAUDE_INSTANT_1_2,\n ModelType.CLAUDE_2_0,\n ModelType.CLAUDE_2_1,\n ModelType.CLAUDE_3_OPUS,\n ModelType.CLAUDE_3_SONNET,\n ModelType.CLAUDE_3_HAIKU,\n ModelType.CLAUDE_3_5_SONNET,\n ModelType.CLAUDE_3_5_HAIKU,\n ModelType.CLAUDE_3_7_SONNET,\n ModelType.CLAUDE_SONNET_4,\n ModelType.CLAUDE_OPUS_4,\n ModelType.CLAUDE_OPUS_4_1,\n }\n\n @property\n def is_groq(self) -> bool:\n r\"\"\"Returns whether this type of models is served by Groq.\"\"\"\n return self in {\n ModelType.GROQ_LLAMA_3_1_8B,\n ModelType.GROQ_LLAMA_3_3_70B,\n ModelType.GROQ_LLAMA_3_3_70B_PREVIEW,\n ModelType.GROQ_LLAMA_3_8B,\n ModelType.GROQ_LLAMA_3_70B,\n ModelType.GROQ_MIXTRAL_8_7B,\n ModelType.GROQ_GEMMA_2_9B_IT,\n }\n\n @property\n def is_nebius(self) -> bool:\n r\"\"\"Returns whether this type of models is served by Nebius AI\n Studio.\"\"\"\n return self in {\n ModelType.NEBIUS_GPT_OSS_120B,\n ModelType.NEBIUS_GPT_OSS_20B,\n ModelType.NEBIUS_GLM_4_5,\n ModelType.NEBIUS_DEEPSEEK_V3,\n ModelType.NEBIUS_DEEPSEEK_R1,\n ModelType.NEBIUS_LLAMA_3_1_70B,\n ModelType.NEBIUS_MISTRAL_7B_INSTRUCT,\n }\n\n @property\n def is_cometapi(self) -> bool:\n r\"\"\"Returns whether this type of models is served by CometAPI.\"\"\"\n return self in {\n ModelType.COMETAPI_GPT_5_CHAT_LATEST,\n ModelType.COMETAPI_CHATGPT_4O_LATEST,\n ModelType.COMETAPI_GPT_5_MINI,\n ModelType.COMETAPI_GPT_5_NANO,\n ModelType.COMETAPI_GPT_5,\n ModelType.COMETAPI_GPT_4_1,\n ModelType.COMETAPI_GPT_4O_MINI,\n ModelType.COMETAPI_O4_MINI_2025_04_16,\n ModelType.COMETAPI_O3_PRO_2025_06_10,\n ModelType.COMETAPI_CLAUDE_OPUS_4_1_20250805,\n ModelType.COMETAPI_CLAUDE_OPUS_4_1_20250805_THINKING,\n ModelType.COMETAPI_CLAUDE_SONNET_4_20250514,\n ModelType.COMETAPI_CLAUDE_SONNET_4_20250514_THINKING,\n ModelType.COMETAPI_CLAUDE_3_7_SONNET_LATEST,\n ModelType.COMETAPI_CLAUDE_3_5_HAIKU_LATEST,\n ModelType.COMETAPI_GEMINI_2_5_PRO,\n ModelType.COMETAPI_GEMINI_2_5_FLASH,\n ModelType.COMETAPI_GEMINI_2_5_FLASH_LITE,\n ModelType.COMETAPI_GEMINI_2_0_FLASH,\n ModelType.COMETAPI_GROK_4_0709,\n ModelType.COMETAPI_GROK_3,\n ModelType.COMETAPI_GROK_3_MINI,\n ModelType.COMETAPI_GROK_2_IMAGE_1212,\n ModelType.COMETAPI_DEEPSEEK_V3_1,\n ModelType.COMETAPI_DEEPSEEK_V3,\n ModelType.COMETAPI_DEEPSEEK_R1_0528,\n ModelType.COMETAPI_DEEPSEEK_CHAT,\n ModelType.COMETAPI_DEEPSEEK_REASONER,\n ModelType.COMETAPI_QWEN3_30B_A3B,\n ModelType.COMETAPI_QWEN3_CODER_PLUS_2025_07_22,\n }\n\n @property\n def is_openrouter(self) -> bool:\n r\"\"\"Returns whether this type of models is served by OpenRouter.\"\"\"\n return self in {\n ModelType.OPENROUTER_LLAMA_3_1_405B,\n ModelType.OPENROUTER_LLAMA_3_1_70B,\n ModelType.OPENROUTER_LLAMA_4_MAVERICK,\n ModelType.OPENROUTER_LLAMA_4_MAVERICK_FREE,\n ModelType.OPENROUTER_LLAMA_4_SCOUT,\n ModelType.OPENROUTER_LLAMA_4_SCOUT_FREE,\n ModelType.OPENROUTER_OLYMPICODER_7B,\n ModelType.OPENROUTER_HORIZON_ALPHA,\n ModelType.OPENROUTER_GROK_4_FAST,\n ModelType.OPENROUTER_GEMINI_2_5_FLASH,\n ModelType.OPENROUTER_GPT_4O_MINI,\n ModelType.OPENROUTER_QWEN_PLUS,\n ModelType.OPENROUTER_QWEN_VL_MAX,\n ModelType.OPENROUTER_o3,\n ModelType.OPENROUTER_CLAUDE_SONNET_4_5\n }\n\n @property\n def is_lmstudio(self) -> bool:\n r\"\"\"Returns whether this type of models is served by LMStudio.\"\"\"\n return self in {\n ModelType.LMSTUDIO_GEMMA_3_1B,\n ModelType.LMSTUDIO_GEMMA_3_4B,\n ModelType.LMSTUDIO_GEMMA_3_12B,\n ModelType.LMSTUDIO_GEMMA_3_27B,\n }\n\n @property\n def is_together(self) -> bool:\n r\"\"\"Returns whether this type of models is served by Together AI.\"\"\"\n return self in {\n ModelType.TOGETHER_LLAMA_3_1_405B,\n ModelType.TOGETHER_LLAMA_3_1_70B,\n ModelType.TOGETHER_LLAMA_3_3_70B,\n ModelType.TOGETHER_LLAMA_3_3_70B,\n ModelType.TOGETHER_MISTRAL_7B,\n ModelType.TOGETHER_MIXTRAL_8_7B,\n }\n\n @property\n def is_sambanova(self) -> bool:\n r\"\"\"Returns whether this type of model is served by SambaNova AI.\"\"\"\n return self in {\n ModelType.SAMBA_LLAMA_3_1_8B,\n ModelType.SAMBA_LLAMA_3_1_70B,\n ModelType.SAMBA_LLAMA_3_1_405B,\n }\n\n @property\n def is_mistral(self) -> bool:\n r\"\"\"Returns whether this type of models is served by Mistral.\"\"\"\n return self in {\n ModelType.MISTRAL_LARGE,\n ModelType.MISTRAL_NEMO,\n ModelType.MISTRAL_CODESTRAL,\n ModelType.MISTRAL_7B,\n ModelType.MISTRAL_MIXTRAL_8x7B,\n ModelType.MISTRAL_MIXTRAL_8x22B,\n ModelType.MISTRAL_CODESTRAL_MAMBA,\n ModelType.MISTRAL_PIXTRAL_12B,\n ModelType.MISTRAL_8B,\n ModelType.MISTRAL_3B,\n ModelType.MISTRAL_MEDIUM_3_1,\n ModelType.MISTRAL_SMALL_3_2,\n ModelType.MAGISTRAL_SMALL_1_2,\n ModelType.MAGISTRAL_MEDIUM_1_2,\n }\n\n @property\n def is_nvidia(self) -> bool:\n r\"\"\"Returns whether this type of models is a NVIDIA model.\"\"\"\n return self in {\n ModelType.NVIDIA_NEMOTRON_340B_INSTRUCT,\n ModelType.NVIDIA_NEMOTRON_340B_REWARD,\n ModelType.NVIDIA_YI_LARGE,\n ModelType.NVIDIA_MISTRAL_LARGE,\n ModelType.NVIDIA_LLAMA3_70B,\n ModelType.NVIDIA_MIXTRAL_8X7B,\n ModelType.NVIDIA_LLAMA3_1_8B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_1_70B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_1_405B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_2_1B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_2_3B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_3_70B_INSTRUCT,\n }\n\n @property\n def is_gemini(self) -> bool:\n r\"\"\"Returns whether this type of models is Gemini model.\n\n Returns:\n bool: Whether this type of models is gemini.\n \"\"\"\n return self in {\n ModelType.GEMINI_2_5_FLASH,\n ModelType.GEMINI_2_5_PRO,\n ModelType.GEMINI_2_0_FLASH,\n ModelType.GEMINI_2_0_FLASH_EXP,\n ModelType.GEMINI_2_0_FLASH_THINKING,\n ModelType.GEMINI_2_0_PRO_EXP,\n ModelType.GEMINI_2_0_FLASH_LITE,\n ModelType.GEMINI_2_0_FLASH_LITE_PREVIEW,\n ModelType.GEMINI_1_5_FLASH,\n ModelType.GEMINI_1_5_PRO,\n }\n\n @property\n def is_reka(self) -> bool:\n r\"\"\"Returns whether this type of models is Reka model.\n\n Returns:\n bool: Whether this type of models is Reka.\n \"\"\"\n return self in {\n ModelType.REKA_CORE,\n ModelType.REKA_EDGE,\n ModelType.REKA_FLASH,\n }\n\n @property\n def is_cohere(self) -> bool:\n r\"\"\"Returns whether this type of models is a Cohere model.\n\n Returns:\n bool: Whether this type of models is Cohere.\n \"\"\"\n return self in {\n ModelType.COHERE_COMMAND_R_PLUS,\n ModelType.COHERE_COMMAND_R,\n ModelType.COHERE_COMMAND_LIGHT,\n ModelType.COHERE_COMMAND,\n ModelType.COHERE_COMMAND_NIGHTLY,\n }\n\n @property\n def is_yi(self) -> bool:\n r\"\"\"Returns whether this type of models is Yi model.\n\n Returns:\n bool: Whether this type of models is Yi.\n \"\"\"\n return self in {\n ModelType.YI_LIGHTNING,\n ModelType.YI_LARGE,\n ModelType.YI_MEDIUM,\n ModelType.YI_LARGE_TURBO,\n ModelType.YI_VISION,\n ModelType.YI_MEDIUM_200K,\n ModelType.YI_SPARK,\n ModelType.YI_LARGE_RAG,\n ModelType.YI_LARGE_FC,\n }\n\n @property\n def is_qwen(self) -> bool:\n return self in {\n ModelType.QWEN_MAX,\n ModelType.QWEN_PLUS,\n ModelType.QWEN_TURBO,\n ModelType.QWEN_LONG,\n ModelType.QWEN_VL_MAX,\n ModelType.QWEN_VL_PLUS,\n ModelType.QWEN_MATH_PLUS,\n ModelType.QWEN_MATH_TURBO,\n ModelType.QWEN_CODER_TURBO,\n ModelType.QWEN_2_5_CODER_32B,\n ModelType.QWEN_2_5_VL_72B,\n ModelType.QWEN_2_5_72B,\n ModelType.QWEN_2_5_32B,\n ModelType.QWEN_2_5_14B,\n ModelType.QWEN_QWQ_32B,\n ModelType.QWEN_QVQ_72B,\n ModelType.QWEN_QWQ_PLUS,\n ModelType.QWEN_PLUS_LATEST,\n ModelType.QWEN_PLUS_2025_04_28,\n ModelType.QWEN_TURBO_LATEST,\n ModelType.QWEN_TURBO_2025_04_28,\n ModelType.QWEN_3_CODER_PLUS,\n }\n\n @property\n def is_deepseek(self) -> bool:\n return self in {\n ModelType.DEEPSEEK_CHAT,\n ModelType.DEEPSEEK_REASONER,\n }\n\n @property\n def is_netmind(self) -> bool:\n return self in {\n ModelType.NETMIND_LLAMA_4_MAVERICK_17B_128E_INSTRUCT,\n ModelType.NETMIND_LLAMA_4_SCOUT_17B_16E_INSTRUCT,\n ModelType.NETMIND_DEEPSEEK_R1,\n ModelType.NETMIND_DEEPSEEK_V3,\n ModelType.NETMIND_DOUBAO_1_5_PRO,\n ModelType.NETMIND_QWQ_32B,\n }\n\n @property\n def is_ppio(self) -> bool:\n return self in {\n ModelType.PPIO_DEEPSEEK_PROVER_V2_671B,\n ModelType.PPIO_DEEPSEEK_R1_TURBO,\n ModelType.PPIO_DEEPSEEK_V3_TURBO,\n ModelType.PPIO_DEEPSEEK_R1_COMMUNITY,\n ModelType.PPIO_DEEPSEEK_V3_COMMUNITY,\n ModelType.PPIO_DEEPSEEK_R1,\n ModelType.PPIO_DEEPSEEK_V3,\n ModelType.PPIO_QWEN_2_5_72B,\n ModelType.PPIO_BAICHUAN_2_13B_CHAT,\n ModelType.PPIO_LLAMA_3_3_70B,\n ModelType.PPIO_LLAMA_3_1_70B,\n ModelType.PPIO_YI_1_5_34B_CHAT,\n }\n\n @property\n def is_internlm(self) -> bool:\n return self in {\n ModelType.INTERNLM3_LATEST,\n ModelType.INTERNLM3_8B_INSTRUCT,\n ModelType.INTERNLM2_5_LATEST,\n ModelType.INTERNLM2_PRO_CHAT,\n }\n\n @property\n def is_modelscope(self) -> bool:\n return self in {\n ModelType.MODELSCOPE_QWEN_2_5_7B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_14B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_32B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_72B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_7B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_14B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_32B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_3_235B_A22B,\n ModelType.MODELSCOPE_QWEN_3_32B,\n ModelType.MODELSCOPE_QWQ_32B,\n ModelType.MODELSCOPE_QWQ_32B_PREVIEW,\n ModelType.MODELSCOPE_LLAMA_3_1_8B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_1_70B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_1_405B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_3_70B_INSTRUCT,\n ModelType.MODELSCOPE_MINISTRAL_8B_INSTRUCT,\n ModelType.MODELSCOPE_DEEPSEEK_V3_0324,\n }\n\n @property\n def is_moonshot(self) -> bool:\n return self in {\n ModelType.MOONSHOT_V1_8K,\n ModelType.MOONSHOT_V1_32K,\n ModelType.MOONSHOT_V1_128K,\n ModelType.MOONSHOT_KIMI_K2,\n }\n\n @property\n def is_sglang(self) -> bool:\n return self in {\n ModelType.SGLANG_LLAMA_3_1_8B,\n ModelType.SGLANG_LLAMA_3_1_70B,\n ModelType.SGLANG_LLAMA_3_1_405B,\n ModelType.SGLANG_LLAMA_3_2_1B,\n ModelType.SGLANG_MIXTRAL_NEMO,\n ModelType.SGLANG_MISTRAL_7B,\n ModelType.SGLANG_QWEN_2_5_7B,\n ModelType.SGLANG_QWEN_2_5_32B,\n ModelType.SGLANG_QWEN_2_5_72B,\n }\n\n @property\n def is_siliconflow(self) -> bool:\n return self in {\n ModelType.SILICONFLOW_DEEPSEEK_V2_5,\n ModelType.SILICONFLOW_DEEPSEEK_V3,\n ModelType.SILICONFLOW_INTERN_LM2_5_20B_CHAT,\n ModelType.SILICONFLOW_INTERN_LM2_5_7B_CHAT,\n ModelType.SILICONFLOW_PRO_INTERN_LM2_5_7B_CHAT,\n ModelType.SILICONFLOW_QWEN2_5_72B_INSTRUCT,\n ModelType.SILICONFLOW_QWEN2_5_32B_INSTRUCT,\n ModelType.SILICONFLOW_QWEN2_5_14B_INSTRUCT,\n ModelType.SILICONFLOW_QWEN2_5_7B_INSTRUCT,\n ModelType.SILICONFLOW_PRO_QWEN2_5_7B_INSTRUCT,\n ModelType.SILICONFLOW_THUDM_GLM_4_9B_CHAT,\n ModelType.SILICONFLOW_PRO_THUDM_GLM_4_9B_CHAT,\n }\n\n @property\n def is_watsonx(self) -> bool:\n return self in {\n ModelType.WATSONX_GRANITE_3_8B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_3_70B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_1B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_3B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_11B_VISION_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_90B_VISION_INSTRUCT,\n ModelType.WATSONX_LLAMA_GUARD_3_11B_VISION_INSTRUCT,\n ModelType.WATSONX_MISTRAL_LARGE,\n }\n\n @property\n def is_qianfan(self) -> bool:\n return self in {\n ModelType.ERNIE_X1_TURBO_32K,\n ModelType.ERNIE_X1_32K,\n ModelType.ERNIE_X1_32K_PREVIEW,\n ModelType.ERNIE_4_5_TURBO_128K,\n ModelType.ERNIE_4_5_TURBO_32K,\n ModelType.DEEPSEEK_V3,\n ModelType.DEEPSEEK_R1,\n ModelType.QWEN3_235B_A22B,\n }\n\n @property\n def is_novita(self) -> bool:\n return self in {\n ModelType.NOVITA_LLAMA_4_MAVERICK_17B,\n ModelType.NOVITA_LLAMA_4_SCOUT_17B,\n ModelType.NOVITA_DEEPSEEK_V3_0324,\n ModelType.NOVITA_QWEN_2_5_V1_72B,\n ModelType.NOVITA_DEEPSEEK_V3_TURBO,\n ModelType.NOVITA_DEEPSEEK_R1_TURBO,\n ModelType.NOVITA_GEMMA_3_27B_IT,\n ModelType.NOVITA_QWEN_32B,\n ModelType.NOVITA_L3_8B_STHENO_V3_2,\n ModelType.NOVITA_MYTHOMAX_L2_13B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_8B,\n ModelType.NOVITA_DEEPSEEK_V3,\n ModelType.NOVITA_LLAMA_3_1_8B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_QWEN_14B,\n ModelType.NOVITA_LLAMA_3_3_70B,\n ModelType.NOVITA_QWEN_2_5_72B,\n ModelType.NOVITA_MISTRAL_NEMO,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_QWEN_32B,\n ModelType.NOVITA_LLAMA_3_8B,\n ModelType.NOVITA_WIZARDLM_2_8X22B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_70B,\n ModelType.NOVITA_LLAMA_3_1_70B,\n ModelType.NOVITA_GEMMA_2_9B_IT,\n ModelType.NOVITA_MISTRAL_7B,\n ModelType.NOVITA_LLAMA_3_70B,\n ModelType.NOVITA_DEEPSEEK_R1,\n ModelType.NOVITA_HERMES_2_PRO_LLAMA_3_8B,\n ModelType.NOVITA_L3_70B_EURYALE_V2_1,\n ModelType.NOVITA_DOLPHIN_MIXTRAL_8X22B,\n ModelType.NOVITA_AIROBOROS_L2_70B,\n ModelType.NOVITA_MIDNIGHT_ROSE_70B,\n ModelType.NOVITA_L3_8B_LUNARIS,\n ModelType.NOVITA_GLM_4_9B_0414,\n ModelType.NOVITA_GLM_Z1_9B_0414,\n ModelType.NOVITA_GLM_Z1_32B_0414,\n ModelType.NOVITA_GLM_4_32B_0414,\n ModelType.NOVITA_GLM_Z1_RUMINATION_32B_0414,\n ModelType.NOVITA_QWEN_2_5_7B,\n ModelType.NOVITA_LLAMA_3_2_1B,\n ModelType.NOVITA_LLAMA_3_2_11B_VISION,\n ModelType.NOVITA_LLAMA_3_2_3B,\n ModelType.NOVITA_LLAMA_3_1_8B_BF16,\n ModelType.NOVITA_L31_70B_EURYALE_V2_2,\n }\n\n @property\n def is_crynux(self) -> bool:\n return self in {\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_1_5B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_7B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_LLAMA_8B,\n ModelType.CRYNUX_QWEN_3_4_B,\n ModelType.CRYNUX_QWEN_3_8_B,\n ModelType.CRYNUX_QWEN_2_5_7B,\n ModelType.CRYNUX_QWEN_2_5_7B_INSTRUCT,\n ModelType.CRYNUX_NOUS_HERMES_3_LLAMA_3_1_8B,\n ModelType.CRYNUX_NOUS_HERMES_3_LLAMA_3_2_3B,\n }\n\n @property\n def is_aiml(self) -> bool:\n return self in {\n ModelType.AIML_MIXTRAL_8X7B,\n ModelType.AIML_MISTRAL_7B_INSTRUCT,\n }\n\n @property\n def token_limit(self) -> int:\n r\"\"\"Returns the maximum token limit for a given model.\n\n Returns:\n int: The maximum token limit for the given model.\n \"\"\"\n if self is ModelType.GLM_4V:\n return 1024\n elif self in {\n ModelType.STUB,\n ModelType.REKA_CORE,\n ModelType.REKA_EDGE,\n ModelType.REKA_FLASH,\n ModelType.QWEN_MATH_PLUS,\n ModelType.QWEN_MATH_TURBO,\n ModelType.COHERE_COMMAND,\n ModelType.COHERE_COMMAND_LIGHT,\n ModelType.NVIDIA_NEMOTRON_340B_INSTRUCT,\n ModelType.NVIDIA_NEMOTRON_340B_REWARD,\n ModelType.NOVITA_MYTHOMAX_L2_13B,\n ModelType.NOVITA_AIROBOROS_L2_70B,\n ModelType.NOVITA_MIDNIGHT_ROSE_70B,\n }:\n return 4_096\n elif self in {\n ModelType.GPT_4,\n ModelType.GROQ_LLAMA_3_8B,\n ModelType.GROQ_LLAMA_3_70B,\n ModelType.GROQ_LLAMA_3_3_70B_PREVIEW,\n ModelType.GROQ_GEMMA_2_9B_IT,\n ModelType.GLM_3_TURBO,\n ModelType.GLM_4,\n ModelType.QWEN_VL_PLUS,\n ModelType.NVIDIA_LLAMA3_70B,\n ModelType.TOGETHER_MISTRAL_7B,\n ModelType.MOONSHOT_V1_8K,\n ModelType.GLM_4V_FLASH,\n ModelType.GLM_4_AIRX,\n ModelType.OPENROUTER_OLYMPICODER_7B,\n ModelType.LMSTUDIO_GEMMA_3_1B,\n ModelType.LMSTUDIO_GEMMA_3_4B,\n ModelType.LMSTUDIO_GEMMA_3_12B,\n ModelType.LMSTUDIO_GEMMA_3_27B,\n ModelType.WATSONX_GRANITE_3_8B_INSTRUCT,\n ModelType.NOVITA_L3_8B_STHENO_V3_2,\n ModelType.NOVITA_LLAMA_3_8B,\n ModelType.NOVITA_GEMMA_2_9B_IT,\n ModelType.NOVITA_LLAMA_3_70B,\n ModelType.NOVITA_HERMES_2_PRO_LLAMA_3_8B,\n ModelType.NOVITA_L3_70B_EURYALE_V2_1,\n ModelType.NOVITA_L3_8B_LUNARIS,\n ModelType.NOVITA_LLAMA_3_1_8B_BF16,\n ModelType.NOVITA_L31_70B_EURYALE_V2_2,\n }:\n return 8_192\n elif self in {\n ModelType.PPIO_BAICHUAN_2_13B_CHAT,\n }:\n return 14_336\n elif self in {\n ModelType.PPIO_DEEPSEEK_PROVER_V2_671B,\n ModelType.NOVITA_DOLPHIN_MIXTRAL_8X22B,\n }:\n return 16_000\n elif self in {\n ModelType.GPT_3_5_TURBO,\n ModelType.YI_LIGHTNING,\n ModelType.YI_MEDIUM,\n ModelType.YI_LARGE_TURBO,\n ModelType.YI_VISION,\n ModelType.YI_SPARK,\n ModelType.YI_LARGE_RAG,\n ModelType.SAMBA_LLAMA_3_1_8B,\n ModelType.SAMBA_LLAMA_3_1_405B,\n ModelType.GLM_4V_PLUS_0111,\n ModelType.GLM_ZERO_PREVIEW,\n ModelType.PPIO_YI_1_5_34B_CHAT,\n ModelType.NOVITA_LLAMA_3_1_8B,\n }:\n return 16_384\n elif self in {\n ModelType.NETMIND_DOUBAO_1_5_PRO,\n ModelType.NOVITA_GEMMA_3_27B_IT,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_8B,\n ModelType.NOVITA_QWEN_2_5_72B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_LLAMA_70B,\n ModelType.NOVITA_GLM_4_9B_0414,\n ModelType.NOVITA_GLM_Z1_9B_0414,\n ModelType.NOVITA_GLM_Z1_32B_0414,\n ModelType.NOVITA_GLM_4_32B_0414,\n ModelType.NOVITA_GLM_Z1_RUMINATION_32B_0414,\n ModelType.NOVITA_QWEN_2_5_7B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_1_5B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_QWEN_7B,\n ModelType.CRYNUX_DEEPSEEK_R1_DISTILL_LLAMA_8B,\n ModelType.CRYNUX_QWEN_3_4_B,\n ModelType.CRYNUX_QWEN_3_8_B,\n ModelType.CRYNUX_QWEN_2_5_7B,\n ModelType.CRYNUX_QWEN_2_5_7B_INSTRUCT,\n ModelType.CRYNUX_NOUS_HERMES_3_LLAMA_3_1_8B,\n ModelType.CRYNUX_NOUS_HERMES_3_LLAMA_3_2_3B,\n ModelType.ERNIE_X1_TURBO_32K,\n ModelType.ERNIE_X1_32K,\n ModelType.ERNIE_X1_32K_PREVIEW,\n ModelType.ERNIE_4_5_TURBO_32K,\n ModelType.QWEN3_235B_A22B,\n }:\n return 32_000\n elif self in {\n ModelType.MISTRAL_CODESTRAL,\n ModelType.MISTRAL_7B,\n ModelType.MISTRAL_MIXTRAL_8x7B,\n ModelType.GROQ_MIXTRAL_8_7B,\n ModelType.YI_LARGE,\n ModelType.YI_LARGE_FC,\n ModelType.QWEN_MAX,\n ModelType.QWEN_VL_MAX,\n ModelType.NVIDIA_YI_LARGE,\n ModelType.NVIDIA_MISTRAL_LARGE,\n ModelType.NVIDIA_MIXTRAL_8X7B,\n ModelType.QWEN_QWQ_32B,\n ModelType.QWEN_QWQ_PLUS,\n ModelType.QWEN_QVQ_72B,\n ModelType.INTERNLM3_8B_INSTRUCT,\n ModelType.INTERNLM3_LATEST,\n ModelType.INTERNLM2_5_LATEST,\n ModelType.INTERNLM2_PRO_CHAT,\n ModelType.TOGETHER_MIXTRAL_8_7B,\n ModelType.SGLANG_MISTRAL_7B,\n ModelType.MOONSHOT_V1_32K,\n ModelType.AIML_MIXTRAL_8X7B,\n ModelType.AIML_MISTRAL_7B_INSTRUCT,\n ModelType.PPIO_QWEN_2_5_72B,\n ModelType.PPIO_LLAMA_3_1_70B,\n ModelType.MODELSCOPE_QWEN_2_5_7B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_14B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_32B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_72B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_7B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_14B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_2_5_CODER_32B_INSTRUCT,\n ModelType.MODELSCOPE_QWEN_3_235B_A22B,\n ModelType.MODELSCOPE_QWEN_3_32B,\n ModelType.MODELSCOPE_QWQ_32B,\n ModelType.MODELSCOPE_QWQ_32B_PREVIEW,\n ModelType.MODELSCOPE_LLAMA_3_1_8B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_1_70B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_1_405B_INSTRUCT,\n ModelType.MODELSCOPE_LLAMA_3_3_70B_INSTRUCT,\n ModelType.MODELSCOPE_MINISTRAL_8B_INSTRUCT,\n ModelType.MODELSCOPE_DEEPSEEK_V3_0324,\n ModelType.OPENROUTER_LLAMA_3_1_405B,\n ModelType.WATSONX_MISTRAL_LARGE,\n ModelType.NOVITA_QWEN_32B,\n ModelType.NOVITA_LLAMA_3_1_70B,\n ModelType.NOVITA_MISTRAL_7B,\n ModelType.NOVITA_LLAMA_3_2_11B_VISION,\n ModelType.NOVITA_LLAMA_3_2_3B,\n ModelType.NEBIUS_MISTRAL_7B_INSTRUCT,\n }:\n return 32_768\n elif self in {\n ModelType.MISTRAL_MIXTRAL_8x22B,\n ModelType.DEEPSEEK_CHAT,\n ModelType.DEEPSEEK_REASONER,\n ModelType.PPIO_DEEPSEEK_R1_TURBO,\n ModelType.PPIO_DEEPSEEK_V3_TURBO,\n ModelType.PPIO_DEEPSEEK_R1_COMMUNITY,\n ModelType.PPIO_DEEPSEEK_V3_COMMUNITY,\n ModelType.PPIO_DEEPSEEK_R1,\n ModelType.PPIO_DEEPSEEK_V3,\n ModelType.AWS_DEEPSEEK_R1,\n ModelType.NETMIND_QWQ_32B,\n ModelType.NOVITA_DEEPSEEK_V3_TURBO,\n ModelType.NOVITA_DEEPSEEK_R1_TURBO,\n ModelType.NOVITA_DEEPSEEK_V3,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_QWEN_14B,\n ModelType.NOVITA_DEEPSEEK_R1_DISTILL_QWEN_32B,\n ModelType.NOVITA_DEEPSEEK_R1,\n }:\n return 64_000\n elif self in {\n ModelType.NOVITA_WIZARDLM_2_8X22B,\n }:\n return 65_535\n elif self in {\n ModelType.NOVITA_QWEN_2_5_V1_72B,\n ModelType.DEEPSEEK_R1,\n }:\n return 96_000\n elif self in {\n ModelType.CLAUDE_2_0,\n ModelType.CLAUDE_INSTANT_1_2,\n }:\n return 100_000\n elif self in {\n ModelType.GPT_4O,\n ModelType.GPT_4O_MINI,\n ModelType.GPT_4_TURBO,\n ModelType.O1_PREVIEW,\n ModelType.O1_MINI,\n ModelType.GPT_4_5_PREVIEW,\n ModelType.GPT_5,\n ModelType.GPT_5_NANO,\n ModelType.GPT_5_MINI,\n ModelType.MISTRAL_LARGE,\n ModelType.MISTRAL_NEMO,\n ModelType.MISTRAL_PIXTRAL_12B,\n ModelType.MISTRAL_8B,\n ModelType.MISTRAL_3B,\n ModelType.MISTRAL_SMALL_3_2,\n ModelType.MAGISTRAL_SMALL_1_2,\n ModelType.QWEN_2_5_CODER_32B,\n ModelType.QWEN_2_5_VL_72B,\n ModelType.QWEN_2_5_72B,\n ModelType.QWEN_2_5_32B,\n ModelType.QWEN_2_5_14B,\n ModelType.COHERE_COMMAND_R,\n ModelType.COHERE_COMMAND_R_PLUS,\n ModelType.COHERE_COMMAND_NIGHTLY,\n ModelType.NVIDIA_LLAMA3_1_8B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_1_70B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_1_405B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_2_1B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_2_3B_INSTRUCT,\n ModelType.NVIDIA_LLAMA3_3_70B_INSTRUCT,\n ModelType.GROQ_LLAMA_3_3_70B,\n ModelType.SAMBA_LLAMA_3_1_70B,\n ModelType.SGLANG_LLAMA_3_1_8B,\n ModelType.SGLANG_LLAMA_3_1_70B,\n ModelType.SGLANG_LLAMA_3_1_405B,\n ModelType.SGLANG_LLAMA_3_2_1B,\n ModelType.SGLANG_MIXTRAL_NEMO,\n ModelType.MOONSHOT_V1_128K,\n ModelType.GLM_4_PLUS,\n ModelType.GLM_4_AIR,\n ModelType.GLM_4_AIR_0111,\n ModelType.GLM_4_FLASHX,\n ModelType.GLM_4_FLASH,\n ModelType.AWS_LLAMA_3_3_70B_INSTRUCT,\n ModelType.AWS_LLAMA_3_2_90B_INSTRUCT,\n ModelType.AWS_LLAMA_3_2_11B_INSTRUCT,\n ModelType.NETMIND_DEEPSEEK_R1,\n ModelType.NETMIND_DEEPSEEK_V3,\n ModelType.NOVITA_DEEPSEEK_V3_0324,\n ModelType.MISTRAL_MEDIUM_3_1,\n ModelType.MAGISTRAL_MEDIUM_1_2,\n ModelType.ERNIE_4_5_TURBO_128K,\n ModelType.DEEPSEEK_V3,\n ModelType.MOONSHOT_KIMI_K2,\n ModelType.NEBIUS_GLM_4_5,\n ModelType.NEBIUS_DEEPSEEK_V3,\n ModelType.NEBIUS_DEEPSEEK_R1,\n ModelType.NEBIUS_GPT_OSS_120B,\n ModelType.NEBIUS_GPT_OSS_20B,\n ModelType.COMETAPI_GPT_5_CHAT_LATEST,\n ModelType.COMETAPI_CHATGPT_4O_LATEST,\n ModelType.COMETAPI_GPT_5_MINI,\n ModelType.COMETAPI_GPT_5_NANO,\n ModelType.COMETAPI_GPT_5,\n ModelType.COMETAPI_GPT_4_1,\n ModelType.COMETAPI_GPT_4O_MINI,\n ModelType.COMETAPI_O4_MINI_2025_04_16,\n ModelType.COMETAPI_O3_PRO_2025_06_10,\n ModelType.COMETAPI_CLAUDE_OPUS_4_1_20250805,\n ModelType.COMETAPI_CLAUDE_OPUS_4_1_20250805_THINKING,\n ModelType.COMETAPI_CLAUDE_SONNET_4_20250514,\n ModelType.COMETAPI_CLAUDE_SONNET_4_20250514_THINKING,\n ModelType.COMETAPI_CLAUDE_3_7_SONNET_LATEST,\n ModelType.COMETAPI_CLAUDE_3_5_HAIKU_LATEST,\n ModelType.COMETAPI_GEMINI_2_5_PRO,\n ModelType.COMETAPI_GEMINI_2_5_FLASH,\n ModelType.COMETAPI_GEMINI_2_5_FLASH_LITE,\n ModelType.COMETAPI_GEMINI_2_0_FLASH,\n ModelType.COMETAPI_GROK_4_0709,\n ModelType.COMETAPI_GROK_3,\n ModelType.COMETAPI_GROK_3_MINI,\n ModelType.COMETAPI_GROK_2_IMAGE_1212,\n ModelType.COMETAPI_DEEPSEEK_V3_1,\n ModelType.COMETAPI_DEEPSEEK_V3,\n ModelType.COMETAPI_DEEPSEEK_R1_0528,\n ModelType.COMETAPI_DEEPSEEK_CHAT,\n ModelType.COMETAPI_DEEPSEEK_REASONER,\n ModelType.COMETAPI_QWEN3_30B_A3B,\n ModelType.COMETAPI_QWEN3_CODER_PLUS_2025_07_22,\n }:\n return 128_000\n elif self in {\n ModelType.NOVITA_LLAMA_3_2_1B,\n }:\n return 131_000\n elif self in {\n ModelType.GROQ_LLAMA_3_1_8B,\n ModelType.QWEN_PLUS,\n ModelType.QWEN_TURBO,\n ModelType.QWEN_CODER_TURBO,\n ModelType.QWEN_PLUS_LATEST,\n ModelType.QWEN_PLUS_2025_04_28,\n ModelType.QWEN_TURBO_LATEST,\n ModelType.QWEN_TURBO_2025_04_28,\n ModelType.TOGETHER_LLAMA_3_1_8B,\n ModelType.TOGETHER_LLAMA_3_1_70B,\n ModelType.TOGETHER_LLAMA_3_1_405B,\n ModelType.TOGETHER_LLAMA_3_3_70B,\n ModelType.SGLANG_QWEN_2_5_7B,\n ModelType.SGLANG_QWEN_2_5_32B,\n ModelType.SGLANG_QWEN_2_5_72B,\n ModelType.OPENROUTER_LLAMA_3_1_70B,\n ModelType.PPIO_LLAMA_3_3_70B,\n ModelType.OPENROUTER_LLAMA_4_SCOUT,\n ModelType.WATSONX_LLAMA_3_3_70B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_1B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_3B_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_11B_VISION_INSTRUCT,\n ModelType.WATSONX_LLAMA_3_2_90B_VISION_INSTRUCT,\n ModelType.WATSONX_LLAMA_GUARD_3_11B_VISION_INSTRUCT,\n ModelType.NOVITA_LLAMA_4_SCOUT_17B,\n ModelType.NOVITA_LLAMA_3_3_70B,\n ModelType.NOVITA_MISTRAL_NEMO,\n ModelType.NEBIUS_LLAMA_3_1_70B,\n }:\n return 131_072\n elif self in {\n ModelType.O1,\n ModelType.O3_MINI,\n ModelType.O3_PRO,\n ModelType.CLAUDE_2_1,\n ModelType.CLAUDE_3_OPUS,\n ModelType.CLAUDE_3_SONNET,\n ModelType.CLAUDE_3_HAIKU,\n ModelType.CLAUDE_3_5_SONNET,\n ModelType.CLAUDE_3_5_HAIKU,\n ModelType.CLAUDE_3_7_SONNET,\n ModelType.CLAUDE_SONNET_4,\n ModelType.CLAUDE_OPUS_4,\n ModelType.CLAUDE_OPUS_4_1,\n ModelType.YI_MEDIUM_200K,\n ModelType.AWS_CLAUDE_3_5_SONNET,\n ModelType.AWS_CLAUDE_3_HAIKU,\n ModelType.AWS_CLAUDE_3_SONNET,\n ModelType.AWS_CLAUDE_3_7_SONNET,\n ModelType.AWS_CLAUDE_SONNET_4,\n ModelType.AWS_CLAUDE_OPUS_4,\n ModelType.AWS_CLAUDE_OPUS_4_1,\n ModelType.O4_MINI,\n ModelType.O3,\n }:\n return 200_000\n elif self in {\n ModelType.MISTRAL_CODESTRAL_MAMBA,\n ModelType.OPENROUTER_LLAMA_4_MAVERICK_FREE,\n ModelType.OPENROUTER_HORIZON_ALPHA,\n }:\n return 256_000\n\n elif self in {\n ModelType.NETMIND_LLAMA_4_SCOUT_17B_16E_INSTRUCT,\n }:\n return 320_000\n elif self in {\n ModelType.OPENROUTER_LLAMA_4_SCOUT_FREE,\n ModelType.NETMIND_LLAMA_4_MAVERICK_17B_128E_INSTRUCT,\n }:\n return 512_000\n elif self in {\n ModelType.GEMINI_2_5_FLASH,\n ModelType.GEMINI_2_5_PRO,\n ModelType.GEMINI_2_0_FLASH,\n ModelType.GEMINI_2_0_FLASH_EXP,\n ModelType.GEMINI_2_0_FLASH_THINKING,\n ModelType.GEMINI_2_0_FLASH_LITE,\n ModelType.GEMINI_2_0_FLASH_LITE_PREVIEW,\n ModelType.GEMINI_1_5_FLASH,\n ModelType.GEMINI_1_5_PRO,\n ModelType.GEMINI_2_0_PRO_EXP, # Not given in doc, assume the same\n ModelType.GLM_4_LONG,\n ModelType.TOGETHER_LLAMA_4_MAVERICK,\n ModelType.OPENROUTER_LLAMA_4_MAVERICK,\n ModelType.AMD_GPT4,\n ModelType.GPT_4_1,\n ModelType.GPT_4_1_MINI,\n ModelType.GPT_4_1_NANO,\n ModelType.NOVITA_LLAMA_4_MAVERICK_17B,\n }:\n return 1_048_576\n elif self in {\n ModelType.QWEN_3_CODER_PLUS,\n }:\n return 1_000_000\n elif self in {\n ModelType.QWEN_LONG,\n ModelType.TOGETHER_LLAMA_4_SCOUT,\n }:\n return 10_000_000\n\n else:\n logger.warning(\n f\"Unknown model type {self}, set maximum token limit \"\n f\"to 999_999_999\"\n )\n return 999_999_999\n\n\nclass EmbeddingModelType(Enum):\n TEXT_EMBEDDING_ADA_2 = \"text-embedding-ada-002\"\n TEXT_EMBEDDING_3_SMALL = \"text-embedding-3-small\"\n TEXT_EMBEDDING_3_LARGE = \"text-embedding-3-large\"\n\n JINA_EMBEDDINGS_V3 = \"jina-embeddings-v3\"\n JINA_CLIP_V2 = \"jina-clip-v2\"\n JINA_COLBERT_V2 = \"jina-colbert-v2\"\n JINA_EMBEDDINGS_V2_BASE_CODE = \"jina-embeddings-v2-base-code\"\n\n MISTRAL_EMBED = \"mistral-embed\"\n\n GEMINI_EMBEDDING_EXP = \"gemini-embedding-exp-03-07\"\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this type of models is an OpenAI-released model.\"\"\"\n return self in {\n EmbeddingModelType.TEXT_EMBEDDING_ADA_2,\n EmbeddingModelType.TEXT_EMBEDDING_3_SMALL,\n EmbeddingModelType.TEXT_EMBEDDING_3_LARGE,\n }\n\n @property\n def is_jina(self) -> bool:\n r\"\"\"Returns whether this type of models is an Jina model.\"\"\"\n return self in {\n EmbeddingModelType.JINA_EMBEDDINGS_V3,\n EmbeddingModelType.JINA_CLIP_V2,\n EmbeddingModelType.JINA_COLBERT_V2,\n EmbeddingModelType.JINA_EMBEDDINGS_V2_BASE_CODE,\n }\n\n @property\n def is_mistral(self) -> bool:\n r\"\"\"Returns whether this type of models is an Mistral-released\n model.\n \"\"\"\n return self in {\n EmbeddingModelType.MISTRAL_EMBED,\n }\n\n @property\n def is_gemini(self) -> bool:\n r\"\"\"Returns whether this type of models is an Gemini-released model.\"\"\"\n return self in {\n EmbeddingModelType.GEMINI_EMBEDDING_EXP,\n }\n\n @property\n def output_dim(self) -> int:\n if self in {\n EmbeddingModelType.JINA_COLBERT_V2,\n }:\n return 128\n elif self in {\n EmbeddingModelType.JINA_EMBEDDINGS_V2_BASE_CODE,\n }:\n return 768\n elif self in {\n EmbeddingModelType.JINA_EMBEDDINGS_V3,\n EmbeddingModelType.JINA_CLIP_V2,\n }:\n return 1024\n elif self is EmbeddingModelType.TEXT_EMBEDDING_ADA_2:\n return 1536\n elif self is EmbeddingModelType.TEXT_EMBEDDING_3_SMALL:\n return 1536\n elif self is EmbeddingModelType.TEXT_EMBEDDING_3_LARGE:\n return 3072\n elif self is EmbeddingModelType.MISTRAL_EMBED:\n return 1024\n elif self is EmbeddingModelType.GEMINI_EMBEDDING_EXP:\n return 3072\n else:\n raise ValueError(f\"Unknown model type {self}.\")\n\n\nclass GeminiEmbeddingTaskType(str, Enum):\n r\"\"\"Task types for Gemini embedding models.\n\n For more information, please refer to:\n https://ai.google.dev/gemini-api/docs/embeddings#task-types\n \"\"\"\n\n SEMANTIC_SIMILARITY = \"SEMANTIC_SIMILARITY\"\n CLASSIFICATION = \"CLASSIFICATION\"\n CLUSTERING = \"CLUSTERING\"\n RETRIEVAL_DOCUMENT = \"RETRIEVAL_DOCUMENT\"\n RETRIEVAL_QUERY = \"RETRIEVAL_QUERY\"\n QUESTION_ANSWERING = \"QUESTION_ANSWERING\"\n FACT_VERIFICATION = \"FACT_VERIFICATION\"\n CODE_RETRIEVAL_QUERY = \"CODE_RETRIEVAL_QUERY\"\n\n\nclass TaskType(Enum):\n AI_SOCIETY = \"ai_society\"\n CODE = \"code\"\n MISALIGNMENT = \"misalignment\"\n TRANSLATION = \"translation\"\n EVALUATION = \"evaluation\"\n SOLUTION_EXTRACTION = \"solution_extraction\"\n ROLE_DESCRIPTION = \"role_description\"\n GENERATE_TEXT_EMBEDDING_DATA = \"generate_text_embedding_data\"\n OBJECT_RECOGNITION = \"object_recognition\"\n IMAGE_CRAFT = \"image_craft\"\n MULTI_CONDITION_IMAGE_CRAFT = \"multi_condition_image_craft\"\n DEFAULT = \"default\"\n VIDEO_DESCRIPTION = \"video_description\"\n\n\nclass VectorDistance(Enum):\n r\"\"\"Distance metrics used in a vector database.\"\"\"\n\n DOT = \"dot\"\n r\"\"\"Dot product. https://en.wikipedia.org/wiki/Dot_product\"\"\"\n\n COSINE = \"cosine\"\n r\"\"\"Cosine similarity. https://en.wikipedia.org/wiki/Cosine_similarity\"\"\"\n\n EUCLIDEAN = \"euclidean\"\n r\"\"\"Euclidean distance. https://en.wikipedia.org/wiki/Euclidean_distance\"\"\"\n\n\nclass OpenAIBackendRole(Enum):\n ASSISTANT = \"assistant\"\n SYSTEM = \"system\"\n DEVELOPER = \"developer\"\n USER = \"user\"\n FUNCTION = \"function\"\n TOOL = \"tool\"\n\n\nclass TerminationMode(Enum):\n ANY = \"any\"\n ALL = \"all\"\n\n\nclass OpenAIImageTypeMeta(EnumMeta):\n def __contains__(cls, image_type: object) -> bool:\n try:\n cls(image_type)\n except ValueError:\n return False\n return True\n\n\nclass OpenAIImageType(Enum, metaclass=OpenAIImageTypeMeta):\n r\"\"\"Image types supported by OpenAI vision model.\"\"\"\n\n # https://platform.openai.com/docs/guides/vision\n PNG = \"png\"\n JPEG = \"jpeg\"\n JPG = \"jpg\"\n WEBP = \"webp\"\n GIF = \"gif\"\n\n\nclass OpenAIVisionDetailType(Enum):\n AUTO = \"auto\"\n LOW = \"low\"\n HIGH = \"high\"\n\n\nclass StorageType(Enum):\n MILVUS = \"milvus\"\n QDRANT = \"qdrant\"\n TIDB = \"tidb\"\n\n\nclass OpenAPIName(Enum):\n COURSERA = \"coursera\"\n KLARNA = \"klarna\"\n SPEAK = \"speak\"\n NASA_APOD = \"nasa_apod\"\n BIZTOC = \"biztoc\"\n CREATE_QR_CODE = \"create_qr_code\"\n OUTSCHOOL = \"outschool\"\n WEB_SCRAPER = \"web_scraper\"\n\n\nclass ModelPlatformType(Enum):\n DEFAULT = os.getenv(\"DEFAULT_MODEL_PLATFORM_TYPE\", \"openai\")\n\n OPENAI = \"openai\"\n AWS_BEDROCK = \"aws-bedrock\"\n AZURE = \"azure\"\n ANTHROPIC = \"anthropic\"\n GROQ = \"groq\"\n NEBIUS = \"nebius\"\n COMETAPI = \"cometapi\"\n OPENROUTER = \"openrouter\"\n OLLAMA = \"ollama\"\n LITELLM = \"litellm\"\n LMSTUDIO = \"lmstudio\"\n ZHIPU = \"zhipuai\"\n GEMINI = \"gemini\"\n VLLM = \"vllm\"\n MISTRAL = \"mistral\"\n REKA = \"reka\"\n TOGETHER = \"together\"\n STUB = \"stub\"\n OPENAI_COMPATIBLE_MODEL = \"openai-compatible-model\"\n SAMBA = \"samba-nova\"\n COHERE = \"cohere\"\n YI = \"lingyiwanwu\"\n QWEN = \"tongyi-qianwen\"\n AMD = \"amd\"\n NVIDIA = \"nvidia\"\n DEEPSEEK = \"deepseek\"\n PPIO = \"ppio\"\n SGLANG = \"sglang\"\n INTERNLM = \"internlm\"\n MOONSHOT = \"moonshot\"\n MODELSCOPE = \"modelscope\"\n SILICONFLOW = \"siliconflow\"\n AIML = \"aiml\"\n VOLCANO = \"volcano\"\n NETMIND = \"netmind\"\n NOVITA = \"novita\"\n WATSONX = \"watsonx\"\n QIANFAN = \"qianfan\"\n CRYNUX = \"crynux\"\n\n @classmethod\n def from_name(cls, name):\n r\"\"\"Returns the ModelPlatformType enum value from a string.\"\"\"\n for model_platfrom_type in cls:\n if model_platfrom_type.value == name:\n return model_platfrom_type\n raise ValueError(f\"Unknown ModelPlatformType name: {name}\")\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this platform is openai.\"\"\"\n return self is ModelPlatformType.OPENAI\n\n @property\n def is_aws_bedrock(self) -> bool:\n r\"\"\"Returns whether this platform is aws-bedrock.\"\"\"\n return self is ModelPlatformType.AWS_BEDROCK\n\n @property\n def is_azure(self) -> bool:\n r\"\"\"Returns whether this platform is azure.\"\"\"\n return self is ModelPlatformType.AZURE\n\n @property\n def is_anthropic(self) -> bool:\n r\"\"\"Returns whether this platform is anthropic.\"\"\"\n return self is ModelPlatformType.ANTHROPIC\n\n @property\n def is_groq(self) -> bool:\n r\"\"\"Returns whether this platform is groq.\"\"\"\n return self is ModelPlatformType.GROQ\n\n @property\n def is_openrouter(self) -> bool:\n r\"\"\"Returns whether this platform is openrouter.\"\"\"\n return self is ModelPlatformType.OPENROUTER\n\n @property\n def is_lmstudio(self) -> bool:\n r\"\"\"Returns whether this platform is lmstudio.\"\"\"\n return self is ModelPlatformType.LMSTUDIO\n\n @property\n def is_ollama(self) -> bool:\n r\"\"\"Returns whether this platform is ollama.\"\"\"\n return self is ModelPlatformType.OLLAMA\n\n @property\n def is_vllm(self) -> bool:\n r\"\"\"Returns whether this platform is vllm.\"\"\"\n return self is ModelPlatformType.VLLM\n\n @property\n def is_sglang(self) -> bool:\n r\"\"\"Returns whether this platform is sglang.\"\"\"\n return self is ModelPlatformType.SGLANG\n\n @property\n def is_together(self) -> bool:\n r\"\"\"Returns whether this platform is together.\"\"\"\n return self is ModelPlatformType.TOGETHER\n\n @property\n def is_litellm(self) -> bool:\n r\"\"\"Returns whether this platform is litellm.\"\"\"\n return self is ModelPlatformType.LITELLM\n\n @property\n def is_zhipuai(self) -> bool:\n r\"\"\"Returns whether this platform is zhipu.\"\"\"\n return self is ModelPlatformType.ZHIPU\n\n @property\n def is_mistral(self) -> bool:\n r\"\"\"Returns whether this platform is mistral.\"\"\"\n return self is ModelPlatformType.MISTRAL\n\n @property\n def is_openai_compatible_model(self) -> bool:\n r\"\"\"Returns whether this is a platform supporting openai\n compatibility\"\"\"\n return self is ModelPlatformType.OPENAI_COMPATIBLE_MODEL\n\n @property\n def is_gemini(self) -> bool:\n r\"\"\"Returns whether this platform is Gemini.\"\"\"\n return self is ModelPlatformType.GEMINI\n\n @property\n def is_reka(self) -> bool:\n r\"\"\"Returns whether this platform is Reka.\"\"\"\n return self is ModelPlatformType.REKA\n\n @property\n def is_samba(self) -> bool:\n r\"\"\"Returns whether this platform is Samba Nova.\"\"\"\n return self is ModelPlatformType.SAMBA\n\n @property\n def is_cohere(self) -> bool:\n r\"\"\"Returns whether this platform is Cohere.\"\"\"\n return self is ModelPlatformType.COHERE\n\n @property\n def is_yi(self) -> bool:\n r\"\"\"Returns whether this platform is Yi.\"\"\"\n return self is ModelPlatformType.YI\n\n @property\n def is_qwen(self) -> bool:\n r\"\"\"Returns whether this platform is Qwen.\"\"\"\n return self is ModelPlatformType.QWEN\n\n @property\n def is_nvidia(self) -> bool:\n r\"\"\"Returns whether this platform is Nvidia.\"\"\"\n return self is ModelPlatformType.NVIDIA\n\n @property\n def is_deepseek(self) -> bool:\n r\"\"\"Returns whether this platform is DeepSeek.\"\"\"\n return self is ModelPlatformType.DEEPSEEK\n\n @property\n def is_netmind(self) -> bool:\n r\"\"\"Returns whether this platform is Netmind.\"\"\"\n return self is ModelPlatformType.NETMIND\n\n @property\n def is_ppio(self) -> bool:\n r\"\"\"Returns whether this platform is PPIO.\"\"\"\n return self is ModelPlatformType.PPIO\n\n @property\n def is_internlm(self) -> bool:\n r\"\"\"Returns whether this platform is InternLM.\"\"\"\n return self is ModelPlatformType.INTERNLM\n\n @property\n def is_moonshot(self) -> bool:\n r\"\"\"Returns whether this platform is Moonshot model.\"\"\"\n return self is ModelPlatformType.MOONSHOT\n\n @property\n def is_modelscope(self) -> bool:\n r\"\"\"Returns whether this platform is ModelScope model.\"\"\"\n return self is ModelPlatformType.MODELSCOPE\n\n @property\n def is_siliconflow(self) -> bool:\n r\"\"\"Returns whether this platform is SiliconFlow.\"\"\"\n return self is ModelPlatformType.SILICONFLOW\n\n @property\n def is_aiml(self) -> bool:\n r\"\"\"Returns whether this platform is AIML.\"\"\"\n return self is ModelPlatformType.AIML\n\n @property\n def is_volcano(self) -> bool:\n r\"\"\"Returns whether this platform is volcano.\"\"\"\n return self is ModelPlatformType.VOLCANO\n\n @property\n def is_novita(self) -> bool:\n r\"\"\"Returns whether this platform is Novita.\"\"\"\n return self is ModelPlatformType.NOVITA\n\n @property\n def is_watsonx(self) -> bool:\n r\"\"\"Returns whether this platform is WatsonX.\"\"\"\n return self is ModelPlatformType.WATSONX\n\n @property\n def is_crynux(self) -> bool:\n r\"\"\"Returns whether this platform is Crynux.\"\"\"\n return self is ModelPlatformType.CRYNUX\n\n\nclass AudioModelType(Enum):\n TTS_1 = \"tts-1\"\n TTS_1_HD = \"tts-1-hd\"\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this type of audio models is an OpenAI-released\n model.\"\"\"\n return self in {\n AudioModelType.TTS_1,\n AudioModelType.TTS_1_HD,\n }\n\n\nclass VoiceType(Enum):\n ALLOY = \"alloy\"\n ECHO = \"echo\"\n FABLE = \"fable\"\n ONYX = \"onyx\"\n NOVA = \"nova\"\n SHIMMER = \"shimmer\"\n\n @property\n def is_openai(self) -> bool:\n r\"\"\"Returns whether this type of voice is an OpenAI-released voice.\"\"\"\n return self in {\n VoiceType.ALLOY,\n VoiceType.ECHO,\n VoiceType.FABLE,\n VoiceType.ONYX,\n VoiceType.NOVA,\n VoiceType.SHIMMER,\n }\n\n\nclass JinaReturnFormat(Enum):\n DEFAULT = None\n MARKDOWN = \"markdown\"\n HTML = \"html\"\n TEXT = \"text\"\n\n\nclass HuggingFaceRepoType(str, Enum):\n DATASET = \"dataset\"\n MODEL = \"model\"\n SPACE = \"space\""}}}}