camel-ai 0.2.67__py3-none-any.whl → 0.2.80a2__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.
- camel/__init__.py +1 -1
- camel/agents/_types.py +6 -2
- camel/agents/_utils.py +38 -0
- camel/agents/chat_agent.py +4014 -410
- camel/agents/mcp_agent.py +30 -27
- camel/agents/repo_agent.py +2 -1
- camel/benchmarks/browsecomp.py +6 -6
- camel/configs/__init__.py +15 -0
- camel/configs/aihubmix_config.py +88 -0
- camel/configs/amd_config.py +70 -0
- camel/configs/cometapi_config.py +104 -0
- camel/configs/minimax_config.py +93 -0
- camel/configs/nebius_config.py +103 -0
- camel/configs/vllm_config.py +2 -0
- camel/data_collectors/alpaca_collector.py +15 -6
- camel/datagen/self_improving_cot.py +1 -1
- camel/datasets/base_generator.py +39 -10
- camel/environments/__init__.py +12 -0
- camel/environments/rlcards_env.py +860 -0
- camel/environments/single_step.py +28 -3
- camel/environments/tic_tac_toe.py +1 -1
- camel/interpreters/__init__.py +2 -0
- camel/interpreters/docker/Dockerfile +4 -16
- camel/interpreters/docker_interpreter.py +3 -2
- camel/interpreters/e2b_interpreter.py +34 -1
- camel/interpreters/internal_python_interpreter.py +51 -2
- camel/interpreters/microsandbox_interpreter.py +395 -0
- camel/loaders/__init__.py +11 -2
- camel/loaders/base_loader.py +85 -0
- camel/loaders/chunkr_reader.py +9 -0
- camel/loaders/firecrawl_reader.py +4 -4
- camel/logger.py +1 -1
- camel/memories/agent_memories.py +84 -1
- camel/memories/base.py +34 -0
- camel/memories/blocks/chat_history_block.py +122 -4
- camel/memories/blocks/vectordb_block.py +8 -1
- camel/memories/context_creators/score_based.py +29 -237
- camel/memories/records.py +88 -8
- camel/messages/base.py +166 -40
- camel/messages/func_message.py +32 -5
- camel/models/__init__.py +10 -0
- camel/models/aihubmix_model.py +83 -0
- camel/models/aiml_model.py +1 -16
- camel/models/amd_model.py +101 -0
- camel/models/anthropic_model.py +117 -18
- camel/models/aws_bedrock_model.py +2 -33
- camel/models/azure_openai_model.py +205 -91
- camel/models/base_audio_model.py +3 -1
- camel/models/base_model.py +189 -24
- camel/models/cohere_model.py +5 -17
- camel/models/cometapi_model.py +83 -0
- camel/models/crynux_model.py +1 -16
- camel/models/deepseek_model.py +6 -16
- camel/models/fish_audio_model.py +6 -0
- camel/models/gemini_model.py +71 -20
- camel/models/groq_model.py +1 -17
- camel/models/internlm_model.py +1 -16
- camel/models/litellm_model.py +49 -32
- camel/models/lmstudio_model.py +1 -17
- camel/models/minimax_model.py +83 -0
- camel/models/mistral_model.py +1 -16
- camel/models/model_factory.py +27 -1
- camel/models/model_manager.py +24 -6
- camel/models/modelscope_model.py +1 -16
- camel/models/moonshot_model.py +185 -19
- camel/models/nebius_model.py +83 -0
- camel/models/nemotron_model.py +0 -5
- camel/models/netmind_model.py +1 -16
- camel/models/novita_model.py +1 -16
- camel/models/nvidia_model.py +1 -16
- camel/models/ollama_model.py +4 -19
- camel/models/openai_compatible_model.py +171 -46
- camel/models/openai_model.py +205 -77
- camel/models/openrouter_model.py +1 -17
- camel/models/ppio_model.py +1 -16
- camel/models/qianfan_model.py +1 -16
- camel/models/qwen_model.py +1 -16
- camel/models/reka_model.py +1 -16
- camel/models/samba_model.py +34 -47
- camel/models/sglang_model.py +64 -31
- camel/models/siliconflow_model.py +1 -16
- camel/models/stub_model.py +0 -4
- camel/models/togetherai_model.py +1 -16
- camel/models/vllm_model.py +1 -16
- camel/models/volcano_model.py +0 -17
- camel/models/watsonx_model.py +1 -16
- camel/models/yi_model.py +1 -16
- camel/models/zhipuai_model.py +60 -16
- camel/parsers/__init__.py +18 -0
- camel/parsers/mcp_tool_call_parser.py +176 -0
- camel/retrievers/auto_retriever.py +1 -0
- camel/runtimes/configs.py +11 -11
- camel/runtimes/daytona_runtime.py +15 -16
- camel/runtimes/docker_runtime.py +6 -6
- camel/runtimes/remote_http_runtime.py +5 -5
- camel/services/agent_openapi_server.py +380 -0
- camel/societies/__init__.py +2 -0
- camel/societies/role_playing.py +26 -28
- camel/societies/workforce/__init__.py +2 -0
- camel/societies/workforce/events.py +122 -0
- camel/societies/workforce/prompts.py +249 -38
- camel/societies/workforce/role_playing_worker.py +82 -20
- camel/societies/workforce/single_agent_worker.py +634 -34
- camel/societies/workforce/structured_output_handler.py +512 -0
- camel/societies/workforce/task_channel.py +169 -23
- camel/societies/workforce/utils.py +176 -9
- camel/societies/workforce/worker.py +77 -23
- camel/societies/workforce/workflow_memory_manager.py +772 -0
- camel/societies/workforce/workforce.py +3168 -478
- camel/societies/workforce/workforce_callback.py +74 -0
- camel/societies/workforce/workforce_logger.py +203 -175
- camel/societies/workforce/workforce_metrics.py +33 -0
- camel/storages/__init__.py +4 -0
- camel/storages/key_value_storages/json.py +15 -2
- camel/storages/key_value_storages/mem0_cloud.py +48 -47
- camel/storages/object_storages/google_cloud.py +1 -1
- camel/storages/vectordb_storages/__init__.py +6 -0
- camel/storages/vectordb_storages/chroma.py +731 -0
- camel/storages/vectordb_storages/oceanbase.py +13 -13
- camel/storages/vectordb_storages/pgvector.py +349 -0
- camel/storages/vectordb_storages/qdrant.py +3 -3
- camel/storages/vectordb_storages/surreal.py +365 -0
- camel/storages/vectordb_storages/tidb.py +8 -6
- camel/tasks/task.py +244 -27
- camel/toolkits/__init__.py +46 -8
- camel/toolkits/aci_toolkit.py +64 -19
- camel/toolkits/arxiv_toolkit.py +6 -6
- camel/toolkits/base.py +63 -5
- camel/toolkits/code_execution.py +28 -1
- camel/toolkits/context_summarizer_toolkit.py +684 -0
- camel/toolkits/craw4ai_toolkit.py +93 -0
- camel/toolkits/dappier_toolkit.py +10 -6
- camel/toolkits/dingtalk.py +1135 -0
- camel/toolkits/edgeone_pages_mcp_toolkit.py +49 -0
- camel/toolkits/excel_toolkit.py +901 -67
- camel/toolkits/file_toolkit.py +1402 -0
- camel/toolkits/function_tool.py +30 -6
- camel/toolkits/github_toolkit.py +107 -20
- camel/toolkits/gmail_toolkit.py +1839 -0
- camel/toolkits/google_calendar_toolkit.py +38 -4
- camel/toolkits/google_drive_mcp_toolkit.py +54 -0
- camel/toolkits/human_toolkit.py +34 -10
- camel/toolkits/hybrid_browser_toolkit/__init__.py +18 -0
- camel/toolkits/hybrid_browser_toolkit/config_loader.py +185 -0
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit.py +246 -0
- camel/toolkits/hybrid_browser_toolkit/hybrid_browser_toolkit_ts.py +1973 -0
- camel/toolkits/hybrid_browser_toolkit/installer.py +203 -0
- camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json +3749 -0
- camel/toolkits/hybrid_browser_toolkit/ts/package.json +32 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/browser-scripts.js +125 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/browser-session.ts +1815 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/config-loader.ts +233 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/hybrid-browser-toolkit.ts +590 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/index.ts +7 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/parent-child-filter.ts +226 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/snapshot-parser.ts +219 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/som-screenshot-injected.ts +543 -0
- camel/toolkits/hybrid_browser_toolkit/ts/src/types.ts +130 -0
- camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json +26 -0
- camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js +319 -0
- camel/toolkits/hybrid_browser_toolkit/ws_wrapper.py +1032 -0
- camel/toolkits/hybrid_browser_toolkit_py/__init__.py +17 -0
- camel/toolkits/hybrid_browser_toolkit_py/actions.py +575 -0
- camel/toolkits/hybrid_browser_toolkit_py/agent.py +311 -0
- camel/toolkits/hybrid_browser_toolkit_py/browser_session.py +787 -0
- camel/toolkits/hybrid_browser_toolkit_py/config_loader.py +490 -0
- camel/toolkits/hybrid_browser_toolkit_py/hybrid_browser_toolkit.py +2390 -0
- camel/toolkits/hybrid_browser_toolkit_py/snapshot.py +233 -0
- camel/toolkits/hybrid_browser_toolkit_py/stealth_script.js +0 -0
- camel/toolkits/hybrid_browser_toolkit_py/unified_analyzer.js +1043 -0
- camel/toolkits/image_generation_toolkit.py +390 -0
- camel/toolkits/jina_reranker_toolkit.py +3 -4
- camel/toolkits/klavis_toolkit.py +5 -1
- camel/toolkits/markitdown_toolkit.py +104 -0
- camel/toolkits/math_toolkit.py +64 -10
- camel/toolkits/mcp_toolkit.py +370 -45
- camel/toolkits/memory_toolkit.py +5 -1
- camel/toolkits/message_agent_toolkit.py +608 -0
- camel/toolkits/message_integration.py +724 -0
- camel/toolkits/minimax_mcp_toolkit.py +195 -0
- camel/toolkits/note_taking_toolkit.py +277 -0
- camel/toolkits/notion_mcp_toolkit.py +224 -0
- camel/toolkits/openbb_toolkit.py +5 -1
- camel/toolkits/origene_mcp_toolkit.py +56 -0
- camel/toolkits/playwright_mcp_toolkit.py +12 -31
- camel/toolkits/pptx_toolkit.py +25 -12
- camel/toolkits/resend_toolkit.py +168 -0
- camel/toolkits/screenshot_toolkit.py +213 -0
- camel/toolkits/search_toolkit.py +437 -142
- camel/toolkits/slack_toolkit.py +104 -50
- camel/toolkits/sympy_toolkit.py +1 -1
- camel/toolkits/task_planning_toolkit.py +3 -3
- camel/toolkits/terminal_toolkit/__init__.py +18 -0
- camel/toolkits/terminal_toolkit/terminal_toolkit.py +957 -0
- camel/toolkits/terminal_toolkit/utils.py +532 -0
- camel/toolkits/thinking_toolkit.py +1 -1
- camel/toolkits/vertex_ai_veo_toolkit.py +590 -0
- camel/toolkits/video_analysis_toolkit.py +106 -26
- camel/toolkits/video_download_toolkit.py +17 -14
- camel/toolkits/web_deploy_toolkit.py +1219 -0
- camel/toolkits/wechat_official_toolkit.py +483 -0
- camel/toolkits/zapier_toolkit.py +5 -1
- camel/types/__init__.py +2 -2
- camel/types/agents/tool_calling_record.py +4 -1
- camel/types/enums.py +316 -40
- camel/types/openai_types.py +2 -2
- camel/types/unified_model_type.py +31 -4
- camel/utils/commons.py +36 -5
- camel/utils/constants.py +3 -0
- camel/utils/context_utils.py +1003 -0
- camel/utils/mcp.py +138 -4
- camel/utils/mcp_client.py +45 -1
- camel/utils/message_summarizer.py +148 -0
- camel/utils/token_counting.py +43 -20
- camel/utils/tool_result.py +44 -0
- {camel_ai-0.2.67.dist-info → camel_ai-0.2.80a2.dist-info}/METADATA +296 -85
- {camel_ai-0.2.67.dist-info → camel_ai-0.2.80a2.dist-info}/RECORD +219 -146
- camel/loaders/pandas_reader.py +0 -368
- camel/toolkits/dalle_toolkit.py +0 -175
- camel/toolkits/file_write_toolkit.py +0 -444
- camel/toolkits/openai_agent_toolkit.py +0 -135
- camel/toolkits/terminal_toolkit.py +0 -1037
- {camel_ai-0.2.67.dist-info → camel_ai-0.2.80a2.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.67.dist-info → camel_ai-0.2.80a2.dist-info}/licenses/LICENSE +0 -0
camel/models/openai_model.py
CHANGED
|
@@ -16,9 +16,14 @@ import warnings
|
|
|
16
16
|
from typing import Any, Dict, List, Optional, Type, Union
|
|
17
17
|
|
|
18
18
|
from openai import AsyncOpenAI, AsyncStream, OpenAI, Stream
|
|
19
|
+
from openai.lib.streaming.chat import (
|
|
20
|
+
AsyncChatCompletionStreamManager,
|
|
21
|
+
ChatCompletionStreamManager,
|
|
22
|
+
)
|
|
19
23
|
from pydantic import BaseModel
|
|
20
24
|
|
|
21
|
-
from camel.configs import
|
|
25
|
+
from camel.configs import ChatGPTConfig
|
|
26
|
+
from camel.logger import get_logger
|
|
22
27
|
from camel.messages import OpenAIMessage
|
|
23
28
|
from camel.models import BaseModelBackend
|
|
24
29
|
from camel.types import (
|
|
@@ -35,11 +40,18 @@ from camel.utils import (
|
|
|
35
40
|
update_langfuse_trace,
|
|
36
41
|
)
|
|
37
42
|
|
|
43
|
+
logger = get_logger(__name__)
|
|
44
|
+
|
|
38
45
|
if os.environ.get("LANGFUSE_ENABLED", "False").lower() == "true":
|
|
39
46
|
try:
|
|
40
47
|
from langfuse.decorators import observe
|
|
41
48
|
except ImportError:
|
|
42
49
|
from camel.utils import observe
|
|
50
|
+
elif os.environ.get("TRACEROOT_ENABLED", "False").lower() == "true":
|
|
51
|
+
try:
|
|
52
|
+
from traceroot import trace as observe # type: ignore[import]
|
|
53
|
+
except ImportError:
|
|
54
|
+
from camel.utils import observe
|
|
43
55
|
else:
|
|
44
56
|
from camel.utils import observe
|
|
45
57
|
|
|
@@ -78,9 +90,21 @@ class OpenAIModel(BaseModelBackend):
|
|
|
78
90
|
(default: :obj:`None`)
|
|
79
91
|
max_retries (int, optional): Maximum number of retries for API calls.
|
|
80
92
|
(default: :obj:`3`)
|
|
93
|
+
client (Optional[Any], optional): A custom synchronous OpenAI client
|
|
94
|
+
instance. If provided, this client will be used instead of
|
|
95
|
+
creating a new one. Useful for RL frameworks like AReaL or rLLM
|
|
96
|
+
that provide OpenAI-compatible clients. The client should
|
|
97
|
+
implement the OpenAI client interface with
|
|
98
|
+
`.chat.completions.create()` and `.beta.chat.completions.parse()`
|
|
99
|
+
methods. (default: :obj:`None`)
|
|
100
|
+
async_client (Optional[Any], optional): A custom asynchronous OpenAI
|
|
101
|
+
client instance. If provided, this client will be used instead of
|
|
102
|
+
creating a new one. The client should implement the AsyncOpenAI
|
|
103
|
+
client interface. (default: :obj:`None`)
|
|
81
104
|
**kwargs (Any): Additional arguments to pass to the
|
|
82
105
|
OpenAI client initialization. These can include parameters like
|
|
83
106
|
'organization', 'default_headers', 'http_client', etc.
|
|
107
|
+
Ignored if custom clients are provided.
|
|
84
108
|
"""
|
|
85
109
|
|
|
86
110
|
@api_keys_required(
|
|
@@ -97,6 +121,8 @@ class OpenAIModel(BaseModelBackend):
|
|
|
97
121
|
token_counter: Optional[BaseTokenCounter] = None,
|
|
98
122
|
timeout: Optional[float] = None,
|
|
99
123
|
max_retries: int = 3,
|
|
124
|
+
client: Optional[Any] = None,
|
|
125
|
+
async_client: Optional[Any] = None,
|
|
100
126
|
**kwargs: Any,
|
|
101
127
|
) -> None:
|
|
102
128
|
if model_config_dict is None:
|
|
@@ -112,42 +138,54 @@ class OpenAIModel(BaseModelBackend):
|
|
|
112
138
|
model_type, model_config_dict, api_key, url, token_counter, timeout
|
|
113
139
|
)
|
|
114
140
|
|
|
115
|
-
if
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
# Create Langfuse client with base parameters and additional
|
|
120
|
-
# arguments
|
|
121
|
-
self._client = LangfuseOpenAI(
|
|
122
|
-
timeout=self._timeout,
|
|
123
|
-
max_retries=self._max_retries,
|
|
124
|
-
base_url=self._url,
|
|
125
|
-
api_key=self._api_key,
|
|
126
|
-
**kwargs,
|
|
127
|
-
)
|
|
128
|
-
self._async_client = LangfuseAsyncOpenAI(
|
|
129
|
-
timeout=self._timeout,
|
|
130
|
-
max_retries=self._max_retries,
|
|
131
|
-
base_url=self._url,
|
|
132
|
-
api_key=self._api_key,
|
|
133
|
-
**kwargs,
|
|
134
|
-
)
|
|
141
|
+
# Use custom clients if provided, otherwise create new ones
|
|
142
|
+
if client is not None:
|
|
143
|
+
# Use the provided custom sync client
|
|
144
|
+
self._client = client
|
|
135
145
|
else:
|
|
136
|
-
# Create
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
# Create default sync client
|
|
147
|
+
if is_langfuse_available():
|
|
148
|
+
from langfuse.openai import OpenAI as LangfuseOpenAI
|
|
149
|
+
|
|
150
|
+
self._client = LangfuseOpenAI(
|
|
151
|
+
timeout=self._timeout,
|
|
152
|
+
max_retries=self._max_retries,
|
|
153
|
+
base_url=self._url,
|
|
154
|
+
api_key=self._api_key,
|
|
155
|
+
**kwargs,
|
|
156
|
+
)
|
|
157
|
+
else:
|
|
158
|
+
self._client = OpenAI(
|
|
159
|
+
timeout=self._timeout,
|
|
160
|
+
max_retries=self._max_retries,
|
|
161
|
+
base_url=self._url,
|
|
162
|
+
api_key=self._api_key,
|
|
163
|
+
**kwargs,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
if async_client is not None:
|
|
167
|
+
# Use the provided custom async client
|
|
168
|
+
self._async_client = async_client
|
|
169
|
+
else:
|
|
170
|
+
# Create default async client
|
|
171
|
+
if is_langfuse_available():
|
|
172
|
+
from langfuse.openai import AsyncOpenAI as LangfuseAsyncOpenAI
|
|
173
|
+
|
|
174
|
+
self._async_client = LangfuseAsyncOpenAI(
|
|
175
|
+
timeout=self._timeout,
|
|
176
|
+
max_retries=self._max_retries,
|
|
177
|
+
base_url=self._url,
|
|
178
|
+
api_key=self._api_key,
|
|
179
|
+
**kwargs,
|
|
180
|
+
)
|
|
181
|
+
else:
|
|
182
|
+
self._async_client = AsyncOpenAI(
|
|
183
|
+
timeout=self._timeout,
|
|
184
|
+
max_retries=self._max_retries,
|
|
185
|
+
base_url=self._url,
|
|
186
|
+
api_key=self._api_key,
|
|
187
|
+
**kwargs,
|
|
188
|
+
)
|
|
151
189
|
|
|
152
190
|
def _sanitize_config(self, config_dict: Dict[str, Any]) -> Dict[str, Any]:
|
|
153
191
|
r"""Sanitize the model configuration for O1 models."""
|
|
@@ -238,7 +276,11 @@ class OpenAIModel(BaseModelBackend):
|
|
|
238
276
|
messages: List[OpenAIMessage],
|
|
239
277
|
response_format: Optional[Type[BaseModel]] = None,
|
|
240
278
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
241
|
-
) -> Union[
|
|
279
|
+
) -> Union[
|
|
280
|
+
ChatCompletion,
|
|
281
|
+
Stream[ChatCompletionChunk],
|
|
282
|
+
ChatCompletionStreamManager[BaseModel],
|
|
283
|
+
]:
|
|
242
284
|
r"""Runs inference of OpenAI chat completion.
|
|
243
285
|
|
|
244
286
|
Args:
|
|
@@ -250,33 +292,51 @@ class OpenAIModel(BaseModelBackend):
|
|
|
250
292
|
use for the request.
|
|
251
293
|
|
|
252
294
|
Returns:
|
|
253
|
-
Union[ChatCompletion, Stream[ChatCompletionChunk]
|
|
254
|
-
|
|
255
|
-
`
|
|
295
|
+
Union[ChatCompletion, Stream[ChatCompletionChunk],
|
|
296
|
+
ChatCompletionStreamManager[BaseModel]]:
|
|
297
|
+
`ChatCompletion` in the non-stream mode,
|
|
298
|
+
`Stream[ChatCompletionChunk]`in the stream mode,
|
|
299
|
+
or `ChatCompletionStreamManager[BaseModel]` for
|
|
300
|
+
structured output streaming.
|
|
256
301
|
"""
|
|
257
302
|
|
|
258
303
|
# Update Langfuse trace with current agent session and metadata
|
|
259
304
|
agent_session_id = get_current_agent_session_id()
|
|
305
|
+
model_type_str = str(self.model_type)
|
|
306
|
+
if not agent_session_id:
|
|
307
|
+
agent_session_id = "no-session-id"
|
|
308
|
+
metadata = {
|
|
309
|
+
"source": "camel",
|
|
310
|
+
"agent_id": agent_session_id,
|
|
311
|
+
"agent_type": "camel_chat_agent",
|
|
312
|
+
"model_type": model_type_str,
|
|
313
|
+
}
|
|
314
|
+
metadata = {k: str(v) for k, v in metadata.items()}
|
|
260
315
|
if agent_session_id:
|
|
261
316
|
update_langfuse_trace(
|
|
262
317
|
session_id=agent_session_id,
|
|
263
|
-
metadata=
|
|
264
|
-
|
|
265
|
-
"agent_id": agent_session_id,
|
|
266
|
-
"agent_type": "camel_chat_agent",
|
|
267
|
-
"model_type": str(self.model_type),
|
|
268
|
-
},
|
|
269
|
-
tags=["CAMEL-AI", str(self.model_type)],
|
|
318
|
+
metadata=metadata,
|
|
319
|
+
tags=["CAMEL-AI", model_type_str],
|
|
270
320
|
)
|
|
321
|
+
logger.info(f"metadata: {metadata}")
|
|
271
322
|
|
|
272
323
|
messages = self._adapt_messages_for_o1_models(messages)
|
|
273
324
|
response_format = response_format or self.model_config_dict.get(
|
|
274
325
|
"response_format", None
|
|
275
326
|
)
|
|
327
|
+
|
|
328
|
+
# Check if streaming is enabled
|
|
329
|
+
is_streaming = self.model_config_dict.get("stream", False)
|
|
330
|
+
|
|
276
331
|
if response_format:
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
332
|
+
if is_streaming:
|
|
333
|
+
# Use streaming parse for structured output
|
|
334
|
+
return self._request_stream_parse(
|
|
335
|
+
messages, response_format, tools
|
|
336
|
+
)
|
|
337
|
+
else:
|
|
338
|
+
# Use non-streaming parse for structured output
|
|
339
|
+
return self._request_parse(messages, response_format, tools)
|
|
280
340
|
else:
|
|
281
341
|
result = self._request_chat_completion(messages, tools)
|
|
282
342
|
|
|
@@ -288,7 +348,11 @@ class OpenAIModel(BaseModelBackend):
|
|
|
288
348
|
messages: List[OpenAIMessage],
|
|
289
349
|
response_format: Optional[Type[BaseModel]] = None,
|
|
290
350
|
tools: Optional[List[Dict[str, Any]]] = None,
|
|
291
|
-
) -> Union[
|
|
351
|
+
) -> Union[
|
|
352
|
+
ChatCompletion,
|
|
353
|
+
AsyncStream[ChatCompletionChunk],
|
|
354
|
+
AsyncChatCompletionStreamManager[BaseModel],
|
|
355
|
+
]:
|
|
292
356
|
r"""Runs inference of OpenAI chat completion in async mode.
|
|
293
357
|
|
|
294
358
|
Args:
|
|
@@ -300,33 +364,52 @@ class OpenAIModel(BaseModelBackend):
|
|
|
300
364
|
use for the request.
|
|
301
365
|
|
|
302
366
|
Returns:
|
|
303
|
-
Union[ChatCompletion, AsyncStream[ChatCompletionChunk]
|
|
304
|
-
|
|
305
|
-
`
|
|
367
|
+
Union[ChatCompletion, AsyncStream[ChatCompletionChunk],
|
|
368
|
+
AsyncChatCompletionStreamManager[BaseModel]]:
|
|
369
|
+
`ChatCompletion` in the non-stream mode,
|
|
370
|
+
`AsyncStream[ChatCompletionChunk]` in the stream mode, or
|
|
371
|
+
`AsyncChatCompletionStreamManager[BaseModel]` for
|
|
372
|
+
structured output streaming.
|
|
306
373
|
"""
|
|
307
374
|
|
|
308
375
|
# Update Langfuse trace with current agent session and metadata
|
|
309
376
|
agent_session_id = get_current_agent_session_id()
|
|
310
|
-
|
|
377
|
+
model_type_str = str(self.model_type)
|
|
378
|
+
if not agent_session_id:
|
|
379
|
+
agent_session_id = "no-session-id"
|
|
380
|
+
metadata = {
|
|
381
|
+
"source": "camel",
|
|
382
|
+
"agent_id": agent_session_id,
|
|
383
|
+
"agent_type": "camel_chat_agent",
|
|
384
|
+
"model_type": model_type_str,
|
|
385
|
+
}
|
|
386
|
+
metadata = {k: str(v) for k, v in metadata.items()}
|
|
311
387
|
update_langfuse_trace(
|
|
312
388
|
session_id=agent_session_id,
|
|
313
|
-
metadata=
|
|
314
|
-
|
|
315
|
-
"agent_id": agent_session_id,
|
|
316
|
-
"agent_type": "camel_chat_agent",
|
|
317
|
-
"model_type": str(self.model_type),
|
|
318
|
-
},
|
|
319
|
-
tags=["CAMEL-AI", str(self.model_type)],
|
|
389
|
+
metadata=metadata,
|
|
390
|
+
tags=["CAMEL-AI", model_type_str],
|
|
320
391
|
)
|
|
392
|
+
logger.info(f"metadata: {metadata}")
|
|
321
393
|
|
|
322
394
|
messages = self._adapt_messages_for_o1_models(messages)
|
|
323
395
|
response_format = response_format or self.model_config_dict.get(
|
|
324
396
|
"response_format", None
|
|
325
397
|
)
|
|
398
|
+
|
|
399
|
+
# Check if streaming is enabled
|
|
400
|
+
is_streaming = self.model_config_dict.get("stream", False)
|
|
401
|
+
|
|
326
402
|
if response_format:
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
403
|
+
if is_streaming:
|
|
404
|
+
# Use streaming parse for structured output
|
|
405
|
+
return await self._arequest_stream_parse(
|
|
406
|
+
messages, response_format, tools
|
|
407
|
+
)
|
|
408
|
+
else:
|
|
409
|
+
# Use non-streaming parse for structured output
|
|
410
|
+
return await self._arequest_parse(
|
|
411
|
+
messages, response_format, tools
|
|
412
|
+
)
|
|
330
413
|
else:
|
|
331
414
|
result = await self._arequest_chat_completion(messages, tools)
|
|
332
415
|
|
|
@@ -422,20 +505,65 @@ class OpenAIModel(BaseModelBackend):
|
|
|
422
505
|
**request_config,
|
|
423
506
|
)
|
|
424
507
|
|
|
425
|
-
def
|
|
426
|
-
|
|
427
|
-
|
|
508
|
+
def _request_stream_parse(
|
|
509
|
+
self,
|
|
510
|
+
messages: List[OpenAIMessage],
|
|
511
|
+
response_format: Type[BaseModel],
|
|
512
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
513
|
+
) -> ChatCompletionStreamManager[BaseModel]:
|
|
514
|
+
r"""Request streaming structured output parsing.
|
|
428
515
|
|
|
429
|
-
|
|
430
|
-
ValueError: If the model configuration dictionary contains any
|
|
431
|
-
unexpected arguments to OpenAI API.
|
|
516
|
+
Note: This uses OpenAI's beta streaming API for structured outputs.
|
|
432
517
|
"""
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
518
|
+
import copy
|
|
519
|
+
|
|
520
|
+
request_config = copy.deepcopy(self.model_config_dict)
|
|
521
|
+
|
|
522
|
+
# Remove stream from config as it's handled by the stream method
|
|
523
|
+
request_config.pop("stream", None)
|
|
524
|
+
|
|
525
|
+
if tools is not None:
|
|
526
|
+
request_config["tools"] = tools
|
|
527
|
+
|
|
528
|
+
request_config = self._sanitize_config(request_config)
|
|
529
|
+
|
|
530
|
+
# Use the beta streaming API for structured outputs
|
|
531
|
+
return self._client.beta.chat.completions.stream(
|
|
532
|
+
messages=messages,
|
|
533
|
+
model=self.model_type,
|
|
534
|
+
response_format=response_format,
|
|
535
|
+
**request_config,
|
|
536
|
+
)
|
|
537
|
+
|
|
538
|
+
async def _arequest_stream_parse(
|
|
539
|
+
self,
|
|
540
|
+
messages: List[OpenAIMessage],
|
|
541
|
+
response_format: Type[BaseModel],
|
|
542
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
|
543
|
+
) -> AsyncChatCompletionStreamManager[BaseModel]:
|
|
544
|
+
r"""Request async streaming structured output parsing.
|
|
545
|
+
|
|
546
|
+
Note: This uses OpenAI's beta streaming API for structured outputs.
|
|
547
|
+
"""
|
|
548
|
+
import copy
|
|
549
|
+
|
|
550
|
+
request_config = copy.deepcopy(self.model_config_dict)
|
|
551
|
+
|
|
552
|
+
# Remove stream from config as it's handled by the stream method
|
|
553
|
+
request_config.pop("stream", None)
|
|
554
|
+
|
|
555
|
+
if tools is not None:
|
|
556
|
+
request_config["tools"] = tools
|
|
557
|
+
|
|
558
|
+
request_config = self._sanitize_config(request_config)
|
|
559
|
+
|
|
560
|
+
# Use the beta streaming API for structured outputs
|
|
561
|
+
return self._async_client.beta.chat.completions.stream(
|
|
562
|
+
messages=messages,
|
|
563
|
+
model=self.model_type,
|
|
564
|
+
response_format=response_format,
|
|
565
|
+
**request_config,
|
|
566
|
+
)
|
|
439
567
|
|
|
440
568
|
@property
|
|
441
569
|
def stream(self) -> bool:
|
camel/models/openrouter_model.py
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import os
|
|
15
15
|
from typing import Any, Dict, Optional, Union
|
|
16
16
|
|
|
17
|
-
from camel.configs import
|
|
17
|
+
from camel.configs import OpenRouterConfig
|
|
18
18
|
from camel.models.openai_compatible_model import OpenAICompatibleModel
|
|
19
19
|
from camel.types import ModelType
|
|
20
20
|
from camel.utils import (
|
|
@@ -81,19 +81,3 @@ class OpenRouterModel(OpenAICompatibleModel):
|
|
|
81
81
|
max_retries=max_retries,
|
|
82
82
|
**kwargs,
|
|
83
83
|
)
|
|
84
|
-
|
|
85
|
-
def check_model_config(self):
|
|
86
|
-
r"""Check whether the model configuration contains any unexpected
|
|
87
|
-
arguments to OpenRouter API. But OpenRouter API does not have any
|
|
88
|
-
additional arguments to check.
|
|
89
|
-
|
|
90
|
-
Raises:
|
|
91
|
-
ValueError: If the model configuration dictionary contains any
|
|
92
|
-
unexpected arguments to OpenRouter API.
|
|
93
|
-
"""
|
|
94
|
-
for param in self.model_config_dict:
|
|
95
|
-
if param not in OPENROUTER_API_PARAMS:
|
|
96
|
-
raise ValueError(
|
|
97
|
-
f"Unexpected argument `{param}` is "
|
|
98
|
-
"input into OpenRouter model backend."
|
|
99
|
-
)
|
camel/models/ppio_model.py
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import os
|
|
16
16
|
from typing import Any, Dict, Optional, Union
|
|
17
17
|
|
|
18
|
-
from camel.configs import
|
|
18
|
+
from camel.configs import PPIOConfig
|
|
19
19
|
from camel.models.openai_compatible_model import OpenAICompatibleModel
|
|
20
20
|
from camel.types import ModelType
|
|
21
21
|
from camel.utils import (
|
|
@@ -86,18 +86,3 @@ class PPIOModel(OpenAICompatibleModel):
|
|
|
86
86
|
max_retries=max_retries,
|
|
87
87
|
**kwargs,
|
|
88
88
|
)
|
|
89
|
-
|
|
90
|
-
def check_model_config(self):
|
|
91
|
-
r"""Check whether the model configuration contains any
|
|
92
|
-
unexpected arguments to PPIO API.
|
|
93
|
-
|
|
94
|
-
Raises:
|
|
95
|
-
ValueError: If the model configuration dictionary contains any
|
|
96
|
-
unexpected arguments to PPIO API.
|
|
97
|
-
"""
|
|
98
|
-
for param in self.model_config_dict:
|
|
99
|
-
if param not in PPIO_API_PARAMS:
|
|
100
|
-
raise ValueError(
|
|
101
|
-
f"Unexpected argument `{param}` is "
|
|
102
|
-
"input into PPIO model backend."
|
|
103
|
-
)
|
camel/models/qianfan_model.py
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import os
|
|
16
16
|
from typing import Any, Dict, Optional, Union
|
|
17
17
|
|
|
18
|
-
from camel.configs import
|
|
18
|
+
from camel.configs import QianfanConfig
|
|
19
19
|
from camel.models.openai_compatible_model import OpenAICompatibleModel
|
|
20
20
|
from camel.types import ModelType
|
|
21
21
|
from camel.utils import (
|
|
@@ -87,18 +87,3 @@ class QianfanModel(OpenAICompatibleModel):
|
|
|
87
87
|
max_retries=max_retries,
|
|
88
88
|
**kwargs,
|
|
89
89
|
)
|
|
90
|
-
|
|
91
|
-
def check_model_config(self):
|
|
92
|
-
r"""Check whether the model configuration contains any
|
|
93
|
-
unexpected arguments to Qianfan API.
|
|
94
|
-
|
|
95
|
-
Raises:
|
|
96
|
-
ValueError: If the model configuration dictionary contains any
|
|
97
|
-
unexpected arguments to Qianfan API.
|
|
98
|
-
"""
|
|
99
|
-
for param in self.model_config_dict:
|
|
100
|
-
if param not in QIANFAN_API_PARAMS:
|
|
101
|
-
raise ValueError(
|
|
102
|
-
f"Unexpected argument `{param}` is "
|
|
103
|
-
"input into QIANFAN model backend."
|
|
104
|
-
)
|
camel/models/qwen_model.py
CHANGED
|
@@ -18,7 +18,7 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
18
18
|
|
|
19
19
|
from openai import AsyncStream, Stream
|
|
20
20
|
|
|
21
|
-
from camel.configs import
|
|
21
|
+
from camel.configs import QwenConfig
|
|
22
22
|
from camel.messages import OpenAIMessage
|
|
23
23
|
from camel.models.openai_compatible_model import OpenAICompatibleModel
|
|
24
24
|
from camel.types import (
|
|
@@ -259,18 +259,3 @@ class QwenModel(OpenAICompatibleModel):
|
|
|
259
259
|
**request_config,
|
|
260
260
|
)
|
|
261
261
|
return self._post_handle_response(response)
|
|
262
|
-
|
|
263
|
-
def check_model_config(self):
|
|
264
|
-
r"""Check whether the model configuration contains any
|
|
265
|
-
unexpected arguments to Qwen API.
|
|
266
|
-
|
|
267
|
-
Raises:
|
|
268
|
-
ValueError: If the model configuration dictionary contains any
|
|
269
|
-
unexpected arguments to Qwen API.
|
|
270
|
-
"""
|
|
271
|
-
for param in self.model_config_dict:
|
|
272
|
-
if param not in QWEN_API_PARAMS:
|
|
273
|
-
raise ValueError(
|
|
274
|
-
f"Unexpected argument `{param}` is "
|
|
275
|
-
"input into Qwen model backend."
|
|
276
|
-
)
|
camel/models/reka_model.py
CHANGED
|
@@ -16,7 +16,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, Union
|
|
|
16
16
|
|
|
17
17
|
from pydantic import BaseModel
|
|
18
18
|
|
|
19
|
-
from camel.configs import
|
|
19
|
+
from camel.configs import RekaConfig
|
|
20
20
|
from camel.messages import OpenAIMessage
|
|
21
21
|
from camel.models import BaseModelBackend
|
|
22
22
|
from camel.types import ChatCompletion, ModelType
|
|
@@ -354,21 +354,6 @@ class RekaModel(BaseModelBackend):
|
|
|
354
354
|
|
|
355
355
|
return openai_response
|
|
356
356
|
|
|
357
|
-
def check_model_config(self):
|
|
358
|
-
r"""Check whether the model configuration contains any
|
|
359
|
-
unexpected arguments to Reka API.
|
|
360
|
-
|
|
361
|
-
Raises:
|
|
362
|
-
ValueError: If the model configuration dictionary contains any
|
|
363
|
-
unexpected arguments to Reka API.
|
|
364
|
-
"""
|
|
365
|
-
for param in self.model_config_dict:
|
|
366
|
-
if param not in REKA_API_PARAMS:
|
|
367
|
-
raise ValueError(
|
|
368
|
-
f"Unexpected argument `{param}` is "
|
|
369
|
-
"input into Reka model backend."
|
|
370
|
-
)
|
|
371
|
-
|
|
372
357
|
@property
|
|
373
358
|
def stream(self) -> bool:
|
|
374
359
|
r"""Returns whether the model is in stream mode, which sends partial
|
camel/models/samba_model.py
CHANGED
|
@@ -22,8 +22,6 @@ from openai import AsyncOpenAI, AsyncStream, OpenAI, Stream
|
|
|
22
22
|
from pydantic import BaseModel
|
|
23
23
|
|
|
24
24
|
from camel.configs import (
|
|
25
|
-
SAMBA_CLOUD_API_PARAMS,
|
|
26
|
-
SAMBA_VERSE_API_PARAMS,
|
|
27
25
|
SambaCloudAPIConfig,
|
|
28
26
|
)
|
|
29
27
|
from camel.messages import OpenAIMessage
|
|
@@ -90,8 +88,16 @@ class SambaModel(BaseModelBackend):
|
|
|
90
88
|
(default: :obj:`None`)
|
|
91
89
|
max_retries (int, optional): Maximum number of retries for API calls.
|
|
92
90
|
(default: :obj:`3`)
|
|
91
|
+
client (Optional[Any], optional): A custom synchronous
|
|
92
|
+
OpenAI-compatible client instance. If provided, this client will
|
|
93
|
+
be used instead of creating a new one. Only applicable when using
|
|
94
|
+
SambaNova Cloud API. (default: :obj:`None`)
|
|
95
|
+
async_client (Optional[Any], optional): A custom asynchronous
|
|
96
|
+
OpenAI-compatible client instance. If provided, this client will
|
|
97
|
+
be used instead of creating a new one. Only applicable when using
|
|
98
|
+
SambaNova Cloud API. (default: :obj:`None`)
|
|
93
99
|
**kwargs (Any): Additional arguments to pass to the client
|
|
94
|
-
initialization.
|
|
100
|
+
initialization. Ignored if custom clients are provided.
|
|
95
101
|
"""
|
|
96
102
|
|
|
97
103
|
@api_keys_required(
|
|
@@ -108,6 +114,8 @@ class SambaModel(BaseModelBackend):
|
|
|
108
114
|
token_counter: Optional[BaseTokenCounter] = None,
|
|
109
115
|
timeout: Optional[float] = None,
|
|
110
116
|
max_retries: int = 3,
|
|
117
|
+
client: Optional[Any] = None,
|
|
118
|
+
async_client: Optional[Any] = None,
|
|
111
119
|
**kwargs: Any,
|
|
112
120
|
) -> None:
|
|
113
121
|
if model_config_dict is None:
|
|
@@ -128,21 +136,30 @@ class SambaModel(BaseModelBackend):
|
|
|
128
136
|
max_retries,
|
|
129
137
|
)
|
|
130
138
|
|
|
139
|
+
# Only create clients for Cloud API mode
|
|
131
140
|
if self._url == "https://api.sambanova.ai/v1":
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
# Use custom clients if provided, otherwise create new ones
|
|
142
|
+
if client is not None:
|
|
143
|
+
self._client = client
|
|
144
|
+
else:
|
|
145
|
+
self._client = OpenAI(
|
|
146
|
+
timeout=self._timeout,
|
|
147
|
+
max_retries=self._max_retries,
|
|
148
|
+
base_url=self._url,
|
|
149
|
+
api_key=self._api_key,
|
|
150
|
+
**kwargs,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
if async_client is not None:
|
|
154
|
+
self._async_client = async_client
|
|
155
|
+
else:
|
|
156
|
+
self._async_client = AsyncOpenAI(
|
|
157
|
+
timeout=self._timeout,
|
|
158
|
+
max_retries=self._max_retries,
|
|
159
|
+
base_url=self._url,
|
|
160
|
+
api_key=self._api_key,
|
|
161
|
+
**kwargs,
|
|
162
|
+
)
|
|
146
163
|
|
|
147
164
|
@property
|
|
148
165
|
def token_counter(self) -> BaseTokenCounter:
|
|
@@ -156,36 +173,6 @@ class SambaModel(BaseModelBackend):
|
|
|
156
173
|
self._token_counter = OpenAITokenCounter(ModelType.GPT_4O_MINI)
|
|
157
174
|
return self._token_counter
|
|
158
175
|
|
|
159
|
-
def check_model_config(self):
|
|
160
|
-
r"""Check whether the model configuration contains any
|
|
161
|
-
unexpected arguments to SambaNova API.
|
|
162
|
-
|
|
163
|
-
Raises:
|
|
164
|
-
ValueError: If the model configuration dictionary contains any
|
|
165
|
-
unexpected arguments to SambaNova API.
|
|
166
|
-
"""
|
|
167
|
-
if self._url == "https://sambaverse.sambanova.ai/api/predict":
|
|
168
|
-
for param in self.model_config_dict:
|
|
169
|
-
if param not in SAMBA_VERSE_API_PARAMS:
|
|
170
|
-
raise ValueError(
|
|
171
|
-
f"Unexpected argument `{param}` is "
|
|
172
|
-
"input into SambaVerse API."
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
elif self._url == "https://api.sambanova.ai/v1":
|
|
176
|
-
for param in self.model_config_dict:
|
|
177
|
-
if param not in SAMBA_CLOUD_API_PARAMS:
|
|
178
|
-
raise ValueError(
|
|
179
|
-
f"Unexpected argument `{param}` is "
|
|
180
|
-
"input into SambaCloud API."
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
else:
|
|
184
|
-
raise ValueError(
|
|
185
|
-
f"{self._url} is not supported, please check the url to the"
|
|
186
|
-
" SambaNova service"
|
|
187
|
-
)
|
|
188
|
-
|
|
189
176
|
@observe(as_type="generation")
|
|
190
177
|
async def _arun( # type: ignore[misc]
|
|
191
178
|
self,
|