agno 2.3.16__py3-none-any.whl → 2.3.18__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/__init__.py +2 -0
- agno/agent/agent.py +4 -53
- agno/agent/remote.py +351 -0
- agno/client/__init__.py +3 -0
- agno/client/os.py +2669 -0
- agno/db/base.py +20 -0
- agno/db/mongo/async_mongo.py +11 -0
- agno/db/mongo/mongo.py +10 -0
- agno/db/mysql/async_mysql.py +9 -0
- agno/db/mysql/mysql.py +9 -0
- agno/db/postgres/async_postgres.py +9 -0
- agno/db/postgres/postgres.py +9 -0
- agno/db/postgres/utils.py +3 -2
- agno/db/sqlite/async_sqlite.py +9 -0
- agno/db/sqlite/sqlite.py +11 -1
- agno/exceptions.py +23 -0
- agno/knowledge/chunking/semantic.py +123 -46
- agno/knowledge/reader/csv_reader.py +1 -1
- agno/knowledge/reader/field_labeled_csv_reader.py +1 -1
- agno/knowledge/reader/json_reader.py +1 -1
- agno/models/google/gemini.py +5 -0
- agno/os/app.py +108 -25
- agno/os/auth.py +25 -1
- agno/os/interfaces/a2a/a2a.py +7 -6
- agno/os/interfaces/a2a/router.py +13 -13
- agno/os/interfaces/agui/agui.py +5 -3
- agno/os/interfaces/agui/router.py +23 -16
- agno/os/interfaces/base.py +7 -7
- agno/os/interfaces/slack/router.py +6 -6
- agno/os/interfaces/slack/slack.py +7 -7
- agno/os/interfaces/whatsapp/router.py +29 -6
- agno/os/interfaces/whatsapp/whatsapp.py +11 -8
- agno/os/managers.py +326 -0
- agno/os/mcp.py +651 -79
- agno/os/router.py +125 -18
- agno/os/routers/agents/router.py +65 -22
- agno/os/routers/agents/schema.py +16 -4
- agno/os/routers/database.py +5 -0
- agno/os/routers/evals/evals.py +93 -11
- agno/os/routers/evals/utils.py +6 -6
- agno/os/routers/knowledge/knowledge.py +104 -16
- agno/os/routers/memory/memory.py +124 -7
- agno/os/routers/metrics/metrics.py +21 -4
- agno/os/routers/session/session.py +141 -12
- agno/os/routers/teams/router.py +40 -14
- agno/os/routers/teams/schema.py +12 -4
- agno/os/routers/traces/traces.py +54 -4
- agno/os/routers/workflows/router.py +223 -117
- agno/os/routers/workflows/schema.py +65 -1
- agno/os/schema.py +38 -12
- agno/os/utils.py +87 -166
- agno/remote/__init__.py +3 -0
- agno/remote/base.py +484 -0
- agno/run/workflow.py +1 -0
- agno/team/__init__.py +2 -0
- agno/team/remote.py +287 -0
- agno/team/team.py +25 -54
- agno/tracing/exporter.py +10 -6
- agno/tracing/setup.py +2 -1
- agno/utils/agent.py +58 -1
- agno/utils/http.py +68 -20
- agno/utils/os.py +0 -0
- agno/utils/remote.py +23 -0
- agno/vectordb/chroma/chromadb.py +452 -16
- agno/vectordb/pgvector/pgvector.py +7 -0
- agno/vectordb/redis/redisdb.py +1 -1
- agno/workflow/__init__.py +2 -0
- agno/workflow/agent.py +2 -2
- agno/workflow/remote.py +222 -0
- agno/workflow/types.py +0 -73
- agno/workflow/workflow.py +119 -68
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/METADATA +1 -1
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/RECORD +76 -66
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/WHEEL +0 -0
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.16.dist-info → agno-2.3.18.dist-info}/top_level.txt +0 -0
agno/db/base.py
CHANGED
|
@@ -58,6 +58,14 @@ class BaseDb(ABC):
|
|
|
58
58
|
"""Create all tables for this database."""
|
|
59
59
|
pass
|
|
60
60
|
|
|
61
|
+
def close(self) -> None:
|
|
62
|
+
"""Close database connections and release resources.
|
|
63
|
+
|
|
64
|
+
Override in subclasses to properly dispose of connection pools.
|
|
65
|
+
Should be called during application shutdown.
|
|
66
|
+
"""
|
|
67
|
+
pass
|
|
68
|
+
|
|
61
69
|
# --- Schema Version ---
|
|
62
70
|
@abstractmethod
|
|
63
71
|
def get_latest_schema_version(self, table_name: str):
|
|
@@ -517,6 +525,18 @@ class AsyncBaseDb(ABC):
|
|
|
517
525
|
self.culture_table_name = culture_table or "agno_culture"
|
|
518
526
|
self.versions_table_name = versions_table or "agno_schema_versions"
|
|
519
527
|
|
|
528
|
+
async def _create_all_tables(self) -> None:
|
|
529
|
+
"""Create all tables for this database. Override in subclasses."""
|
|
530
|
+
pass
|
|
531
|
+
|
|
532
|
+
async def close(self) -> None:
|
|
533
|
+
"""Close database connections and release resources.
|
|
534
|
+
|
|
535
|
+
Override in subclasses to properly dispose of connection pools.
|
|
536
|
+
Should be called during application shutdown.
|
|
537
|
+
"""
|
|
538
|
+
pass
|
|
539
|
+
|
|
520
540
|
@abstractmethod
|
|
521
541
|
async def table_exists(self, table_name: str) -> bool:
|
|
522
542
|
"""Check if a table with the given name exists in this database.
|
agno/db/mongo/async_mongo.py
CHANGED
|
@@ -249,6 +249,17 @@ class AsyncMongoDb(AsyncBaseDb):
|
|
|
249
249
|
if collection_name and not await self.table_exists(collection_name):
|
|
250
250
|
await self._get_collection(collection_type, create_collection_if_not_found=True)
|
|
251
251
|
|
|
252
|
+
async def close(self) -> None:
|
|
253
|
+
"""Close the MongoDB client connection.
|
|
254
|
+
|
|
255
|
+
Should be called during application shutdown to properly release
|
|
256
|
+
all database connections.
|
|
257
|
+
"""
|
|
258
|
+
if self._client is not None:
|
|
259
|
+
self._client.close()
|
|
260
|
+
self._client = None
|
|
261
|
+
self._database = None
|
|
262
|
+
|
|
252
263
|
def _ensure_client(self) -> AsyncMongoClientType:
|
|
253
264
|
"""
|
|
254
265
|
Ensure the MongoDB async client is valid for the current event loop.
|
agno/db/mongo/mongo.py
CHANGED
|
@@ -98,10 +98,20 @@ class MongoDb(BaseDb):
|
|
|
98
98
|
|
|
99
99
|
self.db_url: Optional[str] = db_url
|
|
100
100
|
self.db_client: MongoClient = _client
|
|
101
|
+
|
|
101
102
|
self.db_name: str = db_name if db_name is not None else "agno"
|
|
102
103
|
|
|
103
104
|
self._database: Optional[Database] = None
|
|
104
105
|
|
|
106
|
+
def close(self) -> None:
|
|
107
|
+
"""Close the MongoDB client connection.
|
|
108
|
+
|
|
109
|
+
Should be called during application shutdown to properly release
|
|
110
|
+
all database connections.
|
|
111
|
+
"""
|
|
112
|
+
if self.db_client is not None:
|
|
113
|
+
self.db_client.close()
|
|
114
|
+
|
|
105
115
|
@property
|
|
106
116
|
def database(self) -> Database:
|
|
107
117
|
if self._database is None:
|
agno/db/mysql/async_mysql.py
CHANGED
|
@@ -123,6 +123,15 @@ class AsyncMySQLDb(AsyncBaseDb):
|
|
|
123
123
|
expire_on_commit=False,
|
|
124
124
|
)
|
|
125
125
|
|
|
126
|
+
async def close(self) -> None:
|
|
127
|
+
"""Close database connections and dispose of the connection pool.
|
|
128
|
+
|
|
129
|
+
Should be called during application shutdown to properly release
|
|
130
|
+
all database connections.
|
|
131
|
+
"""
|
|
132
|
+
if self.db_engine is not None:
|
|
133
|
+
await self.db_engine.dispose()
|
|
134
|
+
|
|
126
135
|
# -- DB methods --
|
|
127
136
|
async def table_exists(self, table_name: str) -> bool:
|
|
128
137
|
"""Check if a table with the given name exists in the MySQL database.
|
agno/db/mysql/mysql.py
CHANGED
|
@@ -121,6 +121,15 @@ class MySQLDb(BaseDb):
|
|
|
121
121
|
# Initialize database session
|
|
122
122
|
self.Session: scoped_session = scoped_session(sessionmaker(bind=self.db_engine))
|
|
123
123
|
|
|
124
|
+
def close(self) -> None:
|
|
125
|
+
"""Close database connections and dispose of the connection pool.
|
|
126
|
+
|
|
127
|
+
Should be called during application shutdown to properly release
|
|
128
|
+
all database connections.
|
|
129
|
+
"""
|
|
130
|
+
if self.db_engine is not None:
|
|
131
|
+
self.db_engine.dispose()
|
|
132
|
+
|
|
124
133
|
# -- DB methods --
|
|
125
134
|
def table_exists(self, table_name: str) -> bool:
|
|
126
135
|
"""Check if a table with the given name exists in the MySQL database.
|
|
@@ -128,6 +128,15 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
128
128
|
expire_on_commit=False,
|
|
129
129
|
)
|
|
130
130
|
|
|
131
|
+
async def close(self) -> None:
|
|
132
|
+
"""Close database connections and dispose of the connection pool.
|
|
133
|
+
|
|
134
|
+
Should be called during application shutdown to properly release
|
|
135
|
+
all database connections.
|
|
136
|
+
"""
|
|
137
|
+
if self.db_engine is not None:
|
|
138
|
+
await self.db_engine.dispose()
|
|
139
|
+
|
|
131
140
|
# -- DB methods --
|
|
132
141
|
async def table_exists(self, table_name: str) -> bool:
|
|
133
142
|
"""Check if a table with the given name exists in the Postgres database.
|
agno/db/postgres/postgres.py
CHANGED
|
@@ -124,6 +124,15 @@ class PostgresDb(BaseDb):
|
|
|
124
124
|
# Initialize database session
|
|
125
125
|
self.Session: scoped_session = scoped_session(sessionmaker(bind=self.db_engine, expire_on_commit=False))
|
|
126
126
|
|
|
127
|
+
def close(self) -> None:
|
|
128
|
+
"""Close database connections and dispose of the connection pool.
|
|
129
|
+
|
|
130
|
+
Should be called during application shutdown to properly release
|
|
131
|
+
all database connections.
|
|
132
|
+
"""
|
|
133
|
+
if self.db_engine is not None:
|
|
134
|
+
self.db_engine.dispose()
|
|
135
|
+
|
|
127
136
|
# -- DB methods --
|
|
128
137
|
def table_exists(self, table_name: str) -> bool:
|
|
129
138
|
"""Check if a table with the given name exists in the Postgres database.
|
agno/db/postgres/utils.py
CHANGED
|
@@ -298,8 +298,9 @@ def calculate_date_metrics(date_to_process: date, sessions_data: dict) -> dict:
|
|
|
298
298
|
for session in sessions:
|
|
299
299
|
if session.get("user_id"):
|
|
300
300
|
all_user_ids.add(session["user_id"])
|
|
301
|
-
|
|
302
|
-
|
|
301
|
+
runs = session.get("runs", []) or []
|
|
302
|
+
metrics[runs_count_key] += len(runs)
|
|
303
|
+
if runs:
|
|
303
304
|
for run in runs:
|
|
304
305
|
if model_id := run.get("model"):
|
|
305
306
|
model_provider = run.get("model_provider", "")
|
agno/db/sqlite/async_sqlite.py
CHANGED
|
@@ -124,6 +124,15 @@ class AsyncSqliteDb(AsyncBaseDb):
|
|
|
124
124
|
# Initialize database session factory
|
|
125
125
|
self.async_session_factory = async_sessionmaker(bind=self.db_engine, expire_on_commit=False)
|
|
126
126
|
|
|
127
|
+
async def close(self) -> None:
|
|
128
|
+
"""Close database connections and dispose of the connection pool.
|
|
129
|
+
|
|
130
|
+
Should be called during application shutdown to properly release
|
|
131
|
+
all database connections.
|
|
132
|
+
"""
|
|
133
|
+
if self.db_engine is not None:
|
|
134
|
+
await self.db_engine.dispose()
|
|
135
|
+
|
|
127
136
|
# -- DB methods --
|
|
128
137
|
async def table_exists(self, table_name: str) -> bool:
|
|
129
138
|
"""Check if a table with the given name exists in the SQLite database.
|
agno/db/sqlite/sqlite.py
CHANGED
|
@@ -125,6 +125,15 @@ class SqliteDb(BaseDb):
|
|
|
125
125
|
# Initialize database session
|
|
126
126
|
self.Session: scoped_session = scoped_session(sessionmaker(bind=self.db_engine))
|
|
127
127
|
|
|
128
|
+
def close(self) -> None:
|
|
129
|
+
"""Close database connections and dispose of the connection pool.
|
|
130
|
+
|
|
131
|
+
Should be called during application shutdown to properly release
|
|
132
|
+
all database connections.
|
|
133
|
+
"""
|
|
134
|
+
if self.db_engine is not None:
|
|
135
|
+
self.db_engine.dispose()
|
|
136
|
+
|
|
128
137
|
# -- DB methods --
|
|
129
138
|
def table_exists(self, table_name: str) -> bool:
|
|
130
139
|
"""Check if a table with the given name exists in the SQLite database.
|
|
@@ -1110,7 +1119,8 @@ class SqliteDb(BaseDb):
|
|
|
1110
1119
|
# Select topics from all results
|
|
1111
1120
|
stmt = select(table.c.topics)
|
|
1112
1121
|
result = sess.execute(stmt).fetchall()
|
|
1113
|
-
|
|
1122
|
+
result = result[0][0]
|
|
1123
|
+
return list(set(result))
|
|
1114
1124
|
|
|
1115
1125
|
except Exception as e:
|
|
1116
1126
|
log_debug(f"Exception reading from memory table: {e}")
|
agno/exceptions.py
CHANGED
|
@@ -178,3 +178,26 @@ class RetryableModelProviderError(Exception):
|
|
|
178
178
|
original_error: Optional[str] = None
|
|
179
179
|
# Guidance message to retry a model invocation after an error
|
|
180
180
|
retry_guidance_message: Optional[str] = None
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class RemoteServerUnavailableError(AgnoError):
|
|
184
|
+
"""Exception raised when a remote server is unavailable.
|
|
185
|
+
|
|
186
|
+
This can happen due to:
|
|
187
|
+
- Connection refused (server not running)
|
|
188
|
+
- Connection timeout
|
|
189
|
+
- Network errors
|
|
190
|
+
- DNS resolution failures
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
def __init__(
|
|
194
|
+
self,
|
|
195
|
+
message: str,
|
|
196
|
+
base_url: Optional[str] = None,
|
|
197
|
+
original_error: Optional[Exception] = None,
|
|
198
|
+
):
|
|
199
|
+
super().__init__(message, status_code=503)
|
|
200
|
+
self.base_url = base_url
|
|
201
|
+
self.original_error = original_error
|
|
202
|
+
self.type = "remote_server_unavailable_error"
|
|
203
|
+
self.error_id = "remote_server_unavailable_error"
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from typing import Any, Dict, List, Literal, Optional, Union
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
import numpy as np
|
|
5
|
+
except ImportError:
|
|
6
|
+
raise ImportError("`numpy` not installed. Please install using `pip install numpy`")
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from chonkie import SemanticChunker
|
|
10
|
+
from chonkie.embeddings.base import BaseEmbeddings
|
|
11
|
+
except ImportError:
|
|
12
|
+
raise ImportError(
|
|
13
|
+
"`chonkie` is required for semantic chunking. "
|
|
14
|
+
"Please install it using `pip install chonkie` to use SemanticChunking."
|
|
15
|
+
)
|
|
3
16
|
|
|
4
17
|
from agno.knowledge.chunking.strategy import ChunkingStrategy
|
|
5
18
|
from agno.knowledge.document.base import Document
|
|
@@ -7,10 +20,69 @@ from agno.knowledge.embedder.base import Embedder
|
|
|
7
20
|
from agno.utils.log import log_info
|
|
8
21
|
|
|
9
22
|
|
|
10
|
-
|
|
11
|
-
"""
|
|
23
|
+
def _get_chonkie_embedder_wrapper(embedder: Embedder):
|
|
24
|
+
"""Create a wrapper that adapts Agno Embedder to chonkie's BaseEmbeddings interface."""
|
|
25
|
+
|
|
26
|
+
class _ChonkieEmbedderWrapper(BaseEmbeddings):
|
|
27
|
+
"""Wrapper to make Agno Embedders compatible with chonkie."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, agno_embedder: Embedder):
|
|
30
|
+
super().__init__()
|
|
31
|
+
self._embedder = agno_embedder
|
|
32
|
+
|
|
33
|
+
def embed(self, text: str):
|
|
34
|
+
embedding = self._embedder.get_embedding(text) # type: ignore[attr-defined]
|
|
35
|
+
return np.array(embedding, dtype=np.float32)
|
|
36
|
+
|
|
37
|
+
def get_tokenizer(self):
|
|
38
|
+
"""Return a simple token counter function."""
|
|
39
|
+
return lambda text: len(text.split())
|
|
12
40
|
|
|
13
|
-
|
|
41
|
+
@property
|
|
42
|
+
def dimension(self) -> int:
|
|
43
|
+
return getattr(self._embedder, "dimensions")
|
|
44
|
+
|
|
45
|
+
return _ChonkieEmbedderWrapper(embedder)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class SemanticChunking(ChunkingStrategy):
|
|
49
|
+
"""Chunking strategy that splits text into semantic chunks using chonkie.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
embedder: The embedder to use for generating embeddings. Can be:
|
|
53
|
+
- A string model identifier (e.g., "minishlab/potion-base-32M") for chonkie's built-in models
|
|
54
|
+
- A chonkie BaseEmbeddings instance (used directly)
|
|
55
|
+
- An Agno Embedder (wrapped for chonkie compatibility)
|
|
56
|
+
chunk_size: Maximum tokens allowed per chunk.
|
|
57
|
+
similarity_threshold: Threshold for semantic similarity (0-1).
|
|
58
|
+
similarity_window: Number of sentences to consider for similarity calculation.
|
|
59
|
+
min_sentences_per_chunk: Minimum number of sentences per chunk.
|
|
60
|
+
min_characters_per_sentence: Minimum number of characters per sentence.
|
|
61
|
+
delimiters: Delimiters to use for sentence splitting.
|
|
62
|
+
include_delimiters: Whether to include delimiter in prev/next sentence or None.
|
|
63
|
+
skip_window: Number of groups to skip when merging (0=disabled).
|
|
64
|
+
filter_window: Window length for the Savitzky-Golay filter.
|
|
65
|
+
filter_polyorder: Polynomial order for the Savitzky-Golay filter.
|
|
66
|
+
filter_tolerance: Tolerance for the Savitzky-Golay filter.
|
|
67
|
+
chunker_params: Additional parameters to pass to chonkie's SemanticChunker.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
def __init__(
|
|
71
|
+
self,
|
|
72
|
+
embedder: Optional[Union[str, Embedder, BaseEmbeddings]] = None,
|
|
73
|
+
chunk_size: int = 5000,
|
|
74
|
+
similarity_threshold: float = 0.5,
|
|
75
|
+
similarity_window: int = 3,
|
|
76
|
+
min_sentences_per_chunk: int = 1,
|
|
77
|
+
min_characters_per_sentence: int = 24,
|
|
78
|
+
delimiters: Optional[List[str]] = None,
|
|
79
|
+
include_delimiters: Literal["prev", "next", None] = "prev",
|
|
80
|
+
skip_window: int = 0,
|
|
81
|
+
filter_window: int = 5,
|
|
82
|
+
filter_polyorder: int = 3,
|
|
83
|
+
filter_tolerance: float = 0.2,
|
|
84
|
+
chunker_params: Optional[Dict[str, Any]] = None,
|
|
85
|
+
):
|
|
14
86
|
if embedder is None:
|
|
15
87
|
from agno.knowledge.embedder.openai import OpenAIEmbedder
|
|
16
88
|
|
|
@@ -19,50 +91,55 @@ class SemanticChunking(ChunkingStrategy):
|
|
|
19
91
|
self.embedder = embedder
|
|
20
92
|
self.chunk_size = chunk_size
|
|
21
93
|
self.similarity_threshold = similarity_threshold
|
|
22
|
-
self.
|
|
94
|
+
self.similarity_window = similarity_window
|
|
95
|
+
self.min_sentences_per_chunk = min_sentences_per_chunk
|
|
96
|
+
self.min_characters_per_sentence = min_characters_per_sentence
|
|
97
|
+
self.delimiters = delimiters if delimiters is not None else [". ", "! ", "? ", "\n"]
|
|
98
|
+
self.include_delimiters = include_delimiters
|
|
99
|
+
self.skip_window = skip_window
|
|
100
|
+
self.filter_window = filter_window
|
|
101
|
+
self.filter_polyorder = filter_polyorder
|
|
102
|
+
self.filter_tolerance = filter_tolerance
|
|
103
|
+
self.chunker_params = chunker_params
|
|
104
|
+
self.chunker: Optional[SemanticChunker] = None
|
|
23
105
|
|
|
24
106
|
def _initialize_chunker(self):
|
|
25
107
|
"""Lazily initialize the chunker with chonkie dependency."""
|
|
26
|
-
if self.chunker is None:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
self.chunker = SemanticChunker( # type: ignore
|
|
62
|
-
embedding_model=getattr(self.embedder, "id", None) or "text-embedding-3-small",
|
|
63
|
-
chunk_size=self.chunk_size,
|
|
64
|
-
threshold=self.similarity_threshold,
|
|
65
|
-
)
|
|
108
|
+
if self.chunker is not None:
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
# Determine embedding model based on type:
|
|
112
|
+
# - str: pass directly to chonkie (uses chonkie's built-in models)
|
|
113
|
+
# - BaseEmbeddings: pass directly to chonkie
|
|
114
|
+
# - Agno Embedder: wrap for chonkie compatibility
|
|
115
|
+
embedding_model: Union[str, BaseEmbeddings]
|
|
116
|
+
if isinstance(self.embedder, str):
|
|
117
|
+
embedding_model = self.embedder
|
|
118
|
+
elif isinstance(self.embedder, BaseEmbeddings):
|
|
119
|
+
embedding_model = self.embedder
|
|
120
|
+
elif isinstance(self.embedder, Embedder):
|
|
121
|
+
embedding_model = _get_chonkie_embedder_wrapper(self.embedder)
|
|
122
|
+
else:
|
|
123
|
+
raise ValueError("Invalid embedder type. Must be a string, BaseEmbeddings, or Embedder instance.")
|
|
124
|
+
|
|
125
|
+
_chunker_params: Dict[str, Any] = {
|
|
126
|
+
"embedding_model": embedding_model,
|
|
127
|
+
"chunk_size": self.chunk_size,
|
|
128
|
+
"threshold": self.similarity_threshold,
|
|
129
|
+
"similarity_window": self.similarity_window,
|
|
130
|
+
"min_sentences_per_chunk": self.min_sentences_per_chunk,
|
|
131
|
+
"min_characters_per_sentence": self.min_characters_per_sentence,
|
|
132
|
+
"delim": self.delimiters,
|
|
133
|
+
"include_delim": self.include_delimiters,
|
|
134
|
+
"skip_window": self.skip_window,
|
|
135
|
+
"filter_window": self.filter_window,
|
|
136
|
+
"filter_polyorder": self.filter_polyorder,
|
|
137
|
+
"filter_tolerance": self.filter_tolerance,
|
|
138
|
+
}
|
|
139
|
+
if self.chunker_params:
|
|
140
|
+
_chunker_params.update(self.chunker_params)
|
|
141
|
+
|
|
142
|
+
self.chunker = SemanticChunker(**_chunker_params)
|
|
66
143
|
|
|
67
144
|
def chunk(self, document: Document) -> List[Document]:
|
|
68
145
|
"""Split document into semantic chunks using chonkie"""
|
|
@@ -77,4 +77,4 @@ class JSONReader(Reader):
|
|
|
77
77
|
|
|
78
78
|
async def async_read(self, path: Union[Path, IO[Any]], name: Optional[str] = None) -> List[Document]:
|
|
79
79
|
"""Asynchronously read JSON files."""
|
|
80
|
-
return await asyncio.to_thread(self.read, path, name)
|
|
80
|
+
return await asyncio.to_thread(self.read, path, name)
|
agno/models/google/gemini.py
CHANGED
|
@@ -25,6 +25,7 @@ from agno.utils.log import log_debug, log_error, log_info, log_warning
|
|
|
25
25
|
from agno.utils.tokens import count_schema_tokens, count_text_tokens, count_tool_tokens
|
|
26
26
|
|
|
27
27
|
try:
|
|
28
|
+
from google.oauth2.service_account import Credentials
|
|
28
29
|
from google import genai
|
|
29
30
|
from google.genai import Client as GeminiClient
|
|
30
31
|
from google.genai.errors import ClientError, ServerError
|
|
@@ -66,6 +67,7 @@ class Gemini(Model):
|
|
|
66
67
|
- Set `vertexai` to `True` to use the Vertex AI API.
|
|
67
68
|
- Set your `project_id` (or set `GOOGLE_CLOUD_PROJECT` environment variable) and `location` (optional).
|
|
68
69
|
- Set `http_options` (optional) to configure the HTTP options.
|
|
70
|
+
- Set `credentials` (optional) to use the Google Cloud credentials.
|
|
69
71
|
|
|
70
72
|
Based on https://googleapis.github.io/python-genai/
|
|
71
73
|
"""
|
|
@@ -110,6 +112,7 @@ class Gemini(Model):
|
|
|
110
112
|
request_params: Optional[Dict[str, Any]] = None
|
|
111
113
|
|
|
112
114
|
# Client parameters
|
|
115
|
+
credentials: Optional[Credentials] = None
|
|
113
116
|
api_key: Optional[str] = None
|
|
114
117
|
vertexai: bool = False
|
|
115
118
|
project_id: Optional[str] = None
|
|
@@ -158,6 +161,8 @@ class Gemini(Model):
|
|
|
158
161
|
log_error("GOOGLE_CLOUD_LOCATION not set. Please set the GOOGLE_CLOUD_LOCATION environment variable.")
|
|
159
162
|
client_params["project"] = project_id
|
|
160
163
|
client_params["location"] = location
|
|
164
|
+
if self.credentials:
|
|
165
|
+
client_params["credentials"] = self.credentials
|
|
161
166
|
|
|
162
167
|
client_params = {k: v for k, v in client_params.items() if v is not None}
|
|
163
168
|
|