Skip to content

Commit bf1462a

Browse files
authored
Release 1.4.6 (#3154)
# Changelog ## New Features: - **Cerebras Model Provider**: Added Cerebras as a model provider. - **Claude Web Search**: Added support for [Claude’s new web search tool](https://www.anthropic.com/news/web-search) - **Knowledge Base Metadata Filtering (Beta)**: Added support for filtering documents by metadata - **Two Ways to Apply Filters**: - **Explicit Filtering**: Pass filters directly to Agent or during run/query ```python # Option 1: Filters on Agent initialization agent = Agent( knowledge=knowledge_base, knowledge_filters={"filter_1": "abc"} ) # Option 2: Filters on run execution agent.run("Tell me about...", knowledge_filters={"filter_1": "abc"}) ``` See docs [here](https://github.com/agno-agi/agno/blob/main/cookbook/agent_concepts/knowledge/filters/pdf/filtering.py) - **Agentic Filtering**: Agent automatically detects and applies filters from user queries ```python # Enable automatic filter detection agent = Agent( knowledge=knowledge_base, enable_agentic_knowledge_filters=True ) # Agent extracts filters from query agent.run("Tell me about John Doe's experience...") ``` See docs [here](https://github.com/agno-agi/agno/blob/main/cookbook/agent_concepts/knowledge/filters/pdf/agentic_filtering.py) - Two approaches for adding metadata to documents: 1. **During Knowledge Base Initialization**: ```python knowledge_base = PDFKnowledgeBase(path=[ { "path": "file_1.pdf", "metadata": { "user_id": "abc" } }, { "path": "file_2.pdf", "metadata": { "user_id": "xyz" } } ]) ``` 2. **During Individual Document Loading:** ```python knowledge_base.load_document( path="file.pdf", metadata={"user_id": "abc"} ) ``` - **Compatibility** - **Knowledge Base Types**: `PDF`, `Text`, `DOCX`, `JSON`, and `PDF_URL` - **Vector Databases**: `Qdrant`, `LanceDB`, and `MongoDB` ## Improvements: - **User and Session ID in Tools**: Added `current_user_id` and `current_session_id` as default variables in ## Bug Fixes: - **Knowledge Base ID Clashes**: Knowledge files with overlapping names (e.g., `abc.-.xyz.pdf` and `abc.-.def.pdf`) were being incorrectly identified due to the readers using formatted names as unique id which were getting uniqueness conflict. Introduced a unique ID for each document in all the readers using `uuidv4()` to ensure strict identification and prevent conflicts.
1 parent a6a5799 commit bf1462a

File tree

17 files changed

+49
-172
lines changed

17 files changed

+49
-172
lines changed

libs/agno/agno/agent/agent.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,8 +1922,10 @@ def create_run_response(
19221922

19231923
def _initialize_session_state(self, user_id: Optional[str] = None, session_id: Optional[str] = None) -> None:
19241924
self.session_state = self.session_state or {}
1925-
self.session_state["current_user_id"] = user_id
1926-
self.session_state["current_session_id"] = session_id
1925+
if user_id is not None:
1926+
self.session_state["current_user_id"] = user_id
1927+
if session_id is not None:
1928+
self.session_state["current_session_id"] = session_id
19271929

19281930
def _make_memories_and_summaries(
19291931
self,

libs/agno/agno/document/reader/base.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class Reader:
1818

1919
def __init__(self, chunk_size: int = 5000, chunking_strategy: Optional[ChunkingStrategy] = None) -> None:
2020
self.chunk_size = chunk_size
21-
self.chunking_strategy = chunking_strategy or FixedSizeChunking(chunk_size=self.chunk_size)
21+
self.chunking_strategy = chunking_strategy
2222

2323
def read(self, obj: Any) -> List[Document]:
2424
raise NotImplementedError
@@ -27,6 +27,8 @@ async def async_read(self, obj: Any) -> List[Document]:
2727
raise NotImplementedError
2828

2929
def chunk_document(self, document: Document) -> List[Document]:
30+
if self.chunking_strategy is None:
31+
self.chunking_strategy = FixedSizeChunking(chunk_size=self.chunk_size)
3032
return self.chunking_strategy.chunk(document) # type: ignore
3133

3234
async def chunk_documents_async(self, documents: List[Document]) -> List[Document]:

libs/agno/agno/document/reader/csv_reader.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def read(self, file: Union[Path, IO[Any]], delimiter: str = ",", quotechar: str
3030
logger.info(f"Reading: {file}")
3131
file_content = file.open(newline="", mode="r", encoding="utf-8")
3232
else:
33-
logger.info(f"Reading uploaded file: {file.name}")
33+
logger.info(f"Reading retrieved file: {file.name}")
3434
file.seek(0)
3535
file_content = io.StringIO(file.read().decode("utf-8")) # type: ignore
3636

@@ -82,7 +82,7 @@ async def async_read(
8282
content = await file_content.read()
8383
file_content_io = io.StringIO(content)
8484
else:
85-
logger.info(f"Reading uploaded file async: {file.name}")
85+
logger.info(f"Reading retrieved file async: {file.name}")
8686
file.seek(0)
8787
file_content_io = io.StringIO(file.read().decode("utf-8")) # type: ignore
8888

@@ -152,7 +152,6 @@ def read(self, url: str) -> List[Document]:
152152

153153
file_obj = io.BytesIO(response.content)
154154
file_obj.name = filename
155-
156155
documents = CSVReader().read(file=file_obj)
157156

158157
file_obj.close()

libs/agno/agno/models/anthropic/claude.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,12 @@ def _format_tools_for_model(self) -> Optional[List[Dict[str, Any]]]:
144144
return None
145145

146146
tools: List[Dict[str, Any]] = []
147-
for func_def in self._tools:
148-
if func_def.get("type") != "function":
149-
tools.append(func_def)
147+
for tool_def in self._tools:
148+
if tool_def.get("type", "") != "function":
149+
tools.append(tool_def)
150150
continue
151+
152+
func_def = tool_def.get("function", {})
151153
parameters: Dict[str, Any] = func_def.get("parameters", {})
152154
properties: Dict[str, Any] = parameters.get("properties", {})
153155
required_params: List[str] = []
@@ -502,6 +504,7 @@ def parse_provider_response_delta(
502504

503505
# Capture citations from the final response
504506
elif isinstance(response, MessageStopEvent):
507+
model_response.content = ""
505508
model_response.citations = Citations(raw=[], urls=[], documents=[])
506509
for block in response.message.content:
507510
citations = getattr(block, "citations", None)
@@ -517,9 +520,6 @@ def parse_provider_response_delta(
517520
model_response.citations.documents.append( # type: ignore
518521
DocumentCitation(document_title=citation.document_title, cited_text=citation.cited_text)
519522
)
520-
521-
# Handle message completion and usage metrics
522-
elif isinstance(response, MessageStopEvent):
523523
if response.message.usage is not None:
524524
model_response.response_usage = response.message.usage
525525

libs/agno/agno/team/team.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,8 +1996,10 @@ async def _arun_stream(
19961996

19971997
def _initialize_session_state(self, user_id: Optional[str] = None, session_id: Optional[str] = None) -> None:
19981998
self.session_state = self.session_state or {}
1999-
self.session_state["current_user_id"] = user_id
2000-
self.session_state["current_session_id"] = session_id
1999+
if user_id is not None:
2000+
self.session_state["current_user_id"] = user_id
2001+
if session_id is not None:
2002+
self.session_state["current_session_id"] = session_id
20012003

20022004
def _make_memories_and_summaries(
20032005
self, run_messages: RunMessages, session_id: str, user_id: Optional[str] = None

libs/agno/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "agno"
3-
version = "1.4.5"
3+
version = "1.4.6"
44
description = "Agno: a lightweight library for building Reasoning Agents"
55
requires-python = ">=3.7,<4"
66
readme = "README.md"

libs/agno/tests/integration/agent/test_metrics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def test_session_metrics():
3131
response = agent.run("What is current news in France?")
3232

3333
input_tokens_list = response.metrics.get("input_tokens", [])
34-
assert len(input_tokens_list) == 2 # Should be 2 assistant messages
34+
assert len(input_tokens_list) >= 2 # Should be atleast 2 assistant messages
3535

3636
input_tokens += sum(response.metrics.get("input_tokens", []))
3737
output_tokens += sum(response.metrics.get("output_tokens", []))

libs/agno/tests/integration/agent/test_reasoning_content_knowledge_tools.py

Lines changed: 0 additions & 131 deletions
This file was deleted.

libs/agno/tests/integration/knowledge/test_docx_knowledge_base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ def test_docx_knowledge_base_with_metadata_path_invalid_filter(setup_vector_db):
256256
assert len(response_content) > 50
257257

258258
clarification_phrases = [
259-
"specify which",
259+
"specify",
260260
"which candidate",
261261
"please clarify",
262262
"need more information",
@@ -321,7 +321,7 @@ async def test_async_docx_knowledge_base_with_metadata_path_invalid_filter(setup
321321
assert len(response_content) > 50
322322

323323
clarification_phrases = [
324-
"specify which",
324+
"specify",
325325
"which candidate",
326326
"please clarify",
327327
"need more information",
@@ -550,7 +550,7 @@ async def test_async_knowledge_base_with_invalid_filter(setup_vector_db):
550550
assert len(response_content) > 50
551551

552552
clarification_phrases = [
553-
"specify which",
553+
"specify",
554554
"which candidate",
555555
"please clarify",
556556
"need more information",

libs/agno/tests/integration/knowledge/test_json_knowledge_base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ def test_docx_knowledge_base_with_metadata_path_invalid_filter(setup_vector_db):
276276
assert len(response_content) > 50
277277

278278
clarification_phrases = [
279-
"specify which",
279+
"specify",
280280
"which candidate",
281281
"please clarify",
282282
"need more information",
@@ -340,7 +340,7 @@ async def test_async_docx_knowledge_base_with_metadata_path_invalid_filter(setup
340340
assert len(response_content) > 50
341341

342342
clarification_phrases = [
343-
"specify which",
343+
"specify",
344344
"which candidate",
345345
"please clarify",
346346
"need more information",
@@ -437,7 +437,7 @@ def test_knowledge_base_with_invalid_filter(setup_vector_db):
437437
assert len(response_content) > 50
438438

439439
clarification_phrases = [
440-
"specify which",
440+
"specify",
441441
"which candidate",
442442
"please clarify",
443443
"need more information",
@@ -569,7 +569,7 @@ async def test_async_knowledge_base_with_invalid_filter(setup_vector_db):
569569
assert len(response_content) > 50
570570

571571
clarification_phrases = [
572-
"specify which",
572+
"specify",
573573
"which candidate",
574574
"please clarify",
575575
"need more information",

0 commit comments

Comments
 (0)