pygeai 0.6.0b11__py3-none-any.whl → 0.6.0b13__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.
Files changed (138) hide show
  1. pygeai/_docs/source/content/ai_lab/cli.rst +4 -4
  2. pygeai/_docs/source/content/ai_lab/models.rst +169 -35
  3. pygeai/_docs/source/content/ai_lab/runner.rst +2 -2
  4. pygeai/_docs/source/content/ai_lab/spec.rst +9 -9
  5. pygeai/_docs/source/content/ai_lab/usage.rst +34 -34
  6. pygeai/_docs/source/content/ai_lab.rst +1 -1
  7. pygeai/_docs/source/content/analytics.rst +598 -0
  8. pygeai/_docs/source/content/api_reference/chat.rst +428 -2
  9. pygeai/_docs/source/content/api_reference/embeddings.rst +1 -1
  10. pygeai/_docs/source/content/api_reference/project.rst +184 -0
  11. pygeai/_docs/source/content/api_reference/rag.rst +2 -2
  12. pygeai/_docs/source/content/authentication.rst +295 -0
  13. pygeai/_docs/source/content/cli.rst +79 -2
  14. pygeai/_docs/source/content/debugger.rst +1 -1
  15. pygeai/_docs/source/content/migration.rst +19 -2
  16. pygeai/_docs/source/index.rst +2 -0
  17. pygeai/_docs/source/pygeai.analytics.rst +53 -0
  18. pygeai/_docs/source/pygeai.cli.commands.rst +8 -0
  19. pygeai/_docs/source/pygeai.rst +1 -0
  20. pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
  21. pygeai/_docs/source/pygeai.tests.auth.rst +8 -0
  22. pygeai/_docs/source/pygeai.tests.rst +1 -1
  23. pygeai/analytics/__init__.py +0 -0
  24. pygeai/analytics/clients.py +505 -0
  25. pygeai/analytics/endpoints.py +35 -0
  26. pygeai/analytics/managers.py +606 -0
  27. pygeai/analytics/mappers.py +207 -0
  28. pygeai/analytics/responses.py +240 -0
  29. pygeai/assistant/managers.py +1 -1
  30. pygeai/chat/managers.py +1 -1
  31. pygeai/cli/commands/analytics.py +525 -0
  32. pygeai/cli/commands/base.py +16 -0
  33. pygeai/cli/commands/common.py +28 -24
  34. pygeai/cli/commands/migrate.py +75 -6
  35. pygeai/cli/commands/organization.py +265 -0
  36. pygeai/cli/commands/validators.py +144 -1
  37. pygeai/cli/error_handler.py +41 -6
  38. pygeai/cli/geai.py +106 -18
  39. pygeai/cli/parsers.py +75 -31
  40. pygeai/cli/texts/help.py +75 -6
  41. pygeai/core/base/clients.py +18 -4
  42. pygeai/core/base/session.py +59 -7
  43. pygeai/core/common/config.py +25 -2
  44. pygeai/core/common/exceptions.py +64 -1
  45. pygeai/core/embeddings/managers.py +1 -1
  46. pygeai/core/files/managers.py +1 -1
  47. pygeai/core/rerank/managers.py +1 -1
  48. pygeai/core/services/rest.py +20 -2
  49. pygeai/evaluation/clients.py +5 -3
  50. pygeai/lab/agents/clients.py +3 -3
  51. pygeai/lab/agents/endpoints.py +2 -2
  52. pygeai/lab/agents/mappers.py +50 -2
  53. pygeai/lab/clients.py +5 -2
  54. pygeai/lab/managers.py +8 -10
  55. pygeai/lab/models.py +70 -2
  56. pygeai/lab/tools/clients.py +1 -59
  57. pygeai/migration/__init__.py +3 -1
  58. pygeai/migration/strategies.py +72 -3
  59. pygeai/organization/clients.py +110 -1
  60. pygeai/organization/endpoints.py +11 -7
  61. pygeai/organization/limits/managers.py +1 -1
  62. pygeai/organization/managers.py +135 -3
  63. pygeai/organization/mappers.py +28 -2
  64. pygeai/organization/responses.py +11 -1
  65. pygeai/tests/analytics/__init__.py +0 -0
  66. pygeai/tests/analytics/test_clients.py +86 -0
  67. pygeai/tests/analytics/test_managers.py +94 -0
  68. pygeai/tests/analytics/test_mappers.py +84 -0
  69. pygeai/tests/analytics/test_responses.py +73 -0
  70. pygeai/tests/auth/test_oauth.py +172 -0
  71. pygeai/tests/cli/commands/test_migrate.py +14 -1
  72. pygeai/tests/cli/commands/test_organization.py +69 -1
  73. pygeai/tests/cli/test_error_handler.py +4 -4
  74. pygeai/tests/cli/test_geai_driver.py +1 -1
  75. pygeai/tests/lab/agents/test_mappers.py +128 -1
  76. pygeai/tests/lab/test_models.py +2 -0
  77. pygeai/tests/lab/tools/test_clients.py +2 -31
  78. pygeai/tests/organization/test_clients.py +180 -1
  79. pygeai/tests/organization/test_managers.py +40 -0
  80. pygeai/tests/snippets/analytics/__init__.py +0 -0
  81. pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
  82. pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
  83. pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
  84. pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
  85. pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
  86. pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
  87. pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
  88. pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
  89. pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
  90. pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
  91. pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
  92. pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
  93. pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
  94. pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
  95. pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
  96. pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
  97. pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
  98. pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
  99. pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
  100. pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
  101. pygeai/tests/snippets/organization/add_project_member.py +10 -0
  102. pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
  103. {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b13.dist-info}/METADATA +1 -1
  104. {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b13.dist-info}/RECORD +108 -98
  105. pygeai/_docs/source/pygeai.tests.snippets.assistants.data_analyst.rst +0 -37
  106. pygeai/_docs/source/pygeai.tests.snippets.assistants.rag.rst +0 -85
  107. pygeai/_docs/source/pygeai.tests.snippets.assistants.rst +0 -78
  108. pygeai/_docs/source/pygeai.tests.snippets.auth.rst +0 -10
  109. pygeai/_docs/source/pygeai.tests.snippets.chat.rst +0 -125
  110. pygeai/_docs/source/pygeai.tests.snippets.dbg.rst +0 -45
  111. pygeai/_docs/source/pygeai.tests.snippets.embeddings.rst +0 -61
  112. pygeai/_docs/source/pygeai.tests.snippets.evaluation.dataset.rst +0 -197
  113. pygeai/_docs/source/pygeai.tests.snippets.evaluation.plan.rst +0 -133
  114. pygeai/_docs/source/pygeai.tests.snippets.evaluation.result.rst +0 -37
  115. pygeai/_docs/source/pygeai.tests.snippets.evaluation.rst +0 -20
  116. pygeai/_docs/source/pygeai.tests.snippets.extras.rst +0 -37
  117. pygeai/_docs/source/pygeai.tests.snippets.files.rst +0 -53
  118. pygeai/_docs/source/pygeai.tests.snippets.gam.rst +0 -21
  119. pygeai/_docs/source/pygeai.tests.snippets.lab.agents.rst +0 -93
  120. pygeai/_docs/source/pygeai.tests.snippets.lab.processes.jobs.rst +0 -21
  121. pygeai/_docs/source/pygeai.tests.snippets.lab.processes.kbs.rst +0 -45
  122. pygeai/_docs/source/pygeai.tests.snippets.lab.processes.rst +0 -46
  123. pygeai/_docs/source/pygeai.tests.snippets.lab.rst +0 -82
  124. pygeai/_docs/source/pygeai.tests.snippets.lab.samples.rst +0 -21
  125. pygeai/_docs/source/pygeai.tests.snippets.lab.strategies.rst +0 -45
  126. pygeai/_docs/source/pygeai.tests.snippets.lab.tools.rst +0 -85
  127. pygeai/_docs/source/pygeai.tests.snippets.lab.use_cases.rst +0 -117
  128. pygeai/_docs/source/pygeai.tests.snippets.migrate.rst +0 -10
  129. pygeai/_docs/source/pygeai.tests.snippets.organization.rst +0 -109
  130. pygeai/_docs/source/pygeai.tests.snippets.rag.rst +0 -85
  131. pygeai/_docs/source/pygeai.tests.snippets.rerank.rst +0 -21
  132. pygeai/_docs/source/pygeai.tests.snippets.rst +0 -32
  133. pygeai/_docs/source/pygeai.tests.snippets.secrets.rst +0 -10
  134. pygeai/_docs/source/pygeai.tests.snippets.usage_limit.rst +0 -77
  135. {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b13.dist-info}/WHEEL +0 -0
  136. {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b13.dist-info}/entry_points.txt +0 -0
  137. {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b13.dist-info}/licenses/LICENSE +0 -0
  138. {pygeai-0.6.0b11.dist-info → pygeai-0.6.0b13.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,525 @@
1
+ from pygeai.cli.commands import Command, Option, ArgumentsEnum
2
+ from pygeai.cli.commands.builders import build_help_text
3
+ from pygeai.cli.texts.help import ANALYTICS_HELP_TEXT
4
+ from pygeai.core.common.exceptions import MissingRequirementException
5
+ from pygeai.core.utils.console import Console
6
+ from pygeai.analytics.managers import AnalyticsManager
7
+ import csv
8
+ from datetime import datetime, timedelta
9
+
10
+
11
+ def show_help():
12
+ help_text = build_help_text(analytics_commands, ANALYTICS_HELP_TEXT)
13
+ Console.write_stdout(help_text)
14
+
15
+
16
+ def get_default_date_range():
17
+ today = datetime.now()
18
+ first_day_current_month = today.replace(day=1)
19
+ last_day_last_month = first_day_current_month - timedelta(days=1)
20
+ first_day_last_month = last_day_last_month.replace(day=1)
21
+
22
+ start_date = first_day_last_month.strftime('%Y-%m-%d')
23
+ end_date = last_day_last_month.strftime('%Y-%m-%d')
24
+
25
+ return start_date, end_date
26
+
27
+
28
+ START_DATE_OPTION = Option(
29
+ "start_date",
30
+ ["--start-date", "-s"],
31
+ "Start date in YYYY-MM-DD format (defaults to first day of last month)",
32
+ True
33
+ )
34
+
35
+ END_DATE_OPTION = Option(
36
+ "end_date",
37
+ ["--end-date", "-e"],
38
+ "End date in YYYY-MM-DD format (defaults to last day of last month)",
39
+ True
40
+ )
41
+
42
+ AGENT_NAME_OPTION = Option(
43
+ "agent_name",
44
+ ["--agent-name", "-a"],
45
+ "Name of the agent to filter results",
46
+ True
47
+ )
48
+
49
+ CSV_EXPORT_OPTION = Option(
50
+ "csv_file",
51
+ ["--csv", "-c"],
52
+ "Export results to CSV file",
53
+ True
54
+ )
55
+
56
+
57
+ def get_agents_created_and_modified(option_list: list):
58
+ start_date = None
59
+ end_date = None
60
+ for option_flag, option_arg in option_list:
61
+ if option_flag.name == "start_date":
62
+ start_date = option_arg
63
+ if option_flag.name == "end_date":
64
+ end_date = option_arg
65
+
66
+ if not (start_date and end_date):
67
+ raise MissingRequirementException("Cannot retrieve agents created and modified without start-date and end-date")
68
+
69
+ manager = AnalyticsManager()
70
+ result = manager.get_agents_created_and_modified(start_date, end_date)
71
+ Console.write_stdout(f"Agents created and modified:\n Created: {result.createdAgents}\n Modified: {result.modifiedAgents}")
72
+
73
+
74
+ agents_created_options = [START_DATE_OPTION, END_DATE_OPTION]
75
+
76
+
77
+ def get_total_requests_per_day(option_list: list):
78
+ start_date = None
79
+ end_date = None
80
+ agent_name = None
81
+ for option_flag, option_arg in option_list:
82
+ if option_flag.name == "start_date":
83
+ start_date = option_arg
84
+ if option_flag.name == "end_date":
85
+ end_date = option_arg
86
+ if option_flag.name == "agent_name":
87
+ agent_name = option_arg
88
+
89
+ if not (start_date and end_date):
90
+ raise MissingRequirementException("Cannot retrieve total requests per day without start-date and end-date")
91
+
92
+ manager = AnalyticsManager()
93
+ result = manager.get_total_requests_per_day(start_date, end_date, agent_name)
94
+ Console.write_stdout(f"Total requests per day:")
95
+ for item in result.requestsPerDay:
96
+ Console.write_stdout(f" {item.date}: {item.totalRequests} requests ({item.totalRequestsWithError} errors)")
97
+
98
+
99
+ total_requests_per_day_options = [START_DATE_OPTION, END_DATE_OPTION, AGENT_NAME_OPTION]
100
+
101
+
102
+ def get_total_cost(option_list: list):
103
+ start_date = None
104
+ end_date = None
105
+ for option_flag, option_arg in option_list:
106
+ if option_flag.name == "start_date":
107
+ start_date = option_arg
108
+ if option_flag.name == "end_date":
109
+ end_date = option_arg
110
+
111
+ if not (start_date and end_date):
112
+ raise MissingRequirementException("Cannot retrieve total cost without start-date and end-date")
113
+
114
+ manager = AnalyticsManager()
115
+ result = manager.get_total_cost(start_date, end_date)
116
+ Console.write_stdout(f"Total cost: ${result.totalCost:.2f}")
117
+
118
+
119
+ total_cost_options = [START_DATE_OPTION, END_DATE_OPTION]
120
+
121
+
122
+ def get_average_cost_per_request(option_list: list):
123
+ start_date = None
124
+ end_date = None
125
+ for option_flag, option_arg in option_list:
126
+ if option_flag.name == "start_date":
127
+ start_date = option_arg
128
+ if option_flag.name == "end_date":
129
+ end_date = option_arg
130
+
131
+ if not (start_date and end_date):
132
+ raise MissingRequirementException("Cannot retrieve average cost per request without start-date and end-date")
133
+
134
+ manager = AnalyticsManager()
135
+ result = manager.get_average_cost_per_request(start_date, end_date)
136
+ Console.write_stdout(f"Average cost per request: ${result.averageCost:.4f}")
137
+
138
+
139
+ average_cost_per_request_options = [START_DATE_OPTION, END_DATE_OPTION]
140
+
141
+
142
+ def get_total_tokens(option_list: list):
143
+ start_date = None
144
+ end_date = None
145
+ for option_flag, option_arg in option_list:
146
+ if option_flag.name == "start_date":
147
+ start_date = option_arg
148
+ if option_flag.name == "end_date":
149
+ end_date = option_arg
150
+
151
+ if not (start_date and end_date):
152
+ raise MissingRequirementException("Cannot retrieve total tokens without start-date and end-date")
153
+
154
+ manager = AnalyticsManager()
155
+ result = manager.get_total_tokens(start_date, end_date)
156
+ Console.write_stdout(f"Total tokens:\n Input: {result.totalInputTokens}\n Output: {result.totalOutputTokens}\n Total: {result.totalTokens}")
157
+
158
+
159
+ total_tokens_options = [START_DATE_OPTION, END_DATE_OPTION]
160
+
161
+
162
+ def get_overall_error_rate(option_list: list):
163
+ start_date = None
164
+ end_date = None
165
+ for option_flag, option_arg in option_list:
166
+ if option_flag.name == "start_date":
167
+ start_date = option_arg
168
+ if option_flag.name == "end_date":
169
+ end_date = option_arg
170
+
171
+ if not (start_date and end_date):
172
+ raise MissingRequirementException("Cannot retrieve overall error rate without start-date and end-date")
173
+
174
+ manager = AnalyticsManager()
175
+ result = manager.get_overall_error_rate(start_date, end_date)
176
+ Console.write_stdout(f"Overall error rate: {result.errorRate:.2%}")
177
+
178
+
179
+ error_rate_options = [START_DATE_OPTION, END_DATE_OPTION]
180
+
181
+
182
+ def get_top_agents_by_requests(option_list: list):
183
+ start_date = None
184
+ end_date = None
185
+ for option_flag, option_arg in option_list:
186
+ if option_flag.name == "start_date":
187
+ start_date = option_arg
188
+ if option_flag.name == "end_date":
189
+ end_date = option_arg
190
+
191
+ if not (start_date and end_date):
192
+ raise MissingRequirementException("Cannot retrieve top agents by requests without start-date and end-date")
193
+
194
+ manager = AnalyticsManager()
195
+ result = manager.get_top_10_agents_by_requests(start_date, end_date)
196
+ Console.write_stdout("Top 10 agents by requests:")
197
+ for idx, agent in enumerate(result.topAgents, 1):
198
+ Console.write_stdout(f" {idx}. {agent.agentName}: {agent.totalRequests} requests")
199
+
200
+
201
+ top_agents_options = [START_DATE_OPTION, END_DATE_OPTION]
202
+
203
+
204
+ def get_total_active_users(option_list: list):
205
+ start_date = None
206
+ end_date = None
207
+ for option_flag, option_arg in option_list:
208
+ if option_flag.name == "start_date":
209
+ start_date = option_arg
210
+ if option_flag.name == "end_date":
211
+ end_date = option_arg
212
+
213
+ if not (start_date and end_date):
214
+ raise MissingRequirementException("Cannot retrieve total active users without start-date and end-date")
215
+
216
+ manager = AnalyticsManager()
217
+ result = manager.get_total_active_users(start_date, end_date)
218
+ Console.write_stdout(f"Total active users: {result.totalActiveUsers}")
219
+
220
+
221
+ active_users_options = [START_DATE_OPTION, END_DATE_OPTION]
222
+
223
+
224
+ def get_full_report(option_list: list):
225
+ start_date = None
226
+ end_date = None
227
+ csv_file = None
228
+ for option_flag, option_arg in option_list:
229
+ if option_flag.name == "start_date":
230
+ start_date = option_arg
231
+ if option_flag.name == "end_date":
232
+ end_date = option_arg
233
+ if option_flag.name == "csv_file":
234
+ csv_file = option_arg
235
+
236
+ if not start_date or not end_date:
237
+ start_date, end_date = get_default_date_range()
238
+ Console.write_stdout(f"Using default date range: {start_date} to {end_date}")
239
+
240
+ manager = AnalyticsManager()
241
+
242
+ Console.write_stdout(f"\n{'='*80}")
243
+ Console.write_stdout(f"ANALYTICS FULL REPORT - Period: {start_date} to {end_date}")
244
+ Console.write_stdout(f"{'='*80}\n")
245
+
246
+ report_data = {}
247
+
248
+ try:
249
+ Console.write_stdout("LAB METRICS")
250
+ Console.write_stdout("-" * 80)
251
+ agents_created = manager.get_agents_created_and_modified(start_date, end_date)
252
+ Console.write_stdout(f"Agents Created: {agents_created.createdAgents}")
253
+ Console.write_stdout(f"Agents Modified: {agents_created.modifiedAgents}")
254
+ report_data["Agents Created"] = agents_created.createdAgents
255
+ report_data["Agents Modified"] = agents_created.modifiedAgents
256
+ except Exception as e:
257
+ Console.write_stdout(f"Error retrieving agents data: {e}")
258
+
259
+ try:
260
+ flows_created = manager.get_flows_created_and_modified(start_date, end_date)
261
+ Console.write_stdout(f"Flows Created: {flows_created.createdFlows}")
262
+ Console.write_stdout(f"Flows Modified: {flows_created.modifiedFlows}")
263
+ report_data["Flows Created"] = flows_created.createdFlows
264
+ report_data["Flows Modified"] = flows_created.modifiedFlows
265
+ except Exception as e:
266
+ Console.write_stdout(f"Error retrieving flows data: {e}")
267
+
268
+ try:
269
+ processes_created = manager.get_processes_created_and_modified(start_date, end_date)
270
+ Console.write_stdout(f"Processes Created: {processes_created.createdProcesses}")
271
+ Console.write_stdout(f"Processes Modified: {processes_created.modifiedProcesses}")
272
+ report_data["Processes Created"] = processes_created.createdProcesses
273
+ report_data["Processes Modified"] = processes_created.modifiedProcesses
274
+ except Exception as e:
275
+ Console.write_stdout(f"Error retrieving processes data: {e}")
276
+
277
+ Console.write_stdout("\nREQUEST METRICS")
278
+ Console.write_stdout("-" * 80)
279
+
280
+ try:
281
+ total_requests = manager.get_total_requests(start_date, end_date)
282
+ Console.write_stdout(f"Total Requests: {total_requests.totalRequests}")
283
+ report_data["Total Requests"] = total_requests.totalRequests
284
+ except Exception as e:
285
+ Console.write_stdout(f"Error retrieving total requests: {e}")
286
+
287
+ try:
288
+ total_errors = manager.get_total_requests_with_error(start_date, end_date)
289
+ Console.write_stdout(f"Total Requests with Error: {total_errors.totalRequestsWithError}")
290
+ report_data["Total Requests with Error"] = total_errors.totalRequestsWithError
291
+ except Exception as e:
292
+ Console.write_stdout(f"Error retrieving error requests: {e}")
293
+
294
+ try:
295
+ error_rate = manager.get_overall_error_rate(start_date, end_date)
296
+ Console.write_stdout(f"Overall Error Rate: {error_rate.errorRate:.2%}")
297
+ report_data["Overall Error Rate (%)"] = f"{error_rate.errorRate:.2%}"
298
+ except Exception as e:
299
+ Console.write_stdout(f"Error retrieving error rate: {e}")
300
+
301
+ try:
302
+ avg_request_time = manager.get_average_request_time(start_date, end_date)
303
+ Console.write_stdout(f"Average Request Time: {avg_request_time.averageTime:.2f} ms")
304
+ report_data["Average Request Time (ms)"] = f"{avg_request_time.averageTime:.2f}"
305
+ except Exception as e:
306
+ Console.write_stdout(f"Error retrieving average request time: {e}")
307
+
308
+ Console.write_stdout("\nCOST METRICS")
309
+ Console.write_stdout("-" * 80)
310
+
311
+ try:
312
+ total_cost = manager.get_total_cost(start_date, end_date)
313
+ Console.write_stdout(f"Total Cost: ${total_cost.totalCost:.2f}")
314
+ report_data["Total Cost (USD)"] = f"{total_cost.totalCost:.2f}"
315
+ except Exception as e:
316
+ Console.write_stdout(f"Error retrieving total cost: {e}")
317
+
318
+ try:
319
+ avg_cost = manager.get_average_cost_per_request(start_date, end_date)
320
+ Console.write_stdout(f"Average Cost per Request: ${avg_cost.averageCost:.4f}")
321
+ report_data["Average Cost per Request (USD)"] = f"{avg_cost.averageCost:.4f}"
322
+ except Exception as e:
323
+ Console.write_stdout(f"Error retrieving average cost: {e}")
324
+
325
+ Console.write_stdout("\nTOKEN METRICS")
326
+ Console.write_stdout("-" * 80)
327
+
328
+ try:
329
+ total_tokens = manager.get_total_tokens(start_date, end_date)
330
+ Console.write_stdout(f"Total Input Tokens: {total_tokens.totalInputTokens}")
331
+ Console.write_stdout(f"Total Output Tokens: {total_tokens.totalOutputTokens}")
332
+ Console.write_stdout(f"Total Tokens: {total_tokens.totalTokens}")
333
+ report_data["Total Input Tokens"] = total_tokens.totalInputTokens
334
+ report_data["Total Output Tokens"] = total_tokens.totalOutputTokens
335
+ report_data["Total Tokens"] = total_tokens.totalTokens
336
+ except Exception as e:
337
+ Console.write_stdout(f"Error retrieving token data: {e}")
338
+
339
+ try:
340
+ avg_tokens = manager.get_average_tokens_per_request(start_date, end_date)
341
+ Console.write_stdout(f"Average Input Tokens per Request: {avg_tokens.averageInputTokens:.2f}")
342
+ Console.write_stdout(f"Average Output Tokens per Request: {avg_tokens.averageOutputTokens:.2f}")
343
+ Console.write_stdout(f"Average Total Tokens per Request: {avg_tokens.averageTotalTokens:.2f}")
344
+ report_data["Average Input Tokens per Request"] = f"{avg_tokens.averageInputTokens:.2f}"
345
+ report_data["Average Output Tokens per Request"] = f"{avg_tokens.averageOutputTokens:.2f}"
346
+ report_data["Average Total Tokens per Request"] = f"{avg_tokens.averageTotalTokens:.2f}"
347
+ except Exception as e:
348
+ Console.write_stdout(f"Error retrieving average tokens: {e}")
349
+
350
+ Console.write_stdout("\nUSER & AGENT METRICS")
351
+ Console.write_stdout("-" * 80)
352
+
353
+ try:
354
+ active_users = manager.get_total_active_users(start_date, end_date)
355
+ Console.write_stdout(f"Total Active Users: {active_users.totalActiveUsers}")
356
+ report_data["Total Active Users"] = active_users.totalActiveUsers
357
+ except Exception as e:
358
+ Console.write_stdout(f"Error retrieving active users: {e}")
359
+
360
+ try:
361
+ active_agents = manager.get_total_active_agents(start_date, end_date)
362
+ Console.write_stdout(f"Total Active Agents: {active_agents.totalActiveAgents}")
363
+ report_data["Total Active Agents"] = active_agents.totalActiveAgents
364
+ except Exception as e:
365
+ Console.write_stdout(f"Error retrieving active agents: {e}")
366
+
367
+ try:
368
+ active_projects = manager.get_total_active_projects(start_date, end_date)
369
+ Console.write_stdout(f"Total Active Projects: {active_projects.totalActiveProjects}")
370
+ report_data["Total Active Projects"] = active_projects.totalActiveProjects
371
+ except Exception as e:
372
+ Console.write_stdout(f"Error retrieving active projects: {e}")
373
+
374
+ Console.write_stdout("\nTOP 10 AGENTS BY REQUESTS")
375
+ Console.write_stdout("-" * 80)
376
+
377
+ try:
378
+ top_agents_requests = manager.get_top_10_agents_by_requests(start_date, end_date)
379
+ for idx, agent in enumerate(top_agents_requests.topAgents, 1):
380
+ Console.write_stdout(f"{idx}. {agent.agentName}: {agent.totalRequests} requests")
381
+ except Exception as e:
382
+ Console.write_stdout(f"Error retrieving top agents by requests: {e}")
383
+
384
+ Console.write_stdout("\nTOP 10 AGENTS BY TOKENS")
385
+ Console.write_stdout("-" * 80)
386
+
387
+ try:
388
+ top_agents_tokens = manager.get_top_10_agents_by_tokens(start_date, end_date)
389
+ for idx, agent in enumerate(top_agents_tokens.topAgents, 1):
390
+ Console.write_stdout(f"{idx}. {agent.agentName}: {agent.totalTokens} tokens")
391
+ except Exception as e:
392
+ Console.write_stdout(f"Error retrieving top agents by tokens: {e}")
393
+
394
+ Console.write_stdout("\nTOP 10 USERS BY REQUESTS")
395
+ Console.write_stdout("-" * 80)
396
+
397
+ try:
398
+ top_users_requests = manager.get_top_10_users_by_requests(start_date, end_date)
399
+ for idx, user in enumerate(top_users_requests.topUsers, 1):
400
+ Console.write_stdout(f"{idx}. {user.userEmail}: {user.totalRequests} requests")
401
+ except Exception as e:
402
+ Console.write_stdout(f"Error retrieving top users by requests: {e}")
403
+
404
+ Console.write_stdout("\nTOP 10 USERS BY COST")
405
+ Console.write_stdout("-" * 80)
406
+
407
+ try:
408
+ top_users_cost = manager.get_top_10_users_by_cost(start_date, end_date)
409
+ for idx, user in enumerate(top_users_cost.topUsers, 1):
410
+ Console.write_stdout(f"{idx}. {user.userEmail}: ${user.totalCost:.2f}")
411
+ except Exception as e:
412
+ Console.write_stdout(f"Error retrieving top users by cost: {e}")
413
+
414
+ Console.write_stdout(f"\n{'='*80}\n")
415
+
416
+ if csv_file:
417
+ try:
418
+ with open(csv_file, 'w', newline='') as f:
419
+ writer = csv.writer(f)
420
+ writer.writerow(['Metric', 'Value'])
421
+ writer.writerow(['Report Period', f"{start_date} to {end_date}"])
422
+ writer.writerow(['Generated At', datetime.now().strftime('%Y-%m-%d %H:%M:%S')])
423
+ writer.writerow([])
424
+ for key, value in report_data.items():
425
+ writer.writerow([key, value])
426
+ Console.write_stdout(f"Report exported to: {csv_file}")
427
+ except Exception as e:
428
+ Console.write_stdout(f"Error exporting to CSV: {e}")
429
+
430
+
431
+ full_report_options = [START_DATE_OPTION, END_DATE_OPTION, CSV_EXPORT_OPTION]
432
+
433
+
434
+ analytics_commands = [
435
+ Command(
436
+ "help",
437
+ ["help", "h"],
438
+ "Display analytics help text",
439
+ show_help,
440
+ ArgumentsEnum.NOT_AVAILABLE,
441
+ [],
442
+ []
443
+ ),
444
+ Command(
445
+ "agents_created",
446
+ ["agents-created", "ac"],
447
+ "Get total agents created and modified",
448
+ get_agents_created_and_modified,
449
+ ArgumentsEnum.OPTIONAL,
450
+ [],
451
+ agents_created_options
452
+ ),
453
+ Command(
454
+ "requests_per_day",
455
+ ["requests-per-day", "rpd"],
456
+ "Get total requests per day",
457
+ get_total_requests_per_day,
458
+ ArgumentsEnum.OPTIONAL,
459
+ [],
460
+ total_requests_per_day_options
461
+ ),
462
+ Command(
463
+ "total_cost",
464
+ ["total-cost", "tc"],
465
+ "Get total cost for the period",
466
+ get_total_cost,
467
+ ArgumentsEnum.OPTIONAL,
468
+ [],
469
+ total_cost_options
470
+ ),
471
+ Command(
472
+ "average_cost",
473
+ ["average-cost", "ac"],
474
+ "Get average cost per request",
475
+ get_average_cost_per_request,
476
+ ArgumentsEnum.OPTIONAL,
477
+ [],
478
+ average_cost_per_request_options
479
+ ),
480
+ Command(
481
+ "total_tokens",
482
+ ["total-tokens", "tt"],
483
+ "Get total tokens consumed",
484
+ get_total_tokens,
485
+ ArgumentsEnum.OPTIONAL,
486
+ [],
487
+ total_tokens_options
488
+ ),
489
+ Command(
490
+ "error_rate",
491
+ ["error-rate", "er"],
492
+ "Get overall error rate",
493
+ get_overall_error_rate,
494
+ ArgumentsEnum.OPTIONAL,
495
+ [],
496
+ error_rate_options
497
+ ),
498
+ Command(
499
+ "top_agents",
500
+ ["top-agents", "ta"],
501
+ "Get top 10 agents by requests",
502
+ get_top_agents_by_requests,
503
+ ArgumentsEnum.OPTIONAL,
504
+ [],
505
+ top_agents_options
506
+ ),
507
+ Command(
508
+ "active_users",
509
+ ["active-users", "au"],
510
+ "Get total active users",
511
+ get_total_active_users,
512
+ ArgumentsEnum.OPTIONAL,
513
+ [],
514
+ active_users_options
515
+ ),
516
+ Command(
517
+ "full_report",
518
+ ["full-report", "fr"],
519
+ "Get comprehensive analytics report",
520
+ get_full_report,
521
+ ArgumentsEnum.OPTIONAL,
522
+ [],
523
+ full_report_options
524
+ ),
525
+ ]
@@ -1,5 +1,6 @@
1
1
  from pygeai.cli.commands import ArgumentsEnum, Command, Option
2
2
  from pygeai.cli.commands.admin import admin_commands
3
+ from pygeai.cli.commands.analytics import analytics_commands
3
4
  from pygeai.cli.commands.assistant import assistant_commands
4
5
  from pygeai.cli.commands.auth import auth_commands
5
6
  from pygeai.cli.commands.builders import build_help_text
@@ -121,6 +122,15 @@ base_commands = [
121
122
  organization_commands,
122
123
  [],
123
124
  ),
125
+ Command(
126
+ "analytics",
127
+ ["analytics", "anl"],
128
+ "Invoke analytics endpoints to retrieve metrics and insights",
129
+ None,
130
+ ArgumentsEnum.REQUIRED,
131
+ analytics_commands,
132
+ [],
133
+ ),
124
134
  Command(
125
135
  "assistant",
126
136
  ["assistant", "ast"],
@@ -295,4 +305,10 @@ base_options = (
295
305
  "Set output file to save the command result",
296
306
  True
297
307
  ),
308
+ Option(
309
+ "verbose",
310
+ ["--verbose", "-v"],
311
+ "Enable verbose mode with detailed logging output",
312
+ False
313
+ ),
298
314
  )
@@ -109,39 +109,43 @@ def get_messages(message_list: list):
109
109
  return messages
110
110
 
111
111
 
112
- def get_boolean_value(option_arg: str):
112
+ def get_boolean_value(option_arg: str) -> bool:
113
113
  """
114
- Converts a string argument into a boolean value.
115
-
116
- :param option_arg: str - A string representation of an integer (e.g., "0" or "1") to be converted to a boolean.
117
- "0" is interpreted as `False`, and "1" is interpreted as `True`.
118
- :return: bool - The boolean value corresponding to the input.
119
- :raises WrongArgumentError: If the input is not a valid integer or is not "0" or "1".
120
- Possible values for `option_arg` are "0" (off) or "1" (on).
121
- """
122
- try:
123
- return bool(int(option_arg))
124
- except ValueError as e:
114
+ Converts a string argument into a boolean value with flexible input formats.
115
+
116
+ :param option_arg: str - A string representation of a boolean.
117
+ Accepts: "0"/"1", "true"/"false", "yes"/"no", "on"/"off".
118
+ :return: bool - The boolean value corresponding to the input.
119
+ :raises WrongArgumentError: If the input is not a valid boolean representation.
120
+ """
121
+ normalized = option_arg.lower().strip()
122
+
123
+ if normalized in ("0", "false", "no", "off"):
124
+ return False
125
+ elif normalized in ("1", "true", "yes", "on"):
126
+ return True
127
+ else:
125
128
  raise WrongArgumentError("Possible values are 0 or 1, for off and on, respectively.")
126
129
 
127
130
 
128
- def get_penalty_float_value(option_arg: str):
131
+ def get_penalty_float_value(option_arg: str) -> float:
129
132
  """
130
- Converts a string argument into a float value representing a penalty and validates its range.
133
+ Converts a string argument into a float value representing a penalty and validates its range.
131
134
 
132
- :param option_arg: str - A string representation of a float to be converted to a penalty value.
135
+ :param option_arg: str - A string representation of a float to be converted to a penalty value.
133
136
  The value must be between -2.0 and 2.0 (inclusive).
134
- :return: float - The float value corresponding to the input, if valid.
135
- :raises WrongArgumentError: If the input is not a valid float or if the value is outside the range [-2.0, 2.0].
136
- The penalty must be a number between -2.0 and 2.0.
137
- """
137
+ :return: float - The float value corresponding to the input, if valid.
138
+ :raises WrongArgumentError: If the input is not a valid float or if the value is outside the range [-2.0, 2.0].
139
+ """
138
140
  try:
139
- penalty = float(option_arg)
140
- if penalty < -2.0 or 2.0 < penalty:
141
- raise ValueError("Penalty out of range")
142
- return penalty
143
- except Exception as e:
141
+ penalty_value = float(option_arg)
142
+ except ValueError:
143
+ raise WrongArgumentError("If defined, penalty must be a number between -2.0 and 2.0")
144
+
145
+ if not (-2.0 <= penalty_value <= 2.0):
144
146
  raise WrongArgumentError("If defined, penalty must be a number between -2.0 and 2.0")
147
+
148
+ return penalty_value
145
149
 
146
150
 
147
151
  def _build_llm_options(