octostar-python-client 0.1.759__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.
- octostar/__init__.py +9 -0
- octostar/api/__init__.py +1 -0
- octostar/api/apps/__init__.py +0 -0
- octostar/api/apps/deploy_app.py +210 -0
- octostar/api/apps/execute_app_job.py +188 -0
- octostar/api/apps/get_app_logs.py +210 -0
- octostar/api/apps/get_apps_url.py +188 -0
- octostar/api/apps/get_job_logs.py +210 -0
- octostar/api/apps/get_job_progress.py +162 -0
- octostar/api/apps/kill_job.py +160 -0
- octostar/api/apps/list_app_jobs.py +276 -0
- octostar/api/apps/list_apps.py +251 -0
- octostar/api/apps/set_job_progress.py +216 -0
- octostar/api/apps/undeploy_app.py +160 -0
- octostar/api/metadata/__init__.py +0 -0
- octostar/api/metadata/get_version.py +232 -0
- octostar/api/metadata/get_whoami.py +232 -0
- octostar/api/notifications/__init__.py +0 -0
- octostar/api/notifications/delete_stream.py +222 -0
- octostar/api/notifications/get_subscriptions.py +240 -0
- octostar/api/notifications/publish_notification.py +275 -0
- octostar/api/notifications/pull_events_from_stream.py +282 -0
- octostar/api/notifications/push_event_to_stream.py +265 -0
- octostar/api/notifications/toast.py +264 -0
- octostar/api/ontology/__init__.py +0 -0
- octostar/api/ontology/fetch_ontology_data.py +275 -0
- octostar/api/ontology/get_ontologies.py +237 -0
- octostar/api/ontology/multi_query.py +297 -0
- octostar/api/ontology/query.py +276 -0
- octostar/api/pipeline/__init__.py +1 -0
- octostar/api/pipeline/get_processing_status.py +185 -0
- octostar/api/pipeline/update_processing_status.py +164 -0
- octostar/api/search/__init__.py +0 -0
- octostar/api/search/get_annotations.py +153 -0
- octostar/api/workspace_data/__init__.py +0 -0
- octostar/api/workspace_data/delete_blob.py +212 -0
- octostar/api/workspace_data/delete_entities.py +326 -0
- octostar/api/workspace_data/download_blob.py +235 -0
- octostar/api/workspace_data/get_attachment.py +336 -0
- octostar/api/workspace_data/get_files_tree.py +397 -0
- octostar/api/workspace_data/upload_blob.py +235 -0
- octostar/api/workspace_data/upsert_entities.py +284 -0
- octostar/api/workspace_permissions/__init__.py +0 -0
- octostar/api/workspace_permissions/get_permissions.py +325 -0
- octostar/api/workspace_tags/__init__.py +0 -0
- octostar/api/workspace_tags/delete_tag_from_entities.py +141 -0
- octostar/api/workspace_tags/tag_entities.py +180 -0
- octostar/client.py +492 -0
- octostar/errors.py +50 -0
- octostar/models/__init__.py +249 -0
- octostar/models/acknowledgement.py +74 -0
- octostar/models/acknowledgement_with_data.py +82 -0
- octostar/models/app_status.py +239 -0
- octostar/models/app_status_annotations.py +66 -0
- octostar/models/app_status_labels.py +69 -0
- octostar/models/app_with_url.py +82 -0
- octostar/models/child_processing_status.py +118 -0
- octostar/models/delete_entities_response_401.py +74 -0
- octostar/models/delete_entities_response_409.py +82 -0
- octostar/models/delete_entities_response_500.py +82 -0
- octostar/models/delete_stream_response_401.py +74 -0
- octostar/models/delete_tag_from_entities_response_401.py +74 -0
- octostar/models/deploy_app_json_body.py +90 -0
- octostar/models/deploy_app_json_body_secrets.py +65 -0
- octostar/models/deploy_app_response_200.py +98 -0
- octostar/models/deploy_app_response_200_data.py +60 -0
- octostar/models/deploy_app_response_400.py +82 -0
- octostar/models/deploy_app_response_403.py +82 -0
- octostar/models/deploy_app_response_404.py +82 -0
- octostar/models/deploy_app_response_409.py +82 -0
- octostar/models/deploy_app_response_500.py +82 -0
- octostar/models/entity.py +80 -0
- octostar/models/entity_response.py +99 -0
- octostar/models/entity_response_s3_urls.py +93 -0
- octostar/models/entity_response_s3_urls_additional_property.py +105 -0
- octostar/models/entity_response_s3_urls_additional_property_fields.py +114 -0
- octostar/models/execute_app_job_json_body.py +151 -0
- octostar/models/execute_app_job_json_body_annotation.py +65 -0
- octostar/models/execute_app_job_response_401.py +74 -0
- octostar/models/fetch_ontology_data_response_200.py +60 -0
- octostar/models/fetch_ontology_data_response_401.py +74 -0
- octostar/models/fetch_ontology_data_response_500.py +82 -0
- octostar/models/get_app_logs_response_401.py +74 -0
- octostar/models/get_app_logs_response_404.py +74 -0
- octostar/models/get_app_logs_response_500.py +82 -0
- octostar/models/get_apps_url_json_body.py +76 -0
- octostar/models/get_apps_url_response_401.py +74 -0
- octostar/models/get_apps_url_response_500.py +82 -0
- octostar/models/get_attachment_response_200.py +74 -0
- octostar/models/get_attachment_response_401.py +74 -0
- octostar/models/get_files_tree_response_200.py +106 -0
- octostar/models/get_files_tree_response_200_status.py +8 -0
- octostar/models/get_files_tree_response_400.py +111 -0
- octostar/models/get_files_tree_response_400_data.py +60 -0
- octostar/models/get_files_tree_response_400_status.py +8 -0
- octostar/models/get_files_tree_response_401.py +74 -0
- octostar/models/get_files_tree_response_500.py +111 -0
- octostar/models/get_files_tree_response_500_data.py +60 -0
- octostar/models/get_files_tree_response_500_status.py +8 -0
- octostar/models/get_job_logs_response_401.py +74 -0
- octostar/models/get_job_logs_response_404.py +74 -0
- octostar/models/get_job_logs_response_500.py +82 -0
- octostar/models/get_job_progress_response_401.py +74 -0
- octostar/models/get_object_response_401.py +74 -0
- octostar/models/get_ontologies_response_401.py +74 -0
- octostar/models/get_ontologies_response_500.py +81 -0
- octostar/models/get_permissions_response_200.py +98 -0
- octostar/models/get_permissions_response_400.py +82 -0
- octostar/models/get_permissions_response_401.py +74 -0
- octostar/models/get_permissions_response_500.py +82 -0
- octostar/models/get_processing_status_response_200.py +104 -0
- octostar/models/get_processing_status_response_200_data.py +87 -0
- octostar/models/get_processing_status_response_400.py +82 -0
- octostar/models/get_processing_status_response_500.py +82 -0
- octostar/models/get_subscriptions_response_200_item.py +74 -0
- octostar/models/get_version_response_200.py +74 -0
- octostar/models/get_version_response_404.py +74 -0
- octostar/models/get_whoami_response_200.py +129 -0
- octostar/models/get_whoami_response_401.py +74 -0
- octostar/models/insert_entity.py +114 -0
- octostar/models/insert_entity_base.py +266 -0
- octostar/models/insert_entity_relationships_item.py +107 -0
- octostar/models/insert_entity_request.py +94 -0
- octostar/models/internal_server_error.py +82 -0
- octostar/models/job_execution_result.py +146 -0
- octostar/models/job_status.py +196 -0
- octostar/models/job_status_labels.py +60 -0
- octostar/models/job_with_url.py +82 -0
- octostar/models/kill_job_response_401.py +74 -0
- octostar/models/list_app_jobs_response_401.py +74 -0
- octostar/models/list_app_jobs_response_500.py +82 -0
- octostar/models/list_apps_response_401.py +74 -0
- octostar/models/list_apps_response_500.py +82 -0
- octostar/models/multi_query_json_body.py +100 -0
- octostar/models/multi_query_json_body_queries_item.py +80 -0
- octostar/models/multi_query_response_400.py +82 -0
- octostar/models/multi_query_response_401.py +74 -0
- octostar/models/not_found_error.py +74 -0
- octostar/models/octostar_event.py +96 -0
- octostar/models/octostar_event_octostar_payload.py +100 -0
- octostar/models/octostar_event_octostar_payload_level.py +11 -0
- octostar/models/os_notification.py +122 -0
- octostar/models/processing_status.py +262 -0
- octostar/models/processing_status_code.py +14 -0
- octostar/models/progress_request.py +73 -0
- octostar/models/publish_notification_response_401.py +74 -0
- octostar/models/pull_events_from_stream_response_401.py +74 -0
- octostar/models/push_event_to_stream_response_401.py +74 -0
- octostar/models/query_json_body.py +101 -0
- octostar/models/query_json_body_params.py +60 -0
- octostar/models/query_response_400.py +82 -0
- octostar/models/query_response_401.py +74 -0
- octostar/models/set_job_progress_response_401.py +74 -0
- octostar/models/string_to_value_label_map.py +99 -0
- octostar/models/string_to_value_label_map_data.py +89 -0
- octostar/models/string_to_value_label_map_data_additional_property.py +80 -0
- octostar/models/successful_get_tags.py +103 -0
- octostar/models/successful_insertion.py +98 -0
- octostar/models/tag_entities_response_401.py +74 -0
- octostar/models/toast_level.py +11 -0
- octostar/models/toast_response_401.py +74 -0
- octostar/models/undeploy_app_response_401.py +74 -0
- octostar/models/update_processing_status_response_200.py +82 -0
- octostar/models/update_processing_status_response_400.py +82 -0
- octostar/models/update_processing_status_response_500.py +82 -0
- octostar/models/upsert_entities_response_401.py +74 -0
- octostar/models/upsert_entity.py +114 -0
- octostar/models/upsert_entity_base.py +266 -0
- octostar/models/upsert_entity_relationships_item.py +107 -0
- octostar/py.typed +1 -0
- octostar/types.py +54 -0
- octostar/utils/__init__.py +15 -0
- octostar/utils/chat/__init__.py +0 -0
- octostar/utils/chat/chat.py +513 -0
- octostar/utils/chat/detokenize.py +105 -0
- octostar/utils/chat/get_default_model.py +50 -0
- octostar/utils/chat/list_models.py +91 -0
- octostar/utils/chat/tokenize.py +105 -0
- octostar/utils/commons.py +226 -0
- octostar/utils/exceptions.py +134 -0
- octostar/utils/jobs/__init__.py +0 -0
- octostar/utils/jobs/apps/__init__.py +0 -0
- octostar/utils/jobs/apps/deploy_app.py +81 -0
- octostar/utils/jobs/apps/execute_app_job.py +114 -0
- octostar/utils/jobs/apps/get_app_logs.py +113 -0
- octostar/utils/jobs/apps/get_app_secret.py +102 -0
- octostar/utils/jobs/apps/get_apps_url.py +73 -0
- octostar/utils/jobs/apps/list_app_jobs.py +62 -0
- octostar/utils/jobs/apps/list_apps.py +126 -0
- octostar/utils/jobs/apps/undeploy_app.py +48 -0
- octostar/utils/jobs/get_job_logs.py +113 -0
- octostar/utils/jobs/get_job_progress.py +76 -0
- octostar/utils/jobs/kill_job.py +47 -0
- octostar/utils/jobs/set_job_progress.py +67 -0
- octostar/utils/meta/__init__.py +0 -0
- octostar/utils/meta/get_version.py +30 -0
- octostar/utils/meta/get_whoami.py +30 -0
- octostar/utils/notifications/__init__.py +0 -0
- octostar/utils/notifications/delete_stream.py +58 -0
- octostar/utils/notifications/get_my_subscriptions.py +49 -0
- octostar/utils/notifications/publish_notification.py +73 -0
- octostar/utils/notifications/pull_event_from_stream.py +63 -0
- octostar/utils/notifications/pull_events_from_stream.py +64 -0
- octostar/utils/notifications/push_event_to_stream.py +109 -0
- octostar/utils/notifications/push_events_to_stream.py +137 -0
- octostar/utils/notifications/toast.py +92 -0
- octostar/utils/ontology/__init__.py +10 -0
- octostar/utils/ontology/fetch_ontology_data.py +141 -0
- octostar/utils/ontology/get_ontologies.py +55 -0
- octostar/utils/ontology/multiquery_ontology.py +287 -0
- octostar/utils/ontology/query_ontology.py +186 -0
- octostar/utils/pipeline/__init__.py +1 -0
- octostar/utils/pipeline/get_processing_status.py +230 -0
- octostar/utils/pipeline/update_processing_status.py +286 -0
- octostar/utils/search/__init__.py +11 -0
- octostar/utils/search/bulk_update.py +138 -0
- octostar/utils/search/count.py +117 -0
- octostar/utils/search/get_entity_annotations.py +304 -0
- octostar/utils/search/get_index_definition.py +111 -0
- octostar/utils/search/multi_search.py +129 -0
- octostar/utils/workspace/__init__.py +0 -0
- octostar/utils/workspace/delete_entities.py +247 -0
- octostar/utils/workspace/delete_entity.py +81 -0
- octostar/utils/workspace/delete_relationship.py +78 -0
- octostar/utils/workspace/delete_relationships.py +85 -0
- octostar/utils/workspace/delete_temporary_blob.py +85 -0
- octostar/utils/workspace/extract_entities.py +140 -0
- octostar/utils/workspace/get_filepath_from_item.py +85 -0
- octostar/utils/workspace/get_filepaths_from_items.py +100 -0
- octostar/utils/workspace/get_files_tree.py +102 -0
- octostar/utils/workspace/get_item_from_filepath.py +102 -0
- octostar/utils/workspace/get_items_from_filepaths.py +108 -0
- octostar/utils/workspace/linkcharts/__init__.py +0 -0
- octostar/utils/workspace/linkcharts/create_linkchart.py +241 -0
- octostar/utils/workspace/permissions/PermissionLevel.py +8 -0
- octostar/utils/workspace/permissions/__init__.py +1 -0
- octostar/utils/workspace/permissions/get_permissions.py +81 -0
- octostar/utils/workspace/read_attachment.py +284 -0
- octostar/utils/workspace/read_file.py +113 -0
- octostar/utils/workspace/read_temporary_blob.py +428 -0
- octostar/utils/workspace/saved_searches/__init__.py +0 -0
- octostar/utils/workspace/saved_searches/create_saved_search.py +183 -0
- octostar/utils/workspace/tags/__init__.py +0 -0
- octostar/utils/workspace/tags/delete_tag_from_entities.py +96 -0
- octostar/utils/workspace/tags/tag_entities.py +175 -0
- octostar/utils/workspace/upsert_entities.py +268 -0
- octostar/utils/workspace/upsert_entity.py +110 -0
- octostar/utils/workspace/upsert_relationship.py +128 -0
- octostar/utils/workspace/upsert_relationships.py +194 -0
- octostar/utils/workspace/write_attachment.py +263 -0
- octostar/utils/workspace/write_file.py +335 -0
- octostar/utils/workspace/write_temporary_blob.py +218 -0
- octostar_python_client-0.1.759.dist-info/METADATA +159 -0
- octostar_python_client-0.1.759.dist-info/RECORD +257 -0
- octostar_python_client-0.1.759.dist-info/WHEEL +5 -0
- octostar_python_client-0.1.759.dist-info/licenses/LICENSE +21 -0
- octostar_python_client-0.1.759.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
import asyncio as _asyncio
|
|
2
|
+
import httpx
|
|
3
|
+
from collections.abc import AsyncIterator, Callable
|
|
4
|
+
from typing import Optional, List, Any, Literal, Union, Dict, TypedDict
|
|
5
|
+
from pydantic import BaseModel, Field, ValidationError
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
from enum import Enum
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from ...client import Client, get_default_client
|
|
12
|
+
from ..exceptions import ApiConnectionError, StopAsyncIterationWithResult
|
|
13
|
+
from ..commons import network_retry_strategy, TimeoutAsyncGenerator
|
|
14
|
+
|
|
15
|
+
_logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class EntityBase(BaseModel):
|
|
19
|
+
class Config:
|
|
20
|
+
extra = "allow"
|
|
21
|
+
|
|
22
|
+
entity_type: str = "os_workspace"
|
|
23
|
+
entity_id: str
|
|
24
|
+
entity_label: Optional[str] = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SearchSetModel(BaseModel):
|
|
28
|
+
entity_id: str
|
|
29
|
+
entity_label: str
|
|
30
|
+
query: dict
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class ChatMessagePriority(Enum):
|
|
34
|
+
CRITICAL = 0
|
|
35
|
+
CONTEXTUAL = 1
|
|
36
|
+
HISTORICAL = 2
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
ContextMode = Literal["limited_to_context", "context_boosted"]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class ToolName(TypedDict):
|
|
43
|
+
source: str
|
|
44
|
+
name: str
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ExecutionMode(str, Enum):
|
|
48
|
+
"""The execution mode for a chat request."""
|
|
49
|
+
|
|
50
|
+
COMPLETION = "completion"
|
|
51
|
+
"""Pure pass-through: no system prompt or processing, just forwards messages to the LLM."""
|
|
52
|
+
|
|
53
|
+
SIMPLE = "simple"
|
|
54
|
+
"""Basic chat with a system prompt, but no RAG retrieval or tool usage."""
|
|
55
|
+
|
|
56
|
+
AGENTIC = "agentic"
|
|
57
|
+
"""Full agent: formulates a plan, retrieves context via RAG, and invokes tools as needed."""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class ChatMessage(BaseModel):
|
|
61
|
+
"""
|
|
62
|
+
Represents a single chat message in the conversation. Class is taken from octostar-api lib.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
id: str = Field(..., description="The unique ID of the message.")
|
|
66
|
+
role: str = Field(
|
|
67
|
+
...,
|
|
68
|
+
description="The role of the message sender. Must be 'user', 'assistant', or 'system'.",
|
|
69
|
+
)
|
|
70
|
+
content: Union[List[EntityBase], SearchSetModel, str, Dict[str, Any]] = Field(
|
|
71
|
+
..., description="The content of the message."
|
|
72
|
+
)
|
|
73
|
+
type: Optional[
|
|
74
|
+
Literal[
|
|
75
|
+
"text",
|
|
76
|
+
"json",
|
|
77
|
+
"add_entities",
|
|
78
|
+
"remove_entities",
|
|
79
|
+
"add_search_set",
|
|
80
|
+
"remove_search_set",
|
|
81
|
+
]
|
|
82
|
+
] = Field(
|
|
83
|
+
None,
|
|
84
|
+
description=(
|
|
85
|
+
"The type of the message. Can be 'text', 'json', 'add_entities', 'remove_entities', 'add_search_set' or 'remove_search_set."
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
timestamp: Optional[datetime] = Field(
|
|
89
|
+
None, description="The timestamp of the message in ISO 8601 format."
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class ChatStreamEvent(TypedDict, total=False):
|
|
94
|
+
"""A single event from the streaming chat endpoint."""
|
|
95
|
+
|
|
96
|
+
channel: str
|
|
97
|
+
"""The event channel: 'text', 'agentic', 'context', 'final_prompt', 'heartbeat', 'error', or 'status'."""
|
|
98
|
+
|
|
99
|
+
content: Any
|
|
100
|
+
"""The event payload. For 'text' events this is the accumulated response text so far."""
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _build_request(
|
|
104
|
+
prompt: str,
|
|
105
|
+
*,
|
|
106
|
+
chat_history: Optional[list[ChatMessage]],
|
|
107
|
+
workspaces: Optional[list[EntityBase]],
|
|
108
|
+
context_mode: str,
|
|
109
|
+
model_name: Optional[str],
|
|
110
|
+
execution_mode: ExecutionMode,
|
|
111
|
+
disabled_tools: Optional[list[ToolName]],
|
|
112
|
+
streaming: bool,
|
|
113
|
+
client: Client,
|
|
114
|
+
extra_body: Optional[dict] = None,
|
|
115
|
+
) -> tuple:
|
|
116
|
+
"""Build the endpoint URL, headers, and JSON body for the chat API.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
(endpoint_url, headers, body)
|
|
120
|
+
"""
|
|
121
|
+
endpoint_url = f"{client.get_base_url_v1()}/api/v1/chat"
|
|
122
|
+
headers = {
|
|
123
|
+
"Content-Type": "application/json",
|
|
124
|
+
# ``.token`` lives on AuthenticatedClient (the runtime type); the
|
|
125
|
+
# param is annotated with the Client base for call-site flexibility.
|
|
126
|
+
"Authorization": f"Bearer {client.token}", # pyright: ignore[reportAttributeAccessIssue]
|
|
127
|
+
"x-ontology": client.ontology,
|
|
128
|
+
}
|
|
129
|
+
ws_list = workspaces or []
|
|
130
|
+
ws_dicts = [ws.model_dump() for ws in ws_list]
|
|
131
|
+
for ws in ws_dicts:
|
|
132
|
+
if "os_workspace" not in ws:
|
|
133
|
+
ws["os_workspace"] = ws["entity_id"]
|
|
134
|
+
hist = chat_history or []
|
|
135
|
+
hist_dicts = [ch.model_dump() for ch in hist]
|
|
136
|
+
hist_dicts = [
|
|
137
|
+
{
|
|
138
|
+
**m,
|
|
139
|
+
"timestamp": (
|
|
140
|
+
m.get("timestamp", "").strftime("%Y-%m-%d %H:%M:%S")
|
|
141
|
+
if isinstance(m.get("timestamp"), datetime)
|
|
142
|
+
else None
|
|
143
|
+
),
|
|
144
|
+
}
|
|
145
|
+
for m in hist_dicts
|
|
146
|
+
]
|
|
147
|
+
body = {
|
|
148
|
+
**(extra_body or {}),
|
|
149
|
+
"model_name": model_name,
|
|
150
|
+
"messages": hist_dicts,
|
|
151
|
+
"prompt": prompt,
|
|
152
|
+
"streaming": streaming,
|
|
153
|
+
"execution_mode": execution_mode,
|
|
154
|
+
"context_mode": context_mode,
|
|
155
|
+
"api_key": "",
|
|
156
|
+
"cohere_key": "",
|
|
157
|
+
"open_workspaces": ws_dicts,
|
|
158
|
+
"disabled_tools": disabled_tools or [],
|
|
159
|
+
"deployment_url": client.get_base_url_v1(),
|
|
160
|
+
**(
|
|
161
|
+
{} if "prompt_overrides" in (extra_body or {}) else {"prompt_overrides": {}}
|
|
162
|
+
),
|
|
163
|
+
}
|
|
164
|
+
return endpoint_url, headers, body
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _parse_response(message, response_validation):
|
|
168
|
+
if response_validation == "json" or (
|
|
169
|
+
isinstance(response_validation, type)
|
|
170
|
+
and issubclass(response_validation, BaseModel)
|
|
171
|
+
):
|
|
172
|
+
message = message.strip()
|
|
173
|
+
if message.startswith("```json"):
|
|
174
|
+
message = message[7:]
|
|
175
|
+
if message.startswith("```"):
|
|
176
|
+
message = message[3:]
|
|
177
|
+
if message.endswith("```"):
|
|
178
|
+
message = message[:-3]
|
|
179
|
+
try:
|
|
180
|
+
message = json.loads(message)
|
|
181
|
+
except json.JSONDecodeError as e:
|
|
182
|
+
raise ValueError(f"Response is not valid JSON: {e}\nContent: {message}")
|
|
183
|
+
if response_validation == "json":
|
|
184
|
+
return message
|
|
185
|
+
elif isinstance(response_validation, type) and issubclass(
|
|
186
|
+
response_validation, BaseModel
|
|
187
|
+
):
|
|
188
|
+
try:
|
|
189
|
+
return response_validation.model_validate(message)
|
|
190
|
+
except ValidationError as e:
|
|
191
|
+
raise ValueError(
|
|
192
|
+
f"Response does not match schema {response_validation.__name__}: {e}\nContent: {message}"
|
|
193
|
+
)
|
|
194
|
+
else:
|
|
195
|
+
return message
|
|
196
|
+
else:
|
|
197
|
+
return message
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def sync(
|
|
201
|
+
prompt: str,
|
|
202
|
+
chat_history: Optional[list[ChatMessage]] = None,
|
|
203
|
+
workspaces: Optional[list[EntityBase]] = None,
|
|
204
|
+
context_mode: Literal["limited_to_context", "context_boosted"] = "context_boosted",
|
|
205
|
+
model_name: Optional[str] = None,
|
|
206
|
+
timeout: Optional[float] = 300.0,
|
|
207
|
+
retries: int = 2,
|
|
208
|
+
disabled_tools: Optional[list[ToolName]] = None,
|
|
209
|
+
execution_mode: ExecutionMode = ExecutionMode.COMPLETION,
|
|
210
|
+
response_validation: Union[None, Literal["json"], type[BaseModel]] = None,
|
|
211
|
+
client: Optional[Client] = None,
|
|
212
|
+
**kwargs,
|
|
213
|
+
) -> Union[str, dict, list, BaseModel]:
|
|
214
|
+
"""
|
|
215
|
+
# Make a request for the AI chat endpoint.
|
|
216
|
+
|
|
217
|
+
## Arguments
|
|
218
|
+
- `prompt`: The user prompt to send to the chatbot.
|
|
219
|
+
- `chat_history`: The list of messages that precede the user prompt.
|
|
220
|
+
- `workspaces`: The list of workspaces the chatbot is able to see.
|
|
221
|
+
- `context_mode`: The filtering mode for entities retrieved by the chatbot using RAG. Can be set to:
|
|
222
|
+
* 'context_boosted': The context provided in the chat history is boosted in the RAG results,
|
|
223
|
+
but results from the whole knowledge base can be retrieved;
|
|
224
|
+
* 'limited_to_context': Only context provided in the chat history can be retrieved and used via RAG.
|
|
225
|
+
- `timeout`: The timeout for the connection to the search engine. Can be set to "None" for no enforced timeout.
|
|
226
|
+
- `retries`: The number of connection retries. Note that each retry may cost additional tokens.
|
|
227
|
+
- `disabled_tools`: A list of tools that the LLM is banned from using for this invocation.
|
|
228
|
+
- `execution_mode`: The mode with which the LLM will answer. Defaults to
|
|
229
|
+
'completion'. Only 'completion' is supported — 'simple' and 'agentic'
|
|
230
|
+
are deprecated and rejected by the backend with HTTP 400:
|
|
231
|
+
* 'completion': Pure pass-through — no system prompt or processing, just forwards messages to the LLM;
|
|
232
|
+
- `response_validation`: Whether the response should follow a given pattern. Possible values are:
|
|
233
|
+
* None: No validation on the response;
|
|
234
|
+
* 'json': Response is validated to be a JSON;
|
|
235
|
+
* type[BaseModel]: Response is validated against the given pydantic model class;
|
|
236
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
237
|
+
- `**kwargs`: Additional keyword arguments are merged into the request body.
|
|
238
|
+
Explicit parameters above take precedence over kwargs.
|
|
239
|
+
|
|
240
|
+
## Returns
|
|
241
|
+
The chatbot response, as plain text.
|
|
242
|
+
|
|
243
|
+
## Raises
|
|
244
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
245
|
+
"""
|
|
246
|
+
if not client:
|
|
247
|
+
client = get_default_client()
|
|
248
|
+
endpoint_url, headers, body = _build_request(
|
|
249
|
+
prompt,
|
|
250
|
+
chat_history=chat_history,
|
|
251
|
+
workspaces=workspaces,
|
|
252
|
+
context_mode=context_mode,
|
|
253
|
+
model_name=model_name,
|
|
254
|
+
execution_mode=execution_mode,
|
|
255
|
+
disabled_tools=disabled_tools,
|
|
256
|
+
streaming=False,
|
|
257
|
+
client=client,
|
|
258
|
+
extra_body=kwargs,
|
|
259
|
+
)
|
|
260
|
+
response = None
|
|
261
|
+
try:
|
|
262
|
+
for attempt in network_retry_strategy(retries=retries):
|
|
263
|
+
with attempt:
|
|
264
|
+
with httpx.Client() as httpx_client:
|
|
265
|
+
response = httpx_client.post(
|
|
266
|
+
endpoint_url, json=body, headers=headers, timeout=timeout
|
|
267
|
+
)
|
|
268
|
+
response.raise_for_status()
|
|
269
|
+
try:
|
|
270
|
+
chatbot_response = response.json()["response"]["content"]
|
|
271
|
+
except Exception as e:
|
|
272
|
+
raise ConnectionError(
|
|
273
|
+
f"Unparsable response format {response.content} with exception {e}"
|
|
274
|
+
)
|
|
275
|
+
try:
|
|
276
|
+
chatbot_response = _parse_response(
|
|
277
|
+
chatbot_response, response_validation
|
|
278
|
+
)
|
|
279
|
+
except Exception as e:
|
|
280
|
+
raise ConnectionError(
|
|
281
|
+
f"Validation failed for {chatbot_response} with exception {e}"
|
|
282
|
+
)
|
|
283
|
+
except Exception:
|
|
284
|
+
raise ApiConnectionError("chat", response, client)
|
|
285
|
+
return chatbot_response
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
async def asyncio(
|
|
289
|
+
prompt: str,
|
|
290
|
+
chat_history: Optional[list[ChatMessage]] = None,
|
|
291
|
+
workspaces: Optional[list[EntityBase]] = None,
|
|
292
|
+
context_mode: Literal["limited_to_context", "context_boosted"] = "context_boosted",
|
|
293
|
+
model_name: Optional[str] = None,
|
|
294
|
+
timeout: Optional[float] = 300.0,
|
|
295
|
+
retries: int = 2,
|
|
296
|
+
disabled_tools: Optional[list[ToolName]] = None,
|
|
297
|
+
execution_mode: ExecutionMode = ExecutionMode.COMPLETION,
|
|
298
|
+
response_validation: Union[None, Literal["json"], type[BaseModel]] = None,
|
|
299
|
+
client: Optional[Client] = None,
|
|
300
|
+
**kwargs,
|
|
301
|
+
) -> Union[str, dict, list, BaseModel]:
|
|
302
|
+
"""
|
|
303
|
+
# Make asynchronously a request for the AI chat endpoint.
|
|
304
|
+
|
|
305
|
+
## Arguments
|
|
306
|
+
- `prompt`: The user prompt to send to the chatbot.
|
|
307
|
+
- `chat_history`: The list of messages that precede the user prompt.
|
|
308
|
+
- `workspaces`: The list of workspaces the chatbot is able to see.
|
|
309
|
+
- `context_mode`: The filtering mode for entities retrieved by the chatbot using RAG. Can be set to:
|
|
310
|
+
* 'context_boosted': The context provided in the chat history is boosted in the RAG results,
|
|
311
|
+
but results from the whole knowledge base can be retrieved;
|
|
312
|
+
* 'limited_to_context': Only context provided in the chat history can be retrieved and used via RAG.
|
|
313
|
+
- `timeout`: The timeout for the connection to the search engine. Can be set to "None" for no enforced timeout.
|
|
314
|
+
- `retries`: The number of connection retries. Note that each retry may cost additional tokens.
|
|
315
|
+
- `disabled_tools`: A list of tools that the LLM is banned from using for this invocation.
|
|
316
|
+
- `execution_mode`: The mode with which the LLM will answer. Defaults to
|
|
317
|
+
'completion'. Only 'completion' is supported — 'simple' and 'agentic'
|
|
318
|
+
are deprecated and rejected by the backend with HTTP 400:
|
|
319
|
+
* 'completion': Pure pass-through — no system prompt or processing, just forwards messages to the LLM;
|
|
320
|
+
- `response_validation`: Whether the response should follow a given pattern. Possible values are:
|
|
321
|
+
* None: No validation on the response, response is in plain text;
|
|
322
|
+
* 'json': Response is validated to be a JSON, and returned as a dict;
|
|
323
|
+
* type[BaseModel]: Response is validated against the given pydantic model class, and returned as an instance of that class;
|
|
324
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
325
|
+
- `**kwargs`: Additional keyword arguments are merged into the request body.
|
|
326
|
+
Explicit parameters above take precedence over kwargs.
|
|
327
|
+
|
|
328
|
+
## Returns
|
|
329
|
+
The chatbot response, parsed or as plain text.
|
|
330
|
+
|
|
331
|
+
## Raises
|
|
332
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
333
|
+
"""
|
|
334
|
+
if not client:
|
|
335
|
+
client = get_default_client()
|
|
336
|
+
endpoint_url, headers, body = _build_request(
|
|
337
|
+
prompt,
|
|
338
|
+
chat_history=chat_history,
|
|
339
|
+
workspaces=workspaces,
|
|
340
|
+
context_mode=context_mode,
|
|
341
|
+
model_name=model_name,
|
|
342
|
+
execution_mode=execution_mode,
|
|
343
|
+
disabled_tools=disabled_tools,
|
|
344
|
+
streaming=False,
|
|
345
|
+
client=client,
|
|
346
|
+
extra_body=kwargs,
|
|
347
|
+
)
|
|
348
|
+
response = None
|
|
349
|
+
try:
|
|
350
|
+
for attempt in network_retry_strategy(retries=retries):
|
|
351
|
+
with attempt:
|
|
352
|
+
async with httpx.AsyncClient() as httpx_client:
|
|
353
|
+
response = await httpx_client.post(
|
|
354
|
+
endpoint_url, json=body, headers=headers, timeout=timeout
|
|
355
|
+
)
|
|
356
|
+
response.raise_for_status()
|
|
357
|
+
try:
|
|
358
|
+
chatbot_response = response.json()["response"]["content"]
|
|
359
|
+
except Exception as e:
|
|
360
|
+
raise ConnectionError(
|
|
361
|
+
f"Unparsable response format {response.content} with exception {e}"
|
|
362
|
+
)
|
|
363
|
+
try:
|
|
364
|
+
chatbot_response = _parse_response(
|
|
365
|
+
chatbot_response, response_validation
|
|
366
|
+
)
|
|
367
|
+
except Exception as e:
|
|
368
|
+
raise ConnectionError(
|
|
369
|
+
f"Validation failed for {chatbot_response} with exception {e}"
|
|
370
|
+
)
|
|
371
|
+
except Exception:
|
|
372
|
+
raise ApiConnectionError("chat", response, client)
|
|
373
|
+
return chatbot_response
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
async def streaming(
|
|
377
|
+
prompt: str,
|
|
378
|
+
chat_history: Optional[list[ChatMessage]] = None,
|
|
379
|
+
workspaces: Optional[list[EntityBase]] = None,
|
|
380
|
+
context_mode: Literal["limited_to_context", "context_boosted"] = "context_boosted",
|
|
381
|
+
model_name: Optional[str] = None,
|
|
382
|
+
timeout: Optional[float] = 300.0,
|
|
383
|
+
disabled_tools: Optional[list[ToolName]] = None,
|
|
384
|
+
execution_mode: ExecutionMode = ExecutionMode.COMPLETION,
|
|
385
|
+
fail_condition: Optional[Callable[[List[ChatStreamEvent]], bool]] = None,
|
|
386
|
+
end_condition: Optional[Callable[[List[ChatStreamEvent]], bool]] = None,
|
|
387
|
+
client: Optional[Client] = None,
|
|
388
|
+
**kwargs,
|
|
389
|
+
) -> AsyncIterator[Union[ChatStreamEvent, str]]:
|
|
390
|
+
"""
|
|
391
|
+
# Stream a request to the AI chat endpoint.
|
|
392
|
+
|
|
393
|
+
Opens a streaming HTTP connection and yields parsed events as they arrive.
|
|
394
|
+
Each event is a `ChatStreamEvent` dict with a `channel` key indicating the
|
|
395
|
+
event type and a `content` key with the payload.
|
|
396
|
+
|
|
397
|
+
Catch `StopAsyncIterationWithResult` to get the final accumulated text
|
|
398
|
+
response after the stream ends::
|
|
399
|
+
|
|
400
|
+
try:
|
|
401
|
+
async for event in chat.streaming(prompt="Hello"):
|
|
402
|
+
print(event) # process events in real-time
|
|
403
|
+
except StopAsyncIterationWithResult as r:
|
|
404
|
+
final_text = r.value # the full response text
|
|
405
|
+
|
|
406
|
+
## Arguments
|
|
407
|
+
- `prompt`: The user prompt to send to the chatbot.
|
|
408
|
+
- `chat_history`: The list of messages that precede the user prompt.
|
|
409
|
+
- `workspaces`: The list of workspaces the chatbot is able to see.
|
|
410
|
+
- `context_mode`: The filtering mode for entities retrieved by the chatbot using RAG. Can be set to:
|
|
411
|
+
* 'context_boosted': The context provided in the chat history is boosted in the RAG results,
|
|
412
|
+
but results from the whole knowledge base can be retrieved;
|
|
413
|
+
* 'limited_to_context': Only context provided in the chat history can be retrieved and used via RAG.
|
|
414
|
+
- `timeout`: The timeout for the connection to the search engine. Can be set to "None" for no enforced timeout.
|
|
415
|
+
- `disabled_tools`: A list of tools that the LLM is banned from using for this invocation.
|
|
416
|
+
- `execution_mode`: The mode with which the LLM will answer. Defaults to
|
|
417
|
+
'completion'. Only 'completion' is supported — 'simple' and 'agentic'
|
|
418
|
+
are deprecated and rejected by the backend with HTTP 400:
|
|
419
|
+
* 'completion': Pure pass-through — no system prompt or processing, just forwards messages to the LLM;
|
|
420
|
+
- `fail_condition`: Custom condition to determine when the stream should be considered
|
|
421
|
+
failed. Receives the list of ChatStreamEvent dicts collected so far and returns
|
|
422
|
+
True to trigger an ApiConnectionError. If None, defaults to failing on events
|
|
423
|
+
with channel ``'error'``.
|
|
424
|
+
- `end_condition`: Custom condition to determine when the stream should stop early.
|
|
425
|
+
Receives the list of ChatStreamEvent dicts collected so far and returns True to
|
|
426
|
+
end the stream. If None, defaults to streaming until completion (or timeout).
|
|
427
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
428
|
+
- `**kwargs`: Additional keyword arguments are merged into the request body.
|
|
429
|
+
Explicit parameters above take precedence over kwargs.
|
|
430
|
+
|
|
431
|
+
## Yields
|
|
432
|
+
`ChatStreamEvent` dicts. Common channels:
|
|
433
|
+
- `'text'`: Accumulated generated text so far.
|
|
434
|
+
- `'agentic'`: Tool-call or agent status updates.
|
|
435
|
+
- `'context'`: RAG context entities retrieved.
|
|
436
|
+
- `'final_prompt'`: The full prompt sent to the LLM.
|
|
437
|
+
- `'heartbeat'`: Keep-alive pings (can be ignored).
|
|
438
|
+
- `'error'`: Error messages from the server.
|
|
439
|
+
|
|
440
|
+
## Raises
|
|
441
|
+
- `StopAsyncIterationWithResult`: When the stream ends normally. `value` holds
|
|
442
|
+
the final accumulated text response (``str``).
|
|
443
|
+
- `ApiConnectionError`: If the connection or initial response failed, or the
|
|
444
|
+
fail_condition returned True.
|
|
445
|
+
"""
|
|
446
|
+
if fail_condition is None:
|
|
447
|
+
fail_condition = lambda events: any(e.get("channel") == "error" for e in events)
|
|
448
|
+
if end_condition is None:
|
|
449
|
+
end_condition = lambda _events: False
|
|
450
|
+
|
|
451
|
+
if not client:
|
|
452
|
+
client = get_default_client()
|
|
453
|
+
endpoint_url, headers, body = _build_request(
|
|
454
|
+
prompt,
|
|
455
|
+
chat_history=chat_history,
|
|
456
|
+
workspaces=workspaces,
|
|
457
|
+
context_mode=context_mode,
|
|
458
|
+
model_name=model_name,
|
|
459
|
+
execution_mode=execution_mode,
|
|
460
|
+
disabled_tools=disabled_tools,
|
|
461
|
+
streaming=True,
|
|
462
|
+
client=client,
|
|
463
|
+
extra_body=kwargs,
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
async def _parse_lines(resp: httpx.Response) -> AsyncIterator[ChatStreamEvent]:
|
|
467
|
+
async for line in resp.aiter_lines():
|
|
468
|
+
if not line.strip():
|
|
469
|
+
continue
|
|
470
|
+
try:
|
|
471
|
+
yield json.loads(line)
|
|
472
|
+
except json.JSONDecodeError:
|
|
473
|
+
_logger.warning("chat streaming: unparsable line: %s", line[:200])
|
|
474
|
+
|
|
475
|
+
collected_events: List[ChatStreamEvent] = []
|
|
476
|
+
accumulated_text = ""
|
|
477
|
+
try:
|
|
478
|
+
async with httpx.AsyncClient() as httpx_client:
|
|
479
|
+
async with httpx_client.stream(
|
|
480
|
+
"POST", endpoint_url, json=body, headers=headers, timeout=timeout
|
|
481
|
+
) as response:
|
|
482
|
+
if response.status_code != 200:
|
|
483
|
+
await response.aread()
|
|
484
|
+
raise ConnectionError(
|
|
485
|
+
f"chat streaming: HTTP {response.status_code}: {response.text[:500]}"
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
event_stream = _parse_lines(response)
|
|
489
|
+
if timeout is not None:
|
|
490
|
+
event_stream = TimeoutAsyncGenerator(event_stream, timeout)
|
|
491
|
+
|
|
492
|
+
try:
|
|
493
|
+
async for event in event_stream:
|
|
494
|
+
collected_events.append(event)
|
|
495
|
+
|
|
496
|
+
if event.get("channel") == "text":
|
|
497
|
+
accumulated_text += event.get("content", "")
|
|
498
|
+
|
|
499
|
+
if fail_condition(collected_events):
|
|
500
|
+
raise ConnectionError(
|
|
501
|
+
"chat streaming: fail_condition triggered"
|
|
502
|
+
)
|
|
503
|
+
if end_condition(collected_events):
|
|
504
|
+
break
|
|
505
|
+
|
|
506
|
+
yield event
|
|
507
|
+
except _asyncio.TimeoutError:
|
|
508
|
+
_logger.warning(
|
|
509
|
+
"chat streaming: timed out after %s seconds", timeout
|
|
510
|
+
)
|
|
511
|
+
except (ConnectionError, httpx.HTTPStatusError) as e:
|
|
512
|
+
raise ApiConnectionError("chat streaming", None, client) from e
|
|
513
|
+
raise StopAsyncIterationWithResult(value=accumulated_text)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from ...client import Client, get_default_client
|
|
4
|
+
from ..exceptions import ApiConnectionError
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from ..commons import network_retry_strategy
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _prepare_detokenize_request(client, tokens, model_name):
|
|
10
|
+
endpoint_url = f"{client.get_base_url_v1()}/api/v2/ai/llm/detokenize"
|
|
11
|
+
headers = {
|
|
12
|
+
"Authorization": f"Bearer {client.token}",
|
|
13
|
+
"x-ontology": client.ontology,
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
"url": endpoint_url,
|
|
17
|
+
"headers": headers,
|
|
18
|
+
"timeout": 60,
|
|
19
|
+
"json": {
|
|
20
|
+
"tokens": tokens,
|
|
21
|
+
"model_name": model_name,
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def sync(
|
|
27
|
+
tokens: list[int],
|
|
28
|
+
model_name: str,
|
|
29
|
+
client: Optional[Client] = None,
|
|
30
|
+
) -> str:
|
|
31
|
+
"""
|
|
32
|
+
# Detokenize a list of LLM tokens into a string.
|
|
33
|
+
|
|
34
|
+
## Arguments
|
|
35
|
+
- `tokens`: The input list of tokens.
|
|
36
|
+
- `model_name`: The model with which to detokenize the input text.
|
|
37
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
38
|
+
|
|
39
|
+
## Returns
|
|
40
|
+
The detokenized string.
|
|
41
|
+
|
|
42
|
+
## Raises
|
|
43
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
44
|
+
"""
|
|
45
|
+
if not client:
|
|
46
|
+
client = get_default_client()
|
|
47
|
+
response = None
|
|
48
|
+
try:
|
|
49
|
+
for attempt in network_retry_strategy(retries=3):
|
|
50
|
+
with attempt:
|
|
51
|
+
with httpx.Client() as httpx_client:
|
|
52
|
+
response = httpx_client.post(
|
|
53
|
+
**_prepare_detokenize_request(client, tokens, model_name)
|
|
54
|
+
)
|
|
55
|
+
response.raise_for_status()
|
|
56
|
+
try:
|
|
57
|
+
response = response.json()["text"]
|
|
58
|
+
except Exception as e:
|
|
59
|
+
raise ConnectionError(
|
|
60
|
+
f"Unparsable response format {response.content} with exception {e}"
|
|
61
|
+
)
|
|
62
|
+
except Exception:
|
|
63
|
+
raise ApiConnectionError("detokenize", response, client)
|
|
64
|
+
return response # pyright: ignore[reportReturnType]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
async def asyncio(
|
|
68
|
+
tokens: list[int],
|
|
69
|
+
model_name: str,
|
|
70
|
+
client: Optional[Client] = None,
|
|
71
|
+
) -> str:
|
|
72
|
+
"""
|
|
73
|
+
# Detokenize a list of LLM tokens into a string.
|
|
74
|
+
|
|
75
|
+
## Arguments
|
|
76
|
+
- `tokens`: The input list of tokens.
|
|
77
|
+
- `model_name`: The model with which to detokenize the input text.
|
|
78
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
79
|
+
|
|
80
|
+
## Returns
|
|
81
|
+
The detokenized string.
|
|
82
|
+
|
|
83
|
+
## Raises
|
|
84
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
85
|
+
"""
|
|
86
|
+
if not client:
|
|
87
|
+
client = get_default_client()
|
|
88
|
+
response = None
|
|
89
|
+
try:
|
|
90
|
+
for attempt in network_retry_strategy(retries=3):
|
|
91
|
+
with attempt:
|
|
92
|
+
async with httpx.AsyncClient() as httpx_client:
|
|
93
|
+
response = await httpx_client.post(
|
|
94
|
+
**_prepare_detokenize_request(client, tokens, model_name)
|
|
95
|
+
)
|
|
96
|
+
response.raise_for_status()
|
|
97
|
+
try:
|
|
98
|
+
response = response.json()["text"]
|
|
99
|
+
except Exception as e:
|
|
100
|
+
raise ConnectionError(
|
|
101
|
+
f"Unparsable response format {response.content} with exception {e}"
|
|
102
|
+
)
|
|
103
|
+
except Exception:
|
|
104
|
+
raise ApiConnectionError("detokenize", response, client)
|
|
105
|
+
return response # pyright: ignore[reportReturnType]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from ...client import Client
|
|
3
|
+
from . import list_models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _get_default_model_from_list(models):
|
|
7
|
+
default_model = list(filter(lambda x: x.get("is_default") == True, models))
|
|
8
|
+
if len(default_model) != 1:
|
|
9
|
+
raise ValueError(f"Found {len(default_model)} default models instead of 1")
|
|
10
|
+
return default_model[0]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def sync(
|
|
14
|
+
client: Optional[Client] = None,
|
|
15
|
+
) -> dict:
|
|
16
|
+
"""
|
|
17
|
+
# Get the current default AI chat model.
|
|
18
|
+
|
|
19
|
+
## Arguments
|
|
20
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
21
|
+
|
|
22
|
+
## Returns
|
|
23
|
+
The information about the default AI model.
|
|
24
|
+
|
|
25
|
+
## Raises
|
|
26
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
27
|
+
- `ValueError`: If no default model is available.
|
|
28
|
+
"""
|
|
29
|
+
models = list_models.sync(client=client)
|
|
30
|
+
return _get_default_model_from_list(models)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def asyncio(
|
|
34
|
+
client: Optional[Client] = None,
|
|
35
|
+
) -> dict:
|
|
36
|
+
"""
|
|
37
|
+
# Get asynchronously the current default AI chat model.
|
|
38
|
+
|
|
39
|
+
## Arguments
|
|
40
|
+
- `client`: The Client with which to connect to Octostar. If None, the default one is used.
|
|
41
|
+
|
|
42
|
+
## Returns
|
|
43
|
+
The information about the default AI model.
|
|
44
|
+
|
|
45
|
+
## Raises
|
|
46
|
+
- `ApiConnectionError`: If the query was unsuccessful.
|
|
47
|
+
- `ValueError`: If no default model is available.
|
|
48
|
+
"""
|
|
49
|
+
models = await list_models.asyncio(client=client)
|
|
50
|
+
return _get_default_model_from_list(models)
|