camel-ai 0.2.59__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.

Files changed (506) hide show
  1. camel/__init__.py +3 -3
  2. camel/agents/__init__.py +2 -2
  3. camel/agents/_types.py +9 -4
  4. camel/agents/_utils.py +40 -2
  5. camel/agents/base.py +2 -2
  6. camel/agents/chat_agent.py +5012 -902
  7. camel/agents/critic_agent.py +2 -2
  8. camel/agents/deductive_reasoner_agent.py +56 -56
  9. camel/agents/embodied_agent.py +2 -2
  10. camel/agents/knowledge_graph_agent.py +20 -20
  11. camel/agents/mcp_agent.py +39 -36
  12. camel/agents/multi_hop_generator_agent.py +3 -3
  13. camel/agents/programmed_agent_instruction.py +2 -2
  14. camel/agents/repo_agent.py +4 -3
  15. camel/agents/role_assignment_agent.py +2 -2
  16. camel/agents/search_agent.py +2 -2
  17. camel/agents/task_agent.py +2 -2
  18. camel/agents/tool_agents/__init__.py +2 -2
  19. camel/agents/tool_agents/base.py +2 -2
  20. camel/agents/tool_agents/hugging_face_tool_agent.py +3 -3
  21. camel/benchmarks/__init__.py +2 -2
  22. camel/benchmarks/apibank.py +5 -5
  23. camel/benchmarks/apibench.py +2 -2
  24. camel/benchmarks/base.py +2 -2
  25. camel/benchmarks/browsecomp.py +44 -33
  26. camel/benchmarks/gaia.py +17 -13
  27. camel/benchmarks/mock_website/README.md +94 -0
  28. camel/benchmarks/mock_website/mock_web.py +299 -0
  29. camel/benchmarks/mock_website/requirements.txt +3 -0
  30. camel/benchmarks/mock_website/shopping_mall/app.py +465 -0
  31. camel/benchmarks/mock_website/task.json +104 -0
  32. camel/benchmarks/nexus.py +3 -3
  33. camel/benchmarks/ragbench.py +2 -2
  34. camel/bots/__init__.py +2 -2
  35. camel/bots/discord/__init__.py +2 -2
  36. camel/bots/discord/discord_app.py +2 -2
  37. camel/bots/discord/discord_installation.py +2 -2
  38. camel/bots/discord/discord_store.py +3 -3
  39. camel/bots/slack/__init__.py +2 -2
  40. camel/bots/slack/models.py +4 -4
  41. camel/bots/slack/slack_app.py +2 -2
  42. camel/bots/telegram_bot.py +2 -2
  43. camel/configs/__init__.py +26 -2
  44. camel/configs/aihubmix_config.py +90 -0
  45. camel/configs/aiml_config.py +2 -2
  46. camel/configs/amd_config.py +70 -0
  47. camel/configs/anthropic_config.py +8 -7
  48. camel/configs/base_config.py +2 -2
  49. camel/configs/bedrock_config.py +5 -3
  50. camel/configs/cerebras_config.py +98 -0
  51. camel/configs/cohere_config.py +3 -3
  52. camel/configs/cometapi_config.py +106 -0
  53. camel/configs/crynux_config.py +94 -0
  54. camel/configs/deepseek_config.py +9 -8
  55. camel/configs/gemini_config.py +6 -4
  56. camel/configs/groq_config.py +6 -4
  57. camel/configs/internlm_config.py +6 -4
  58. camel/configs/litellm_config.py +2 -2
  59. camel/configs/lmstudio_config.py +6 -4
  60. camel/configs/minimax_config.py +95 -0
  61. camel/configs/mistral_config.py +3 -3
  62. camel/configs/modelscope_config.py +5 -3
  63. camel/configs/moonshot_config.py +2 -2
  64. camel/configs/nebius_config.py +105 -0
  65. camel/configs/netmind_config.py +2 -2
  66. camel/configs/novita_config.py +2 -2
  67. camel/configs/nvidia_config.py +2 -2
  68. camel/configs/ollama_config.py +2 -2
  69. camel/configs/openai_config.py +8 -3
  70. camel/configs/openrouter_config.py +6 -4
  71. camel/configs/ppio_config.py +2 -2
  72. camel/configs/qianfan_config.py +85 -0
  73. camel/configs/qwen_config.py +2 -2
  74. camel/configs/reka_config.py +3 -3
  75. camel/configs/samba_config.py +8 -6
  76. camel/configs/sglang_config.py +2 -2
  77. camel/configs/siliconflow_config.py +2 -2
  78. camel/configs/togetherai_config.py +2 -2
  79. camel/configs/vllm_config.py +4 -2
  80. camel/configs/watsonx_config.py +2 -2
  81. camel/configs/yi_config.py +6 -4
  82. camel/configs/zhipuai_config.py +6 -4
  83. camel/{data_collector → data_collectors}/__init__.py +2 -2
  84. camel/{data_collector → data_collectors}/alpaca_collector.py +19 -10
  85. camel/{data_collector → data_collectors}/base.py +2 -2
  86. camel/{data_collector → data_collectors}/sharegpt_collector.py +3 -3
  87. camel/datagen/__init__.py +2 -2
  88. camel/datagen/cot_datagen.py +32 -37
  89. camel/datagen/evol_instruct/__init__.py +2 -2
  90. camel/datagen/evol_instruct/evol_instruct.py +2 -2
  91. camel/datagen/evol_instruct/scorer.py +24 -25
  92. camel/datagen/evol_instruct/templates.py +48 -48
  93. camel/datagen/self_improving_cot.py +5 -5
  94. camel/datagen/self_instruct/__init__.py +2 -2
  95. camel/datagen/self_instruct/filter/__init__.py +2 -2
  96. camel/datagen/self_instruct/filter/filter_function.py +2 -2
  97. camel/datagen/self_instruct/filter/filter_registry.py +2 -2
  98. camel/datagen/self_instruct/filter/instruction_filter.py +2 -2
  99. camel/datagen/self_instruct/self_instruct.py +2 -2
  100. camel/datagen/self_instruct/templates.py +47 -47
  101. camel/datagen/source2synth/__init__.py +2 -2
  102. camel/datagen/source2synth/data_processor.py +2 -2
  103. camel/datagen/source2synth/models.py +2 -2
  104. camel/datagen/source2synth/user_data_processor_config.py +2 -2
  105. camel/datahubs/__init__.py +2 -2
  106. camel/datahubs/base.py +2 -2
  107. camel/datahubs/huggingface.py +2 -2
  108. camel/datahubs/models.py +2 -2
  109. camel/datasets/__init__.py +2 -2
  110. camel/datasets/base_generator.py +41 -12
  111. camel/datasets/few_shot_generator.py +18 -18
  112. camel/datasets/models.py +3 -3
  113. camel/datasets/self_instruct_generator.py +2 -2
  114. camel/datasets/static_dataset.py +152 -2
  115. camel/embeddings/__init__.py +2 -2
  116. camel/embeddings/azure_embedding.py +2 -2
  117. camel/embeddings/base.py +2 -2
  118. camel/embeddings/gemini_embedding.py +2 -2
  119. camel/embeddings/jina_embedding.py +10 -3
  120. camel/embeddings/mistral_embedding.py +2 -2
  121. camel/embeddings/openai_compatible_embedding.py +2 -2
  122. camel/embeddings/openai_embedding.py +2 -2
  123. camel/embeddings/sentence_transformers_embeddings.py +4 -4
  124. camel/embeddings/together_embedding.py +2 -2
  125. camel/embeddings/vlm_embedding.py +11 -4
  126. camel/environments/__init__.py +14 -2
  127. camel/environments/models.py +2 -2
  128. camel/environments/multi_step.py +2 -2
  129. camel/environments/rlcards_env.py +860 -0
  130. camel/environments/single_step.py +30 -5
  131. camel/environments/tic_tac_toe.py +3 -3
  132. camel/extractors/__init__.py +2 -2
  133. camel/extractors/base.py +2 -2
  134. camel/extractors/python_strategies.py +2 -2
  135. camel/generators.py +2 -2
  136. camel/human.py +2 -2
  137. camel/interpreters/__init__.py +4 -2
  138. camel/interpreters/base.py +16 -3
  139. camel/interpreters/docker/Dockerfile +53 -7
  140. camel/interpreters/docker_interpreter.py +70 -11
  141. camel/interpreters/e2b_interpreter.py +59 -11
  142. camel/interpreters/internal_python_interpreter.py +81 -4
  143. camel/interpreters/interpreter_error.py +2 -2
  144. camel/interpreters/ipython_interpreter.py +23 -5
  145. camel/interpreters/microsandbox_interpreter.py +395 -0
  146. camel/interpreters/subprocess_interpreter.py +36 -4
  147. camel/loaders/__init__.py +17 -5
  148. camel/loaders/apify_reader.py +2 -2
  149. camel/loaders/base_io.py +2 -2
  150. camel/loaders/base_loader.py +85 -0
  151. camel/loaders/chunkr_reader.py +128 -93
  152. camel/loaders/crawl4ai_reader.py +2 -2
  153. camel/loaders/firecrawl_reader.py +6 -6
  154. camel/loaders/jina_url_reader.py +2 -2
  155. camel/loaders/markitdown.py +2 -2
  156. camel/loaders/mineru_extractor.py +2 -2
  157. camel/loaders/mistral_reader.py +148 -0
  158. camel/loaders/scrapegraph_reader.py +2 -2
  159. camel/loaders/unstructured_io.py +2 -2
  160. camel/logger.py +5 -5
  161. camel/memories/__init__.py +2 -2
  162. camel/memories/agent_memories.py +86 -3
  163. camel/memories/base.py +36 -2
  164. camel/memories/blocks/__init__.py +2 -2
  165. camel/memories/blocks/chat_history_block.py +126 -9
  166. camel/memories/blocks/vectordb_block.py +10 -3
  167. camel/memories/context_creators/__init__.py +2 -2
  168. camel/memories/context_creators/score_based.py +31 -239
  169. camel/memories/records.py +98 -13
  170. camel/messages/__init__.py +2 -2
  171. camel/messages/base.py +193 -46
  172. camel/messages/conversion/__init__.py +2 -2
  173. camel/messages/conversion/alpaca.py +2 -2
  174. camel/messages/conversion/conversation_models.py +2 -2
  175. camel/messages/conversion/sharegpt/__init__.py +2 -2
  176. camel/messages/conversion/sharegpt/function_call_formatter.py +2 -2
  177. camel/messages/conversion/sharegpt/hermes/__init__.py +2 -2
  178. camel/messages/conversion/sharegpt/hermes/hermes_function_formatter.py +2 -2
  179. camel/messages/func_message.py +54 -17
  180. camel/models/__init__.py +18 -2
  181. camel/models/_utils.py +3 -3
  182. camel/models/aihubmix_model.py +83 -0
  183. camel/models/aiml_model.py +11 -18
  184. camel/models/amd_model.py +101 -0
  185. camel/models/anthropic_model.py +127 -20
  186. camel/models/aws_bedrock_model.py +12 -35
  187. camel/models/azure_openai_model.py +263 -63
  188. camel/models/base_audio_model.py +5 -3
  189. camel/models/base_model.py +195 -26
  190. camel/models/cerebras_model.py +83 -0
  191. camel/models/cohere_model.py +81 -21
  192. camel/models/cometapi_model.py +83 -0
  193. camel/models/crynux_model.py +87 -0
  194. camel/models/deepseek_model.py +61 -59
  195. camel/models/fish_audio_model.py +8 -2
  196. camel/models/gemini_model.py +439 -30
  197. camel/models/groq_model.py +11 -19
  198. camel/models/internlm_model.py +11 -18
  199. camel/models/litellm_model.py +94 -34
  200. camel/models/lmstudio_model.py +17 -20
  201. camel/models/minimax_model.py +83 -0
  202. camel/models/mistral_model.py +84 -19
  203. camel/models/model_factory.py +49 -6
  204. camel/models/model_manager.py +33 -11
  205. camel/models/modelscope_model.py +13 -193
  206. camel/models/moonshot_model.py +195 -21
  207. camel/models/nebius_model.py +83 -0
  208. camel/models/nemotron_model.py +19 -9
  209. camel/models/netmind_model.py +11 -18
  210. camel/models/novita_model.py +11 -18
  211. camel/models/nvidia_model.py +11 -18
  212. camel/models/ollama_model.py +14 -21
  213. camel/models/openai_audio_models.py +2 -2
  214. camel/models/openai_compatible_model.py +234 -27
  215. camel/models/openai_model.py +255 -39
  216. camel/models/openrouter_model.py +11 -19
  217. camel/models/ppio_model.py +11 -18
  218. camel/models/qianfan_model.py +89 -0
  219. camel/models/qwen_model.py +13 -193
  220. camel/models/reka_model.py +90 -21
  221. camel/models/reward/__init__.py +2 -2
  222. camel/models/reward/base_reward_model.py +2 -2
  223. camel/models/reward/evaluator.py +2 -2
  224. camel/models/reward/nemotron_model.py +2 -2
  225. camel/models/reward/skywork_model.py +2 -2
  226. camel/models/samba_model.py +117 -49
  227. camel/models/sglang_model.py +162 -42
  228. camel/models/siliconflow_model.py +12 -35
  229. camel/models/stub_model.py +10 -7
  230. camel/models/togetherai_model.py +11 -18
  231. camel/models/vllm_model.py +10 -18
  232. camel/models/volcano_model.py +16 -20
  233. camel/models/watsonx_model.py +69 -19
  234. camel/models/yi_model.py +11 -18
  235. camel/models/zhipuai_model.py +70 -18
  236. camel/parsers/__init__.py +18 -0
  237. camel/parsers/mcp_tool_call_parser.py +176 -0
  238. camel/personas/__init__.py +2 -2
  239. camel/personas/persona.py +2 -2
  240. camel/personas/persona_hub.py +2 -2
  241. camel/prompts/__init__.py +2 -2
  242. camel/prompts/ai_society.py +2 -2
  243. camel/prompts/base.py +2 -2
  244. camel/prompts/code.py +2 -2
  245. camel/prompts/evaluation.py +2 -2
  246. camel/prompts/generate_text_embedding_data.py +2 -2
  247. camel/prompts/image_craft.py +2 -2
  248. camel/prompts/misalignment.py +2 -2
  249. camel/prompts/multi_condition_image_craft.py +2 -2
  250. camel/prompts/object_recognition.py +2 -2
  251. camel/prompts/persona_hub.py +3 -3
  252. camel/prompts/prompt_templates.py +2 -2
  253. camel/prompts/role_description_prompt_template.py +2 -2
  254. camel/prompts/solution_extraction.py +8 -8
  255. camel/prompts/task_prompt_template.py +2 -2
  256. camel/prompts/translation.py +2 -2
  257. camel/prompts/video_description_prompt.py +3 -3
  258. camel/responses/__init__.py +2 -2
  259. camel/responses/agent_responses.py +2 -2
  260. camel/retrievers/__init__.py +2 -2
  261. camel/retrievers/auto_retriever.py +23 -3
  262. camel/retrievers/base.py +2 -2
  263. camel/retrievers/bm25_retriever.py +3 -4
  264. camel/retrievers/cohere_rerank_retriever.py +2 -2
  265. camel/retrievers/hybrid_retrival.py +4 -4
  266. camel/retrievers/vector_retriever.py +2 -2
  267. camel/runtimes/Dockerfile.multi-toolkit +90 -0
  268. camel/{runtime → runtimes}/__init__.py +2 -2
  269. camel/runtimes/api.py +153 -0
  270. camel/{runtime → runtimes}/base.py +2 -2
  271. camel/{runtime → runtimes}/configs.py +13 -13
  272. camel/{runtime → runtimes}/daytona_runtime.py +18 -19
  273. camel/{runtime → runtimes}/docker_runtime.py +13 -13
  274. camel/{runtime → runtimes}/llm_guard_runtime.py +28 -28
  275. camel/{runtime → runtimes}/remote_http_runtime.py +12 -12
  276. camel/{runtime → runtimes}/ubuntu_docker_runtime.py +3 -3
  277. camel/{runtime → runtimes}/utils/__init__.py +2 -2
  278. camel/{runtime → runtimes}/utils/function_risk_toolkit.py +2 -2
  279. camel/{runtime → runtimes}/utils/ignore_risk_toolkit.py +2 -2
  280. camel/schemas/__init__.py +2 -2
  281. camel/schemas/base.py +2 -2
  282. camel/schemas/openai_converter.py +3 -3
  283. camel/schemas/outlines_converter.py +2 -2
  284. camel/services/agent_openapi_server.py +380 -0
  285. camel/societies/__init__.py +4 -2
  286. camel/societies/babyagi_playing.py +2 -2
  287. camel/societies/role_playing.py +201 -80
  288. camel/societies/workforce/__init__.py +10 -3
  289. camel/societies/workforce/base.py +9 -5
  290. camel/societies/workforce/events.py +143 -0
  291. camel/societies/workforce/prompts.py +258 -33
  292. camel/societies/workforce/role_playing_worker.py +95 -30
  293. camel/societies/workforce/single_agent_worker.py +659 -30
  294. camel/societies/workforce/structured_output_handler.py +512 -0
  295. camel/societies/workforce/task_channel.py +182 -38
  296. camel/societies/workforce/utils.py +784 -18
  297. camel/societies/workforce/worker.py +96 -28
  298. camel/societies/workforce/workflow_memory_manager.py +1746 -0
  299. camel/societies/workforce/workforce.py +5730 -366
  300. camel/societies/workforce/workforce_callback.py +103 -0
  301. camel/societies/workforce/workforce_logger.py +647 -0
  302. camel/societies/workforce/workforce_metrics.py +33 -0
  303. camel/storages/__init__.py +10 -2
  304. camel/storages/graph_storages/__init__.py +2 -2
  305. camel/storages/graph_storages/base.py +2 -2
  306. camel/storages/graph_storages/graph_element.py +2 -2
  307. camel/storages/graph_storages/nebula_graph.py +4 -4
  308. camel/storages/graph_storages/neo4j_graph.py +7 -7
  309. camel/storages/key_value_storages/__init__.py +2 -2
  310. camel/storages/key_value_storages/base.py +2 -2
  311. camel/storages/key_value_storages/in_memory.py +2 -2
  312. camel/storages/key_value_storages/json.py +17 -4
  313. camel/storages/key_value_storages/mem0_cloud.py +50 -49
  314. camel/storages/key_value_storages/redis.py +2 -2
  315. camel/storages/object_storages/__init__.py +2 -2
  316. camel/storages/object_storages/amazon_s3.py +2 -2
  317. camel/storages/object_storages/azure_blob.py +2 -2
  318. camel/storages/object_storages/base.py +2 -2
  319. camel/storages/object_storages/google_cloud.py +3 -3
  320. camel/storages/vectordb_storages/__init__.py +12 -2
  321. camel/storages/vectordb_storages/base.py +2 -2
  322. camel/storages/vectordb_storages/chroma.py +731 -0
  323. camel/storages/vectordb_storages/faiss.py +712 -0
  324. camel/storages/vectordb_storages/milvus.py +2 -2
  325. camel/storages/vectordb_storages/oceanbase.py +16 -17
  326. camel/storages/vectordb_storages/pgvector.py +349 -0
  327. camel/storages/vectordb_storages/qdrant.py +6 -6
  328. camel/storages/vectordb_storages/surreal.py +372 -0
  329. camel/storages/vectordb_storages/tidb.py +11 -8
  330. camel/storages/vectordb_storages/weaviate.py +714 -0
  331. camel/tasks/__init__.py +2 -2
  332. camel/tasks/task.py +366 -27
  333. camel/tasks/task_prompt.py +3 -3
  334. camel/terminators/__init__.py +2 -2
  335. camel/terminators/base.py +2 -2
  336. camel/terminators/response_terminator.py +2 -2
  337. camel/terminators/token_limit_terminator.py +2 -2
  338. camel/toolkits/__init__.py +58 -10
  339. camel/toolkits/aci_toolkit.py +66 -21
  340. camel/toolkits/arxiv_toolkit.py +8 -8
  341. camel/toolkits/ask_news_toolkit.py +2 -2
  342. camel/toolkits/async_browser_toolkit.py +174 -575
  343. camel/toolkits/audio_analysis_toolkit.py +3 -3
  344. camel/toolkits/base.py +65 -7
  345. camel/toolkits/bohrium_toolkit.py +318 -0
  346. camel/toolkits/browser_toolkit.py +306 -566
  347. camel/toolkits/browser_toolkit_commons.py +568 -0
  348. camel/toolkits/code_execution.py +67 -11
  349. camel/toolkits/context_summarizer_toolkit.py +684 -0
  350. camel/toolkits/craw4ai_toolkit.py +93 -0
  351. camel/toolkits/dappier_toolkit.py +12 -8
  352. camel/toolkits/data_commons_toolkit.py +2 -2
  353. camel/toolkits/dingtalk.py +1135 -0
  354. camel/toolkits/earth_science_toolkit.py +5367 -0
  355. camel/toolkits/edgeone_pages_mcp_toolkit.py +49 -0
  356. camel/toolkits/excel_toolkit.py +910 -70
  357. camel/toolkits/file_toolkit.py +1402 -0
  358. camel/toolkits/function_tool.py +128 -20
  359. camel/toolkits/github_toolkit.py +148 -43
  360. camel/toolkits/gmail_toolkit.py +1839 -0
  361. camel/toolkits/google_calendar_toolkit.py +40 -6
  362. camel/toolkits/google_drive_mcp_toolkit.py +54 -0
  363. camel/toolkits/google_maps_toolkit.py +2 -2
  364. camel/toolkits/google_scholar_toolkit.py +2 -2
  365. camel/toolkits/human_toolkit.py +36 -12
  366. camel/toolkits/hybrid_browser_toolkit/__init__.py +18 -0
  367. camel/toolkits/hybrid_browser_toolkit/config_loader.py +185 -0
  368. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +246 -0
  369. camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +1973 -0
  370. camel/toolkits/hybrid_browser_toolkit/installer.py +203 -0
  371. camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +4589 -0
  372. camel/toolkits/hybrid_browser_toolkit/ts/package.json +33 -0
  373. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-scripts.js +125 -0
  374. camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +1929 -0
  375. camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +233 -0
  376. camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +589 -0
  377. camel/toolkits/hybrid_browser_toolkit/ts/src/index.ts +7 -0
  378. camel/toolkits/hybrid_browser_toolkit/ts/src/parent-child-filter.ts +226 -0
  379. camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +219 -0
  380. camel/toolkits/hybrid_browser_toolkit/ts/src/som-screenshot-injected.ts +543 -0
  381. camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +129 -0
  382. camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json +27 -0
  383. camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +319 -0
  384. camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +1037 -0
  385. camel/toolkits/hybrid_browser_toolkit_py/__init__.py +17 -0
  386. camel/toolkits/hybrid_browser_toolkit_py/actions.py +575 -0
  387. camel/toolkits/hybrid_browser_toolkit_py/agent.py +311 -0
  388. camel/toolkits/hybrid_browser_toolkit_py/browser_session.py +787 -0
  389. camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +490 -0
  390. camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +2390 -0
  391. camel/toolkits/hybrid_browser_toolkit_py/snapshot.py +233 -0
  392. camel/toolkits/hybrid_browser_toolkit_py/stealth_script.js +0 -0
  393. camel/toolkits/hybrid_browser_toolkit_py/unified_analyzer.js +1043 -0
  394. camel/toolkits/image_analysis_toolkit.py +3 -3
  395. camel/toolkits/image_generation_toolkit.py +390 -0
  396. camel/toolkits/jina_reranker_toolkit.py +195 -79
  397. camel/toolkits/klavis_toolkit.py +7 -3
  398. camel/toolkits/linkedin_toolkit.py +2 -2
  399. camel/toolkits/markitdown_toolkit.py +104 -0
  400. camel/toolkits/math_toolkit.py +66 -12
  401. camel/toolkits/mcp_toolkit.py +841 -600
  402. camel/toolkits/memory_toolkit.py +7 -3
  403. camel/toolkits/meshy_toolkit.py +2 -2
  404. camel/toolkits/message_agent_toolkit.py +608 -0
  405. camel/toolkits/message_integration.py +724 -0
  406. camel/toolkits/mineru_toolkit.py +2 -2
  407. camel/toolkits/minimax_mcp_toolkit.py +195 -0
  408. camel/toolkits/networkx_toolkit.py +2 -2
  409. camel/toolkits/note_taking_toolkit.py +277 -0
  410. camel/toolkits/notion_mcp_toolkit.py +224 -0
  411. camel/toolkits/notion_toolkit.py +2 -2
  412. camel/toolkits/open_api_specs/biztoc/__init__.py +2 -2
  413. camel/toolkits/open_api_specs/biztoc/ai-plugin.json +1 -1
  414. camel/toolkits/open_api_specs/coursera/__init__.py +2 -2
  415. camel/toolkits/open_api_specs/create_qr_code/__init__.py +2 -2
  416. camel/toolkits/open_api_specs/klarna/__init__.py +2 -2
  417. camel/toolkits/open_api_specs/nasa_apod/__init__.py +2 -2
  418. camel/toolkits/open_api_specs/outschool/__init__.py +2 -2
  419. camel/toolkits/open_api_specs/outschool/ai-plugin.json +1 -1
  420. camel/toolkits/open_api_specs/outschool/openapi.yaml +1 -1
  421. camel/toolkits/open_api_specs/outschool/paths/__init__.py +2 -2
  422. camel/toolkits/open_api_specs/outschool/paths/get_classes.py +2 -2
  423. camel/toolkits/open_api_specs/outschool/paths/search_teachers.py +2 -2
  424. camel/toolkits/open_api_specs/security_config.py +2 -2
  425. camel/toolkits/open_api_specs/speak/__init__.py +2 -2
  426. camel/toolkits/open_api_specs/web_scraper/__init__.py +2 -2
  427. camel/toolkits/open_api_specs/web_scraper/ai-plugin.json +1 -1
  428. camel/toolkits/open_api_specs/web_scraper/paths/__init__.py +2 -2
  429. camel/toolkits/open_api_specs/web_scraper/paths/scraper.py +2 -2
  430. camel/toolkits/open_api_toolkit.py +2 -2
  431. camel/toolkits/openbb_toolkit.py +7 -3
  432. camel/toolkits/origene_mcp_toolkit.py +56 -0
  433. camel/toolkits/page_script.js +86 -74
  434. camel/toolkits/playwright_mcp_toolkit.py +27 -32
  435. camel/toolkits/pptx_toolkit.py +790 -0
  436. camel/toolkits/pubmed_toolkit.py +2 -2
  437. camel/toolkits/pulse_mcp_search_toolkit.py +2 -2
  438. camel/toolkits/pyautogui_toolkit.py +2 -2
  439. camel/toolkits/reddit_toolkit.py +2 -2
  440. camel/toolkits/resend_toolkit.py +168 -0
  441. camel/toolkits/retrieval_toolkit.py +2 -2
  442. camel/toolkits/screenshot_toolkit.py +213 -0
  443. camel/toolkits/search_toolkit.py +539 -146
  444. camel/toolkits/searxng_toolkit.py +2 -2
  445. camel/toolkits/semantic_scholar_toolkit.py +2 -2
  446. camel/toolkits/slack_toolkit.py +108 -58
  447. camel/toolkits/sql_toolkit.py +712 -0
  448. camel/toolkits/stripe_toolkit.py +2 -2
  449. camel/toolkits/sympy_toolkit.py +3 -3
  450. camel/toolkits/task_planning_toolkit.py +134 -0
  451. camel/toolkits/terminal_toolkit/__init__.py +18 -0
  452. camel/toolkits/terminal_toolkit/terminal_toolkit.py +1070 -0
  453. camel/toolkits/terminal_toolkit/utils.py +532 -0
  454. camel/toolkits/thinking_toolkit.py +3 -3
  455. camel/toolkits/twitter_toolkit.py +8 -3
  456. camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
  457. camel/toolkits/video_analysis_toolkit.py +112 -29
  458. camel/toolkits/video_download_toolkit.py +22 -16
  459. camel/toolkits/weather_toolkit.py +2 -2
  460. camel/toolkits/web_deploy_toolkit.py +1219 -0
  461. camel/toolkits/wechat_official_toolkit.py +483 -0
  462. camel/toolkits/whatsapp_toolkit.py +2 -2
  463. camel/toolkits/wolfram_alpha_toolkit.py +53 -25
  464. camel/toolkits/zapier_toolkit.py +7 -3
  465. camel/types/__init__.py +4 -4
  466. camel/types/agents/__init__.py +2 -2
  467. camel/types/agents/tool_calling_record.py +6 -3
  468. camel/types/enums.py +454 -35
  469. camel/types/mcp_registries.py +2 -2
  470. camel/types/openai_types.py +4 -4
  471. camel/types/unified_model_type.py +43 -6
  472. camel/utils/__init__.py +20 -2
  473. camel/utils/async_func.py +2 -2
  474. camel/utils/chunker/__init__.py +2 -2
  475. camel/utils/chunker/base.py +2 -2
  476. camel/utils/chunker/code_chunker.py +2 -2
  477. camel/utils/chunker/uio_chunker.py +2 -2
  478. camel/utils/commons.py +65 -7
  479. camel/utils/constants.py +5 -2
  480. camel/utils/context_utils.py +1134 -0
  481. camel/utils/deduplication.py +2 -2
  482. camel/utils/filename.py +2 -2
  483. camel/utils/langfuse.py +258 -0
  484. camel/utils/mcp.py +140 -6
  485. camel/utils/mcp_client.py +1056 -0
  486. camel/utils/message_summarizer.py +148 -0
  487. camel/utils/response_format.py +2 -2
  488. camel/utils/token_counting.py +45 -22
  489. camel/utils/tool_result.py +44 -0
  490. camel/verifiers/__init__.py +2 -2
  491. camel/verifiers/base.py +2 -2
  492. camel/verifiers/math_verifier.py +2 -2
  493. camel/verifiers/models.py +2 -2
  494. camel/verifiers/physics_verifier.py +2 -2
  495. camel/verifiers/python_verifier.py +2 -2
  496. {camel_ai-0.2.59.dist-info → camel_ai-0.2.82.dist-info}/METADATA +349 -108
  497. camel_ai-0.2.82.dist-info/RECORD +507 -0
  498. {camel_ai-0.2.59.dist-info → camel_ai-0.2.82.dist-info}/WHEEL +1 -1
  499. {camel_ai-0.2.59.dist-info → camel_ai-0.2.82.dist-info}/licenses/LICENSE +1 -1
  500. camel/loaders/pandas_reader.py +0 -368
  501. camel/runtime/api.py +0 -97
  502. camel/toolkits/dalle_toolkit.py +0 -171
  503. camel/toolkits/file_write_toolkit.py +0 -395
  504. camel/toolkits/openai_agent_toolkit.py +0 -135
  505. camel/toolkits/terminal_toolkit.py +0 -1037
  506. camel_ai-0.2.59.dist-info/RECORD +0 -410
@@ -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