veadk-python 0.2.9__py3-none-any.whl → 0.2.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of veadk-python might be problematic. Click here for more details.
- veadk/a2a/remote_ve_agent.py +63 -6
- veadk/agent.py +10 -3
- veadk/agent_builder.py +2 -3
- veadk/auth/veauth/ark_veauth.py +43 -51
- veadk/auth/veauth/utils.py +57 -0
- veadk/cli/cli.py +2 -0
- veadk/cli/cli_kb.py +75 -0
- veadk/cli/cli_web.py +4 -0
- veadk/configs/model_configs.py +3 -3
- veadk/consts.py +9 -0
- veadk/integrations/__init__.py +13 -0
- veadk/integrations/ve_viking_db_memory/__init__.py +13 -0
- veadk/integrations/ve_viking_db_memory/ve_viking_db_memory.py +293 -0
- veadk/knowledgebase/knowledgebase.py +19 -32
- veadk/memory/__init__.py +1 -1
- veadk/memory/long_term_memory.py +40 -68
- veadk/memory/long_term_memory_backends/base_backend.py +4 -2
- veadk/memory/long_term_memory_backends/in_memory_backend.py +8 -6
- veadk/memory/long_term_memory_backends/mem0_backend.py +25 -10
- veadk/memory/long_term_memory_backends/opensearch_backend.py +40 -36
- veadk/memory/long_term_memory_backends/redis_backend.py +59 -46
- veadk/memory/long_term_memory_backends/vikingdb_memory_backend.py +56 -35
- veadk/memory/short_term_memory.py +12 -8
- veadk/memory/short_term_memory_backends/postgresql_backend.py +3 -1
- veadk/runner.py +42 -19
- veadk/tools/builtin_tools/generate_image.py +56 -17
- veadk/tools/builtin_tools/image_edit.py +17 -7
- veadk/tools/builtin_tools/image_generate.py +17 -7
- veadk/tools/builtin_tools/load_knowledgebase.py +97 -0
- veadk/tools/builtin_tools/video_generate.py +11 -9
- veadk/tools/builtin_tools/web_search.py +10 -3
- veadk/tools/load_knowledgebase_tool.py +12 -0
- veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +5 -0
- veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +7 -0
- veadk/tracing/telemetry/exporters/apmplus_exporter.py +82 -2
- veadk/tracing/telemetry/exporters/inmemory_exporter.py +8 -2
- veadk/tracing/telemetry/telemetry.py +41 -5
- veadk/utils/misc.py +6 -10
- veadk/utils/volcengine_sign.py +2 -0
- veadk/version.py +1 -1
- {veadk_python-0.2.9.dist-info → veadk_python-0.2.11.dist-info}/METADATA +4 -3
- {veadk_python-0.2.9.dist-info → veadk_python-0.2.11.dist-info}/RECORD +46 -40
- {veadk_python-0.2.9.dist-info → veadk_python-0.2.11.dist-info}/WHEEL +0 -0
- {veadk_python-0.2.9.dist-info → veadk_python-0.2.11.dist-info}/entry_points.txt +0 -0
- {veadk_python-0.2.9.dist-info → veadk_python-0.2.11.dist-info}/licenses/LICENSE +0 -0
- {veadk_python-0.2.9.dist-info → veadk_python-0.2.11.dist-info}/top_level.txt +0 -0
veadk/runner.py
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import os
|
|
16
15
|
import functools
|
|
16
|
+
import os
|
|
17
17
|
from types import MethodType
|
|
18
18
|
from typing import Union
|
|
19
19
|
|
|
@@ -34,7 +34,7 @@ from veadk.evaluation import EvalSetRecorder
|
|
|
34
34
|
from veadk.memory.short_term_memory import ShortTermMemory
|
|
35
35
|
from veadk.types import MediaMessage
|
|
36
36
|
from veadk.utils.logger import get_logger
|
|
37
|
-
from veadk.utils.misc import formatted_timestamp,
|
|
37
|
+
from veadk.utils.misc import formatted_timestamp, read_file_to_bytes
|
|
38
38
|
|
|
39
39
|
logger = get_logger(__name__)
|
|
40
40
|
|
|
@@ -50,11 +50,7 @@ RunnerMessage = Union[
|
|
|
50
50
|
async def pre_run_process(self, process_func, new_message, user_id, session_id):
|
|
51
51
|
if new_message.parts:
|
|
52
52
|
for part in new_message.parts:
|
|
53
|
-
if
|
|
54
|
-
part.inline_data
|
|
55
|
-
and part.inline_data.mime_type == "image/png"
|
|
56
|
-
and self.upload_inline_data_to_tos
|
|
57
|
-
):
|
|
53
|
+
if part.inline_data and self.upload_inline_data_to_tos:
|
|
58
54
|
await process_func(
|
|
59
55
|
part,
|
|
60
56
|
self.app_name,
|
|
@@ -105,9 +101,20 @@ def _convert_messages(
|
|
|
105
101
|
if isinstance(messages, str):
|
|
106
102
|
_messages = [types.Content(role="user", parts=[types.Part(text=messages)])]
|
|
107
103
|
elif isinstance(messages, MediaMessage):
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
import filetype
|
|
105
|
+
|
|
106
|
+
file_data = read_file_to_bytes(messages.media)
|
|
107
|
+
|
|
108
|
+
kind = filetype.guess(file_data)
|
|
109
|
+
if kind is None:
|
|
110
|
+
raise ValueError("Unsupported or unknown file type.")
|
|
111
|
+
|
|
112
|
+
mime_type = kind.mime
|
|
113
|
+
|
|
114
|
+
assert mime_type.startswith(("image/", "video/")), (
|
|
115
|
+
f"Unsupported media type: {mime_type}"
|
|
110
116
|
)
|
|
117
|
+
|
|
111
118
|
_messages = [
|
|
112
119
|
types.Content(
|
|
113
120
|
role="user",
|
|
@@ -116,8 +123,8 @@ def _convert_messages(
|
|
|
116
123
|
types.Part(
|
|
117
124
|
inline_data=Blob(
|
|
118
125
|
display_name=messages.media,
|
|
119
|
-
data=
|
|
120
|
-
mime_type=
|
|
126
|
+
data=file_data,
|
|
127
|
+
mime_type=mime_type,
|
|
121
128
|
)
|
|
122
129
|
),
|
|
123
130
|
],
|
|
@@ -249,15 +256,21 @@ class Runner(ADKRunner):
|
|
|
249
256
|
)
|
|
250
257
|
|
|
251
258
|
if self.short_term_memory:
|
|
252
|
-
await self.short_term_memory.create_session(
|
|
253
|
-
app_name=self.app_name, user_id=
|
|
259
|
+
session = await self.short_term_memory.create_session(
|
|
260
|
+
app_name=self.app_name, user_id=user_id, session_id=session_id
|
|
261
|
+
)
|
|
262
|
+
assert session, (
|
|
263
|
+
f"Failed to create session with app_name={self.app_name}, user_id={user_id}, session_id={session_id}, "
|
|
264
|
+
)
|
|
265
|
+
logger.debug(
|
|
266
|
+
f"Auto create session: {session.id}, user_id: {session.user_id}, app_name: {self.app_name}"
|
|
254
267
|
)
|
|
255
268
|
|
|
256
269
|
final_output = ""
|
|
257
270
|
for converted_message in converted_messages:
|
|
258
271
|
try:
|
|
259
272
|
async for event in self.run_async(
|
|
260
|
-
user_id=
|
|
273
|
+
user_id=user_id,
|
|
261
274
|
session_id=session_id,
|
|
262
275
|
new_message=converted_message,
|
|
263
276
|
run_config=run_config,
|
|
@@ -271,7 +284,8 @@ class Runner(ADKRunner):
|
|
|
271
284
|
and event.content.parts[0].text is not None
|
|
272
285
|
and len(event.content.parts[0].text.strip()) > 0
|
|
273
286
|
):
|
|
274
|
-
final_output
|
|
287
|
+
final_output = event.content.parts[0].text
|
|
288
|
+
logger.debug(f"Event output: {final_output}")
|
|
275
289
|
except LlmCallsLimitExceededError as e:
|
|
276
290
|
logger.warning(f"Max number of llm calls limit exceeded: {e}")
|
|
277
291
|
final_output = ""
|
|
@@ -359,19 +373,28 @@ class Runner(ADKRunner):
|
|
|
359
373
|
)
|
|
360
374
|
return eval_set_path
|
|
361
375
|
|
|
362
|
-
async def save_session_to_long_term_memory(
|
|
376
|
+
async def save_session_to_long_term_memory(
|
|
377
|
+
self, session_id: str, user_id: str = "", app_name: str = ""
|
|
378
|
+
) -> None:
|
|
363
379
|
if not self.long_term_memory:
|
|
364
380
|
logger.warning("Long-term memory is not enabled. Failed to save session.")
|
|
365
381
|
return
|
|
366
382
|
|
|
383
|
+
if not user_id:
|
|
384
|
+
user_id = self.user_id
|
|
385
|
+
|
|
386
|
+
if not app_name:
|
|
387
|
+
app_name = self.app_name
|
|
388
|
+
|
|
367
389
|
session = await self.session_service.get_session(
|
|
368
|
-
app_name=
|
|
369
|
-
user_id=
|
|
390
|
+
app_name=app_name,
|
|
391
|
+
user_id=user_id,
|
|
370
392
|
session_id=session_id,
|
|
371
393
|
)
|
|
394
|
+
|
|
372
395
|
if not session:
|
|
373
396
|
logger.error(
|
|
374
|
-
f"Session {session_id} not found in session service, cannot save to long-term memory."
|
|
397
|
+
f"Session {session_id} (app_name={app_name}, user_id={user_id}) not found in session service, cannot save to long-term memory."
|
|
375
398
|
)
|
|
376
399
|
return
|
|
377
400
|
|
|
@@ -12,28 +12,35 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import base64
|
|
16
|
+
import json
|
|
17
|
+
import mimetypes
|
|
18
|
+
import traceback
|
|
15
19
|
from typing import Dict
|
|
16
20
|
|
|
17
21
|
from google.adk.tools import ToolContext
|
|
18
|
-
from
|
|
19
|
-
from veadk.consts import DEFAULT_IMAGE_GENERATE_MODEL_NAME, DEFAULT_MODEL_AGENT_API_BASE
|
|
20
|
-
|
|
21
|
-
import base64
|
|
22
|
-
from volcenginesdkarkruntime import Ark
|
|
22
|
+
from google.genai.types import Blob, Part
|
|
23
23
|
from opentelemetry import trace
|
|
24
|
-
import traceback
|
|
25
|
-
from veadk.version import VERSION
|
|
26
24
|
from opentelemetry.trace import Span
|
|
27
|
-
from
|
|
25
|
+
from volcenginesdkarkruntime import Ark
|
|
28
26
|
from volcenginesdkarkruntime.types.images.images import SequentialImageGenerationOptions
|
|
29
|
-
import json
|
|
30
27
|
|
|
28
|
+
from veadk.config import getenv, settings
|
|
29
|
+
from veadk.consts import (
|
|
30
|
+
DEFAULT_IMAGE_GENERATE_MODEL_NAME,
|
|
31
|
+
DEFAULT_IMAGE_GENERATE_MODEL_API_BASE,
|
|
32
|
+
)
|
|
33
|
+
from veadk.utils.logger import get_logger
|
|
34
|
+
from veadk.utils.misc import formatted_timestamp, read_file_to_bytes
|
|
35
|
+
from veadk.version import VERSION
|
|
31
36
|
|
|
32
37
|
logger = get_logger(__name__)
|
|
33
38
|
|
|
34
39
|
client = Ark(
|
|
35
|
-
api_key=getenv(
|
|
36
|
-
|
|
40
|
+
api_key=getenv(
|
|
41
|
+
"MODEL_IMAGE_API_KEY", getenv("MODEL_AGENT_API_KEY", settings.model.api_key)
|
|
42
|
+
),
|
|
43
|
+
base_url=getenv("MODEL_IMAGE_API_BASE", DEFAULT_IMAGE_GENERATE_MODEL_API_BASE),
|
|
37
44
|
)
|
|
38
45
|
|
|
39
46
|
|
|
@@ -121,7 +128,7 @@ async def image_generate(
|
|
|
121
128
|
- size 推荐使用 2048x2048 或表格里的标准比例,确保生成质量。
|
|
122
129
|
"""
|
|
123
130
|
|
|
124
|
-
success_list = []
|
|
131
|
+
success_list: list[dict] = []
|
|
125
132
|
error_list = []
|
|
126
133
|
|
|
127
134
|
for idx, item in enumerate(tasks):
|
|
@@ -184,7 +191,9 @@ async def image_generate(
|
|
|
184
191
|
and max_images
|
|
185
192
|
):
|
|
186
193
|
response = client.images.generate(
|
|
187
|
-
model=
|
|
194
|
+
model=getenv(
|
|
195
|
+
"MODEL_IMAGE_NAME", DEFAULT_IMAGE_GENERATE_MODEL_NAME
|
|
196
|
+
),
|
|
188
197
|
**inputs,
|
|
189
198
|
sequential_image_generation_options=SequentialImageGenerationOptions(
|
|
190
199
|
max_images=max_images
|
|
@@ -192,7 +201,10 @@ async def image_generate(
|
|
|
192
201
|
)
|
|
193
202
|
else:
|
|
194
203
|
response = client.images.generate(
|
|
195
|
-
model=
|
|
204
|
+
model=getenv(
|
|
205
|
+
"MODEL_IMAGE_NAME", DEFAULT_IMAGE_GENERATE_MODEL_NAME
|
|
206
|
+
),
|
|
207
|
+
**inputs,
|
|
196
208
|
)
|
|
197
209
|
if not response.error:
|
|
198
210
|
for i, image_data in enumerate(response.data):
|
|
@@ -261,8 +273,12 @@ async def image_generate(
|
|
|
261
273
|
output_part=output_part,
|
|
262
274
|
output_tokens=output_tokens,
|
|
263
275
|
total_tokens=total_tokens,
|
|
264
|
-
request_model=
|
|
265
|
-
|
|
276
|
+
request_model=getenv(
|
|
277
|
+
"MODEL_IMAGE_NAME", DEFAULT_IMAGE_GENERATE_MODEL_NAME
|
|
278
|
+
),
|
|
279
|
+
response_model=getenv(
|
|
280
|
+
"MODEL_IMAGE_NAME", DEFAULT_IMAGE_GENERATE_MODEL_NAME
|
|
281
|
+
),
|
|
266
282
|
)
|
|
267
283
|
if len(success_list) == 0:
|
|
268
284
|
return {
|
|
@@ -271,6 +287,28 @@ async def image_generate(
|
|
|
271
287
|
"error_list": error_list,
|
|
272
288
|
}
|
|
273
289
|
else:
|
|
290
|
+
app_name = tool_context._invocation_context.app_name
|
|
291
|
+
user_id = tool_context._invocation_context.user_id
|
|
292
|
+
session_id = tool_context._invocation_context.session.id
|
|
293
|
+
|
|
294
|
+
artifact_service = tool_context._invocation_context.artifact_service
|
|
295
|
+
if artifact_service:
|
|
296
|
+
for image in success_list:
|
|
297
|
+
for _, image_tos_url in image.items():
|
|
298
|
+
filename = f"artifact_{formatted_timestamp()}"
|
|
299
|
+
await artifact_service.save_artifact(
|
|
300
|
+
app_name=app_name,
|
|
301
|
+
user_id=user_id,
|
|
302
|
+
session_id=session_id,
|
|
303
|
+
filename=filename,
|
|
304
|
+
artifact=Part(
|
|
305
|
+
inline_data=Blob(
|
|
306
|
+
display_name=filename,
|
|
307
|
+
data=read_file_to_bytes(image_tos_url),
|
|
308
|
+
mime_type=mimetypes.guess_type(image_tos_url)[0],
|
|
309
|
+
)
|
|
310
|
+
),
|
|
311
|
+
)
|
|
274
312
|
return {
|
|
275
313
|
"status": "success",
|
|
276
314
|
"success_list": success_list,
|
|
@@ -332,10 +370,11 @@ def add_span_attributes(
|
|
|
332
370
|
|
|
333
371
|
def _upload_image_to_tos(image_bytes: bytes, object_key: str) -> None:
|
|
334
372
|
try:
|
|
335
|
-
from veadk.integrations.ve_tos.ve_tos import VeTOS
|
|
336
373
|
import os
|
|
337
374
|
from datetime import datetime
|
|
338
375
|
|
|
376
|
+
from veadk.integrations.ve_tos.ve_tos import VeTOS
|
|
377
|
+
|
|
339
378
|
timestamp: str = datetime.now().strftime("%Y%m%d%H%M%S%f")[:-3]
|
|
340
379
|
object_key = f"{timestamp}-{object_key}"
|
|
341
380
|
bucket_name = os.getenv("DATABASE_TOS_BUCKET")
|
|
@@ -15,8 +15,11 @@
|
|
|
15
15
|
from typing import Dict
|
|
16
16
|
from google.adk.tools import ToolContext
|
|
17
17
|
from volcenginesdkarkruntime import Ark
|
|
18
|
-
from veadk.config import getenv
|
|
19
|
-
from veadk.consts import
|
|
18
|
+
from veadk.config import getenv, settings
|
|
19
|
+
from veadk.consts import (
|
|
20
|
+
DEFAULT_IMAGE_EDIT_MODEL_API_BASE,
|
|
21
|
+
DEFAULT_IMAGE_EDIT_MODEL_NAME,
|
|
22
|
+
)
|
|
20
23
|
import base64
|
|
21
24
|
from opentelemetry import trace
|
|
22
25
|
import traceback
|
|
@@ -28,8 +31,10 @@ from veadk.utils.logger import get_logger
|
|
|
28
31
|
logger = get_logger(__name__)
|
|
29
32
|
|
|
30
33
|
client = Ark(
|
|
31
|
-
api_key=getenv(
|
|
32
|
-
|
|
34
|
+
api_key=getenv(
|
|
35
|
+
"MODEL_EDIT_API_KEY", getenv("MODEL_AGENT_API_KEY", settings.model.api_key)
|
|
36
|
+
),
|
|
37
|
+
base_url=getenv("MODEL_EDIT_API_BASE", DEFAULT_IMAGE_EDIT_MODEL_API_BASE),
|
|
33
38
|
)
|
|
34
39
|
|
|
35
40
|
|
|
@@ -123,7 +128,8 @@ async def image_edit(
|
|
|
123
128
|
"parts.1.image_url.url": origin_image,
|
|
124
129
|
}
|
|
125
130
|
response = client.images.generate(
|
|
126
|
-
model=DEFAULT_IMAGE_EDIT_MODEL_NAME,
|
|
131
|
+
model=getenv("MODEL_EDIT_NAME", DEFAULT_IMAGE_EDIT_MODEL_NAME),
|
|
132
|
+
**inputs,
|
|
127
133
|
)
|
|
128
134
|
output_part = None
|
|
129
135
|
if response.data and len(response.data) > 0:
|
|
@@ -175,8 +181,12 @@ async def image_edit(
|
|
|
175
181
|
output_part=output_part,
|
|
176
182
|
output_tokens=response.usage.output_tokens,
|
|
177
183
|
total_tokens=response.usage.total_tokens,
|
|
178
|
-
request_model=
|
|
179
|
-
|
|
184
|
+
request_model=getenv(
|
|
185
|
+
"MODEL_EDIT_NAME", DEFAULT_IMAGE_EDIT_MODEL_NAME
|
|
186
|
+
),
|
|
187
|
+
response_model=getenv(
|
|
188
|
+
"MODEL_EDIT_NAME", DEFAULT_IMAGE_EDIT_MODEL_NAME
|
|
189
|
+
),
|
|
180
190
|
)
|
|
181
191
|
|
|
182
192
|
except Exception as e:
|
|
@@ -15,8 +15,11 @@
|
|
|
15
15
|
from typing import Dict
|
|
16
16
|
|
|
17
17
|
from google.adk.tools import ToolContext
|
|
18
|
-
from veadk.config import getenv
|
|
19
|
-
from veadk.consts import
|
|
18
|
+
from veadk.config import getenv, settings
|
|
19
|
+
from veadk.consts import (
|
|
20
|
+
DEFAULT_TEXT_TO_IMAGE_MODEL_NAME,
|
|
21
|
+
DEFAULT_TEXT_TO_IMAGE_MODEL_API_BASE,
|
|
22
|
+
)
|
|
20
23
|
import base64
|
|
21
24
|
from volcenginesdkarkruntime import Ark
|
|
22
25
|
from opentelemetry import trace
|
|
@@ -29,8 +32,10 @@ from veadk.utils.logger import get_logger
|
|
|
29
32
|
logger = get_logger(__name__)
|
|
30
33
|
|
|
31
34
|
client = Ark(
|
|
32
|
-
api_key=getenv(
|
|
33
|
-
|
|
35
|
+
api_key=getenv(
|
|
36
|
+
"MODEL_IMAGE_API_KEY", getenv("MODEL_AGENT_API_KEY", settings.model.api_key)
|
|
37
|
+
),
|
|
38
|
+
base_url=getenv("MODEL_IMAGE_API_BASE", DEFAULT_TEXT_TO_IMAGE_MODEL_API_BASE),
|
|
34
39
|
)
|
|
35
40
|
|
|
36
41
|
|
|
@@ -120,7 +125,8 @@ async def image_generate(
|
|
|
120
125
|
"content": json.dumps(inputs, ensure_ascii=False),
|
|
121
126
|
}
|
|
122
127
|
response = client.images.generate(
|
|
123
|
-
model=DEFAULT_TEXT_TO_IMAGE_MODEL_NAME,
|
|
128
|
+
model=getenv("MODEL_IMAGE_NAME", DEFAULT_TEXT_TO_IMAGE_MODEL_NAME),
|
|
129
|
+
**inputs,
|
|
124
130
|
)
|
|
125
131
|
output_part = None
|
|
126
132
|
if response.data and len(response.data) > 0:
|
|
@@ -172,8 +178,12 @@ async def image_generate(
|
|
|
172
178
|
output_part=output_part,
|
|
173
179
|
output_tokens=response.usage.output_tokens,
|
|
174
180
|
total_tokens=response.usage.total_tokens,
|
|
175
|
-
request_model=
|
|
176
|
-
|
|
181
|
+
request_model=getenv(
|
|
182
|
+
"MODEL_IMAGE_NAME", DEFAULT_TEXT_TO_IMAGE_MODEL_NAME
|
|
183
|
+
),
|
|
184
|
+
response_model=getenv(
|
|
185
|
+
"MODEL_IMAGE_NAME", DEFAULT_TEXT_TO_IMAGE_MODEL_NAME
|
|
186
|
+
),
|
|
177
187
|
)
|
|
178
188
|
|
|
179
189
|
except Exception as e:
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from google.adk.models.llm_request import LlmRequest
|
|
18
|
+
from google.adk.tools.function_tool import FunctionTool
|
|
19
|
+
from google.adk.tools.tool_context import ToolContext
|
|
20
|
+
from google.genai import types
|
|
21
|
+
from pydantic import BaseModel, Field
|
|
22
|
+
from typing_extensions import override
|
|
23
|
+
|
|
24
|
+
from veadk.knowledgebase import KnowledgeBase
|
|
25
|
+
from veadk.knowledgebase.entry import KnowledgebaseEntry
|
|
26
|
+
from veadk.utils.logger import get_logger
|
|
27
|
+
|
|
28
|
+
logger = get_logger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class LoadKnowledgebaseResponse(BaseModel):
|
|
32
|
+
knowledges: list[KnowledgebaseEntry] = Field(default_factory=list)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class LoadKnowledgebaseTool(FunctionTool):
|
|
36
|
+
"""A tool that loads the common knowledgebase"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, knowledgebase: KnowledgeBase):
|
|
39
|
+
super().__init__(self.load_knowledgebase)
|
|
40
|
+
|
|
41
|
+
self.knowledgebase = knowledgebase
|
|
42
|
+
|
|
43
|
+
if not self.custom_metadata:
|
|
44
|
+
self.custom_metadata = {}
|
|
45
|
+
self.custom_metadata["backend"] = knowledgebase.backend
|
|
46
|
+
|
|
47
|
+
@override
|
|
48
|
+
def _get_declaration(self) -> types.FunctionDeclaration | None:
|
|
49
|
+
return types.FunctionDeclaration(
|
|
50
|
+
name=self.name,
|
|
51
|
+
description=self.description,
|
|
52
|
+
parameters=types.Schema(
|
|
53
|
+
type=types.Type.OBJECT,
|
|
54
|
+
properties={
|
|
55
|
+
"query": types.Schema(
|
|
56
|
+
type=types.Type.STRING,
|
|
57
|
+
)
|
|
58
|
+
},
|
|
59
|
+
required=["query"],
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
@override
|
|
64
|
+
async def process_llm_request(
|
|
65
|
+
self,
|
|
66
|
+
*,
|
|
67
|
+
tool_context: ToolContext,
|
|
68
|
+
llm_request: LlmRequest,
|
|
69
|
+
) -> None:
|
|
70
|
+
await super().process_llm_request(
|
|
71
|
+
tool_context=tool_context, llm_request=llm_request
|
|
72
|
+
)
|
|
73
|
+
# Tell the model about the knowledgebase.
|
|
74
|
+
llm_request.append_instructions(
|
|
75
|
+
[
|
|
76
|
+
f"""
|
|
77
|
+
You have a knowledgebase (knowledegebase name is `{self.knowledgebase.name}`, knowledgebase description is `{self.knowledgebase.description}`). You can use it to answer questions. If any questions need
|
|
78
|
+
you to look up the knowledgebase, you should call load_knowledgebase function with a query.
|
|
79
|
+
"""
|
|
80
|
+
]
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
async def load_knowledgebase(
|
|
84
|
+
self, query: str, tool_context: ToolContext
|
|
85
|
+
) -> LoadKnowledgebaseResponse:
|
|
86
|
+
"""Loads the knowledgebase for the user.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
query: The query to load the knowledgebase for.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
A list of knowledgebase results.
|
|
93
|
+
"""
|
|
94
|
+
logger.info(f"Search knowledgebase: {self.knowledgebase.name}")
|
|
95
|
+
response = self.knowledgebase.search(query)
|
|
96
|
+
logger.info(f"Loaded {len(response)} knowledgebase entries for query: {query}")
|
|
97
|
+
return LoadKnowledgebaseResponse(knowledges=response)
|
|
@@ -25,16 +25,18 @@ from volcenginesdkarkruntime.types.content_generation.create_task_content_param
|
|
|
25
25
|
CreateTaskContentParam,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
from veadk.config import getenv
|
|
29
|
-
from veadk.consts import
|
|
28
|
+
from veadk.config import getenv, settings
|
|
29
|
+
from veadk.consts import DEFAULT_VIDEO_MODEL_API_BASE, DEFAULT_VIDEO_MODEL_NAME
|
|
30
30
|
from veadk.utils.logger import get_logger
|
|
31
31
|
from veadk.version import VERSION
|
|
32
32
|
|
|
33
33
|
logger = get_logger(__name__)
|
|
34
34
|
|
|
35
35
|
client = Ark(
|
|
36
|
-
api_key=getenv(
|
|
37
|
-
|
|
36
|
+
api_key=getenv(
|
|
37
|
+
"MODEL_VIDEO_API_KEY", getenv("MODEL_AGENT_API_KEY", settings.model.api_key)
|
|
38
|
+
),
|
|
39
|
+
base_url=getenv("MODEL_VIDEO_API_BASE", DEFAULT_VIDEO_MODEL_API_BASE),
|
|
38
40
|
)
|
|
39
41
|
|
|
40
42
|
|
|
@@ -43,7 +45,7 @@ async def generate(prompt, first_frame_image=None, last_frame_image=None):
|
|
|
43
45
|
if first_frame_image is None:
|
|
44
46
|
logger.debug("text generation")
|
|
45
47
|
response = client.content_generation.tasks.create(
|
|
46
|
-
model=DEFAULT_VIDEO_MODEL_NAME,
|
|
48
|
+
model=getenv("MODEL_VIDEO_NAME", DEFAULT_VIDEO_MODEL_NAME),
|
|
47
49
|
content=[
|
|
48
50
|
{"type": "text", "text": prompt},
|
|
49
51
|
],
|
|
@@ -51,7 +53,7 @@ async def generate(prompt, first_frame_image=None, last_frame_image=None):
|
|
|
51
53
|
elif last_frame_image is None:
|
|
52
54
|
logger.debug("first frame generation")
|
|
53
55
|
response = client.content_generation.tasks.create(
|
|
54
|
-
model=DEFAULT_VIDEO_MODEL_NAME,
|
|
56
|
+
model=getenv("MODEL_VIDEO_NAME", DEFAULT_VIDEO_MODEL_NAME),
|
|
55
57
|
content=cast(
|
|
56
58
|
list[CreateTaskContentParam], # avoid IDE warning
|
|
57
59
|
[
|
|
@@ -66,7 +68,7 @@ async def generate(prompt, first_frame_image=None, last_frame_image=None):
|
|
|
66
68
|
else:
|
|
67
69
|
logger.debug("last frame generation")
|
|
68
70
|
response = client.content_generation.tasks.create(
|
|
69
|
-
model=DEFAULT_VIDEO_MODEL_NAME,
|
|
71
|
+
model=getenv("MODEL_VIDEO_NAME", DEFAULT_VIDEO_MODEL_NAME),
|
|
70
72
|
content=[
|
|
71
73
|
{"type": "text", "text": prompt},
|
|
72
74
|
{
|
|
@@ -263,8 +265,8 @@ async def video_generate(params: list, tool_context: ToolContext) -> Dict:
|
|
|
263
265
|
output_part=output_part,
|
|
264
266
|
output_tokens=total_tokens,
|
|
265
267
|
total_tokens=total_tokens,
|
|
266
|
-
request_model=DEFAULT_VIDEO_MODEL_NAME,
|
|
267
|
-
response_model=DEFAULT_VIDEO_MODEL_NAME,
|
|
268
|
+
request_model=getenv("MODEL_VIDEO_NAME", DEFAULT_VIDEO_MODEL_NAME),
|
|
269
|
+
response_model=getenv("MODEL_VIDEO_NAME", DEFAULT_VIDEO_MODEL_NAME),
|
|
268
270
|
)
|
|
269
271
|
|
|
270
272
|
if len(success_list) == 0:
|
|
@@ -23,6 +23,7 @@ import json
|
|
|
23
23
|
from urllib.parse import quote
|
|
24
24
|
|
|
25
25
|
import requests
|
|
26
|
+
from google.adk.tools import ToolContext
|
|
26
27
|
|
|
27
28
|
from veadk.config import getenv
|
|
28
29
|
from veadk.utils.logger import get_logger
|
|
@@ -151,7 +152,7 @@ def request(method, date, query, header, ak, sk, action, body):
|
|
|
151
152
|
return r.json()
|
|
152
153
|
|
|
153
154
|
|
|
154
|
-
def web_search(query: str) -> list[str]:
|
|
155
|
+
def web_search(query: str, tool_context: ToolContext) -> list[str]:
|
|
155
156
|
"""Search a query in websites.
|
|
156
157
|
|
|
157
158
|
Args:
|
|
@@ -166,8 +167,14 @@ def web_search(query: str) -> list[str]:
|
|
|
166
167
|
"Count": 5,
|
|
167
168
|
"NeedSummary": True,
|
|
168
169
|
}
|
|
169
|
-
|
|
170
|
-
|
|
170
|
+
|
|
171
|
+
ak = tool_context.state.get("VOLCENGINE_ACCESS_KEY")
|
|
172
|
+
if not ak:
|
|
173
|
+
ak = getenv("VOLCENGINE_ACCESS_KEY")
|
|
174
|
+
|
|
175
|
+
sk = tool_context.state.get("VOLCENGINE_SECRET_KEY")
|
|
176
|
+
if not sk:
|
|
177
|
+
sk = getenv("VOLCENGINE_SECRET_KEY")
|
|
171
178
|
|
|
172
179
|
now = datetime.datetime.utcnow()
|
|
173
180
|
response_body = request(
|
|
@@ -25,6 +25,9 @@ from typing_extensions import override
|
|
|
25
25
|
|
|
26
26
|
from veadk.knowledgebase import KnowledgeBase
|
|
27
27
|
from veadk.knowledgebase.entry import KnowledgebaseEntry
|
|
28
|
+
from veadk.utils.logger import get_logger
|
|
29
|
+
|
|
30
|
+
logger = get_logger(__name__)
|
|
28
31
|
|
|
29
32
|
if TYPE_CHECKING:
|
|
30
33
|
from google.adk.models.llm_request import LlmRequest
|
|
@@ -96,6 +99,15 @@ class LoadKnowledgebaseTool(FunctionTool):
|
|
|
96
99
|
|
|
97
100
|
def __init__(self):
|
|
98
101
|
super().__init__(load_knowledgebase)
|
|
102
|
+
global knowledgebase
|
|
103
|
+
if knowledgebase is None:
|
|
104
|
+
logger.info(
|
|
105
|
+
"Get global knowledgebase instance failed, failed to set knowledgebase tool backend."
|
|
106
|
+
)
|
|
107
|
+
else:
|
|
108
|
+
if not self.custom_metadata:
|
|
109
|
+
self.custom_metadata = {}
|
|
110
|
+
self.custom_metadata["backend"] = knowledgebase.backend
|
|
99
111
|
|
|
100
112
|
@override
|
|
101
113
|
def _get_declaration(self) -> types.FunctionDeclaration | None:
|
|
@@ -325,6 +325,10 @@ def llm_gen_ai_operation_name(params: LLMAttributesParams) -> ExtractorResponse:
|
|
|
325
325
|
return ExtractorResponse(content="chat")
|
|
326
326
|
|
|
327
327
|
|
|
328
|
+
def llm_gen_ai_span_kind(params: LLMAttributesParams) -> ExtractorResponse:
|
|
329
|
+
return ExtractorResponse(content="llm")
|
|
330
|
+
|
|
331
|
+
|
|
328
332
|
# def llm_gen_ai_system_message(params: LLMAttributesParams) -> ExtractorResponse:
|
|
329
333
|
# event_attributes = {
|
|
330
334
|
# "content": str(params.llm_request.config.system_instruction),
|
|
@@ -559,6 +563,7 @@ LLM_ATTRIBUTES = {
|
|
|
559
563
|
"gen_ai.is_streaming": llm_gen_ai_is_streaming,
|
|
560
564
|
# -> 1.4. span kind
|
|
561
565
|
"gen_ai.operation.name": llm_gen_ai_operation_name,
|
|
566
|
+
"gen_ai.span.kind": llm_gen_ai_span_kind, # apmplus required
|
|
562
567
|
# -> 1.5. inputs
|
|
563
568
|
"gen_ai.prompt": llm_gen_ai_prompt,
|
|
564
569
|
# -> 1.6. outputs
|
|
@@ -23,6 +23,10 @@ def tool_gen_ai_operation_name(params: ToolAttributesParams) -> ExtractorRespons
|
|
|
23
23
|
return ExtractorResponse(content="execute_tool")
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def tool_gen_ai_span_kind(params: ToolAttributesParams) -> ExtractorResponse:
|
|
27
|
+
return ExtractorResponse(content="tool")
|
|
28
|
+
|
|
29
|
+
|
|
26
30
|
def tool_gen_ai_tool_message(params: ToolAttributesParams) -> ExtractorResponse:
|
|
27
31
|
tool_input = {
|
|
28
32
|
"role": "tool",
|
|
@@ -73,4 +77,7 @@ TOOL_ATTRIBUTES = {
|
|
|
73
77
|
"gen_ai.tool.output": tool_gen_ai_tool_output, # TLS required
|
|
74
78
|
"cozeloop.input": tool_gen_ai_tool_input, # CozeLoop required
|
|
75
79
|
"cozeloop.output": tool_gen_ai_tool_output, # CozeLoop required
|
|
80
|
+
"gen_ai.span.kind": tool_gen_ai_span_kind, # apmplus required
|
|
81
|
+
"gen_ai.input": tool_gen_ai_tool_input, # apmplus required
|
|
82
|
+
"gen_ai.output": tool_gen_ai_tool_output, # apmplus required
|
|
76
83
|
}
|