veadk-python 0.2.2__py3-none-any.whl → 0.2.4__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/agent.py +3 -13
- veadk/agents/loop_agent.py +55 -0
- veadk/agents/parallel_agent.py +60 -0
- veadk/agents/sequential_agent.py +55 -0
- veadk/cli/cli_deploy.py +11 -0
- veadk/cli/cli_web.py +27 -0
- veadk/evaluation/adk_evaluator/__init__.py +4 -0
- veadk/evaluation/adk_evaluator/adk_evaluator.py +170 -217
- veadk/evaluation/base_evaluator.py +26 -20
- veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +8 -5
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +37 -7
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +2 -6
- veadk/integrations/ve_faas/ve_faas.py +5 -1
- veadk/runner.py +55 -5
- veadk/tracing/base_tracer.py +25 -200
- veadk/tracing/telemetry/{metrics/__init__.py → attributes/attributes.py} +16 -0
- veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +71 -0
- veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +392 -0
- veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +70 -0
- veadk/tracing/telemetry/attributes/extractors/types.py +75 -0
- veadk/tracing/telemetry/exporters/apmplus_exporter.py +97 -38
- veadk/tracing/telemetry/exporters/base_exporter.py +10 -10
- veadk/tracing/telemetry/exporters/cozeloop_exporter.py +20 -13
- veadk/tracing/telemetry/exporters/inmemory_exporter.py +46 -32
- veadk/tracing/telemetry/exporters/tls_exporter.py +18 -12
- veadk/tracing/telemetry/opentelemetry_tracer.py +102 -102
- veadk/tracing/telemetry/telemetry.py +149 -0
- veadk/types.py +6 -1
- veadk/utils/misc.py +1 -1
- veadk/utils/patches.py +25 -0
- veadk/version.py +1 -1
- veadk_python-0.2.4.dist-info/METADATA +345 -0
- veadk_python-0.2.4.dist-info/RECORD +122 -0
- veadk/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/__pycache__/agent.cpython-310.pyc +0 -0
- veadk/__pycache__/config.cpython-310.pyc +0 -0
- veadk/__pycache__/consts.cpython-310.pyc +0 -0
- veadk/__pycache__/runner.cpython-310.pyc +0 -0
- veadk/__pycache__/types.cpython-310.pyc +0 -0
- veadk/__pycache__/version.cpython-310.pyc +0 -0
- veadk/a2a/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/a2a/__pycache__/agent_card.cpython-310.pyc +0 -0
- veadk/a2a/__pycache__/remote_ve_agent.cpython-310.pyc +0 -0
- veadk/a2a/__pycache__/ve_a2a_server.cpython-310.pyc +0 -0
- veadk/a2a/__pycache__/ve_agent_executor.cpython-310.pyc +0 -0
- veadk/cli/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/cli/__pycache__/cli.cpython-310.pyc +0 -0
- veadk/cli/__pycache__/cli_deploy.cpython-310.pyc +0 -0
- veadk/cli/__pycache__/cli_init.cpython-310.pyc +0 -0
- veadk/cli/__pycache__/cli_prompt.cpython-310.pyc +0 -0
- veadk/cli/__pycache__/cli_studio.cpython-310.pyc +0 -0
- veadk/cli/__pycache__/cli_web.cpython-310.pyc +0 -0
- veadk/cli/__pycache__/main.cpython-310.pyc +0 -0
- veadk/cloud/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/cloud/__pycache__/cloud_agent_engine.cpython-310.pyc +0 -0
- veadk/cloud/__pycache__/cloud_app.cpython-310.pyc +0 -0
- veadk/database/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/database/__pycache__/base_database.cpython-310.pyc +0 -0
- veadk/database/__pycache__/database_adapter.cpython-310.pyc +0 -0
- veadk/database/__pycache__/database_factory.cpython-310.pyc +0 -0
- veadk/database/__pycache__/local_database.cpython-310.pyc +0 -0
- veadk/database/kv/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/database/relational/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/database/vector/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/database/vector/__pycache__/opensearch_vector_database.cpython-310.pyc +0 -0
- veadk/database/vector/__pycache__/type.cpython-310.pyc +0 -0
- veadk/database/viking/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/evaluation/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/evaluation/__pycache__/base_evaluator.cpython-310.pyc +0 -0
- veadk/evaluation/__pycache__/eval_set_file_loader.cpython-310.pyc +0 -0
- veadk/evaluation/__pycache__/eval_set_recorder.cpython-310.pyc +0 -0
- veadk/evaluation/__pycache__/types.cpython-310.pyc +0 -0
- veadk/evaluation/adk_evaluator/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/evaluation/deepeval_evaluator/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/evaluation/deepeval_evaluator/__pycache__/deepeval_evaluator.cpython-310.pyc +0 -0
- veadk/evaluation/utils/__pycache__/prometheus.cpython-310.pyc +0 -0
- veadk/integrations/ve_apig/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/integrations/ve_apig/__pycache__/apig.cpython-310.pyc +0 -0
- veadk/integrations/ve_apig/__pycache__/ve_apig.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/__pycache__/types.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/__pycache__/ve_faas.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/__pycache__/ve_faas_utils.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/__pycache__/vefaas.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/__pycache__/vefaas_utils.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__pycache__/agent.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__pycache__/app.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__pycache__/studio_app.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name|replace('-', '_') }}/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name|replace('-', '_') }}/__pycache__/agent.cpython-310.pyc +0 -0
- veadk/integrations/ve_prompt_pilot/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/integrations/ve_prompt_pilot/__pycache__/agentpilot.cpython-310.pyc +0 -0
- veadk/knowledgebase/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/knowledgebase/__pycache__/knowledgebase.cpython-310.pyc +0 -0
- veadk/knowledgebase/__pycache__/knowledgebase_database_adapter.cpython-310.pyc +0 -0
- veadk/memory/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/memory/__pycache__/long_term_memory.cpython-310.pyc +0 -0
- veadk/memory/__pycache__/memory_database_adapter.cpython-310.pyc +0 -0
- veadk/memory/__pycache__/short_term_memory.cpython-310.pyc +0 -0
- veadk/memory/__pycache__/short_term_memory_processor.cpython-310.pyc +0 -0
- veadk/prompts/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/prompts/__pycache__/agent_default_prompt.cpython-310.pyc +0 -0
- veadk/prompts/__pycache__/prompt_memory_processor.cpython-310.pyc +0 -0
- veadk/prompts/__pycache__/prompt_optimization.cpython-310.pyc +0 -0
- veadk/tools/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/tools/__pycache__/demo_tools.cpython-310.pyc +0 -0
- veadk/tools/__pycache__/load_knowledgebase_tool.cpython-310.pyc +0 -0
- veadk/tools/builtin_tools/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/tools/builtin_tools/__pycache__/lark.cpython-310.pyc +0 -0
- veadk/tools/builtin_tools/__pycache__/vesearch.cpython-310.pyc +0 -0
- veadk/tools/builtin_tools/__pycache__/web_search.cpython-310.pyc +0 -0
- veadk/tools/sandbox/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/tracing/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/tracing/__pycache__/base_tracer.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/__pycache__/opentelemetry_tracer.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/exporters/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/exporters/__pycache__/apiserver_exporter.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/exporters/__pycache__/apmplus_exporter.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/exporters/__pycache__/base_exporter.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/exporters/__pycache__/cozeloop_exporter.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/exporters/__pycache__/inmemory_exporter.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/exporters/__pycache__/tls_exporter.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/metrics/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/metrics/__pycache__/opentelemetry_metrics.cpython-310.pyc +0 -0
- veadk/tracing/telemetry/metrics/opentelemetry_metrics.py +0 -73
- veadk/utils/__pycache__/__init__.cpython-310.pyc +0 -0
- veadk/utils/__pycache__/logger.cpython-310.pyc +0 -0
- veadk/utils/__pycache__/mcp_utils.cpython-310.pyc +0 -0
- veadk/utils/__pycache__/misc.cpython-310.pyc +0 -0
- veadk/utils/__pycache__/patches.cpython-310.pyc +0 -0
- veadk/utils/__pycache__/volcengine_sign.cpython-310.pyc +0 -0
- veadk_python-0.2.2.dist-info/METADATA +0 -144
- veadk_python-0.2.2.dist-info/RECORD +0 -213
- {veadk_python-0.2.2.dist-info → veadk_python-0.2.4.dist-info}/WHEEL +0 -0
- {veadk_python-0.2.2.dist-info → veadk_python-0.2.4.dist-info}/entry_points.txt +0 -0
- {veadk_python-0.2.2.dist-info → veadk_python-0.2.4.dist-info}/licenses/LICENSE +0 -0
- {veadk_python-0.2.2.dist-info → veadk_python-0.2.4.dist-info}/top_level.txt +0 -0
|
@@ -17,9 +17,16 @@ from contextlib import asynccontextmanager
|
|
|
17
17
|
from typing import Callable
|
|
18
18
|
|
|
19
19
|
from agent import agent_run_config
|
|
20
|
+
|
|
20
21
|
from fastapi import FastAPI
|
|
22
|
+
from fastapi.routing import APIRoute
|
|
23
|
+
|
|
21
24
|
from fastmcp import FastMCP
|
|
22
25
|
|
|
26
|
+
from starlette.routing import Route
|
|
27
|
+
|
|
28
|
+
from google.adk.a2a.utils.agent_card_builder import AgentCardBuilder
|
|
29
|
+
|
|
23
30
|
from veadk.a2a.ve_a2a_server import init_app
|
|
24
31
|
from veadk.runner import Runner
|
|
25
32
|
from veadk.tracing.telemetry.exporters.apmplus_exporter import APMPlusExporter
|
|
@@ -39,6 +46,8 @@ app_name = agent_run_config.app_name
|
|
|
39
46
|
agent = agent_run_config.agent
|
|
40
47
|
short_term_memory = agent_run_config.short_term_memory
|
|
41
48
|
|
|
49
|
+
agent_card_builder = AgentCardBuilder(agent=agent)
|
|
50
|
+
|
|
42
51
|
|
|
43
52
|
def load_tracer() -> None:
|
|
44
53
|
EXPORTER_REGISTRY = {
|
|
@@ -61,11 +70,8 @@ def load_tracer() -> None:
|
|
|
61
70
|
else:
|
|
62
71
|
exporters.append(exporter_cls())
|
|
63
72
|
|
|
64
|
-
tracer = OpentelemetryTracer(
|
|
65
|
-
name="veadk_tracer", app_name=agent_run_config.app_name, exporters=exporters
|
|
66
|
-
)
|
|
73
|
+
tracer = OpentelemetryTracer(name="veadk_tracer", exporters=exporters)
|
|
67
74
|
agent_run_config.agent.tracers.extend([tracer])
|
|
68
|
-
tracer.do_hooks(agent=agent_run_config.agent)
|
|
69
75
|
|
|
70
76
|
|
|
71
77
|
def build_mcp_run_agent_func() -> Callable:
|
|
@@ -104,8 +110,16 @@ def build_mcp_run_agent_func() -> Callable:
|
|
|
104
110
|
return run_agent
|
|
105
111
|
|
|
106
112
|
|
|
113
|
+
async def agent_card() -> dict:
|
|
114
|
+
agent_card = await agent_card_builder.build()
|
|
115
|
+
return agent_card.model_dump()
|
|
116
|
+
|
|
117
|
+
|
|
107
118
|
load_tracer()
|
|
108
119
|
|
|
120
|
+
# Build a run_agent function for building MCP server
|
|
121
|
+
run_agent_func = build_mcp_run_agent_func()
|
|
122
|
+
|
|
109
123
|
a2a_app = init_app(
|
|
110
124
|
server_url="0.0.0.0",
|
|
111
125
|
app_name=app_name,
|
|
@@ -113,9 +127,8 @@ a2a_app = init_app(
|
|
|
113
127
|
short_term_memory=short_term_memory,
|
|
114
128
|
)
|
|
115
129
|
|
|
116
|
-
# Build a run_agent function for building MCP server
|
|
117
|
-
run_agent_func = build_mcp_run_agent_func()
|
|
118
130
|
a2a_app.post("/run_agent", operation_id="run_agent", tags=["mcp"])(run_agent_func)
|
|
131
|
+
a2a_app.get("/agent_card", operation_id="agent_card", tags=["mcp"])(agent_card)
|
|
119
132
|
|
|
120
133
|
|
|
121
134
|
# === Build mcp server ===
|
|
@@ -134,7 +147,14 @@ async def combined_lifespan(app: FastAPI):
|
|
|
134
147
|
|
|
135
148
|
|
|
136
149
|
# Create main FastAPI app with combined lifespan
|
|
137
|
-
app = FastAPI(
|
|
150
|
+
app = FastAPI(
|
|
151
|
+
title=a2a_app.title,
|
|
152
|
+
version=a2a_app.version,
|
|
153
|
+
lifespan=combined_lifespan,
|
|
154
|
+
openapi_url=None,
|
|
155
|
+
docs_url=None,
|
|
156
|
+
redoc_url=None
|
|
157
|
+
)
|
|
138
158
|
|
|
139
159
|
# Mount A2A routes to main app
|
|
140
160
|
for route in a2a_app.routes:
|
|
@@ -143,4 +163,14 @@ for route in a2a_app.routes:
|
|
|
143
163
|
# Mount MCP server at /mcp endpoint
|
|
144
164
|
app.mount("/mcp", mcp_app)
|
|
145
165
|
|
|
166
|
+
|
|
167
|
+
# remove openapi routes
|
|
168
|
+
paths = ["/openapi.json", "/docs", "/redoc"]
|
|
169
|
+
new_routes = []
|
|
170
|
+
for route in app.router.routes:
|
|
171
|
+
if isinstance(route, (APIRoute, Route)) and route.path in paths:
|
|
172
|
+
continue
|
|
173
|
+
new_routes.append(route)
|
|
174
|
+
app.router.routes = new_routes
|
|
175
|
+
|
|
146
176
|
# === Build mcp server end ===
|
|
@@ -33,12 +33,8 @@ while [[ $# -gt 0 ]]; do
|
|
|
33
33
|
esac
|
|
34
34
|
done
|
|
35
35
|
|
|
36
|
-
# in case of
|
|
37
|
-
python3 -m pip install uvicorn[standard]
|
|
38
|
-
|
|
39
|
-
python3 -m pip install fastapi
|
|
40
|
-
|
|
41
|
-
python3 -m pip install fastmcp
|
|
36
|
+
# in case of deployment deps not installed in user's requirements.txt
|
|
37
|
+
python3 -m pip install uvicorn[standard] fastapi
|
|
42
38
|
|
|
43
39
|
USE_ADK_WEB=${USE_ADK_WEB:-False}
|
|
44
40
|
|
|
@@ -120,7 +120,11 @@ class VeFaaS:
|
|
|
120
120
|
envs=envs,
|
|
121
121
|
)
|
|
122
122
|
)
|
|
123
|
-
|
|
123
|
+
|
|
124
|
+
# avoid print secrets
|
|
125
|
+
logger.debug(
|
|
126
|
+
f"Function creation in {res.project_name} project with ID {res.id}"
|
|
127
|
+
)
|
|
124
128
|
|
|
125
129
|
function_id = res.id
|
|
126
130
|
|
veadk/runner.py
CHANGED
|
@@ -15,12 +15,16 @@ from typing import Union
|
|
|
15
15
|
|
|
16
16
|
from google.adk.agents import RunConfig
|
|
17
17
|
from google.adk.agents.run_config import StreamingMode
|
|
18
|
+
from google.adk.plugins.base_plugin import BasePlugin
|
|
18
19
|
from google.adk.runners import Runner as ADKRunner
|
|
19
20
|
from google.genai import types
|
|
20
21
|
from google.genai.types import Blob
|
|
21
22
|
|
|
22
23
|
from veadk.a2a.remote_ve_agent import RemoteVeAgent
|
|
23
24
|
from veadk.agent import Agent
|
|
25
|
+
from veadk.agents.loop_agent import LoopAgent
|
|
26
|
+
from veadk.agents.parallel_agent import ParallelAgent
|
|
27
|
+
from veadk.agents.sequential_agent import SequentialAgent
|
|
24
28
|
from veadk.evaluation import EvalSetRecorder
|
|
25
29
|
from veadk.memory.short_term_memory import ShortTermMemory
|
|
26
30
|
from veadk.types import MediaMessage
|
|
@@ -38,12 +42,15 @@ RunnerMessage = Union[
|
|
|
38
42
|
list[MediaMessage | str], # multiple turn prompt with media and text-based prompt
|
|
39
43
|
]
|
|
40
44
|
|
|
45
|
+
VeAgent = Union[Agent, RemoteVeAgent, SequentialAgent, ParallelAgent, LoopAgent]
|
|
46
|
+
|
|
41
47
|
|
|
42
48
|
class Runner:
|
|
43
49
|
def __init__(
|
|
44
50
|
self,
|
|
45
|
-
agent:
|
|
51
|
+
agent: VeAgent,
|
|
46
52
|
short_term_memory: ShortTermMemory,
|
|
53
|
+
plugins: list[BasePlugin] | None = None,
|
|
47
54
|
app_name: str = "veadk_default_app",
|
|
48
55
|
user_id: str = "veadk_default_user",
|
|
49
56
|
):
|
|
@@ -60,8 +67,6 @@ class Runner:
|
|
|
60
67
|
# prevent VeRemoteAgent has no long-term memory attr
|
|
61
68
|
if isinstance(self.agent, Agent):
|
|
62
69
|
self.long_term_memory = self.agent.long_term_memory
|
|
63
|
-
for tracer in self.agent.tracers:
|
|
64
|
-
tracer.set_app_name(self.app_name)
|
|
65
70
|
else:
|
|
66
71
|
self.long_term_memory = None
|
|
67
72
|
|
|
@@ -70,6 +75,7 @@ class Runner:
|
|
|
70
75
|
agent=self.agent,
|
|
71
76
|
session_service=self.session_service,
|
|
72
77
|
memory_service=self.long_term_memory,
|
|
78
|
+
plugins=plugins,
|
|
73
79
|
)
|
|
74
80
|
|
|
75
81
|
def _convert_messages(self, messages) -> list:
|
|
@@ -163,13 +169,57 @@ class Runner:
|
|
|
163
169
|
if save_tracing_data:
|
|
164
170
|
self.save_tracing_file(session_id)
|
|
165
171
|
|
|
172
|
+
self._print_trace_id()
|
|
173
|
+
|
|
166
174
|
return final_output
|
|
167
175
|
|
|
168
|
-
def
|
|
176
|
+
def get_trace_id(self) -> str:
|
|
177
|
+
if not isinstance(self.agent, Agent):
|
|
178
|
+
logger.warning(
|
|
179
|
+
("The agent is not an instance of VeADK Agent, no trace id provided.")
|
|
180
|
+
)
|
|
181
|
+
return "<unknown_trace_id>"
|
|
182
|
+
|
|
183
|
+
if not self.agent.tracers:
|
|
184
|
+
logger.warning(
|
|
185
|
+
"No tracer is configured in the agent, no trace id provided."
|
|
186
|
+
)
|
|
187
|
+
return "<unknown_trace_id>"
|
|
188
|
+
|
|
189
|
+
try:
|
|
190
|
+
trace_id = self.agent.tracers[0].trace_id # type: ignore
|
|
191
|
+
return trace_id
|
|
192
|
+
except Exception as e:
|
|
193
|
+
logger.warning(f"Get tracer id failed as {e}")
|
|
194
|
+
return "<unknown_trace_id>"
|
|
195
|
+
|
|
196
|
+
def _print_trace_id(self) -> None:
|
|
169
197
|
if not isinstance(self.agent, Agent):
|
|
198
|
+
logger.warning(
|
|
199
|
+
("The agent is not an instance of VeADK Agent, no trace id provided.")
|
|
200
|
+
)
|
|
201
|
+
return
|
|
202
|
+
|
|
203
|
+
if not self.agent.tracers:
|
|
204
|
+
logger.warning(
|
|
205
|
+
"No tracer is configured in the agent, no trace id provided."
|
|
206
|
+
)
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
try:
|
|
210
|
+
trace_id = self.agent.tracers[0].trace_id # type: ignore
|
|
211
|
+
logger.info(f"Trace id: {trace_id}")
|
|
212
|
+
except Exception as e:
|
|
213
|
+
logger.warning(f"Get tracer id failed as {e}")
|
|
214
|
+
return
|
|
215
|
+
|
|
216
|
+
def save_tracing_file(self, session_id: str) -> str:
|
|
217
|
+
if not isinstance(
|
|
218
|
+
self.agent, (Agent, SequentialAgent, ParallelAgent, LoopAgent)
|
|
219
|
+
):
|
|
170
220
|
logger.warning(
|
|
171
221
|
(
|
|
172
|
-
"The agent is not an instance of
|
|
222
|
+
"The agent is not an instance of Agent, SequentialAgent, ParallelAgent or LoopAgent, cannot save tracing file."
|
|
173
223
|
)
|
|
174
224
|
)
|
|
175
225
|
return ""
|
veadk/tracing/base_tracer.py
CHANGED
|
@@ -12,214 +12,39 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import json
|
|
16
15
|
from abc import ABC, abstractmethod
|
|
17
|
-
from typing import Any, Optional
|
|
18
|
-
|
|
19
|
-
from google.adk.agents.callback_context import CallbackContext
|
|
20
|
-
from google.adk.models.llm_request import LlmRequest
|
|
21
|
-
from google.adk.models.llm_response import LlmResponse
|
|
22
|
-
from google.adk.tools import BaseTool, ToolContext
|
|
23
|
-
from opentelemetry import trace
|
|
24
16
|
|
|
25
17
|
from veadk.utils.logger import get_logger
|
|
26
18
|
|
|
27
19
|
logger = get_logger(__name__)
|
|
28
20
|
|
|
29
21
|
|
|
22
|
+
def replace_bytes_with_empty(data):
|
|
23
|
+
"""
|
|
24
|
+
Recursively traverse the data structure and replace all bytes types with empty strings.
|
|
25
|
+
Supports handling any nested structure of lists and dictionaries.
|
|
26
|
+
"""
|
|
27
|
+
if isinstance(data, dict):
|
|
28
|
+
# Handle dictionary: Recursively process each value
|
|
29
|
+
return {k: replace_bytes_with_empty(v) for k, v in data.items()}
|
|
30
|
+
elif isinstance(data, list):
|
|
31
|
+
# Handle list: Recursively process each element
|
|
32
|
+
return [replace_bytes_with_empty(item) for item in data]
|
|
33
|
+
elif isinstance(data, bytes):
|
|
34
|
+
# When encountering the bytes type, replace it with an empty string
|
|
35
|
+
return "<image data>"
|
|
36
|
+
else:
|
|
37
|
+
# Keep other types unchanged
|
|
38
|
+
return data
|
|
39
|
+
|
|
40
|
+
|
|
30
41
|
class BaseTracer(ABC):
|
|
31
42
|
def __init__(self, name: str):
|
|
32
|
-
self.
|
|
33
|
-
|
|
43
|
+
self.name = name
|
|
44
|
+
self._trace_id = "<unknown_trace_id>"
|
|
45
|
+
self._trace_file_path = "<unknown_trace_file_path>"
|
|
34
46
|
|
|
35
47
|
@abstractmethod
|
|
36
|
-
def dump(self, user_id: str, session_id: str, path: str = "/tmp") -> str:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
self, callback_context: CallbackContext, llm_request: LlmRequest
|
|
40
|
-
) -> Optional[LlmResponse]:
|
|
41
|
-
"""agent run stage"""
|
|
42
|
-
trace.get_tracer("gcp.vertex.agent")
|
|
43
|
-
span = trace.get_current_span()
|
|
44
|
-
# logger.debug(f"llm_request: {llm_request}")
|
|
45
|
-
|
|
46
|
-
req = llm_request.model_dump()
|
|
47
|
-
|
|
48
|
-
app_name = getattr(self, "app_name", "veadk_app")
|
|
49
|
-
agent_name = callback_context.agent_name
|
|
50
|
-
model_name = req.get("model", "unknown")
|
|
51
|
-
max_tokens = (
|
|
52
|
-
None
|
|
53
|
-
if not req.get("live_connect_config")
|
|
54
|
-
else req["live_connect_config"].get("max_output_tokens", None)
|
|
55
|
-
)
|
|
56
|
-
temperature = (
|
|
57
|
-
None
|
|
58
|
-
if not req.get("live_connect_config")
|
|
59
|
-
else req["live_connect_config"].get("temperature", None)
|
|
60
|
-
)
|
|
61
|
-
top_p = (
|
|
62
|
-
None
|
|
63
|
-
if not req.get("live_connect_config")
|
|
64
|
-
else req["live_connect_config"].get("top_p", None)
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
attributes = {}
|
|
68
|
-
attributes["agent.name"] = agent_name
|
|
69
|
-
attributes["app.name"] = app_name
|
|
70
|
-
attributes["gen_ai.system"] = "veadk"
|
|
71
|
-
if model_name:
|
|
72
|
-
attributes["gen_ai.request.model"] = model_name
|
|
73
|
-
attributes["gen_ai.response.model"] = (
|
|
74
|
-
model_name # The req model and the resp model should be consistent.
|
|
75
|
-
)
|
|
76
|
-
attributes["gen_ai.request.type"] = "completion"
|
|
77
|
-
if max_tokens:
|
|
78
|
-
attributes["gen_ai.request.max_tokens"] = max_tokens
|
|
79
|
-
if temperature:
|
|
80
|
-
attributes["gen_ai.request.temperature"] = temperature
|
|
81
|
-
if top_p:
|
|
82
|
-
attributes["gen_ai.request.top_p"] = top_p
|
|
83
|
-
|
|
84
|
-
# Print attributes for debugging
|
|
85
|
-
# print("Tracing attributes:", attributes)
|
|
86
|
-
|
|
87
|
-
# Set all attributes at once if possible, else fallback to individual
|
|
88
|
-
if hasattr(span, "set_attributes"):
|
|
89
|
-
span.set_attributes(attributes)
|
|
90
|
-
else:
|
|
91
|
-
# Fallback for OpenTelemetry versions without set_attributes
|
|
92
|
-
for k, v in attributes.items():
|
|
93
|
-
span.set_attribute(k, v)
|
|
94
|
-
|
|
95
|
-
def tracer_hook_after_model(
|
|
96
|
-
self, callback_context: CallbackContext, llm_response: LlmResponse
|
|
97
|
-
) -> Optional[LlmResponse]:
|
|
98
|
-
"""call llm stage"""
|
|
99
|
-
trace.get_tracer("gcp.vertex.agent")
|
|
100
|
-
span = trace.get_current_span()
|
|
101
|
-
# logger.debug(f"llm_response: {llm_response}")
|
|
102
|
-
# logger.debug(f"callback_context: {callback_context}")
|
|
103
|
-
|
|
104
|
-
# Refined: collect all attributes, use set_attributes, print for debugging
|
|
105
|
-
attributes = {}
|
|
106
|
-
|
|
107
|
-
app_name = getattr(self, "app_name", "veadk_app")
|
|
108
|
-
agent_name = callback_context.agent_name
|
|
109
|
-
attributes["agent.name"] = agent_name
|
|
110
|
-
attributes["app.name"] = app_name
|
|
111
|
-
|
|
112
|
-
# prompt
|
|
113
|
-
user_content = callback_context.user_content
|
|
114
|
-
role = None
|
|
115
|
-
content = None
|
|
116
|
-
if getattr(user_content, "role", None):
|
|
117
|
-
role = getattr(user_content, "role", None)
|
|
118
|
-
|
|
119
|
-
if user_content and getattr(user_content, "parts", None):
|
|
120
|
-
content = user_content.model_dump(exclude_none=True).get("parts", None)
|
|
121
|
-
content = json.dumps(content) if content else None
|
|
122
|
-
|
|
123
|
-
if role and content:
|
|
124
|
-
attributes["gen_ai.prompt.0.role"] = role
|
|
125
|
-
attributes["gen_ai.prompt.0.content"] = content
|
|
126
|
-
|
|
127
|
-
# completion
|
|
128
|
-
completion_content = getattr(llm_response, "content").model_dump(
|
|
129
|
-
exclude_none=True
|
|
130
|
-
)
|
|
131
|
-
if completion_content:
|
|
132
|
-
content = json.dumps(
|
|
133
|
-
getattr(llm_response, "content").model_dump(exclude_none=True)["parts"]
|
|
134
|
-
)
|
|
135
|
-
role = getattr(llm_response, "content").model_dump(exclude_none=True)[
|
|
136
|
-
"role"
|
|
137
|
-
]
|
|
138
|
-
if role and content:
|
|
139
|
-
attributes["gen_ai.completion.0.role"] = role
|
|
140
|
-
attributes["gen_ai.completion.0.content"] = content
|
|
141
|
-
|
|
142
|
-
if not llm_response.usage_metadata:
|
|
143
|
-
return
|
|
144
|
-
|
|
145
|
-
# tokens
|
|
146
|
-
metadata = llm_response.usage_metadata.model_dump()
|
|
147
|
-
if metadata:
|
|
148
|
-
prompt_tokens = metadata.get("prompt_token_count", None)
|
|
149
|
-
completion_tokens = metadata.get("candidates_token_count", None)
|
|
150
|
-
total_tokens = metadata.get("total_token_count", None)
|
|
151
|
-
cache_read_input_tokens = (
|
|
152
|
-
metadata.get("cache_read_input_tokens") or 0
|
|
153
|
-
) # Might change, once openai introduces their equivalent.
|
|
154
|
-
cache_create_input_tokens = (
|
|
155
|
-
metadata.get("cache_create_input_tokens") or 0
|
|
156
|
-
) # Might change, once openai introduces their equivalent.
|
|
157
|
-
if prompt_tokens:
|
|
158
|
-
attributes["gen_ai.usage.prompt_tokens"] = prompt_tokens
|
|
159
|
-
if completion_tokens:
|
|
160
|
-
attributes["gen_ai.usage.completion_tokens"] = completion_tokens
|
|
161
|
-
if total_tokens:
|
|
162
|
-
attributes["gen_ai.usage.total_tokens"] = total_tokens
|
|
163
|
-
if cache_read_input_tokens is not None:
|
|
164
|
-
attributes["gen_ai.usage.cache_read_input_tokens"] = (
|
|
165
|
-
cache_read_input_tokens
|
|
166
|
-
)
|
|
167
|
-
if cache_create_input_tokens is not None:
|
|
168
|
-
attributes["gen_ai.usage.cache_create_input_tokens"] = (
|
|
169
|
-
cache_create_input_tokens
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
# Print attributes for debugging
|
|
173
|
-
# print("Tracing attributes:", attributes)
|
|
174
|
-
|
|
175
|
-
# Set all attributes at once if possible, else fallback to individual
|
|
176
|
-
if hasattr(span, "set_attributes"):
|
|
177
|
-
span.set_attributes(attributes)
|
|
178
|
-
else:
|
|
179
|
-
# Fallback for OpenTelemetry versions without set_attributes
|
|
180
|
-
for k, v in attributes.items():
|
|
181
|
-
span.set_attribute(k, v)
|
|
182
|
-
|
|
183
|
-
def tracer_hook_after_tool(
|
|
184
|
-
self,
|
|
185
|
-
tool: BaseTool,
|
|
186
|
-
args: dict[str, Any],
|
|
187
|
-
tool_context: ToolContext,
|
|
188
|
-
tool_response: dict,
|
|
189
|
-
):
|
|
190
|
-
trace.get_tracer("gcp.vertex.agent")
|
|
191
|
-
span = trace.get_current_span()
|
|
192
|
-
agent_name = tool_context.agent_name
|
|
193
|
-
tool_name = tool.name
|
|
194
|
-
app_name = getattr(self, "app_name", "veadk_app")
|
|
195
|
-
attributes = {
|
|
196
|
-
"agent.name": agent_name,
|
|
197
|
-
"app.name": app_name,
|
|
198
|
-
"tool.name": tool_name,
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
# Set all attributes at once if possible, else fallback to individual
|
|
202
|
-
if hasattr(span, "set_attributes"):
|
|
203
|
-
span.set_attributes(attributes)
|
|
204
|
-
else:
|
|
205
|
-
# Fallback for OpenTelemetry versions without set_attributes
|
|
206
|
-
for k, v in attributes.items():
|
|
207
|
-
span.set_attribute(k, v)
|
|
208
|
-
|
|
209
|
-
def set_app_name(self, app_name):
|
|
210
|
-
self.app_name = app_name
|
|
211
|
-
|
|
212
|
-
def do_hooks(self, agent) -> None:
|
|
213
|
-
if not getattr(agent, "before_model_callback", None):
|
|
214
|
-
agent.before_model_callback = []
|
|
215
|
-
if not getattr(agent, "after_model_callback", None):
|
|
216
|
-
agent.after_model_callback = []
|
|
217
|
-
if not getattr(agent, "after_tool_callback", None):
|
|
218
|
-
agent.after_tool_callback = []
|
|
219
|
-
|
|
220
|
-
if self.tracer_hook_before_model not in agent.before_model_callback:
|
|
221
|
-
agent.before_model_callback.append(self.tracer_hook_before_model)
|
|
222
|
-
if self.tracer_hook_after_model not in agent.after_model_callback:
|
|
223
|
-
agent.after_model_callback.append(self.tracer_hook_after_model)
|
|
224
|
-
if self.tracer_hook_after_tool not in agent.after_tool_callback:
|
|
225
|
-
agent.after_tool_callback.append(self.tracer_hook_after_tool)
|
|
48
|
+
def dump(self, user_id: str, session_id: str, path: str = "/tmp") -> str:
|
|
49
|
+
"""Dump the trace data to a local file."""
|
|
50
|
+
...
|
|
@@ -11,3 +11,19 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from veadk.tracing.telemetry.attributes.extractors.common_attributes_extractors import (
|
|
16
|
+
COMMON_ATTRIBUTES,
|
|
17
|
+
)
|
|
18
|
+
from veadk.tracing.telemetry.attributes.extractors.llm_attributes_extractors import (
|
|
19
|
+
LLM_ATTRIBUTES,
|
|
20
|
+
)
|
|
21
|
+
from veadk.tracing.telemetry.attributes.extractors.tool_attributes_extractors import (
|
|
22
|
+
TOOL_ATTRIBUTES,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
ATTRIBUTES = {
|
|
26
|
+
"common": COMMON_ATTRIBUTES,
|
|
27
|
+
"llm": LLM_ATTRIBUTES,
|
|
28
|
+
"tool": TOOL_ATTRIBUTES,
|
|
29
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
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 veadk.version import VERSION
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def common_gen_ai_system(**kwargs) -> str:
|
|
19
|
+
"""This field will be parsed as `model_provider` in Volcengine CozeLoop platform."""
|
|
20
|
+
model_provider = kwargs.get("model_provider")
|
|
21
|
+
return model_provider or "<unknown_model_provider>"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def common_gen_ai_system_version(**kwargs) -> str:
|
|
25
|
+
return VERSION
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def common_gen_ai_app_name(**kwargs) -> str:
|
|
29
|
+
app_name = kwargs.get("app_name")
|
|
30
|
+
return app_name or "<unknown_app_name>"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def common_gen_ai_agent_name(**kwargs) -> str:
|
|
34
|
+
agent_name = kwargs.get("agent_name")
|
|
35
|
+
return agent_name or "<unknown_agent_name>"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def common_gen_ai_user_id(**kwargs) -> str:
|
|
39
|
+
user_id = kwargs.get("user_id")
|
|
40
|
+
return user_id or "<unknown_user_id>"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def common_gen_ai_session_id(**kwargs) -> str:
|
|
44
|
+
session_id = kwargs.get("session_id")
|
|
45
|
+
return session_id or "<unknown_session_id>"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def common_cozeloop_report_source(**kwargs) -> str:
|
|
49
|
+
return "veadk"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def llm_openinference_instrumentation_veadk(**kwargs) -> str:
|
|
53
|
+
return VERSION
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
COMMON_ATTRIBUTES = {
|
|
57
|
+
"gen_ai.system": common_gen_ai_system,
|
|
58
|
+
"gen_ai.system.version": common_gen_ai_system_version,
|
|
59
|
+
"gen_ai.agent.name": common_gen_ai_agent_name,
|
|
60
|
+
"openinference.instrumentation.veadk": llm_openinference_instrumentation_veadk,
|
|
61
|
+
"gen_ai.app.name": common_gen_ai_app_name, # APMPlus required
|
|
62
|
+
"gen_ai.user.id": common_gen_ai_user_id, # APMPlus required
|
|
63
|
+
"gen_ai.session.id": common_gen_ai_session_id, # APMPlus required
|
|
64
|
+
"agent_name": common_gen_ai_agent_name, # CozeLoop required
|
|
65
|
+
"agent.name": common_gen_ai_agent_name, # TLS required
|
|
66
|
+
"app_name": common_gen_ai_app_name, # CozeLoop required
|
|
67
|
+
"app.name": common_gen_ai_app_name, # TLS required
|
|
68
|
+
"user.id": common_gen_ai_user_id, # CozeLoop / TLS required
|
|
69
|
+
"session.id": common_gen_ai_session_id, # CozeLoop / TLS required
|
|
70
|
+
"cozeloop.report.source": common_cozeloop_report_source, # CozeLoop required
|
|
71
|
+
}
|