diff --git a/camel/configs/nvidia_config.py b/camel/configs/nvidia_config.py deleted file mode 100644 index e90ea673fb..0000000000 --- a/camel/configs/nvidia_config.py +++ /dev/null @@ -1,70 +0,0 @@ -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= -from __future__ import annotations - -from typing import List, Optional, Union - -from pydantic import Field - -from camel.configs.base_config import BaseConfig -from camel.types import NOT_GIVEN, NotGiven - - -class NvidiaConfig(BaseConfig): - r"""Configuration class for NVIDIA API models. - - This class defines the configuration parameters for NVIDIA's language - models, including temperature, sampling parameters, and response format - settings. - - Args: - stream (bool, optional): Whether to stream the response. - (default: :obj:`False`) - temperature (float, optional): Controls randomness in the response. - Higher values make output more random, lower values make it more - deterministic. Range: [0.0, 2.0]. (default: :obj:`0.7`) - top_p (float, optional): Controls diversity via nucleus sampling. - Range: [0.0, 1.0]. (default: :obj:`0.95`) - presence_penalty (float, optional): Penalizes new tokens based on - whether they appear in the text so far. Range: [-2.0, 2.0]. - (default: :obj:`0.0`) - frequency_penalty (float, optional): Penalizes new tokens based on - their frequency in the text so far. Range: [-2.0, 2.0]. - (default: :obj:`0.0`) - max_tokens (Union[int, NotGiven], optional): Maximum number of tokens - to generate. If not provided, model will use its default maximum. - (default: :obj:`NOT_GIVEN`) - seed (Optional[int], optional): Random seed for deterministic sampling. - (default: :obj:`None`) - tools (Optional[List[Dict]], optional): List of tools available to the - model. This includes tools such as a text editor, a calculator, or - a search engine. (default: :obj:`None`) - tool_choice (Optional[str], optional): Tool choice configuration. - (default: :obj:`None`) - stop (Optional[List[str]], optional): List of stop sequences. - (default: :obj:`None`) - """ - - stream: bool = Field(default=False) - temperature: float = Field(default=0.7) - top_p: float = Field(default=0.95) - presence_penalty: float = Field(default=0.0) - frequency_penalty: float = Field(default=0.0) - max_tokens: Union[int, NotGiven] = Field(default=NOT_GIVEN) - seed: Optional[int] = Field(default=None) - tool_choice: Optional[str] = Field(default=None) - stop: Optional[List[str]] = Field(default=None) - - -NVIDIA_API_PARAMS = {param for param in NvidiaConfig.model_fields.keys()} diff --git a/camel/messages/conversion/alpaca.py b/camel/messages/conversion/alpaca.py deleted file mode 100644 index 316d6bd81c..0000000000 --- a/camel/messages/conversion/alpaca.py +++ /dev/null @@ -1,122 +0,0 @@ -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= - -import re - -from pydantic import BaseModel, Field, field_validator - - -class AlpacaItem(BaseModel): - r"""Represents an instruction-response item in the Alpaca format. - - Appropripate for both cases where input field is empty, or populated. - Provides parsing from string format using the class method from_string(). - - Args: - instruction (str): The instruction/question/prompt - input (str): Input context or examples (put empty string if none) - output (str): The response/answer to the instruction - """ - - instruction: str = Field(description="The instruction/question/prompt") - input: str = Field( - description="Optional context or input for the task." - " For example, when the instruction is \"Summarize the " - "following article\", the input is the article." - ) - output: str = Field(description="The response/answer to the instruction") - - @field_validator('instruction', 'output') - def no_section_markers(cls, value: str) -> str: - r"""Ensures fields don't contain section markers like '### - Response:' - """ - if ( - '### Response' in value - or '### Instruction' in value - or '### Input' in value - ): - raise ValueError("Field cannot contain section markers") - return value.strip() - - @classmethod - def from_string(cls, text: str) -> "AlpacaItem": - r"""Creates an AlpacaItem from a formatted string. - - Args: - text: String in either of these formats: - With input: - ### Instruction: - {instruction} - ### Input: - {input} - ### Response: - {response} - - Without input: - ### Instruction: - {instruction} - ### Response: - {response} - - Returns: - AlpacaItem: Parsed instance - - Raises: - ValueError: text doesn't match expected format or sections missing - """ - # Strip and standardize newlines - text = text.strip().replace('\r\n', '\n') - - # Try to extract sections using regex - instruction_match = re.search( - r'###\s*Instruction:\s*\n(.+?)(?=\n###|\Z)', text, re.DOTALL - ) - input_match = re.search( - r'###\s*Input:\s*\n(.+?)(?=\n###|\Z)', text, re.DOTALL - ) - response_match = re.search( - r'###\s*Response:\s*\n(.+?)(?=\n###|\Z)', text, re.DOTALL - ) - - if not instruction_match or not response_match: - raise ValueError( - "Text must contain '### Instruction:'" - " and '### Response:' sections" - ) - - return cls( - instruction=instruction_match.group(1).strip(), - input=input_match.group(1).strip() if input_match else "", - output=response_match.group(1).strip(), - ) - - def to_string(self) -> str: - r"""Converts the AlpacaItem to its string representation. - - Returns: - str: Formatted string representation with sections markers - """ - return "\n".join( - [ - "### Instruction:", - self.instruction, - "", - "### Input:", - self.input, - "", - "### Response:", - self.output, - ] - ) diff --git a/camel/messages/conversion/conversation_models.py b/camel/messages/conversion/conversation_models.py deleted file mode 100644 index 28dbea5c62..0000000000 --- a/camel/messages/conversion/conversation_models.py +++ /dev/null @@ -1,178 +0,0 @@ -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= - -import json -from typing import Any, Dict, List, Literal - -from pydantic import ( - BaseModel, - Field, - RootModel, - field_validator, - model_validator, -) - - -class ShareGPTMessage(BaseModel): - r"""A single message in ShareGPT format with enhanced validation""" - - from_: Literal["human", "gpt", "system", "tool"] = Field( - alias="from", description="The role of the message sender" - ) - value: str = Field( - min_length=0, - max_length=100000, - description="The content of the message", - ) - - model_config = { - "populate_by_name": True, - "extra": "forbid", - "json_schema_extra": { - "examples": [ - {"from": "human", "value": "What's the weather like today?"} - ] - }, - } - - -class ShareGPTConversation(RootModel): - r"""A full conversation in ShareGPT format with validation""" - - root: List[ShareGPTMessage] - - @model_validator(mode='after') - def validate_conversation_flow(self) -> 'ShareGPTConversation': - r"""Validate the conversation follows logical message order""" - messages = self.root - - if not messages: - raise ValueError("Conversation cannot be empty") - - if messages[0].from_ not in ("system", "human"): - raise ValueError( - "Conversation must start with either system or human message" - ) - - # Validate message sequence - for i in range(1, len(messages)): - curr, prev = messages[i], messages[i - 1] - - if curr.from_ == "tool": - if prev.from_ != "gpt" or "" not in prev.value: - raise ValueError( - f"Tool response at position {i} " - f"must follow an gpt message with a tool call" - ) - - if curr.from_ == "gpt" and prev.from_ not in ( - "human", - "tool", - ): - raise ValueError( - f"Assistant message at position {i} " - f"must follow a human or tool message" - ) - - return self - - def model_dump(self, **kwargs): - return self.root - - def __iter__(self): - return iter(self.root) - - -class ToolCall(BaseModel): - r"""Represents a single tool/function call with validation""" - - name: str = Field( - min_length=1, - max_length=256, - description="The name of the tool to call", - ) - arguments: Dict[str, Any] = Field( - description="The arguments to pass to the tool" - ) - - @field_validator('arguments') - @classmethod - def validate_arguments(cls, v: Dict[str, Any]) -> Dict[str, Any]: - r"""Validate argument structure and content""" - - # Try to serialize arguments to ensure they're JSON-compatible - try: - json.dumps(v) - except (TypeError, ValueError): - raise ValueError("Arguments must be JSON-serializable") - - return v - - model_config = { - "extra": "forbid", - "json_schema_extra": { - "examples": [ - { - "name": "get_weather", - "arguments": {"city": "London", "units": "celsius"}, - } - ] - }, - } - - -class ToolResponse(BaseModel): - r"""Represents a tool/function response with validation. This is a - base class and default implementation for tool responses, for the purpose - of converting between different formats. - """ - - name: str = Field( - min_length=1, - max_length=256, - description="The name of the tool that was called", - ) - content: Any = Field( - description="The response content from the tool." - " Must be JSON serializable literal or object" - ) - - @field_validator('content') - @classmethod - def validate_content(cls, v: Dict[str, Any]) -> Dict[str, Any]: - r"""Validate response content structure""" - - # Ensure content is JSON-serializable - try: - json.dumps(v) - except (TypeError, ValueError): - raise ValueError("Response content must be JSON-serializable") - - return v - - model_config = { - "extra": "forbid", - "json_schema_extra": { - "examples": [ - { - "name": "get_weather", - "content": { - "temperature": 20, - "conditions": "sunny", - "humidity": 65, - }, - } - ] - }, - } diff --git a/camel/models/nvidia_model.py b/camel/models/nvidia_model.py deleted file mode 100644 index 34af71363f..0000000000 --- a/camel/models/nvidia_model.py +++ /dev/null @@ -1,141 +0,0 @@ -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= - -import os -from typing import Any, Dict, List, Optional, Union - -from openai import OpenAI, Stream -from openai.types.chat import ( - ChatCompletion, - ChatCompletionChunk, -) - -from camel.configs import NVIDIA_API_PARAMS, NvidiaConfig -from camel.messages import OpenAIMessage -from camel.models import BaseModelBackend -from camel.types import ModelType -from camel.utils import BaseTokenCounter, OpenAITokenCounter, api_keys_required - - -class NvidiaModel(BaseModelBackend): - r"""NVIDIA API in a unified BaseModelBackend interface. - - Args: - model_type (Union[ModelType, str]): Model for which a backend is - created, one of NVIDIA series. - model_config_dict (Optional[Dict[str, Any]], optional): A dictionary - that will be fed into:obj:`openai.ChatCompletion.create()`. If - :obj:`None`, :obj:`NvidiaConfig().as_dict()` will be used. - (default: :obj:`None`) - api_key (Optional[str], optional): The API key for authenticating with - the NVIDIA service. (default: :obj:`None`) - url (Optional[str], optional): The url to the NVIDIA service. - (default: :obj:`None`) - token_counter (Optional[BaseTokenCounter], optional): Token counter to - use for the model. If not provided, :obj:`OpenAITokenCounter( - ModelType.GPT_4)` will be used. - (default: :obj:`None`) - """ - - def __init__( - self, - model_type: Union[ModelType, str], - model_config_dict: Optional[Dict[str, Any]] = None, - api_key: Optional[str] = None, - url: Optional[str] = None, - token_counter: Optional[BaseTokenCounter] = None, - ) -> None: - if model_config_dict is None: - model_config_dict = NvidiaConfig().as_dict() - api_key = api_key or os.environ.get("NVIDIA_API_KEY") - url = url or os.environ.get( - "NVIDIA_API_BASE_URL", "https://integrate.api.nvidia.com/v1" - ) - super().__init__( - model_type, model_config_dict, api_key, url, token_counter - ) - self._client = OpenAI( - timeout=60, - max_retries=3, - api_key=self._api_key, - base_url=self._url, - ) - - @api_keys_required("NVIDIA_API_KEY") - def run( - self, - messages: List[OpenAIMessage], - ) -> Union[ChatCompletion, Stream[ChatCompletionChunk]]: - r"""Runs inference of NVIDIA chat completion. - - Args: - messages (List[OpenAIMessage]): Message list with the chat history - in OpenAI API format. - - Returns: - Union[ChatCompletion, Stream[ChatCompletionChunk]]: - `ChatCompletion` in the non-stream mode, or - `Stream[ChatCompletionChunk]` in the stream mode. - """ - - # Remove tool-related parameters if no tools are specified - config = dict(self.model_config_dict) - if not config.get('tools'): # None or empty list - config.pop('tools', None) - config.pop('tool_choice', None) - - response = self._client.chat.completions.create( - messages=messages, - model=self.model_type, - **config, - ) - return response - - @property - def token_counter(self) -> BaseTokenCounter: - r"""Initialize the token counter for the model backend. - - Returns: - OpenAITokenCounter: The token counter following the model's - tokenization style. - """ - - if not self._token_counter: - self._token_counter = OpenAITokenCounter(ModelType.GPT_4O_MINI) - return self._token_counter - - def check_model_config(self): - r"""Check whether the model configuration contains any - unexpected arguments to NVIDIA API. - - Raises: - ValueError: If the model configuration dictionary contains any - unexpected arguments to NVIDIA API. - """ - for param in self.model_config_dict: - if param not in NVIDIA_API_PARAMS: - raise ValueError( - f"Unexpected argument `{param}` is " - "input into NVIDIA model backend." - ) - - @property - def stream(self) -> bool: - r"""Returns whether the model is in stream mode, which sends partial - results each time. - - Returns: - bool: Whether the model is in stream mode. - """ - return self.model_config_dict.get('stream', False) diff --git a/camel/toolkits/meshy_toolkit.py b/camel/toolkits/meshy_toolkit.py deleted file mode 100644 index cf49e01f91..0000000000 --- a/camel/toolkits/meshy_toolkit.py +++ /dev/null @@ -1,185 +0,0 @@ -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= - -import os -from typing import Any, Dict - -import requests - -from camel.toolkits.base import BaseToolkit -from camel.utils import api_keys_required - - -class MeshyToolkit(BaseToolkit): - r"""A class representing a toolkit for 3D model generation using Meshy. - - This class provides methods that handle text/image to 3D model - generation using Meshy. - - Call the generate_3d_model_complete method to generate a refined 3D model. - - Ref: - https://docs.meshy.ai/api-text-to-3d-beta#create-a-text-to-3d-preview-task - """ - - @api_keys_required("MESHY_API_KEY") - def __init__(self): - r"""Initializes the MeshyToolkit with the API key from the - environment. - """ - self.api_key = os.getenv('MESHY_API_KEY') - - def generate_3d_preview( - self, prompt: str, art_style: str, negative_prompt: str - ) -> Dict[str, Any]: - r"""Generates a 3D preview using the Meshy API. - - Args: - prompt (str): Description of the object. - art_style (str): Art style for the 3D model. - negative_prompt (str): What the model should not look like. - - Returns: - Dict[str, Any]: The result property of the response contains the - task id of the newly created Text to 3D task. - """ - payload = { - "mode": "preview", - "prompt": prompt, - "art_style": art_style, - "negative_prompt": negative_prompt, - } - headers = {"Authorization": f"Bearer {self.api_key}"} - - response = requests.post( - "https://api.meshy.ai/v2/text-to-3d", - headers=headers, - json=payload, - ) - response.raise_for_status() - return response.json() - - def refine_3d_model(self, preview_task_id: str) -> Dict[str, Any]: - r"""Refines a 3D model using the Meshy API. - - Args: - preview_task_id (str): The task ID of the preview to refine. - - Returns: - Dict[str, Any]: The response from the Meshy API. - """ - payload = {"mode": "refine", "preview_task_id": preview_task_id} - headers = {"Authorization": f"Bearer {self.api_key}"} - - response = requests.post( - "https://api.meshy.ai/v2/text-to-3d", - headers=headers, - json=payload, - ) - response.raise_for_status() - return response.json() - - def get_task_status(self, task_id: str) -> Dict[str, Any]: - r"""Retrieves the status or result of a specific 3D model generation - task using the Meshy API. - - Args: - task_id (str): The ID of the task to retrieve. - - Returns: - Dict[str, Any]: The response from the Meshy API. - """ - headers = {"Authorization": f"Bearer {self.api_key}"} - - response = requests.get( - f"https://api.meshy.ai/v2/text-to-3d/{task_id}", - headers=headers, - ) - response.raise_for_status() - return response.json() - - def wait_for_task_completion( - self, task_id: str, polling_interval: int = 10, timeout: int = 3600 - ) -> Dict[str, Any]: - r"""Waits for a task to complete by polling its status. - - Args: - task_id (str): The ID of the task to monitor. - polling_interval (int): Seconds to wait between status checks. - (default::obj:`10`) - timeout (int): Maximum seconds to wait before timing out. - (default::obj:`3600`) - - Returns: - Dict[str, Any]: Final response from the API when task completes. - - Raises: - TimeoutError: If task doesn't complete within timeout period. - RuntimeError: If task fails or is canceled. - """ - import time - - start_time = time.time() - - while True: - if time.time() - start_time > timeout: - raise TimeoutError( - f"Task {task_id} timed out after {timeout} seconds" - ) - - response = self.get_task_status(task_id) - status = response.get("status") # Direct access to status field - elapsed = int(time.time() - start_time) - - print(f"Status after {elapsed}s: {status}") - - if status == "SUCCEEDED": - return response - elif status in [ - "FAILED", - "CANCELED", - ]: # Also updating these status values - raise RuntimeError(f"Task {task_id} {status}") - - time.sleep(polling_interval) - - def generate_3d_model_complete( - self, prompt: str, art_style: str, negative_prompt: str - ) -> Dict[str, Any]: - r"""Generates a complete 3D model by handling preview and refinement - stages - - Args: - prompt (str): Description of the object. - art_style (str): Art style for the 3D model. - negative_prompt (str): What the model should not look like. - - Returns: - Dict[str, Any]: The final refined 3D model response. - """ - # Generate preview - preview_response = self.generate_3d_preview( - prompt, art_style, negative_prompt - ) - preview_task_id = str(preview_response.get("result")) - - # Wait for preview completion - self.wait_for_task_completion(preview_task_id) - - # Start refinement - refine_response = self.refine_3d_model(preview_task_id) - refine_task_id = str(refine_response.get("result")) - - # Wait for refinement completion and return final result - return self.wait_for_task_completion(refine_task_id) diff --git a/examples/toolkits/meshy_toolkit.py b/examples/toolkits/meshy_toolkit.py deleted file mode 100644 index 5cc5119053..0000000000 --- a/examples/toolkits/meshy_toolkit.py +++ /dev/null @@ -1,62 +0,0 @@ -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. ========= -from camel.toolkits import MeshyToolkit - -toolkit = MeshyToolkit() - -# Example data for testing -prompt = "A figuring of Tin tin the cartoon character" -art_style = "realistic" -negative_prompt = "low quality, low resolution, low poly, ugly" - -# 3D model generation -print("Starting 3D model generation...") -final_response = toolkit.generate_3d_model_complete( - prompt=prompt, art_style=art_style, negative_prompt=negative_prompt -) -print("\nFinal Response:", final_response) -# ruff: noqa: E501 -""" -========================================================================== -Starting 3D model generation... -Status after 0s: PENDING -Status after 11s: IN_PROGRESS -Status after 22s: IN_PROGRESS -Status after 32s: SUCCEEDED -Status after 0s: PENDING -Status after 11s: IN_PROGRESS -Status after 21s: IN_PROGRESS -Status after 32s: IN_PROGRESS -Status after 43s: IN_PROGRESS -Status after 53s: IN_PROGRESS -Status after 64s: IN_PROGRESS -Status after 74s: IN_PROGRESS -Status after 85s: IN_PROGRESS -Status after 95s: IN_PROGRESS -Status after 106s: IN_PROGRESS -Status after 117s: SUCCEEDED - -Final Response: {'id': '01939144-7dea-73c7-af06-efa79c83243f', 'mode': -'refine', 'name': '', 'seed': 1733308970, 'art_style': 'realistic', -'texture_richness': 'high', 'prompt': 'A figuring of Tin tin the cartoon -character', 'negative_prompt': 'low quality, low resolution, low poly, ugly', -'status': 'SUCCEEDED', 'created_at': 1733309005313, 'progress': 100, -'started_at': 1733309006267, 'finished_at': 1733309113474, 'task_error': None, -'model_urls': {'glb': 'https://assets.meshy.ai/5e05026a-0e91-4073-83fe-0263b1b4d348/tasks/01939144-7dea-73c7-af06-efa79c83243f/output/model.glb?Expires=4886870400&Signature=TEbWpN8sFZOf1FKWBVxKNdT2Ltm1Ma6vHuUUpBh6rZaAzfTBQPKvV2i7RmD~wwaebbQSBvVVagF4j587tNKNwHPqkGtpBjBu2q43n4lWM6W--RxSqbOCvVZ54PiAzzlVjM9PzPz-MasrWQtYipm5qJ5tsWd7XoxB6Wv2tZMZEWsftdLxmXdp9SuoBcu5NM~MRnyvhEYPmwU9uCAKfh4FZ14mhfx6TeDpCprYh1ngnlkLzDXk5Mdw0HJ1zuYpnkCOUtth84p6Oq5aU0HtWtUVd2tLi53rqKn9QC0qxcH7QlPxxI1aoUtzqaMXXiqCGylzZuPTZILhdFWeAoiEtCOLZw__&Key-Pair-Id=KL5I0C8H7HX83', 'fbx': 'https://assets.meshy.ai/5e05026a-0e91-4073-83fe-0263b1b4d348/tasks/01939144-7dea-73c7-af06-efa79c83243f/output/model.fbx?Expires=4886870400&Signature=jGOPhF8FL1wa9mVbodNoq1jMVzi2gklWRrrl2qWAZvWAhadc4wgjmgTweBKsNiO~KMTGzCiey7iqSIGm6dDEYAMv72HExpIO7I8HwAVPp4KwhzORzwr6OcEoY9-7fFR9yEg~WqnWewmdkrcnUVHHx2Z9imkDkIhISn1IOERkum48mTemlyejb87CXGV14uX3hxIVKle4at6S8tMUfpXhCdZ3aIxmgt9Dpsobol92XtQbpC-JhJSOgMNBWtAH3OUXAgECsYrRRZND9gcZZkUZlXHHZt439JsU8MPoXZd4RQ0OGn~vb6W51rvQ904ErsYZf47dLYNswaxb6Se3oKm~zw__&Key-Pair-Id=KL5I0C8H7HX83', 'usdz': 'https://assets.meshy.ai/5e05026a-0e91-4073-83fe-0263b1b4d348/tasks/01939144-7dea-73c7-af06-efa79c83243f/output/model.usdz?Expires=4886870400&Signature=ICOOIH6EDVdy9LYCk-azYqBWtl6t9v2xZpRk8C8kQKa38jUXdukjoLLN469VP5a7rdIKinLA~I5-hMr-kd-MEmwJzE3JKw2ojNimYPa5Uvnr3R~4S~2fQgCPWfn2xVkt6Cvfx~Qj8~ZNVxMj0jvnKkIySRHYaqvCxMfASHCB7Kz9LN3lBWuT709pEnQ6mtwLJWybLlIJkMFOVoapw~epIgWBtJjhMNwPCzXswUddKSdirOHIm8JRoN3~Ha99oxo4nSN5tyf3u2fWLxGOTeAyp7Hcq97gMkdqjuNc14k2n7fPULgbSCkHepLIG8GQrNLMfA6hkphkIj0LdjC6AQ7pvg__&Key-Pair-Id=KL5I0C8H7HX83', 'obj': 'https://assets.meshy.ai/5e05026a-0e91-4073-83fe-0263b1b4d348/tasks/01939144-7dea-73c7-af06-efa79c83243f/output/model.obj?Expires=4886870400&Signature=a53mEQASL7jRU8Xz5WhN-~d3~74BlBlqDMufryX-j1~jXTgbMEEhY2dC5R7dHHHJbJ4ns9GQ8cbjxcCImVvjkiLvPYZ-lraLaqMnbG~hatsZNv6wDZxTson8jsiqTSHaLnamp83zycLotM~zrUW0DIHGoFWvf9DPTKqy4Z0ZAOxOsA9qfAmJI6k2CVHLu0hMRLAjm3f8KA4j90kJBBVuYvABZi27hP-aURhD09zoAMp~AsrXSKxFjd5wcYqKko78qch2K2H5NaAUGhsKbuNmBMFaxc0C5dKgSlKufWmib86vUOe1dYLQyqGTS85u5dVQSwFrDY5gyugGJ4TH-aVQVw__&Key-Pair-Id=KL5I0C8H7HX83', 'mtl': 'https://assets.meshy.ai/5e05026a-0e91-4073-83fe-0263b1b4d348/tasks/01939144-7dea-73c7-af06-efa79c83243f/output/model.mtl?Expires=4886870400&Signature=FnY3cNMqEymvBw~33riU~HkVIifWKEUh0ndV90VaWMnKczU~Wqng7AYTqwywr6PNQDuFL~iQFw-y6qvklsV9I0aTg8OoYQ3dfCaRqydwUbN80aonk~fwpAJUwBxqbhhN4n9T~7WTX-pyo0w5vQ09wte4G-4yAIUEM7qlOwZohdfK2a~EIhnq9WiV92TuGtm0c4x5n6png9ZjX5pHnp~a77UCBJlIQ1teN5Rb3I9HFh4sbUGdcXUas7B9EIq4YiabjO9vf5FGwicb2XQ-YxJFJJdEJwbBp6l6iZCbSk-WijmIWmyD~8A~jhTNwlG9UHR5qTsnprntgoRyLdTRSXvDzg__&Key-Pair-Id=KL5I0C8H7HX83'}, -'thumbnail_url': 'https://assets.meshy.ai/5e05026a-0e91-4073-83fe-0263b1b4d348/tasks/01939144-7dea-73c7-af06-efa79c83243f/output/preview.png?Expires=4886870400&Signature=B16evi199mig4RTFq0FVPrHGkpjpPudRpLfpcY2FxJIkIFYg42-v8BfsL3eWAM-XDlDqahPSXtqqm6emVkSu550iPqo2yy-URoDifiIl5petEy~42nHtc1-dZB1HcEvtcyycHOjmk1y8zQfZBgQ8cjGq0Ds19xSdOXIo7-~QDPWhUGUTreJvBNg17GitgvcfYbGj2g6gibYJWjwatM7A6yHhq3d53N8eDcmO5L6dBH3VwUFTxDWBQXwUT7aXkS7dsQ7Wz5CkIbbH~T-4Pn5KpdJy1Kf1Lrh1YpOUN4T7JI8Ot5urYKYRj4cZ96xpDD9gicPGvgrRaicFyb1sSwW2ow__&Key-Pair-Id=KL5I0C8H7HX83', -'video_url': 'https://assets.meshy.ai/5e05026a-0e91-4073-83fe-0263b1b4d348/tasks/01939144-7dea-73c7-af06-efa79c83243f/output/output.mp4?Expires=4886870400&Signature=r8t11N9~XGzNfuW3KowxarSpr7hC8eQb0kzkKADOz3hdTA9vAqBdv5AVdMGDlMmH9IP4R60UCnVNT6scA1EeN3FZLXaHaWbsxHDuc4XdUk7DE7AbwUKSbl~YdUSu5-RkNu6vaMHTiB55XubUJhv9ReB25a6Ifee0rf1ulGs-amFSMlL~eNPq6HTUI6NGAqi1p~VeFzE53JV5sWvU2JYnbGe8kzruC705z1LiCU-9isWzJGuOIy~RpiVfYzSmgh4xeILaYKpxR2ZM2uVtbi6snl~aYsqiKMIIMxMg-aZDWn-f5voiWaCL1OUV5fxbI82ZRJNd5DSlVjI~umqZZIl-iw__&Key-Pair-Id=KL5I0C8H7HX83', -'texture_urls': [{'base_color': 'https://assets.meshy.ai/5e05026a-0e91-4073-83fe-0263b1b4d348/tasks/01939144-7dea-73c7-af06-efa79c83243f/output/texture_0.png?Expires=4886870400&Signature=Q8SGRrnE00-mGHCAcIOUUAig~YtTJqVx1n2IqFFbXBNUPvf~hsTYzcKgC2wQjF25tj0D6yQ8BiIktN9WjsKu0SnbeED~ofHIA0quheMjwHL~hfdj63LGWkMumVEjE2ZVwDv-DdlROF3ayw5hQxzlRbcHwXLq0n2xMHmj-WetyiYBKCcJbXbZMOAtlo8e40d21CGMnjImduCvdwhpqwNKUx4MwHeM2W0GW4OC94AoSF8AccHJeQPD2gdu7JHoTuZFjcqS-9YCjmHT7Y5Xg7rmeNYz40O21sYci0b54NvBDzX-6HvydjqtY-ofudppaxlC77Zd~FaVcCz5rH2J43cdLg__&Key-Pair-Id=KL5I0C8H7HX83'}]} -(camel-ai-py3.12) -========================================================================== -"""