agno 1.7.8__py3-none-any.whl → 1.7.9__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.
- agno/agent/agent.py +32 -26
- agno/document/reader/pdf_reader.py +239 -136
- agno/run/response.py +10 -0
- agno/run/team.py +10 -0
- agno/team/team.py +24 -13
- agno/tools/aws_lambda.py +10 -0
- agno/vectordb/lancedb/lance_db.py +10 -2
- agno/vectordb/pgvector/pgvector.py +3 -0
- {agno-1.7.8.dist-info → agno-1.7.9.dist-info}/METADATA +1 -1
- {agno-1.7.8.dist-info → agno-1.7.9.dist-info}/RECORD +14 -14
- {agno-1.7.8.dist-info → agno-1.7.9.dist-info}/WHEEL +0 -0
- {agno-1.7.8.dist-info → agno-1.7.9.dist-info}/entry_points.txt +0 -0
- {agno-1.7.8.dist-info → agno-1.7.9.dist-info}/licenses/LICENSE +0 -0
- {agno-1.7.8.dist-info → agno-1.7.9.dist-info}/top_level.txt +0 -0
agno/agent/agent.py
CHANGED
|
@@ -893,7 +893,7 @@ class Agent:
|
|
|
893
893
|
):
|
|
894
894
|
yield event
|
|
895
895
|
else:
|
|
896
|
-
from agno.
|
|
896
|
+
from agno.run.response import IntermediateRunResponseContentEvent, RunResponseContentEvent
|
|
897
897
|
|
|
898
898
|
for event in self._handle_model_response_stream(
|
|
899
899
|
run_response=run_response,
|
|
@@ -903,7 +903,10 @@ class Agent:
|
|
|
903
903
|
):
|
|
904
904
|
if isinstance(event, RunResponseContentEvent):
|
|
905
905
|
if stream_intermediate_steps:
|
|
906
|
-
yield
|
|
906
|
+
yield IntermediateRunResponseContentEvent(
|
|
907
|
+
content=event.content,
|
|
908
|
+
content_type=event.content_type,
|
|
909
|
+
)
|
|
907
910
|
else:
|
|
908
911
|
yield event
|
|
909
912
|
|
|
@@ -1331,7 +1334,7 @@ class Agent:
|
|
|
1331
1334
|
):
|
|
1332
1335
|
yield event
|
|
1333
1336
|
else:
|
|
1334
|
-
from agno.
|
|
1337
|
+
from agno.run.response import IntermediateRunResponseContentEvent, RunResponseContentEvent
|
|
1335
1338
|
|
|
1336
1339
|
async for event in self._ahandle_model_response_stream(
|
|
1337
1340
|
run_response=run_response,
|
|
@@ -1341,7 +1344,10 @@ class Agent:
|
|
|
1341
1344
|
):
|
|
1342
1345
|
if isinstance(event, RunResponseContentEvent):
|
|
1343
1346
|
if stream_intermediate_steps:
|
|
1344
|
-
yield
|
|
1347
|
+
yield IntermediateRunResponseContentEvent(
|
|
1348
|
+
content=event.content,
|
|
1349
|
+
content_type=event.content_type,
|
|
1350
|
+
)
|
|
1345
1351
|
else:
|
|
1346
1352
|
yield event
|
|
1347
1353
|
|
|
@@ -4973,9 +4979,26 @@ class Agent:
|
|
|
4973
4979
|
|
|
4974
4980
|
run_messages.messages += history_copy
|
|
4975
4981
|
|
|
4976
|
-
# 4.Add
|
|
4982
|
+
# 4. Add messages to run_messages if provided
|
|
4983
|
+
if messages is not None and len(messages) > 0:
|
|
4984
|
+
for _m in messages:
|
|
4985
|
+
if isinstance(_m, Message):
|
|
4986
|
+
run_messages.messages.append(_m)
|
|
4987
|
+
if run_messages.extra_messages is None:
|
|
4988
|
+
run_messages.extra_messages = []
|
|
4989
|
+
run_messages.extra_messages.append(_m)
|
|
4990
|
+
elif isinstance(_m, dict):
|
|
4991
|
+
try:
|
|
4992
|
+
run_messages.messages.append(Message.model_validate(_m))
|
|
4993
|
+
if run_messages.extra_messages is None:
|
|
4994
|
+
run_messages.extra_messages = []
|
|
4995
|
+
run_messages.extra_messages.append(Message.model_validate(_m))
|
|
4996
|
+
except Exception as e:
|
|
4997
|
+
log_warning(f"Failed to validate message: {e}")
|
|
4998
|
+
|
|
4999
|
+
# 5. Add user message to run_messages
|
|
4977
5000
|
user_message: Optional[Message] = None
|
|
4978
|
-
#
|
|
5001
|
+
# 5.1 Build user message if message is None, str or list
|
|
4979
5002
|
if message is None or isinstance(message, str) or isinstance(message, list):
|
|
4980
5003
|
user_message = self.get_user_message(
|
|
4981
5004
|
message=message,
|
|
@@ -4986,16 +5009,16 @@ class Agent:
|
|
|
4986
5009
|
knowledge_filters=knowledge_filters,
|
|
4987
5010
|
**kwargs,
|
|
4988
5011
|
)
|
|
4989
|
-
#
|
|
5012
|
+
# 5.2 If message is provided as a Message, use it directly
|
|
4990
5013
|
elif isinstance(message, Message):
|
|
4991
5014
|
user_message = message
|
|
4992
|
-
#
|
|
5015
|
+
# 5.3 If message is provided as a dict, try to validate it as a Message
|
|
4993
5016
|
elif isinstance(message, dict):
|
|
4994
5017
|
try:
|
|
4995
5018
|
user_message = Message.model_validate(message)
|
|
4996
5019
|
except Exception as e:
|
|
4997
5020
|
log_warning(f"Failed to validate message: {e}")
|
|
4998
|
-
#
|
|
5021
|
+
# 5.4 If message is provided as a BaseModel, convert it to a Message
|
|
4999
5022
|
elif isinstance(message, BaseModel):
|
|
5000
5023
|
try:
|
|
5001
5024
|
# Create a user message with the BaseModel content
|
|
@@ -5008,23 +5031,6 @@ class Agent:
|
|
|
5008
5031
|
run_messages.user_message = user_message
|
|
5009
5032
|
run_messages.messages.append(user_message)
|
|
5010
5033
|
|
|
5011
|
-
# 5. Add messages to run_messages if provided
|
|
5012
|
-
if messages is not None and len(messages) > 0:
|
|
5013
|
-
for _m in messages:
|
|
5014
|
-
if isinstance(_m, Message):
|
|
5015
|
-
run_messages.messages.append(_m)
|
|
5016
|
-
if run_messages.extra_messages is None:
|
|
5017
|
-
run_messages.extra_messages = []
|
|
5018
|
-
run_messages.extra_messages.append(_m)
|
|
5019
|
-
elif isinstance(_m, dict):
|
|
5020
|
-
try:
|
|
5021
|
-
run_messages.messages.append(Message.model_validate(_m))
|
|
5022
|
-
if run_messages.extra_messages is None:
|
|
5023
|
-
run_messages.extra_messages = []
|
|
5024
|
-
run_messages.extra_messages.append(Message.model_validate(_m))
|
|
5025
|
-
except Exception as e:
|
|
5026
|
-
log_warning(f"Failed to validate message: {e}")
|
|
5027
|
-
|
|
5028
5034
|
return run_messages
|
|
5029
5035
|
|
|
5030
5036
|
def get_continue_run_messages(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import re
|
|
2
3
|
from pathlib import Path
|
|
3
|
-
from typing import IO, Any, List, Optional, Union
|
|
4
|
+
from typing import IO, Any, List, Optional, Tuple, Union
|
|
4
5
|
from uuid import uuid4
|
|
5
6
|
|
|
6
7
|
from agno.document.base import Document
|
|
@@ -15,7 +16,13 @@ except ImportError:
|
|
|
15
16
|
raise ImportError("`pypdf` not installed. Please install it via `pip install pypdf`.")
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
PAGE_START_NUMBERING_FORMAT_DEFAULT = "<start page {page_nr}>"
|
|
20
|
+
PAGE_END_NUMBERING_FORMAT_DEFAULT = "<end page {page_nr}>"
|
|
21
|
+
PAGE_NUMBERING_CORRECTNESS_RATIO_FOR_REMOVAL = 0.4
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _ocr_reader(page: Any) -> str:
|
|
25
|
+
"""A single PDF page object."""
|
|
19
26
|
try:
|
|
20
27
|
import rapidocr_onnxruntime as rapidocr
|
|
21
28
|
except ImportError:
|
|
@@ -23,7 +30,6 @@ def process_image_page(doc_name: str, page_number: int, page: Any) -> Document:
|
|
|
23
30
|
"`rapidocr_onnxruntime` not installed. Please install it via `pip install rapidocr_onnxruntime`."
|
|
24
31
|
)
|
|
25
32
|
ocr = rapidocr.RapidOCR()
|
|
26
|
-
page_text = page.extract_text() or ""
|
|
27
33
|
images_text_list = []
|
|
28
34
|
|
|
29
35
|
# Extract and process images
|
|
@@ -34,22 +40,13 @@ def process_image_page(doc_name: str, page_number: int, page: Any) -> Document:
|
|
|
34
40
|
ocr_result, elapse = ocr(image_data)
|
|
35
41
|
|
|
36
42
|
# Extract text from OCR result
|
|
37
|
-
if ocr_result
|
|
38
|
-
images_text_list += [item[1] for item in ocr_result]
|
|
43
|
+
images_text_list += [item[1] for item in ocr_result] if ocr_result else []
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
content = page_text + "\n" + images_text
|
|
42
|
-
|
|
43
|
-
# Append the document
|
|
44
|
-
return Document(
|
|
45
|
-
name=doc_name,
|
|
46
|
-
id=str(uuid4()),
|
|
47
|
-
meta_data={"page": page_number},
|
|
48
|
-
content=content,
|
|
49
|
-
)
|
|
45
|
+
return "\n".join(images_text_list)
|
|
50
46
|
|
|
51
47
|
|
|
52
|
-
async def
|
|
48
|
+
async def _async_ocr_reader(page: Any) -> str:
|
|
49
|
+
"""page: A single PDF page object."""
|
|
53
50
|
try:
|
|
54
51
|
import rapidocr_onnxruntime as rapidocr
|
|
55
52
|
except ImportError:
|
|
@@ -58,9 +55,6 @@ async def async_process_image_page(doc_name: str, page_number: int, page: Any) -
|
|
|
58
55
|
)
|
|
59
56
|
ocr = rapidocr.RapidOCR()
|
|
60
57
|
|
|
61
|
-
page_text = page.extract_text() or ""
|
|
62
|
-
images_text_list: List = []
|
|
63
|
-
|
|
64
58
|
# Process images in parallel
|
|
65
59
|
async def process_image(image_data: bytes) -> List[str]:
|
|
66
60
|
ocr_result, _ = ocr(image_data)
|
|
@@ -69,27 +63,221 @@ async def async_process_image_page(doc_name: str, page_number: int, page: Any) -
|
|
|
69
63
|
image_tasks = [process_image(image.data) for image in page.images]
|
|
70
64
|
images_results = await asyncio.gather(*image_tasks)
|
|
71
65
|
|
|
66
|
+
images_text_list: List = []
|
|
72
67
|
for result in images_results:
|
|
73
68
|
images_text_list.extend(result)
|
|
74
69
|
|
|
75
70
|
images_text = "\n".join(images_text_list)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
71
|
+
return images_text
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _clean_page_numbers(
|
|
75
|
+
page_content_list: List[str],
|
|
76
|
+
extra_content: List[str] = [],
|
|
77
|
+
page_start_numbering_format: str = PAGE_START_NUMBERING_FORMAT_DEFAULT,
|
|
78
|
+
page_end_numbering_format: str = PAGE_END_NUMBERING_FORMAT_DEFAULT,
|
|
79
|
+
) -> Tuple[List[str], Optional[int]]:
|
|
80
|
+
f"""
|
|
81
|
+
Identifies and removes or reformats page numbers from a list of PDF page contents, based on the most consistent sequential numbering.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
page_content_list (List[str]): A list of strings where each string represents the content of a PDF page.
|
|
85
|
+
extra_content (List[str]): A list of strings where each string will be appended after the main content. Can be used for appending image information.
|
|
86
|
+
page_start_numbering_format (str): A format string to prepend to the page content, with `{{page_nr}}` as a placeholder for the page number.
|
|
87
|
+
Defaults to {PAGE_START_NUMBERING_FORMAT_DEFAULT}. Make it an empty string to remove the page number.
|
|
88
|
+
page_end_numbering_format (str): A format string to append to the page content, with `{{page_nr}}` as a placeholder for the page number.
|
|
89
|
+
Defaults to {PAGE_END_NUMBERING_FORMAT_DEFAULT}. Make it an empty string to remove the page number.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
List[str]: The list of page contents with page numbers removed or reformatted based on the detected sequence.
|
|
93
|
+
Optional[Int]: The shift for the page numbering. Can be (-2, -1, 0, 1, 2).
|
|
94
|
+
|
|
95
|
+
Notes:
|
|
96
|
+
- The function scans for page numbers using a regular expression that matches digits at the start or end of a string.
|
|
97
|
+
- It evaluates several potential starting points for numbering (-2, -1, 0, 1, 2 shifts) to determine the most consistent sequence.
|
|
98
|
+
- If at least a specified ratio of pages (defined by `PAGE_NUMBERING_CORRECTNESS_RATIO_FOR_REMOVAL`) has correct sequential numbering,
|
|
99
|
+
the page numbers are processed.
|
|
100
|
+
- If page numbers are found, the function will add formatted page numbers to each page's content if `page_start_numbering_format` or
|
|
101
|
+
`page_end_numbering_format` is provided.
|
|
102
|
+
"""
|
|
103
|
+
assert len(extra_content) == 0 or len(extra_content) == len(page_content_list), (
|
|
104
|
+
"Please provide an equally sized list of extra content if provided."
|
|
83
105
|
)
|
|
84
106
|
|
|
107
|
+
# Regex to match potential page numbers at the start or end of a string
|
|
108
|
+
page_number_regex = re.compile(r"^\s*(\d+)\s*|\s*(\d+)\s*$")
|
|
109
|
+
|
|
110
|
+
def find_page_number(content):
|
|
111
|
+
match = page_number_regex.search(content)
|
|
112
|
+
if match:
|
|
113
|
+
return int(match.group(1) or match.group(2))
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
page_numbers = [find_page_number(content) for content in page_content_list]
|
|
117
|
+
if all(x is None or x > 5 for x in page_numbers):
|
|
118
|
+
# This approach won't work reliably for higher page numbers.
|
|
119
|
+
return page_content_list, None
|
|
120
|
+
|
|
121
|
+
# Possible range shifts to detect page numbering
|
|
122
|
+
range_shifts = [-2, -1, 0, 1, 2]
|
|
123
|
+
best_match, best_correct_count, best_shift = _identify_best_page_sequence(page_numbers, range_shifts)
|
|
124
|
+
|
|
125
|
+
# Check if at least ..% of the pages have correct sequential numbering
|
|
126
|
+
if best_match and best_correct_count / len(page_numbers) >= PAGE_NUMBERING_CORRECTNESS_RATIO_FOR_REMOVAL:
|
|
127
|
+
# Remove the page numbers from the content
|
|
128
|
+
for i, expected_number in enumerate(best_match):
|
|
129
|
+
page_content_list[i] = re.sub(
|
|
130
|
+
rf"^\s*{expected_number}\s*|\s*{expected_number}\s*$", "", page_content_list[i]
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
page_start = (
|
|
134
|
+
page_start_numbering_format.format(page_nr=expected_number) + "\n"
|
|
135
|
+
if page_start_numbering_format
|
|
136
|
+
else ""
|
|
137
|
+
)
|
|
138
|
+
page_end = (
|
|
139
|
+
"\n" + page_end_numbering_format.format(page_nr=expected_number) if page_end_numbering_format else ""
|
|
140
|
+
)
|
|
141
|
+
extra_info = "\n" + extra_content[i] if extra_content else ""
|
|
142
|
+
|
|
143
|
+
# Add formatted page numbering if configured.
|
|
144
|
+
page_content_list[i] = page_start + page_content_list[i] + extra_info + page_end
|
|
145
|
+
else:
|
|
146
|
+
best_shift = None
|
|
147
|
+
|
|
148
|
+
return page_content_list, best_shift
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _identify_best_page_sequence(page_numbers, range_shifts):
|
|
152
|
+
best_match = None
|
|
153
|
+
best_shift: Optional[int] = None
|
|
154
|
+
best_correct_count = 0
|
|
155
|
+
|
|
156
|
+
for shift in range_shifts:
|
|
157
|
+
expected_numbers = [i + shift for i in range(len(page_numbers))]
|
|
158
|
+
# Check if expected number occurs (or that the expected "2" occurs in an incorrectly merged number like 25,
|
|
159
|
+
# where 2 is the page number and 5 is part of the PDF content).
|
|
160
|
+
correct_count = sum(
|
|
161
|
+
1
|
|
162
|
+
for actual, expected in zip(page_numbers, expected_numbers)
|
|
163
|
+
if actual == expected or str(actual).startswith(str(expected)) or str(actual).endswith(str(expected))
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
if correct_count > best_correct_count:
|
|
167
|
+
best_correct_count = correct_count
|
|
168
|
+
best_match = expected_numbers
|
|
169
|
+
best_shift = shift
|
|
170
|
+
|
|
171
|
+
return best_match, best_correct_count, best_shift
|
|
172
|
+
|
|
85
173
|
|
|
86
174
|
class BasePDFReader(Reader):
|
|
175
|
+
def __init__(
|
|
176
|
+
self,
|
|
177
|
+
split_on_pages: bool = True,
|
|
178
|
+
page_start_numbering_format: Optional[str] = None,
|
|
179
|
+
page_end_numbering_format: Optional[str] = None,
|
|
180
|
+
**kwargs,
|
|
181
|
+
):
|
|
182
|
+
if page_start_numbering_format is None:
|
|
183
|
+
page_start_numbering_format = PAGE_START_NUMBERING_FORMAT_DEFAULT
|
|
184
|
+
if page_end_numbering_format is None:
|
|
185
|
+
page_end_numbering_format = PAGE_END_NUMBERING_FORMAT_DEFAULT
|
|
186
|
+
|
|
187
|
+
self.split_on_pages = split_on_pages
|
|
188
|
+
self.page_start_numbering_format = page_start_numbering_format
|
|
189
|
+
self.page_end_numbering_format = page_end_numbering_format
|
|
190
|
+
|
|
191
|
+
super().__init__(**kwargs)
|
|
192
|
+
|
|
87
193
|
def _build_chunked_documents(self, documents: List[Document]) -> List[Document]:
|
|
88
194
|
chunked_documents: List[Document] = []
|
|
89
195
|
for document in documents:
|
|
90
196
|
chunked_documents.extend(self.chunk_document(document))
|
|
91
197
|
return chunked_documents
|
|
92
198
|
|
|
199
|
+
def _create_documents(self, pdf_content: List[str], doc_name: str, use_uuid_for_id: bool, page_number_shift):
|
|
200
|
+
if self.split_on_pages:
|
|
201
|
+
shift = page_number_shift if page_number_shift is not None else 1
|
|
202
|
+
documents: List[Document] = []
|
|
203
|
+
for page_number, page_content in enumerate(pdf_content, start=shift):
|
|
204
|
+
documents.append(
|
|
205
|
+
Document(
|
|
206
|
+
name=doc_name,
|
|
207
|
+
id=(str(uuid4()) if use_uuid_for_id else f"{doc_name}_{page_number}"),
|
|
208
|
+
meta_data={"page": page_number},
|
|
209
|
+
content=page_content,
|
|
210
|
+
)
|
|
211
|
+
)
|
|
212
|
+
else:
|
|
213
|
+
pdf_content_str = "\n".join(pdf_content)
|
|
214
|
+
document = Document(
|
|
215
|
+
name=doc_name,
|
|
216
|
+
id=str(uuid4()) if use_uuid_for_id else doc_name,
|
|
217
|
+
meta_data={},
|
|
218
|
+
content=pdf_content_str,
|
|
219
|
+
)
|
|
220
|
+
documents = [document]
|
|
221
|
+
|
|
222
|
+
if self.chunk:
|
|
223
|
+
return self._build_chunked_documents(documents)
|
|
224
|
+
|
|
225
|
+
return documents
|
|
226
|
+
|
|
227
|
+
def _pdf_reader_to_documents(
|
|
228
|
+
self,
|
|
229
|
+
doc_reader: DocumentReader,
|
|
230
|
+
doc_name,
|
|
231
|
+
read_images=False,
|
|
232
|
+
use_uuid_for_id=False,
|
|
233
|
+
):
|
|
234
|
+
pdf_content = []
|
|
235
|
+
pdf_images_text = []
|
|
236
|
+
for page in doc_reader.pages:
|
|
237
|
+
pdf_content.append(page.extract_text())
|
|
238
|
+
if read_images:
|
|
239
|
+
pdf_images_text.append(_ocr_reader(page))
|
|
240
|
+
|
|
241
|
+
pdf_content, shift = _clean_page_numbers(
|
|
242
|
+
page_content_list=pdf_content,
|
|
243
|
+
extra_content=pdf_images_text,
|
|
244
|
+
page_start_numbering_format=self.page_start_numbering_format,
|
|
245
|
+
page_end_numbering_format=self.page_end_numbering_format,
|
|
246
|
+
)
|
|
247
|
+
return self._create_documents(pdf_content, doc_name, use_uuid_for_id, shift)
|
|
248
|
+
|
|
249
|
+
async def _async_pdf_reader_to_documents(
|
|
250
|
+
self,
|
|
251
|
+
doc_reader: DocumentReader,
|
|
252
|
+
doc_name: str,
|
|
253
|
+
read_images=False,
|
|
254
|
+
use_uuid_for_id=False,
|
|
255
|
+
):
|
|
256
|
+
async def _read_pdf_page(page, read_images) -> Tuple[str, str]:
|
|
257
|
+
# We tried "asyncio.to_thread(page.extract_text)", but it maintains state internally, which leads to issues.
|
|
258
|
+
page_text = page.extract_text()
|
|
259
|
+
|
|
260
|
+
if read_images:
|
|
261
|
+
pdf_images_text = await _async_ocr_reader(page)
|
|
262
|
+
else:
|
|
263
|
+
pdf_images_text = ""
|
|
264
|
+
|
|
265
|
+
return page_text, pdf_images_text
|
|
266
|
+
|
|
267
|
+
# Process pages in parallel using asyncio.gather
|
|
268
|
+
pdf_content: List[Tuple[str, str]] = await asyncio.gather(
|
|
269
|
+
*[_read_pdf_page(page, read_images) for page in doc_reader.pages]
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
pdf_content_clean, shift = _clean_page_numbers(
|
|
273
|
+
page_content_list=[x[0] for x in pdf_content],
|
|
274
|
+
extra_content=[x[1] for x in pdf_content],
|
|
275
|
+
page_start_numbering_format=self.page_start_numbering_format,
|
|
276
|
+
page_end_numbering_format=self.page_end_numbering_format,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
return self._create_documents(pdf_content_clean, doc_name, use_uuid_for_id, shift)
|
|
280
|
+
|
|
93
281
|
|
|
94
282
|
class PDFReader(BasePDFReader):
|
|
95
283
|
"""Reader for PDF files"""
|
|
@@ -106,24 +294,13 @@ class PDFReader(BasePDFReader):
|
|
|
106
294
|
log_info(f"Reading: {doc_name}")
|
|
107
295
|
|
|
108
296
|
try:
|
|
109
|
-
|
|
297
|
+
pdf_reader = DocumentReader(pdf)
|
|
110
298
|
except PdfStreamError as e:
|
|
111
299
|
logger.error(f"Error reading PDF: {e}")
|
|
112
300
|
return []
|
|
113
301
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
documents.append(
|
|
117
|
-
Document(
|
|
118
|
-
name=doc_name,
|
|
119
|
-
id=str(uuid4()),
|
|
120
|
-
meta_data={"page": page_number},
|
|
121
|
-
content=page.extract_text(),
|
|
122
|
-
)
|
|
123
|
-
)
|
|
124
|
-
if self.chunk:
|
|
125
|
-
return self._build_chunked_documents(documents)
|
|
126
|
-
return documents
|
|
302
|
+
# Read and chunk.
|
|
303
|
+
return self._pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=True)
|
|
127
304
|
|
|
128
305
|
async def async_read(self, pdf: Union[str, Path, IO[Any]]) -> List[Document]:
|
|
129
306
|
try:
|
|
@@ -137,30 +314,13 @@ class PDFReader(BasePDFReader):
|
|
|
137
314
|
log_info(f"Reading: {doc_name}")
|
|
138
315
|
|
|
139
316
|
try:
|
|
140
|
-
|
|
317
|
+
pdf_reader = DocumentReader(pdf)
|
|
141
318
|
except PdfStreamError as e:
|
|
142
319
|
logger.error(f"Error reading PDF: {e}")
|
|
143
320
|
return []
|
|
144
321
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
name=doc_name,
|
|
148
|
-
id=str(uuid4()),
|
|
149
|
-
meta_data={"page": page_number},
|
|
150
|
-
content=page.extract_text(),
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
# Process pages in parallel using asyncio.gather
|
|
154
|
-
documents = await asyncio.gather(
|
|
155
|
-
*[
|
|
156
|
-
_process_document(doc_name, page_number, page)
|
|
157
|
-
for page_number, page in enumerate(doc_reader.pages, start=1)
|
|
158
|
-
]
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
if self.chunk:
|
|
162
|
-
return self._build_chunked_documents(documents)
|
|
163
|
-
return documents
|
|
322
|
+
# Read and chunk.
|
|
323
|
+
return await self._async_pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=True)
|
|
164
324
|
|
|
165
325
|
|
|
166
326
|
class PDFUrlReader(BasePDFReader):
|
|
@@ -182,21 +342,10 @@ class PDFUrlReader(BasePDFReader):
|
|
|
182
342
|
response = fetch_with_retry(url, proxy=self.proxy)
|
|
183
343
|
|
|
184
344
|
doc_name = url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
documents.append(
|
|
190
|
-
Document(
|
|
191
|
-
name=doc_name,
|
|
192
|
-
id=f"{doc_name}_{page_number}",
|
|
193
|
-
meta_data={"page": page_number},
|
|
194
|
-
content=page.extract_text(),
|
|
195
|
-
)
|
|
196
|
-
)
|
|
197
|
-
if self.chunk:
|
|
198
|
-
return self._build_chunked_documents(documents)
|
|
199
|
-
return documents
|
|
345
|
+
pdf_reader = DocumentReader(BytesIO(response.content))
|
|
346
|
+
|
|
347
|
+
# Read and chunk.
|
|
348
|
+
return self._pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=False)
|
|
200
349
|
|
|
201
350
|
async def async_read(self, url: str) -> List[Document]:
|
|
202
351
|
if not url:
|
|
@@ -213,27 +362,10 @@ class PDFUrlReader(BasePDFReader):
|
|
|
213
362
|
response = await async_fetch_with_retry(url, client=client)
|
|
214
363
|
|
|
215
364
|
doc_name = url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
async def _process_document(doc_name: str, page_number: int, page: Any) -> Document:
|
|
219
|
-
return Document(
|
|
220
|
-
name=doc_name,
|
|
221
|
-
id=f"{doc_name}_{page_number}",
|
|
222
|
-
meta_data={"page": page_number},
|
|
223
|
-
content=page.extract_text(),
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
# Process pages in parallel using asyncio.gather
|
|
227
|
-
documents = await asyncio.gather(
|
|
228
|
-
*[
|
|
229
|
-
_process_document(doc_name, page_number, page)
|
|
230
|
-
for page_number, page in enumerate(doc_reader.pages, start=1)
|
|
231
|
-
]
|
|
232
|
-
)
|
|
365
|
+
pdf_reader = DocumentReader(BytesIO(response.content))
|
|
233
366
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
return documents
|
|
367
|
+
# Read and chunk.
|
|
368
|
+
return await self._async_pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=False)
|
|
237
369
|
|
|
238
370
|
|
|
239
371
|
class PDFImageReader(BasePDFReader):
|
|
@@ -252,16 +384,10 @@ class PDFImageReader(BasePDFReader):
|
|
|
252
384
|
doc_name = "pdf"
|
|
253
385
|
|
|
254
386
|
log_info(f"Reading: {doc_name}")
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
documents = []
|
|
258
|
-
for page_number, page in enumerate(doc_reader.pages, start=1):
|
|
259
|
-
documents.append(process_image_page(doc_name, page_number, page))
|
|
260
|
-
|
|
261
|
-
if self.chunk:
|
|
262
|
-
return self._build_chunked_documents(documents)
|
|
387
|
+
pdf_reader = DocumentReader(pdf)
|
|
263
388
|
|
|
264
|
-
|
|
389
|
+
# Read and chunk.
|
|
390
|
+
return self._pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
|
|
265
391
|
|
|
266
392
|
async def async_read(self, pdf: Union[str, Path, IO[Any]]) -> List[Document]:
|
|
267
393
|
if not pdf:
|
|
@@ -276,18 +402,10 @@ class PDFImageReader(BasePDFReader):
|
|
|
276
402
|
doc_name = "pdf"
|
|
277
403
|
|
|
278
404
|
log_info(f"Reading: {doc_name}")
|
|
279
|
-
|
|
405
|
+
pdf_reader = DocumentReader(pdf)
|
|
280
406
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
async_process_image_page(doc_name, page_number, page)
|
|
284
|
-
for page_number, page in enumerate(doc_reader.pages, start=1)
|
|
285
|
-
]
|
|
286
|
-
)
|
|
287
|
-
|
|
288
|
-
if self.chunk:
|
|
289
|
-
return self._build_chunked_documents(documents)
|
|
290
|
-
return documents
|
|
407
|
+
# Read and chunk.
|
|
408
|
+
return await self._async_pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
|
|
291
409
|
|
|
292
410
|
|
|
293
411
|
class PDFUrlImageReader(BasePDFReader):
|
|
@@ -310,17 +428,10 @@ class PDFUrlImageReader(BasePDFReader):
|
|
|
310
428
|
response = httpx.get(url, proxy=self.proxy) if self.proxy else httpx.get(url)
|
|
311
429
|
|
|
312
430
|
doc_name = url.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
documents = []
|
|
316
|
-
for page_number, page in enumerate(doc_reader.pages, start=1):
|
|
317
|
-
documents.append(process_image_page(doc_name, page_number, page))
|
|
318
|
-
|
|
319
|
-
# Optionally chunk documents
|
|
320
|
-
if self.chunk:
|
|
321
|
-
return self._build_chunked_documents(documents)
|
|
431
|
+
pdf_reader = DocumentReader(BytesIO(response.content))
|
|
322
432
|
|
|
323
|
-
|
|
433
|
+
# Read and chunk.
|
|
434
|
+
return self._pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
|
|
324
435
|
|
|
325
436
|
async def async_read(self, url: str) -> List[Document]:
|
|
326
437
|
if not url:
|
|
@@ -338,15 +449,7 @@ class PDFUrlImageReader(BasePDFReader):
|
|
|
338
449
|
response.raise_for_status()
|
|
339
450
|
|
|
340
451
|
doc_name = url.split("/")[-1].split(".")[0].replace(" ", "_")
|
|
341
|
-
|
|
452
|
+
pdf_reader = DocumentReader(BytesIO(response.content))
|
|
342
453
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
async_process_image_page(doc_name, page_number, page)
|
|
346
|
-
for page_number, page in enumerate(doc_reader.pages, start=1)
|
|
347
|
-
]
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
if self.chunk:
|
|
351
|
-
return self._build_chunked_documents(documents)
|
|
352
|
-
return documents
|
|
454
|
+
# Read and chunk.
|
|
455
|
+
return await self._async_pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
|
agno/run/response.py
CHANGED
|
@@ -17,6 +17,7 @@ class RunEvent(str, Enum):
|
|
|
17
17
|
|
|
18
18
|
run_started = "RunStarted"
|
|
19
19
|
run_response_content = "RunResponseContent"
|
|
20
|
+
run_intermediate_response_content = "RunIntermediateResponseContent"
|
|
20
21
|
run_completed = "RunCompleted"
|
|
21
22
|
run_error = "RunError"
|
|
22
23
|
run_cancelled = "RunCancelled"
|
|
@@ -92,6 +93,13 @@ class RunResponseContentEvent(BaseAgentRunResponseEvent):
|
|
|
92
93
|
extra_data: Optional[RunResponseExtraData] = None
|
|
93
94
|
|
|
94
95
|
|
|
96
|
+
@dataclass
|
|
97
|
+
class IntermediateRunResponseContentEvent(BaseAgentRunResponseEvent):
|
|
98
|
+
event: str = RunEvent.run_intermediate_response_content.value
|
|
99
|
+
content: Optional[Any] = None
|
|
100
|
+
content_type: str = "str"
|
|
101
|
+
|
|
102
|
+
|
|
95
103
|
@dataclass
|
|
96
104
|
class RunResponseCompletedEvent(BaseAgentRunResponseEvent):
|
|
97
105
|
event: str = RunEvent.run_completed.value
|
|
@@ -207,6 +215,7 @@ class OutputModelResponseCompletedEvent(BaseAgentRunResponseEvent):
|
|
|
207
215
|
RunResponseEvent = Union[
|
|
208
216
|
RunResponseStartedEvent,
|
|
209
217
|
RunResponseContentEvent,
|
|
218
|
+
IntermediateRunResponseContentEvent,
|
|
210
219
|
RunResponseCompletedEvent,
|
|
211
220
|
RunResponseErrorEvent,
|
|
212
221
|
RunResponseCancelledEvent,
|
|
@@ -230,6 +239,7 @@ RunResponseEvent = Union[
|
|
|
230
239
|
RUN_EVENT_TYPE_REGISTRY = {
|
|
231
240
|
RunEvent.run_started.value: RunResponseStartedEvent,
|
|
232
241
|
RunEvent.run_response_content.value: RunResponseContentEvent,
|
|
242
|
+
RunEvent.run_intermediate_response_content.value: IntermediateRunResponseContentEvent,
|
|
233
243
|
RunEvent.run_completed.value: RunResponseCompletedEvent,
|
|
234
244
|
RunEvent.run_error.value: RunResponseErrorEvent,
|
|
235
245
|
RunEvent.run_cancelled.value: RunResponseCancelledEvent,
|
agno/run/team.py
CHANGED
|
@@ -17,6 +17,7 @@ class TeamRunEvent(str, Enum):
|
|
|
17
17
|
|
|
18
18
|
run_started = "TeamRunStarted"
|
|
19
19
|
run_response_content = "TeamRunResponseContent"
|
|
20
|
+
run_intermediate_response_content = "TeamRunIntermediateResponseContent"
|
|
20
21
|
run_completed = "TeamRunCompleted"
|
|
21
22
|
run_error = "TeamRunError"
|
|
22
23
|
run_cancelled = "TeamRunCancelled"
|
|
@@ -94,6 +95,13 @@ class RunResponseContentEvent(BaseTeamRunResponseEvent):
|
|
|
94
95
|
extra_data: Optional[RunResponseExtraData] = None
|
|
95
96
|
|
|
96
97
|
|
|
98
|
+
@dataclass
|
|
99
|
+
class IntermediateRunResponseContentEvent(BaseTeamRunResponseEvent):
|
|
100
|
+
event: str = TeamRunEvent.run_intermediate_response_content.value
|
|
101
|
+
content: Optional[Any] = None
|
|
102
|
+
content_type: str = "str"
|
|
103
|
+
|
|
104
|
+
|
|
97
105
|
@dataclass
|
|
98
106
|
class RunResponseCompletedEvent(BaseTeamRunResponseEvent):
|
|
99
107
|
event: str = TeamRunEvent.run_completed.value
|
|
@@ -191,6 +199,7 @@ class OutputModelResponseCompletedEvent(BaseTeamRunResponseEvent):
|
|
|
191
199
|
TeamRunResponseEvent = Union[
|
|
192
200
|
RunResponseStartedEvent,
|
|
193
201
|
RunResponseContentEvent,
|
|
202
|
+
IntermediateRunResponseContentEvent,
|
|
194
203
|
RunResponseCompletedEvent,
|
|
195
204
|
RunResponseErrorEvent,
|
|
196
205
|
RunResponseCancelledEvent,
|
|
@@ -211,6 +220,7 @@ TeamRunResponseEvent = Union[
|
|
|
211
220
|
TEAM_RUN_EVENT_TYPE_REGISTRY = {
|
|
212
221
|
TeamRunEvent.run_started.value: RunResponseStartedEvent,
|
|
213
222
|
TeamRunEvent.run_response_content.value: RunResponseContentEvent,
|
|
223
|
+
TeamRunEvent.run_intermediate_response_content.value: IntermediateRunResponseContentEvent,
|
|
214
224
|
TeamRunEvent.run_completed.value: RunResponseCompletedEvent,
|
|
215
225
|
TeamRunEvent.run_error.value: RunResponseErrorEvent,
|
|
216
226
|
TeamRunEvent.run_cancelled.value: RunResponseCancelledEvent,
|
agno/team/team.py
CHANGED
|
@@ -1110,16 +1110,21 @@ class Team:
|
|
|
1110
1110
|
response_format=response_format,
|
|
1111
1111
|
stream_intermediate_steps=stream_intermediate_steps,
|
|
1112
1112
|
):
|
|
1113
|
-
from agno.run.team import RunResponseContentEvent
|
|
1113
|
+
from agno.run.team import IntermediateRunResponseContentEvent, RunResponseContentEvent
|
|
1114
1114
|
|
|
1115
1115
|
if isinstance(event, RunResponseContentEvent):
|
|
1116
1116
|
if stream_intermediate_steps:
|
|
1117
|
-
yield
|
|
1117
|
+
yield IntermediateRunResponseContentEvent(
|
|
1118
|
+
content=event.content,
|
|
1119
|
+
content_type=event.content_type,
|
|
1120
|
+
)
|
|
1118
1121
|
else:
|
|
1119
1122
|
yield event
|
|
1120
1123
|
|
|
1121
1124
|
yield from self._generate_response_with_output_model_stream(
|
|
1122
|
-
run_response=run_response,
|
|
1125
|
+
run_response=run_response,
|
|
1126
|
+
run_messages=run_messages,
|
|
1127
|
+
stream_intermediate_steps=stream_intermediate_steps,
|
|
1123
1128
|
)
|
|
1124
1129
|
|
|
1125
1130
|
# If a parser model is provided, structure the response separately
|
|
@@ -1519,19 +1524,28 @@ class Team:
|
|
|
1519
1524
|
):
|
|
1520
1525
|
yield event
|
|
1521
1526
|
else:
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
async for event in self._agenerate_response_with_output_model_stream(
|
|
1527
|
+
async for event in self._ahandle_model_response_stream(
|
|
1525
1528
|
run_response=run_response,
|
|
1526
1529
|
run_messages=run_messages,
|
|
1530
|
+
response_format=response_format,
|
|
1527
1531
|
stream_intermediate_steps=stream_intermediate_steps,
|
|
1528
1532
|
):
|
|
1533
|
+
from agno.run.team import IntermediateRunResponseContentEvent, RunResponseContentEvent
|
|
1534
|
+
|
|
1529
1535
|
if isinstance(event, RunResponseContentEvent):
|
|
1530
1536
|
if stream_intermediate_steps:
|
|
1531
|
-
yield
|
|
1537
|
+
yield IntermediateRunResponseContentEvent(
|
|
1538
|
+
content=event.content,
|
|
1539
|
+
content_type=event.content_type,
|
|
1540
|
+
)
|
|
1532
1541
|
else:
|
|
1533
1542
|
yield event
|
|
1534
1543
|
|
|
1544
|
+
async for event in self._agenerate_response_with_output_model_stream(
|
|
1545
|
+
run_response=run_response,
|
|
1546
|
+
run_messages=run_messages,
|
|
1547
|
+
stream_intermediate_steps=stream_intermediate_steps,
|
|
1548
|
+
):
|
|
1535
1549
|
yield event
|
|
1536
1550
|
|
|
1537
1551
|
# If a parser model is provided, structure the response separately
|
|
@@ -2446,10 +2460,9 @@ class Team:
|
|
|
2446
2460
|
model_response.content = output_model_response.content
|
|
2447
2461
|
|
|
2448
2462
|
def _generate_response_with_output_model_stream(
|
|
2449
|
-
self, run_response: TeamRunResponse, run_messages: RunMessages, stream_intermediate_steps: bool =
|
|
2463
|
+
self, run_response: TeamRunResponse, run_messages: RunMessages, stream_intermediate_steps: bool = False
|
|
2450
2464
|
):
|
|
2451
2465
|
"""Parse the model response using the output model stream."""
|
|
2452
|
-
|
|
2453
2466
|
from agno.utils.events import (
|
|
2454
2467
|
create_team_output_model_response_completed_event,
|
|
2455
2468
|
create_team_output_model_response_started_event,
|
|
@@ -2497,7 +2510,7 @@ class Team:
|
|
|
2497
2510
|
model_response.content = output_model_response.content
|
|
2498
2511
|
|
|
2499
2512
|
async def _agenerate_response_with_output_model_stream(
|
|
2500
|
-
self, run_response: TeamRunResponse, run_messages: RunMessages, stream_intermediate_steps: bool =
|
|
2513
|
+
self, run_response: TeamRunResponse, run_messages: RunMessages, stream_intermediate_steps: bool = False
|
|
2501
2514
|
):
|
|
2502
2515
|
"""Parse the model response using the output model stream."""
|
|
2503
2516
|
from agno.utils.events import (
|
|
@@ -2514,9 +2527,7 @@ class Team:
|
|
|
2514
2527
|
messages_for_output_model = self.get_messages_for_output_model(run_messages.messages)
|
|
2515
2528
|
model_response = ModelResponse(content="")
|
|
2516
2529
|
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
async for model_response_event in model_response_stream:
|
|
2530
|
+
async for model_response_event in self.output_model.aresponse_stream(messages=messages_for_output_model):
|
|
2520
2531
|
for event in self._handle_model_response_chunk(
|
|
2521
2532
|
run_response=run_response,
|
|
2522
2533
|
full_model_response=model_response,
|
agno/tools/aws_lambda.py
CHANGED
|
@@ -26,6 +26,9 @@ class AWSLambdaTools(Toolkit):
|
|
|
26
26
|
super().__init__(name="aws-lambda", tools=tools, **kwargs)
|
|
27
27
|
|
|
28
28
|
def list_functions(self) -> str:
|
|
29
|
+
"""
|
|
30
|
+
List all AWS Lambda functions in the configured AWS account.
|
|
31
|
+
"""
|
|
29
32
|
try:
|
|
30
33
|
response = self.client.list_functions()
|
|
31
34
|
functions = [func["FunctionName"] for func in response["Functions"]]
|
|
@@ -34,6 +37,13 @@ class AWSLambdaTools(Toolkit):
|
|
|
34
37
|
return f"Error listing functions: {str(e)}"
|
|
35
38
|
|
|
36
39
|
def invoke_function(self, function_name: str, payload: str = "{}") -> str:
|
|
40
|
+
"""
|
|
41
|
+
Invoke a specific AWS Lambda function with an optional JSON payload.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
function_name (str): The name of the Lambda function to invoke.
|
|
45
|
+
payload (str): The JSON payload to send to the function. Defaults to "{}".
|
|
46
|
+
"""
|
|
37
47
|
try:
|
|
38
48
|
response = self.client.invoke(FunctionName=function_name, Payload=payload)
|
|
39
49
|
return f"Function invoked successfully. Status code: {response['StatusCode']}, Payload: {response['Payload'].read().decode('utf-8')}"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from hashlib import md5
|
|
3
|
+
from os import getenv
|
|
3
4
|
from typing import Any, Dict, List, Optional
|
|
4
5
|
|
|
5
6
|
try:
|
|
@@ -74,9 +75,12 @@ class LanceDb(VectorDb):
|
|
|
74
75
|
# Distance metric
|
|
75
76
|
self.distance: Distance = distance
|
|
76
77
|
|
|
78
|
+
# Remote LanceDB connection details
|
|
79
|
+
self.api_key: Optional[str] = api_key
|
|
80
|
+
|
|
77
81
|
# LanceDB connection details
|
|
78
82
|
self.uri: lancedb.URI = uri
|
|
79
|
-
self.connection: lancedb.
|
|
83
|
+
self.connection: lancedb.DBConnection = connection or lancedb.connect(uri=self.uri, api_key=api_key)
|
|
80
84
|
self.table: Optional[lancedb.db.LanceTable] = table
|
|
81
85
|
|
|
82
86
|
self.async_connection: Optional[lancedb.AsyncConnection] = async_connection
|
|
@@ -168,7 +172,11 @@ class LanceDb(VectorDb):
|
|
|
168
172
|
schema = self._base_schema()
|
|
169
173
|
|
|
170
174
|
log_info(f"Creating table: {self.table_name}")
|
|
171
|
-
|
|
175
|
+
if self.api_key or getenv("LANCEDB_API_KEY"):
|
|
176
|
+
log_info("API key found, creating table in remote LanceDB")
|
|
177
|
+
tbl = self.connection.create_table(name=self.table_name, schema=schema, mode="overwrite") # type: ignore
|
|
178
|
+
else:
|
|
179
|
+
tbl = self.connection.create_table(name=self.table_name, schema=schema, mode="overwrite", exist_ok=True) # type: ignore
|
|
172
180
|
return tbl # type: ignore
|
|
173
181
|
|
|
174
182
|
def doc_exists(self, document: Document) -> bool:
|
|
@@ -766,6 +766,9 @@ class PgVector(VectorDb):
|
|
|
766
766
|
)
|
|
767
767
|
)
|
|
768
768
|
|
|
769
|
+
if self.reranker:
|
|
770
|
+
search_results = self.reranker.rerank(query=query, documents=search_results)
|
|
771
|
+
|
|
769
772
|
log_info(f"Found {len(search_results)} documents")
|
|
770
773
|
return search_results
|
|
771
774
|
except Exception as e:
|
|
@@ -5,7 +5,7 @@ agno/exceptions.py,sha256=HWuuNFS5J0l1RYJsdUrSx51M22aFEoh9ltoeonXBoBw,2891
|
|
|
5
5
|
agno/media.py,sha256=lXJuylmhuIEWThKZkQ9pUZPp8Kms7EdT4N_U4YN9I00,12656
|
|
6
6
|
agno/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
agno/agent/__init__.py,sha256=Ai6GVyw-0rkA2eYAfoEQIvbi_mrWQUxuPFaFbSDJYCQ,1306
|
|
8
|
-
agno/agent/agent.py,sha256=
|
|
8
|
+
agno/agent/agent.py,sha256=jNCP1lMtzKmDliOgPhItQTrx6HJG5ZHNo3P4g41Jy9k,381426
|
|
9
9
|
agno/agent/metrics.py,sha256=Lf7JYgPPdqRCyPfCDVUjnmUZ1SkWXrJClL80aW2ffEw,4379
|
|
10
10
|
agno/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
agno/api/agent.py,sha256=J-Y4HI-J0Bu6r9gxRYCM3U7SnVBGwLIouDy806KSIIw,2821
|
|
@@ -92,7 +92,7 @@ agno/document/reader/docx_reader.py,sha256=fNSZNzBlROQow7nagouEfN8E4KgVp3hTcSj3d
|
|
|
92
92
|
agno/document/reader/firecrawl_reader.py,sha256=4CFACPA22t0gI1YgYL1mZLZQN_T6LrLj8V9mAmU2In8,5748
|
|
93
93
|
agno/document/reader/json_reader.py,sha256=TrE14YAPkEd3q1e1dFf1ZX-GJPlXadsbeCzNh6EGpgg,2189
|
|
94
94
|
agno/document/reader/markdown_reader.py,sha256=SX0Zydj_0AmBr8Grk8z9jDiNmebU7rnPg2aAJoFEHAk,3546
|
|
95
|
-
agno/document/reader/pdf_reader.py,sha256=
|
|
95
|
+
agno/document/reader/pdf_reader.py,sha256=KgY_V7dI0XC-hoYIKYg_nGszzsthWF58ejocegkY-1I,17269
|
|
96
96
|
agno/document/reader/text_reader.py,sha256=jtCuhWHkC5QNPmRF3DyXcXVKHM1jnqqxXVxHKZIpkfQ,3315
|
|
97
97
|
agno/document/reader/url_reader.py,sha256=dQmuO1NkJg9A9m2YeiVMuR7GikLl_K1FudE0UO62Um4,1988
|
|
98
98
|
agno/document/reader/website_reader.py,sha256=Ei-FIsdw0FWhGOBVge24JcNMfiAHL8nUA1tawrfBZPM,17307
|
|
@@ -291,8 +291,8 @@ agno/reranker/sentence_transformer.py,sha256=Pqv38uZ5MhwYPQkei8ixs3jANoBOIKqVwI3
|
|
|
291
291
|
agno/run/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
292
292
|
agno/run/base.py,sha256=cueGFKz_TOCNO9aMe8IBFwohax4z6IgL0e3HAK7XqRQ,7546
|
|
293
293
|
agno/run/messages.py,sha256=rAC4CLW-xBA6qFS1BOvcjJ9j_qYf0a7sX1mcdY04zMU,1126
|
|
294
|
-
agno/run/response.py,sha256=
|
|
295
|
-
agno/run/team.py,sha256=
|
|
294
|
+
agno/run/response.py,sha256=CafLgeLszVbdre7jm1A5TNG4WMpN0OiPMPk6ioeN-cg,15766
|
|
295
|
+
agno/run/team.py,sha256=WT5HbqVA1fvKPQg8gr2tpdeaNq2aM3WoWpas93P07ck,16504
|
|
296
296
|
agno/run/workflow.py,sha256=2eBvNXbGini3-cWwl3dOf-o-VgGq51ZEl4GCbQFblaw,1581
|
|
297
297
|
agno/run/v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
298
298
|
agno/run/v2/workflow.py,sha256=FiZY5eWl6oEJCEfBUIX2q1WDHLI8mqVmaWWwKBA1PL8,18903
|
|
@@ -328,14 +328,14 @@ agno/storage/workflow/mongodb.py,sha256=x-0Jl2WovupTfwuVNOSndE9-7V4U7BBIjejtJ1Wa
|
|
|
328
328
|
agno/storage/workflow/postgres.py,sha256=66bvx6eT7PtFvd4EtTCfI2smynAyvpjvAPYtPo-PCNg,91
|
|
329
329
|
agno/storage/workflow/sqlite.py,sha256=PLqEA1YC8AtIklINr6wy8lzK6KABEqvlJW-nz5KacWM,85
|
|
330
330
|
agno/team/__init__.py,sha256=OSkwJhm4uSoOwpHLeDdcH4q2R_BmfS-7a9_aPxB-Skw,967
|
|
331
|
-
agno/team/team.py,sha256=
|
|
331
|
+
agno/team/team.py,sha256=9rZuwihREck6SU6-IZQMOOjZfzxGeQVulsYTMGtb4Rw,377428
|
|
332
332
|
agno/tools/__init__.py,sha256=jNll2sELhPPbqm5nPeT4_uyzRO2_KRTW-8Or60kioS0,210
|
|
333
333
|
agno/tools/agentql.py,sha256=w6FlCfhuS0cc2BHa9K6dZjqO1ycA66fSZbR_nvXiVSo,3813
|
|
334
334
|
agno/tools/airflow.py,sha256=2ZCwx65w_tSXm4xEzZQR_teOiXJlnEgIqU9AgQTQemI,2493
|
|
335
335
|
agno/tools/api.py,sha256=gd86Fvk_3kHcaNWepTQ_Bmzs9RwajwiwcsEHJKdngB8,4238
|
|
336
336
|
agno/tools/apify.py,sha256=WWs9NWiiyMW5jKRRYLDHBoPPX4ScGMMt87VCXHowTy0,13555
|
|
337
337
|
agno/tools/arxiv.py,sha256=xnfbzOBDuHRj5SHImlz_q-pdRT9o_Vnna-VtDt1JuDU,5202
|
|
338
|
-
agno/tools/aws_lambda.py,sha256=
|
|
338
|
+
agno/tools/aws_lambda.py,sha256=CbVQpoLudpmle1KkgecuVDqE_JdapBBf26OdIj8fUsY,1831
|
|
339
339
|
agno/tools/aws_ses.py,sha256=fl5NTRWcljzxp4WxTg2gIAjLMNcuEWs_vnjeRtEKRHY,2090
|
|
340
340
|
agno/tools/baidusearch.py,sha256=HBdhLz1HUtKXJjIQru21jKiSonG9jEjNB_W6FPjklew,2883
|
|
341
341
|
agno/tools/bitbucket.py,sha256=CLhYdB_HTriy44VHtsRtqCY-BhnHpZMBHQ9vgL4vpWg,11207
|
|
@@ -511,14 +511,14 @@ agno/vectordb/clickhouse/index.py,sha256=_YW-8AuEYy5kzOHi0zIzjngpQPgJOBdSrn9BfEL
|
|
|
511
511
|
agno/vectordb/couchbase/__init__.py,sha256=dKZkcQLFN4r2_NIdXby4inzAAn4BDMlb9T2BW_i0_gQ,93
|
|
512
512
|
agno/vectordb/couchbase/couchbase.py,sha256=I-nWRPAEyEoww-1FpQJLM6CyxWXWPtR9dRjpAyzLWyo,48814
|
|
513
513
|
agno/vectordb/lancedb/__init__.py,sha256=tb9qvinKyWMTLjJYMwW_lhYHFvrfWTfHODtBfMj-NLE,111
|
|
514
|
-
agno/vectordb/lancedb/lance_db.py,sha256=
|
|
514
|
+
agno/vectordb/lancedb/lance_db.py,sha256=PBLtn0AkAVEEYJywYKzdf5gWbQWvka6yJXeAfsJQdtI,22886
|
|
515
515
|
agno/vectordb/milvus/__init__.py,sha256=I9V-Rm-rIYxWdRVIs6bKI-6JSJsyOd1-vvasvVpYHuE,127
|
|
516
516
|
agno/vectordb/milvus/milvus.py,sha256=SwLPmgP80dPWFeN9ehj3D1yseyVXbHJDIBNCu-NPs9s,30002
|
|
517
517
|
agno/vectordb/mongodb/__init__.py,sha256=yYwaWdxZRnFTd87Hfgs8_DO4QxcJxy1iL3__bnxP71I,73
|
|
518
518
|
agno/vectordb/mongodb/mongodb.py,sha256=yG_bs7iJrXatrmI2BMLALxkVT1qVx4BYoiUcXWXlSsg,48537
|
|
519
519
|
agno/vectordb/pgvector/__init__.py,sha256=Lui0HBzoHPIsKh5QuiT0eyTvYW88nQPfd_723jjHFCk,288
|
|
520
520
|
agno/vectordb/pgvector/index.py,sha256=qfGgPP33SwZkXLfUcAC_XgQsyZIyggpGS2bfIkjjs-E,495
|
|
521
|
-
agno/vectordb/pgvector/pgvector.py,sha256=
|
|
521
|
+
agno/vectordb/pgvector/pgvector.py,sha256=JE52MgXSXRqbySPMzgy1DcvJxZhabiw1ufFHf6QImWA,44305
|
|
522
522
|
agno/vectordb/pineconedb/__init__.py,sha256=D7iThXtUCxNO0Nyjunv5Z91Jc1vHG1pgAFXthqD1I_w,92
|
|
523
523
|
agno/vectordb/pineconedb/pineconedb.py,sha256=NaYmkskY1eLAWIM-HSBa-DVHEMQ6ZuZDqqUmmHZhlro,18399
|
|
524
524
|
agno/vectordb/qdrant/__init__.py,sha256=x1ReQt79f9aI_T4JUWb36KNFnvdd-kVwZ1sLsU4sW7Q,76
|
|
@@ -550,9 +550,9 @@ agno/workspace/enums.py,sha256=MxF1CUMXBaZMTKLEfiR-7kEhTki2Gfz6W7u49RdYYaE,123
|
|
|
550
550
|
agno/workspace/helpers.py,sha256=Mp-VlRsPVhW10CfDWYVhc9ANLk9RjNurDfCgXmycZCg,2066
|
|
551
551
|
agno/workspace/operator.py,sha256=CNLwVR45eE5dSRjto2o0c9NgCi2xD-JZR5uLt9kfIt8,30758
|
|
552
552
|
agno/workspace/settings.py,sha256=bcyHHN7lH1LPSMt4i_20XpTjZLoNXdzwyW-G9nHYV40,5703
|
|
553
|
-
agno-1.7.
|
|
554
|
-
agno-1.7.
|
|
555
|
-
agno-1.7.
|
|
556
|
-
agno-1.7.
|
|
557
|
-
agno-1.7.
|
|
558
|
-
agno-1.7.
|
|
553
|
+
agno-1.7.9.dist-info/licenses/LICENSE,sha256=m2rfTWFUfIwCaQqgT2WeBjuKzMKEJRwnaiofg9n8MsQ,16751
|
|
554
|
+
agno-1.7.9.dist-info/METADATA,sha256=F9YGHpMsxVonyK77LMJ7vPXygE1klxiUtekDCh58O6g,44277
|
|
555
|
+
agno-1.7.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
556
|
+
agno-1.7.9.dist-info/entry_points.txt,sha256=Be-iPnPVabMohESsuUdV5w6IAYEIlpc2emJZbyNnfGI,88
|
|
557
|
+
agno-1.7.9.dist-info/top_level.txt,sha256=MKyeuVesTyOKIXUhc-d_tPa2Hrh0oTA4LM0izowpx70,5
|
|
558
|
+
agno-1.7.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|