camel-ai 0.2.65__py3-none-any.whl → 0.2.83a6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of camel-ai might be problematic. Click here for more details.
- camel/__init__.py +3 -3
- camel/agents/__init__.py +2 -2
- camel/agents/_types.py +9 -4
- camel/agents/_utils.py +40 -2
- camel/agents/base.py +2 -2
- camel/agents/chat_agent.py +5107 -995
- camel/agents/critic_agent.py +2 -2
- camel/agents/deductive_reasoner_agent.py +56 -56
- camel/agents/embodied_agent.py +2 -2
- camel/agents/knowledge_graph_agent.py +20 -20
- camel/agents/mcp_agent.py +35 -36
- camel/agents/multi_hop_generator_agent.py +3 -3
- camel/agents/programmed_agent_instruction.py +2 -2
- camel/agents/repo_agent.py +4 -3
- camel/agents/role_assignment_agent.py +2 -2
- camel/agents/search_agent.py +2 -2
- camel/agents/task_agent.py +2 -2
- camel/agents/tool_agents/__init__.py +2 -2
- camel/agents/tool_agents/base.py +2 -2
- camel/agents/tool_agents/hugging_face_tool_agent.py +3 -3
- camel/benchmarks/__init__.py +2 -2
- camel/benchmarks/apibank.py +5 -5
- camel/benchmarks/apibench.py +2 -2
- camel/benchmarks/base.py +2 -2
- camel/benchmarks/browsecomp.py +44 -33
- camel/benchmarks/gaia.py +17 -13
- camel/benchmarks/mock_website/README.md +1 -3
- camel/benchmarks/mock_website/mock_web.py +2 -2
- camel/benchmarks/mock_website/requirements.txt +1 -1
- camel/benchmarks/mock_website/shopping_mall/app.py +2 -2
- camel/benchmarks/mock_website/task.json +1 -1
- camel/benchmarks/nexus.py +3 -3
- camel/benchmarks/ragbench.py +2 -2
- camel/bots/__init__.py +2 -2
- camel/bots/discord/__init__.py +2 -2
- camel/bots/discord/discord_app.py +2 -2
- camel/bots/discord/discord_installation.py +2 -2
- camel/bots/discord/discord_store.py +3 -3
- camel/bots/slack/__init__.py +2 -2
- camel/bots/slack/models.py +4 -4
- camel/bots/slack/slack_app.py +2 -2
- camel/bots/telegram_bot.py +2 -2
- camel/configs/__init__.py +29 -2
- camel/configs/aihubmix_config.py +90 -0
- camel/configs/aiml_config.py +2 -2
- camel/configs/amd_config.py +70 -0
- camel/configs/anthropic_config.py +2 -2
- camel/configs/base_config.py +2 -2
- camel/configs/bedrock_config.py +5 -3
- camel/configs/cerebras_config.py +98 -0
- camel/configs/cohere_config.py +2 -2
- camel/configs/cometapi_config.py +106 -0
- camel/configs/crynux_config.py +2 -2
- camel/configs/deepseek_config.py +9 -8
- camel/configs/function_gemma_config.py +59 -0
- camel/configs/gemini_config.py +6 -4
- camel/configs/groq_config.py +6 -4
- camel/configs/internlm_config.py +6 -4
- camel/configs/litellm_config.py +2 -2
- camel/configs/lmstudio_config.py +6 -4
- camel/configs/minimax_config.py +95 -0
- camel/configs/mistral_config.py +2 -2
- camel/configs/modelscope_config.py +5 -3
- camel/configs/moonshot_config.py +2 -2
- camel/configs/nebius_config.py +105 -0
- camel/configs/netmind_config.py +2 -2
- camel/configs/novita_config.py +2 -2
- camel/configs/nvidia_config.py +2 -2
- camel/configs/ollama_config.py +2 -2
- camel/configs/openai_config.py +5 -3
- camel/configs/openrouter_config.py +6 -4
- camel/configs/ppio_config.py +2 -2
- camel/configs/qianfan_config.py +85 -0
- camel/configs/qwen_config.py +2 -2
- camel/configs/reka_config.py +2 -2
- camel/configs/samba_config.py +6 -4
- camel/configs/sglang_config.py +2 -2
- camel/configs/siliconflow_config.py +2 -2
- camel/configs/togetherai_config.py +2 -2
- camel/configs/vllm_config.py +4 -2
- camel/configs/watsonx_config.py +2 -2
- camel/configs/yi_config.py +6 -4
- camel/configs/zhipuai_config.py +6 -4
- camel/data_collectors/__init__.py +2 -2
- camel/data_collectors/alpaca_collector.py +18 -9
- camel/data_collectors/base.py +2 -2
- camel/data_collectors/sharegpt_collector.py +2 -2
- camel/datagen/__init__.py +2 -2
- camel/datagen/cot_datagen.py +3 -3
- camel/datagen/evol_instruct/__init__.py +2 -2
- camel/datagen/evol_instruct/evol_instruct.py +2 -2
- camel/datagen/evol_instruct/scorer.py +12 -12
- camel/datagen/evol_instruct/templates.py +16 -16
- camel/datagen/self_improving_cot.py +5 -5
- camel/datagen/self_instruct/__init__.py +2 -2
- camel/datagen/self_instruct/filter/__init__.py +2 -2
- camel/datagen/self_instruct/filter/filter_function.py +2 -2
- camel/datagen/self_instruct/filter/filter_registry.py +2 -2
- camel/datagen/self_instruct/filter/instruction_filter.py +2 -2
- camel/datagen/self_instruct/self_instruct.py +2 -2
- camel/datagen/self_instruct/templates.py +47 -47
- camel/datagen/source2synth/__init__.py +2 -2
- camel/datagen/source2synth/data_processor.py +2 -2
- camel/datagen/source2synth/models.py +2 -2
- camel/datagen/source2synth/user_data_processor_config.py +2 -2
- camel/datahubs/__init__.py +2 -2
- camel/datahubs/base.py +2 -2
- camel/datahubs/huggingface.py +2 -2
- camel/datahubs/models.py +2 -2
- camel/datasets/__init__.py +2 -2
- camel/datasets/base_generator.py +41 -12
- camel/datasets/few_shot_generator.py +18 -18
- camel/datasets/models.py +2 -2
- camel/datasets/self_instruct_generator.py +2 -2
- camel/datasets/static_dataset.py +2 -2
- camel/embeddings/__init__.py +2 -2
- camel/embeddings/azure_embedding.py +2 -2
- camel/embeddings/base.py +2 -2
- camel/embeddings/gemini_embedding.py +2 -2
- camel/embeddings/jina_embedding.py +2 -2
- camel/embeddings/mistral_embedding.py +2 -2
- camel/embeddings/openai_compatible_embedding.py +2 -2
- camel/embeddings/openai_embedding.py +2 -2
- camel/embeddings/sentence_transformers_embeddings.py +2 -2
- camel/embeddings/together_embedding.py +2 -2
- camel/embeddings/vlm_embedding.py +2 -2
- camel/environments/__init__.py +14 -2
- camel/environments/models.py +2 -2
- camel/environments/multi_step.py +2 -2
- camel/environments/rlcards_env.py +860 -0
- camel/environments/single_step.py +30 -5
- camel/environments/tic_tac_toe.py +3 -3
- camel/extractors/__init__.py +2 -2
- camel/extractors/base.py +2 -2
- camel/extractors/python_strategies.py +2 -2
- camel/generators.py +2 -2
- camel/human.py +2 -2
- camel/interpreters/__init__.py +4 -2
- camel/interpreters/base.py +2 -2
- camel/interpreters/docker/Dockerfile +14 -24
- camel/interpreters/docker_interpreter.py +5 -4
- camel/interpreters/e2b_interpreter.py +36 -3
- camel/interpreters/internal_python_interpreter.py +53 -4
- camel/interpreters/interpreter_error.py +2 -2
- camel/interpreters/ipython_interpreter.py +2 -2
- camel/interpreters/microsandbox_interpreter.py +395 -0
- camel/interpreters/subprocess_interpreter.py +2 -2
- camel/loaders/__init__.py +13 -4
- camel/loaders/apify_reader.py +2 -2
- camel/loaders/base_io.py +2 -2
- camel/loaders/base_loader.py +85 -0
- camel/loaders/chunkr_reader.py +11 -2
- camel/loaders/crawl4ai_reader.py +2 -2
- camel/loaders/firecrawl_reader.py +6 -6
- camel/loaders/jina_url_reader.py +2 -2
- camel/loaders/markitdown.py +2 -2
- camel/loaders/mineru_extractor.py +2 -2
- camel/loaders/mistral_reader.py +2 -2
- camel/loaders/scrapegraph_reader.py +2 -2
- camel/loaders/unstructured_io.py +2 -2
- camel/logger.py +5 -5
- camel/memories/__init__.py +2 -2
- camel/memories/agent_memories.py +86 -3
- camel/memories/base.py +36 -2
- camel/memories/blocks/__init__.py +2 -2
- camel/memories/blocks/chat_history_block.py +125 -7
- camel/memories/blocks/vectordb_block.py +10 -3
- camel/memories/context_creators/__init__.py +2 -2
- camel/memories/context_creators/score_based.py +109 -230
- camel/memories/records.py +90 -10
- camel/messages/__init__.py +2 -2
- camel/messages/base.py +178 -43
- camel/messages/conversion/__init__.py +2 -2
- camel/messages/conversion/alpaca.py +2 -2
- camel/messages/conversion/conversation_models.py +2 -2
- camel/messages/conversion/sharegpt/__init__.py +2 -2
- camel/messages/conversion/sharegpt/function_call_formatter.py +2 -2
- camel/messages/conversion/sharegpt/hermes/__init__.py +2 -2
- camel/messages/conversion/sharegpt/hermes/hermes_function_formatter.py +2 -2
- camel/messages/func_message.py +54 -17
- camel/models/__init__.py +18 -2
- camel/models/_utils.py +3 -3
- camel/models/aihubmix_model.py +83 -0
- camel/models/aiml_model.py +11 -18
- camel/models/amd_model.py +101 -0
- camel/models/anthropic_model.py +127 -20
- camel/models/aws_bedrock_model.py +12 -35
- camel/models/azure_openai_model.py +214 -115
- camel/models/base_audio_model.py +5 -3
- camel/models/base_model.py +378 -31
- camel/models/cerebras_model.py +83 -0
- camel/models/cohere_model.py +18 -49
- camel/models/cometapi_model.py +83 -0
- camel/models/crynux_model.py +11 -18
- camel/models/deepseek_model.py +20 -84
- camel/models/fish_audio_model.py +8 -2
- camel/models/function_gemma_model.py +889 -0
- camel/models/gemini_model.py +391 -52
- camel/models/groq_model.py +11 -19
- camel/models/internlm_model.py +11 -18
- camel/models/litellm_model.py +57 -49
- camel/models/lmstudio_model.py +17 -20
- camel/models/minimax_model.py +83 -0
- camel/models/mistral_model.py +20 -47
- camel/models/model_factory.py +39 -3
- camel/models/model_manager.py +26 -8
- camel/models/modelscope_model.py +13 -193
- camel/models/moonshot_model.py +183 -21
- camel/models/nebius_model.py +83 -0
- camel/models/nemotron_model.py +19 -9
- camel/models/netmind_model.py +11 -18
- camel/models/novita_model.py +11 -18
- camel/models/nvidia_model.py +11 -18
- camel/models/ollama_model.py +14 -21
- camel/models/openai_audio_models.py +2 -2
- camel/models/openai_compatible_model.py +190 -71
- camel/models/openai_model.py +192 -86
- camel/models/openrouter_model.py +11 -19
- camel/models/ppio_model.py +11 -18
- camel/models/qianfan_model.py +89 -0
- camel/models/qwen_model.py +13 -193
- camel/models/reka_model.py +23 -49
- camel/models/reward/__init__.py +2 -2
- camel/models/reward/base_reward_model.py +2 -2
- camel/models/reward/evaluator.py +2 -2
- camel/models/reward/nemotron_model.py +2 -2
- camel/models/reward/skywork_model.py +2 -2
- camel/models/samba_model.py +50 -75
- camel/models/sglang_model.py +90 -68
- camel/models/siliconflow_model.py +12 -35
- camel/models/stub_model.py +10 -7
- camel/models/togetherai_model.py +11 -18
- camel/models/vllm_model.py +10 -18
- camel/models/volcano_model.py +158 -19
- camel/models/watsonx_model.py +9 -47
- camel/models/yi_model.py +11 -18
- camel/models/zhipuai_model.py +70 -18
- camel/parsers/__init__.py +18 -0
- camel/parsers/mcp_tool_call_parser.py +176 -0
- camel/personas/__init__.py +2 -2
- camel/personas/persona.py +2 -2
- camel/personas/persona_hub.py +2 -2
- camel/prompts/__init__.py +2 -2
- camel/prompts/ai_society.py +2 -2
- camel/prompts/base.py +2 -2
- camel/prompts/code.py +2 -2
- camel/prompts/evaluation.py +2 -2
- camel/prompts/generate_text_embedding_data.py +2 -2
- camel/prompts/image_craft.py +2 -2
- camel/prompts/misalignment.py +2 -2
- camel/prompts/multi_condition_image_craft.py +2 -2
- camel/prompts/object_recognition.py +2 -2
- camel/prompts/persona_hub.py +3 -3
- camel/prompts/prompt_templates.py +2 -2
- camel/prompts/role_description_prompt_template.py +2 -2
- camel/prompts/solution_extraction.py +8 -8
- camel/prompts/task_prompt_template.py +2 -2
- camel/prompts/translation.py +2 -2
- camel/prompts/video_description_prompt.py +3 -3
- camel/responses/__init__.py +2 -2
- camel/responses/agent_responses.py +2 -2
- camel/retrievers/__init__.py +2 -2
- camel/retrievers/auto_retriever.py +3 -2
- camel/retrievers/base.py +2 -2
- camel/retrievers/bm25_retriever.py +2 -2
- camel/retrievers/cohere_rerank_retriever.py +2 -2
- camel/retrievers/hybrid_retrival.py +2 -2
- camel/retrievers/vector_retriever.py +2 -2
- camel/runtimes/Dockerfile.multi-toolkit +90 -0
- camel/runtimes/__init__.py +2 -2
- camel/runtimes/api.py +79 -23
- camel/runtimes/base.py +2 -2
- camel/runtimes/configs.py +13 -13
- camel/runtimes/daytona_runtime.py +17 -18
- camel/runtimes/docker_runtime.py +12 -12
- camel/runtimes/llm_guard_runtime.py +26 -26
- camel/runtimes/remote_http_runtime.py +11 -11
- camel/runtimes/ubuntu_docker_runtime.py +2 -2
- camel/runtimes/utils/__init__.py +2 -2
- camel/runtimes/utils/function_risk_toolkit.py +2 -2
- camel/runtimes/utils/ignore_risk_toolkit.py +2 -2
- camel/schemas/__init__.py +2 -2
- camel/schemas/base.py +2 -2
- camel/schemas/openai_converter.py +3 -3
- camel/schemas/outlines_converter.py +2 -2
- camel/services/agent_openapi_server.py +380 -0
- camel/societies/__init__.py +4 -2
- camel/societies/babyagi_playing.py +2 -2
- camel/societies/role_playing.py +201 -80
- camel/societies/workforce/__init__.py +10 -3
- camel/societies/workforce/base.py +2 -2
- camel/societies/workforce/events.py +145 -0
- camel/societies/workforce/prompts.py +259 -33
- camel/societies/workforce/role_playing_worker.py +88 -31
- camel/societies/workforce/single_agent_worker.py +638 -40
- camel/societies/workforce/structured_output_handler.py +512 -0
- camel/societies/workforce/task_channel.py +182 -38
- camel/societies/workforce/utils.py +780 -65
- camel/societies/workforce/worker.py +92 -26
- camel/societies/workforce/workflow_memory_manager.py +1746 -0
- camel/societies/workforce/workforce.py +5354 -372
- camel/societies/workforce/workforce_callback.py +103 -0
- camel/societies/workforce/workforce_logger.py +647 -0
- camel/societies/workforce/workforce_metrics.py +33 -0
- camel/storages/__init__.py +6 -2
- camel/storages/graph_storages/__init__.py +2 -2
- camel/storages/graph_storages/base.py +2 -2
- camel/storages/graph_storages/graph_element.py +2 -2
- camel/storages/graph_storages/nebula_graph.py +4 -4
- camel/storages/graph_storages/neo4j_graph.py +7 -7
- camel/storages/key_value_storages/__init__.py +2 -2
- camel/storages/key_value_storages/base.py +2 -2
- camel/storages/key_value_storages/in_memory.py +2 -2
- camel/storages/key_value_storages/json.py +17 -4
- camel/storages/key_value_storages/mem0_cloud.py +50 -49
- camel/storages/key_value_storages/redis.py +2 -2
- camel/storages/object_storages/__init__.py +2 -2
- camel/storages/object_storages/amazon_s3.py +2 -2
- camel/storages/object_storages/azure_blob.py +2 -2
- camel/storages/object_storages/base.py +2 -2
- camel/storages/object_storages/google_cloud.py +3 -3
- camel/storages/vectordb_storages/__init__.py +8 -2
- camel/storages/vectordb_storages/base.py +2 -2
- camel/storages/vectordb_storages/chroma.py +731 -0
- camel/storages/vectordb_storages/faiss.py +2 -2
- camel/storages/vectordb_storages/milvus.py +2 -2
- camel/storages/vectordb_storages/oceanbase.py +15 -15
- camel/storages/vectordb_storages/pgvector.py +349 -0
- camel/storages/vectordb_storages/qdrant.py +6 -6
- camel/storages/vectordb_storages/surreal.py +372 -0
- camel/storages/vectordb_storages/tidb.py +11 -8
- camel/storages/vectordb_storages/weaviate.py +2 -2
- camel/tasks/__init__.py +2 -2
- camel/tasks/task.py +348 -26
- camel/tasks/task_prompt.py +3 -3
- camel/terminators/__init__.py +2 -2
- camel/terminators/base.py +2 -2
- camel/terminators/response_terminator.py +2 -2
- camel/terminators/token_limit_terminator.py +2 -2
- camel/toolkits/__init__.py +57 -10
- camel/toolkits/aci_toolkit.py +66 -21
- camel/toolkits/arxiv_toolkit.py +8 -8
- camel/toolkits/ask_news_toolkit.py +2 -2
- camel/toolkits/async_browser_toolkit.py +4 -4
- camel/toolkits/audio_analysis_toolkit.py +3 -3
- camel/toolkits/base.py +106 -6
- camel/toolkits/bohrium_toolkit.py +2 -2
- camel/toolkits/browser_toolkit.py +34 -21
- camel/toolkits/browser_toolkit_commons.py +4 -4
- camel/toolkits/code_execution.py +31 -4
- camel/toolkits/context_summarizer_toolkit.py +684 -0
- camel/toolkits/craw4ai_toolkit.py +93 -0
- camel/toolkits/dappier_toolkit.py +12 -8
- camel/toolkits/data_commons_toolkit.py +2 -2
- camel/toolkits/dingtalk.py +1135 -0
- camel/toolkits/earth_science_toolkit.py +5367 -0
- camel/toolkits/edgeone_pages_mcp_toolkit.py +49 -0
- camel/toolkits/excel_toolkit.py +905 -71
- camel/toolkits/file_toolkit.py +1402 -0
- camel/toolkits/function_tool.py +205 -27
- camel/toolkits/github_toolkit.py +109 -22
- camel/toolkits/gmail_toolkit.py +1839 -0
- camel/toolkits/google_calendar_toolkit.py +40 -6
- camel/toolkits/google_drive_mcp_toolkit.py +54 -0
- camel/toolkits/google_maps_toolkit.py +2 -2
- camel/toolkits/google_scholar_toolkit.py +2 -2
- camel/toolkits/human_toolkit.py +36 -12
- camel/toolkits/hybrid_browser_toolkit/__init__.py +18 -0
- camel/toolkits/hybrid_browser_toolkit/config_loader.py +185 -0
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +246 -0
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +1958 -0
- camel/toolkits/hybrid_browser_toolkit/installer.py +203 -0
- camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +4589 -0
- camel/toolkits/hybrid_browser_toolkit/ts/package.json +33 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/browser-scripts.js +125 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +1940 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +233 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +589 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/index.ts +7 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/parent-child-filter.ts +226 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +219 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/som-screenshot-injected.ts +543 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +129 -0
- camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json +27 -0
- camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +325 -0
- camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +1037 -0
- camel/toolkits/hybrid_browser_toolkit_py/__init__.py +17 -0
- camel/toolkits/hybrid_browser_toolkit_py/actions.py +575 -0
- camel/toolkits/hybrid_browser_toolkit_py/agent.py +311 -0
- camel/toolkits/hybrid_browser_toolkit_py/browser_session.py +787 -0
- camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +490 -0
- camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +2390 -0
- camel/toolkits/hybrid_browser_toolkit_py/snapshot.py +233 -0
- camel/toolkits/hybrid_browser_toolkit_py/stealth_script.js +0 -0
- camel/toolkits/hybrid_browser_toolkit_py/unified_analyzer.js +1043 -0
- camel/toolkits/image_analysis_toolkit.py +3 -6
- camel/toolkits/image_generation_toolkit.py +390 -0
- camel/toolkits/jina_reranker_toolkit.py +5 -6
- camel/toolkits/klavis_toolkit.py +7 -3
- camel/toolkits/linkedin_toolkit.py +2 -2
- camel/toolkits/markitdown_toolkit.py +104 -0
- camel/toolkits/math_toolkit.py +66 -12
- camel/toolkits/mcp_toolkit.py +412 -36
- camel/toolkits/memory_toolkit.py +7 -3
- camel/toolkits/meshy_toolkit.py +2 -2
- camel/toolkits/message_agent_toolkit.py +608 -0
- camel/toolkits/message_integration.py +728 -0
- camel/toolkits/microsoft_outlook_mail_toolkit.py +1885 -0
- camel/toolkits/mineru_toolkit.py +2 -2
- camel/toolkits/minimax_mcp_toolkit.py +195 -0
- camel/toolkits/networkx_toolkit.py +2 -2
- camel/toolkits/note_taking_toolkit.py +277 -0
- camel/toolkits/notion_mcp_toolkit.py +224 -0
- camel/toolkits/notion_toolkit.py +2 -2
- camel/toolkits/open_api_specs/biztoc/__init__.py +2 -2
- camel/toolkits/open_api_specs/biztoc/ai-plugin.json +1 -1
- camel/toolkits/open_api_specs/coursera/__init__.py +2 -2
- camel/toolkits/open_api_specs/create_qr_code/__init__.py +2 -2
- camel/toolkits/open_api_specs/klarna/__init__.py +2 -2
- camel/toolkits/open_api_specs/nasa_apod/__init__.py +2 -2
- camel/toolkits/open_api_specs/outschool/__init__.py +2 -2
- camel/toolkits/open_api_specs/outschool/ai-plugin.json +1 -1
- camel/toolkits/open_api_specs/outschool/openapi.yaml +1 -1
- camel/toolkits/open_api_specs/outschool/paths/__init__.py +2 -2
- camel/toolkits/open_api_specs/outschool/paths/get_classes.py +2 -2
- camel/toolkits/open_api_specs/outschool/paths/search_teachers.py +2 -2
- camel/toolkits/open_api_specs/security_config.py +2 -2
- camel/toolkits/open_api_specs/speak/__init__.py +2 -2
- camel/toolkits/open_api_specs/web_scraper/__init__.py +2 -2
- camel/toolkits/open_api_specs/web_scraper/ai-plugin.json +1 -1
- camel/toolkits/open_api_specs/web_scraper/paths/__init__.py +2 -2
- camel/toolkits/open_api_specs/web_scraper/paths/scraper.py +2 -2
- camel/toolkits/open_api_toolkit.py +2 -2
- camel/toolkits/openbb_toolkit.py +7 -3
- camel/toolkits/origene_mcp_toolkit.py +56 -0
- camel/toolkits/page_script.js +53 -53
- camel/toolkits/playwright_mcp_toolkit.py +13 -31
- camel/toolkits/pptx_toolkit.py +36 -23
- camel/toolkits/pubmed_toolkit.py +2 -2
- camel/toolkits/pulse_mcp_search_toolkit.py +2 -2
- camel/toolkits/pyautogui_toolkit.py +2 -2
- camel/toolkits/reddit_toolkit.py +2 -2
- camel/toolkits/resend_toolkit.py +168 -0
- camel/toolkits/retrieval_toolkit.py +2 -2
- camel/toolkits/screenshot_toolkit.py +213 -0
- camel/toolkits/search_toolkit.py +606 -156
- camel/toolkits/searxng_toolkit.py +2 -2
- camel/toolkits/semantic_scholar_toolkit.py +2 -2
- camel/toolkits/slack_toolkit.py +108 -58
- camel/toolkits/sql_toolkit.py +712 -0
- camel/toolkits/stripe_toolkit.py +2 -2
- camel/toolkits/sympy_toolkit.py +3 -3
- camel/toolkits/task_planning_toolkit.py +5 -5
- camel/toolkits/terminal_toolkit/__init__.py +18 -0
- camel/toolkits/terminal_toolkit/terminal_toolkit.py +1281 -0
- camel/toolkits/terminal_toolkit/utils.py +659 -0
- camel/toolkits/thinking_toolkit.py +3 -3
- camel/toolkits/twitter_toolkit.py +2 -2
- camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
- camel/toolkits/video_analysis_toolkit.py +109 -29
- camel/toolkits/video_download_toolkit.py +19 -16
- camel/toolkits/weather_toolkit.py +2 -2
- camel/toolkits/web_deploy_toolkit.py +1219 -0
- camel/toolkits/wechat_official_toolkit.py +483 -0
- camel/toolkits/whatsapp_toolkit.py +2 -2
- camel/toolkits/wolfram_alpha_toolkit.py +2 -2
- camel/toolkits/zapier_toolkit.py +7 -3
- camel/types/__init__.py +4 -4
- camel/types/agents/__init__.py +2 -2
- camel/types/agents/tool_calling_record.py +6 -3
- camel/types/enums.py +381 -41
- camel/types/mcp_registries.py +2 -2
- camel/types/openai_types.py +4 -4
- camel/types/unified_model_type.py +46 -10
- camel/utils/__init__.py +5 -2
- camel/utils/agent_context.py +41 -0
- camel/utils/async_func.py +2 -2
- camel/utils/chunker/__init__.py +2 -2
- camel/utils/chunker/base.py +2 -2
- camel/utils/chunker/code_chunker.py +2 -2
- camel/utils/chunker/uio_chunker.py +2 -2
- camel/utils/commons.py +38 -7
- camel/utils/constants.py +5 -2
- camel/utils/context_utils.py +1134 -0
- camel/utils/deduplication.py +2 -2
- camel/utils/filename.py +2 -2
- camel/utils/langfuse.py +18 -10
- camel/utils/mcp.py +140 -6
- camel/utils/mcp_client.py +48 -38
- camel/utils/message_summarizer.py +148 -0
- camel/utils/response_format.py +2 -2
- camel/utils/token_counting.py +45 -22
- camel/utils/tool_result.py +44 -0
- camel/verifiers/__init__.py +2 -2
- camel/verifiers/base.py +2 -2
- camel/verifiers/math_verifier.py +2 -2
- camel/verifiers/models.py +2 -2
- camel/verifiers/physics_verifier.py +2 -2
- camel/verifiers/python_verifier.py +2 -2
- {camel_ai-0.2.65.dist-info → camel_ai-0.2.83a6.dist-info}/METADATA +355 -117
- camel_ai-0.2.83a6.dist-info/RECORD +511 -0
- {camel_ai-0.2.65.dist-info → camel_ai-0.2.83a6.dist-info}/WHEEL +1 -1
- {camel_ai-0.2.65.dist-info → camel_ai-0.2.83a6.dist-info}/licenses/LICENSE +1 -1
- camel/loaders/pandas_reader.py +0 -368
- camel/toolkits/dalle_toolkit.py +0 -175
- camel/toolkits/file_write_toolkit.py +0 -444
- camel/toolkits/openai_agent_toolkit.py +0 -135
- camel/toolkits/terminal_toolkit.py +0 -1037
- camel_ai-0.2.65.dist-info/RECORD +0 -426
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ========= Copyright 2023-
|
|
1
|
+
# ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
2
2
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
3
|
# you may not use this file except in compliance with the License.
|
|
4
4
|
# You may obtain a copy of the License at
|
|
@@ -10,41 +10,30 @@
|
|
|
10
10
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
11
|
# See the License for the specific language governing permissions and
|
|
12
12
|
# limitations under the License.
|
|
13
|
-
# ========= Copyright 2023-
|
|
14
|
-
from typing import List, Optional, Tuple
|
|
13
|
+
# ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
15
14
|
|
|
16
|
-
from
|
|
15
|
+
from typing import List, Optional, Tuple
|
|
17
16
|
|
|
18
|
-
from camel.logger import get_logger
|
|
19
17
|
from camel.memories.base import BaseContextCreator
|
|
20
18
|
from camel.memories.records import ContextRecord
|
|
21
19
|
from camel.messages import OpenAIMessage
|
|
22
20
|
from camel.types.enums import OpenAIBackendRole
|
|
23
21
|
from camel.utils import BaseTokenCounter
|
|
24
22
|
|
|
25
|
-
logger = get_logger(__name__)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class _ContextUnit(BaseModel):
|
|
29
|
-
idx: int
|
|
30
|
-
record: ContextRecord
|
|
31
|
-
num_tokens: int
|
|
32
|
-
|
|
33
23
|
|
|
34
24
|
class ScoreBasedContextCreator(BaseContextCreator):
|
|
35
|
-
r"""A
|
|
36
|
-
from :obj:`BaseContextCreator`.
|
|
25
|
+
r"""A context creation strategy that orders records chronologically.
|
|
37
26
|
|
|
38
|
-
This class
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
27
|
+
This class supports token count estimation to reduce expensive repeated
|
|
28
|
+
token counting. When a cached token count is available, it estimates
|
|
29
|
+
new message tokens using character-based approximation instead of
|
|
30
|
+
calling the token counter for every message.
|
|
42
31
|
|
|
43
32
|
Args:
|
|
44
|
-
token_counter (BaseTokenCounter):
|
|
45
|
-
|
|
46
|
-
token_limit (int):
|
|
47
|
-
|
|
33
|
+
token_counter (BaseTokenCounter): Token counter instance used to
|
|
34
|
+
compute the combined token count of the returned messages.
|
|
35
|
+
token_limit (int): Retained for API compatibility. No longer used to
|
|
36
|
+
filter records.
|
|
48
37
|
"""
|
|
49
38
|
|
|
50
39
|
def __init__(
|
|
@@ -52,6 +41,10 @@ class ScoreBasedContextCreator(BaseContextCreator):
|
|
|
52
41
|
) -> None:
|
|
53
42
|
self._token_counter = token_counter
|
|
54
43
|
self._token_limit = token_limit
|
|
44
|
+
# Token count cache: stores the known token count and corresponding
|
|
45
|
+
# message count from the last LLM response
|
|
46
|
+
self._cached_token_count: Optional[int] = None
|
|
47
|
+
self._cached_message_count: int = 0
|
|
55
48
|
|
|
56
49
|
@property
|
|
57
50
|
def token_counter(self) -> BaseTokenCounter:
|
|
@@ -61,230 +54,116 @@ class ScoreBasedContextCreator(BaseContextCreator):
|
|
|
61
54
|
def token_limit(self) -> int:
|
|
62
55
|
return self._token_limit
|
|
63
56
|
|
|
64
|
-
def
|
|
65
|
-
self,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
r"""Constructs conversation context from chat history while respecting
|
|
69
|
-
token limits.
|
|
70
|
-
|
|
71
|
-
Key strategies:
|
|
72
|
-
1. System message is always prioritized and preserved
|
|
73
|
-
2. Truncation removes low-score messages first
|
|
74
|
-
3. Final output maintains chronological order and in history memory,
|
|
75
|
-
the score of each message decreases according to keep_rate. The
|
|
76
|
-
newer the message, the higher the score.
|
|
77
|
-
|
|
78
|
-
Args:
|
|
79
|
-
records (List[ContextRecord]): List of context records with scores
|
|
80
|
-
and timestamps.
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
Tuple[List[OpenAIMessage], int]:
|
|
84
|
-
- Ordered list of OpenAI messages
|
|
85
|
-
- Total token count of the final context
|
|
86
|
-
|
|
87
|
-
Raises:
|
|
88
|
-
RuntimeError: If system message alone exceeds token limit
|
|
89
|
-
"""
|
|
90
|
-
# ======================
|
|
91
|
-
# 1. System Message Handling
|
|
92
|
-
# ======================
|
|
93
|
-
system_unit, regular_units = self._extract_system_message(records)
|
|
94
|
-
system_tokens = system_unit.num_tokens if system_unit else 0
|
|
95
|
-
|
|
96
|
-
# Check early if system message alone exceeds token limit
|
|
97
|
-
if system_tokens > self.token_limit:
|
|
98
|
-
raise RuntimeError(
|
|
99
|
-
f"System message alone exceeds token limit"
|
|
100
|
-
f": {system_tokens} > {self.token_limit}",
|
|
101
|
-
system_tokens,
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
# ======================
|
|
105
|
-
# 2. Deduplication & Initial Processing
|
|
106
|
-
# ======================
|
|
107
|
-
seen_uuids = set()
|
|
108
|
-
if system_unit:
|
|
109
|
-
seen_uuids.add(system_unit.record.memory_record.uuid)
|
|
110
|
-
|
|
111
|
-
# Process non-system messages with deduplication
|
|
112
|
-
for idx, record in enumerate(records):
|
|
113
|
-
if record.memory_record.uuid in seen_uuids:
|
|
114
|
-
continue
|
|
115
|
-
seen_uuids.add(record.memory_record.uuid)
|
|
116
|
-
|
|
117
|
-
token_count = self.token_counter.count_tokens_from_messages(
|
|
118
|
-
[record.memory_record.to_openai_message()]
|
|
119
|
-
)
|
|
120
|
-
regular_units.append(
|
|
121
|
-
_ContextUnit(
|
|
122
|
-
idx=idx,
|
|
123
|
-
record=record,
|
|
124
|
-
num_tokens=token_count,
|
|
125
|
-
)
|
|
126
|
-
)
|
|
127
|
-
|
|
128
|
-
# ======================
|
|
129
|
-
# 3. Token Calculation
|
|
130
|
-
# ======================
|
|
131
|
-
total_tokens = system_tokens + sum(u.num_tokens for u in regular_units)
|
|
132
|
-
|
|
133
|
-
# ======================
|
|
134
|
-
# 4. Early Return if Within Limit
|
|
135
|
-
# ======================
|
|
136
|
-
if total_tokens <= self.token_limit:
|
|
137
|
-
sorted_units = sorted(
|
|
138
|
-
regular_units, key=self._conversation_sort_key
|
|
139
|
-
)
|
|
140
|
-
return self._assemble_output(sorted_units, system_unit)
|
|
141
|
-
|
|
142
|
-
# ======================
|
|
143
|
-
# 5. Truncation Logic
|
|
144
|
-
# ======================
|
|
145
|
-
logger.warning(
|
|
146
|
-
f"Context truncation required "
|
|
147
|
-
f"({total_tokens} > {self.token_limit}), "
|
|
148
|
-
f"pruning low-score messages."
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
# Sort for truncation: high scores first, older messages first at same
|
|
152
|
-
# score
|
|
153
|
-
sorted_for_truncation = sorted(
|
|
154
|
-
regular_units, key=self._truncation_sort_key
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
# Reverse to process from lowest score (end of sorted list)
|
|
158
|
-
remaining_units = []
|
|
159
|
-
current_total = system_tokens
|
|
160
|
-
|
|
161
|
-
for unit in sorted_for_truncation:
|
|
162
|
-
potential_total = current_total + unit.num_tokens
|
|
163
|
-
if potential_total <= self.token_limit:
|
|
164
|
-
remaining_units.append(unit)
|
|
165
|
-
current_total = potential_total
|
|
166
|
-
|
|
167
|
-
# ======================
|
|
168
|
-
# 6. Output Assembly
|
|
169
|
-
# ======================
|
|
170
|
-
|
|
171
|
-
# In case system message is the only message in memory when sorted
|
|
172
|
-
# units are empty, raise an error
|
|
173
|
-
if system_unit and len(remaining_units) == 0 and len(records) > 1:
|
|
174
|
-
raise RuntimeError(
|
|
175
|
-
"System message and current message exceeds token limit ",
|
|
176
|
-
total_tokens,
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
# Sort remaining units chronologically
|
|
180
|
-
final_units = sorted(remaining_units, key=self._conversation_sort_key)
|
|
181
|
-
return self._assemble_output(final_units, system_unit)
|
|
182
|
-
|
|
183
|
-
def _extract_system_message(
|
|
184
|
-
self, records: List[ContextRecord]
|
|
185
|
-
) -> Tuple[Optional[_ContextUnit], List[_ContextUnit]]:
|
|
186
|
-
r"""Extracts the system message from records and validates it.
|
|
57
|
+
def set_cached_token_count(
|
|
58
|
+
self, token_count: int, message_count: int
|
|
59
|
+
) -> None:
|
|
60
|
+
r"""Set the cached token count from LLM response usage.
|
|
187
61
|
|
|
188
62
|
Args:
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
Tuple[Optional[_ContextUnit], List[_ContextUnit]]: containing:
|
|
194
|
-
- The system message as a `_ContextUnit`, if valid; otherwise,
|
|
195
|
-
`None`.
|
|
196
|
-
- An empty list, serving as the initial container for regular
|
|
197
|
-
messages.
|
|
63
|
+
token_count (int): The total token count (prompt + completion)
|
|
64
|
+
from LLM response usage.
|
|
65
|
+
message_count (int): The number of messages including the
|
|
66
|
+
assistant response that will be added to memory.
|
|
198
67
|
"""
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
first_record = records[0]
|
|
203
|
-
if (
|
|
204
|
-
first_record.memory_record.role_at_backend
|
|
205
|
-
!= OpenAIBackendRole.SYSTEM
|
|
206
|
-
):
|
|
207
|
-
return None, []
|
|
208
|
-
|
|
209
|
-
message = first_record.memory_record.to_openai_message()
|
|
210
|
-
tokens = self.token_counter.count_tokens_from_messages([message])
|
|
211
|
-
system_message_unit = _ContextUnit(
|
|
212
|
-
idx=0,
|
|
213
|
-
record=first_record,
|
|
214
|
-
num_tokens=tokens,
|
|
215
|
-
)
|
|
216
|
-
return system_message_unit, []
|
|
217
|
-
|
|
218
|
-
def _truncation_sort_key(self, unit: _ContextUnit) -> Tuple[float, float]:
|
|
219
|
-
r"""Defines the sorting key for the truncation phase.
|
|
220
|
-
|
|
221
|
-
Sorting priority:
|
|
222
|
-
- Primary: Sort by score in descending order (higher scores first).
|
|
223
|
-
- Secondary: Sort by timestamp in ascending order (older messages
|
|
224
|
-
first when scores are equal).
|
|
225
|
-
|
|
226
|
-
Args:
|
|
227
|
-
unit (_ContextUnit): A `_ContextUnit` representing a conversation
|
|
228
|
-
record.
|
|
68
|
+
self._cached_token_count = token_count
|
|
69
|
+
self._cached_message_count = message_count
|
|
229
70
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
"""
|
|
235
|
-
return (-unit.record.score, unit.record.timestamp)
|
|
71
|
+
def clear_cache(self) -> None:
|
|
72
|
+
r"""Clear the cached token count."""
|
|
73
|
+
self._cached_token_count = None
|
|
74
|
+
self._cached_message_count = 0
|
|
236
75
|
|
|
237
|
-
def
|
|
238
|
-
|
|
239
|
-
) -> Tuple[float, float]:
|
|
240
|
-
r"""Defines the sorting key for assembling the final output.
|
|
76
|
+
def _estimate_message_tokens(self, message: OpenAIMessage) -> int:
|
|
77
|
+
r"""Estimate token count for a single message.
|
|
241
78
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
- Secondary: Sort by score in descending order (higher scores first
|
|
245
|
-
when timestamps are equal).
|
|
79
|
+
Uses ~2 chars/token as a conservative approximation to handle both
|
|
80
|
+
ASCII (~4 chars/token) and CJK text (~1-2 chars/token).
|
|
246
81
|
|
|
247
82
|
Args:
|
|
248
|
-
|
|
249
|
-
record.
|
|
83
|
+
message: The OpenAI message to estimate.
|
|
250
84
|
|
|
251
85
|
Returns:
|
|
252
|
-
|
|
253
|
-
- Timestamp for chronological sorting.
|
|
254
|
-
- Negative score for descending order sorting.
|
|
86
|
+
Estimated token count (intentionally conservative).
|
|
255
87
|
"""
|
|
256
|
-
|
|
88
|
+
content = message.get("content", "")
|
|
89
|
+
token_estimate = 4 # message overhead
|
|
90
|
+
|
|
91
|
+
if isinstance(content, list):
|
|
92
|
+
# Multimodal content
|
|
93
|
+
for part in content:
|
|
94
|
+
if isinstance(part, dict):
|
|
95
|
+
if part.get("type") == "image_url":
|
|
96
|
+
# Images: 85 (low) to ~1500 (high detail large image)
|
|
97
|
+
# Use 1500 as conservative estimate
|
|
98
|
+
token_estimate += 1500
|
|
99
|
+
else:
|
|
100
|
+
token_estimate += len(str(part)) // 2
|
|
101
|
+
else:
|
|
102
|
+
token_estimate += len(str(part)) // 2
|
|
103
|
+
else:
|
|
104
|
+
token_estimate += len(str(content)) // 2
|
|
105
|
+
|
|
106
|
+
# Add tool_calls if present (already text, safe to serialize)
|
|
107
|
+
if message.get("tool_calls"):
|
|
108
|
+
token_estimate += len(str(message.get("tool_calls"))) // 2
|
|
109
|
+
|
|
110
|
+
return token_estimate
|
|
257
111
|
|
|
258
|
-
def
|
|
112
|
+
def create_context(
|
|
259
113
|
self,
|
|
260
|
-
|
|
261
|
-
system_unit: Optional[_ContextUnit],
|
|
114
|
+
records: List[ContextRecord],
|
|
262
115
|
) -> Tuple[List[OpenAIMessage], int]:
|
|
263
|
-
|
|
116
|
+
"""Returns messages sorted by timestamp and their total token count."""
|
|
117
|
+
|
|
118
|
+
system_record: Optional[ContextRecord] = None
|
|
119
|
+
remaining_records: List[ContextRecord] = []
|
|
120
|
+
|
|
121
|
+
for record in records:
|
|
122
|
+
if (
|
|
123
|
+
system_record is None
|
|
124
|
+
and record.memory_record.role_at_backend
|
|
125
|
+
== OpenAIBackendRole.SYSTEM
|
|
126
|
+
):
|
|
127
|
+
system_record = record
|
|
128
|
+
continue
|
|
129
|
+
remaining_records.append(record)
|
|
264
130
|
|
|
265
|
-
|
|
266
|
-
context_units (List[_ContextUnit]): Sorted list of regular message
|
|
267
|
-
units.
|
|
268
|
-
system_unit (Optional[_ContextUnit]): System message unit (if
|
|
269
|
-
present).
|
|
131
|
+
remaining_records.sort(key=lambda record: record.timestamp)
|
|
270
132
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
"""
|
|
275
|
-
messages = []
|
|
276
|
-
total_tokens = 0
|
|
133
|
+
messages: List[OpenAIMessage] = []
|
|
134
|
+
if system_record is not None:
|
|
135
|
+
messages.append(system_record.memory_record.to_openai_message())
|
|
277
136
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
137
|
+
messages.extend(
|
|
138
|
+
record.memory_record.to_openai_message()
|
|
139
|
+
for record in remaining_records
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if not messages:
|
|
143
|
+
return [], 0
|
|
284
144
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
145
|
+
current_count = len(messages)
|
|
146
|
+
|
|
147
|
+
# Use cache if available and valid
|
|
148
|
+
if (
|
|
149
|
+
self._cached_token_count is not None
|
|
150
|
+
and self._cached_message_count > 0
|
|
151
|
+
):
|
|
152
|
+
if current_count == self._cached_message_count:
|
|
153
|
+
# Same message count, use cached value directly
|
|
154
|
+
return messages, self._cached_token_count
|
|
155
|
+
elif current_count > self._cached_message_count:
|
|
156
|
+
# New messages added, estimate incrementally
|
|
157
|
+
new_messages = messages[self._cached_message_count :]
|
|
158
|
+
estimated_new_tokens = sum(
|
|
159
|
+
self._estimate_message_tokens(msg) for msg in new_messages
|
|
160
|
+
)
|
|
161
|
+
return (
|
|
162
|
+
messages,
|
|
163
|
+
self._cached_token_count + estimated_new_tokens,
|
|
164
|
+
)
|
|
165
|
+
# current_count < cached: messages were removed, cache invalid
|
|
289
166
|
|
|
167
|
+
# No cache or cache is stale - do full calculation
|
|
168
|
+
total_tokens = self.token_counter.count_tokens_from_messages(messages)
|
|
290
169
|
return messages, total_tokens
|
camel/memories/records.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ========= Copyright 2023-
|
|
1
|
+
# ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
2
2
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
3
|
# you may not use this file except in compliance with the License.
|
|
4
4
|
# You may obtain a copy of the License at
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
11
|
# See the License for the specific language governing permissions and
|
|
12
12
|
# limitations under the License.
|
|
13
|
-
# ========= Copyright 2023-
|
|
13
|
+
# ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
14
|
|
|
15
15
|
# Enables postponed evaluation of annotations (for string-based type hints)
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
|
+
import inspect
|
|
18
19
|
import time
|
|
19
|
-
from dataclasses import asdict
|
|
20
20
|
from typing import Any, ClassVar, Dict
|
|
21
21
|
from uuid import UUID, uuid4
|
|
22
22
|
|
|
@@ -63,6 +63,20 @@ class MemoryRecord(BaseModel):
|
|
|
63
63
|
"FunctionCallingMessage": FunctionCallingMessage,
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
# Cache for constructor parameters (performance optimization)
|
|
67
|
+
_constructor_params_cache: ClassVar[Dict[str, set]] = {}
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def _get_constructor_params(cls, message_cls) -> set:
|
|
71
|
+
"""Get constructor parameters for a message class with caching."""
|
|
72
|
+
cls_name = message_cls.__name__
|
|
73
|
+
if cls_name not in cls._constructor_params_cache:
|
|
74
|
+
sig = inspect.signature(message_cls.__init__)
|
|
75
|
+
cls._constructor_params_cache[cls_name] = set(
|
|
76
|
+
sig.parameters.keys()
|
|
77
|
+
) - {'self'}
|
|
78
|
+
return cls._constructor_params_cache[cls_name]
|
|
79
|
+
|
|
66
80
|
@classmethod
|
|
67
81
|
def from_dict(cls, record_dict: Dict[str, Any]) -> "MemoryRecord":
|
|
68
82
|
r"""Reconstruct a :obj:`MemoryRecord` from the input dict.
|
|
@@ -70,14 +84,78 @@ class MemoryRecord(BaseModel):
|
|
|
70
84
|
Args:
|
|
71
85
|
record_dict(Dict[str, Any]): A dict generated by :meth:`to_dict`.
|
|
72
86
|
"""
|
|
87
|
+
from camel.types import OpenAIBackendRole, RoleType
|
|
88
|
+
|
|
73
89
|
message_cls = cls._MESSAGE_TYPES[record_dict["message"]["__class__"]]
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
90
|
+
data = record_dict["message"].copy()
|
|
91
|
+
data.pop("__class__")
|
|
92
|
+
|
|
93
|
+
# Convert role_type string to enum
|
|
94
|
+
if "role_type" in data and isinstance(data["role_type"], str):
|
|
95
|
+
data["role_type"] = RoleType(data["role_type"])
|
|
96
|
+
|
|
97
|
+
# Deserialize image_list from base64 strings/URLs back to PIL Images/
|
|
98
|
+
# URLs
|
|
99
|
+
if "image_list" in data and data["image_list"] is not None:
|
|
100
|
+
import base64
|
|
101
|
+
from io import BytesIO
|
|
102
|
+
|
|
103
|
+
from PIL import Image
|
|
104
|
+
|
|
105
|
+
image_objects = []
|
|
106
|
+
for img_item in data["image_list"]:
|
|
107
|
+
if isinstance(img_item, dict):
|
|
108
|
+
# New format with type indicator
|
|
109
|
+
if img_item["type"] == "url":
|
|
110
|
+
# URL string, keep as-is
|
|
111
|
+
image_objects.append(img_item["data"])
|
|
112
|
+
else: # type == "base64"
|
|
113
|
+
# Base64 encoded image, convert to PIL Image
|
|
114
|
+
img_bytes = base64.b64decode(img_item["data"])
|
|
115
|
+
img = Image.open(BytesIO(img_bytes))
|
|
116
|
+
# Restore the format attribute if it was saved
|
|
117
|
+
if "format" in img_item:
|
|
118
|
+
img.format = img_item["format"]
|
|
119
|
+
image_objects.append(img)
|
|
120
|
+
else:
|
|
121
|
+
# Legacy format: assume it's a base64 string
|
|
122
|
+
img_bytes = base64.b64decode(img_item)
|
|
123
|
+
img = Image.open(BytesIO(img_bytes))
|
|
124
|
+
image_objects.append(img)
|
|
125
|
+
data["image_list"] = image_objects
|
|
126
|
+
|
|
127
|
+
# Deserialize video_bytes from base64 string
|
|
128
|
+
if "video_bytes" in data and data["video_bytes"] is not None:
|
|
129
|
+
import base64
|
|
130
|
+
|
|
131
|
+
data["video_bytes"] = base64.b64decode(data["video_bytes"])
|
|
132
|
+
|
|
133
|
+
# Get valid constructor parameters (cached)
|
|
134
|
+
valid_params = cls._get_constructor_params(message_cls)
|
|
135
|
+
|
|
136
|
+
# Separate constructor args from extra fields
|
|
137
|
+
kwargs = {k: v for k, v in data.items() if k in valid_params}
|
|
138
|
+
extra_fields = {k: v for k, v in data.items() if k not in valid_params}
|
|
139
|
+
|
|
140
|
+
# Handle meta_dict properly: merge existing meta_dict with extra fields
|
|
141
|
+
existing_meta = kwargs.get("meta_dict", {}) or {}
|
|
142
|
+
if extra_fields:
|
|
143
|
+
# Extra fields take precedence, but preserve existing meta_dict
|
|
144
|
+
# structure
|
|
145
|
+
merged_meta = {**existing_meta, **extra_fields}
|
|
146
|
+
kwargs["meta_dict"] = merged_meta
|
|
147
|
+
elif not existing_meta:
|
|
148
|
+
kwargs["meta_dict"] = None
|
|
149
|
+
|
|
150
|
+
# Convert role_at_backend
|
|
151
|
+
role_at_backend = record_dict["role_at_backend"]
|
|
152
|
+
if isinstance(role_at_backend, str):
|
|
153
|
+
role_at_backend = OpenAIBackendRole(role_at_backend)
|
|
154
|
+
|
|
77
155
|
return cls(
|
|
78
156
|
uuid=UUID(record_dict["uuid"]),
|
|
79
|
-
message=
|
|
80
|
-
role_at_backend=
|
|
157
|
+
message=message_cls(**kwargs),
|
|
158
|
+
role_at_backend=role_at_backend,
|
|
81
159
|
extra_info=record_dict["extra_info"],
|
|
82
160
|
timestamp=record_dict["timestamp"],
|
|
83
161
|
agent_id=record_dict["agent_id"],
|
|
@@ -91,9 +169,11 @@ class MemoryRecord(BaseModel):
|
|
|
91
169
|
"uuid": str(self.uuid),
|
|
92
170
|
"message": {
|
|
93
171
|
"__class__": self.message.__class__.__name__,
|
|
94
|
-
**
|
|
172
|
+
**self.message.to_dict(),
|
|
95
173
|
},
|
|
96
|
-
"role_at_backend": self.role_at_backend
|
|
174
|
+
"role_at_backend": self.role_at_backend.value
|
|
175
|
+
if hasattr(self.role_at_backend, "value")
|
|
176
|
+
else self.role_at_backend,
|
|
97
177
|
"extra_info": self.extra_info,
|
|
98
178
|
"timestamp": self.timestamp,
|
|
99
179
|
"agent_id": self.agent_id,
|
camel/messages/__init__.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ========= Copyright 2023-
|
|
1
|
+
# ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
2
2
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
3
|
# you may not use this file except in compliance with the License.
|
|
4
4
|
# You may obtain a copy of the License at
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
11
|
# See the License for the specific language governing permissions and
|
|
12
12
|
# limitations under the License.
|
|
13
|
-
# ========= Copyright 2023-
|
|
13
|
+
# ========= Copyright 2023-2026 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
14
|
from typing import Union
|
|
15
15
|
|
|
16
16
|
from camel.types import (
|