camel-ai 0.2.65__py3-none-any.whl → 0.2.82__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 +4835 -947
- 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 +23 -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/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 +31 -239
- 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 +16 -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 +212 -89
- camel/models/base_audio_model.py +5 -3
- camel/models/base_model.py +195 -26
- camel/models/cerebras_model.py +83 -0
- camel/models/cohere_model.py +16 -21
- camel/models/cometapi_model.py +83 -0
- camel/models/crynux_model.py +11 -18
- camel/models/deepseek_model.py +18 -58
- camel/models/fish_audio_model.py +8 -2
- camel/models/gemini_model.py +389 -26
- camel/models/groq_model.py +11 -19
- camel/models/internlm_model.py +11 -18
- camel/models/litellm_model.py +56 -34
- camel/models/lmstudio_model.py +17 -20
- camel/models/minimax_model.py +83 -0
- camel/models/mistral_model.py +18 -19
- camel/models/model_factory.py +37 -3
- camel/models/model_manager.py +26 -8
- camel/models/modelscope_model.py +13 -193
- camel/models/moonshot_model.py +195 -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 +188 -45
- camel/models/openai_model.py +216 -71
- 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 +21 -21
- 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 +48 -47
- camel/models/sglang_model.py +88 -40
- 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 +16 -20
- camel/models/watsonx_model.py +7 -19
- 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 +143 -0
- camel/societies/workforce/prompts.py +258 -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 +5276 -355
- 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 +54 -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 +65 -7
- 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 +126 -18
- 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 +1973 -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 +1929 -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 +319 -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 +724 -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 +539 -146
- 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 +1070 -0
- camel/toolkits/terminal_toolkit/utils.py +532 -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 +378 -39
- camel/types/mcp_registries.py +2 -2
- camel/types/openai_types.py +4 -4
- camel/types/unified_model_type.py +38 -6
- camel/utils/__init__.py +2 -2
- 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 +2 -2
- 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.82.dist-info}/METADATA +327 -94
- camel_ai-0.2.82.dist-info/RECORD +507 -0
- {camel_ai-0.2.65.dist-info → camel_ai-0.2.82.dist-info}/WHEEL +1 -1
- {camel_ai-0.2.65.dist-info → camel_ai-0.2.82.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
|
@@ -0,0 +1,731 @@
|
|
|
1
|
+
# ========= Copyright 2023-2025 @ 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-2025 @ CAMEL-AI.org. All Rights Reserved. =========
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Literal, Optional
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from chromadb.api import ClientAPI
|
|
19
|
+
from chromadb.api.models.Collection import Collection
|
|
20
|
+
from chromadb.api.types import (
|
|
21
|
+
QueryResult,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from camel.logger import get_logger
|
|
25
|
+
from camel.storages.vectordb_storages import (
|
|
26
|
+
BaseVectorStorage,
|
|
27
|
+
VectorDBQuery,
|
|
28
|
+
VectorDBQueryResult,
|
|
29
|
+
VectorDBStatus,
|
|
30
|
+
VectorRecord,
|
|
31
|
+
)
|
|
32
|
+
from camel.types import VectorDistance
|
|
33
|
+
from camel.utils import dependencies_required
|
|
34
|
+
|
|
35
|
+
logger = get_logger(__name__)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ChromaStorage(BaseVectorStorage):
|
|
39
|
+
r"""An implementation of the `BaseVectorStorage` for interacting with
|
|
40
|
+
ChromaDB, a vector database for embeddings.
|
|
41
|
+
ChromaDB is an open-source AI-native vector database focused on developer
|
|
42
|
+
productivity and happiness. The detailed information about ChromaDB is
|
|
43
|
+
available at: `ChromaDB <https://docs.trychroma.com/>`_
|
|
44
|
+
|
|
45
|
+
This class provides multiple ways to connect to ChromaDB instances:
|
|
46
|
+
- Ephemeral (in-memory for testing/prototyping)
|
|
47
|
+
- Persistent (local file storage)
|
|
48
|
+
- HTTP (remote ChromaDB server)
|
|
49
|
+
- Cloud (ChromaDB Cloud - future support)
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
vector_dim (int): The dimension of storing vectors.
|
|
53
|
+
collection_name (Optional[str], optional): Name for the collection in
|
|
54
|
+
ChromaDB. If not provided, auto-generated with timestamp.
|
|
55
|
+
(default: :obj:`None`)
|
|
56
|
+
client_type (Literal["ephemeral", "persistent", "http", "cloud"]):
|
|
57
|
+
Type of ChromaDB client to use. Supported types: 'ephemeral',
|
|
58
|
+
'persistent', 'http', 'cloud'. (default: :obj:`"ephemeral"`)
|
|
59
|
+
|
|
60
|
+
# Persistent client parameters
|
|
61
|
+
path (Optional[str], optional): Path to directory for persistent
|
|
62
|
+
storage. Only used when client_type='persistent'.
|
|
63
|
+
(default: :obj:`"./chroma"`)
|
|
64
|
+
|
|
65
|
+
# HTTP client parameters
|
|
66
|
+
host (str, optional): Host for remote ChromaDB server.
|
|
67
|
+
(default: :obj:`"localhost"`)
|
|
68
|
+
port (int, optional): Port for remote ChromaDB server.
|
|
69
|
+
(default: :obj:`8000`)
|
|
70
|
+
ssl (bool, optional): Whether to use SSL for HTTP connections.
|
|
71
|
+
(default: :obj:`False`)
|
|
72
|
+
headers (Optional[Dict[str, str]], optional): Additional headers for
|
|
73
|
+
HTTP client requests. (default: :obj:`None`)
|
|
74
|
+
|
|
75
|
+
# Cloud client parameters
|
|
76
|
+
api_key (Optional[str], optional): API key for ChromaDB Cloud.
|
|
77
|
+
(default: :obj:`None`)
|
|
78
|
+
cloud_host (str, optional): ChromaDB Cloud host.
|
|
79
|
+
(default: :obj:`"api.trychroma.com"`)
|
|
80
|
+
cloud_port (int, optional): ChromaDB Cloud port.
|
|
81
|
+
(default: :obj:`8000`)
|
|
82
|
+
enable_ssl (bool, optional): Whether to enable SSL for
|
|
83
|
+
cloud connection.(default: :obj:`True`)
|
|
84
|
+
|
|
85
|
+
# Common parameters for all client types
|
|
86
|
+
settings (Optional[Any], optional): ChromaDB settings object for
|
|
87
|
+
advanced configuration. (default: :obj:`None`)
|
|
88
|
+
tenant (Optional[str], optional): Tenant name for multi-tenancy
|
|
89
|
+
support. (default: :obj:`None`)
|
|
90
|
+
database (Optional[str], optional): Database name for multi-database
|
|
91
|
+
support. (default: :obj:`None`)
|
|
92
|
+
distance (VectorDistance, optional): The distance metric for vector
|
|
93
|
+
comparison. (default: :obj:`VectorDistance.COSINE`)
|
|
94
|
+
|
|
95
|
+
delete_collection_on_del (bool, optional): Flag to determine if the
|
|
96
|
+
collection should be deleted upon object destruction.
|
|
97
|
+
(default: :obj:`False`)
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
ImportError: If `chromadb` package is not installed.
|
|
101
|
+
ValueError: If invalid client configuration is provided.
|
|
102
|
+
RuntimeError: If there's an error setting up the collection.
|
|
103
|
+
|
|
104
|
+
Examples:
|
|
105
|
+
>>> # In-memory storage (ephemeral)
|
|
106
|
+
>>> storage = ChromaStorage(
|
|
107
|
+
... vector_dim=384,
|
|
108
|
+
... client_type="ephemeral"
|
|
109
|
+
... )
|
|
110
|
+
|
|
111
|
+
>>> # Persistent storage (custom path)
|
|
112
|
+
>>> storage = ChromaStorage(
|
|
113
|
+
... vector_dim=384,
|
|
114
|
+
... client_type="persistent",
|
|
115
|
+
... path="/path/to/chroma/data"
|
|
116
|
+
... )
|
|
117
|
+
|
|
118
|
+
>>> # Remote HTTP connection (custom host/port)
|
|
119
|
+
>>> storage = ChromaStorage(
|
|
120
|
+
... vector_dim=384,
|
|
121
|
+
... client_type="http",
|
|
122
|
+
... host="remote-server.com",
|
|
123
|
+
... port=9000,
|
|
124
|
+
... ssl=True
|
|
125
|
+
... )
|
|
126
|
+
|
|
127
|
+
>>> # ChromaDB Cloud (using defaults)
|
|
128
|
+
>>> storage = ChromaStorage(
|
|
129
|
+
... vector_dim=384,
|
|
130
|
+
... client_type="cloud",
|
|
131
|
+
... tenant="my-tenant",
|
|
132
|
+
... database="my-database",
|
|
133
|
+
... api_key="your-api-key" # optional
|
|
134
|
+
... )
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
@dependencies_required('chromadb')
|
|
138
|
+
def __init__(
|
|
139
|
+
self,
|
|
140
|
+
vector_dim: int,
|
|
141
|
+
collection_name: Optional[str] = None,
|
|
142
|
+
client_type: Literal[
|
|
143
|
+
"ephemeral", "persistent", "http", "cloud"
|
|
144
|
+
] = "ephemeral",
|
|
145
|
+
# Persistent client parameters
|
|
146
|
+
path: Optional[str] = "./chroma",
|
|
147
|
+
# HTTP client parameters
|
|
148
|
+
host: str = "localhost",
|
|
149
|
+
port: int = 8000,
|
|
150
|
+
ssl: bool = False,
|
|
151
|
+
headers: Optional[Dict[str, str]] = None,
|
|
152
|
+
# Cloud client parameters
|
|
153
|
+
api_key: Optional[str] = None,
|
|
154
|
+
cloud_host: str = "api.trychroma.com",
|
|
155
|
+
cloud_port: int = 8000,
|
|
156
|
+
enable_ssl: bool = True,
|
|
157
|
+
# Common parameters for all client types
|
|
158
|
+
settings: Optional[Any] = None,
|
|
159
|
+
tenant: Optional[str] = None,
|
|
160
|
+
database: Optional[str] = None,
|
|
161
|
+
distance: VectorDistance = VectorDistance.COSINE,
|
|
162
|
+
delete_collection_on_del: bool = False,
|
|
163
|
+
**kwargs: Any,
|
|
164
|
+
) -> None:
|
|
165
|
+
self.vector_dim = vector_dim
|
|
166
|
+
self.distance = distance
|
|
167
|
+
self.collection_name = (
|
|
168
|
+
collection_name or self._generate_collection_name()
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
self.delete_collection_on_del = delete_collection_on_del
|
|
172
|
+
|
|
173
|
+
# Validate client type
|
|
174
|
+
self._validate_client_type(client_type)
|
|
175
|
+
self.client_type: Literal[
|
|
176
|
+
"ephemeral", "persistent", "http", "cloud"
|
|
177
|
+
] = client_type
|
|
178
|
+
|
|
179
|
+
# Store connection parameters for later use
|
|
180
|
+
self._connection_params = {
|
|
181
|
+
'path': path,
|
|
182
|
+
'host': host,
|
|
183
|
+
'port': port,
|
|
184
|
+
'ssl': ssl,
|
|
185
|
+
'headers': headers,
|
|
186
|
+
'api_key': api_key,
|
|
187
|
+
'cloud_host': cloud_host,
|
|
188
|
+
'cloud_port': cloud_port,
|
|
189
|
+
'enable_ssl': enable_ssl,
|
|
190
|
+
'settings': settings,
|
|
191
|
+
'tenant': tenant,
|
|
192
|
+
'database': database,
|
|
193
|
+
**kwargs,
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
# Validate client configuration
|
|
197
|
+
self._validate_client_config()
|
|
198
|
+
|
|
199
|
+
# Create client using the unified approach
|
|
200
|
+
self._client: "ClientAPI" = self._get_connection_client()
|
|
201
|
+
logger.info(f"Created ChromaDB client with type: {self.client_type}")
|
|
202
|
+
|
|
203
|
+
# Create or get the collection
|
|
204
|
+
self._collection: "Collection" = self._get_or_create_collection()
|
|
205
|
+
|
|
206
|
+
logger.info(
|
|
207
|
+
f"Successfully initialized ChromaDB storage "
|
|
208
|
+
f"({self.client_type}) with collection: {self.collection_name}"
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
def __del__(self) -> None:
|
|
212
|
+
r"""Deletes the collection if :obj:`delete_collection_on_del` is set to
|
|
213
|
+
:obj:`True`.
|
|
214
|
+
"""
|
|
215
|
+
if (
|
|
216
|
+
hasattr(self, "delete_collection_on_del")
|
|
217
|
+
and self.delete_collection_on_del
|
|
218
|
+
):
|
|
219
|
+
try:
|
|
220
|
+
self.delete_collection()
|
|
221
|
+
except Exception as e:
|
|
222
|
+
logger.error(
|
|
223
|
+
f"Failed to delete collection "
|
|
224
|
+
f"'{self.collection_name}': {e}"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
def _validate_client_type(
|
|
228
|
+
self, client_type: Literal["ephemeral", "persistent", "http", "cloud"]
|
|
229
|
+
) -> None:
|
|
230
|
+
r"""Validates client type parameter.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
client_type (Literal["ephemeral", "persistent", "http", "cloud"]):
|
|
234
|
+
The client type to validate.
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
ValueError: If client type is invalid.
|
|
238
|
+
"""
|
|
239
|
+
valid_types = ["ephemeral", "persistent", "http", "cloud"]
|
|
240
|
+
if client_type not in valid_types:
|
|
241
|
+
raise ValueError(
|
|
242
|
+
f"Invalid client_type '{client_type}'. "
|
|
243
|
+
f"Must be one of: {valid_types}"
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
def _validate_client_config(self) -> None:
|
|
247
|
+
r"""Validates client configuration parameters.
|
|
248
|
+
|
|
249
|
+
Raises:
|
|
250
|
+
ValueError: If configuration is invalid.
|
|
251
|
+
"""
|
|
252
|
+
if self.client_type == "persistent":
|
|
253
|
+
# path has a default value, but ensure it's not None
|
|
254
|
+
if self._connection_params.get('path') is None:
|
|
255
|
+
raise ValueError(
|
|
256
|
+
"path parameter cannot be None "
|
|
257
|
+
"for 'persistent' client type"
|
|
258
|
+
)
|
|
259
|
+
elif self.client_type == "cloud":
|
|
260
|
+
# For cloud client, tenant and database are required
|
|
261
|
+
if self._connection_params.get('tenant') is None:
|
|
262
|
+
raise ValueError(
|
|
263
|
+
"tenant parameter is required for 'cloud' client type"
|
|
264
|
+
)
|
|
265
|
+
if self._connection_params.get('database') is None:
|
|
266
|
+
raise ValueError(
|
|
267
|
+
"database parameter is required for 'cloud' client type"
|
|
268
|
+
)
|
|
269
|
+
# 'ephemeral' and 'http' clients have sensible defaults
|
|
270
|
+
# and don't require validation
|
|
271
|
+
|
|
272
|
+
def _get_connection_client(self) -> "ClientAPI":
|
|
273
|
+
r"""Get ChromaDB client based on client type and user settings."""
|
|
274
|
+
import chromadb
|
|
275
|
+
|
|
276
|
+
# Map client types to handler methods
|
|
277
|
+
client_handlers: Dict[
|
|
278
|
+
Literal["ephemeral", "persistent", "http", "cloud"], Any
|
|
279
|
+
] = {
|
|
280
|
+
'ephemeral': self._create_ephemeral_client,
|
|
281
|
+
'persistent': self._create_persistent_client,
|
|
282
|
+
'http': self._create_http_client,
|
|
283
|
+
'cloud': self._create_cloud_client,
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
# Get client handler
|
|
287
|
+
handler = client_handlers[self.client_type]
|
|
288
|
+
|
|
289
|
+
try:
|
|
290
|
+
return handler(chromadb)
|
|
291
|
+
except Exception as e:
|
|
292
|
+
logger.error(f"Failed to create {self.client_type} client: {e}")
|
|
293
|
+
raise
|
|
294
|
+
|
|
295
|
+
def _create_ephemeral_client(self, chromadb_module: Any) -> "ClientAPI":
|
|
296
|
+
r"""Create an ephemeral ChromaDB client (in-memory)."""
|
|
297
|
+
client_kwargs = self._get_common_client_kwargs()
|
|
298
|
+
client = chromadb_module.EphemeralClient(**client_kwargs)
|
|
299
|
+
logger.info("Created ChromaDB EphemeralClient (in-memory)")
|
|
300
|
+
return client
|
|
301
|
+
|
|
302
|
+
def _create_persistent_client(self, chromadb_module: Any) -> "ClientAPI":
|
|
303
|
+
r"""Create a persistent ChromaDB client (local file storage)."""
|
|
304
|
+
client_kwargs = {'path': self._connection_params['path']}
|
|
305
|
+
client_kwargs.update(self._get_common_client_kwargs())
|
|
306
|
+
client = chromadb_module.PersistentClient(**client_kwargs)
|
|
307
|
+
logger.info(
|
|
308
|
+
f"Created ChromaDB PersistentClient: "
|
|
309
|
+
f"{self._connection_params['path']}"
|
|
310
|
+
)
|
|
311
|
+
return client
|
|
312
|
+
|
|
313
|
+
def _create_http_client(self, chromadb_module: Any) -> "ClientAPI":
|
|
314
|
+
r"""Create an HTTP ChromaDB client (remote server)."""
|
|
315
|
+
client_kwargs = {
|
|
316
|
+
'host': self._connection_params['host'],
|
|
317
|
+
'port': self._connection_params['port'],
|
|
318
|
+
'ssl': self._connection_params['ssl'],
|
|
319
|
+
}
|
|
320
|
+
if self._connection_params.get('headers') is not None:
|
|
321
|
+
client_kwargs['headers'] = self._connection_params['headers']
|
|
322
|
+
client_kwargs.update(self._get_common_client_kwargs())
|
|
323
|
+
|
|
324
|
+
client = chromadb_module.HttpClient(**client_kwargs)
|
|
325
|
+
logger.info(
|
|
326
|
+
f"Created ChromaDB HttpClient: {self._connection_params['host']}:"
|
|
327
|
+
f"{self._connection_params['port']}"
|
|
328
|
+
)
|
|
329
|
+
return client
|
|
330
|
+
|
|
331
|
+
def _create_cloud_client(self, chromadb_module: Any) -> "ClientAPI":
|
|
332
|
+
r"""Create a cloud ChromaDB client."""
|
|
333
|
+
try:
|
|
334
|
+
client_kwargs = {
|
|
335
|
+
'cloud_host': self._connection_params['cloud_host'],
|
|
336
|
+
'cloud_port': self._connection_params['cloud_port'],
|
|
337
|
+
'enable_ssl': self._connection_params['enable_ssl'],
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
# Add optional API key
|
|
341
|
+
if self._connection_params.get('api_key') is not None:
|
|
342
|
+
client_kwargs['api_key'] = self._connection_params['api_key']
|
|
343
|
+
|
|
344
|
+
# Add common parameters (settings, tenant, database)
|
|
345
|
+
client_kwargs.update(self._get_common_client_kwargs())
|
|
346
|
+
|
|
347
|
+
client = chromadb_module.CloudClient(**client_kwargs)
|
|
348
|
+
logger.info(
|
|
349
|
+
f"Created ChromaDB CloudClient: "
|
|
350
|
+
f"{self._connection_params['cloud_host']}:"
|
|
351
|
+
f"{self._connection_params['cloud_port']}"
|
|
352
|
+
)
|
|
353
|
+
return client
|
|
354
|
+
except AttributeError:
|
|
355
|
+
raise RuntimeError(
|
|
356
|
+
"CloudClient is not yet available in this version of "
|
|
357
|
+
"ChromaDB. Please use a different client type or "
|
|
358
|
+
"upgrade ChromaDB when CloudClient is released."
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
def _get_common_client_kwargs(self) -> Dict[str, Any]:
|
|
362
|
+
r"""Get common kwargs for all ChromaDB clients."""
|
|
363
|
+
common_kwargs: Dict[str, Any] = {}
|
|
364
|
+
|
|
365
|
+
# Add truly common parameters that all ChromaDB clients support
|
|
366
|
+
if self._connection_params.get('settings') is not None:
|
|
367
|
+
common_kwargs['settings'] = self._connection_params['settings']
|
|
368
|
+
if self._connection_params.get('tenant') is not None:
|
|
369
|
+
common_kwargs['tenant'] = self._connection_params['tenant']
|
|
370
|
+
if self._connection_params.get('database') is not None:
|
|
371
|
+
common_kwargs['database'] = self._connection_params['database']
|
|
372
|
+
|
|
373
|
+
return common_kwargs
|
|
374
|
+
|
|
375
|
+
def _generate_collection_name(self) -> str:
|
|
376
|
+
r"""Generates a collection name if user doesn't provide one.
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
str: Generated collection name based on current timestamp.
|
|
380
|
+
"""
|
|
381
|
+
timestamp = (
|
|
382
|
+
datetime.now().isoformat().replace(':', '-').replace('.', '-')
|
|
383
|
+
)
|
|
384
|
+
return f"chroma_collection_{timestamp}"
|
|
385
|
+
|
|
386
|
+
def _get_distance_function(self) -> str:
|
|
387
|
+
r"""Maps VectorDistance to ChromaDB distance function.
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
str: ChromaDB distance function name.
|
|
391
|
+
|
|
392
|
+
References:
|
|
393
|
+
https://docs.trychroma.com/docs/collections/configure
|
|
394
|
+
"""
|
|
395
|
+
distance_map: Dict[VectorDistance, str] = {
|
|
396
|
+
VectorDistance.COSINE: "cosine",
|
|
397
|
+
VectorDistance.EUCLIDEAN: "l2",
|
|
398
|
+
VectorDistance.DOT: "ip", # inner product
|
|
399
|
+
}
|
|
400
|
+
return distance_map.get(self.distance, "cosine")
|
|
401
|
+
|
|
402
|
+
def _get_or_create_collection(self) -> "Collection":
|
|
403
|
+
r"""Gets existing collection or creates a new one.
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
ChromaDB collection object.
|
|
407
|
+
|
|
408
|
+
Raises:
|
|
409
|
+
RuntimeError: If collection operations fail.
|
|
410
|
+
"""
|
|
411
|
+
try:
|
|
412
|
+
logger.info(
|
|
413
|
+
"Using fallback collection creation (older ChromaDB API)"
|
|
414
|
+
)
|
|
415
|
+
collection = self._client.get_or_create_collection(
|
|
416
|
+
name=self.collection_name,
|
|
417
|
+
metadata={"hnsw:space": self._get_distance_function()},
|
|
418
|
+
)
|
|
419
|
+
logger.info(f"Got or created collection: {self.collection_name}")
|
|
420
|
+
|
|
421
|
+
return collection
|
|
422
|
+
|
|
423
|
+
except Exception as e:
|
|
424
|
+
raise RuntimeError(f"Failed to get or create collection: {e}")
|
|
425
|
+
|
|
426
|
+
def add(
|
|
427
|
+
self,
|
|
428
|
+
records: List[VectorRecord],
|
|
429
|
+
**kwargs: Any,
|
|
430
|
+
) -> None:
|
|
431
|
+
r"""Adds vector records to ChromaDB collection.
|
|
432
|
+
|
|
433
|
+
Args:
|
|
434
|
+
records (List[VectorRecord]): List of vector records to be saved.
|
|
435
|
+
**kwargs (Any): Additional keyword arguments for ChromaDB add
|
|
436
|
+
operation.
|
|
437
|
+
|
|
438
|
+
Raises:
|
|
439
|
+
RuntimeError: If there is an error during the saving process.
|
|
440
|
+
"""
|
|
441
|
+
if not records:
|
|
442
|
+
return
|
|
443
|
+
|
|
444
|
+
try:
|
|
445
|
+
# Prepare data for ChromaDB
|
|
446
|
+
ids: List[str] = [record.id for record in records]
|
|
447
|
+
embeddings: List[List[float]] = [
|
|
448
|
+
record.vector for record in records
|
|
449
|
+
]
|
|
450
|
+
|
|
451
|
+
# Prepare metadatas - ChromaDB requires a list
|
|
452
|
+
metadatas: List[Dict[str, Any]] = []
|
|
453
|
+
for record in records:
|
|
454
|
+
if record.payload is not None:
|
|
455
|
+
metadatas.append(record.payload)
|
|
456
|
+
else:
|
|
457
|
+
metadatas.append({})
|
|
458
|
+
|
|
459
|
+
# Add to collection using upsert for safety
|
|
460
|
+
add_kwargs: Dict[str, Any] = {
|
|
461
|
+
'ids': ids,
|
|
462
|
+
'embeddings': embeddings,
|
|
463
|
+
'metadatas': metadatas,
|
|
464
|
+
}
|
|
465
|
+
add_kwargs.update(kwargs)
|
|
466
|
+
|
|
467
|
+
self._collection.upsert(**add_kwargs)
|
|
468
|
+
|
|
469
|
+
logger.info(
|
|
470
|
+
f"Successfully added {len(records)} records to "
|
|
471
|
+
f"ChromaDB collection: {self.collection_name}"
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
except Exception as e:
|
|
475
|
+
raise RuntimeError(f"Failed to add records to ChromaDB: {e}")
|
|
476
|
+
|
|
477
|
+
def delete(
|
|
478
|
+
self,
|
|
479
|
+
ids: List[str],
|
|
480
|
+
**kwargs: Any,
|
|
481
|
+
) -> None:
|
|
482
|
+
r"""Deletes vectors by their IDs from ChromaDB collection.
|
|
483
|
+
|
|
484
|
+
Args:
|
|
485
|
+
ids (List[str]): List of unique identifiers for the vectors to be
|
|
486
|
+
deleted.
|
|
487
|
+
**kwargs (Any): Additional keyword arguments for ChromaDB delete
|
|
488
|
+
operation.
|
|
489
|
+
|
|
490
|
+
Raises:
|
|
491
|
+
RuntimeError: If there is an error during the deletion process.
|
|
492
|
+
"""
|
|
493
|
+
if not ids:
|
|
494
|
+
return
|
|
495
|
+
try:
|
|
496
|
+
delete_kwargs: Dict[str, Any] = {'ids': ids}
|
|
497
|
+
delete_kwargs.update(kwargs)
|
|
498
|
+
|
|
499
|
+
self._collection.delete(**delete_kwargs)
|
|
500
|
+
logger.info(
|
|
501
|
+
f"Successfully deleted {len(ids)} records from "
|
|
502
|
+
f"ChromaDB collection: {self.collection_name}"
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
except Exception as e:
|
|
506
|
+
raise RuntimeError(f"Failed to delete records from ChromaDB: {e}")
|
|
507
|
+
|
|
508
|
+
def status(self) -> VectorDBStatus:
|
|
509
|
+
r"""Returns status of the ChromaDB collection.
|
|
510
|
+
|
|
511
|
+
Returns:
|
|
512
|
+
VectorDBStatus: The vector database status containing dimension
|
|
513
|
+
and count information.
|
|
514
|
+
|
|
515
|
+
Raises:
|
|
516
|
+
RuntimeError: If there is an error getting the status.
|
|
517
|
+
"""
|
|
518
|
+
try:
|
|
519
|
+
count: int = self._collection.count()
|
|
520
|
+
return VectorDBStatus(
|
|
521
|
+
vector_dim=self.vector_dim, vector_count=count
|
|
522
|
+
)
|
|
523
|
+
except Exception as e:
|
|
524
|
+
raise RuntimeError(f"Failed to get ChromaDB status: {e}")
|
|
525
|
+
|
|
526
|
+
def query(
|
|
527
|
+
self,
|
|
528
|
+
query: VectorDBQuery,
|
|
529
|
+
**kwargs: Any,
|
|
530
|
+
) -> List[VectorDBQueryResult]:
|
|
531
|
+
r"""Searches for similar vectors in ChromaDB based on the provided
|
|
532
|
+
query.
|
|
533
|
+
|
|
534
|
+
Args:
|
|
535
|
+
query (VectorDBQuery): The query object containing the search
|
|
536
|
+
vector and the number of top similar vectors to retrieve.
|
|
537
|
+
**kwargs (Any): Additional keyword arguments for ChromaDB query
|
|
538
|
+
operation.
|
|
539
|
+
|
|
540
|
+
Returns:
|
|
541
|
+
List[VectorDBQueryResult]: A list of vectors retrieved from the
|
|
542
|
+
storage based on similarity to the query vector.
|
|
543
|
+
|
|
544
|
+
Raises:
|
|
545
|
+
RuntimeError: If there is an error during the query process.
|
|
546
|
+
"""
|
|
547
|
+
try:
|
|
548
|
+
# Query ChromaDB
|
|
549
|
+
query_kwargs: Dict[str, Any] = {
|
|
550
|
+
'query_embeddings': [query.query_vector],
|
|
551
|
+
'n_results': query.top_k,
|
|
552
|
+
'include': ["embeddings", "metadatas", "distances"],
|
|
553
|
+
}
|
|
554
|
+
query_kwargs.update(kwargs)
|
|
555
|
+
|
|
556
|
+
results: "QueryResult" = self._collection.query(**query_kwargs)
|
|
557
|
+
|
|
558
|
+
# Convert ChromaDB results to VectorDBQueryResult format
|
|
559
|
+
query_results: List[VectorDBQueryResult] = []
|
|
560
|
+
|
|
561
|
+
if results.get("ids") and len(results["ids"]) > 0:
|
|
562
|
+
ids: List[str] = results["ids"][0]
|
|
563
|
+
|
|
564
|
+
# Safely extract embeddings with proper type handling
|
|
565
|
+
embeddings_result = results.get("embeddings")
|
|
566
|
+
if embeddings_result and len(embeddings_result) > 0:
|
|
567
|
+
embeddings_raw = embeddings_result[0]
|
|
568
|
+
# Convert to List[List[float]] format
|
|
569
|
+
if embeddings_raw is not None:
|
|
570
|
+
embeddings: List[List[float]] = []
|
|
571
|
+
for emb in embeddings_raw:
|
|
572
|
+
if hasattr(emb, '__iter__'):
|
|
573
|
+
# Convert any array-like structure to
|
|
574
|
+
# list of floats
|
|
575
|
+
embeddings.append([float(x) for x in emb])
|
|
576
|
+
else:
|
|
577
|
+
embeddings.append([])
|
|
578
|
+
else:
|
|
579
|
+
embeddings = []
|
|
580
|
+
else:
|
|
581
|
+
embeddings = []
|
|
582
|
+
|
|
583
|
+
# Safely extract metadatas with proper type handling
|
|
584
|
+
metadatas_result = results.get("metadatas")
|
|
585
|
+
if metadatas_result and len(metadatas_result) > 0:
|
|
586
|
+
metadatas_raw = metadatas_result[0]
|
|
587
|
+
# Convert to List[Dict[str, Any]] format
|
|
588
|
+
if metadatas_raw is not None:
|
|
589
|
+
metadatas: List[Dict[str, Any]] = []
|
|
590
|
+
for meta in metadatas_raw:
|
|
591
|
+
if meta is not None:
|
|
592
|
+
# Convert Mapping to Dict
|
|
593
|
+
metadatas.append(dict(meta))
|
|
594
|
+
else:
|
|
595
|
+
metadatas.append({})
|
|
596
|
+
else:
|
|
597
|
+
metadatas = []
|
|
598
|
+
else:
|
|
599
|
+
metadatas = []
|
|
600
|
+
|
|
601
|
+
# Safely extract distances with proper type handling
|
|
602
|
+
distances_result = results.get("distances")
|
|
603
|
+
if distances_result and len(distances_result) > 0:
|
|
604
|
+
distances_raw = distances_result[0]
|
|
605
|
+
distances: List[float] = (
|
|
606
|
+
list(distances_raw)
|
|
607
|
+
if distances_raw is not None
|
|
608
|
+
else []
|
|
609
|
+
)
|
|
610
|
+
else:
|
|
611
|
+
distances = []
|
|
612
|
+
|
|
613
|
+
for i, record_id in enumerate(ids):
|
|
614
|
+
# ChromaDB returns distances (lower is more similar)
|
|
615
|
+
# Convert to similarity score (higher is more similar)
|
|
616
|
+
distance: float = (
|
|
617
|
+
distances[i] if i < len(distances) else 1.0
|
|
618
|
+
)
|
|
619
|
+
similarity: float = self._distance_to_similarity(distance)
|
|
620
|
+
|
|
621
|
+
embedding: List[float] = (
|
|
622
|
+
embeddings[i] if i < len(embeddings) else []
|
|
623
|
+
)
|
|
624
|
+
metadata: Dict[str, Any] = (
|
|
625
|
+
metadatas[i] if i < len(metadatas) else {}
|
|
626
|
+
)
|
|
627
|
+
|
|
628
|
+
result = VectorDBQueryResult.create(
|
|
629
|
+
similarity=similarity,
|
|
630
|
+
vector=embedding,
|
|
631
|
+
id=record_id,
|
|
632
|
+
payload=metadata,
|
|
633
|
+
)
|
|
634
|
+
query_results.append(result)
|
|
635
|
+
|
|
636
|
+
logger.debug(
|
|
637
|
+
f"Query returned {len(query_results)} results from "
|
|
638
|
+
f"ChromaDB collection: {self.collection_name}"
|
|
639
|
+
)
|
|
640
|
+
return query_results
|
|
641
|
+
|
|
642
|
+
except Exception as e:
|
|
643
|
+
raise RuntimeError(f"Failed to query ChromaDB: {e}")
|
|
644
|
+
|
|
645
|
+
def _distance_to_similarity(self, distance: float) -> float:
|
|
646
|
+
r"""Convert distance to similarity score based on distance metric.
|
|
647
|
+
|
|
648
|
+
Args:
|
|
649
|
+
distance (float): Distance value from ChromaDB.
|
|
650
|
+
|
|
651
|
+
Returns:
|
|
652
|
+
float: Similarity score (higher means more similar).
|
|
653
|
+
"""
|
|
654
|
+
if self.distance == VectorDistance.COSINE:
|
|
655
|
+
# Cosine distance: 0 (identical) to 2 (opposite)
|
|
656
|
+
# Convert to similarity: 1 - (distance / 2)
|
|
657
|
+
return max(0.0, 1.0 - (distance / 2.0))
|
|
658
|
+
elif self.distance == VectorDistance.EUCLIDEAN:
|
|
659
|
+
# L2 distance: 0 (identical) to ∞
|
|
660
|
+
# Convert to similarity: 1 / (1 + distance)
|
|
661
|
+
return 1.0 / (1.0 + distance)
|
|
662
|
+
elif self.distance == VectorDistance.DOT:
|
|
663
|
+
# Inner product: higher values are more similar
|
|
664
|
+
# ChromaDB returns (1 - dot_product) as distance for inner product
|
|
665
|
+
# Convert back to similarity: similarity = 1 - distance
|
|
666
|
+
return max(0.0, 1.0 - distance)
|
|
667
|
+
else:
|
|
668
|
+
# Default: treat as cosine distance
|
|
669
|
+
return max(0.0, 1.0 - distance)
|
|
670
|
+
|
|
671
|
+
def clear(self) -> None:
|
|
672
|
+
r"""Removes all vectors from the ChromaDB collection.
|
|
673
|
+
|
|
674
|
+
Raises:
|
|
675
|
+
RuntimeError: If there is an error clearing the collection.
|
|
676
|
+
"""
|
|
677
|
+
try:
|
|
678
|
+
# Delete the current collection
|
|
679
|
+
self._client.delete_collection(name=self.collection_name)
|
|
680
|
+
|
|
681
|
+
# Recreate the collection
|
|
682
|
+
self._collection = self._get_or_create_collection()
|
|
683
|
+
|
|
684
|
+
logger.info(
|
|
685
|
+
f"Successfully cleared collection: {self.collection_name}"
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
except Exception as e:
|
|
689
|
+
raise RuntimeError(f"Failed to clear ChromaDB collection: {e}")
|
|
690
|
+
|
|
691
|
+
def load(self) -> None:
|
|
692
|
+
r"""Load the collection hosted on cloud service.
|
|
693
|
+
|
|
694
|
+
For ChromaDB, collections are automatically available when client
|
|
695
|
+
connects, so this method is a no-op.
|
|
696
|
+
"""
|
|
697
|
+
# ChromaDB collections are automatically available when client connects
|
|
698
|
+
# No explicit loading is required
|
|
699
|
+
pass
|
|
700
|
+
|
|
701
|
+
def delete_collection(self) -> None:
|
|
702
|
+
r"""Deletes the entire collection from ChromaDB.
|
|
703
|
+
|
|
704
|
+
Raises:
|
|
705
|
+
RuntimeError: If there is an error deleting the collection.
|
|
706
|
+
"""
|
|
707
|
+
try:
|
|
708
|
+
self._client.delete_collection(name=self.collection_name)
|
|
709
|
+
logger.info(
|
|
710
|
+
f"Successfully deleted collection: {self.collection_name}"
|
|
711
|
+
)
|
|
712
|
+
except Exception as e:
|
|
713
|
+
raise RuntimeError(f"Failed to delete ChromaDB collection: {e}")
|
|
714
|
+
|
|
715
|
+
@property
|
|
716
|
+
def client(self) -> "ClientAPI":
|
|
717
|
+
r"""Provides access to the underlying ChromaDB client.
|
|
718
|
+
|
|
719
|
+
Returns:
|
|
720
|
+
chromadb.Client: The ChromaDB client instance.
|
|
721
|
+
"""
|
|
722
|
+
return self._client
|
|
723
|
+
|
|
724
|
+
@property
|
|
725
|
+
def collection(self) -> "Collection":
|
|
726
|
+
r"""Provides access to the underlying ChromaDB collection.
|
|
727
|
+
|
|
728
|
+
Returns:
|
|
729
|
+
ChromaDB collection instance.
|
|
730
|
+
"""
|
|
731
|
+
return self._collection
|