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
camel/models/gemini_model.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,14 +10,23 @@
|
|
|
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
|
import os
|
|
15
|
-
from typing import
|
|
15
|
+
from typing import (
|
|
16
|
+
Any,
|
|
17
|
+
AsyncGenerator,
|
|
18
|
+
Dict,
|
|
19
|
+
Generator,
|
|
20
|
+
List,
|
|
21
|
+
Optional,
|
|
22
|
+
Type,
|
|
23
|
+
Union,
|
|
24
|
+
)
|
|
16
25
|
|
|
17
26
|
from openai import AsyncStream, Stream
|
|
18
27
|
from pydantic import BaseModel
|
|
19
28
|
|
|
20
|
-
from camel.configs import
|
|
29
|
+
from camel.configs import GeminiConfig
|
|
21
30
|
from camel.messages import OpenAIMessage
|
|
22
31
|
from camel.models.openai_compatible_model import OpenAICompatibleModel
|
|
23
32
|
from camel.types import (
|
|
@@ -28,8 +37,6 @@ from camel.types import (
|
|
|
28
37
|
from camel.utils import (
|
|
29
38
|
BaseTokenCounter,
|
|
30
39
|
api_keys_required,
|
|
31
|
-
get_current_agent_session_id,
|
|
32
|
-
update_langfuse_trace,
|
|
33
40
|
)
|
|
34
41
|
|
|
35
42
|
if os.environ.get("LANGFUSE_ENABLED", "False").lower() == "true":
|
|
@@ -37,6 +44,11 @@ if os.environ.get("LANGFUSE_ENABLED", "False").lower() == "true":
|
|
|
37
44
|
from langfuse.decorators import observe
|
|
38
45
|
except ImportError:
|
|
39
46
|
from camel.utils import observe
|
|
47
|
+
elif os.environ.get("TRACEROOT_ENABLED", "False").lower() == "true":
|
|
48
|
+
try:
|
|
49
|
+
from traceroot import trace as observe # type: ignore[import]
|
|
50
|
+
except ImportError:
|
|
51
|
+
from camel.utils import observe
|
|
40
52
|
else:
|
|
41
53
|
from camel.utils import observe
|
|
42
54
|
|
|
@@ -64,6 +76,10 @@ class GeminiModel(OpenAICompatibleModel):
|
|
|
64
76
|
API calls. If not provided, will fall back to the MODEL_TIMEOUT
|
|
65
77
|
environment variable or default to 180 seconds.
|
|
66
78
|
(default: :obj:`None`)
|
|
79
|
+
max_retries (int, optional): Maximum number of retries for API calls.
|
|
80
|
+
(default: :obj:`3`)
|
|
81
|
+
**kwargs (Any): Additional arguments to pass to the client
|
|
82
|
+
initialization.
|
|
67
83
|
"""
|
|
68
84
|
|
|
69
85
|
@api_keys_required(
|
|
@@ -79,6 +95,8 @@ class GeminiModel(OpenAICompatibleModel):
|
|
|
79
95
|
url: Optional[str] = None,
|
|
80
96
|
token_counter: Optional[BaseTokenCounter] = None,
|
|
81
97
|
timeout: Optional[float] = None,
|
|
98
|
+
max_retries: int = 3,
|
|
99
|
+
**kwargs: Any,
|
|
82
100
|
) -> None:
|
|
83
101
|
if model_config_dict is None:
|
|
84
102
|
model_config_dict = GeminiConfig().as_dict()
|
|
@@ -95,20 +113,344 @@ class GeminiModel(OpenAICompatibleModel):
|
|
|
95
113
|
url=url,
|
|
96
114
|
token_counter=token_counter,
|
|
97
115
|
timeout=timeout,
|
|
116
|
+
max_retries=max_retries,
|
|
117
|
+
**kwargs,
|
|
98
118
|
)
|
|
99
119
|
|
|
100
120
|
def _process_messages(self, messages) -> List[OpenAIMessage]:
|
|
101
121
|
r"""Process the messages for Gemini API to ensure no empty content,
|
|
102
|
-
which is not accepted by Gemini.
|
|
122
|
+
which is not accepted by Gemini. Also preserves thought signatures
|
|
123
|
+
required for Gemini 3 Pro function calling.
|
|
124
|
+
|
|
125
|
+
This method also merges consecutive assistant messages with single
|
|
126
|
+
tool calls into a single assistant message with multiple tool calls,
|
|
127
|
+
as required by Gemini's OpenAI-compatible API for parallel function
|
|
128
|
+
calling.
|
|
103
129
|
"""
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
130
|
+
import copy
|
|
131
|
+
|
|
132
|
+
processed_messages: List[OpenAIMessage] = []
|
|
133
|
+
i = 0
|
|
134
|
+
n = len(messages)
|
|
135
|
+
|
|
136
|
+
while i < n:
|
|
137
|
+
msg = messages[i]
|
|
138
|
+
|
|
139
|
+
# Check if this is an assistant message with a single tool_call
|
|
140
|
+
# that might need to be merged with subsequent ones
|
|
141
|
+
if (
|
|
142
|
+
msg.get('role') == 'assistant'
|
|
143
|
+
and 'tool_calls' in msg
|
|
144
|
+
and isinstance(msg['tool_calls'], list)
|
|
145
|
+
and len(msg['tool_calls']) == 1
|
|
146
|
+
):
|
|
147
|
+
# Look ahead to check if there are more assistant messages
|
|
148
|
+
# with single tool calls (interleaved with their tool results)
|
|
149
|
+
j = i + 1
|
|
150
|
+
has_more_tool_calls = False
|
|
151
|
+
|
|
152
|
+
# Collect tool_call_ids we've seen so far
|
|
153
|
+
first_tool_call_id = msg['tool_calls'][0].get('id')
|
|
154
|
+
seen_tool_call_ids = (
|
|
155
|
+
{first_tool_call_id} if first_tool_call_id else set()
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Scan ahead to find pattern: tool_result, assistant,
|
|
159
|
+
# tool_result, ...
|
|
160
|
+
while j < n:
|
|
161
|
+
next_msg = messages[j]
|
|
162
|
+
next_role = next_msg.get('role')
|
|
163
|
+
|
|
164
|
+
if next_role == 'tool':
|
|
165
|
+
# Tool result - check if it belongs to our batch
|
|
166
|
+
if next_msg.get('tool_call_id') in seen_tool_call_ids:
|
|
167
|
+
j += 1
|
|
168
|
+
continue
|
|
169
|
+
else:
|
|
170
|
+
# Tool result for unknown call, stop scanning
|
|
171
|
+
break
|
|
172
|
+
elif (
|
|
173
|
+
next_role == 'assistant'
|
|
174
|
+
and 'tool_calls' in next_msg
|
|
175
|
+
and isinstance(next_msg['tool_calls'], list)
|
|
176
|
+
and len(next_msg['tool_calls']) == 1
|
|
177
|
+
):
|
|
178
|
+
# Another single tool call - mark for merging
|
|
179
|
+
has_more_tool_calls = True
|
|
180
|
+
tc_id = next_msg['tool_calls'][0].get('id')
|
|
181
|
+
if tc_id:
|
|
182
|
+
seen_tool_call_ids.add(tc_id)
|
|
183
|
+
j += 1
|
|
184
|
+
continue
|
|
185
|
+
else:
|
|
186
|
+
# Something else, stop scanning
|
|
187
|
+
break
|
|
188
|
+
|
|
189
|
+
if has_more_tool_calls:
|
|
190
|
+
# Need to merge: collect all tool calls and results
|
|
191
|
+
merged_tool_calls = []
|
|
192
|
+
tool_results = []
|
|
193
|
+
is_first = True
|
|
194
|
+
|
|
195
|
+
for k in range(i, j):
|
|
196
|
+
m = messages[k]
|
|
197
|
+
if m.get('role') == 'assistant' and 'tool_calls' in m:
|
|
198
|
+
tc = m['tool_calls'][0]
|
|
199
|
+
if is_first:
|
|
200
|
+
# Keep extra_content only on first tool call
|
|
201
|
+
merged_tool_calls.append(copy.deepcopy(tc))
|
|
202
|
+
is_first = False
|
|
203
|
+
else:
|
|
204
|
+
# Remove extra_content from subsequent tool
|
|
205
|
+
# calls
|
|
206
|
+
tc_copy = {
|
|
207
|
+
k: v
|
|
208
|
+
for k, v in tc.items()
|
|
209
|
+
if k != 'extra_content'
|
|
210
|
+
}
|
|
211
|
+
merged_tool_calls.append(tc_copy)
|
|
212
|
+
elif m.get('role') == 'tool':
|
|
213
|
+
tool_results.append(copy.deepcopy(m))
|
|
214
|
+
|
|
215
|
+
# Build merged assistant message
|
|
216
|
+
merged_msg = copy.deepcopy(msg)
|
|
217
|
+
merged_msg['tool_calls'] = merged_tool_calls
|
|
218
|
+
if 'content' in merged_msg and merged_msg['content'] == '':
|
|
219
|
+
merged_msg['content'] = 'null'
|
|
220
|
+
|
|
221
|
+
processed_messages.append(merged_msg)
|
|
222
|
+
processed_messages.extend(tool_results)
|
|
223
|
+
i = j
|
|
224
|
+
continue
|
|
225
|
+
|
|
226
|
+
# Regular message processing (no merging needed)
|
|
227
|
+
msg_copy = copy.deepcopy(msg)
|
|
107
228
|
if 'content' in msg_copy and msg_copy['content'] == '':
|
|
108
229
|
msg_copy['content'] = 'null'
|
|
109
230
|
processed_messages.append(msg_copy)
|
|
231
|
+
i += 1
|
|
232
|
+
|
|
110
233
|
return processed_messages
|
|
111
234
|
|
|
235
|
+
def _preserve_thought_signatures(
|
|
236
|
+
self,
|
|
237
|
+
response: Union[
|
|
238
|
+
ChatCompletion,
|
|
239
|
+
Stream[ChatCompletionChunk],
|
|
240
|
+
AsyncStream[ChatCompletionChunk],
|
|
241
|
+
],
|
|
242
|
+
) -> Union[
|
|
243
|
+
ChatCompletion,
|
|
244
|
+
Generator[ChatCompletionChunk, None, None],
|
|
245
|
+
AsyncGenerator[ChatCompletionChunk, None],
|
|
246
|
+
]:
|
|
247
|
+
r"""Preserve thought signatures from Gemini responses for future
|
|
248
|
+
requests.
|
|
249
|
+
|
|
250
|
+
According to the Gemini documentation, when a response contains tool
|
|
251
|
+
calls with thought signatures, these signatures must be preserved
|
|
252
|
+
exactly as received when the response is added to conversation history
|
|
253
|
+
for subsequent requests.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
response: The response from Gemini API
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
The response with thought signatures properly preserved.
|
|
260
|
+
For streaming responses, returns generators that preserve
|
|
261
|
+
signatures.
|
|
262
|
+
"""
|
|
263
|
+
# For streaming responses, we need to wrap the stream to preserve
|
|
264
|
+
# thought signatures in tool calls as they come in
|
|
265
|
+
if isinstance(response, Stream):
|
|
266
|
+
return self._wrap_stream_with_thought_preservation(response)
|
|
267
|
+
elif isinstance(response, AsyncStream):
|
|
268
|
+
return self._wrap_async_stream_with_thought_preservation(response)
|
|
269
|
+
|
|
270
|
+
# For non-streaming responses, thought signatures are already preserved
|
|
271
|
+
# in _process_messages when the response becomes part of conversation
|
|
272
|
+
# history
|
|
273
|
+
return response
|
|
274
|
+
|
|
275
|
+
def _wrap_stream_with_thought_preservation(
|
|
276
|
+
self, stream: Stream[ChatCompletionChunk]
|
|
277
|
+
) -> Generator[ChatCompletionChunk, None, None]:
|
|
278
|
+
r"""Wrap a streaming response to preserve thought signatures in tool
|
|
279
|
+
calls.
|
|
280
|
+
|
|
281
|
+
This method ensures that when Gemini streaming responses contain tool
|
|
282
|
+
calls with thought signatures, these are properly preserved in the
|
|
283
|
+
extra_content field for future conversation context.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
stream: The original streaming response from Gemini
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
A wrapped stream that preserves thought signatures
|
|
290
|
+
"""
|
|
291
|
+
|
|
292
|
+
def thought_preserving_generator():
|
|
293
|
+
accumulated_signatures = {} # Store signatures by tool call index
|
|
294
|
+
|
|
295
|
+
for chunk in stream:
|
|
296
|
+
# Process chunk normally first
|
|
297
|
+
processed_chunk = chunk
|
|
298
|
+
|
|
299
|
+
# Check if this chunk contains tool call deltas with thought
|
|
300
|
+
# signatures
|
|
301
|
+
if (
|
|
302
|
+
hasattr(chunk, 'choices')
|
|
303
|
+
and chunk.choices
|
|
304
|
+
and hasattr(chunk.choices[0], 'delta')
|
|
305
|
+
and hasattr(chunk.choices[0].delta, 'tool_calls')
|
|
306
|
+
):
|
|
307
|
+
delta_tool_calls = chunk.choices[0].delta.tool_calls
|
|
308
|
+
if delta_tool_calls:
|
|
309
|
+
for tool_call_delta in delta_tool_calls:
|
|
310
|
+
index = tool_call_delta.index
|
|
311
|
+
|
|
312
|
+
# Check for thought signatures in the tool call
|
|
313
|
+
# response Gemini may include these in custom
|
|
314
|
+
# fields
|
|
315
|
+
if hasattr(tool_call_delta, 'extra_content'):
|
|
316
|
+
extra_content = tool_call_delta.extra_content
|
|
317
|
+
if (
|
|
318
|
+
isinstance(extra_content, dict)
|
|
319
|
+
and 'google' in extra_content
|
|
320
|
+
):
|
|
321
|
+
google_content = extra_content['google']
|
|
322
|
+
if 'thought_signature' in google_content:
|
|
323
|
+
# Store the thought signature for this
|
|
324
|
+
# tool call
|
|
325
|
+
accumulated_signatures[index] = (
|
|
326
|
+
extra_content
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
# Also check if thought signature is in function
|
|
330
|
+
# response
|
|
331
|
+
elif hasattr(
|
|
332
|
+
tool_call_delta, 'function'
|
|
333
|
+
) and hasattr(
|
|
334
|
+
tool_call_delta.function, 'extra_content'
|
|
335
|
+
):
|
|
336
|
+
func_extra = (
|
|
337
|
+
tool_call_delta.function.extra_content
|
|
338
|
+
)
|
|
339
|
+
if (
|
|
340
|
+
isinstance(func_extra, dict)
|
|
341
|
+
and 'google' in func_extra
|
|
342
|
+
):
|
|
343
|
+
accumulated_signatures[index] = func_extra
|
|
344
|
+
|
|
345
|
+
# If we have accumulated signature for this tool
|
|
346
|
+
# call, ensure it's preserved in the chunk
|
|
347
|
+
if index in accumulated_signatures:
|
|
348
|
+
# Add extra_content to tool call delta if it
|
|
349
|
+
# doesn't exist
|
|
350
|
+
if not hasattr(
|
|
351
|
+
tool_call_delta, 'extra_content'
|
|
352
|
+
):
|
|
353
|
+
tool_call_delta.extra_content = (
|
|
354
|
+
accumulated_signatures[index]
|
|
355
|
+
)
|
|
356
|
+
elif tool_call_delta.extra_content is None:
|
|
357
|
+
tool_call_delta.extra_content = (
|
|
358
|
+
accumulated_signatures[index]
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
yield processed_chunk
|
|
362
|
+
|
|
363
|
+
return thought_preserving_generator()
|
|
364
|
+
|
|
365
|
+
def _wrap_async_stream_with_thought_preservation(
|
|
366
|
+
self, stream: AsyncStream[ChatCompletionChunk]
|
|
367
|
+
) -> AsyncGenerator[ChatCompletionChunk, None]:
|
|
368
|
+
r"""Wrap an async streaming response to preserve thought signatures in
|
|
369
|
+
tool calls.
|
|
370
|
+
|
|
371
|
+
This method ensures that when Gemini async streaming responses contain
|
|
372
|
+
tool calls with thought signatures, these are properly preserved in
|
|
373
|
+
the extra_content field for future conversation context.
|
|
374
|
+
|
|
375
|
+
Args:
|
|
376
|
+
stream: The original async streaming response from Gemini
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
A wrapped async stream that preserves thought signatures
|
|
380
|
+
"""
|
|
381
|
+
|
|
382
|
+
async def async_thought_preserving_generator():
|
|
383
|
+
accumulated_signatures = {} # Store signatures by tool call index
|
|
384
|
+
|
|
385
|
+
async for chunk in stream:
|
|
386
|
+
# Process chunk normally first
|
|
387
|
+
processed_chunk = chunk
|
|
388
|
+
|
|
389
|
+
# Check if this chunk contains tool call deltas with thought
|
|
390
|
+
# signatures
|
|
391
|
+
if (
|
|
392
|
+
hasattr(chunk, 'choices')
|
|
393
|
+
and chunk.choices
|
|
394
|
+
and hasattr(chunk.choices[0], 'delta')
|
|
395
|
+
and hasattr(chunk.choices[0].delta, 'tool_calls')
|
|
396
|
+
):
|
|
397
|
+
delta_tool_calls = chunk.choices[0].delta.tool_calls
|
|
398
|
+
if delta_tool_calls:
|
|
399
|
+
for tool_call_delta in delta_tool_calls:
|
|
400
|
+
index = tool_call_delta.index
|
|
401
|
+
|
|
402
|
+
# Check for thought signatures in the tool call
|
|
403
|
+
# response
|
|
404
|
+
if hasattr(tool_call_delta, 'extra_content'):
|
|
405
|
+
extra_content = tool_call_delta.extra_content
|
|
406
|
+
if (
|
|
407
|
+
isinstance(extra_content, dict)
|
|
408
|
+
and 'google' in extra_content
|
|
409
|
+
):
|
|
410
|
+
google_content = extra_content['google']
|
|
411
|
+
if 'thought_signature' in google_content:
|
|
412
|
+
# Store the thought signature for this
|
|
413
|
+
# tool call
|
|
414
|
+
accumulated_signatures[index] = (
|
|
415
|
+
extra_content
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
# Also check if thought signature is in function
|
|
419
|
+
# response
|
|
420
|
+
elif hasattr(
|
|
421
|
+
tool_call_delta, 'function'
|
|
422
|
+
) and hasattr(
|
|
423
|
+
tool_call_delta.function, 'extra_content'
|
|
424
|
+
):
|
|
425
|
+
func_extra = (
|
|
426
|
+
tool_call_delta.function.extra_content
|
|
427
|
+
)
|
|
428
|
+
if (
|
|
429
|
+
isinstance(func_extra, dict)
|
|
430
|
+
and 'google' in func_extra
|
|
431
|
+
):
|
|
432
|
+
accumulated_signatures[index] = func_extra
|
|
433
|
+
|
|
434
|
+
# If we have accumulated signature for this tool
|
|
435
|
+
# call, ensure it's preserved in the chunk
|
|
436
|
+
if index in accumulated_signatures:
|
|
437
|
+
# Add extra_content to tool call delta if it
|
|
438
|
+
# doesn't exist
|
|
439
|
+
if not hasattr(
|
|
440
|
+
tool_call_delta, 'extra_content'
|
|
441
|
+
):
|
|
442
|
+
tool_call_delta.extra_content = (
|
|
443
|
+
accumulated_signatures[index]
|
|
444
|
+
)
|
|
445
|
+
elif tool_call_delta.extra_content is None:
|
|
446
|
+
tool_call_delta.extra_content = (
|
|
447
|
+
accumulated_signatures[index]
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
yield processed_chunk
|
|
451
|
+
|
|
452
|
+
return async_thought_preserving_generator()
|
|
453
|
+
|
|
112
454
|
@observe()
|
|
113
455
|
def _run(
|
|
114
456
|
self,
|
|
@@ -131,18 +473,7 @@ class GeminiModel(OpenAICompatibleModel):
|
|
|
131
473
|
`ChatCompletion` in the non-stream mode, or
|
|
132
474
|
`Stream[ChatCompletionChunk]` in the stream mode.
|
|
133
475
|
"""
|
|
134
|
-
|
|
135
|
-
# Update Langfuse trace with current agent session and metadata
|
|
136
|
-
agent_session_id = get_current_agent_session_id()
|
|
137
|
-
if agent_session_id:
|
|
138
|
-
update_langfuse_trace(
|
|
139
|
-
session_id=agent_session_id,
|
|
140
|
-
metadata={
|
|
141
|
-
"agent_id": agent_session_id,
|
|
142
|
-
"model_type": str(self.model_type),
|
|
143
|
-
},
|
|
144
|
-
tags=["CAMEL-AI", str(self.model_type)],
|
|
145
|
-
)
|
|
476
|
+
self._log_and_trace()
|
|
146
477
|
|
|
147
478
|
response_format = response_format or self.model_config_dict.get(
|
|
148
479
|
"response_format", None
|
|
@@ -184,18 +515,7 @@ class GeminiModel(OpenAICompatibleModel):
|
|
|
184
515
|
`ChatCompletion` in the non-stream mode, or
|
|
185
516
|
`AsyncStream[ChatCompletionChunk]` in the stream mode.
|
|
186
517
|
"""
|
|
187
|
-
|
|
188
|
-
# Update Langfuse trace with current agent session and metadata
|
|
189
|
-
agent_session_id = get_current_agent_session_id()
|
|
190
|
-
if agent_session_id:
|
|
191
|
-
update_langfuse_trace(
|
|
192
|
-
session_id=agent_session_id,
|
|
193
|
-
metadata={
|
|
194
|
-
"agent_id": agent_session_id,
|
|
195
|
-
"model_type": str(self.model_type),
|
|
196
|
-
},
|
|
197
|
-
tags=["CAMEL-AI", str(self.model_type)],
|
|
198
|
-
)
|
|
518
|
+
self._log_and_trace()
|
|
199
519
|
|
|
200
520
|
response_format = response_format or self.model_config_dict.get(
|
|
201
521
|
"response_format", None
|
|
@@ -230,7 +550,7 @@ class GeminiModel(OpenAICompatibleModel):
|
|
|
230
550
|
function_dict = tool.get('function', {})
|
|
231
551
|
function_dict.pop("strict", None)
|
|
232
552
|
|
|
233
|
-
# Process parameters to remove anyOf
|
|
553
|
+
# Process parameters to remove anyOf and handle enum/format
|
|
234
554
|
if 'parameters' in function_dict:
|
|
235
555
|
params = function_dict['parameters']
|
|
236
556
|
if 'properties' in params:
|
|
@@ -247,14 +567,31 @@ class GeminiModel(OpenAICompatibleModel):
|
|
|
247
567
|
'description'
|
|
248
568
|
] = prop_value['description']
|
|
249
569
|
|
|
570
|
+
# Handle enum and format restrictions for Gemini
|
|
571
|
+
# API enum: only allowed for string type
|
|
572
|
+
if prop_value.get('type') != 'string':
|
|
573
|
+
prop_value.pop('enum', None)
|
|
574
|
+
|
|
575
|
+
# format: only allowed for string, integer, and
|
|
576
|
+
# number types
|
|
577
|
+
if prop_value.get('type') not in [
|
|
578
|
+
'string',
|
|
579
|
+
'integer',
|
|
580
|
+
'number',
|
|
581
|
+
]:
|
|
582
|
+
prop_value.pop('format', None)
|
|
583
|
+
|
|
250
584
|
request_config["tools"] = tools
|
|
251
585
|
|
|
252
|
-
|
|
586
|
+
response = self._client.chat.completions.create(
|
|
253
587
|
messages=messages,
|
|
254
588
|
model=self.model_type,
|
|
255
589
|
**request_config,
|
|
256
590
|
)
|
|
257
591
|
|
|
592
|
+
# Preserve thought signatures from the response for future requests
|
|
593
|
+
return self._preserve_thought_signatures(response) # type: ignore[return-value]
|
|
594
|
+
|
|
258
595
|
async def _arequest_chat_completion(
|
|
259
596
|
self,
|
|
260
597
|
messages: List[OpenAIMessage],
|
|
@@ -270,7 +607,7 @@ class GeminiModel(OpenAICompatibleModel):
|
|
|
270
607
|
function_dict = tool.get('function', {})
|
|
271
608
|
function_dict.pop("strict", None)
|
|
272
609
|
|
|
273
|
-
# Process parameters to remove anyOf
|
|
610
|
+
# Process parameters to remove anyOf and handle enum/format
|
|
274
611
|
if 'parameters' in function_dict:
|
|
275
612
|
params = function_dict['parameters']
|
|
276
613
|
if 'properties' in params:
|
|
@@ -287,25 +624,27 @@ class GeminiModel(OpenAICompatibleModel):
|
|
|
287
624
|
'description'
|
|
288
625
|
] = prop_value['description']
|
|
289
626
|
|
|
627
|
+
# Handle enum and format restrictions for Gemini
|
|
628
|
+
# API enum: only allowed for string type
|
|
629
|
+
if prop_value.get('type') != 'string':
|
|
630
|
+
prop_value.pop('enum', None)
|
|
631
|
+
|
|
632
|
+
# format: only allowed for string, integer, and
|
|
633
|
+
# number types
|
|
634
|
+
if prop_value.get('type') not in [
|
|
635
|
+
'string',
|
|
636
|
+
'integer',
|
|
637
|
+
'number',
|
|
638
|
+
]:
|
|
639
|
+
prop_value.pop('format', None)
|
|
640
|
+
|
|
290
641
|
request_config["tools"] = tools
|
|
291
642
|
|
|
292
|
-
|
|
643
|
+
response = await self._async_client.chat.completions.create(
|
|
293
644
|
messages=messages,
|
|
294
645
|
model=self.model_type,
|
|
295
646
|
**request_config,
|
|
296
647
|
)
|
|
297
648
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
unexpected arguments to Gemini API.
|
|
301
|
-
|
|
302
|
-
Raises:
|
|
303
|
-
ValueError: If the model configuration dictionary contains any
|
|
304
|
-
unexpected arguments to Gemini API.
|
|
305
|
-
"""
|
|
306
|
-
for param in self.model_config_dict:
|
|
307
|
-
if param not in Gemini_API_PARAMS:
|
|
308
|
-
raise ValueError(
|
|
309
|
-
f"Unexpected argument `{param}` is "
|
|
310
|
-
"input into Gemini model backend."
|
|
311
|
-
)
|
|
649
|
+
# Preserve thought signatures from the response for future requests
|
|
650
|
+
return self._preserve_thought_signatures(response) # type: ignore[return-value]
|
camel/models/groq_model.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,11 +10,11 @@
|
|
|
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
|
import os
|
|
15
15
|
from typing import Any, Dict, Optional, Union
|
|
16
16
|
|
|
17
|
-
from camel.configs import
|
|
17
|
+
from camel.configs import GroqConfig
|
|
18
18
|
from camel.models.openai_compatible_model import OpenAICompatibleModel
|
|
19
19
|
from camel.types import ModelType
|
|
20
20
|
from camel.utils import (
|
|
@@ -45,6 +45,10 @@ class GroqModel(OpenAICompatibleModel):
|
|
|
45
45
|
API calls. If not provided, will fall back to the MODEL_TIMEOUT
|
|
46
46
|
environment variable or default to 180 seconds.
|
|
47
47
|
(default: :obj:`None`)
|
|
48
|
+
max_retries (int, optional): Maximum number of retries for API calls.
|
|
49
|
+
(default: :obj:`3`)
|
|
50
|
+
**kwargs (Any): Additional arguments to pass to the client
|
|
51
|
+
initialization.
|
|
48
52
|
"""
|
|
49
53
|
|
|
50
54
|
@api_keys_required([("api_key", "GROQ_API_KEY")])
|
|
@@ -56,6 +60,8 @@ class GroqModel(OpenAICompatibleModel):
|
|
|
56
60
|
url: Optional[str] = None,
|
|
57
61
|
token_counter: Optional[BaseTokenCounter] = None,
|
|
58
62
|
timeout: Optional[float] = None,
|
|
63
|
+
max_retries: int = 3,
|
|
64
|
+
**kwargs: Any,
|
|
59
65
|
) -> None:
|
|
60
66
|
if model_config_dict is None:
|
|
61
67
|
model_config_dict = GroqConfig().as_dict()
|
|
@@ -71,20 +77,6 @@ class GroqModel(OpenAICompatibleModel):
|
|
|
71
77
|
url=url,
|
|
72
78
|
token_counter=token_counter,
|
|
73
79
|
timeout=timeout,
|
|
80
|
+
max_retries=max_retries,
|
|
81
|
+
**kwargs,
|
|
74
82
|
)
|
|
75
|
-
|
|
76
|
-
def check_model_config(self):
|
|
77
|
-
r"""Check whether the model configuration contains any unexpected
|
|
78
|
-
arguments to Groq API. But Groq API does not have any additional
|
|
79
|
-
arguments to check.
|
|
80
|
-
|
|
81
|
-
Raises:
|
|
82
|
-
ValueError: If the model configuration dictionary contains any
|
|
83
|
-
unexpected arguments to Groq API.
|
|
84
|
-
"""
|
|
85
|
-
for param in self.model_config_dict:
|
|
86
|
-
if param not in GROQ_API_PARAMS:
|
|
87
|
-
raise ValueError(
|
|
88
|
-
f"Unexpected argument `{param}` is "
|
|
89
|
-
"input into Groq model backend."
|
|
90
|
-
)
|
camel/models/internlm_model.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
|
|
|
15
15
|
import os
|
|
16
16
|
from typing import Any, Dict, List, Optional, Type, Union
|
|
@@ -18,7 +18,7 @@ from typing import Any, Dict, List, Optional, Type, Union
|
|
|
18
18
|
from openai import AsyncStream
|
|
19
19
|
from pydantic import BaseModel
|
|
20
20
|
|
|
21
|
-
from camel.configs import
|
|
21
|
+
from camel.configs import InternLMConfig
|
|
22
22
|
from camel.messages import OpenAIMessage
|
|
23
23
|
from camel.models.openai_compatible_model import OpenAICompatibleModel
|
|
24
24
|
from camel.types import (
|
|
@@ -54,6 +54,10 @@ class InternLMModel(OpenAICompatibleModel):
|
|
|
54
54
|
API calls. If not provided, will fall back to the MODEL_TIMEOUT
|
|
55
55
|
environment variable or default to 180 seconds.
|
|
56
56
|
(default: :obj:`None`)
|
|
57
|
+
max_retries (int, optional): Maximum number of retries for API calls.
|
|
58
|
+
(default: :obj:`3`)
|
|
59
|
+
**kwargs (Any): Additional arguments to pass to the client
|
|
60
|
+
initialization.
|
|
57
61
|
"""
|
|
58
62
|
|
|
59
63
|
@api_keys_required(
|
|
@@ -69,6 +73,8 @@ class InternLMModel(OpenAICompatibleModel):
|
|
|
69
73
|
url: Optional[str] = None,
|
|
70
74
|
token_counter: Optional[BaseTokenCounter] = None,
|
|
71
75
|
timeout: Optional[float] = None,
|
|
76
|
+
max_retries: int = 3,
|
|
77
|
+
**kwargs: Any,
|
|
72
78
|
) -> None:
|
|
73
79
|
self.model_config = model_config_dict or InternLMConfig().as_dict()
|
|
74
80
|
api_key = api_key or os.environ.get("INTERNLM_API_KEY")
|
|
@@ -84,6 +90,8 @@ class InternLMModel(OpenAICompatibleModel):
|
|
|
84
90
|
url=url,
|
|
85
91
|
token_counter=token_counter,
|
|
86
92
|
timeout=timeout,
|
|
93
|
+
max_retries=max_retries,
|
|
94
|
+
**kwargs,
|
|
87
95
|
)
|
|
88
96
|
|
|
89
97
|
async def _arun(
|
|
@@ -93,18 +101,3 @@ class InternLMModel(OpenAICompatibleModel):
|
|
|
93
101
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
94
102
|
) -> Union[ChatCompletion, AsyncStream[ChatCompletionChunk]]:
|
|
95
103
|
raise NotImplementedError("InternLM does not support async inference.")
|
|
96
|
-
|
|
97
|
-
def check_model_config(self):
|
|
98
|
-
r"""Check whether the model configuration contains any
|
|
99
|
-
unexpected arguments to InternLM API.
|
|
100
|
-
|
|
101
|
-
Raises:
|
|
102
|
-
ValueError: If the model configuration dictionary contains any
|
|
103
|
-
unexpected arguments to InternLM API.
|
|
104
|
-
"""
|
|
105
|
-
for param in self.model_config_dict:
|
|
106
|
-
if param not in INTERNLM_API_PARAMS:
|
|
107
|
-
raise ValueError(
|
|
108
|
-
f"Unexpected argument `{param}` is "
|
|
109
|
-
"input into InternLM model backend."
|
|
110
|
-
)
|