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