From 1e97ef1cb4ab2c7dacf45de52aae0aed5ae74459 Mon Sep 17 00:00:00 2001 From: Vladimir Lipkin Date: Fri, 8 Nov 2024 19:46:09 +0100 Subject: [PATCH] Fix problem with zeros at assistant options (#26) --- .../_assistants/assistant.py | 32 +- src/yandex_cloud_ml_sdk/_assistants/domain.py | 15 +- src/yandex_cloud_ml_sdk/_assistants/utils.py | 14 +- src/yandex_cloud_ml_sdk/_types/resource.py | 2 +- .../test_assistant_zeros.gprc.json | 631 ++++++++++++++++++ tests/assistants/test_assistants.py | 33 +- 6 files changed, 693 insertions(+), 34 deletions(-) create mode 100644 tests/assistants/cassettes/test_assistants/test_assistant_zeros.gprc.json diff --git a/src/yandex_cloud_ml_sdk/_assistants/assistant.py b/src/yandex_cloud_ml_sdk/_assistants/assistant.py index d1623e7..4a8dc51 100644 --- a/src/yandex_cloud_ml_sdk/_assistants/assistant.py +++ b/src/yandex_cloud_ml_sdk/_assistants/assistant.py @@ -41,10 +41,11 @@ def _kwargs_from_message(cls, proto: ProtoAssistant, sdk: BaseSDK) -> dict[str, kwargs = super()._kwargs_from_message(proto, sdk=sdk) model = sdk.models.completions(proto.model_uri) - if max_tokens := proto.completion_options.max_tokens.value: - model = model.configure(max_tokens=max_tokens) - if temperature := proto.completion_options.temperature.value: - model = model.configure(temperature=temperature) + completion_options = proto.completion_options + if completion_options.HasField('max_tokens'): + model = model.configure(max_tokens=completion_options.max_tokens.value) + if completion_options.HasField('temperature'): + model = model.configure(temperature=completion_options.temperature.value) kwargs['model'] = model kwargs['tools'] = tuple( @@ -80,23 +81,20 @@ async def _update( expiration_policy=expiration_policy ) - model_uri: str | None = None - model_temperature: float | None = self.model.config.temperature - model_max_tokens: int | None = self.model.config.max_tokens + model_uri: UndefinedOr[str] | None = UNDEFINED if is_defined(model): if isinstance(model, str): model_uri = self._sdk.models.completions(model).uri elif isinstance(model, BaseGPTModel): model_uri = model.uri - model_temperature = model.config.temperature - model_max_tokens = model.config.max_tokens + if not is_defined(temperature) and model.config.temperature is not None: + temperature = model.config.temperature + if not is_defined(max_tokens) and model.config.max_tokens is not None: + max_tokens = model.config.max_tokens else: raise TypeError('model argument must be str, GPTModel object either undefined') - model_temperature = get_defined_value(temperature, model_temperature) - model_max_tokens = get_defined_value(max_tokens, model_max_tokens) - request = UpdateAssistantRequest( assistant_id=self.id, name=get_defined_value(name, ''), @@ -108,11 +106,11 @@ async def _update( max_prompt_tokens=get_defined_value(max_prompt_tokens, None) ), completion_options=get_completion_options( - temperature=model_temperature, - max_tokens=model_max_tokens + temperature=temperature, + max_tokens=max_tokens, ) ) - if model_uri: + if model_uri and is_defined(model_uri): request.model_uri = model_uri self._fill_update_mask( @@ -125,8 +123,8 @@ async def _update( 'expiration_config.expiration_policy': expiration_policy, 'instruction': instruction, 'model_uri': model_uri, - 'completion_options.temperature': model_temperature, - 'completion_options.max_tokens': model_max_tokens, + 'completion_options.temperature': temperature, + 'completion_options.max_tokens': max_tokens, 'prompt_truncation_options.max_prompt_tokens': max_prompt_tokens, } ) diff --git a/src/yandex_cloud_ml_sdk/_assistants/domain.py b/src/yandex_cloud_ml_sdk/_assistants/domain.py index bbc692a..24148e4 100644 --- a/src/yandex_cloud_ml_sdk/_assistants/domain.py +++ b/src/yandex_cloud_ml_sdk/_assistants/domain.py @@ -48,20 +48,17 @@ async def _create( expiration_config = ExpirationConfig.coerce(ttl_days=ttl_days, expiration_policy=expiration_policy) model_uri: str = '' - model_temperature: float | None = None - model_max_tokens: int | None = None if isinstance(model, str): model_uri = self._sdk.models.completions(model).uri elif isinstance(model, BaseGPTModel): model_uri = model.uri - model_temperature = model.config.temperature - model_max_tokens = model.config.max_tokens + if not is_defined(temperature) and model.config.temperature is not None: + temperature = model.config.temperature + if not is_defined(max_tokens) and model.config.max_tokens is not None: + max_tokens = model.config.max_tokens else: raise TypeError('model argument must be str, GPTModel object either undefined') - model_temperature = get_defined_value(temperature, model_temperature) - model_max_tokens = get_defined_value(max_tokens, model_max_tokens) - tools_: tuple[BaseTool, ...] = () if is_defined(tools): # NB: mypy doesn't love abstract class used as TypeVar substitution here @@ -79,8 +76,8 @@ async def _create( ), model_uri=model_uri, completion_options=get_completion_options( - temperature=model_temperature, - max_tokens=model_max_tokens + temperature=temperature, + max_tokens=max_tokens ), tools=[tool._to_proto() for tool in tools_] ) diff --git a/src/yandex_cloud_ml_sdk/_assistants/utils.py b/src/yandex_cloud_ml_sdk/_assistants/utils.py index 3fd659e..cad2970 100644 --- a/src/yandex_cloud_ml_sdk/_assistants/utils.py +++ b/src/yandex_cloud_ml_sdk/_assistants/utils.py @@ -3,16 +3,18 @@ from yandex.cloud.ai.assistants.v1.common_pb2 import CompletionOptions, PromptTruncationOptions +from yandex_cloud_ml_sdk._types.misc import UndefinedOr, is_defined + def get_completion_options( *, - temperature: float | None, - max_tokens: int | None, + temperature: UndefinedOr[float] | None, + max_tokens: UndefinedOr[int] | None, ) -> CompletionOptions: options = CompletionOptions() - if temperature is not None: + if temperature is not None and is_defined(temperature): options.temperature.value = temperature - if max_tokens is not None: + if max_tokens is not None and is_defined(max_tokens): options.max_tokens.value = max_tokens return options @@ -20,10 +22,10 @@ def get_completion_options( def get_prompt_trunctation_options( *, - max_prompt_tokens: int | None + max_prompt_tokens: UndefinedOr[int] | None ) -> PromptTruncationOptions: options = PromptTruncationOptions() - if max_prompt_tokens is not None: + if max_prompt_tokens is not None and is_defined(max_prompt_tokens): options.max_prompt_tokens.value = max_prompt_tokens return options diff --git a/src/yandex_cloud_ml_sdk/_types/resource.py b/src/yandex_cloud_ml_sdk/_types/resource.py index 00044ab..639d286 100644 --- a/src/yandex_cloud_ml_sdk/_types/resource.py +++ b/src/yandex_cloud_ml_sdk/_types/resource.py @@ -60,7 +60,7 @@ def _update_from_proto(self, proto: Message) -> Self: def _fill_update_mask(self, mask: FieldMask, fields: dict[str, Any]) -> None: for key, value in fields.items(): - if is_defined(value) and value is not None: + if is_defined(value): mask.paths.append(key) diff --git a/tests/assistants/cassettes/test_assistants/test_assistant_zeros.gprc.json b/tests/assistants/cassettes/test_assistants/test_assistant_zeros.gprc.json new file mode 100644 index 0000000..feba549 --- /dev/null +++ b/tests/assistants/cassettes/test_assistants/test_assistant_zeros.gprc.json @@ -0,0 +1,631 @@ +{ + "interactions": [ + { + "request": { + "cls": "ListApiEndpointsRequest", + "module": "yandex.cloud.endpoint.api_endpoint_service_pb2", + "message": {} + }, + "response": { + "cls": "ListApiEndpointsResponse", + "module": "yandex.cloud.endpoint.api_endpoint_service_pb2", + "message": { + "endpoints": [ + { + "id": "ai-foundation-models", + "address": "llm.api.cloud.yandex.net:443" + }, + { + "id": "ai-llm", + "address": "llm.api.cloud.yandex.net:443" + }, + { + "id": "ai-speechkit", + "address": "transcribe.api.cloud.yandex.net:443" + }, + { + "id": "ai-stt", + "address": "transcribe.api.cloud.yandex.net:443" + }, + { + "id": "ai-stt-v3", + "address": "stt.api.cloud.yandex.net:443" + }, + { + "id": "ai-translate", + "address": "translate.api.cloud.yandex.net:443" + }, + { + "id": "ai-vision", + "address": "vision.api.cloud.yandex.net:443" + }, + { + "id": "ai-vision-ocr", + "address": "ocr.api.cloud.yandex.net:443" + }, + { + "id": "alb", + "address": "alb.api.cloud.yandex.net:443" + }, + { + "id": "apigateway-connections", + "address": "apigateway-connections.api.cloud.yandex.net:443" + }, + { + "id": "application-load-balancer", + "address": "alb.api.cloud.yandex.net:443" + }, + { + "id": "apploadbalancer", + "address": "alb.api.cloud.yandex.net:443" + }, + { + "id": "audittrails", + "address": "audittrails.api.cloud.yandex.net:443" + }, + { + "id": "baas", + "address": "backup.api.cloud.yandex.net:443" + }, + { + "id": "backup", + "address": "backup.api.cloud.yandex.net:443" + }, + { + "id": "billing", + "address": "billing.api.cloud.yandex.net:443" + }, + { + "id": "broker-data", + "address": "iot-data.api.cloud.yandex.net:443" + }, + { + "id": "cdn", + "address": "cdn.api.cloud.yandex.net:443" + }, + { + "id": "certificate-manager", + "address": "certificate-manager.api.cloud.yandex.net:443" + }, + { + "id": "certificate-manager-data", + "address": "data.certificate-manager.api.cloud.yandex.net:443" + }, + { + "id": "cic", + "address": "cic-api.api.cloud.yandex.net:443" + }, + { + "id": "cloudapps", + "address": "cloudapps.api.cloud.yandex.net:443" + }, + { + "id": "cloudbackup", + "address": "backup.api.cloud.yandex.net:443" + }, + { + "id": "clouddesktops", + "address": "clouddesktops.api.cloud.yandex.net:443" + }, + { + "id": "cloudrouter", + "address": "cic-api.api.cloud.yandex.net:443" + }, + { + "id": "cloudvideo", + "address": "video.api.cloud.yandex.net:443" + }, + { + "id": "compute", + "address": "compute.api.cloud.yandex.net:443" + }, + { + "id": "container-registry", + "address": "container-registry.api.cloud.yandex.net:443" + }, + { + "id": "dataproc", + "address": "dataproc.api.cloud.yandex.net:443" + }, + { + "id": "dataproc-manager", + "address": "dataproc-manager.api.cloud.yandex.net:443" + }, + { + "id": "datasphere", + "address": "datasphere.api.cloud.yandex.net:443" + }, + { + "id": "datatransfer", + "address": "datatransfer.api.cloud.yandex.net:443" + }, + { + "id": "dns", + "address": "dns.api.cloud.yandex.net:443" + }, + { + "id": "endpoint", + "address": "api.cloud.yandex.net:443" + }, + { + "id": "iam", + "address": "iam.api.cloud.yandex.net:443" + }, + { + "id": "iot-broker", + "address": "iot-broker.api.cloud.yandex.net:443" + }, + { + "id": "iot-data", + "address": "iot-data.api.cloud.yandex.net:443" + }, + { + "id": "iot-devices", + "address": "iot-devices.api.cloud.yandex.net:443" + }, + { + "id": "k8s", + "address": "mks.api.cloud.yandex.net:443" + }, + { + "id": "kms", + "address": "kms.api.cloud.yandex.net:443" + }, + { + "id": "kms-crypto", + "address": "kms.yandex:443" + }, + { + "id": "load-balancer", + "address": "load-balancer.api.cloud.yandex.net:443" + }, + { + "id": "loadtesting", + "address": "loadtesting.api.cloud.yandex.net:443" + }, + { + "id": "locator", + "address": "locator.api.cloud.yandex.net:443" + }, + { + "id": "lockbox", + "address": "lockbox.api.cloud.yandex.net:443" + }, + { + "id": "lockbox-payload", + "address": "payload.lockbox.api.cloud.yandex.net:443" + }, + { + "id": "log-ingestion", + "address": "ingester.logging.yandexcloud.net:443" + }, + { + "id": "log-reading", + "address": "reader.logging.yandexcloud.net:443" + }, + { + "id": "logging", + "address": "logging.api.cloud.yandex.net:443" + }, + { + "id": "managed-airflow", + "address": "airflow.api.cloud.yandex.net:443" + }, + { + "id": "managed-clickhouse", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "managed-elasticsearch", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "managed-greenplum", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "managed-kafka", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "managed-kubernetes", + "address": "mks.api.cloud.yandex.net:443" + }, + { + "id": "managed-mongodb", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "managed-mysql", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "managed-opensearch", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "managed-postgresql", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "managed-redis", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "managed-sqlserver", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "marketplace", + "address": "marketplace.api.cloud.yandex.net:443" + }, + { + "id": "mdb-clickhouse", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "mdb-mongodb", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "mdb-mysql", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "mdb-opensearch", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "mdb-postgresql", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "mdb-redis", + "address": "mdb.api.cloud.yandex.net:443" + }, + { + "id": "mdbproxy", + "address": "mdbproxy.api.cloud.yandex.net:443" + }, + { + "id": "monitoring", + "address": "monitoring.api.cloud.yandex.net:443" + }, + { + "id": "operation", + "address": "operation.api.cloud.yandex.net:443" + }, + { + "id": "organization-manager", + "address": "organization-manager.api.cloud.yandex.net:443" + }, + { + "id": "organizationmanager", + "address": "organization-manager.api.cloud.yandex.net:443" + }, + { + "id": "resource-manager", + "address": "resource-manager.api.cloud.yandex.net:443" + }, + { + "id": "resourcemanager", + "address": "resource-manager.api.cloud.yandex.net:443" + }, + { + "id": "searchapi", + "address": "searchapi.api.cloud.yandex.net:443" + }, + { + "id": "serialssh", + "address": "serialssh.cloud.yandex.net:9600" + }, + { + "id": "serverless-apigateway", + "address": "serverless-apigateway.api.cloud.yandex.net:443" + }, + { + "id": "serverless-containers", + "address": "serverless-containers.api.cloud.yandex.net:443" + }, + { + "id": "serverless-eventrouter", + "address": "serverless-eventrouter.api.cloud.yandex.net:443" + }, + { + "id": "serverless-functions", + "address": "serverless-functions.api.cloud.yandex.net:443" + }, + { + "id": "serverless-gateway-connections", + "address": "apigateway-connections.api.cloud.yandex.net:443" + }, + { + "id": "serverless-triggers", + "address": "serverless-triggers.api.cloud.yandex.net:443" + }, + { + "id": "serverless-workflows", + "address": "serverless-workflows.api.cloud.yandex.net:443" + }, + { + "id": "serverlesseventrouter-events", + "address": "events.eventrouter.serverless.yandexcloud.net:443" + }, + { + "id": "smart-captcha", + "address": "smartcaptcha.api.cloud.yandex.net:443" + }, + { + "id": "smart-web-security", + "address": "smartwebsecurity.api.cloud.yandex.net:443" + }, + { + "id": "storage", + "address": "storage.yandexcloud.net:443" + }, + { + "id": "storage-api", + "address": "storage.api.cloud.yandex.net:443" + }, + { + "id": "video", + "address": "video.api.cloud.yandex.net:443" + }, + { + "id": "vpc", + "address": "vpc.api.cloud.yandex.net:443" + }, + { + "id": "ydb", + "address": "ydb.api.cloud.yandex.net:443" + } + ] + } + } + }, + { + "request": { + "cls": "CreateAssistantRequest", + "module": "yandex.cloud.ai.assistants.v1.assistant_service_pb2", + "message": { + "folderId": "b1ghsjum2v37c2un8h64", + "modelUri": "gpt://b1ghsjum2v37c2un8h64/yandexgpt/latest", + "promptTruncationOptions": {}, + "completionOptions": {} + } + }, + "response": { + "cls": "Assistant", + "module": "yandex.cloud.ai.assistants.v1.assistant_pb2", + "message": { + "id": "fvt837cmh38cm468jd23", + "folderId": "b1ghsjum2v37c2un8h64", + "createdBy": "ajek27c96hekgf8f8016", + "createdAt": "2024-11-08T17:23:23.316658Z", + "updatedBy": "ajek27c96hekgf8f8016", + "updatedAt": "2024-11-08T17:23:23.316658Z", + "expirationConfig": { + "expirationPolicy": "SINCE_LAST_ACTIVE", + "ttlDays": "7" + }, + "expiresAt": "2024-11-15T17:23:23.316658Z", + "modelUri": "gpt://b1ghsjum2v37c2un8h64/yandexgpt/latest", + "promptTruncationOptions": {}, + "completionOptions": {} + } + } + }, + { + "request": { + "cls": "UpdateAssistantRequest", + "module": "yandex.cloud.ai.assistants.v1.assistant_service_pb2", + "message": { + "assistantId": "fvt837cmh38cm468jd23", + "updateMask": "completionOptions.temperature", + "promptTruncationOptions": {}, + "completionOptions": { + "temperature": 0.5 + } + } + }, + "response": { + "cls": "Assistant", + "module": "yandex.cloud.ai.assistants.v1.assistant_pb2", + "message": { + "id": "fvt837cmh38cm468jd23", + "folderId": "b1ghsjum2v37c2un8h64", + "createdBy": "ajek27c96hekgf8f8016", + "createdAt": "2024-11-08T17:23:23.316658Z", + "updatedBy": "ajek27c96hekgf8f8016", + "updatedAt": "2024-11-08T17:23:23.397020Z", + "expirationConfig": { + "expirationPolicy": "SINCE_LAST_ACTIVE", + "ttlDays": "7" + }, + "expiresAt": "2024-11-15T17:23:23.316658Z", + "modelUri": "gpt://b1ghsjum2v37c2un8h64/yandexgpt/latest", + "promptTruncationOptions": {}, + "completionOptions": { + "temperature": 0.5 + } + } + } + }, + { + "request": { + "cls": "UpdateAssistantRequest", + "module": "yandex.cloud.ai.assistants.v1.assistant_service_pb2", + "message": { + "assistantId": "fvt837cmh38cm468jd23", + "updateMask": "completionOptions.temperature", + "promptTruncationOptions": {}, + "completionOptions": {} + } + }, + "response": { + "cls": "Assistant", + "module": "yandex.cloud.ai.assistants.v1.assistant_pb2", + "message": { + "id": "fvt837cmh38cm468jd23", + "folderId": "b1ghsjum2v37c2un8h64", + "createdBy": "ajek27c96hekgf8f8016", + "createdAt": "2024-11-08T17:23:23.316658Z", + "updatedBy": "ajek27c96hekgf8f8016", + "updatedAt": "2024-11-08T17:23:23.486762Z", + "expirationConfig": { + "expirationPolicy": "SINCE_LAST_ACTIVE", + "ttlDays": "7" + }, + "expiresAt": "2024-11-15T17:23:23.316658Z", + "modelUri": "gpt://b1ghsjum2v37c2un8h64/yandexgpt/latest", + "promptTruncationOptions": {}, + "completionOptions": { + "temperature": 0.0 + } + } + } + }, + { + "request": { + "cls": "UpdateAssistantRequest", + "module": "yandex.cloud.ai.assistants.v1.assistant_service_pb2", + "message": { + "assistantId": "fvt837cmh38cm468jd23", + "updateMask": "completionOptions.temperature", + "promptTruncationOptions": {}, + "completionOptions": { + "temperature": 0.0 + } + } + }, + "response": { + "cls": "Assistant", + "module": "yandex.cloud.ai.assistants.v1.assistant_pb2", + "message": { + "id": "fvt837cmh38cm468jd23", + "folderId": "b1ghsjum2v37c2un8h64", + "createdBy": "ajek27c96hekgf8f8016", + "createdAt": "2024-11-08T17:23:23.316658Z", + "updatedBy": "ajek27c96hekgf8f8016", + "updatedAt": "2024-11-08T17:23:23.557513Z", + "expirationConfig": { + "expirationPolicy": "SINCE_LAST_ACTIVE", + "ttlDays": "7" + }, + "expiresAt": "2024-11-15T17:23:23.316658Z", + "modelUri": "gpt://b1ghsjum2v37c2un8h64/yandexgpt/latest", + "promptTruncationOptions": {}, + "completionOptions": { + "temperature": 0.0 + } + } + } + }, + { + "request": { + "cls": "CreateAssistantRequest", + "module": "yandex.cloud.ai.assistants.v1.assistant_service_pb2", + "message": { + "folderId": "b1ghsjum2v37c2un8h64", + "modelUri": "gpt://b1ghsjum2v37c2un8h64/yandexgpt/latest", + "promptTruncationOptions": {}, + "completionOptions": { + "temperature": 0.0 + } + } + }, + "response": { + "cls": "Assistant", + "module": "yandex.cloud.ai.assistants.v1.assistant_pb2", + "message": { + "id": "fvtei28uf91tkt87r395", + "folderId": "b1ghsjum2v37c2un8h64", + "createdBy": "ajek27c96hekgf8f8016", + "createdAt": "2024-11-08T17:23:23.639521Z", + "updatedBy": "ajek27c96hekgf8f8016", + "updatedAt": "2024-11-08T17:23:23.639521Z", + "expirationConfig": { + "expirationPolicy": "SINCE_LAST_ACTIVE", + "ttlDays": "7" + }, + "expiresAt": "2024-11-15T17:23:23.639521Z", + "modelUri": "gpt://b1ghsjum2v37c2un8h64/yandexgpt/latest", + "promptTruncationOptions": {}, + "completionOptions": { + "temperature": 0.0 + } + } + } + }, + { + "request": { + "cls": "UpdateAssistantRequest", + "module": "yandex.cloud.ai.assistants.v1.assistant_service_pb2", + "message": { + "assistantId": "fvtei28uf91tkt87r395", + "updateMask": "completionOptions.temperature", + "promptTruncationOptions": {}, + "completionOptions": {} + } + }, + "response": { + "cls": "Assistant", + "module": "yandex.cloud.ai.assistants.v1.assistant_pb2", + "message": { + "id": "fvtei28uf91tkt87r395", + "folderId": "b1ghsjum2v37c2un8h64", + "createdBy": "ajek27c96hekgf8f8016", + "createdAt": "2024-11-08T17:23:23.639521Z", + "updatedBy": "ajek27c96hekgf8f8016", + "updatedAt": "2024-11-08T17:23:23.693361Z", + "expirationConfig": { + "expirationPolicy": "SINCE_LAST_ACTIVE", + "ttlDays": "7" + }, + "expiresAt": "2024-11-15T17:23:23.639521Z", + "modelUri": "gpt://b1ghsjum2v37c2un8h64/yandexgpt/latest", + "promptTruncationOptions": {}, + "completionOptions": { + "temperature": 0.0 + } + } + } + }, + { + "request": { + "cls": "UpdateAssistantRequest", + "module": "yandex.cloud.ai.assistants.v1.assistant_service_pb2", + "message": { + "assistantId": "fvt837cmh38cm468jd23", + "updateMask": "completionOptions.maxTokens", + "promptTruncationOptions": {}, + "completionOptions": { + "maxTokens": "50" + } + } + }, + "response": { + "cls": "Assistant", + "module": "yandex.cloud.ai.assistants.v1.assistant_pb2", + "message": { + "id": "fvt837cmh38cm468jd23", + "folderId": "b1ghsjum2v37c2un8h64", + "createdBy": "ajek27c96hekgf8f8016", + "createdAt": "2024-11-08T17:23:23.316658Z", + "updatedBy": "ajek27c96hekgf8f8016", + "updatedAt": "2024-11-08T17:23:23.733754Z", + "expirationConfig": { + "expirationPolicy": "SINCE_LAST_ACTIVE", + "ttlDays": "7" + }, + "expiresAt": "2024-11-15T17:23:23.316658Z", + "modelUri": "gpt://b1ghsjum2v37c2un8h64/yandexgpt/latest", + "promptTruncationOptions": {}, + "completionOptions": { + "maxTokens": "50" + } + } + } + } + ] +} diff --git a/tests/assistants/test_assistants.py b/tests/assistants/test_assistants.py index 74a91c3..a71d1af 100644 --- a/tests/assistants/test_assistants.py +++ b/tests/assistants/test_assistants.py @@ -7,7 +7,6 @@ @pytest.mark.allow_grpc -@pytest.mark.vcr async def test_assistant(async_sdk): assistant = await async_sdk.assistants.create('yandexgpt') @@ -67,6 +66,38 @@ async def test_assistant(async_sdk): await assistant.delete() +@pytest.mark.allow_grpc +async def test_assistant_zeros(async_sdk): + assistant = await async_sdk.assistants.create('yandexgpt') + assert assistant.model.config.temperature is None + + await assistant.update(temperature=0.5) + assert assistant.model.config.temperature == 0.5 + + await assistant.update(temperature=None) + # XXX this is a bug: + assert assistant.model.config.temperature == 0 + + await assistant.update(temperature=0) + assert assistant.model.config.temperature == 0 + + assistant2 = await async_sdk.assistants.create('yandexgpt', temperature=0) + assert assistant2.model.config.temperature == 0 + + await assistant2.update(temperature=None) + # XXX this is a bug: + assert assistant2.model.config.temperature == 0 + + assert assistant.model.config.max_tokens is None + + await assistant.update(max_tokens=50) + assert assistant.model.config.max_tokens == 50 + + # XXX this is not working by because of the backend bug + # await assistant.update(max_tokens=None) + # assert assistant.model.config.max_tokens == 0 + + @pytest.mark.allow_grpc async def test_assistant_get(async_sdk): assistant = await async_sdk.assistants.create('yandexgpt')