veadk-python 0.2.16__py3-none-any.whl → 0.2.17__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.
- veadk/a2a/remote_ve_agent.py +56 -1
- veadk/agent.py +79 -26
- veadk/agents/loop_agent.py +22 -9
- veadk/agents/parallel_agent.py +21 -9
- veadk/agents/sequential_agent.py +18 -9
- veadk/auth/veauth/apmplus_veauth.py +32 -39
- veadk/auth/veauth/ark_veauth.py +3 -1
- veadk/auth/veauth/utils.py +12 -0
- veadk/auth/veauth/viking_mem0_veauth.py +91 -0
- veadk/cli/cli.py +5 -1
- veadk/cli/cli_create.py +62 -1
- veadk/cli/cli_deploy.py +36 -1
- veadk/cli/cli_eval.py +55 -0
- veadk/cli/cli_init.py +44 -3
- veadk/cli/cli_kb.py +36 -1
- veadk/cli/cli_pipeline.py +66 -1
- veadk/cli/cli_prompt.py +16 -1
- veadk/cli/cli_uploadevalset.py +15 -1
- veadk/cli/cli_web.py +35 -4
- veadk/cloud/cloud_agent_engine.py +142 -25
- veadk/cloud/cloud_app.py +219 -12
- veadk/configs/database_configs.py +4 -0
- veadk/configs/model_configs.py +5 -1
- veadk/configs/tracing_configs.py +2 -2
- veadk/evaluation/adk_evaluator/adk_evaluator.py +77 -17
- veadk/evaluation/base_evaluator.py +219 -3
- veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +116 -1
- veadk/evaluation/eval_set_file_loader.py +20 -0
- veadk/evaluation/eval_set_recorder.py +54 -0
- veadk/evaluation/types.py +32 -0
- veadk/evaluation/utils/prometheus.py +61 -0
- veadk/knowledgebase/backends/base_backend.py +14 -1
- veadk/knowledgebase/backends/in_memory_backend.py +10 -1
- veadk/knowledgebase/backends/opensearch_backend.py +26 -0
- veadk/knowledgebase/backends/redis_backend.py +29 -2
- veadk/knowledgebase/backends/vikingdb_knowledge_backend.py +43 -5
- veadk/knowledgebase/knowledgebase.py +173 -12
- veadk/memory/long_term_memory.py +148 -4
- veadk/memory/long_term_memory_backends/mem0_backend.py +11 -0
- veadk/memory/short_term_memory.py +119 -5
- veadk/runner.py +412 -1
- veadk/tools/builtin_tools/llm_shield.py +381 -0
- veadk/tools/builtin_tools/mcp_router.py +9 -2
- veadk/tools/builtin_tools/run_code.py +25 -5
- veadk/tools/builtin_tools/web_search.py +38 -154
- veadk/tracing/base_tracer.py +28 -1
- veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +105 -1
- veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +260 -0
- veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +69 -0
- veadk/tracing/telemetry/attributes/extractors/types.py +78 -0
- veadk/tracing/telemetry/exporters/apmplus_exporter.py +157 -0
- veadk/tracing/telemetry/exporters/base_exporter.py +8 -0
- veadk/tracing/telemetry/exporters/cozeloop_exporter.py +60 -1
- veadk/tracing/telemetry/exporters/inmemory_exporter.py +118 -1
- veadk/tracing/telemetry/exporters/tls_exporter.py +66 -0
- veadk/tracing/telemetry/opentelemetry_tracer.py +111 -1
- veadk/tracing/telemetry/telemetry.py +118 -2
- veadk/version.py +1 -1
- {veadk_python-0.2.16.dist-info → veadk_python-0.2.17.dist-info}/METADATA +1 -1
- {veadk_python-0.2.16.dist-info → veadk_python-0.2.17.dist-info}/RECORD +64 -62
- {veadk_python-0.2.16.dist-info → veadk_python-0.2.17.dist-info}/WHEEL +0 -0
- {veadk_python-0.2.16.dist-info → veadk_python-0.2.17.dist-info}/entry_points.txt +0 -0
- {veadk_python-0.2.16.dist-info → veadk_python-0.2.17.dist-info}/licenses/LICENSE +0 -0
- {veadk_python-0.2.16.dist-info → veadk_python-0.2.17.dist-info}/top_level.txt +0 -0
|
@@ -50,20 +50,87 @@ def wrap_get_session_with_callbacks(obj, callback_fn: Callable):
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
class ShortTermMemory(BaseModel):
|
|
53
|
+
"""Short term memory for agent execution.
|
|
54
|
+
|
|
55
|
+
The short term memory represents the context of the agent model. All content in the short term memory will be sent to agent model directly, including the system prompt, historical user prompt, and historical model responses.
|
|
56
|
+
|
|
57
|
+
Attributes:
|
|
58
|
+
backend (Literal["local", "mysql", "sqlite", "postgresql", "database"]):
|
|
59
|
+
The backend of short term memory:
|
|
60
|
+
- `local` for in-memory storage
|
|
61
|
+
- `mysql` for mysql / PostgreSQL storage
|
|
62
|
+
- `sqlite` for locally sqlite storage
|
|
63
|
+
backend_configs (dict): Configuration dict for init short term memory backend.
|
|
64
|
+
db_url (str):
|
|
65
|
+
Database connection url for init short term memory backend.
|
|
66
|
+
For example, `sqlite:///./test.db`. Once set, it will override the `backend` parameter.
|
|
67
|
+
local_database_path (str):
|
|
68
|
+
Local database path, only used when `backend` is `sqlite`.
|
|
69
|
+
Default to `/tmp/veadk_local_database.db`.
|
|
70
|
+
after_load_memory_callback (Callable | None):
|
|
71
|
+
A callback to be called after loading memory from the backend. The callback function should accept `Session` as an input.
|
|
72
|
+
|
|
73
|
+
Examples:
|
|
74
|
+
### In-memory simple memory
|
|
75
|
+
|
|
76
|
+
You can initialize a short term memory with in-memory storage:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from veadk import Agent, Runner
|
|
80
|
+
from veadk.memory.short_term_memory import ShortTermMemory
|
|
81
|
+
import asyncio
|
|
82
|
+
|
|
83
|
+
session_id = "veadk_playground_session"
|
|
84
|
+
|
|
85
|
+
agent = Agent()
|
|
86
|
+
short_term_memory = ShortTermMemory(backend="local")
|
|
87
|
+
|
|
88
|
+
runner = Runner(
|
|
89
|
+
agent=agent, short_term_memory=short_term_memory)
|
|
90
|
+
|
|
91
|
+
# This invocation will be stored in short-term memory
|
|
92
|
+
response = asyncio.run(runner.run(
|
|
93
|
+
messages="My name is VeADK", session_id=session_id
|
|
94
|
+
))
|
|
95
|
+
print(response)
|
|
96
|
+
|
|
97
|
+
# The history invocation can be fetched by model
|
|
98
|
+
response = asyncio.run(runner.run(
|
|
99
|
+
messages="Do you remember my name?", session_id=session_id # keep the same `session_id`
|
|
100
|
+
))
|
|
101
|
+
print(response)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Memory with a Database URL
|
|
105
|
+
|
|
106
|
+
Also you can use a databasae connection URL to initialize a short-term memory:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from veadk.memory.short_term_memory import ShortTermMemory
|
|
110
|
+
|
|
111
|
+
short_term_memory = ShortTermMemory(db_url="...")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Memory with SQLite
|
|
115
|
+
|
|
116
|
+
Once you want to start the short term memory with a local SQLite, you can specify the backend to `sqlite`. It will create a local database in `local_database_path`:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from veadk.memory.short_term_memory import ShortTermMemory
|
|
120
|
+
|
|
121
|
+
short_term_memory = ShortTermMemory(backend="sqlite", local_database_path="")
|
|
122
|
+
```
|
|
123
|
+
"""
|
|
124
|
+
|
|
53
125
|
backend: Literal["local", "mysql", "sqlite", "postgresql", "database"] = "local"
|
|
54
|
-
"""Short term memory backend. `Local` for in-memory storage, `mysql` for mysql / PostgreSQL storage. `sqlite` for sqlite storage."""
|
|
55
126
|
|
|
56
127
|
backend_configs: dict = Field(default_factory=dict)
|
|
57
|
-
"""Backend specific configurations."""
|
|
58
128
|
|
|
59
129
|
db_url: str = ""
|
|
60
|
-
"""Database connection URL, e.g. `sqlite:///./test.db`. Once set, it will override the `backend` parameter."""
|
|
61
130
|
|
|
62
131
|
local_database_path: str = "/tmp/veadk_local_database.db"
|
|
63
|
-
"""Local database path, only used when `backend` is `sqlite`. Default to `/tmp/veadk_local_database.db`."""
|
|
64
132
|
|
|
65
133
|
after_load_memory_callback: Callable | None = None
|
|
66
|
-
"""A callback to be called after loading memory from the backend. The callback function should accept `Session` as an input."""
|
|
67
134
|
|
|
68
135
|
_session_service: BaseSessionService = PrivateAttr()
|
|
69
136
|
|
|
@@ -108,6 +175,53 @@ class ShortTermMemory(BaseModel):
|
|
|
108
175
|
user_id: str,
|
|
109
176
|
session_id: str,
|
|
110
177
|
) -> Session | None:
|
|
178
|
+
"""Create or retrieve a user session.
|
|
179
|
+
|
|
180
|
+
Short term memory can attempt to create a new session for a given application and user. If a session with the same `session_id` already exists, it will be returned instead of creating a new one.
|
|
181
|
+
|
|
182
|
+
If the underlying session service is backed by a database (`DatabaseSessionService`), the method first lists all existing sessions for the given `app_name` and `user_id` and logs the number of sessions found. It then checks whether a session with the specified `session_id` already exists:
|
|
183
|
+
- If it exists → returns the existing session.
|
|
184
|
+
- If it does not exist → creates and returns a new session.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
app_name (str): The name of the application associated with the session.
|
|
188
|
+
user_id (str): The unique identifier of the user.
|
|
189
|
+
session_id (str): The unique identifier of the session to be created or retrieved.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
Session | None: The retrieved or newly created `Session` object, or `None` if the session creation failed.
|
|
193
|
+
|
|
194
|
+
Examples:
|
|
195
|
+
Create a new session manually:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
import asyncio
|
|
199
|
+
|
|
200
|
+
from veadk.memory import ShortTermMemory
|
|
201
|
+
|
|
202
|
+
app_name = "app_name"
|
|
203
|
+
user_id = "user_id"
|
|
204
|
+
session_id = "session_id"
|
|
205
|
+
|
|
206
|
+
short_term_memory = ShortTermMemory()
|
|
207
|
+
|
|
208
|
+
session = asyncio.run(
|
|
209
|
+
short_term_memory.create_session(
|
|
210
|
+
app_name=app_name, user_id=user_id, session_id=session_id
|
|
211
|
+
)
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
print(session)
|
|
215
|
+
|
|
216
|
+
session = asyncio.run(
|
|
217
|
+
short_term_memory.session_service.get_session(
|
|
218
|
+
app_name=app_name, user_id=user_id, session_id=session_id
|
|
219
|
+
)
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
print(session)
|
|
223
|
+
```
|
|
224
|
+
"""
|
|
111
225
|
if isinstance(self._session_service, DatabaseSessionService):
|
|
112
226
|
list_sessions_response = await self._session_service.list_sessions(
|
|
113
227
|
app_name=app_name, user_id=user_id
|
veadk/runner.py
CHANGED
|
@@ -48,6 +48,28 @@ RunnerMessage = Union[
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
async def pre_run_process(self, process_func, new_message, user_id, session_id):
|
|
51
|
+
"""Pre-run hook invoked before agent execution.
|
|
52
|
+
|
|
53
|
+
Iterates over all ``parts`` of ``new_message`` and, when a ``part`` contains
|
|
54
|
+
``inline_data`` and uploading is enabled, calls ``process_func`` to process
|
|
55
|
+
the data (for example, upload to TOS and rewrite with an accessible URL).
|
|
56
|
+
Typically used together with the ``intercept_new_message`` decorator.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
self: Runner instance.
|
|
60
|
+
process_func: An async processing function with a signature like
|
|
61
|
+
``(part, app_name, user_id, session_id)`` used to handle
|
|
62
|
+
``inline_data`` in the message (e.g., upload to TOS).
|
|
63
|
+
new_message (google.genai.types.Content): Incoming user message.
|
|
64
|
+
user_id (str): User identifier.
|
|
65
|
+
session_id (str): Session identifier.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
None
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
Exception: Propagated if ``process_func`` raises and does not handle it.
|
|
72
|
+
"""
|
|
51
73
|
if new_message.parts:
|
|
52
74
|
for part in new_message.parts:
|
|
53
75
|
if part.inline_data and self.upload_inline_data_to_tos:
|
|
@@ -60,10 +82,42 @@ async def pre_run_process(self, process_func, new_message, user_id, session_id):
|
|
|
60
82
|
|
|
61
83
|
|
|
62
84
|
def post_run_process(self):
|
|
85
|
+
"""Post-run hook executed after agent run.
|
|
86
|
+
|
|
87
|
+
This is currently a no-op placeholder and can be extended to perform
|
|
88
|
+
cleanup or finalize logic after a run.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
self: Runner instance.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
None
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
None
|
|
98
|
+
"""
|
|
63
99
|
return
|
|
64
100
|
|
|
65
101
|
|
|
66
102
|
def intercept_new_message(process_func):
|
|
103
|
+
"""Create a decorator to insert pre/post hooks around ``run_async`` calls.
|
|
104
|
+
|
|
105
|
+
Internally it invokes :func:`pre_run_process` to preprocess the incoming
|
|
106
|
+
message (e.g., upload image/video inline data to TOS), then iterates the
|
|
107
|
+
underlying event stream and finally calls :func:`post_run_process`.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
process_func: Async function used to process ``inline_data`` (typically
|
|
111
|
+
``_upload_image_to_tos``).
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Callable: A decorator that can wrap ``run_async``.
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
Exception: May propagate exceptions raised by the wrapped function or
|
|
118
|
+
the pre-processing step.
|
|
119
|
+
"""
|
|
120
|
+
|
|
67
121
|
def decorator(func):
|
|
68
122
|
@functools.wraps(func)
|
|
69
123
|
async def wrapper(
|
|
@@ -97,7 +151,34 @@ def _convert_messages(
|
|
|
97
151
|
user_id: str,
|
|
98
152
|
session_id: str,
|
|
99
153
|
) -> list:
|
|
100
|
-
"""Convert VeADK
|
|
154
|
+
"""Convert a VeADK ``RunnerMessage`` into a list of Google ADK messages.
|
|
155
|
+
|
|
156
|
+
Supported inputs:
|
|
157
|
+
- ``str``: Single-turn text prompt.
|
|
158
|
+
- :class:`veadk.types.MediaMessage`: Single-turn multimodal prompt (text + image/video).
|
|
159
|
+
- ``list``: A list of the above types (multi-turn with mixed text and multimodal).
|
|
160
|
+
|
|
161
|
+
For multimodal inputs, this reads the local media file bytes and detects
|
|
162
|
+
the MIME type via ``filetype``; only ``image/*`` and ``video/*`` are supported.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
messages (RunnerMessage): Input message or list of messages to convert.
|
|
166
|
+
app_name (str): App name (not directly used; kept for consistency with upload path).
|
|
167
|
+
user_id (str): User ID (not directly used; kept for consistency with upload path).
|
|
168
|
+
session_id (str): Session ID (not directly used; kept for consistency with upload path).
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
list[google.genai.types.Content]: Converted ADK messages.
|
|
172
|
+
|
|
173
|
+
Raises:
|
|
174
|
+
ValueError: If the message type is unknown or media type is unrecognized.
|
|
175
|
+
AssertionError: If the media MIME type is not supported (only image/* and video/*).
|
|
176
|
+
|
|
177
|
+
Note:
|
|
178
|
+
This function only performs structural conversion. To upload inline media
|
|
179
|
+
to an object store and rewrite URLs, use it together with
|
|
180
|
+
``intercept_new_message`` and ``_upload_image_to_tos``.
|
|
181
|
+
"""
|
|
101
182
|
if isinstance(messages, str):
|
|
102
183
|
_messages = [types.Content(role="user", parts=[types.Part(text=messages)])]
|
|
103
184
|
elif isinstance(messages, MediaMessage):
|
|
@@ -146,6 +227,25 @@ def _convert_messages(
|
|
|
146
227
|
async def _upload_image_to_tos(
|
|
147
228
|
part: genai.types.Part, app_name: str, user_id: str, session_id: str
|
|
148
229
|
) -> None:
|
|
230
|
+
"""Upload inline media data in a message part to TOS and rewrite its URL.
|
|
231
|
+
|
|
232
|
+
When ``part.inline_data`` has both ``display_name`` (original filename) and
|
|
233
|
+
``data`` (bytes), it generates an object storage path based on
|
|
234
|
+
``app_name``, ``user_id`` and ``session_id``. After upload, it replaces
|
|
235
|
+
``display_name`` with a signed URL.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
part (google.genai.types.Part): Message part containing ``inline_data``.
|
|
239
|
+
app_name (str): App name.
|
|
240
|
+
user_id (str): User ID.
|
|
241
|
+
session_id (str): Session ID.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
None
|
|
245
|
+
|
|
246
|
+
Raises:
|
|
247
|
+
None: All exceptions are caught and logged; nothing is propagated.
|
|
248
|
+
"""
|
|
149
249
|
try:
|
|
150
250
|
if part.inline_data and part.inline_data.display_name and part.inline_data.data:
|
|
151
251
|
from veadk.integrations.ve_tos.ve_tos import VeTOS
|
|
@@ -164,6 +264,153 @@ async def _upload_image_to_tos(
|
|
|
164
264
|
|
|
165
265
|
|
|
166
266
|
class Runner(ADKRunner):
|
|
267
|
+
"""VeADK Runner that augments ADK with session, memory, tracing, and media upload.
|
|
268
|
+
|
|
269
|
+
This class builds on Google ADK's ``Runner`` and adds:
|
|
270
|
+
- Integration with short-term memory (ShortTermMemory) for auto session management.
|
|
271
|
+
- Optional long-term memory integration and session persistence.
|
|
272
|
+
- New message interception and media upload to TOS.
|
|
273
|
+
- Tracing dump and Trace ID logging.
|
|
274
|
+
- A simplified ``run`` entry that supports multi-turn text/multimodal inputs.
|
|
275
|
+
|
|
276
|
+
Attributes:
|
|
277
|
+
user_id (str): Default user ID.
|
|
278
|
+
long_term_memory: Long-term memory service instance, or ``None`` if not set.
|
|
279
|
+
short_term_memory (veadk.memory.short_term_memory.ShortTermMemory | None):
|
|
280
|
+
Short-term memory instance used to auto-create/manage sessions.
|
|
281
|
+
upload_inline_data_to_tos (bool): Whether to upload inline media to TOS while running.
|
|
282
|
+
session_service: Session service instance (may come from short-term memory).
|
|
283
|
+
memory_service: Memory service instance (may come from agent's long-term memory).
|
|
284
|
+
app_name (str): Application name used in session management and object pathing.
|
|
285
|
+
|
|
286
|
+
Note:
|
|
287
|
+
This class wraps the parent ``run_async`` at initialization to insert media
|
|
288
|
+
upload and post-run handling. If you override the underlying ``run_async``,
|
|
289
|
+
ensure it remains compatible with this interception logic.
|
|
290
|
+
|
|
291
|
+
Examples:
|
|
292
|
+
### Text-only interaction
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
import asyncio
|
|
296
|
+
|
|
297
|
+
from veadk import Agent, Runner
|
|
298
|
+
|
|
299
|
+
agent = Agent()
|
|
300
|
+
|
|
301
|
+
runner = Runner(agent=agent)
|
|
302
|
+
|
|
303
|
+
response = asyncio.run(runner.run(messages="北京的天气怎么样?"))
|
|
304
|
+
|
|
305
|
+
print(response)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Send multimodal data to agent
|
|
309
|
+
|
|
310
|
+
Currently, VeADK support send multimodal data (i.e., text with images) to agent, and invoke the corresponding model to do tasks.
|
|
311
|
+
|
|
312
|
+
!!! info "Note for multimodal running"
|
|
313
|
+
|
|
314
|
+
When sending multimodal data to agent, the model of agent must support multimodal data processing. For example, `doubao-1-6`.
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
import asyncio
|
|
318
|
+
|
|
319
|
+
from veadk import Agent, Runner
|
|
320
|
+
from veadk.types import MediaMessage
|
|
321
|
+
|
|
322
|
+
agent = Agent(model_name="doubao-seed-1-6-250615")
|
|
323
|
+
|
|
324
|
+
runner = Runner(agent=agent)
|
|
325
|
+
|
|
326
|
+
message = MediaMessage(
|
|
327
|
+
text="Describe the image",
|
|
328
|
+
media="https://...", # <-- replace here with an image from web
|
|
329
|
+
)
|
|
330
|
+
response = asyncio.run(runner.run(messages=message))
|
|
331
|
+
|
|
332
|
+
print(response)
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Run with run_async
|
|
336
|
+
|
|
337
|
+
You are recommand that **using `run_async` in production to invoke agent**. During running, the loop will throw out `event`, you can process each `event` according to your requirements.
|
|
338
|
+
|
|
339
|
+
```python
|
|
340
|
+
import uuid
|
|
341
|
+
|
|
342
|
+
from google.genai import types
|
|
343
|
+
from veadk import Agent, Runner
|
|
344
|
+
|
|
345
|
+
APP_NAME = "app"
|
|
346
|
+
USER_ID = "user"
|
|
347
|
+
|
|
348
|
+
agent = Agent()
|
|
349
|
+
|
|
350
|
+
runner = Runner(agent=agent, app_name=APP_NAME)
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
async def main(message: types.Content, session_id: str):
|
|
354
|
+
# before running, you should create a session first
|
|
355
|
+
await runner.short_term_memory.create_session(
|
|
356
|
+
app_name=APP_NAME, user_id=USER_ID, session_id=session_id
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
async for event in runner.run_async(
|
|
360
|
+
user_id=USER_ID,
|
|
361
|
+
session_id=session_id,
|
|
362
|
+
new_message=message,
|
|
363
|
+
):
|
|
364
|
+
# process event here
|
|
365
|
+
print(event)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
if __name__ == "__main__":
|
|
369
|
+
import asyncio
|
|
370
|
+
|
|
371
|
+
message = types.Content(parts=[types.Part(text="Hello")], role="user")
|
|
372
|
+
session_id = str(uuid.uuid1())
|
|
373
|
+
asyncio.run(main(message=message, session_id=session_id))
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### Custom your message
|
|
377
|
+
|
|
378
|
+
You can custom your message content, as Google provides some basic types to build and custom agent's input. For example, you can build a message with a text and several images.
|
|
379
|
+
|
|
380
|
+
```python
|
|
381
|
+
from google.genai import types
|
|
382
|
+
|
|
383
|
+
# build message with a text
|
|
384
|
+
message = types.Content(parts=[types.Part(text="Hello")], role="user")
|
|
385
|
+
|
|
386
|
+
# build message with a text and an image
|
|
387
|
+
message = types.Content(
|
|
388
|
+
parts=[
|
|
389
|
+
types.Part(text="Hello!"),
|
|
390
|
+
types.Part(
|
|
391
|
+
inline_data=types.Blob(display_name="foo.png", data=..., mime_type=...)
|
|
392
|
+
),
|
|
393
|
+
],
|
|
394
|
+
role="user",
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
# build image with several text and several images
|
|
398
|
+
message = types.Content(
|
|
399
|
+
parts=[
|
|
400
|
+
types.Part(text="Hello!"),
|
|
401
|
+
types.Part(text="Please help me to describe the following images."),
|
|
402
|
+
types.Part(
|
|
403
|
+
inline_data=types.Blob(display_name="foo.png", data=..., mime_type=...)
|
|
404
|
+
),
|
|
405
|
+
types.Part(
|
|
406
|
+
inline_data=types.Blob(display_name="bar.png", data=..., mime_type=...)
|
|
407
|
+
),
|
|
408
|
+
],
|
|
409
|
+
role="user",
|
|
410
|
+
)
|
|
411
|
+
```
|
|
412
|
+
"""
|
|
413
|
+
|
|
167
414
|
def __init__(
|
|
168
415
|
self,
|
|
169
416
|
agent: BaseAgent | Agent,
|
|
@@ -174,6 +421,33 @@ class Runner(ADKRunner):
|
|
|
174
421
|
*args,
|
|
175
422
|
**kwargs,
|
|
176
423
|
) -> None:
|
|
424
|
+
"""Initialize a Runner instance.
|
|
425
|
+
|
|
426
|
+
Selects the session service based on provided short-term memory or an
|
|
427
|
+
external ``session_service``. If long-term memory or an external
|
|
428
|
+
``memory_service`` is provided, the passed service is preferred. After
|
|
429
|
+
construction, it injects a message interception layer into the parent's
|
|
430
|
+
``run_async`` to support inline media upload and post-run handling.
|
|
431
|
+
|
|
432
|
+
Args:
|
|
433
|
+
agent (google.adk.agents.base_agent.BaseAgent | veadk.agent.Agent):
|
|
434
|
+
The agent instance used to run interactions.
|
|
435
|
+
short_term_memory (ShortTermMemory | None): Optional short-term memory; if
|
|
436
|
+
not provided and no external ``session_service`` is supplied, an in-memory
|
|
437
|
+
session service will be created.
|
|
438
|
+
app_name (str): Application name. Defaults to ``"veadk_default_app"``.
|
|
439
|
+
user_id (str): Default user ID. Defaults to ``"veadk_default_user"``.
|
|
440
|
+
upload_inline_data_to_tos (bool): Whether to enable inline media upload. Defaults to ``False``.
|
|
441
|
+
*args: Positional args passed through to ``ADKRunner``.
|
|
442
|
+
**kwargs: Keyword args passed through to ``ADKRunner``; may include
|
|
443
|
+
``session_service`` and ``memory_service`` to override defaults.
|
|
444
|
+
|
|
445
|
+
Returns:
|
|
446
|
+
None
|
|
447
|
+
|
|
448
|
+
Raises:
|
|
449
|
+
None
|
|
450
|
+
"""
|
|
177
451
|
self.user_id = user_id
|
|
178
452
|
self.long_term_memory = None
|
|
179
453
|
self.short_term_memory = short_term_memory
|
|
@@ -238,6 +512,30 @@ class Runner(ADKRunner):
|
|
|
238
512
|
save_tracing_data: bool = False,
|
|
239
513
|
upload_inline_data_to_tos: bool = False,
|
|
240
514
|
):
|
|
515
|
+
"""Run a conversation with multi-turn text and multimodal inputs.
|
|
516
|
+
|
|
517
|
+
When short-term memory is configured, a session is auto-created as needed.
|
|
518
|
+
Inputs are converted into ADK message format. If ``upload_inline_data_to_tos``
|
|
519
|
+
is ``True``, media upload is enabled temporarily for this run (does not change
|
|
520
|
+
the Runner's global setting).
|
|
521
|
+
|
|
522
|
+
Args:
|
|
523
|
+
messages (RunnerMessage): Input messages (``str``, ``MediaMessage`` or a list of them).
|
|
524
|
+
user_id (str): Override default user ID; if empty, uses the constructed ``user_id``.
|
|
525
|
+
session_id (str): Session ID. Defaults to a timestamp-based temporary ID.
|
|
526
|
+
run_config (google.adk.agents.RunConfig | None): Run config; if ``None``, a default
|
|
527
|
+
config is created using the environment var ``MODEL_AGENT_MAX_LLM_CALLS``.
|
|
528
|
+
save_tracing_data (bool): Whether to dump tracing data to disk after the run. Defaults to ``False``.
|
|
529
|
+
upload_inline_data_to_tos (bool): Whether to enable media upload only for this run. Defaults to ``False``.
|
|
530
|
+
|
|
531
|
+
Returns:
|
|
532
|
+
str: The textual output from the last event, if present; otherwise an empty string.
|
|
533
|
+
|
|
534
|
+
Raises:
|
|
535
|
+
ValueError: If an input contains an unsupported or unrecognized media type.
|
|
536
|
+
AssertionError: If a media MIME type is not among ``image/*`` or ``video/*``.
|
|
537
|
+
Exception: Exceptions from the underlying ADK/Agent execution may propagate.
|
|
538
|
+
"""
|
|
241
539
|
if upload_inline_data_to_tos:
|
|
242
540
|
_upload_inline_data_to_tos = self.upload_inline_data_to_tos
|
|
243
541
|
self.upload_inline_data_to_tos = upload_inline_data_to_tos
|
|
@@ -302,6 +600,17 @@ class Runner(ADKRunner):
|
|
|
302
600
|
return final_output
|
|
303
601
|
|
|
304
602
|
def get_trace_id(self) -> str:
|
|
603
|
+
"""Get the Trace ID from the current agent's tracer.
|
|
604
|
+
|
|
605
|
+
If the agent is not a :class:`veadk.agent.Agent` or no tracer is configured,
|
|
606
|
+
returns ``"<unknown_trace_id>"``.
|
|
607
|
+
|
|
608
|
+
Returns:
|
|
609
|
+
str: The Trace ID or ``"<unknown_trace_id>"``.
|
|
610
|
+
|
|
611
|
+
Raises:
|
|
612
|
+
None
|
|
613
|
+
"""
|
|
305
614
|
if not isinstance(self.agent, Agent):
|
|
306
615
|
logger.warning(
|
|
307
616
|
("The agent is not an instance of VeADK Agent, no trace id provided.")
|
|
@@ -322,6 +631,17 @@ class Runner(ADKRunner):
|
|
|
322
631
|
return "<unknown_trace_id>"
|
|
323
632
|
|
|
324
633
|
def _print_trace_id(self) -> None:
|
|
634
|
+
"""Log the current tracer's Trace ID.
|
|
635
|
+
|
|
636
|
+
If the agent is not a :class:`veadk.agent.Agent` or no tracer is configured,
|
|
637
|
+
nothing is printed.
|
|
638
|
+
|
|
639
|
+
Returns:
|
|
640
|
+
None
|
|
641
|
+
|
|
642
|
+
Raises:
|
|
643
|
+
None
|
|
644
|
+
"""
|
|
325
645
|
if not isinstance(self.agent, Agent):
|
|
326
646
|
logger.warning(
|
|
327
647
|
("The agent is not an instance of VeADK Agent, no trace id provided.")
|
|
@@ -342,6 +662,37 @@ class Runner(ADKRunner):
|
|
|
342
662
|
return
|
|
343
663
|
|
|
344
664
|
def save_tracing_file(self, session_id: str) -> str:
|
|
665
|
+
"""Dump tracing data to disk and return the last written path.
|
|
666
|
+
|
|
667
|
+
Only effective when the agent is one of
|
|
668
|
+
Agent/SequentialAgent/ParallelAgent/LoopAgent and a tracer is configured;
|
|
669
|
+
otherwise returns an empty string.
|
|
670
|
+
|
|
671
|
+
Args:
|
|
672
|
+
session_id (str): Session ID used to associate the tracing with a session.
|
|
673
|
+
|
|
674
|
+
Returns:
|
|
675
|
+
str: The tracing file path; returns an empty string on failure or when no tracer.
|
|
676
|
+
|
|
677
|
+
Examples:
|
|
678
|
+
You can save the tracing data to a local file.
|
|
679
|
+
|
|
680
|
+
```python
|
|
681
|
+
import asyncio
|
|
682
|
+
|
|
683
|
+
from veadk import Agent, Runner
|
|
684
|
+
|
|
685
|
+
agent = Agent()
|
|
686
|
+
|
|
687
|
+
runner = Runner(agent=agent)
|
|
688
|
+
|
|
689
|
+
session_id = "session"
|
|
690
|
+
asyncio.run(runner.run(messages="Hi!", session_id=session_id))
|
|
691
|
+
|
|
692
|
+
path = runner.save_tracing_file(session_id=session_id)
|
|
693
|
+
print(path)
|
|
694
|
+
```
|
|
695
|
+
"""
|
|
345
696
|
if not isinstance(
|
|
346
697
|
self.agent, (Agent, SequentialAgent, ParallelAgent, LoopAgent)
|
|
347
698
|
):
|
|
@@ -367,6 +718,34 @@ class Runner(ADKRunner):
|
|
|
367
718
|
return ""
|
|
368
719
|
|
|
369
720
|
async def save_eval_set(self, session_id: str, eval_set_id: str = "default") -> str:
|
|
721
|
+
"""Save the current session as part of an evaluation set and return its path.
|
|
722
|
+
|
|
723
|
+
Args:
|
|
724
|
+
session_id (str): Session ID.
|
|
725
|
+
eval_set_id (str): Evaluation set identifier. Defaults to ``"default"``.
|
|
726
|
+
|
|
727
|
+
Returns:
|
|
728
|
+
str: The exported evaluation set file path.
|
|
729
|
+
|
|
730
|
+
Examples:
|
|
731
|
+
You can save the specific session as a evaluation set in Google ADK format.
|
|
732
|
+
|
|
733
|
+
```python
|
|
734
|
+
import asyncio
|
|
735
|
+
|
|
736
|
+
from veadk import Agent, Runner
|
|
737
|
+
|
|
738
|
+
agent = Agent()
|
|
739
|
+
|
|
740
|
+
runner = Runner(agent=agent)
|
|
741
|
+
|
|
742
|
+
session_id = "session"
|
|
743
|
+
asyncio.run(runner.run(messages="Hi!", session_id=session_id))
|
|
744
|
+
|
|
745
|
+
path = runner.save_eval_set(session_id=session_id)
|
|
746
|
+
print(path)
|
|
747
|
+
```
|
|
748
|
+
"""
|
|
370
749
|
eval_set_recorder = EvalSetRecorder(self.session_service, eval_set_id)
|
|
371
750
|
eval_set_path = await eval_set_recorder.dump(
|
|
372
751
|
self.app_name, self.user_id, session_id
|
|
@@ -376,6 +755,38 @@ class Runner(ADKRunner):
|
|
|
376
755
|
async def save_session_to_long_term_memory(
|
|
377
756
|
self, session_id: str, user_id: str = "", app_name: str = ""
|
|
378
757
|
) -> None:
|
|
758
|
+
"""Save the specified session to long-term memory.
|
|
759
|
+
|
|
760
|
+
If ``long_term_memory`` is not configured, the function logs a warning and returns.
|
|
761
|
+
It fetches the session from the session service and then calls the long-term memory's
|
|
762
|
+
``add_session_to_memory`` for persistence.
|
|
763
|
+
|
|
764
|
+
Args:
|
|
765
|
+
session_id (str): Session ID.
|
|
766
|
+
user_id (str): Optional; override default user ID. If empty, uses ``self.user_id``.
|
|
767
|
+
app_name (str): Optional; override default app name. If empty, uses ``self.app_name``.
|
|
768
|
+
|
|
769
|
+
Examples:
|
|
770
|
+
You can save a specific session to long-term memory.
|
|
771
|
+
|
|
772
|
+
```python
|
|
773
|
+
import asyncio
|
|
774
|
+
|
|
775
|
+
from veadk import Agent, Runner
|
|
776
|
+
from veadk.memory import LongTermMemory
|
|
777
|
+
|
|
778
|
+
APP_NAME = "app"
|
|
779
|
+
|
|
780
|
+
agent = Agent(long_term_memory=LongTermMemory(backend="local", app_name=APP_NAME))
|
|
781
|
+
|
|
782
|
+
session_id = "session"
|
|
783
|
+
runner = Runner(agent=agent, app_name=APP_NAME)
|
|
784
|
+
|
|
785
|
+
asyncio.run(runner.run(messages="Hi!", session_id=session_id))
|
|
786
|
+
|
|
787
|
+
asyncio.run(runner.save_session_to_long_term_memory(session_id=session_id))
|
|
788
|
+
```
|
|
789
|
+
"""
|
|
379
790
|
if not self.long_term_memory:
|
|
380
791
|
logger.warning("Long-term memory is not enabled. Failed to save session.")
|
|
381
792
|
return
|