camel-ai 0.2.27__tar.gz → 0.2.28__tar.gz
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_ai-0.2.27 → camel_ai-0.2.28}/PKG-INFO +1 -1
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/__init__.py +1 -1
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/azure_openai_model.py +2 -1
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/sglang_model.py +3 -2
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/vllm_model.py +22 -2
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/graph_storages/neo4j_graph.py +10 -8
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/__init__.py +1 -0
- camel_ai-0.2.28/camel/toolkits/mcp_toolkit.py +509 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/pyproject.toml +1 -1
- camel_ai-0.2.27/camel/toolkits/mcp_toolkit.py +0 -251
- {camel_ai-0.2.27 → camel_ai-0.2.28}/.gitignore +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/LICENSE +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/README.md +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/_types.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/_utils.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/chat_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/critic_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/deductive_reasoner_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/embodied_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/knowledge_graph_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/multi_hop_generator_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/programmed_agent_instruction.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/role_assignment_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/search_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/task_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/tool_agents/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/tool_agents/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/agents/tool_agents/hugging_face_tool_agent.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/benchmarks/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/benchmarks/apibank.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/benchmarks/apibench.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/benchmarks/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/benchmarks/gaia.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/benchmarks/nexus.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/benchmarks/ragbench.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/bots/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/bots/discord/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/bots/discord/discord_app.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/bots/discord/discord_installation.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/bots/discord/discord_store.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/bots/slack/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/bots/slack/models.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/bots/slack/slack_app.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/bots/telegram_bot.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/aiml_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/anthropic_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/base_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/cohere_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/deepseek_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/gemini_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/groq_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/internlm_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/litellm_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/mistral_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/moonshot_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/nvidia_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/ollama_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/openai_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/qwen_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/reka_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/samba_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/sglang_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/siliconflow_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/togetherai_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/vllm_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/yi_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/configs/zhipuai_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/data_collector/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/data_collector/alpaca_collector.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/data_collector/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/data_collector/sharegpt_collector.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/cot_datagen.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/self_improving_cot.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/self_instruct/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/self_instruct/filter/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/self_instruct/filter/filter_function.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/self_instruct/filter/filter_registry.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/self_instruct/filter/instruction_filter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/self_instruct/self_instruct.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/self_instruct/templates.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/source2synth/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/source2synth/data_processor.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/source2synth/models.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datagen/source2synth/user_data_processor_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datahubs/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datahubs/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datahubs/huggingface.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datahubs/models.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datasets/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/datasets/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/embeddings/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/embeddings/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/embeddings/jina_embedding.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/embeddings/mistral_embedding.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/embeddings/openai_compatible_embedding.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/embeddings/openai_embedding.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/embeddings/sentence_transformers_embeddings.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/embeddings/vlm_embedding.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/environments/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/environments/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/extractors/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/extractors/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/extractors/python_strategies.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/generators.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/human.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/interpreters/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/interpreters/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/interpreters/docker/Dockerfile +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/interpreters/docker_interpreter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/interpreters/e2b_interpreter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/interpreters/internal_python_interpreter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/interpreters/interpreter_error.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/interpreters/ipython_interpreter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/interpreters/subprocess_interpreter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/loaders/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/loaders/apify_reader.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/loaders/base_io.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/loaders/chunkr_reader.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/loaders/firecrawl_reader.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/loaders/jina_url_reader.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/loaders/mineru_extractor.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/loaders/panda_reader.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/loaders/unstructured_io.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/logger.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/memories/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/memories/agent_memories.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/memories/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/memories/blocks/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/memories/blocks/chat_history_block.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/memories/blocks/vectordb_block.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/memories/context_creators/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/memories/context_creators/score_based.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/memories/records.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/conversion/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/conversion/alpaca.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/conversion/conversation_models.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/conversion/sharegpt/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/conversion/sharegpt/function_call_formatter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/conversion/sharegpt/hermes/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/conversion/sharegpt/hermes/hermes_function_formatter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/messages/func_message.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/_utils.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/aiml_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/anthropic_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/base_audio_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/base_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/cohere_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/deepseek_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/fish_audio_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/gemini_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/groq_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/internlm_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/litellm_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/mistral_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/model_factory.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/model_manager.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/moonshot_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/nemotron_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/nvidia_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/ollama_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/openai_audio_models.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/openai_compatible_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/openai_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/qwen_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/reka_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/reward/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/reward/base_reward_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/reward/evaluator.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/reward/nemotron_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/reward/skywork_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/samba_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/siliconflow_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/stub_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/togetherai_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/volcano_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/yi_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/models/zhipuai_model.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/personas/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/personas/persona.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/personas/persona_hub.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/ai_society.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/code.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/evaluation.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/generate_text_embedding_data.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/image_craft.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/misalignment.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/multi_condition_image_craft.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/object_recognition.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/persona_hub.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/prompt_templates.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/role_description_prompt_template.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/solution_extraction.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/task_prompt_template.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/translation.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/prompts/video_description_prompt.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/py.typed +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/responses/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/responses/agent_responses.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/retrievers/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/retrievers/auto_retriever.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/retrievers/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/retrievers/bm25_retriever.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/retrievers/cohere_rerank_retriever.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/retrievers/hybrid_retrival.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/retrievers/vector_retriever.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/api.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/configs.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/docker_runtime.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/llm_guard_runtime.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/remote_http_runtime.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/utils/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/utils/function_risk_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/runtime/utils/ignore_risk_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/schemas/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/schemas/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/schemas/openai_converter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/schemas/outlines_converter.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/babyagi_playing.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/role_playing.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/workforce/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/workforce/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/workforce/prompts.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/workforce/role_playing_worker.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/workforce/single_agent_worker.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/workforce/task_channel.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/workforce/utils.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/workforce/worker.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/societies/workforce/workforce.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/graph_storages/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/graph_storages/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/graph_storages/graph_element.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/graph_storages/nebula_graph.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/key_value_storages/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/key_value_storages/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/key_value_storages/in_memory.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/key_value_storages/json.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/key_value_storages/redis.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/object_storages/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/object_storages/amazon_s3.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/object_storages/azure_blob.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/object_storages/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/object_storages/google_cloud.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/vectordb_storages/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/vectordb_storages/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/vectordb_storages/milvus.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/storages/vectordb_storages/qdrant.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/tasks/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/tasks/task.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/tasks/task_prompt.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/terminators/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/terminators/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/terminators/response_terminator.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/terminators/token_limit_terminator.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/arxiv_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/ask_news_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/audio_analysis_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/browser_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/code_execution.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/dalle_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/dappier_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/data_commons_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/excel_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/file_write_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/function_tool.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/github_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/google_maps_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/google_scholar_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/human_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/image_analysis_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/linkedin_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/math_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/meshy_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/mineru_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/networkx_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/notion_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/biztoc/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/biztoc/ai-plugin.json +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/biztoc/openapi.yaml +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/coursera/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/coursera/openapi.yaml +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/create_qr_code/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/create_qr_code/openapi.yaml +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/klarna/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/klarna/openapi.yaml +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/nasa_apod/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/nasa_apod/openapi.yaml +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/outschool/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/outschool/ai-plugin.json +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/outschool/openapi.yaml +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/outschool/paths/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/outschool/paths/get_classes.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/outschool/paths/search_teachers.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/security_config.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/speak/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/speak/openapi.yaml +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/web_scraper/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/web_scraper/ai-plugin.json +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/web_scraper/openapi.yaml +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/web_scraper/paths/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_specs/web_scraper/paths/scraper.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/open_api_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/openbb_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/page_script.js +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/pubmed_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/reddit_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/retrieval_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/search_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/semantic_scholar_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/slack_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/stripe_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/sympy_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/terminal_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/twitter_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/video_analysis_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/video_download_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/weather_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/whatsapp_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/toolkits/zapier_toolkit.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/types/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/types/agents/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/types/agents/tool_calling_record.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/types/enums.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/types/openai_types.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/types/unified_model_type.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/utils/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/utils/async_func.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/utils/commons.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/utils/constants.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/utils/deduplication.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/utils/response_format.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/utils/token_counting.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/verifiers/__init__.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/verifiers/base.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/verifiers/models.py +0 -0
- {camel_ai-0.2.27 → camel_ai-0.2.28}/camel/verifiers/python_verifier.py +0 -0
|
@@ -263,7 +263,8 @@ class AzureOpenAIModel(BaseModelBackend):
|
|
|
263
263
|
@property
|
|
264
264
|
def stream(self) -> bool:
|
|
265
265
|
r"""Returns whether the model is in stream mode,
|
|
266
|
-
|
|
266
|
+
which sends partial results each time.
|
|
267
|
+
|
|
267
268
|
Returns:
|
|
268
269
|
bool: Whether the model is in stream mode.
|
|
269
270
|
"""
|
|
@@ -350,8 +350,9 @@ def _wait_for_server(base_url: str, timeout: Optional[int] = 30) -> None:
|
|
|
350
350
|
r"""Wait for the server to be ready by polling the /v1/models endpoint.
|
|
351
351
|
|
|
352
352
|
Args:
|
|
353
|
-
base_url: The base URL of the server
|
|
354
|
-
timeout: Maximum time to wait in seconds.
|
|
353
|
+
base_url (str): The base URL of the server
|
|
354
|
+
timeout (Optional[int]): Maximum time to wait in seconds.
|
|
355
|
+
(default: :obj:`30`)
|
|
355
356
|
"""
|
|
356
357
|
import requests
|
|
357
358
|
|
|
@@ -139,6 +139,10 @@ class VLLMModel(BaseModelBackend):
|
|
|
139
139
|
Args:
|
|
140
140
|
messages (List[OpenAIMessage]): Message list with the chat history
|
|
141
141
|
in OpenAI API format.
|
|
142
|
+
response_format (Optional[Type[BaseModel]], optional): The format
|
|
143
|
+
to return the response in.
|
|
144
|
+
tools (Optional[List[Dict[str, Any]]], optional): List of tools
|
|
145
|
+
the model may call.
|
|
142
146
|
|
|
143
147
|
Returns:
|
|
144
148
|
Union[ChatCompletion, AsyncStream[ChatCompletionChunk]]:
|
|
@@ -146,10 +150,16 @@ class VLLMModel(BaseModelBackend):
|
|
|
146
150
|
`AsyncStream[ChatCompletionChunk]` in the stream mode.
|
|
147
151
|
"""
|
|
148
152
|
|
|
153
|
+
kwargs = self.model_config_dict.copy()
|
|
154
|
+
if tools:
|
|
155
|
+
kwargs["tools"] = tools
|
|
156
|
+
if response_format:
|
|
157
|
+
kwargs["response_format"] = {"type": "json_object"}
|
|
158
|
+
|
|
149
159
|
response = await self._async_client.chat.completions.create(
|
|
150
160
|
messages=messages,
|
|
151
161
|
model=self.model_type,
|
|
152
|
-
**
|
|
162
|
+
**kwargs,
|
|
153
163
|
)
|
|
154
164
|
return response
|
|
155
165
|
|
|
@@ -164,6 +174,10 @@ class VLLMModel(BaseModelBackend):
|
|
|
164
174
|
Args:
|
|
165
175
|
messages (List[OpenAIMessage]): Message list with the chat history
|
|
166
176
|
in OpenAI API format.
|
|
177
|
+
response_format (Optional[Type[BaseModel]], optional): The format
|
|
178
|
+
to return the response in.
|
|
179
|
+
tools (Optional[List[Dict[str, Any]]], optional): List of tools
|
|
180
|
+
the model may call.
|
|
167
181
|
|
|
168
182
|
Returns:
|
|
169
183
|
Union[ChatCompletion, Stream[ChatCompletionChunk]]:
|
|
@@ -171,10 +185,16 @@ class VLLMModel(BaseModelBackend):
|
|
|
171
185
|
`Stream[ChatCompletionChunk]` in the stream mode.
|
|
172
186
|
"""
|
|
173
187
|
|
|
188
|
+
kwargs = self.model_config_dict.copy()
|
|
189
|
+
if tools:
|
|
190
|
+
kwargs["tools"] = tools
|
|
191
|
+
if response_format:
|
|
192
|
+
kwargs["response_format"] = {"type": "json_object"}
|
|
193
|
+
|
|
174
194
|
response = self._client.chat.completions.create(
|
|
175
195
|
messages=messages,
|
|
176
196
|
model=self.model_type,
|
|
177
|
-
**
|
|
197
|
+
**kwargs,
|
|
178
198
|
)
|
|
179
199
|
return response
|
|
180
200
|
|
|
@@ -343,14 +343,14 @@ class Neo4jGraph(BaseGraphStorage):
|
|
|
343
343
|
self, subj: str, obj: str, rel: str, timestamp: Optional[str] = None
|
|
344
344
|
) -> None:
|
|
345
345
|
r"""Adds a relationship (triplet) between two entities
|
|
346
|
-
|
|
346
|
+
in the database with a timestamp.
|
|
347
347
|
|
|
348
348
|
Args:
|
|
349
349
|
subj (str): The identifier for the subject entity.
|
|
350
350
|
obj (str): The identifier for the object entity.
|
|
351
351
|
rel (str): The relationship between the subject and object.
|
|
352
352
|
timestamp (Optional[str]): The timestamp of the relationship.
|
|
353
|
-
|
|
353
|
+
Defaults to None.
|
|
354
354
|
"""
|
|
355
355
|
query = """
|
|
356
356
|
MERGE (n1:`%s` {id:$subj})
|
|
@@ -737,21 +737,23 @@ class Neo4jGraph(BaseGraphStorage):
|
|
|
737
737
|
obj: Optional[str] = None,
|
|
738
738
|
rel: Optional[str] = None,
|
|
739
739
|
) -> List[Dict[str, Any]]:
|
|
740
|
-
r"""
|
|
741
|
-
Query triplet information. If subj, obj, or rel is
|
|
740
|
+
r"""Query triplet information. If subj, obj, or rel is
|
|
742
741
|
not specified, returns all matching triplets.
|
|
743
742
|
|
|
744
743
|
Args:
|
|
745
744
|
subj (Optional[str]): The ID of the subject node.
|
|
746
|
-
|
|
745
|
+
If None, matches any subject node.
|
|
746
|
+
(default: :obj:`None`)
|
|
747
747
|
obj (Optional[str]): The ID of the object node.
|
|
748
|
-
|
|
748
|
+
If None, matches any object node.
|
|
749
|
+
(default: :obj:`None`)
|
|
749
750
|
rel (Optional[str]): The type of relationship.
|
|
750
|
-
|
|
751
|
+
If None, matches any relationship type.
|
|
752
|
+
(default: :obj:`None`)
|
|
751
753
|
|
|
752
754
|
Returns:
|
|
753
755
|
List[Dict[str, Any]]: A list of matching triplets,
|
|
754
|
-
|
|
756
|
+
each containing subj, obj, rel, and timestamp.
|
|
755
757
|
"""
|
|
756
758
|
import logging
|
|
757
759
|
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
# you may not use this file except in compliance with the License.
|
|
4
|
+
# You may obtain a copy of the License at
|
|
5
|
+
#
|
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
#
|
|
8
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
9
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
10
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
|
+
# See the License for the specific language governing permissions and
|
|
12
|
+
# limitations under the License.
|
|
13
|
+
# ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
|
+
import inspect
|
|
15
|
+
import json
|
|
16
|
+
import os
|
|
17
|
+
from contextlib import AsyncExitStack, asynccontextmanager
|
|
18
|
+
from typing import (
|
|
19
|
+
TYPE_CHECKING,
|
|
20
|
+
Any,
|
|
21
|
+
AsyncGenerator,
|
|
22
|
+
Callable,
|
|
23
|
+
Dict,
|
|
24
|
+
List,
|
|
25
|
+
Optional,
|
|
26
|
+
Set,
|
|
27
|
+
Union,
|
|
28
|
+
)
|
|
29
|
+
from urllib.parse import urlparse
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from mcp import ListToolsResult, Tool
|
|
33
|
+
|
|
34
|
+
from camel.logger import get_logger
|
|
35
|
+
from camel.toolkits import BaseToolkit, FunctionTool
|
|
36
|
+
|
|
37
|
+
logger = get_logger(__name__)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class _MCPServer(BaseToolkit):
|
|
41
|
+
r"""Internal class that provides an abstraction layer to interact with
|
|
42
|
+
external tools using the Model Context Protocol (MCP). It supports two
|
|
43
|
+
modes of connection:
|
|
44
|
+
|
|
45
|
+
1. stdio mode: Connects via standard input/output streams for local
|
|
46
|
+
command-line interactions.
|
|
47
|
+
|
|
48
|
+
2. SSE mode (HTTP Server-Sent Events): Connects via HTTP for persistent,
|
|
49
|
+
event-based interactions.
|
|
50
|
+
|
|
51
|
+
Attributes:
|
|
52
|
+
command_or_url (str): URL for SSE mode or command executable for stdio
|
|
53
|
+
mode. (default: :obj:`'None'`)
|
|
54
|
+
args (List[str]): List of command-line arguments if stdio mode is used.
|
|
55
|
+
(default: :obj:`'None'`)
|
|
56
|
+
env (Dict[str, str]): Environment variables for the stdio mode command.
|
|
57
|
+
(default: :obj:`'None'`)
|
|
58
|
+
timeout (Optional[float]): Connection timeout. (default: :obj:`'None'`)
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def __init__(
|
|
62
|
+
self,
|
|
63
|
+
command_or_url: str,
|
|
64
|
+
args: Optional[List[str]] = None,
|
|
65
|
+
env: Optional[Dict[str, str]] = None,
|
|
66
|
+
timeout: Optional[float] = None,
|
|
67
|
+
):
|
|
68
|
+
from mcp import Tool
|
|
69
|
+
from mcp.client.session import ClientSession
|
|
70
|
+
|
|
71
|
+
super().__init__(timeout=timeout)
|
|
72
|
+
|
|
73
|
+
self.command_or_url = command_or_url
|
|
74
|
+
self.args = args or []
|
|
75
|
+
self.env = env or {}
|
|
76
|
+
|
|
77
|
+
self._mcp_tools: List[Tool] = []
|
|
78
|
+
self._session: Optional['ClientSession'] = None
|
|
79
|
+
self._exit_stack = AsyncExitStack()
|
|
80
|
+
self._is_connected = False
|
|
81
|
+
|
|
82
|
+
async def connect(self):
|
|
83
|
+
r"""Explicitly connect to the MCP server.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
_MCPServer: The connected server instance
|
|
87
|
+
"""
|
|
88
|
+
from mcp.client.session import ClientSession
|
|
89
|
+
from mcp.client.sse import sse_client
|
|
90
|
+
from mcp.client.stdio import StdioServerParameters, stdio_client
|
|
91
|
+
|
|
92
|
+
if self._is_connected:
|
|
93
|
+
logger.warning("Server is already connected")
|
|
94
|
+
return self
|
|
95
|
+
|
|
96
|
+
try:
|
|
97
|
+
if urlparse(self.command_or_url).scheme in ("http", "https"):
|
|
98
|
+
(
|
|
99
|
+
read_stream,
|
|
100
|
+
write_stream,
|
|
101
|
+
) = await self._exit_stack.enter_async_context(
|
|
102
|
+
sse_client(self.command_or_url)
|
|
103
|
+
)
|
|
104
|
+
else:
|
|
105
|
+
server_parameters = StdioServerParameters(
|
|
106
|
+
command=self.command_or_url, args=self.args, env=self.env
|
|
107
|
+
)
|
|
108
|
+
(
|
|
109
|
+
read_stream,
|
|
110
|
+
write_stream,
|
|
111
|
+
) = await self._exit_stack.enter_async_context(
|
|
112
|
+
stdio_client(server_parameters)
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
self._session = await self._exit_stack.enter_async_context(
|
|
116
|
+
ClientSession(read_stream, write_stream)
|
|
117
|
+
)
|
|
118
|
+
await self._session.initialize()
|
|
119
|
+
list_tools_result = await self.list_mcp_tools()
|
|
120
|
+
self._mcp_tools = list_tools_result.tools
|
|
121
|
+
self._is_connected = True
|
|
122
|
+
return self
|
|
123
|
+
except Exception as e:
|
|
124
|
+
# Ensure resources are cleaned up on connection failure
|
|
125
|
+
await self.disconnect()
|
|
126
|
+
logger.error(f"Failed to connect to MCP server: {e}")
|
|
127
|
+
|
|
128
|
+
async def disconnect(self):
|
|
129
|
+
r"""Explicitly disconnect from the MCP server."""
|
|
130
|
+
self._is_connected = False
|
|
131
|
+
await self._exit_stack.aclose()
|
|
132
|
+
self._session = None
|
|
133
|
+
|
|
134
|
+
@asynccontextmanager
|
|
135
|
+
async def connection(self):
|
|
136
|
+
r"""Async context manager for establishing and managing the connection
|
|
137
|
+
with the MCP server. Automatically selects SSE or stdio mode based
|
|
138
|
+
on the provided `command_or_url`.
|
|
139
|
+
|
|
140
|
+
Yields:
|
|
141
|
+
_MCPServer: Instance with active connection ready for tool
|
|
142
|
+
interaction.
|
|
143
|
+
"""
|
|
144
|
+
try:
|
|
145
|
+
await self.connect()
|
|
146
|
+
yield self
|
|
147
|
+
finally:
|
|
148
|
+
await self.disconnect()
|
|
149
|
+
|
|
150
|
+
async def list_mcp_tools(self) -> Union[str, "ListToolsResult"]:
|
|
151
|
+
r"""Retrieves the list of available tools from the connected MCP
|
|
152
|
+
server.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
ListToolsResult: Result containing available MCP tools.
|
|
156
|
+
"""
|
|
157
|
+
if not self._session:
|
|
158
|
+
return "MCP Client is not connected. Call `connection()` first."
|
|
159
|
+
try:
|
|
160
|
+
return await self._session.list_tools()
|
|
161
|
+
except Exception as e:
|
|
162
|
+
return f"Failed to list MCP tools: {e!s}"
|
|
163
|
+
|
|
164
|
+
def generate_function_from_mcp_tool(self, mcp_tool: "Tool") -> Callable:
|
|
165
|
+
r"""Dynamically generates a Python callable function corresponding to
|
|
166
|
+
a given MCP tool.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
mcp_tool (Tool): The MCP tool definition received from the MCP
|
|
170
|
+
server.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
Callable: A dynamically created async Python function that wraps
|
|
174
|
+
the MCP tool.
|
|
175
|
+
"""
|
|
176
|
+
func_name = mcp_tool.name
|
|
177
|
+
func_desc = mcp_tool.description or "No description provided."
|
|
178
|
+
parameters_schema = mcp_tool.inputSchema.get("properties", {})
|
|
179
|
+
required_params = mcp_tool.inputSchema.get("required", [])
|
|
180
|
+
|
|
181
|
+
type_map = {
|
|
182
|
+
"string": str,
|
|
183
|
+
"integer": int,
|
|
184
|
+
"number": float,
|
|
185
|
+
"boolean": bool,
|
|
186
|
+
"array": list,
|
|
187
|
+
"object": dict,
|
|
188
|
+
}
|
|
189
|
+
annotations = {} # used to type hints
|
|
190
|
+
defaults: Dict[str, Any] = {} # store default values
|
|
191
|
+
|
|
192
|
+
func_params = []
|
|
193
|
+
for param_name, param_schema in parameters_schema.items():
|
|
194
|
+
param_type = param_schema.get("type", "Any")
|
|
195
|
+
param_type = type_map.get(param_type, Any)
|
|
196
|
+
|
|
197
|
+
annotations[param_name] = param_type
|
|
198
|
+
if param_name not in required_params:
|
|
199
|
+
defaults[param_name] = None
|
|
200
|
+
|
|
201
|
+
func_params.append(param_name)
|
|
202
|
+
|
|
203
|
+
async def dynamic_function(**kwargs):
|
|
204
|
+
r"""Auto-generated function for MCP Tool interaction.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
kwargs: Keyword arguments corresponding to MCP tool parameters.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
str: The textual result returned by the MCP tool.
|
|
211
|
+
"""
|
|
212
|
+
from mcp.types import CallToolResult
|
|
213
|
+
|
|
214
|
+
missing_params: Set[str] = set(required_params) - set(
|
|
215
|
+
kwargs.keys()
|
|
216
|
+
)
|
|
217
|
+
if missing_params:
|
|
218
|
+
logger.warning(
|
|
219
|
+
f"Missing required parameters: {missing_params}"
|
|
220
|
+
)
|
|
221
|
+
return "Missing required parameters."
|
|
222
|
+
|
|
223
|
+
if not self._session:
|
|
224
|
+
logger.error(
|
|
225
|
+
"MCP Client is not connected. Call `connection()` first."
|
|
226
|
+
)
|
|
227
|
+
return (
|
|
228
|
+
"MCP Client is not connected. Call `connection()` first."
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
try:
|
|
232
|
+
result: CallToolResult = await self._session.call_tool(
|
|
233
|
+
func_name, kwargs
|
|
234
|
+
)
|
|
235
|
+
except Exception as e:
|
|
236
|
+
logger.error(f"Failed to call MCP tool '{func_name}': {e!s}")
|
|
237
|
+
return f"Failed to call MCP tool '{func_name}': {e!s}"
|
|
238
|
+
|
|
239
|
+
if not result.content or len(result.content) == 0:
|
|
240
|
+
return "No data available for this request."
|
|
241
|
+
|
|
242
|
+
# Handle different content types
|
|
243
|
+
try:
|
|
244
|
+
content = result.content[0]
|
|
245
|
+
if content.type == "text":
|
|
246
|
+
return content.text
|
|
247
|
+
elif content.type == "image":
|
|
248
|
+
# Return image URL or data URI if available
|
|
249
|
+
if hasattr(content, "url") and content.url:
|
|
250
|
+
return f"Image available at: {content.url}"
|
|
251
|
+
return "Image content received (data URI not shown)"
|
|
252
|
+
elif content.type == "embedded_resource":
|
|
253
|
+
# Return resource information if available
|
|
254
|
+
if hasattr(content, "name") and content.name:
|
|
255
|
+
return f"Embedded resource: {content.name}"
|
|
256
|
+
return "Embedded resource received"
|
|
257
|
+
else:
|
|
258
|
+
msg = f"Received content of type '{content.type}'"
|
|
259
|
+
return f"{msg} which is not fully supported yet."
|
|
260
|
+
except (IndexError, AttributeError) as e:
|
|
261
|
+
logger.error(
|
|
262
|
+
f"Error processing content from MCP tool response: {e!s}"
|
|
263
|
+
)
|
|
264
|
+
return "Error processing content from MCP tool response"
|
|
265
|
+
|
|
266
|
+
dynamic_function.__name__ = func_name
|
|
267
|
+
dynamic_function.__doc__ = func_desc
|
|
268
|
+
dynamic_function.__annotations__ = annotations
|
|
269
|
+
|
|
270
|
+
sig = inspect.Signature(
|
|
271
|
+
parameters=[
|
|
272
|
+
inspect.Parameter(
|
|
273
|
+
name=param,
|
|
274
|
+
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
275
|
+
default=defaults.get(param, inspect.Parameter.empty),
|
|
276
|
+
annotation=annotations[param],
|
|
277
|
+
)
|
|
278
|
+
for param in func_params
|
|
279
|
+
]
|
|
280
|
+
)
|
|
281
|
+
dynamic_function.__signature__ = sig # type: ignore[attr-defined]
|
|
282
|
+
|
|
283
|
+
return dynamic_function
|
|
284
|
+
|
|
285
|
+
def _build_tool_schema(self, mcp_tool: "Tool") -> Dict[str, Any]:
|
|
286
|
+
input_schema = mcp_tool.inputSchema
|
|
287
|
+
properties = input_schema.get("properties", {})
|
|
288
|
+
required = input_schema.get("required", [])
|
|
289
|
+
|
|
290
|
+
parameters = {
|
|
291
|
+
"type": "object",
|
|
292
|
+
"properties": properties,
|
|
293
|
+
"required": required,
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
"type": "function",
|
|
298
|
+
"function": {
|
|
299
|
+
"name": mcp_tool.name,
|
|
300
|
+
"description": mcp_tool.description
|
|
301
|
+
or "No description provided.",
|
|
302
|
+
"parameters": parameters,
|
|
303
|
+
},
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
def get_tools(self) -> List[FunctionTool]:
|
|
307
|
+
r"""Returns a list of FunctionTool objects representing the
|
|
308
|
+
functions in the toolkit. Each function is dynamically generated
|
|
309
|
+
based on the MCP tool definitions received from the server.
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
List[FunctionTool]: A list of FunctionTool objects
|
|
313
|
+
representing the functions in the toolkit.
|
|
314
|
+
"""
|
|
315
|
+
return [
|
|
316
|
+
FunctionTool(
|
|
317
|
+
self.generate_function_from_mcp_tool(mcp_tool),
|
|
318
|
+
openai_tool_schema=self._build_tool_schema(mcp_tool),
|
|
319
|
+
)
|
|
320
|
+
for mcp_tool in self._mcp_tools
|
|
321
|
+
]
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class MCPToolkit(BaseToolkit):
|
|
325
|
+
r"""MCPToolkit provides a unified interface for managing multiple
|
|
326
|
+
MCP server connections and their tools.
|
|
327
|
+
|
|
328
|
+
This class handles the lifecycle of multiple MCP server connections and
|
|
329
|
+
offers a centralized configuration mechanism for both local and remote
|
|
330
|
+
MCP services.
|
|
331
|
+
|
|
332
|
+
Args:
|
|
333
|
+
servers (Optional[List[_MCPServer]]): List of _MCPServer
|
|
334
|
+
instances to manage.
|
|
335
|
+
config_path (Optional[str]): Path to a JSON configuration file
|
|
336
|
+
defining MCP servers.
|
|
337
|
+
|
|
338
|
+
Note:
|
|
339
|
+
Either `servers` or `config_path` must be provided. If both are
|
|
340
|
+
provided, servers from both sources will be combined.
|
|
341
|
+
|
|
342
|
+
Attributes:
|
|
343
|
+
servers (List[_MCPServer]): List of _MCPServer instances being managed.
|
|
344
|
+
"""
|
|
345
|
+
|
|
346
|
+
def __init__(
|
|
347
|
+
self,
|
|
348
|
+
servers: Optional[List[_MCPServer]] = None,
|
|
349
|
+
config_path: Optional[str] = None,
|
|
350
|
+
):
|
|
351
|
+
super().__init__()
|
|
352
|
+
|
|
353
|
+
if servers and config_path:
|
|
354
|
+
logger.warning(
|
|
355
|
+
"Both servers and config_path are provided. "
|
|
356
|
+
"Servers from both sources will be combined."
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
self.servers = servers or []
|
|
360
|
+
|
|
361
|
+
if config_path:
|
|
362
|
+
self.servers.extend(self._load_servers_from_config(config_path))
|
|
363
|
+
|
|
364
|
+
self._exit_stack = AsyncExitStack()
|
|
365
|
+
self._connected = False
|
|
366
|
+
|
|
367
|
+
def _load_servers_from_config(self, config_path: str) -> List[_MCPServer]:
|
|
368
|
+
r"""Loads MCP server configurations from a JSON file.
|
|
369
|
+
|
|
370
|
+
Args:
|
|
371
|
+
config_path (str): Path to the JSON configuration file.
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
List[_MCPServer]: List of configured _MCPServer instances.
|
|
375
|
+
"""
|
|
376
|
+
try:
|
|
377
|
+
with open(config_path, "r", encoding="utf-8") as f:
|
|
378
|
+
try:
|
|
379
|
+
data = json.load(f)
|
|
380
|
+
except json.JSONDecodeError as e:
|
|
381
|
+
logger.warning(
|
|
382
|
+
f"Invalid JSON in config file '{config_path}': {e!s}"
|
|
383
|
+
)
|
|
384
|
+
return []
|
|
385
|
+
except FileNotFoundError:
|
|
386
|
+
logger.warning(f"Config file not found: '{config_path}'")
|
|
387
|
+
return []
|
|
388
|
+
|
|
389
|
+
all_servers = []
|
|
390
|
+
|
|
391
|
+
# Process local MCP servers
|
|
392
|
+
mcp_servers = data.get("mcpServers", {})
|
|
393
|
+
if not isinstance(mcp_servers, dict):
|
|
394
|
+
logger.warning("'mcpServers' is not a dictionary, skipping...")
|
|
395
|
+
mcp_servers = {}
|
|
396
|
+
|
|
397
|
+
for name, cfg in mcp_servers.items():
|
|
398
|
+
if not isinstance(cfg, dict):
|
|
399
|
+
logger.warning(
|
|
400
|
+
f"Configuration for server '{name}' must be a dictionary"
|
|
401
|
+
)
|
|
402
|
+
continue
|
|
403
|
+
|
|
404
|
+
if "command" not in cfg:
|
|
405
|
+
logger.warning(
|
|
406
|
+
f"Missing required 'command' field for server '{name}'"
|
|
407
|
+
)
|
|
408
|
+
continue
|
|
409
|
+
|
|
410
|
+
server = _MCPServer(
|
|
411
|
+
command_or_url=cfg["command"],
|
|
412
|
+
args=cfg.get("args", []),
|
|
413
|
+
env={**os.environ, **cfg.get("env", {})},
|
|
414
|
+
timeout=cfg.get("timeout", None),
|
|
415
|
+
)
|
|
416
|
+
all_servers.append(server)
|
|
417
|
+
|
|
418
|
+
# Process remote MCP web servers
|
|
419
|
+
mcp_web_servers = data.get("mcpWebServers", {})
|
|
420
|
+
if not isinstance(mcp_web_servers, dict):
|
|
421
|
+
logger.warning("'mcpWebServers' is not a dictionary, skipping...")
|
|
422
|
+
mcp_web_servers = {}
|
|
423
|
+
|
|
424
|
+
for name, cfg in mcp_web_servers.items():
|
|
425
|
+
if not isinstance(cfg, dict):
|
|
426
|
+
logger.warning(
|
|
427
|
+
f"Configuration for web server '{name}' must"
|
|
428
|
+
"be a dictionary"
|
|
429
|
+
)
|
|
430
|
+
continue
|
|
431
|
+
|
|
432
|
+
if "url" not in cfg:
|
|
433
|
+
logger.warning(
|
|
434
|
+
f"Missing required 'url' field for web server '{name}'"
|
|
435
|
+
)
|
|
436
|
+
continue
|
|
437
|
+
|
|
438
|
+
server = _MCPServer(
|
|
439
|
+
command_or_url=cfg["url"],
|
|
440
|
+
timeout=cfg.get("timeout", None),
|
|
441
|
+
)
|
|
442
|
+
all_servers.append(server)
|
|
443
|
+
|
|
444
|
+
return all_servers
|
|
445
|
+
|
|
446
|
+
async def connect(self):
|
|
447
|
+
r"""Explicitly connect to all MCP servers.
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
MCPToolkit: The connected toolkit instance
|
|
451
|
+
"""
|
|
452
|
+
if self._connected:
|
|
453
|
+
logger.warning("MCPToolkit is already connected")
|
|
454
|
+
return self
|
|
455
|
+
|
|
456
|
+
self._exit_stack = AsyncExitStack()
|
|
457
|
+
try:
|
|
458
|
+
# Sequentially connect to each server
|
|
459
|
+
for server in self.servers:
|
|
460
|
+
await server.connect()
|
|
461
|
+
self._connected = True
|
|
462
|
+
return self
|
|
463
|
+
except Exception as e:
|
|
464
|
+
# Ensure resources are cleaned up on connection failure
|
|
465
|
+
await self.disconnect()
|
|
466
|
+
logger.error(f"Failed to connect to one or more MCP servers: {e}")
|
|
467
|
+
|
|
468
|
+
async def disconnect(self):
|
|
469
|
+
r"""Explicitly disconnect from all MCP servers."""
|
|
470
|
+
if not self._connected:
|
|
471
|
+
return
|
|
472
|
+
|
|
473
|
+
for server in self.servers:
|
|
474
|
+
await server.disconnect()
|
|
475
|
+
self._connected = False
|
|
476
|
+
await self._exit_stack.aclose()
|
|
477
|
+
|
|
478
|
+
@asynccontextmanager
|
|
479
|
+
async def connection(self) -> AsyncGenerator["MCPToolkit", None]:
|
|
480
|
+
r"""Async context manager that simultaneously establishes connections
|
|
481
|
+
to all managed MCP server instances.
|
|
482
|
+
|
|
483
|
+
Yields:
|
|
484
|
+
MCPToolkit: Self with all servers connected.
|
|
485
|
+
"""
|
|
486
|
+
try:
|
|
487
|
+
await self.connect()
|
|
488
|
+
yield self
|
|
489
|
+
finally:
|
|
490
|
+
await self.disconnect()
|
|
491
|
+
|
|
492
|
+
def is_connected(self) -> bool:
|
|
493
|
+
r"""Checks if all the managed servers are connected.
|
|
494
|
+
|
|
495
|
+
Returns:
|
|
496
|
+
bool: True if connected, False otherwise.
|
|
497
|
+
"""
|
|
498
|
+
return self._connected
|
|
499
|
+
|
|
500
|
+
def get_tools(self) -> List[FunctionTool]:
|
|
501
|
+
r"""Aggregates all tools from the managed MCP server instances.
|
|
502
|
+
|
|
503
|
+
Returns:
|
|
504
|
+
List[FunctionTool]: Combined list of all available function tools.
|
|
505
|
+
"""
|
|
506
|
+
all_tools = []
|
|
507
|
+
for server in self.servers:
|
|
508
|
+
all_tools.extend(server.get_tools())
|
|
509
|
+
return all_tools
|