pygeai 0.6.0b6__py3-none-any.whl → 0.6.0b10__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.
- pygeai/_docs/source/conf.py +78 -6
- pygeai/_docs/source/content/api_reference/admin.rst +161 -0
- pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
- pygeai/_docs/source/content/api_reference/auth.rst +379 -0
- pygeai/_docs/source/content/api_reference/embeddings.rst +31 -1
- pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
- pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
- pygeai/_docs/source/content/api_reference/files.rst +592 -0
- pygeai/_docs/source/content/api_reference/gam.rst +401 -0
- pygeai/_docs/source/content/api_reference/health.rst +58 -0
- pygeai/_docs/source/content/api_reference/project.rst +20 -18
- pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
- pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
- pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
- pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
- pygeai/_docs/source/content/api_reference.rst +13 -1
- pygeai/_docs/source/content/debugger.rst +376 -83
- pygeai/_docs/source/content/migration.rst +528 -0
- pygeai/_docs/source/content/modules.rst +1 -1
- pygeai/_docs/source/index.rst +59 -7
- pygeai/_docs/source/pygeai.auth.rst +29 -0
- pygeai/_docs/source/pygeai.cli.commands.rst +16 -0
- pygeai/_docs/source/pygeai.cli.rst +8 -0
- pygeai/_docs/source/pygeai.core.utils.rst +16 -0
- pygeai/_docs/source/pygeai.rst +1 -0
- pygeai/_docs/source/pygeai.tests.auth.rst +21 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.rst +16 -0
- pygeai/_docs/source/pygeai.tests.cli.rst +16 -0
- pygeai/_docs/source/pygeai.tests.core.base.rst +8 -0
- pygeai/_docs/source/pygeai.tests.core.embeddings.rst +16 -0
- pygeai/_docs/source/pygeai.tests.core.files.rst +8 -0
- pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.rst +1 -0
- pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +8 -0
- pygeai/_docs/source/pygeai.tests.organization.rst +8 -0
- pygeai/_docs/source/pygeai.tests.rst +2 -0
- pygeai/_docs/source/pygeai.tests.snippets.auth.rst +10 -0
- pygeai/_docs/source/pygeai.tests.snippets.chat.rst +40 -0
- pygeai/_docs/source/pygeai.tests.snippets.dbg.rst +45 -0
- pygeai/_docs/source/pygeai.tests.snippets.embeddings.rst +40 -0
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.dataset.rst +197 -0
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.plan.rst +133 -0
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.result.rst +37 -0
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.rst +10 -0
- pygeai/_docs/source/pygeai.tests.snippets.organization.rst +40 -0
- pygeai/_docs/source/pygeai.tests.snippets.rst +2 -0
- pygeai/admin/clients.py +12 -32
- pygeai/assistant/clients.py +16 -44
- pygeai/assistant/data/clients.py +1 -0
- pygeai/assistant/data_analyst/clients.py +6 -13
- pygeai/assistant/rag/clients.py +24 -67
- pygeai/auth/clients.py +88 -14
- pygeai/auth/endpoints.py +4 -0
- pygeai/chat/clients.py +192 -25
- pygeai/chat/endpoints.py +2 -1
- pygeai/cli/commands/auth.py +178 -2
- pygeai/cli/commands/chat.py +227 -1
- pygeai/cli/commands/embeddings.py +56 -8
- pygeai/cli/commands/lab/ai_lab.py +0 -2
- pygeai/cli/commands/migrate.py +994 -434
- pygeai/cli/commands/organization.py +241 -0
- pygeai/cli/error_handler.py +116 -0
- pygeai/cli/geai.py +28 -10
- pygeai/cli/parsers.py +8 -2
- pygeai/core/base/clients.py +4 -1
- pygeai/core/common/exceptions.py +11 -10
- pygeai/core/embeddings/__init__.py +19 -0
- pygeai/core/embeddings/clients.py +20 -9
- pygeai/core/embeddings/mappers.py +16 -2
- pygeai/core/embeddings/responses.py +9 -2
- pygeai/core/feedback/clients.py +4 -8
- pygeai/core/files/clients.py +10 -25
- pygeai/core/files/managers.py +42 -0
- pygeai/core/llm/clients.py +11 -26
- pygeai/core/models.py +107 -0
- pygeai/core/plugins/clients.py +4 -7
- pygeai/core/rerank/clients.py +4 -8
- pygeai/core/secrets/clients.py +14 -37
- pygeai/core/services/rest.py +1 -1
- pygeai/core/utils/parsers.py +32 -0
- pygeai/core/utils/validators.py +10 -0
- pygeai/dbg/__init__.py +3 -0
- pygeai/dbg/debugger.py +565 -70
- pygeai/evaluation/clients.py +2 -1
- pygeai/evaluation/dataset/clients.py +46 -44
- pygeai/evaluation/plan/clients.py +28 -26
- pygeai/evaluation/result/clients.py +38 -5
- pygeai/gam/clients.py +10 -25
- pygeai/health/clients.py +4 -7
- pygeai/lab/agents/clients.py +21 -54
- pygeai/lab/agents/endpoints.py +2 -0
- pygeai/lab/clients.py +1 -0
- pygeai/lab/models.py +3 -3
- pygeai/lab/processes/clients.py +45 -127
- pygeai/lab/strategies/clients.py +11 -25
- pygeai/lab/tools/clients.py +23 -67
- pygeai/lab/tools/endpoints.py +3 -0
- pygeai/migration/__init__.py +31 -0
- pygeai/migration/strategies.py +404 -155
- pygeai/migration/tools.py +170 -3
- pygeai/organization/clients.py +135 -51
- pygeai/organization/endpoints.py +6 -1
- pygeai/organization/limits/clients.py +32 -91
- pygeai/organization/managers.py +157 -1
- pygeai/organization/mappers.py +76 -2
- pygeai/organization/responses.py +25 -1
- pygeai/proxy/clients.py +4 -1
- pygeai/tests/admin/test_clients.py +16 -11
- pygeai/tests/assistants/rag/test_clients.py +35 -23
- pygeai/tests/assistants/test_clients.py +22 -15
- pygeai/tests/auth/test_clients.py +191 -7
- pygeai/tests/chat/test_clients.py +211 -1
- pygeai/tests/cli/commands/test_embeddings.py +32 -9
- pygeai/tests/cli/commands/test_evaluation.py +7 -0
- pygeai/tests/cli/commands/test_migrate.py +112 -243
- pygeai/tests/cli/test_error_handler.py +225 -0
- pygeai/tests/cli/test_geai_driver.py +154 -0
- pygeai/tests/cli/test_parsers.py +5 -5
- pygeai/tests/core/embeddings/test_clients.py +144 -0
- pygeai/tests/core/embeddings/test_managers.py +171 -0
- pygeai/tests/core/embeddings/test_mappers.py +142 -0
- pygeai/tests/core/feedback/test_clients.py +2 -0
- pygeai/tests/core/files/test_clients.py +1 -0
- pygeai/tests/core/llm/test_clients.py +14 -9
- pygeai/tests/core/plugins/test_clients.py +5 -3
- pygeai/tests/core/rerank/test_clients.py +1 -0
- pygeai/tests/core/secrets/test_clients.py +19 -13
- pygeai/tests/dbg/test_debugger.py +453 -75
- pygeai/tests/evaluation/dataset/test_clients.py +3 -1
- pygeai/tests/evaluation/plan/test_clients.py +4 -2
- pygeai/tests/evaluation/result/test_clients.py +7 -5
- pygeai/tests/gam/test_clients.py +1 -1
- pygeai/tests/health/test_clients.py +1 -0
- pygeai/tests/lab/agents/test_clients.py +9 -0
- pygeai/tests/lab/processes/test_clients.py +36 -0
- pygeai/tests/lab/processes/test_mappers.py +3 -0
- pygeai/tests/lab/strategies/test_clients.py +14 -9
- pygeai/tests/migration/test_strategies.py +45 -218
- pygeai/tests/migration/test_tools.py +133 -9
- pygeai/tests/organization/limits/test_clients.py +17 -0
- pygeai/tests/organization/test_clients.py +206 -1
- pygeai/tests/organization/test_managers.py +122 -1
- pygeai/tests/proxy/test_clients.py +2 -0
- pygeai/tests/proxy/test_integration.py +1 -0
- pygeai/tests/snippets/auth/__init__.py +0 -0
- pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
- pygeai/tests/snippets/chat/get_response.py +15 -0
- pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
- pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
- pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
- pygeai/tests/snippets/dbg/__init__.py +0 -0
- pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
- pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
- pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
- pygeai/tests/snippets/dbg/stepping_example.py +40 -0
- pygeai/tests/snippets/embeddings/cache_example.py +31 -0
- pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
- pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
- pygeai/tests/snippets/embeddings/openai_example.py +30 -0
- pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
- pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
- pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
- pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
- pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
- pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
- pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
- pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
- pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
- pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
- pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
- pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
- pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
- pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
- pygeai/tests/snippets/migrate/__init__.py +45 -0
- pygeai/tests/snippets/migrate/agent_migration.py +110 -0
- pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
- pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
- pygeai/tests/snippets/migrate/process_migration.py +64 -0
- pygeai/tests/snippets/migrate/project_migration.py +42 -0
- pygeai/tests/snippets/migrate/tool_migration.py +64 -0
- pygeai/tests/snippets/organization/create_project.py +2 -2
- pygeai/tests/snippets/organization/get_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_organization_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_project_roles.py +6 -0
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/METADATA +1 -1
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/RECORD +227 -124
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/WHEEL +0 -0
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/entry_points.txt +0 -0
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/licenses/LICENSE +0 -0
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/top_level.txt +0 -0
|
@@ -288,6 +288,202 @@ export_request_data_options = [
|
|
|
288
288
|
)
|
|
289
289
|
]
|
|
290
290
|
|
|
291
|
+
|
|
292
|
+
def get_memberships(option_list: list):
|
|
293
|
+
email = None
|
|
294
|
+
start_page = 1
|
|
295
|
+
page_size = 20
|
|
296
|
+
order_key = None
|
|
297
|
+
order_direction = "desc"
|
|
298
|
+
role_types = None
|
|
299
|
+
|
|
300
|
+
for option_flag, option_arg in option_list:
|
|
301
|
+
if option_flag.name == "email":
|
|
302
|
+
email = option_arg
|
|
303
|
+
if option_flag.name == "start_page":
|
|
304
|
+
start_page = int(option_arg)
|
|
305
|
+
if option_flag.name == "page_size":
|
|
306
|
+
page_size = int(option_arg)
|
|
307
|
+
if option_flag.name == "order_key":
|
|
308
|
+
order_key = option_arg
|
|
309
|
+
if option_flag.name == "order_direction":
|
|
310
|
+
order_direction = option_arg
|
|
311
|
+
if option_flag.name == "role_types":
|
|
312
|
+
role_types = option_arg
|
|
313
|
+
|
|
314
|
+
client = OrganizationClient()
|
|
315
|
+
result = client.get_memberships(email, start_page, page_size, order_key, order_direction, role_types)
|
|
316
|
+
Console.write_stdout(f"Memberships: \n{result}")
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
get_memberships_options = [
|
|
320
|
+
Option(
|
|
321
|
+
"email",
|
|
322
|
+
["--email", "-e"],
|
|
323
|
+
"Email address of the user (optional, case-insensitive)",
|
|
324
|
+
True
|
|
325
|
+
),
|
|
326
|
+
Option(
|
|
327
|
+
"start_page",
|
|
328
|
+
["--start-page"],
|
|
329
|
+
"Page number for pagination (default: 1)",
|
|
330
|
+
True
|
|
331
|
+
),
|
|
332
|
+
Option(
|
|
333
|
+
"page_size",
|
|
334
|
+
["--page-size"],
|
|
335
|
+
"Number of items per page (default: 20)",
|
|
336
|
+
True
|
|
337
|
+
),
|
|
338
|
+
Option(
|
|
339
|
+
"order_key",
|
|
340
|
+
["--order-key"],
|
|
341
|
+
"Field for sorting (only 'organizationName' supported)",
|
|
342
|
+
True
|
|
343
|
+
),
|
|
344
|
+
Option(
|
|
345
|
+
"order_direction",
|
|
346
|
+
["--order-direction"],
|
|
347
|
+
"Sort direction: asc or desc (default: desc)",
|
|
348
|
+
True
|
|
349
|
+
),
|
|
350
|
+
Option(
|
|
351
|
+
"role_types",
|
|
352
|
+
["--role-types"],
|
|
353
|
+
"Comma-separated list: backend, frontend (optional, case-insensitive)",
|
|
354
|
+
True
|
|
355
|
+
),
|
|
356
|
+
]
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def get_project_memberships(option_list: list):
|
|
360
|
+
email = None
|
|
361
|
+
start_page = 1
|
|
362
|
+
page_size = 20
|
|
363
|
+
order_key = None
|
|
364
|
+
order_direction = "desc"
|
|
365
|
+
role_types = None
|
|
366
|
+
|
|
367
|
+
for option_flag, option_arg in option_list:
|
|
368
|
+
if option_flag.name == "email":
|
|
369
|
+
email = option_arg
|
|
370
|
+
if option_flag.name == "start_page":
|
|
371
|
+
start_page = int(option_arg)
|
|
372
|
+
if option_flag.name == "page_size":
|
|
373
|
+
page_size = int(option_arg)
|
|
374
|
+
if option_flag.name == "order_key":
|
|
375
|
+
order_key = option_arg
|
|
376
|
+
if option_flag.name == "order_direction":
|
|
377
|
+
order_direction = option_arg
|
|
378
|
+
if option_flag.name == "role_types":
|
|
379
|
+
role_types = option_arg
|
|
380
|
+
|
|
381
|
+
client = OrganizationClient()
|
|
382
|
+
result = client.get_project_memberships(email, start_page, page_size, order_key, order_direction, role_types)
|
|
383
|
+
Console.write_stdout(f"Project memberships: \n{result}")
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
get_project_memberships_options = [
|
|
387
|
+
Option(
|
|
388
|
+
"email",
|
|
389
|
+
["--email", "-e"],
|
|
390
|
+
"Email address of the user (optional, case-insensitive)",
|
|
391
|
+
True
|
|
392
|
+
),
|
|
393
|
+
Option(
|
|
394
|
+
"start_page",
|
|
395
|
+
["--start-page"],
|
|
396
|
+
"Page number for pagination (default: 1)",
|
|
397
|
+
True
|
|
398
|
+
),
|
|
399
|
+
Option(
|
|
400
|
+
"page_size",
|
|
401
|
+
["--page-size"],
|
|
402
|
+
"Number of items per page (default: 20)",
|
|
403
|
+
True
|
|
404
|
+
),
|
|
405
|
+
Option(
|
|
406
|
+
"order_key",
|
|
407
|
+
["--order-key"],
|
|
408
|
+
"Field for sorting (only 'projectName' supported)",
|
|
409
|
+
True
|
|
410
|
+
),
|
|
411
|
+
Option(
|
|
412
|
+
"order_direction",
|
|
413
|
+
["--order-direction"],
|
|
414
|
+
"Sort direction: asc or desc (default: desc)",
|
|
415
|
+
True
|
|
416
|
+
),
|
|
417
|
+
Option(
|
|
418
|
+
"role_types",
|
|
419
|
+
["--role-types"],
|
|
420
|
+
"Comma-separated list: backend, frontend (optional, case-insensitive)",
|
|
421
|
+
True
|
|
422
|
+
),
|
|
423
|
+
]
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def get_project_roles(option_list: list):
|
|
427
|
+
project_id = None
|
|
428
|
+
for option_flag, option_arg in option_list:
|
|
429
|
+
if option_flag.name == "project_id":
|
|
430
|
+
project_id = option_arg
|
|
431
|
+
|
|
432
|
+
if not project_id:
|
|
433
|
+
raise MissingRequirementException("Cannot retrieve project roles without project-id")
|
|
434
|
+
|
|
435
|
+
client = OrganizationClient()
|
|
436
|
+
result = client.get_project_roles(project_id)
|
|
437
|
+
Console.write_stdout(f"Project roles: \n{result}")
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
get_project_roles_options = [
|
|
441
|
+
PROJECT_ID_OPTION,
|
|
442
|
+
]
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
def get_project_members(option_list: list):
|
|
446
|
+
project_id = None
|
|
447
|
+
for option_flag, option_arg in option_list:
|
|
448
|
+
if option_flag.name == "project_id":
|
|
449
|
+
project_id = option_arg
|
|
450
|
+
|
|
451
|
+
if not project_id:
|
|
452
|
+
raise MissingRequirementException("Cannot retrieve project members without project-id")
|
|
453
|
+
|
|
454
|
+
client = OrganizationClient()
|
|
455
|
+
result = client.get_project_members(project_id)
|
|
456
|
+
Console.write_stdout(f"Project members: \n{result}")
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
get_project_members_options = [
|
|
460
|
+
PROJECT_ID_OPTION,
|
|
461
|
+
]
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def get_organization_members(option_list: list):
|
|
465
|
+
organization_id = None
|
|
466
|
+
for option_flag, option_arg in option_list:
|
|
467
|
+
if option_flag.name == "organization_id":
|
|
468
|
+
organization_id = option_arg
|
|
469
|
+
|
|
470
|
+
if not organization_id:
|
|
471
|
+
raise MissingRequirementException("Cannot retrieve organization members without organization-id")
|
|
472
|
+
|
|
473
|
+
client = OrganizationClient()
|
|
474
|
+
result = client.get_organization_members(organization_id)
|
|
475
|
+
Console.write_stdout(f"Organization members: \n{result}")
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
get_organization_members_options = [
|
|
479
|
+
Option(
|
|
480
|
+
"organization_id",
|
|
481
|
+
["--organization-id", "--oid"],
|
|
482
|
+
"GUID of the organization (required)",
|
|
483
|
+
True
|
|
484
|
+
),
|
|
485
|
+
]
|
|
486
|
+
|
|
291
487
|
organization_commands = [
|
|
292
488
|
Command(
|
|
293
489
|
"help",
|
|
@@ -370,4 +566,49 @@ organization_commands = [
|
|
|
370
566
|
[],
|
|
371
567
|
export_request_data_options
|
|
372
568
|
),
|
|
569
|
+
Command(
|
|
570
|
+
"get_memberships",
|
|
571
|
+
["get-memberships"],
|
|
572
|
+
"Get user memberships across organizations and projects",
|
|
573
|
+
get_memberships,
|
|
574
|
+
ArgumentsEnum.OPTIONAL,
|
|
575
|
+
[],
|
|
576
|
+
get_memberships_options
|
|
577
|
+
),
|
|
578
|
+
Command(
|
|
579
|
+
"get_project_memberships",
|
|
580
|
+
["get-project-memberships"],
|
|
581
|
+
"Get user project memberships within an organization",
|
|
582
|
+
get_project_memberships,
|
|
583
|
+
ArgumentsEnum.OPTIONAL,
|
|
584
|
+
[],
|
|
585
|
+
get_project_memberships_options
|
|
586
|
+
),
|
|
587
|
+
Command(
|
|
588
|
+
"get_project_roles",
|
|
589
|
+
["get-project-roles"],
|
|
590
|
+
"Get all roles supported by a project",
|
|
591
|
+
get_project_roles,
|
|
592
|
+
ArgumentsEnum.REQUIRED,
|
|
593
|
+
[],
|
|
594
|
+
get_project_roles_options
|
|
595
|
+
),
|
|
596
|
+
Command(
|
|
597
|
+
"get_project_members",
|
|
598
|
+
["get-project-members"],
|
|
599
|
+
"Get all members and their roles for a project",
|
|
600
|
+
get_project_members,
|
|
601
|
+
ArgumentsEnum.REQUIRED,
|
|
602
|
+
[],
|
|
603
|
+
get_project_members_options
|
|
604
|
+
),
|
|
605
|
+
Command(
|
|
606
|
+
"get_organization_members",
|
|
607
|
+
["get-organization-members"],
|
|
608
|
+
"Get all members and their roles for an organization",
|
|
609
|
+
get_organization_members,
|
|
610
|
+
ArgumentsEnum.REQUIRED,
|
|
611
|
+
[],
|
|
612
|
+
get_organization_members_options
|
|
613
|
+
),
|
|
373
614
|
]
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
from difflib import SequenceMatcher
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
from pygeai import logger
|
|
6
|
+
from pygeai.cli.commands import Command, Option
|
|
7
|
+
from pygeai.core.utils.console import Console
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ExitCode:
|
|
11
|
+
SUCCESS = 0
|
|
12
|
+
USER_INPUT_ERROR = 1
|
|
13
|
+
MISSING_REQUIREMENT = 2
|
|
14
|
+
SERVICE_ERROR = 3
|
|
15
|
+
KEYBOARD_INTERRUPT = 130
|
|
16
|
+
UNEXPECTED_ERROR = 255
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ErrorHandler:
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def format_error(error_type: str, message: str, suggestion: Optional[str] = None, show_help: bool = True) -> str:
|
|
23
|
+
output = f"ERROR: {message}"
|
|
24
|
+
|
|
25
|
+
if suggestion:
|
|
26
|
+
output += f"\n → {suggestion}"
|
|
27
|
+
|
|
28
|
+
if show_help:
|
|
29
|
+
output += "\n\nRun 'geai help' for usage information."
|
|
30
|
+
|
|
31
|
+
return output
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def find_similar_items(item: str, available_items: List[str], threshold: float = 0.6) -> List[str]:
|
|
35
|
+
similarities = []
|
|
36
|
+
for available in available_items:
|
|
37
|
+
ratio = SequenceMatcher(None, item.lower(), available.lower()).ratio()
|
|
38
|
+
if ratio >= threshold:
|
|
39
|
+
similarities.append((available, ratio))
|
|
40
|
+
|
|
41
|
+
similarities.sort(key=lambda x: x[1], reverse=True)
|
|
42
|
+
return [item[0] for item in similarities[:3]]
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def get_available_commands(commands: List[Command]) -> List[str]:
|
|
46
|
+
all_identifiers = []
|
|
47
|
+
for cmd in commands:
|
|
48
|
+
all_identifiers.extend(cmd.identifiers)
|
|
49
|
+
return all_identifiers
|
|
50
|
+
|
|
51
|
+
@staticmethod
|
|
52
|
+
def get_available_options(options: List[Option]) -> List[str]:
|
|
53
|
+
all_identifiers = []
|
|
54
|
+
for opt in options:
|
|
55
|
+
all_identifiers.extend(opt.identifiers)
|
|
56
|
+
return all_identifiers
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def handle_unknown_command(command: str, available_commands: List[Command]) -> str:
|
|
60
|
+
cmd_identifiers = ErrorHandler.get_available_commands(available_commands)
|
|
61
|
+
similar = ErrorHandler.find_similar_items(command, cmd_identifiers)
|
|
62
|
+
|
|
63
|
+
message = f"'{command}' is not a valid command."
|
|
64
|
+
|
|
65
|
+
if similar:
|
|
66
|
+
suggestion = f"Did you mean: {', '.join(similar)}?"
|
|
67
|
+
else:
|
|
68
|
+
suggestion = f"Available commands: {', '.join(sorted(set([cmd.identifiers[0] for cmd in available_commands])))}"
|
|
69
|
+
|
|
70
|
+
return ErrorHandler.format_error("Unknown Command", message, suggestion)
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
def handle_unknown_option(option: str, available_options: List[Option]) -> str:
|
|
74
|
+
opt_identifiers = ErrorHandler.get_available_options(available_options)
|
|
75
|
+
similar = ErrorHandler.find_similar_items(option, opt_identifiers)
|
|
76
|
+
|
|
77
|
+
message = f"'{option}' is not a valid option."
|
|
78
|
+
|
|
79
|
+
if similar:
|
|
80
|
+
suggestion = f"Did you mean: {', '.join(similar)}?"
|
|
81
|
+
else:
|
|
82
|
+
suggestion = f"Available options: {', '.join(sorted(set([opt.identifiers[0] for opt in available_options])))}"
|
|
83
|
+
|
|
84
|
+
return ErrorHandler.format_error("Unknown Option", message, suggestion)
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def handle_missing_requirement(requirement_message: str) -> str:
|
|
88
|
+
message = requirement_message
|
|
89
|
+
suggestion = "Please provide all required parameters."
|
|
90
|
+
return ErrorHandler.format_error("Missing Requirement", message, suggestion)
|
|
91
|
+
|
|
92
|
+
@staticmethod
|
|
93
|
+
def handle_invalid_agent(error_message: str) -> str:
|
|
94
|
+
message = f"Failed to retrieve or validate the agent.\n Details: {error_message}"
|
|
95
|
+
suggestion = "Check your agent configuration and ensure the agent exists."
|
|
96
|
+
return ErrorHandler.format_error("Invalid Agent", message, suggestion)
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def handle_wrong_argument(error_message: str, usage: str) -> str:
|
|
100
|
+
Console.write_stderr(f"usage: {usage}")
|
|
101
|
+
message = error_message
|
|
102
|
+
suggestion = "Check the command syntax and try again."
|
|
103
|
+
return ErrorHandler.format_error("Invalid Argument", message, suggestion)
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def handle_keyboard_interrupt() -> str:
|
|
107
|
+
return "\n\nOperation cancelled by user."
|
|
108
|
+
|
|
109
|
+
@staticmethod
|
|
110
|
+
def handle_unexpected_error(exception: Exception) -> str:
|
|
111
|
+
logger.error(f"Unexpected error occurred: {exception}")
|
|
112
|
+
logger.error(traceback.format_exc())
|
|
113
|
+
|
|
114
|
+
message = "An unexpected error occurred. This may be a bug."
|
|
115
|
+
suggestion = f"Please report this issue to geai-sdk@globant.com with the following details:\n Error: {str(exception)}\n Run with geai-dbg for more details."
|
|
116
|
+
return ErrorHandler.format_error("Critical Error", message, suggestion, show_help=False)
|
pygeai/cli/geai.py
CHANGED
|
@@ -5,6 +5,7 @@ from pygeai.cli.commands.base import base_commands, base_options
|
|
|
5
5
|
from pygeai.cli.commands import ArgumentsEnum, Command
|
|
6
6
|
from pygeai.cli.parsers import CommandParser
|
|
7
7
|
from pygeai.cli.texts.help import CLI_USAGE
|
|
8
|
+
from pygeai.cli.error_handler import ErrorHandler, ExitCode
|
|
8
9
|
from pygeai.core.base.session import get_session
|
|
9
10
|
from pygeai.core.common.exceptions import UnknownArgumentError, MissingRequirementException, WrongArgumentError, \
|
|
10
11
|
InvalidAgentException
|
|
@@ -64,19 +65,37 @@ class CLIDriver:
|
|
|
64
65
|
arguments = []
|
|
65
66
|
|
|
66
67
|
self.process_command(command, arguments)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
return ExitCode.SUCCESS
|
|
69
|
+
except UnknownArgumentError as e:
|
|
70
|
+
if hasattr(e, 'available_commands') and e.available_commands:
|
|
71
|
+
error_msg = ErrorHandler.handle_unknown_command(e.arg, e.available_commands)
|
|
72
|
+
elif hasattr(e, 'available_options') and e.available_options:
|
|
73
|
+
error_msg = ErrorHandler.handle_unknown_option(e.arg, e.available_options)
|
|
74
|
+
else:
|
|
75
|
+
error_msg = ErrorHandler.format_error("Unknown Argument", str(e))
|
|
76
|
+
|
|
77
|
+
Console.write_stderr(error_msg)
|
|
78
|
+
return ExitCode.USER_INPUT_ERROR
|
|
79
|
+
except WrongArgumentError as e:
|
|
80
|
+
error_msg = ErrorHandler.handle_wrong_argument(str(e), CLI_USAGE)
|
|
81
|
+
Console.write_stderr(error_msg)
|
|
82
|
+
return ExitCode.USER_INPUT_ERROR
|
|
71
83
|
except MissingRequirementException as e:
|
|
72
|
-
|
|
84
|
+
error_msg = ErrorHandler.handle_missing_requirement(str(e))
|
|
85
|
+
Console.write_stderr(error_msg)
|
|
86
|
+
return ExitCode.MISSING_REQUIREMENT
|
|
73
87
|
except InvalidAgentException as e:
|
|
74
|
-
|
|
88
|
+
error_msg = ErrorHandler.handle_invalid_agent(str(e))
|
|
89
|
+
Console.write_stderr(error_msg)
|
|
90
|
+
return ExitCode.SERVICE_ERROR
|
|
75
91
|
except KeyboardInterrupt:
|
|
76
|
-
|
|
92
|
+
message = ErrorHandler.handle_keyboard_interrupt()
|
|
93
|
+
Console.write_stdout(message)
|
|
94
|
+
return ExitCode.KEYBOARD_INTERRUPT
|
|
77
95
|
except Exception as e:
|
|
78
|
-
|
|
79
|
-
|
|
96
|
+
error_msg = ErrorHandler.handle_unexpected_error(e)
|
|
97
|
+
Console.write_stderr(error_msg)
|
|
98
|
+
return ExitCode.UNEXPECTED_ERROR
|
|
80
99
|
|
|
81
100
|
def process_command(self, command: Command, arguments: list[str]):
|
|
82
101
|
"""
|
|
@@ -107,4 +126,3 @@ class CLIDriver:
|
|
|
107
126
|
else:
|
|
108
127
|
option_list = CommandParser(None, subcommand.options).extract_option_list(subcommand_arguments)
|
|
109
128
|
subcommand.action(option_list)
|
|
110
|
-
|
pygeai/cli/parsers.py
CHANGED
|
@@ -18,7 +18,10 @@ class CommandParser:
|
|
|
18
18
|
"""
|
|
19
19
|
command = self._get_associated_command(arg)
|
|
20
20
|
if not command:
|
|
21
|
-
|
|
21
|
+
error = UnknownArgumentError(f"'{arg}' is not a valid command.")
|
|
22
|
+
error.arg = arg
|
|
23
|
+
error.available_commands = self.available_commands
|
|
24
|
+
raise error
|
|
22
25
|
|
|
23
26
|
return command
|
|
24
27
|
|
|
@@ -39,7 +42,10 @@ class CommandParser:
|
|
|
39
42
|
|
|
40
43
|
flag = self._get_associated_option(arg)
|
|
41
44
|
if not flag:
|
|
42
|
-
|
|
45
|
+
error = UnknownArgumentError(f"'{arg}' is not a valid option.")
|
|
46
|
+
error.arg = arg
|
|
47
|
+
error.available_options = self.available_options
|
|
48
|
+
raise error
|
|
43
49
|
|
|
44
50
|
if flag.requires_args:
|
|
45
51
|
complementary_arg = True
|
pygeai/core/base/clients.py
CHANGED
|
@@ -3,6 +3,7 @@ from abc import ABC
|
|
|
3
3
|
from pygeai.core.base.session import get_session, Session
|
|
4
4
|
from pygeai.core.common.exceptions import MissingRequirementException
|
|
5
5
|
from pygeai.core.services.rest import ApiService
|
|
6
|
+
from pygeai.core.utils.validators import validate_status_code
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class BaseClient(ABC):
|
|
@@ -19,7 +20,9 @@ class BaseClient(ABC):
|
|
|
19
20
|
if not self.__session:
|
|
20
21
|
raise MissingRequirementException("API KEY and BASE URL must be defined in order to use this functionality")
|
|
21
22
|
elif api_key and base_url:
|
|
22
|
-
self.__session =
|
|
23
|
+
self.__session = get_session()
|
|
24
|
+
self.__session.api_key = api_key
|
|
25
|
+
self.__session.base_url = base_url
|
|
23
26
|
else:
|
|
24
27
|
self.__session = get_session()
|
|
25
28
|
|
pygeai/core/common/exceptions.py
CHANGED
|
@@ -6,55 +6,56 @@ class GEAIException(Exception):
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class UnknownArgumentError(GEAIException):
|
|
9
|
-
"""
|
|
9
|
+
"""Raised when an unknown or invalid command/option is provided"""
|
|
10
10
|
pass
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class MissingRequirementException(GEAIException):
|
|
14
|
-
"""
|
|
14
|
+
"""Raised when a required parameter or argument is missing"""
|
|
15
15
|
pass
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class WrongArgumentError(GEAIException):
|
|
19
|
-
"""
|
|
19
|
+
"""Raised when arguments are incorrectly formatted or invalid"""
|
|
20
20
|
pass
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class ServerResponseError(GEAIException):
|
|
24
|
-
"""
|
|
24
|
+
"""Raised when the server returns an error response"""
|
|
25
25
|
pass
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class APIError(GEAIException):
|
|
29
|
-
"""
|
|
29
|
+
"""Raised when an API request fails"""
|
|
30
30
|
pass
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class InvalidPathException(GEAIException):
|
|
34
|
-
"""
|
|
34
|
+
"""Raised when a file or directory path is invalid or not found"""
|
|
35
35
|
pass
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class InvalidJSONException(GEAIException):
|
|
39
|
-
"""
|
|
39
|
+
"""Raised when JSON data cannot be parsed or is malformed"""
|
|
40
40
|
pass
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
class InvalidAPIResponseException(GEAIException):
|
|
44
|
-
"""
|
|
44
|
+
"""Raised when the API response format is unexpected or invalid"""
|
|
45
45
|
pass
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
class InvalidResponseException(GEAIException):
|
|
49
|
-
"""
|
|
49
|
+
"""Raised when a response cannot be retrieved or processed"""
|
|
50
50
|
pass
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
class InvalidAgentException(GEAIException):
|
|
54
|
-
"""
|
|
54
|
+
"""Raised when an agent cannot be retrieved, validated, or is misconfigured"""
|
|
55
55
|
pass
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
class APIResponseError(GEAIException):
|
|
59
|
+
"""Raised when there is an error in the API response"""
|
|
59
60
|
pass
|
|
60
61
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from pygeai.core.embeddings.clients import EmbeddingsClient
|
|
2
|
+
from pygeai.core.embeddings.managers import EmbeddingsManager
|
|
3
|
+
from pygeai.core.embeddings.models import EmbeddingConfiguration
|
|
4
|
+
from pygeai.core.embeddings.responses import (
|
|
5
|
+
EmbeddingResponse,
|
|
6
|
+
EmbeddingData,
|
|
7
|
+
UsageInfo,
|
|
8
|
+
TokenDetails
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
'EmbeddingsClient',
|
|
13
|
+
'EmbeddingsManager',
|
|
14
|
+
'EmbeddingConfiguration',
|
|
15
|
+
'EmbeddingResponse',
|
|
16
|
+
'EmbeddingData',
|
|
17
|
+
'UsageInfo',
|
|
18
|
+
'TokenDetails'
|
|
19
|
+
]
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
from json import JSONDecodeError
|
|
2
1
|
|
|
3
2
|
from pygeai import logger
|
|
4
3
|
from pygeai.core.base.clients import BaseClient
|
|
5
|
-
from pygeai.core.common.exceptions import InvalidAPIResponseException
|
|
4
|
+
from pygeai.core.common.exceptions import InvalidAPIResponseException, APIResponseError
|
|
6
5
|
from pygeai.core.embeddings.endpoints import GENERATE_EMBEDDINGS
|
|
6
|
+
from pygeai.core.utils.validators import validate_status_code
|
|
7
|
+
from pygeai.core.utils.parsers import parse_json_response
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class EmbeddingsClient(BaseClient):
|
|
@@ -42,7 +43,21 @@ class EmbeddingsClient(BaseClient):
|
|
|
42
43
|
|
|
43
44
|
:return: dict - A dictionary containing the embedding results, including the model used, the generated
|
|
44
45
|
embedding vectors, and usage statistics.
|
|
46
|
+
:raises ValueError: If validation fails for input parameters.
|
|
45
47
|
"""
|
|
48
|
+
if not input_list or len(input_list) == 0:
|
|
49
|
+
raise ValueError("input_list cannot be empty")
|
|
50
|
+
|
|
51
|
+
for idx, inp in enumerate(input_list):
|
|
52
|
+
if not inp or (isinstance(inp, str) and inp.strip() == ""):
|
|
53
|
+
raise ValueError(f"Input at index {idx} cannot be empty")
|
|
54
|
+
|
|
55
|
+
if encoding_format is not None and encoding_format not in ['float', 'base64']:
|
|
56
|
+
raise ValueError("encoding_format must be either 'float' or 'base64'")
|
|
57
|
+
|
|
58
|
+
if dimensions is not None and dimensions <= 0:
|
|
59
|
+
raise ValueError("dimensions must be a positive integer")
|
|
60
|
+
|
|
46
61
|
data = {
|
|
47
62
|
'model': model,
|
|
48
63
|
'input': input_list,
|
|
@@ -73,10 +88,6 @@ class EmbeddingsClient(BaseClient):
|
|
|
73
88
|
data=data,
|
|
74
89
|
headers=headers
|
|
75
90
|
)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
except JSONDecodeError as e:
|
|
80
|
-
logger.error(f"Unable to generate embeddings: JSON parsin error: {e}; Response: {response.text}")
|
|
81
|
-
raise InvalidAPIResponseException(f"Unable to generate embeddings: {response.text}")
|
|
82
|
-
|
|
91
|
+
validate_status_code(response)
|
|
92
|
+
return parse_json_response(response, "generate embeddings")
|
|
93
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from pygeai.core.embeddings.responses import EmbeddingResponse, EmbeddingData, UsageInfo
|
|
1
|
+
from pygeai.core.embeddings.responses import EmbeddingResponse, EmbeddingData, UsageInfo, TokenDetails
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class EmbeddingsResponseMapper:
|
|
@@ -29,10 +29,24 @@ class EmbeddingsResponseMapper:
|
|
|
29
29
|
|
|
30
30
|
@classmethod
|
|
31
31
|
def map_to_usage_info(cls, data: dict) -> UsageInfo:
|
|
32
|
+
completion_tokens_details_data = data.get('completion_tokens_details')
|
|
33
|
+
prompt_tokens_details_data = data.get('prompt_tokens_details')
|
|
34
|
+
|
|
32
35
|
return UsageInfo(
|
|
33
36
|
prompt_tokens=data.get('prompt_tokens', 0),
|
|
34
37
|
total_cost=data.get('total_cost', 0.0),
|
|
35
38
|
total_tokens=data.get('total_tokens', 0),
|
|
36
39
|
currency=data.get('currency', ''),
|
|
37
|
-
prompt_cost=data.get('prompt_cost', 0.0)
|
|
40
|
+
prompt_cost=data.get('prompt_cost', 0.0),
|
|
41
|
+
completion_tokens_details=cls._parse_token_details(completion_tokens_details_data),
|
|
42
|
+
prompt_tokens_details=cls._parse_token_details(prompt_tokens_details_data)
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def _parse_token_details(cls, data: dict) -> TokenDetails | None:
|
|
47
|
+
if data is None:
|
|
48
|
+
return None
|
|
49
|
+
return TokenDetails(
|
|
50
|
+
reasoning_tokens=data.get('reasoning_tokens'),
|
|
51
|
+
cached_tokens=data.get('cached_tokens')
|
|
38
52
|
)
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
from typing import List
|
|
1
|
+
from typing import List, Union, Optional
|
|
2
2
|
|
|
3
3
|
from pydantic.main import BaseModel
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
class TokenDetails(BaseModel):
|
|
7
|
+
reasoning_tokens: Optional[int] = None
|
|
8
|
+
cached_tokens: Optional[int] = None
|
|
9
|
+
|
|
10
|
+
|
|
6
11
|
class EmbeddingData(BaseModel):
|
|
7
12
|
index: int
|
|
8
|
-
embedding: List[float]
|
|
13
|
+
embedding: Union[List[float], str]
|
|
9
14
|
object: str
|
|
10
15
|
|
|
11
16
|
|
|
@@ -15,6 +20,8 @@ class UsageInfo(BaseModel):
|
|
|
15
20
|
total_tokens: int
|
|
16
21
|
currency: str
|
|
17
22
|
prompt_cost: float
|
|
23
|
+
completion_tokens_details: Optional[TokenDetails] = None
|
|
24
|
+
prompt_tokens_details: Optional[TokenDetails] = None
|
|
18
25
|
|
|
19
26
|
|
|
20
27
|
class EmbeddingResponse(BaseModel):
|