camel-ai 0.2.69a1__py3-none-any.whl → 0.2.69a2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of camel-ai might be problematic. Click here for more details.
- camel/__init__.py +1 -1
- camel/societies/workforce/single_agent_worker.py +11 -4
- camel/societies/workforce/workforce.py +7 -2
- camel/toolkits/function_tool.py +4 -3
- camel/toolkits/video_analysis_toolkit.py +77 -3
- {camel_ai-0.2.69a1.dist-info → camel_ai-0.2.69a2.dist-info}/METADATA +5 -1
- {camel_ai-0.2.69a1.dist-info → camel_ai-0.2.69a2.dist-info}/RECORD +9 -9
- {camel_ai-0.2.69a1.dist-info → camel_ai-0.2.69a2.dist-info}/WHEEL +0 -0
- {camel_ai-0.2.69a1.dist-info → camel_ai-0.2.69a2.dist-info}/licenses/LICENSE +0 -0
camel/__init__.py
CHANGED
|
@@ -286,8 +286,8 @@ class SingleAgentWorker(Worker):
|
|
|
286
286
|
)
|
|
287
287
|
except Exception as e:
|
|
288
288
|
print(
|
|
289
|
-
f"{Fore.RED}Error
|
|
290
|
-
f"
|
|
289
|
+
f"{Fore.RED}Error processing task {task.id}: "
|
|
290
|
+
f"{type(e).__name__}: {e}{Fore.RESET}"
|
|
291
291
|
)
|
|
292
292
|
return TaskState.FAILED
|
|
293
293
|
finally:
|
|
@@ -336,8 +336,15 @@ class SingleAgentWorker(Worker):
|
|
|
336
336
|
|
|
337
337
|
print(f"======\n{Fore.GREEN}Reply from {self}:{Fore.RESET}")
|
|
338
338
|
|
|
339
|
-
|
|
340
|
-
|
|
339
|
+
try:
|
|
340
|
+
result_dict = json.loads(response.msg.content)
|
|
341
|
+
task_result = TaskResult(**result_dict)
|
|
342
|
+
except json.JSONDecodeError as e:
|
|
343
|
+
print(
|
|
344
|
+
f"{Fore.RED}JSON parsing error for task {task.id}: "
|
|
345
|
+
f"Invalid response format - {e}{Fore.RESET}"
|
|
346
|
+
)
|
|
347
|
+
return TaskState.FAILED
|
|
341
348
|
|
|
342
349
|
color = Fore.RED if task_result.failed else Fore.GREEN
|
|
343
350
|
print(
|
|
@@ -882,11 +882,16 @@ class Workforce(BaseNode):
|
|
|
882
882
|
self._task = task
|
|
883
883
|
self._state = WorkforceState.RUNNING
|
|
884
884
|
task.state = TaskState.FAILED # TODO: Add logic for OPEN
|
|
885
|
-
self._pending_tasks.append(task)
|
|
886
885
|
|
|
887
886
|
# Decompose the task into subtasks first
|
|
888
887
|
subtasks = self._decompose_task(task)
|
|
889
|
-
|
|
888
|
+
if subtasks:
|
|
889
|
+
# If decomposition happened, the original task becomes a container.
|
|
890
|
+
# We only execute its subtasks.
|
|
891
|
+
self._pending_tasks.extendleft(reversed(subtasks))
|
|
892
|
+
else:
|
|
893
|
+
# If no decomposition, execute the original task.
|
|
894
|
+
self._pending_tasks.append(task)
|
|
890
895
|
self.set_channel(TaskChannel())
|
|
891
896
|
|
|
892
897
|
# Save initial snapshot
|
camel/toolkits/function_tool.py
CHANGED
|
@@ -531,9 +531,10 @@ class FunctionTool:
|
|
|
531
531
|
param_dict = properties[param_name]
|
|
532
532
|
if "description" not in param_dict:
|
|
533
533
|
warnings.warn(
|
|
534
|
-
f"Parameter description is missing "
|
|
535
|
-
f"
|
|
536
|
-
f"
|
|
534
|
+
f"Parameter description is missing for the "
|
|
535
|
+
f"function '{openai_tool_schema['function']['name']}'. "
|
|
536
|
+
f"The parameter definition is {param_dict}. "
|
|
537
|
+
f"This may affect the quality of tool calling."
|
|
537
538
|
)
|
|
538
539
|
|
|
539
540
|
def get_openai_tool_schema(self) -> Dict[str, Any]:
|
|
@@ -17,6 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
|
|
18
18
|
import io
|
|
19
19
|
import os
|
|
20
|
+
import re
|
|
20
21
|
import tempfile
|
|
21
22
|
from pathlib import Path
|
|
22
23
|
from typing import List, Optional
|
|
@@ -41,6 +42,11 @@ VIDEO_QA_PROMPT = """
|
|
|
41
42
|
Analyze the provided video frames and corresponding audio transcription to \
|
|
42
43
|
answer the given question(s) thoroughly and accurately.
|
|
43
44
|
|
|
45
|
+
The transcriptions may come from two sources:
|
|
46
|
+
1. **Audio Transcription**: The spoken words in the video.
|
|
47
|
+
2. **Visual Text (OCR)**: Text extracted from the video frames (like \
|
|
48
|
+
captions, on-screen text, etc.).
|
|
49
|
+
|
|
44
50
|
Instructions:
|
|
45
51
|
1. Visual Analysis:
|
|
46
52
|
- Examine the video frames to identify visible entities.
|
|
@@ -49,11 +55,13 @@ such as size, color, shape, texture, or behavior.
|
|
|
49
55
|
- Note significant groupings, interactions, or contextual patterns \
|
|
50
56
|
relevant to the analysis.
|
|
51
57
|
|
|
52
|
-
2. Audio Integration:
|
|
58
|
+
2. Audio and Text Integration:
|
|
53
59
|
- Use the audio transcription to complement or clarify your visual \
|
|
54
60
|
observations.
|
|
61
|
+
- Use the visual text (OCR) to get exact textual information that may \
|
|
62
|
+
not be accurately readable from the images alone.
|
|
55
63
|
- Identify names, descriptions, or contextual hints in the \
|
|
56
|
-
|
|
64
|
+
transcriptions that help confirm or refine your visual analysis.
|
|
57
65
|
|
|
58
66
|
3. Detailed Reasoning and Justification:
|
|
59
67
|
- Provide a brief explanation of how you identified and distinguished \
|
|
@@ -65,7 +73,7 @@ your reasoning.
|
|
|
65
73
|
- Specify the total number of distinct species or object types \
|
|
66
74
|
identified in the video.
|
|
67
75
|
- Describe the defining characteristics and any supporting evidence \
|
|
68
|
-
from the video and transcription.
|
|
76
|
+
from the video and transcription sources.
|
|
69
77
|
|
|
70
78
|
5. Important Considerations:
|
|
71
79
|
- Pay close attention to subtle differences that could distinguish \
|
|
@@ -76,6 +84,9 @@ similar-looking species or objects
|
|
|
76
84
|
**Audio Transcription:**
|
|
77
85
|
{audio_transcription}
|
|
78
86
|
|
|
87
|
+
**Visual Text (OCR):**
|
|
88
|
+
{visual_text}
|
|
89
|
+
|
|
79
90
|
**Question:**
|
|
80
91
|
{question}
|
|
81
92
|
"""
|
|
@@ -96,6 +107,8 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
96
107
|
transcription using OpenAI's audio models. Requires a valid OpenAI
|
|
97
108
|
API key. When disabled, video analysis will be based solely on
|
|
98
109
|
visual content. (default: :obj:`False`)
|
|
110
|
+
use_ocr (bool, optional): Whether to enable OCR for extracting text
|
|
111
|
+
from video frames. (default: :obj:`False`)
|
|
99
112
|
frame_interval (float, optional): Interval in seconds between frames
|
|
100
113
|
to extract from the video. (default: :obj:`4.0`)
|
|
101
114
|
output_language (str, optional): The language for output responses.
|
|
@@ -113,6 +126,7 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
113
126
|
download_directory: Optional[str] = None,
|
|
114
127
|
model: Optional[BaseModelBackend] = None,
|
|
115
128
|
use_audio_transcription: bool = False,
|
|
129
|
+
use_ocr: bool = False,
|
|
116
130
|
frame_interval: float = 4.0,
|
|
117
131
|
output_language: str = "English",
|
|
118
132
|
cookies_path: Optional[str] = None,
|
|
@@ -122,6 +136,7 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
122
136
|
self._cleanup = download_directory is None
|
|
123
137
|
self._temp_files: list[str] = [] # Track temporary files for cleanup
|
|
124
138
|
self._use_audio_transcription = use_audio_transcription
|
|
139
|
+
self._use_ocr = use_ocr
|
|
125
140
|
self.output_language = output_language
|
|
126
141
|
self.frame_interval = frame_interval
|
|
127
142
|
|
|
@@ -211,6 +226,53 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
211
226
|
f"{self._download_directory}: {e}"
|
|
212
227
|
)
|
|
213
228
|
|
|
229
|
+
@dependencies_required("pytesseract", "cv2", "numpy")
|
|
230
|
+
def _extract_text_from_frame(self, frame: Image.Image) -> str:
|
|
231
|
+
r"""Extract text from a video frame using OCR.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
frame (Image.Image): PIL image frame to process.
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
str: Extracted text from the frame.
|
|
238
|
+
"""
|
|
239
|
+
import cv2
|
|
240
|
+
import numpy as np
|
|
241
|
+
import pytesseract
|
|
242
|
+
|
|
243
|
+
try:
|
|
244
|
+
# Convert to OpenCV format for preprocessing
|
|
245
|
+
cv_image = cv2.cvtColor(np.array(frame), cv2.COLOR_RGB2BGR)
|
|
246
|
+
|
|
247
|
+
# Preprocessing for better OCR results
|
|
248
|
+
gray = cv2.cvtColor(cv_image, cv2.COLOR_BGR2GRAY)
|
|
249
|
+
blur = cv2.GaussianBlur(gray, (3, 3), 0)
|
|
250
|
+
_, threshold = cv2.threshold(
|
|
251
|
+
blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
# Convert back to PIL image for OCR
|
|
255
|
+
preprocessed_frame = Image.fromarray(threshold)
|
|
256
|
+
return pytesseract.image_to_string(preprocessed_frame).strip()
|
|
257
|
+
except Exception as e:
|
|
258
|
+
logger.error(f"OCR failed: {e}")
|
|
259
|
+
return ""
|
|
260
|
+
|
|
261
|
+
def _process_extracted_text(self, text: str) -> str:
|
|
262
|
+
r"""Clean and format OCR-extracted text.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
text (str): Raw extracted OCR text.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
str: Cleaned and formatted text.
|
|
269
|
+
"""
|
|
270
|
+
# Filter irrelevant characters and noise
|
|
271
|
+
text = re.sub(r'[^\w\s,.?!:;\'"()-]', '', text)
|
|
272
|
+
# Remove excessive whitespace
|
|
273
|
+
text = re.sub(r'\s+', ' ', text).strip()
|
|
274
|
+
return text
|
|
275
|
+
|
|
214
276
|
def _extract_audio_from_video(
|
|
215
277
|
self, video_path: str, output_format: str = "mp3"
|
|
216
278
|
) -> str:
|
|
@@ -511,9 +573,21 @@ class VideoAnalysisToolkit(BaseToolkit):
|
|
|
511
573
|
audio_path = self._extract_audio_from_video(video_path)
|
|
512
574
|
audio_transcript = self._transcribe_audio(audio_path)
|
|
513
575
|
|
|
576
|
+
# Extract visual text with OCR
|
|
577
|
+
visual_text = ""
|
|
514
578
|
video_frames = self._extract_keyframes(video_path)
|
|
579
|
+
# Build visual text only if OCR is enabled
|
|
580
|
+
if self._use_ocr:
|
|
581
|
+
for frame in video_frames:
|
|
582
|
+
text = self._extract_text_from_frame(frame)
|
|
583
|
+
processed = self._process_extracted_text(text)
|
|
584
|
+
if processed:
|
|
585
|
+
visual_text += processed + "\n"
|
|
586
|
+
visual_text = visual_text.strip() or "No visual text detected."
|
|
587
|
+
|
|
515
588
|
prompt = VIDEO_QA_PROMPT.format(
|
|
516
589
|
audio_transcription=audio_transcript,
|
|
590
|
+
visual_text=visual_text,
|
|
517
591
|
question=question,
|
|
518
592
|
)
|
|
519
593
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: camel-ai
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.69a2
|
|
4
4
|
Summary: Communicative Agents for AI Society Study
|
|
5
5
|
Project-URL: Homepage, https://www.camel-ai.org/
|
|
6
6
|
Project-URL: Repository, https://github.com/camel-ai/camel
|
|
@@ -99,6 +99,7 @@ Requires-Dist: pymupdf<2,>=1.22.5; extra == 'all'
|
|
|
99
99
|
Requires-Dist: pyobvector>=0.1.18; extra == 'all'
|
|
100
100
|
Requires-Dist: pyowm<4,>=3.3.0; extra == 'all'
|
|
101
101
|
Requires-Dist: pytelegrambotapi<5,>=4.18.0; extra == 'all'
|
|
102
|
+
Requires-Dist: pytesseract>=0.3.13; extra == 'all'
|
|
102
103
|
Requires-Dist: pytest-asyncio<0.24,>=0.23.0; extra == 'all'
|
|
103
104
|
Requires-Dist: pytest-cov<5,>=4; extra == 'all'
|
|
104
105
|
Requires-Dist: pytest<8,>=7; extra == 'all'
|
|
@@ -226,6 +227,7 @@ Provides-Extra: media-tools
|
|
|
226
227
|
Requires-Dist: ffmpeg-python<0.3,>=0.2.0; extra == 'media-tools'
|
|
227
228
|
Requires-Dist: imageio[pyav]<3,>=2.34.2; extra == 'media-tools'
|
|
228
229
|
Requires-Dist: pydub<0.26,>=0.25.1; extra == 'media-tools'
|
|
230
|
+
Requires-Dist: pytesseract>=0.3.13; extra == 'media-tools'
|
|
229
231
|
Requires-Dist: scenedetect>=0.6.5.2; extra == 'media-tools'
|
|
230
232
|
Requires-Dist: yt-dlp<2025,>=2024.11.4; extra == 'media-tools'
|
|
231
233
|
Provides-Extra: model-platforms
|
|
@@ -252,6 +254,7 @@ Requires-Dist: ffmpeg-python<0.3,>=0.2.0; extra == 'owl'
|
|
|
252
254
|
Requires-Dist: fpdf>=1.7.2; extra == 'owl'
|
|
253
255
|
Requires-Dist: html2text>=2024.2.26; extra == 'owl'
|
|
254
256
|
Requires-Dist: imageio[pyav]<3,>=2.34.2; extra == 'owl'
|
|
257
|
+
Requires-Dist: markitdown==0.1.1; extra == 'owl'
|
|
255
258
|
Requires-Dist: mcp-server-fetch==2025.1.17; extra == 'owl'
|
|
256
259
|
Requires-Dist: mcp-simple-arxiv==0.2.2; extra == 'owl'
|
|
257
260
|
Requires-Dist: newspaper3k<0.3,>=0.2.8; extra == 'owl'
|
|
@@ -266,6 +269,7 @@ Requires-Dist: pyautogui<0.10,>=0.9.54; extra == 'owl'
|
|
|
266
269
|
Requires-Dist: pydub<0.26,>=0.25.1; extra == 'owl'
|
|
267
270
|
Requires-Dist: pylatex>=1.4.2; extra == 'owl'
|
|
268
271
|
Requires-Dist: pymupdf<2,>=1.22.5; extra == 'owl'
|
|
272
|
+
Requires-Dist: pytesseract>=0.3.13; extra == 'owl'
|
|
269
273
|
Requires-Dist: python-dotenv<2,>=1.0.0; extra == 'owl'
|
|
270
274
|
Requires-Dist: python-pptx>=1.0.2; extra == 'owl'
|
|
271
275
|
Requires-Dist: requests-oauthlib<2,>=1.3.1; extra == 'owl'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
camel/__init__.py,sha256=
|
|
1
|
+
camel/__init__.py,sha256=WMfYI5vXSsv0CSAsfpSAJsK0QJ-RqKRd4nHzG-3LE7Q,901
|
|
2
2
|
camel/generators.py,sha256=JRqj9_m1PF4qT6UtybzTQ-KBT9MJQt18OAAYvQ_fr2o,13844
|
|
3
3
|
camel/human.py,sha256=Xg8x1cS5KK4bQ1SDByiHZnzsRpvRP-KZViNvmu38xo4,5475
|
|
4
4
|
camel/logger.py,sha256=rZVeOVYuQ9RYJ5Tqyv0usqy0g4zaVEq4qSfZ9nd2640,5755
|
|
@@ -273,11 +273,11 @@ camel/societies/workforce/__init__.py,sha256=bkTI-PE-MSK9AQ2V2gR6cR2WY-R7Jqy_NmX
|
|
|
273
273
|
camel/societies/workforce/base.py,sha256=z2DmbTP5LL5-aCAAqglznQqCLfPmnyM5zD3w6jjtsb8,2175
|
|
274
274
|
camel/societies/workforce/prompts.py,sha256=_l7OUkzH5p7KOd8HMZle9zB9W3jKza_Yb_6elFKiZ2s,11813
|
|
275
275
|
camel/societies/workforce/role_playing_worker.py,sha256=pWPCtkLx-xbc4SWyZBfMwvWr-R5ZpANhN7g6PDuH8Po,7615
|
|
276
|
-
camel/societies/workforce/single_agent_worker.py,sha256=
|
|
276
|
+
camel/societies/workforce/single_agent_worker.py,sha256=5lF9zzxDJMCtELh6Y407m_D2bMAXMsY3yvY3_Bssd5A,14704
|
|
277
277
|
camel/societies/workforce/task_channel.py,sha256=uqQQI67Tr4awbR4bjZXdx8_4gL6-ON5IjQk_H_ryqT4,7431
|
|
278
278
|
camel/societies/workforce/utils.py,sha256=Gjlz7pLo4r1b6iNHtlIMxeEuat4d6tEEQMI40JAU3kY,6190
|
|
279
279
|
camel/societies/workforce/worker.py,sha256=36tkOyz4G2wfBdrFjt9NBPXsx4UbE6uL5on8sP2aoqk,6414
|
|
280
|
-
camel/societies/workforce/workforce.py,sha256=
|
|
280
|
+
camel/societies/workforce/workforce.py,sha256=xiWLSoRHOC1yz9WK0uXImwQkblr7XIJ6BXdNrEUf7Rk,88755
|
|
281
281
|
camel/societies/workforce/workforce_logger.py,sha256=2xGMMYQPphC5WlPbgWWp9SEY2hGpP-GkhgsNC19irns,24237
|
|
282
282
|
camel/storages/__init__.py,sha256=bFpvvAS2QyZoIr-tnwhMWsZRL411kIRq6IMUHcI7KHs,1989
|
|
283
283
|
camel/storages/graph_storages/__init__.py,sha256=G29BNn651C0WTOpjCl4QnVM-4B9tcNh8DdmsCiONH8Y,948
|
|
@@ -327,7 +327,7 @@ camel/toolkits/dappier_toolkit.py,sha256=OEHOYXX_oXhgbVtWYAy13nO9uXf9i5qEXSwY4Pe
|
|
|
327
327
|
camel/toolkits/data_commons_toolkit.py,sha256=aHZUSL1ACpnYGaf1rE2csVKTmXTmN8lMGRUBYhZ_YEk,14168
|
|
328
328
|
camel/toolkits/excel_toolkit.py,sha256=DSjBXl24_LrJubGFFmB_vqliKzzWTbT1TH309YQVUO8,6653
|
|
329
329
|
camel/toolkits/file_write_toolkit.py,sha256=i1CivjvqTpHakYK_EynNvNikjZZYsusxkjT2v-f9EYc,16473
|
|
330
|
-
camel/toolkits/function_tool.py,sha256=
|
|
330
|
+
camel/toolkits/function_tool.py,sha256=xCDzjxTRCVj_kmbnMFBuwK-3NuzM4JNe_kv9HLtjnIA,33644
|
|
331
331
|
camel/toolkits/github_toolkit.py,sha256=iUyRrjWGAW_iljZVfNyfkm1Vi55wJxK6PsDAQs9pOag,13099
|
|
332
332
|
camel/toolkits/google_calendar_toolkit.py,sha256=E-sdgdbtNBs_CXbhht9t1dsVr4DsTr5NguHkx4fvSmc,15410
|
|
333
333
|
camel/toolkits/google_maps_toolkit.py,sha256=WTnkURpGri9KcY5OwV7AJJHOzmpu5RNmYE1QCVqvwWM,12023
|
|
@@ -365,7 +365,7 @@ camel/toolkits/task_planning_toolkit.py,sha256=Ttw9fHae4omGC1SA-6uaeXVHJ1YkwiVlo
|
|
|
365
365
|
camel/toolkits/terminal_toolkit.py,sha256=gupuTvNkwnFzcFwDB_irSJ9-dXRr8yEAsYq5ChEkkHg,37230
|
|
366
366
|
camel/toolkits/thinking_toolkit.py,sha256=nZYLvKWIx2BM1DYu69I9B5EISAG7aYcLYXKv9663BVk,8000
|
|
367
367
|
camel/toolkits/twitter_toolkit.py,sha256=Px4N8aUxUzy01LhGSWkdrC2JgwKkrY3cvxgMeJ2XYfU,15939
|
|
368
|
-
camel/toolkits/video_analysis_toolkit.py,sha256=
|
|
368
|
+
camel/toolkits/video_analysis_toolkit.py,sha256=Wh08MAVvs3PtgXN88Sk0TXYaGfVmQAol8FPCXMPPpIM,23375
|
|
369
369
|
camel/toolkits/video_download_toolkit.py,sha256=jBb2SQ9OA5HIuGF7FbNQ0KrvvwMWPxUnvUyCHjbHuQQ,7501
|
|
370
370
|
camel/toolkits/weather_toolkit.py,sha256=fs9x9aC38Wsvni6A4PPpbRX6-aBnZiqs2Jix39yoULU,7413
|
|
371
371
|
camel/toolkits/whatsapp_toolkit.py,sha256=udUQXkXyeWsmrUlOJZsGBhHtc_jhB05Axe_TchhibsU,5760
|
|
@@ -431,7 +431,7 @@ camel/verifiers/math_verifier.py,sha256=tA1D4S0sm8nsWISevxSN0hvSVtIUpqmJhzqfbuMo
|
|
|
431
431
|
camel/verifiers/models.py,sha256=GdxYPr7UxNrR1577yW4kyroRcLGfd-H1GXgv8potDWU,2471
|
|
432
432
|
camel/verifiers/physics_verifier.py,sha256=c1grrRddcrVN7szkxhv2QirwY9viIRSITWeWFF5HmLs,30187
|
|
433
433
|
camel/verifiers/python_verifier.py,sha256=ogTz77wODfEcDN4tMVtiSkRQyoiZbHPY2fKybn59lHw,20558
|
|
434
|
-
camel_ai-0.2.
|
|
435
|
-
camel_ai-0.2.
|
|
436
|
-
camel_ai-0.2.
|
|
437
|
-
camel_ai-0.2.
|
|
434
|
+
camel_ai-0.2.69a2.dist-info/METADATA,sha256=5FBG-fY28g9tYIZIpxESs4biHcejU3mVLUQY5sMepWk,45047
|
|
435
|
+
camel_ai-0.2.69a2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
436
|
+
camel_ai-0.2.69a2.dist-info/licenses/LICENSE,sha256=id0nB2my5kG0xXeimIu5zZrbHLS6EQvxvkKkzIHaT2k,11343
|
|
437
|
+
camel_ai-0.2.69a2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|