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.

Files changed (138) hide show
  1. veadk/agent.py +3 -13
  2. veadk/agents/loop_agent.py +55 -0
  3. veadk/agents/parallel_agent.py +60 -0
  4. veadk/agents/sequential_agent.py +55 -0
  5. veadk/cli/cli_deploy.py +11 -0
  6. veadk/cli/cli_web.py +27 -0
  7. veadk/evaluation/adk_evaluator/__init__.py +4 -0
  8. veadk/evaluation/adk_evaluator/adk_evaluator.py +170 -217
  9. veadk/evaluation/base_evaluator.py +26 -20
  10. veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +8 -5
  11. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +37 -7
  12. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +2 -6
  13. veadk/integrations/ve_faas/ve_faas.py +5 -1
  14. veadk/runner.py +55 -5
  15. veadk/tracing/base_tracer.py +25 -200
  16. veadk/tracing/telemetry/{metrics/__init__.py → attributes/attributes.py} +16 -0
  17. veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +71 -0
  18. veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +392 -0
  19. veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +70 -0
  20. veadk/tracing/telemetry/attributes/extractors/types.py +75 -0
  21. veadk/tracing/telemetry/exporters/apmplus_exporter.py +97 -38
  22. veadk/tracing/telemetry/exporters/base_exporter.py +10 -10
  23. veadk/tracing/telemetry/exporters/cozeloop_exporter.py +20 -13
  24. veadk/tracing/telemetry/exporters/inmemory_exporter.py +46 -32
  25. veadk/tracing/telemetry/exporters/tls_exporter.py +18 -12
  26. veadk/tracing/telemetry/opentelemetry_tracer.py +102 -102
  27. veadk/tracing/telemetry/telemetry.py +149 -0
  28. veadk/types.py +6 -1
  29. veadk/utils/misc.py +1 -1
  30. veadk/utils/patches.py +25 -0
  31. veadk/version.py +1 -1
  32. veadk_python-0.2.4.dist-info/METADATA +345 -0
  33. veadk_python-0.2.4.dist-info/RECORD +122 -0
  34. veadk/__pycache__/__init__.cpython-310.pyc +0 -0
  35. veadk/__pycache__/agent.cpython-310.pyc +0 -0
  36. veadk/__pycache__/config.cpython-310.pyc +0 -0
  37. veadk/__pycache__/consts.cpython-310.pyc +0 -0
  38. veadk/__pycache__/runner.cpython-310.pyc +0 -0
  39. veadk/__pycache__/types.cpython-310.pyc +0 -0
  40. veadk/__pycache__/version.cpython-310.pyc +0 -0
  41. veadk/a2a/__pycache__/__init__.cpython-310.pyc +0 -0
  42. veadk/a2a/__pycache__/agent_card.cpython-310.pyc +0 -0
  43. veadk/a2a/__pycache__/remote_ve_agent.cpython-310.pyc +0 -0
  44. veadk/a2a/__pycache__/ve_a2a_server.cpython-310.pyc +0 -0
  45. veadk/a2a/__pycache__/ve_agent_executor.cpython-310.pyc +0 -0
  46. veadk/cli/__pycache__/__init__.cpython-310.pyc +0 -0
  47. veadk/cli/__pycache__/cli.cpython-310.pyc +0 -0
  48. veadk/cli/__pycache__/cli_deploy.cpython-310.pyc +0 -0
  49. veadk/cli/__pycache__/cli_init.cpython-310.pyc +0 -0
  50. veadk/cli/__pycache__/cli_prompt.cpython-310.pyc +0 -0
  51. veadk/cli/__pycache__/cli_studio.cpython-310.pyc +0 -0
  52. veadk/cli/__pycache__/cli_web.cpython-310.pyc +0 -0
  53. veadk/cli/__pycache__/main.cpython-310.pyc +0 -0
  54. veadk/cloud/__pycache__/__init__.cpython-310.pyc +0 -0
  55. veadk/cloud/__pycache__/cloud_agent_engine.cpython-310.pyc +0 -0
  56. veadk/cloud/__pycache__/cloud_app.cpython-310.pyc +0 -0
  57. veadk/database/__pycache__/__init__.cpython-310.pyc +0 -0
  58. veadk/database/__pycache__/base_database.cpython-310.pyc +0 -0
  59. veadk/database/__pycache__/database_adapter.cpython-310.pyc +0 -0
  60. veadk/database/__pycache__/database_factory.cpython-310.pyc +0 -0
  61. veadk/database/__pycache__/local_database.cpython-310.pyc +0 -0
  62. veadk/database/kv/__pycache__/__init__.cpython-310.pyc +0 -0
  63. veadk/database/relational/__pycache__/__init__.cpython-310.pyc +0 -0
  64. veadk/database/vector/__pycache__/__init__.cpython-310.pyc +0 -0
  65. veadk/database/vector/__pycache__/opensearch_vector_database.cpython-310.pyc +0 -0
  66. veadk/database/vector/__pycache__/type.cpython-310.pyc +0 -0
  67. veadk/database/viking/__pycache__/__init__.cpython-310.pyc +0 -0
  68. veadk/evaluation/__pycache__/__init__.cpython-310.pyc +0 -0
  69. veadk/evaluation/__pycache__/base_evaluator.cpython-310.pyc +0 -0
  70. veadk/evaluation/__pycache__/eval_set_file_loader.cpython-310.pyc +0 -0
  71. veadk/evaluation/__pycache__/eval_set_recorder.cpython-310.pyc +0 -0
  72. veadk/evaluation/__pycache__/types.cpython-310.pyc +0 -0
  73. veadk/evaluation/adk_evaluator/__pycache__/__init__.cpython-310.pyc +0 -0
  74. veadk/evaluation/deepeval_evaluator/__pycache__/__init__.cpython-310.pyc +0 -0
  75. veadk/evaluation/deepeval_evaluator/__pycache__/deepeval_evaluator.cpython-310.pyc +0 -0
  76. veadk/evaluation/utils/__pycache__/prometheus.cpython-310.pyc +0 -0
  77. veadk/integrations/ve_apig/__pycache__/__init__.cpython-310.pyc +0 -0
  78. veadk/integrations/ve_apig/__pycache__/apig.cpython-310.pyc +0 -0
  79. veadk/integrations/ve_apig/__pycache__/ve_apig.cpython-310.pyc +0 -0
  80. veadk/integrations/ve_faas/__pycache__/__init__.cpython-310.pyc +0 -0
  81. veadk/integrations/ve_faas/__pycache__/types.cpython-310.pyc +0 -0
  82. veadk/integrations/ve_faas/__pycache__/ve_faas.cpython-310.pyc +0 -0
  83. veadk/integrations/ve_faas/__pycache__/ve_faas_utils.cpython-310.pyc +0 -0
  84. veadk/integrations/ve_faas/__pycache__/vefaas.cpython-310.pyc +0 -0
  85. veadk/integrations/ve_faas/__pycache__/vefaas_utils.cpython-310.pyc +0 -0
  86. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__pycache__/agent.cpython-310.pyc +0 -0
  87. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__pycache__/app.cpython-310.pyc +0 -0
  88. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__pycache__/studio_app.cpython-310.pyc +0 -0
  89. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name|replace('-', '_') }}/__pycache__/__init__.cpython-310.pyc +0 -0
  90. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name|replace('-', '_') }}/__pycache__/agent.cpython-310.pyc +0 -0
  91. veadk/integrations/ve_prompt_pilot/__pycache__/__init__.cpython-310.pyc +0 -0
  92. veadk/integrations/ve_prompt_pilot/__pycache__/agentpilot.cpython-310.pyc +0 -0
  93. veadk/knowledgebase/__pycache__/__init__.cpython-310.pyc +0 -0
  94. veadk/knowledgebase/__pycache__/knowledgebase.cpython-310.pyc +0 -0
  95. veadk/knowledgebase/__pycache__/knowledgebase_database_adapter.cpython-310.pyc +0 -0
  96. veadk/memory/__pycache__/__init__.cpython-310.pyc +0 -0
  97. veadk/memory/__pycache__/long_term_memory.cpython-310.pyc +0 -0
  98. veadk/memory/__pycache__/memory_database_adapter.cpython-310.pyc +0 -0
  99. veadk/memory/__pycache__/short_term_memory.cpython-310.pyc +0 -0
  100. veadk/memory/__pycache__/short_term_memory_processor.cpython-310.pyc +0 -0
  101. veadk/prompts/__pycache__/__init__.cpython-310.pyc +0 -0
  102. veadk/prompts/__pycache__/agent_default_prompt.cpython-310.pyc +0 -0
  103. veadk/prompts/__pycache__/prompt_memory_processor.cpython-310.pyc +0 -0
  104. veadk/prompts/__pycache__/prompt_optimization.cpython-310.pyc +0 -0
  105. veadk/tools/__pycache__/__init__.cpython-310.pyc +0 -0
  106. veadk/tools/__pycache__/demo_tools.cpython-310.pyc +0 -0
  107. veadk/tools/__pycache__/load_knowledgebase_tool.cpython-310.pyc +0 -0
  108. veadk/tools/builtin_tools/__pycache__/__init__.cpython-310.pyc +0 -0
  109. veadk/tools/builtin_tools/__pycache__/lark.cpython-310.pyc +0 -0
  110. veadk/tools/builtin_tools/__pycache__/vesearch.cpython-310.pyc +0 -0
  111. veadk/tools/builtin_tools/__pycache__/web_search.cpython-310.pyc +0 -0
  112. veadk/tools/sandbox/__pycache__/__init__.cpython-310.pyc +0 -0
  113. veadk/tracing/__pycache__/__init__.cpython-310.pyc +0 -0
  114. veadk/tracing/__pycache__/base_tracer.cpython-310.pyc +0 -0
  115. veadk/tracing/telemetry/__pycache__/__init__.cpython-310.pyc +0 -0
  116. veadk/tracing/telemetry/__pycache__/opentelemetry_tracer.cpython-310.pyc +0 -0
  117. veadk/tracing/telemetry/exporters/__pycache__/__init__.cpython-310.pyc +0 -0
  118. veadk/tracing/telemetry/exporters/__pycache__/apiserver_exporter.cpython-310.pyc +0 -0
  119. veadk/tracing/telemetry/exporters/__pycache__/apmplus_exporter.cpython-310.pyc +0 -0
  120. veadk/tracing/telemetry/exporters/__pycache__/base_exporter.cpython-310.pyc +0 -0
  121. veadk/tracing/telemetry/exporters/__pycache__/cozeloop_exporter.cpython-310.pyc +0 -0
  122. veadk/tracing/telemetry/exporters/__pycache__/inmemory_exporter.cpython-310.pyc +0 -0
  123. veadk/tracing/telemetry/exporters/__pycache__/tls_exporter.cpython-310.pyc +0 -0
  124. veadk/tracing/telemetry/metrics/__pycache__/__init__.cpython-310.pyc +0 -0
  125. veadk/tracing/telemetry/metrics/__pycache__/opentelemetry_metrics.cpython-310.pyc +0 -0
  126. veadk/tracing/telemetry/metrics/opentelemetry_metrics.py +0 -73
  127. veadk/utils/__pycache__/__init__.cpython-310.pyc +0 -0
  128. veadk/utils/__pycache__/logger.cpython-310.pyc +0 -0
  129. veadk/utils/__pycache__/mcp_utils.cpython-310.pyc +0 -0
  130. veadk/utils/__pycache__/misc.cpython-310.pyc +0 -0
  131. veadk/utils/__pycache__/patches.cpython-310.pyc +0 -0
  132. veadk/utils/__pycache__/volcengine_sign.cpython-310.pyc +0 -0
  133. veadk_python-0.2.2.dist-info/METADATA +0 -144
  134. veadk_python-0.2.2.dist-info/RECORD +0 -213
  135. {veadk_python-0.2.2.dist-info → veadk_python-0.2.4.dist-info}/WHEEL +0 -0
  136. {veadk_python-0.2.2.dist-info → veadk_python-0.2.4.dist-info}/entry_points.txt +0 -0
  137. {veadk_python-0.2.2.dist-info → veadk_python-0.2.4.dist-info}/licenses/LICENSE +0 -0
  138. {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(title=a2a_app.title, version=a2a_app.version, lifespan=combined_lifespan)
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 uvicorn and fastapi not installed in user's requirements.txt
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
- logger.debug(f"Function creation response: {res}")
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: Agent | RemoteVeAgent,
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 save_tracing_file(self, session_id: str) -> str:
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 VeADK Agent, cannot save tracing file."
222
+ "The agent is not an instance of Agent, SequentialAgent, ParallelAgent or LoopAgent, cannot save tracing file."
173
223
  )
174
224
  )
175
225
  return ""
@@ -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.app_name = "veadk_app_name"
33
- pass
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
- def tracer_hook_before_model(
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
+ }